Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6

* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6: (75 commits)
  Ethernet driver for EISA only SNI RM200/RM400 machines
  Extract chip specific code out of lasi_82596.c
  ehea: Whitespace cleanup
  pasemi_mac: Fix TX interrupt threshold
  spidernet: Replace literal with const
  r8169: perform RX config change after mac filtering
  r8169: mac address change support
  r8169: display some extra debug information during startup
  r8169: add endianess annotations to [RT]xDesc
  r8169: align the IP header when there is no DMA constraint
  r8169: add bit description for the TxPoll register
  r8169: cleanup
  r8169: remove the media option
  r8169: small 8101 comment
  r8169: confusion between hardware and IP header alignment
  r8169: merge with version 8.001.00 of Realtek's r8168 driver
  r8169: merge with version 6.001.00 of Realtek's r8169 driver
  r8169: prettify mac_version
  r8169: populate the hw_start handler for the 8110
  r8169: populate the hw_start handler for the 8168
  ...
This commit is contained in:
Linus Torvalds 2007-07-09 15:26:43 -07:00
commit 71ba22fa73
83 changed files with 6793 additions and 2683 deletions

View file

@ -34,6 +34,11 @@ config PHANTOM
If you choose to build module, its name will be phantom. If unsure,
say N here.
config EEPROM_93CX6
tristate "EEPROM 93CX6 support"
---help---
This is a driver for the EEPROM chipsets 93c46 and 93c66.
The driver supports both read as well as write commands.
If unsure, say N.
@ -187,5 +192,4 @@ config THINKPAD_ACPI_BAY
If you are not sure, say Y here.
endmenu

View file

@ -14,3 +14,4 @@ obj-$(CONFIG_PHANTOM) += phantom.o
obj-$(CONFIG_SGI_IOC4) += ioc4.o
obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o

241
drivers/misc/eeprom_93cx6.c Normal file
View file

@ -0,0 +1,241 @@
/*
Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the
Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
Module: eeprom_93cx6
Abstract: EEPROM reader routines for 93cx6 chipsets.
Supported chipsets: 93c46 & 93c66.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/delay.h>
#include <linux/eeprom_93cx6.h>
MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
MODULE_VERSION("1.0");
MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
MODULE_LICENSE("GPL");
static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
{
eeprom->reg_data_clock = 1;
eeprom->register_write(eeprom);
/*
* Add a short delay for the pulse to work.
* According to the specifications the "maximum minimum"
* time should be 450ns.
*/
ndelay(450);
}
static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
{
eeprom->reg_data_clock = 0;
eeprom->register_write(eeprom);
/*
* Add a short delay for the pulse to work.
* According to the specifications the minimal time
* should be 450ns so a 1us delay is sufficient.
*/
udelay(1);
}
static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
{
/*
* Clear all flags, and enable chip select.
*/
eeprom->register_read(eeprom);
eeprom->reg_data_in = 0;
eeprom->reg_data_out = 0;
eeprom->reg_data_clock = 0;
eeprom->reg_chip_select = 1;
eeprom->register_write(eeprom);
/*
* kick a pulse.
*/
eeprom_93cx6_pulse_high(eeprom);
eeprom_93cx6_pulse_low(eeprom);
}
static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
{
/*
* Clear chip_select and data_in flags.
*/
eeprom->register_read(eeprom);
eeprom->reg_data_in = 0;
eeprom->reg_chip_select = 0;
eeprom->register_write(eeprom);
/*
* kick a pulse.
*/
eeprom_93cx6_pulse_high(eeprom);
eeprom_93cx6_pulse_low(eeprom);
}
static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
const u16 data, const u16 count)
{
unsigned int i;
eeprom->register_read(eeprom);
/*
* Clear data flags.
*/
eeprom->reg_data_in = 0;
eeprom->reg_data_out = 0;
/*
* Start writing all bits.
*/
for (i = count; i > 0; i--) {
/*
* Check if this bit needs to be set.
*/
eeprom->reg_data_in = !!(data & (1 << (i - 1)));
/*
* Write the bit to the eeprom register.
*/
eeprom->register_write(eeprom);
/*
* Kick a pulse.
*/
eeprom_93cx6_pulse_high(eeprom);
eeprom_93cx6_pulse_low(eeprom);
}
eeprom->reg_data_in = 0;
eeprom->register_write(eeprom);
}
static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
u16 *data, const u16 count)
{
unsigned int i;
u16 buf = 0;
eeprom->register_read(eeprom);
/*
* Clear data flags.
*/
eeprom->reg_data_in = 0;
eeprom->reg_data_out = 0;
/*
* Start reading all bits.
*/
for (i = count; i > 0; i--) {
eeprom_93cx6_pulse_high(eeprom);
eeprom->register_read(eeprom);
/*
* Clear data_in flag.
*/
eeprom->reg_data_in = 0;
/*
* Read if the bit has been set.
*/
if (eeprom->reg_data_out)
buf |= (1 << (i - 1));
eeprom_93cx6_pulse_low(eeprom);
}
*data = buf;
}
/**
* eeprom_93cx6_read - Read multiple words from eeprom
* @eeprom: Pointer to eeprom structure
* @word: Word index from where we should start reading
* @data: target pointer where the information will have to be stored
*
* This function will read the eeprom data as host-endian word
* into the given data pointer.
*/
void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
u16 *data)
{
u16 command;
/*
* Initialize the eeprom register
*/
eeprom_93cx6_startup(eeprom);
/*
* Select the read opcode and the word to be read.
*/
command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
eeprom_93cx6_write_bits(eeprom, command,
PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
/*
* Read the requested 16 bits.
*/
eeprom_93cx6_read_bits(eeprom, data, 16);
/*
* Cleanup eeprom register.
*/
eeprom_93cx6_cleanup(eeprom);
}
EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
/**
* eeprom_93cx6_multiread - Read multiple words from eeprom
* @eeprom: Pointer to eeprom structure
* @word: Word index from where we should start reading
* @data: target pointer where the information will have to be stored
* @words: Number of words that should be read.
*
* This function will read all requested words from the eeprom,
* this is done by calling eeprom_93cx6_read() multiple times.
* But with the additional change that while the eeprom_93cx6_read
* will return host ordered bytes, this method will return little
* endian words.
*/
void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
__le16 *data, const u16 words)
{
unsigned int i;
u16 tmp;
for (i = 0; i < words; i++) {
tmp = 0;
eeprom_93cx6_read(eeprom, word + i, &tmp);
data[i] = cpu_to_le16(tmp);
}
}
EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);

View file

@ -107,11 +107,6 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered mu
#define PFX DRV_NAME ": "
#ifndef TRUE
#define FALSE 0
#define TRUE (!FALSE)
#endif
#define CP_DEF_MSG_ENABLE (NETIF_MSG_DRV | \
NETIF_MSG_PROBE | \
NETIF_MSG_LINK)
@ -661,7 +656,7 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
if (status & (TxOK | TxErr | TxEmpty | SWInt))
cp_tx(cp);
if (status & LinkChg)
mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
spin_unlock(&cp->lock);
@ -1188,7 +1183,7 @@ static int cp_open (struct net_device *dev)
goto err_out_hw;
netif_carrier_off(dev);
mii_check_media(&cp->mii_if, netif_msg_link(cp), TRUE);
mii_check_media(&cp->mii_if, netif_msg_link(cp), true);
netif_start_queue(dev);
return 0;
@ -2050,7 +2045,7 @@ static int cp_resume (struct pci_dev *pdev)
spin_lock_irqsave (&cp->lock, flags);
mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
spin_unlock_irqrestore (&cp->lock, flags);

View file

@ -3,10 +3,7 @@
# Network device configuration
#
menu "Network device support"
depends on NET
config NETDEVICES
menuconfig NETDEVICES
default y if UML
bool "Network device support"
---help---
@ -151,11 +148,9 @@ source "drivers/net/phy/Kconfig"
# Ethernet
#
menu "Ethernet (10 or 100Mbit)"
depends on !UML
config NET_ETHERNET
menuconfig NET_ETHERNET
bool "Ethernet (10 or 100Mbit)"
depends on !UML
---help---
Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
type of Local Area Network (LAN) in universities and companies.
@ -180,9 +175,10 @@ config NET_ETHERNET
kernel: saying N will just cause the configurator to skip all
the questions about Ethernet network cards. If unsure, say N.
if NET_ETHERNET
config MII
tristate "Generic Media Independent Interface device support"
depends on NET_ETHERNET
help
Most ethernet controllers have MII transceiver either as an external
or internal device. It is safe to say Y or M here even if your
@ -190,7 +186,7 @@ config MII
config MACB
tristate "Atmel MACB support"
depends on NET_ETHERNET && (AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263)
depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263
select MII
help
The Atmel MACB ethernet interface is found on many AT32 and AT91
@ -203,7 +199,7 @@ source "drivers/net/arm/Kconfig"
config MACE
tristate "MACE (Power Mac ethernet) support"
depends on NET_ETHERNET && PPC_PMAC && PPC32
depends on PPC_PMAC && PPC32
select CRC32
help
Power Macintoshes and clones with Ethernet built-in on the
@ -226,7 +222,7 @@ config MACE_AAUI_PORT
config BMAC
tristate "BMAC (G3 ethernet) support"
depends on NET_ETHERNET && PPC_PMAC && PPC32
depends on PPC_PMAC && PPC32
select CRC32
help
Say Y for support of BMAC Ethernet interfaces. These are used on G3
@ -237,7 +233,7 @@ config BMAC
config ARIADNE
tristate "Ariadne support"
depends on NET_ETHERNET && ZORRO
depends on ZORRO
help
If you have a Village Tronic Ariadne Ethernet adapter, say Y.
Otherwise, say N.
@ -247,7 +243,7 @@ config ARIADNE
config A2065
tristate "A2065 support"
depends on NET_ETHERNET && ZORRO
depends on ZORRO
select CRC32
help
If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise,
@ -258,7 +254,7 @@ config A2065
config HYDRA
tristate "Hydra support"
depends on NET_ETHERNET && ZORRO
depends on ZORRO
select CRC32
help
If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
@ -268,7 +264,7 @@ config HYDRA
config ZORRO8390
tristate "Zorro NS8390-based Ethernet support"
depends on NET_ETHERNET && ZORRO
depends on ZORRO
select CRC32
help
This driver is for Zorro Ethernet cards using an NS8390-compatible
@ -281,7 +277,7 @@ config ZORRO8390
config APNE
tristate "PCMCIA NE2000 support"
depends on NET_ETHERNET && AMIGA_PCMCIA
depends on AMIGA_PCMCIA
select CRC32
help
If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise,
@ -292,7 +288,7 @@ config APNE
config APOLLO_ELPLUS
tristate "Apollo 3c505 support"
depends on NET_ETHERNET && APOLLO
depends on APOLLO
help
Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card.
If you don't have one made for Apollos, you can use one from a PC,
@ -301,7 +297,7 @@ config APOLLO_ELPLUS
config MAC8390
bool "Macintosh NS 8390 based ethernet cards"
depends on NET_ETHERNET && MAC
depends on MAC
select CRC32
help
If you want to include a driver to support Nubus or LC-PDS
@ -311,7 +307,7 @@ config MAC8390
config MAC89x0
tristate "Macintosh CS89x0 based ethernet cards"
depends on NET_ETHERNET && MAC
depends on MAC
---help---
Support for CS89x0 chipset based Ethernet cards. If you have a
Nubus or LC-PDS network (Ethernet) card of this type, say Y and
@ -324,7 +320,7 @@ config MAC89x0
config MACSONIC
tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)"
depends on NET_ETHERNET && MAC
depends on MAC
---help---
Support for NatSemi SONIC based Ethernet devices. This includes
the onboard Ethernet in many Quadras as well as some LC-PDS,
@ -338,7 +334,7 @@ config MACSONIC
config MACMACE
bool "Macintosh (AV) onboard MACE ethernet"
depends on NET_ETHERNET && MAC
depends on MAC
select CRC32
help
Support for the onboard AMD 79C940 MACE Ethernet controller used in
@ -348,7 +344,7 @@ config MACMACE
config MVME147_NET
tristate "MVME147 (Lance) Ethernet support"
depends on NET_ETHERNET && MVME147
depends on MVME147
select CRC32
help
Support for the on-board Ethernet interface on the Motorola MVME147
@ -358,7 +354,7 @@ config MVME147_NET
config MVME16x_NET
tristate "MVME16x Ethernet support"
depends on NET_ETHERNET && MVME16x
depends on MVME16x
help
This is the driver for the Ethernet interface on the Motorola
MVME162, 166, 167, 172 and 177 boards. Say Y here to include the
@ -367,7 +363,7 @@ config MVME16x_NET
config BVME6000_NET
tristate "BVME6000 Ethernet support"
depends on NET_ETHERNET && BVME6000
depends on BVME6000
help
This is the driver for the Ethernet interface on BVME4000 and
BVME6000 VME boards. Say Y here to include the driver for this chip
@ -376,7 +372,7 @@ config BVME6000_NET
config ATARILANCE
tristate "Atari Lance support"
depends on NET_ETHERNET && ATARI
depends on ATARI
help
Say Y to include support for several Atari Ethernet adapters based
on the AMD Lance chipset: RieblCard (with or without battery), or
@ -384,7 +380,7 @@ config ATARILANCE
config ATARI_BIONET
tristate "BioNet-100 support"
depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN
depends on ATARI && ATARI_ACSI && BROKEN
help
Say Y to include support for BioData's BioNet-100 Ethernet adapter
for the ACSI port. The driver works (has to work...) with a polled
@ -392,7 +388,7 @@ config ATARI_BIONET
config ATARI_PAMSNET
tristate "PAMsNet support"
depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN
depends on ATARI && ATARI_ACSI && BROKEN
help
Say Y to include support for the PAMsNet Ethernet adapter for the
ACSI port ("ACSI node"). The driver works (has to work...) with a
@ -400,7 +396,7 @@ config ATARI_PAMSNET
config SUN3LANCE
tristate "Sun3/Sun3x on-board LANCE support"
depends on NET_ETHERNET && (SUN3 || SUN3X)
depends on SUN3 || SUN3X
help
Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80)
featured an AMD Lance 10Mbit Ethernet controller on board; say Y
@ -413,7 +409,7 @@ config SUN3LANCE
config SUN3_82586
bool "Sun3 on-board Intel 82586 support"
depends on NET_ETHERNET && SUN3
depends on SUN3
help
This driver enables support for the on-board Intel 82586 based
Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards. Note
@ -422,7 +418,7 @@ config SUN3_82586
config HPLANCE
bool "HP on-board LANCE support"
depends on NET_ETHERNET && DIO
depends on DIO
select CRC32
help
If you want to use the builtin "LANCE" Ethernet controller on an
@ -430,21 +426,28 @@ config HPLANCE
config LASI_82596
tristate "Lasi ethernet"
depends on NET_ETHERNET && GSC
depends on GSC
help
Say Y here to support the builtin Intel 82596 ethernet controller
found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet.
config SNI_82596
tristate "SNI RM ethernet"
depends on NET_ETHERNET && SNI_RM
help
Say Y here to support the on-board Intel 82596 ethernet controller
built into SNI RM machines.
config MIPS_JAZZ_SONIC
tristate "MIPS JAZZ onboard SONIC Ethernet support"
depends on NET_ETHERNET && MACH_JAZZ
depends on MACH_JAZZ
help
This is the driver for the onboard card of MIPS Magnum 4000,
Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
config MIPS_AU1X00_ENET
bool "MIPS AU1000 Ethernet support"
depends on NET_ETHERNET && SOC_AU1X00
depends on SOC_AU1X00
select PHYLIB
select CRC32
help
@ -453,11 +456,11 @@ config MIPS_AU1X00_ENET
config NET_SB1250_MAC
tristate "SB1250 Ethernet support"
depends on NET_ETHERNET && SIBYTE_SB1xxx_SOC
depends on SIBYTE_SB1xxx_SOC
config SGI_IOC3_ETH
bool "SGI IOC3 Ethernet"
depends on NET_ETHERNET && PCI && SGI_IP27
depends on PCI && SGI_IP27
select CRC32
select MII
help
@ -487,7 +490,7 @@ config SGI_IOC3_ETH_HW_TX_CSUM
config MIPS_SIM_NET
tristate "MIPS simulator Network device"
depends on NET_ETHERNET && MIPS_SIM
depends on MIPS_SIM
help
The MIPSNET device is a simple Ethernet network device which is
emulated by the MIPS Simulator.
@ -495,11 +498,11 @@ config MIPS_SIM_NET
config SGI_O2MACE_ETH
tristate "SGI O2 MACE Fast Ethernet support"
depends on NET_ETHERNET && SGI_IP32=y
depends on SGI_IP32=y
config STNIC
tristate "National DP83902AV support"
depends on NET_ETHERNET && SUPERH
depends on SUPERH
select CRC32
help
Support for cards based on the National Semiconductor DP83902AV
@ -511,7 +514,7 @@ config STNIC
config SUNLANCE
tristate "Sun LANCE support"
depends on NET_ETHERNET && SBUS
depends on SBUS
select CRC32
help
This driver supports the "le" interface present on all 32-bit Sparc
@ -524,7 +527,7 @@ config SUNLANCE
config HAPPYMEAL
tristate "Sun Happy Meal 10/100baseT support"
depends on NET_ETHERNET && (SBUS || PCI)
depends on SBUS || PCI
select CRC32
help
This driver supports the "hme" interface present on most Ultra
@ -537,7 +540,7 @@ config HAPPYMEAL
config SUNBMAC
tristate "Sun BigMAC 10/100baseT support (EXPERIMENTAL)"
depends on NET_ETHERNET && SBUS && EXPERIMENTAL
depends on SBUS && EXPERIMENTAL
select CRC32
help
This driver supports the "be" interface available as an Sbus option.
@ -548,7 +551,7 @@ config SUNBMAC
config SUNQE
tristate "Sun QuadEthernet support"
depends on NET_ETHERNET && SBUS
depends on SBUS
select CRC32
help
This driver supports the "qe" 10baseT Ethernet device, available as
@ -560,7 +563,7 @@ config SUNQE
config SUNGEM
tristate "Sun GEM support"
depends on NET_ETHERNET && PCI
depends on PCI
select CRC32
help
Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also
@ -568,7 +571,7 @@ config SUNGEM
config CASSINI
tristate "Sun Cassini support"
depends on NET_ETHERNET && PCI
depends on PCI
select CRC32
help
Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
@ -576,7 +579,7 @@ config CASSINI
config NET_VENDOR_3COM
bool "3COM cards"
depends on NET_ETHERNET && (ISA || EISA || MCA || PCI)
depends on ISA || EISA || MCA || PCI
help
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@ -736,7 +739,7 @@ config TYPHOON
config LANCE
tristate "AMD LANCE and PCnet (AT1500 and NE2100) support"
depends on NET_ETHERNET && ISA && ISA_DMA_API
depends on ISA && ISA_DMA_API
help
If you have a network (Ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available from
@ -748,7 +751,7 @@ config LANCE
config NET_VENDOR_SMC
bool "Western Digital/SMC cards"
depends on NET_ETHERNET && (ISA || MCA || EISA || MAC)
depends on ISA || MCA || EISA || MAC
help
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@ -818,24 +821,6 @@ config ULTRA32
<file:Documentation/networking/net-modules.txt>. The module
will be called smc-ultra32.
config SMC91X
tristate "SMC 91C9x/91C1xxx support"
select CRC32
select MII
depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN)
help
This is a driver for SMC's 91x series of Ethernet chipsets,
including the SMC91C94 and the SMC91C111. Say Y if you want it
compiled into the kernel, and read the file
<file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
available from <http://www.linuxdoc.org/docs.html#howto>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called smc91x. If you want to compile it as a
module, say M here and read <file:Documentation/kbuild/modules.txt>
as well as <file:Documentation/networking/net-modules.txt>.
config SMC9194
tristate "SMC 9194 support"
depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)
@ -852,10 +837,28 @@ config SMC9194
<file:Documentation/networking/net-modules.txt>. The module
will be called smc9194.
config SMC91X
tristate "SMC 91C9x/91C1xxx support"
select CRC32
select MII
depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN
help
This is a driver for SMC's 91x series of Ethernet chipsets,
including the SMC91C94 and the SMC91C111. Say Y if you want it
compiled into the kernel, and read the file
<file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
available from <http://www.linuxdoc.org/docs.html#howto>.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called smc91x. If you want to compile it as a
module, say M here and read <file:Documentation/kbuild/modules.txt>
as well as <file:Documentation/networking/net-modules.txt>.
config NET_NETX
tristate "NetX Ethernet support"
select MII
depends on NET_ETHERNET && ARCH_NETX
depends on ARCH_NETX
help
This is support for the Hilscher netX builtin Ethernet ports
@ -865,7 +868,7 @@ config NET_NETX
config DM9000
tristate "DM9000 support"
depends on (ARM || MIPS) && NET_ETHERNET
depends on ARM || MIPS
select CRC32
select MII
---help---
@ -879,7 +882,7 @@ config SMC911X
tristate "SMSC LAN911[5678] support"
select CRC32
select MII
depends on NET_ETHERNET && ARCH_PXA
depends on ARCH_PXA
help
This is a driver for SMSC's LAN911x series of Ethernet chipsets
including the new LAN9115, LAN9116, LAN9117, and LAN9118.
@ -893,7 +896,7 @@ config SMC911X
config NET_VENDOR_RACAL
bool "Racal-Interlan (Micom) NI cards"
depends on NET_ETHERNET && ISA
depends on ISA
help
If you have a network (Ethernet) card belonging to this class, such
as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO,
@ -945,7 +948,7 @@ source "drivers/net/tulip/Kconfig"
config AT1700
tristate "AT1700/1720 support (EXPERIMENTAL)"
depends on NET_ETHERNET && (ISA || MCA_LEGACY) && EXPERIMENTAL
depends on (ISA || MCA_LEGACY) && EXPERIMENTAL
select CRC32
---help---
If you have a network (Ethernet) card of this type, say Y and read
@ -958,7 +961,7 @@ config AT1700
config DEPCA
tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support"
depends on NET_ETHERNET && (ISA || EISA || MCA)
depends on ISA || EISA || MCA
select CRC32
---help---
If you have a network (Ethernet) card of this type, say Y and read
@ -972,7 +975,7 @@ config DEPCA
config HP100
tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support"
depends on NET_ETHERNET && (ISA || EISA || PCI)
depends on ISA || EISA || PCI
help
If you have a network (Ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available from
@ -984,7 +987,7 @@ config HP100
config NET_ISA
bool "Other ISA cards"
depends on NET_ETHERNET && ISA
depends on ISA
---help---
If your network (Ethernet) card hasn't been mentioned yet and its
bus system (that's the way the cards talks to the other components
@ -1147,7 +1150,7 @@ config SEEQ8005
config NE2_MCA
tristate "NE/2 (ne2000 MCA version) support"
depends on NET_ETHERNET && MCA_LEGACY
depends on MCA_LEGACY
select CRC32
help
If you have a network (Ethernet) card of this type, say Y and read
@ -1160,7 +1163,7 @@ config NE2_MCA
config IBMLANA
tristate "IBM LAN Adapter/A support"
depends on NET_ETHERNET && MCA && MCA_LEGACY
depends on MCA && MCA_LEGACY
---help---
This is a Micro Channel Ethernet adapter. You need to set
CONFIG_MCA to use this driver. It is both available as an in-kernel
@ -1176,7 +1179,7 @@ config IBMLANA
config IBMVETH
tristate "IBM LAN Virtual Ethernet support"
depends on NET_ETHERNET && PPC_PSERIES
depends on PPC_PSERIES
---help---
This driver supports virtual ethernet adapters on newer IBM iSeries
and pSeries systems.
@ -1257,7 +1260,7 @@ config IBM_EMAC_TAH
config NET_PCI
bool "EISA, VLB, PCI and on board controllers"
depends on NET_ETHERNET && (ISA || EISA || PCI)
depends on ISA || EISA || PCI
help
This is another class of network cards which attach directly to the
bus. If you have one of those, say Y and read the Ethernet-HOWTO,
@ -1313,6 +1316,7 @@ config AMD8111_ETH
To compile this driver as a module, choose M here and read
<file:Documentation/networking/net-modules.txt>. The module
will be called amd8111e.
config AMD8111E_NAPI
bool "Enable NAPI support"
depends on AMD8111_ETH
@ -1778,7 +1782,7 @@ config SC92031
config NET_POCKET
bool "Pocket and portable adapters"
depends on NET_ETHERNET && PARPORT
depends on PARPORT
---help---
Cute little network (Ethernet) devices which attach to the parallel
port ("pocket adapters"), commonly used with laptops. If you have
@ -1847,14 +1851,14 @@ config DE620
config SGISEEQ
tristate "SGI Seeq ethernet controller support"
depends on NET_ETHERNET && SGI_IP22
depends on SGI_IP22
help
Say Y here if you have an Seeq based Ethernet network card. This is
used in many Silicon Graphics machines.
config DECLANCE
tristate "DEC LANCE ethernet controller support"
depends on NET_ETHERNET && MACH_DECSTATION
depends on MACH_DECSTATION
select CRC32
help
This driver is for the series of Ethernet controllers produced by
@ -1884,7 +1888,7 @@ config FEC2
config NE_H8300
tristate "NE2000 compatible support for H8/300"
depends on H8300 && NET_ETHERNET
depends on H8300
help
Say Y here if you want to use the NE2000 compatible
controller on the Renesas H8/300 processor.
@ -1892,7 +1896,7 @@ config NE_H8300
source "drivers/net/fec_8xx/Kconfig"
source "drivers/net/fs_enet/Kconfig"
endmenu
endif # NET_ETHERNET
#
# Gigabit Ethernet
@ -2948,8 +2952,6 @@ config NETCONSOLE
If you want to log kernel messages over the network, enable this.
See <file:Documentation/networking/netconsole.txt> for details.
endif #NETDEVICES
config NETPOLL
def_bool NETCONSOLE
@ -2961,4 +2963,4 @@ config NETPOLL_TRAP
config NET_POLL_CONTROLLER
def_bool NETPOLL
endmenu
endif # NETDEVICES

View file

@ -157,6 +157,7 @@ obj-$(CONFIG_ELPLUS) += 3c505.o
obj-$(CONFIG_AC3200) += ac3200.o 8390.o
obj-$(CONFIG_APRICOT) += 82596.o
obj-$(CONFIG_LASI_82596) += lasi_82596.o
obj-$(CONFIG_SNI_82596) += sni_82596.o
obj-$(CONFIG_MVME16x_NET) += 82596.o
obj-$(CONFIG_BVME6000_NET) += 82596.o
obj-$(CONFIG_SC92031) += sc92031.o

View file

@ -159,10 +159,6 @@ static struct pci_device_id acenic_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
#ifndef SET_NETDEV_DEV
#define SET_NETDEV_DEV(net, pdev) do{} while(0)
#endif
#define ace_sync_irq(irq) synchronize_irq(irq)
#ifndef offset_in_page

View file

@ -4,7 +4,7 @@
#
config ARM_AM79C961A
bool "ARM EBSA110 AM79C961A support"
depends on NET_ETHERNET && ARM && ARCH_EBSA110
depends on ARM && ARCH_EBSA110
select CRC32
help
If you wish to compile a kernel for the EBSA-110, then you should
@ -12,21 +12,21 @@ config ARM_AM79C961A
config ARM_ETHER1
tristate "Acorn Ether1 support"
depends on NET_ETHERNET && ARM && ARCH_ACORN
depends on ARM && ARCH_ACORN
help
If you have an Acorn system with one of these (AKA25) network cards,
you should say Y to this option if you wish to use it with Linux.
config ARM_ETHER3
tristate "Acorn/ANT Ether3 support"
depends on NET_ETHERNET && ARM && ARCH_ACORN
depends on ARM && ARCH_ACORN
help
If you have an Acorn system with one of these network cards, you
should say Y to this option if you wish to use it with Linux.
config ARM_ETHERH
tristate "I-cubed EtherH/ANT EtherM support"
depends on NET_ETHERNET && ARM && ARCH_ACORN
depends on ARM && ARCH_ACORN
select CRC32
help
If you have an Acorn system with one of these network cards, you
@ -34,7 +34,7 @@ config ARM_ETHERH
config ARM_AT91_ETHER
tristate "AT91RM9200 Ethernet support"
depends on NET_ETHERNET && ARM && ARCH_AT91RM9200
depends on ARM && ARCH_AT91RM9200
select MII
help
If you wish to compile a kernel for the AT91RM9200 and enable
@ -42,7 +42,7 @@ config ARM_AT91_ETHER
config EP93XX_ETH
tristate "EP93xx Ethernet support"
depends on NET_ETHERNET && ARM && ARCH_EP93XX
depends on ARM && ARCH_EP93XX
help
This is a driver for the ethernet hardware included in EP93xx CPUs.
Say Y if you are building a kernel for EP93xx based devices.

View file

@ -15,6 +15,7 @@
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/etherdevice.h>
#include <linux/pci.h>
#include <linux/delay.h>
@ -68,8 +69,8 @@
(BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP))
#define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1))
#define RX_PKT_BUF_SZ (1536 + bp->rx_offset + 64)
#define TX_PKT_BUF_SZ (B44_MAX_MTU + ETH_HLEN + 8)
#define RX_PKT_OFFSET 30
#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET + 64)
/* minimum number of free TX descriptors required to wake up TX process */
#define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4)
@ -599,8 +600,7 @@ static void b44_timer(unsigned long __opaque)
spin_unlock_irq(&bp->lock);
bp->timer.expires = jiffies + HZ;
add_timer(&bp->timer);
mod_timer(&bp->timer, round_jiffies(jiffies + HZ));
}
static void b44_tx(struct b44 *bp)
@ -653,7 +653,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
src_map = &bp->rx_buffers[src_idx];
dest_idx = dest_idx_unmasked & (B44_RX_RING_SIZE - 1);
map = &bp->rx_buffers[dest_idx];
skb = dev_alloc_skb(RX_PKT_BUF_SZ);
skb = netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ);
if (skb == NULL)
return -ENOMEM;
@ -669,7 +669,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(skb);
skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
if (skb == NULL)
return -ENOMEM;
mapping = pci_map_single(bp->pdev, skb->data,
@ -684,11 +684,9 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
}
}
skb->dev = bp->dev;
skb_reserve(skb, bp->rx_offset);
rh = (struct rx_header *) skb->data;
skb_reserve(skb, RX_PKT_OFFSET);
rh = (struct rx_header *)
(skb->data - bp->rx_offset);
rh->len = 0;
rh->flags = 0;
@ -698,13 +696,13 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
if (src_map != NULL)
src_map->skb = NULL;
ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - bp->rx_offset));
ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET));
if (dest_idx == (B44_RX_RING_SIZE - 1))
ctrl |= DESC_CTRL_EOT;
dp = &bp->rx_ring[dest_idx];
dp->ctrl = cpu_to_le32(ctrl);
dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
dp->addr = cpu_to_le32((u32) mapping + RX_PKT_OFFSET + bp->dma_offset);
if (bp->flags & B44_FLAG_RX_RING_HACK)
b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
@ -783,7 +781,7 @@ static int b44_rx(struct b44 *bp, int budget)
PCI_DMA_FROMDEVICE);
rh = (struct rx_header *) skb->data;
len = le16_to_cpu(rh->len);
if ((len > (RX_PKT_BUF_SZ - bp->rx_offset)) ||
if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
(rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
drop_it:
b44_recycle_rx(bp, cons, bp->rx_prod);
@ -815,8 +813,8 @@ static int b44_rx(struct b44 *bp, int budget)
pci_unmap_single(bp->pdev, map,
skb_size, PCI_DMA_FROMDEVICE);
/* Leave out rx_header */
skb_put(skb, len+bp->rx_offset);
skb_pull(skb,bp->rx_offset);
skb_put(skb, len + RX_PKT_OFFSET);
skb_pull(skb, RX_PKT_OFFSET);
} else {
struct sk_buff *copy_skb;
@ -828,7 +826,7 @@ static int b44_rx(struct b44 *bp, int budget)
skb_reserve(copy_skb, 2);
skb_put(copy_skb, len);
/* DMA sync done above, copy just the actual packet */
skb_copy_from_linear_data_offset(skb, bp->rx_offset,
skb_copy_from_linear_data_offset(skb, RX_PKT_OFFSET,
copy_skb->data, len);
skb = copy_skb;
}
@ -969,7 +967,6 @@ static void b44_tx_timeout(struct net_device *dev)
static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct b44 *bp = netdev_priv(dev);
struct sk_buff *bounce_skb;
int rc = NETDEV_TX_OK;
dma_addr_t mapping;
u32 len, entry, ctrl;
@ -987,12 +984,13 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
struct sk_buff *bounce_skb;
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
GFP_ATOMIC|GFP_DMA);
bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA);
if (!bounce_skb)
goto err_out;
@ -1001,13 +999,12 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping,
len, PCI_DMA_TODEVICE);
len, PCI_DMA_TODEVICE);
dev_kfree_skb_any(bounce_skb);
goto err_out;
}
skb_copy_from_linear_data(skb, skb_put(bounce_skb, len),
skb->len);
skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len);
dev_kfree_skb_any(skb);
skb = bounce_skb;
}
@ -1396,12 +1393,12 @@ static void b44_init_hw(struct b44 *bp, int reset_kind)
bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
if (reset_kind == B44_PARTIAL_RESET) {
bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
(bp->rx_offset << DMARX_CTRL_ROSHIFT)));
(RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
} else {
bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
(bp->rx_offset << DMARX_CTRL_ROSHIFT)));
(RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
bw32(bp, B44_DMARX_PTR, bp->rx_pending);
@ -2093,11 +2090,6 @@ static int __devinit b44_get_invariants(struct b44 *bp)
bp->phy_addr = eeprom[90] & 0x1f;
/* With this, plus the rx_header prepended to the data by the
* hardware, we'll land the ethernet header on a 2-byte boundary.
*/
bp->rx_offset = 30;
bp->imask = IMASK_DEF;
bp->core_unit = ssb_core_unit(bp);
@ -2348,11 +2340,11 @@ static int b44_resume(struct pci_dev *pdev)
netif_device_attach(bp->dev);
spin_unlock_irq(&bp->lock);
bp->timer.expires = jiffies + HZ;
add_timer(&bp->timer);
b44_enable_ints(bp);
netif_wake_queue(dev);
mod_timer(&bp->timer, jiffies + 1);
return 0;
}

View file

@ -443,8 +443,6 @@ struct b44 {
#define B44_FLAG_TX_RING_HACK 0x40000000
#define B44_FLAG_WOL_ENABLE 0x80000000
u32 rx_offset;
u32 msg_enable;
struct timer_list timer;

View file

@ -71,27 +71,29 @@ enum { /* adapter flags */
QUEUES_BOUND = (1 << 3),
};
struct fl_pg_chunk {
struct page *page;
void *va;
unsigned int offset;
};
struct rx_desc;
struct rx_sw_desc;
struct sge_fl_page {
struct skb_frag_struct frag;
unsigned char *va;
};
struct sge_fl { /* SGE per free-buffer list state */
unsigned int buf_size; /* size of each Rx buffer */
unsigned int credits; /* # of available Rx buffers */
unsigned int size; /* capacity of free list */
unsigned int cidx; /* consumer index */
unsigned int pidx; /* producer index */
unsigned int gen; /* free list generation */
unsigned int cntxt_id; /* SGE context id for the free list */
struct sge_fl_page page;
struct rx_desc *desc; /* address of HW Rx descriptor ring */
struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */
dma_addr_t phys_addr; /* physical address of HW ring start */
unsigned long empty; /* # of times queue ran out of buffers */
struct sge_fl { /* SGE per free-buffer list state */
unsigned int buf_size; /* size of each Rx buffer */
unsigned int credits; /* # of available Rx buffers */
unsigned int size; /* capacity of free list */
unsigned int cidx; /* consumer index */
unsigned int pidx; /* producer index */
unsigned int gen; /* free list generation */
struct fl_pg_chunk pg_chunk;/* page chunk cache */
unsigned int use_pages; /* whether FL uses pages or sk_buffs */
struct rx_desc *desc; /* address of HW Rx descriptor ring */
struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */
dma_addr_t phys_addr; /* physical address of HW ring start */
unsigned int cntxt_id; /* SGE context id for the free list */
unsigned long empty; /* # of times queue ran out of buffers */
unsigned long alloc_failed; /* # of times buffer allocation failed */
};

View file

@ -101,6 +101,7 @@ enum {
TCB_SIZE = 128, /* TCB size */
NMTUS = 16, /* size of MTU table */
NCCTRL_WIN = 32, /* # of congestion control windows */
PROTO_SRAM_LINES = 128, /* size of TP sram */
};
#define MAX_RX_COALESCING_LEN 16224U
@ -123,6 +124,30 @@ enum { /* adapter interrupt-maintained statistics */
IRQ_NUM_STATS /* keep last */
};
enum {
TP_VERSION_MAJOR = 1,
TP_VERSION_MINOR = 0,
TP_VERSION_MICRO = 44
};
#define S_TP_VERSION_MAJOR 16
#define M_TP_VERSION_MAJOR 0xFF
#define V_TP_VERSION_MAJOR(x) ((x) << S_TP_VERSION_MAJOR)
#define G_TP_VERSION_MAJOR(x) \
(((x) >> S_TP_VERSION_MAJOR) & M_TP_VERSION_MAJOR)
#define S_TP_VERSION_MINOR 8
#define M_TP_VERSION_MINOR 0xFF
#define V_TP_VERSION_MINOR(x) ((x) << S_TP_VERSION_MINOR)
#define G_TP_VERSION_MINOR(x) \
(((x) >> S_TP_VERSION_MINOR) & M_TP_VERSION_MINOR)
#define S_TP_VERSION_MICRO 0
#define M_TP_VERSION_MICRO 0xFF
#define V_TP_VERSION_MICRO(x) ((x) << S_TP_VERSION_MICRO)
#define G_TP_VERSION_MICRO(x) \
(((x) >> S_TP_VERSION_MICRO) & M_TP_VERSION_MICRO)
enum {
SGE_QSETS = 8, /* # of SGE Tx/Rx/RspQ sets */
SGE_RXQ_PER_SET = 2, /* # of Rx queues per set */
@ -654,6 +679,9 @@ const struct adapter_info *t3_get_adapter_info(unsigned int board_id);
int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data);
int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data);
int t3_seeprom_wp(struct adapter *adapter, int enable);
int t3_check_tpsram_version(struct adapter *adapter);
int t3_check_tpsram(struct adapter *adapter, u8 *tp_ram, unsigned int size);
int t3_set_proto_sram(struct adapter *adap, u8 *data);
int t3_read_flash(struct adapter *adapter, unsigned int addr,
unsigned int nwords, u32 *data, int byte_oriented);
int t3_load_fw(struct adapter *adapter, const u8 * fw_data, unsigned int size);

View file

@ -2088,6 +2088,42 @@ static void cxgb_netpoll(struct net_device *dev)
}
#endif
#define TPSRAM_NAME "t3%c_protocol_sram-%d.%d.%d.bin"
int update_tpsram(struct adapter *adap)
{
const struct firmware *tpsram;
char buf[64];
struct device *dev = &adap->pdev->dev;
int ret;
char rev;
rev = adap->params.rev == T3_REV_B2 ? 'b' : 'a';
snprintf(buf, sizeof(buf), TPSRAM_NAME, rev,
TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
ret = request_firmware(&tpsram, buf, dev);
if (ret < 0) {
dev_err(dev, "could not load TP SRAM: unable to load %s\n",
buf);
return ret;
}
ret = t3_check_tpsram(adap, tpsram->data, tpsram->size);
if (ret)
goto release_tpsram;
ret = t3_set_proto_sram(adap, tpsram->data);
if (ret)
dev_err(dev, "loading protocol SRAM failed\n");
release_tpsram:
release_firmware(tpsram);
return ret;
}
/*
* Periodic accumulation of MAC statistics.
*/
@ -2437,6 +2473,13 @@ static int __devinit init_one(struct pci_dev *pdev,
goto out_free_dev;
}
err = t3_check_tpsram_version(adapter);
if (err == -EINVAL)
err = update_tpsram(adapter);
if (err)
goto out_free_dev;
/*
* The card is now ready to go. If any errors occur during device
* registration we do not fail the whole card but rather proceed only

View file

@ -1160,6 +1160,8 @@
#define A_TP_MOD_CHANNEL_WEIGHT 0x434
#define A_TP_MOD_RATE_LIMIT 0x438
#define A_TP_PIO_ADDR 0x440
#define A_TP_PIO_DATA 0x444
@ -1214,6 +1216,15 @@
#define G_TXDROPCNTCH0RCVD(x) (((x) >> S_TXDROPCNTCH0RCVD) & \
M_TXDROPCNTCH0RCVD)
#define A_TP_PROXY_FLOW_CNTL 0x4b0
#define A_TP_EMBED_OP_FIELD0 0x4e8
#define A_TP_EMBED_OP_FIELD1 0x4ec
#define A_TP_EMBED_OP_FIELD2 0x4f0
#define A_TP_EMBED_OP_FIELD3 0x4f4
#define A_TP_EMBED_OP_FIELD4 0x4f8
#define A_TP_EMBED_OP_FIELD5 0x4fc
#define A_ULPRX_CTL 0x500
#define S_ROUND_ROBIN 4

View file

@ -46,23 +46,16 @@
#define SGE_RX_SM_BUF_SIZE 1536
/*
* If USE_RX_PAGE is defined, the small freelist populated with (partial)
* pages instead of skbs. Pages are carved up into RX_PAGE_SIZE chunks (must
* be a multiple of the host page size).
*/
#define USE_RX_PAGE
#define RX_PAGE_SIZE 2048
/*
* skb freelist packets are copied into a new skb (and the freelist one is
* reused) if their len is <=
*/
#define SGE_RX_COPY_THRES 256
#define SGE_RX_PULL_LEN 128
/*
* Minimum number of freelist entries before we start dropping TUNNEL frames.
* Page chunk size for FL0 buffers if FL0 is to be populated with page chunks.
* It must be a divisor of PAGE_SIZE. If set to 0 FL0 will use sk_buffs
* directly.
*/
#define FL0_PG_CHUNK_SIZE 2048
#define SGE_RX_DROP_THRES 16
/*
@ -100,12 +93,12 @@ struct tx_sw_desc { /* SW state per Tx descriptor */
struct sk_buff *skb;
};
struct rx_sw_desc { /* SW state per Rx descriptor */
struct rx_sw_desc { /* SW state per Rx descriptor */
union {
struct sk_buff *skb;
struct sge_fl_page page;
} t;
DECLARE_PCI_UNMAP_ADDR(dma_addr);
struct fl_pg_chunk pg_chunk;
};
DECLARE_PCI_UNMAP_ADDR(dma_addr);
};
struct rsp_desc { /* response queue descriptor */
@ -351,27 +344,26 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr),
q->buf_size, PCI_DMA_FROMDEVICE);
if (q->buf_size != RX_PAGE_SIZE) {
kfree_skb(d->t.skb);
d->t.skb = NULL;
if (q->use_pages) {
put_page(d->pg_chunk.page);
d->pg_chunk.page = NULL;
} else {
if (d->t.page.frag.page)
put_page(d->t.page.frag.page);
d->t.page.frag.page = NULL;
kfree_skb(d->skb);
d->skb = NULL;
}
if (++cidx == q->size)
cidx = 0;
}
if (q->page.frag.page)
put_page(q->page.frag.page);
q->page.frag.page = NULL;
if (q->pg_chunk.page) {
__free_page(q->pg_chunk.page);
q->pg_chunk.page = NULL;
}
}
/**
* add_one_rx_buf - add a packet buffer to a free-buffer list
* @va: va of the buffer to add
* @va: buffer start VA
* @len: the buffer length
* @d: the HW Rx descriptor to write
* @sd: the SW Rx descriptor to write
@ -381,7 +373,7 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
* Add a buffer of the given length to the supplied HW and SW Rx
* descriptors.
*/
static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
static inline void add_one_rx_buf(void *va, unsigned int len,
struct rx_desc *d, struct rx_sw_desc *sd,
unsigned int gen, struct pci_dev *pdev)
{
@ -397,6 +389,27 @@ static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
d->gen2 = cpu_to_be32(V_FLD_GEN2(gen));
}
static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp)
{
if (!q->pg_chunk.page) {
q->pg_chunk.page = alloc_page(gfp);
if (unlikely(!q->pg_chunk.page))
return -ENOMEM;
q->pg_chunk.va = page_address(q->pg_chunk.page);
q->pg_chunk.offset = 0;
}
sd->pg_chunk = q->pg_chunk;
q->pg_chunk.offset += q->buf_size;
if (q->pg_chunk.offset == PAGE_SIZE)
q->pg_chunk.page = NULL;
else {
q->pg_chunk.va += q->buf_size;
get_page(q->pg_chunk.page);
}
return 0;
}
/**
* refill_fl - refill an SGE free-buffer list
* @adapter: the adapter
@ -410,49 +423,29 @@ static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
*/
static void refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp)
{
void *buf_start;
struct rx_sw_desc *sd = &q->sdesc[q->pidx];
struct rx_desc *d = &q->desc[q->pidx];
struct sge_fl_page *p = &q->page;
while (n--) {
unsigned char *va;
if (unlikely(q->buf_size != RX_PAGE_SIZE)) {
struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
if (!skb) {
q->alloc_failed++;
if (q->use_pages) {
if (unlikely(alloc_pg_chunk(q, sd, gfp))) {
nomem: q->alloc_failed++;
break;
}
va = skb->data;
sd->t.skb = skb;
buf_start = sd->pg_chunk.va;
} else {
if (!p->frag.page) {
p->frag.page = alloc_pages(gfp, 0);
if (unlikely(!p->frag.page)) {
q->alloc_failed++;
break;
} else {
p->frag.size = RX_PAGE_SIZE;
p->frag.page_offset = 0;
p->va = page_address(p->frag.page);
}
}
struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
memcpy(&sd->t, p, sizeof(*p));
va = p->va;
if (!skb)
goto nomem;
p->frag.page_offset += RX_PAGE_SIZE;
BUG_ON(p->frag.page_offset > PAGE_SIZE);
p->va += RX_PAGE_SIZE;
if (p->frag.page_offset == PAGE_SIZE)
p->frag.page = NULL;
else
get_page(p->frag.page);
sd->skb = skb;
buf_start = skb->data;
}
add_one_rx_buf(va, q->buf_size, d, sd, q->gen, adap->pdev);
add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen,
adap->pdev);
d++;
sd++;
if (++q->pidx == q->size) {
@ -487,7 +480,7 @@ static void recycle_rx_buf(struct adapter *adap, struct sge_fl *q,
struct rx_desc *from = &q->desc[idx];
struct rx_desc *to = &q->desc[q->pidx];
memcpy(&q->sdesc[q->pidx], &q->sdesc[idx], sizeof(struct rx_sw_desc));
q->sdesc[q->pidx] = q->sdesc[idx];
to->addr_lo = from->addr_lo; /* already big endian */
to->addr_hi = from->addr_hi; /* likewise */
wmb();
@ -649,6 +642,132 @@ static inline unsigned int flits_to_desc(unsigned int n)
return flit_desc_map[n];
}
/**
* get_packet - return the next ingress packet buffer from a free list
* @adap: the adapter that received the packet
* @fl: the SGE free list holding the packet
* @len: the packet length including any SGE padding
* @drop_thres: # of remaining buffers before we start dropping packets
*
* Get the next packet from a free list and complete setup of the
* sk_buff. If the packet is small we make a copy and recycle the
* original buffer, otherwise we use the original buffer itself. If a
* positive drop threshold is supplied packets are dropped and their
* buffers recycled if (a) the number of remaining buffers is under the
* threshold and the packet is too big to copy, or (b) the packet should
* be copied but there is no memory for the copy.
*/
static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
unsigned int len, unsigned int drop_thres)
{
struct sk_buff *skb = NULL;
struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
prefetch(sd->skb->data);
fl->credits--;
if (len <= SGE_RX_COPY_THRES) {
skb = alloc_skb(len, GFP_ATOMIC);
if (likely(skb != NULL)) {
__skb_put(skb, len);
pci_dma_sync_single_for_cpu(adap->pdev,
pci_unmap_addr(sd, dma_addr), len,
PCI_DMA_FROMDEVICE);
memcpy(skb->data, sd->skb->data, len);
pci_dma_sync_single_for_device(adap->pdev,
pci_unmap_addr(sd, dma_addr), len,
PCI_DMA_FROMDEVICE);
} else if (!drop_thres)
goto use_orig_buf;
recycle:
recycle_rx_buf(adap, fl, fl->cidx);
return skb;
}
if (unlikely(fl->credits < drop_thres))
goto recycle;
use_orig_buf:
pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
fl->buf_size, PCI_DMA_FROMDEVICE);
skb = sd->skb;
skb_put(skb, len);
__refill_fl(adap, fl);
return skb;
}
/**
* get_packet_pg - return the next ingress packet buffer from a free list
* @adap: the adapter that received the packet
* @fl: the SGE free list holding the packet
* @len: the packet length including any SGE padding
* @drop_thres: # of remaining buffers before we start dropping packets
*
* Get the next packet from a free list populated with page chunks.
* If the packet is small we make a copy and recycle the original buffer,
* otherwise we attach the original buffer as a page fragment to a fresh
* sk_buff. If a positive drop threshold is supplied packets are dropped
* and their buffers recycled if (a) the number of remaining buffers is
* under the threshold and the packet is too big to copy, or (b) there's
* no system memory.
*
* Note: this function is similar to @get_packet but deals with Rx buffers
* that are page chunks rather than sk_buffs.
*/
static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl,
unsigned int len, unsigned int drop_thres)
{
struct sk_buff *skb = NULL;
struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
if (len <= SGE_RX_COPY_THRES) {
skb = alloc_skb(len, GFP_ATOMIC);
if (likely(skb != NULL)) {
__skb_put(skb, len);
pci_dma_sync_single_for_cpu(adap->pdev,
pci_unmap_addr(sd, dma_addr), len,
PCI_DMA_FROMDEVICE);
memcpy(skb->data, sd->pg_chunk.va, len);
pci_dma_sync_single_for_device(adap->pdev,
pci_unmap_addr(sd, dma_addr), len,
PCI_DMA_FROMDEVICE);
} else if (!drop_thres)
return NULL;
recycle:
fl->credits--;
recycle_rx_buf(adap, fl, fl->cidx);
return skb;
}
if (unlikely(fl->credits <= drop_thres))
goto recycle;
skb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC);
if (unlikely(!skb)) {
if (!drop_thres)
return NULL;
goto recycle;
}
pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
fl->buf_size, PCI_DMA_FROMDEVICE);
__skb_put(skb, SGE_RX_PULL_LEN);
memcpy(skb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN);
skb_fill_page_desc(skb, 0, sd->pg_chunk.page,
sd->pg_chunk.offset + SGE_RX_PULL_LEN,
len - SGE_RX_PULL_LEN);
skb->len = len;
skb->data_len = len - SGE_RX_PULL_LEN;
skb->truesize += skb->data_len;
fl->credits--;
/*
* We do not refill FLs here, we let the caller do it to overlap a
* prefetch.
*/
return skb;
}
/**
* get_imm_packet - return the next ingress packet buffer from a response
* @resp: the response descriptor containing the packet data
@ -1715,85 +1834,6 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
netif_rx(skb);
}
#define SKB_DATA_SIZE 128
static void skb_data_init(struct sk_buff *skb, struct sge_fl_page *p,
unsigned int len)
{
skb->len = len;
if (len <= SKB_DATA_SIZE) {
skb_copy_to_linear_data(skb, p->va, len);
skb->tail += len;
put_page(p->frag.page);
} else {
skb_copy_to_linear_data(skb, p->va, SKB_DATA_SIZE);
skb_shinfo(skb)->frags[0].page = p->frag.page;
skb_shinfo(skb)->frags[0].page_offset =
p->frag.page_offset + SKB_DATA_SIZE;
skb_shinfo(skb)->frags[0].size = len - SKB_DATA_SIZE;
skb_shinfo(skb)->nr_frags = 1;
skb->data_len = len - SKB_DATA_SIZE;
skb->tail += SKB_DATA_SIZE;
skb->truesize += skb->data_len;
}
}
/**
* get_packet - return the next ingress packet buffer from a free list
* @adap: the adapter that received the packet
* @fl: the SGE free list holding the packet
* @len: the packet length including any SGE padding
* @drop_thres: # of remaining buffers before we start dropping packets
*
* Get the next packet from a free list and complete setup of the
* sk_buff. If the packet is small we make a copy and recycle the
* original buffer, otherwise we use the original buffer itself. If a
* positive drop threshold is supplied packets are dropped and their
* buffers recycled if (a) the number of remaining buffers is under the
* threshold and the packet is too big to copy, or (b) the packet should
* be copied but there is no memory for the copy.
*/
static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
unsigned int len, unsigned int drop_thres)
{
struct sk_buff *skb = NULL;
struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
prefetch(sd->t.skb->data);
if (len <= SGE_RX_COPY_THRES) {
skb = alloc_skb(len, GFP_ATOMIC);
if (likely(skb != NULL)) {
struct rx_desc *d = &fl->desc[fl->cidx];
dma_addr_t mapping =
(dma_addr_t)((u64) be32_to_cpu(d->addr_hi) << 32 |
be32_to_cpu(d->addr_lo));
__skb_put(skb, len);
pci_dma_sync_single_for_cpu(adap->pdev, mapping, len,
PCI_DMA_FROMDEVICE);
skb_copy_from_linear_data(sd->t.skb, skb->data, len);
pci_dma_sync_single_for_device(adap->pdev, mapping, len,
PCI_DMA_FROMDEVICE);
} else if (!drop_thres)
goto use_orig_buf;
recycle:
recycle_rx_buf(adap, fl, fl->cidx);
return skb;
}
if (unlikely(fl->credits < drop_thres))
goto recycle;
use_orig_buf:
pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
fl->buf_size, PCI_DMA_FROMDEVICE);
skb = sd->t.skb;
skb_put(skb, len);
__refill_fl(adap, fl);
return skb;
}
/**
* handle_rsp_cntrl_info - handles control information in a response
* @qs: the queue set corresponding to the response
@ -1935,7 +1975,7 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
} else if (flags & F_RSPD_IMM_DATA_VALID) {
skb = get_imm_packet(r);
if (unlikely(!skb)) {
no_mem:
no_mem:
q->next_holdoff = NOMEM_INTR_DELAY;
q->nomem++;
/* consume one credit since we tried */
@ -1945,53 +1985,29 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
q->imm_data++;
ethpad = 0;
} else if ((len = ntohl(r->len_cq)) != 0) {
struct sge_fl *fl =
(len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
struct sge_fl *fl;
if (fl->buf_size == RX_PAGE_SIZE) {
struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
struct sge_fl_page *p = &sd->t.page;
prefetch(p->va);
prefetch(p->va + L1_CACHE_BYTES);
fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
if (fl->use_pages) {
void *addr = fl->sdesc[fl->cidx].pg_chunk.va;
prefetch(addr);
#if L1_CACHE_BYTES < 128
prefetch(addr + L1_CACHE_BYTES);
#endif
__refill_fl(adap, fl);
pci_unmap_single(adap->pdev,
pci_unmap_addr(sd, dma_addr),
fl->buf_size,
PCI_DMA_FROMDEVICE);
if (eth) {
if (unlikely(fl->credits <
SGE_RX_DROP_THRES))
goto eth_recycle;
skb = alloc_skb(SKB_DATA_SIZE,
GFP_ATOMIC);
if (unlikely(!skb)) {
eth_recycle:
q->rx_drops++;
recycle_rx_buf(adap, fl,
fl->cidx);
goto eth_done;
}
} else {
skb = alloc_skb(SKB_DATA_SIZE,
GFP_ATOMIC);
if (unlikely(!skb))
goto no_mem;
}
skb_data_init(skb, p, G_RSPD_LEN(len));
eth_done:
fl->credits--;
q->eth_pkts++;
} else {
fl->credits--;
skb = get_packet_pg(adap, fl, G_RSPD_LEN(len),
eth ? SGE_RX_DROP_THRES : 0);
} else
skb = get_packet(adap, fl, G_RSPD_LEN(len),
eth ? SGE_RX_DROP_THRES : 0);
}
if (unlikely(!skb)) {
if (!eth)
goto no_mem;
q->rx_drops++;
} else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT))
__skb_pull(skb, 2);
if (++fl->cidx == fl->size)
fl->cidx = 0;
@ -2016,20 +2032,15 @@ eth_done:
q->credits = 0;
}
if (skb) {
/* Preserve the RSS info in csum & priority */
skb->csum = rss_hi;
skb->priority = rss_lo;
if (likely(skb != NULL)) {
if (eth)
rx_eth(adap, q, skb, ethpad);
else {
if (unlikely(r->rss_hdr.opcode ==
CPL_TRACE_PKT))
__skb_pull(skb, ethpad);
ngathered = rx_offload(&adap->tdev, q,
skb, offload_skbs,
/* Preserve the RSS info in csum & priority */
skb->csum = rss_hi;
skb->priority = rss_lo;
ngathered = rx_offload(&adap->tdev, q, skb,
offload_skbs,
ngathered);
}
}
@ -2635,25 +2646,15 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
q->txq[TXQ_ETH].stop_thres = nports *
flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3);
if (!is_offload(adapter)) {
#ifdef USE_RX_PAGE
q->fl[0].buf_size = RX_PAGE_SIZE;
#if FL0_PG_CHUNK_SIZE > 0
q->fl[0].buf_size = FL0_PG_CHUNK_SIZE;
#else
q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + 2 +
sizeof(struct cpl_rx_pkt);
q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data);
#endif
q->fl[1].buf_size = MAX_FRAME_SIZE + 2 +
sizeof(struct cpl_rx_pkt);
} else {
#ifdef USE_RX_PAGE
q->fl[0].buf_size = RX_PAGE_SIZE;
#else
q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE +
sizeof(struct cpl_rx_data);
#endif
q->fl[1].buf_size = (16 * 1024) -
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
}
q->fl[0].use_pages = FL0_PG_CHUNK_SIZE > 0;
q->fl[1].buf_size = is_offload(adapter) ?
(16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) :
MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt);
spin_lock(&adapter->sge.reg_lock);

View file

@ -847,6 +847,64 @@ static int t3_write_flash(struct adapter *adapter, unsigned int addr,
return 0;
}
/**
* t3_check_tpsram_version - read the tp sram version
* @adapter: the adapter
*
* Reads the protocol sram version from serial eeprom.
*/
int t3_check_tpsram_version(struct adapter *adapter)
{
int ret;
u32 vers;
unsigned int major, minor;
/* Get version loaded in SRAM */
t3_write_reg(adapter, A_TP_EMBED_OP_FIELD0, 0);
ret = t3_wait_op_done(adapter, A_TP_EMBED_OP_FIELD0,
1, 1, 5, 1);
if (ret)
return ret;
vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1);
major = G_TP_VERSION_MAJOR(vers);
minor = G_TP_VERSION_MINOR(vers);
if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR)
return 0;
return -EINVAL;
}
/**
* t3_check_tpsram - check if provided protocol SRAM
* is compatible with this driver
* @adapter: the adapter
* @tp_sram: the firmware image to write
* @size: image size
*
* Checks if an adapter's tp sram is compatible with the driver.
* Returns 0 if the versions are compatible, a negative error otherwise.
*/
int t3_check_tpsram(struct adapter *adapter, u8 *tp_sram, unsigned int size)
{
u32 csum;
unsigned int i;
const u32 *p = (const u32 *)tp_sram;
/* Verify checksum */
for (csum = 0, i = 0; i < size / sizeof(csum); i++)
csum += ntohl(p[i]);
if (csum != 0xffffffff) {
CH_ERR(adapter, "corrupted protocol SRAM image, checksum %u\n",
csum);
return -EINVAL;
}
return 0;
}
enum fw_version_type {
FW_VERSION_N3,
FW_VERSION_T3
@ -921,7 +979,7 @@ static int t3_flash_erase_sectors(struct adapter *adapter, int start, int end)
/*
* t3_load_fw - download firmware
* @adapter: the adapter
* @fw_data: the firrware image to write
* @fw_data: the firmware image to write
* @size: image size
*
* Write the supplied firmware image to the card's serial flash.
@ -2362,7 +2420,7 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
F_TCPCHECKSUMOFFLOAD | V_IPTTL(64));
t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) |
F_MTUENABLE | V_WINDOWSCALEMODE(1) |
V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1));
V_TIMESTAMPSMODE(0) | V_SACKMODE(1) | V_SACKRX(1));
t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) |
V_AUTOSTATE2(1) | V_AUTOSTATE1(0) |
V_BYTETHRESHOLD(16384) | V_MSSTHRESHOLD(2) |
@ -2371,16 +2429,18 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
F_IPV6ENABLE | F_NICMODE);
t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814);
t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105);
t3_set_reg_field(adap, A_TP_PARA_REG6,
adap->params.rev > 0 ? F_ENABLEESND : F_T3A_ENABLEESND,
0);
t3_set_reg_field(adap, A_TP_PARA_REG6, 0,
adap->params.rev > 0 ? F_ENABLEESND :
F_T3A_ENABLEESND);
t3_set_reg_field(adap, A_TP_PC_CONFIG,
F_ENABLEEPCMDAFULL | F_ENABLEOCSPIFULL,
F_TXDEFERENABLE | F_HEARBEATDACK | F_TXCONGESTIONMODE |
F_RXCONGESTIONMODE);
F_ENABLEEPCMDAFULL,
F_ENABLEOCSPIFULL |F_TXDEFERENABLE | F_HEARBEATDACK |
F_TXCONGESTIONMODE | F_RXCONGESTIONMODE);
t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL, 0);
t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1080);
t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1000);
if (adap->params.rev > 0) {
tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE);
t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO,
@ -2390,9 +2450,10 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
} else
t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED);
t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0x12121212);
t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0x12121212);
t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0x1212);
t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0);
t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0);
t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0);
t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0xf2200000);
}
/* Desired TP timer resolution in usec */
@ -2468,6 +2529,7 @@ int t3_tp_set_coalescing_size(struct adapter *adap, unsigned int size, int psh)
val |= F_RXCOALESCEENABLE;
if (psh)
val |= F_RXCOALESCEPSHEN;
size = min(MAX_RX_COALESCING_LEN, size);
t3_write_reg(adap, A_TP_PARA_REG2, V_RXCOALESCESIZE(size) |
V_MAXRXDATA(MAX_RX_COALESCING_LEN));
}
@ -2496,11 +2558,11 @@ static void __devinit init_mtus(unsigned short mtus[])
* it can accomodate max size TCP/IP headers when SACK and timestamps
* are enabled and still have at least 8 bytes of payload.
*/
mtus[0] = 88;
mtus[1] = 256;
mtus[2] = 512;
mtus[3] = 576;
mtus[4] = 808;
mtus[1] = 88;
mtus[1] = 88;
mtus[2] = 256;
mtus[3] = 512;
mtus[4] = 576;
mtus[5] = 1024;
mtus[6] = 1280;
mtus[7] = 1492;
@ -2682,6 +2744,34 @@ static void ulp_config(struct adapter *adap, const struct tp_params *p)
t3_write_reg(adap, A_ULPRX_TDDP_TAGMASK, 0xffffffff);
}
/**
* t3_set_proto_sram - set the contents of the protocol sram
* @adapter: the adapter
* @data: the protocol image
*
* Write the contents of the protocol SRAM.
*/
int t3_set_proto_sram(struct adapter *adap, u8 *data)
{
int i;
u32 *buf = (u32 *)data;
for (i = 0; i < PROTO_SRAM_LINES; i++) {
t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, cpu_to_be32(*buf++));
t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, cpu_to_be32(*buf++));
t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, cpu_to_be32(*buf++));
t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, cpu_to_be32(*buf++));
t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, cpu_to_be32(*buf++));
t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, i << 1 | 1 << 31);
if (t3_wait_op_done(adap, A_TP_EMBED_OP_FIELD0, 1, 1, 5, 1))
return -EIO;
}
t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, 0);
return 0;
}
void t3_config_trace_filter(struct adapter *adapter,
const struct trace_params *tp, int filter_index,
int invert, int enable)
@ -2802,7 +2892,7 @@ static void init_hw_for_avail_ports(struct adapter *adap, int nports)
t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0);
t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_TPTXPORT0EN |
F_PORT0ACTIVE | F_ENFORCEPKT);
t3_write_reg(adap, A_PM1_TX_CFG, 0xc000c000);
t3_write_reg(adap, A_PM1_TX_CFG, 0xffffffff);
} else {
t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN);
t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB);
@ -3097,7 +3187,7 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params)
else
t3_set_reg_field(adapter, A_PCIX_CFG, 0, F_CLIDECEN);
t3_write_reg(adapter, A_PM1_RX_CFG, 0xf000f000);
t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff);
init_hw_for_avail_ports(adapter, adapter->params.nports);
t3_sge_init(adapter, &adapter->params.sge);

View file

@ -39,6 +39,6 @@
/* Firmware version */
#define FW_VERSION_MAJOR 4
#define FW_VERSION_MINOR 0
#define FW_VERSION_MINOR 1
#define FW_VERSION_MICRO 0
#endif /* __CHELSIO_VERSION_H */

View file

@ -39,7 +39,7 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
#define DRV_VERSION "EHEA_0064"
#define DRV_VERSION "EHEA_0065"
#define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
@ -136,10 +136,10 @@ void ehea_dump(void *adr, int len, char *msg);
(0xffffffffffffffffULL >> ((64 - (mask)) & 0xffff))
#define EHEA_BMASK_SET(mask, value) \
((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask))
((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask))
#define EHEA_BMASK_GET(mask, value) \
(EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask)))
(EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask)))
/*
* Generic ehea page
@ -190,7 +190,7 @@ struct ehea_av;
* Queue attributes passed to ehea_create_qp()
*/
struct ehea_qp_init_attr {
/* input parameter */
/* input parameter */
u32 qp_token; /* queue token */
u8 low_lat_rq1;
u8 signalingtype; /* cqe generation flag */
@ -212,7 +212,7 @@ struct ehea_qp_init_attr {
u64 recv_cq_handle;
u64 aff_eq_handle;
/* output parameter */
/* output parameter */
u32 qp_nr;
u16 act_nr_send_wqes;
u16 act_nr_rwqes_rq1;
@ -279,12 +279,12 @@ struct ehea_qp {
* Completion Queue attributes
*/
struct ehea_cq_attr {
/* input parameter */
/* input parameter */
u32 max_nr_of_cqes;
u32 cq_token;
u64 eq_handle;
/* output parameter */
/* output parameter */
u32 act_nr_of_cqes;
u32 nr_pages;
};

View file

@ -211,34 +211,34 @@ static inline void epa_store_acc(struct h_epa epa, u32 offset, u64 value)
}
#define epa_store_eq(epa, offset, value)\
epa_store(epa, EQTEMM_OFFSET(offset), value)
epa_store(epa, EQTEMM_OFFSET(offset), value)
#define epa_load_eq(epa, offset)\
epa_load(epa, EQTEMM_OFFSET(offset))
epa_load(epa, EQTEMM_OFFSET(offset))
#define epa_store_cq(epa, offset, value)\
epa_store(epa, CQTEMM_OFFSET(offset), value)
epa_store(epa, CQTEMM_OFFSET(offset), value)
#define epa_load_cq(epa, offset)\
epa_load(epa, CQTEMM_OFFSET(offset))
epa_load(epa, CQTEMM_OFFSET(offset))
#define epa_store_qp(epa, offset, value)\
epa_store(epa, QPTEMM_OFFSET(offset), value)
epa_store(epa, QPTEMM_OFFSET(offset), value)
#define epa_load_qp(epa, offset)\
epa_load(epa, QPTEMM_OFFSET(offset))
epa_load(epa, QPTEMM_OFFSET(offset))
#define epa_store_qped(epa, offset, value)\
epa_store(epa, QPEDMM_OFFSET(offset), value)
epa_store(epa, QPEDMM_OFFSET(offset), value)
#define epa_load_qped(epa, offset)\
epa_load(epa, QPEDMM_OFFSET(offset))
epa_load(epa, QPEDMM_OFFSET(offset))
#define epa_store_mrmw(epa, offset, value)\
epa_store(epa, MRMWMM_OFFSET(offset), value)
epa_store(epa, MRMWMM_OFFSET(offset), value)
#define epa_load_mrmw(epa, offset)\
epa_load(epa, MRMWMM_OFFSET(offset))
epa_load(epa, MRMWMM_OFFSET(offset))
#define epa_store_base(epa, offset, value)\
epa_store(epa, HCAGR_OFFSET(offset), value)
epa_store(epa, HCAGR_OFFSET(offset), value)
#define epa_load_base(epa, offset)\
epa_load(epa, HCAGR_OFFSET(offset))
epa_load(epa, HCAGR_OFFSET(offset))
static inline void ehea_update_sqa(struct ehea_qp *qp, u16 nr_wqes)
{

View file

@ -81,7 +81,7 @@ MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 ");
static int port_name_cnt = 0;
static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
const struct of_device_id *id);
const struct of_device_id *id);
static int __devexit ehea_remove(struct ibmebus_dev *dev);
@ -236,7 +236,7 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr,
rwqe = ehea_get_next_rwqe(qp, rq_nr);
rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
| EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
| EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
rwqe->sg_list[0].vaddr = (u64)skb->data;
rwqe->sg_list[0].len = packet_size;
@ -427,7 +427,7 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev,
break;
}
skb_copy_to_linear_data(skb, ((char*)cqe) + 64,
cqe->num_bytes_transfered - 4);
cqe->num_bytes_transfered - 4);
ehea_fill_skb(port->netdev, skb, cqe);
} else if (rq == 2) { /* RQ2 */
skb = get_skb_by_index(skb_arr_rq2,
@ -618,7 +618,7 @@ static struct ehea_port *ehea_get_port(struct ehea_adapter *adapter,
for (i = 0; i < EHEA_MAX_PORTS; i++)
if (adapter->port[i])
if (adapter->port[i]->logical_port_id == logical_port)
if (adapter->port[i]->logical_port_id == logical_port)
return adapter->port[i];
return NULL;
}
@ -1695,6 +1695,7 @@ static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
{
if (skb->protocol == htons(ETH_P_IP)) {
const struct iphdr *iph = ip_hdr(skb);
/* IPv4 */
swqe->tx_control |= EHEA_SWQE_CRC
| EHEA_SWQE_IP_CHECKSUM
@ -1705,13 +1706,12 @@ static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
write_ip_start_end(swqe, skb);
if (iph->protocol == IPPROTO_UDP) {
if ((iph->frag_off & IP_MF) ||
(iph->frag_off & IP_OFFSET))
if ((iph->frag_off & IP_MF)
|| (iph->frag_off & IP_OFFSET))
/* IP fragment, so don't change cs */
swqe->tx_control &= ~EHEA_SWQE_TCP_CHECKSUM;
else
write_udp_offset_end(swqe, skb);
} else if (iph->protocol == IPPROTO_TCP) {
write_tcp_offset_end(swqe, skb);
}
@ -1739,6 +1739,7 @@ static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
if (skb->protocol == htons(ETH_P_IP)) {
const struct iphdr *iph = ip_hdr(skb);
/* IPv4 */
write_ip_start_end(swqe, skb);
@ -1751,8 +1752,8 @@ static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
write_tcp_offset_end(swqe, skb);
} else if (iph->protocol == IPPROTO_UDP) {
if ((iph->frag_off & IP_MF) ||
(iph->frag_off & IP_OFFSET))
if ((iph->frag_off & IP_MF)
|| (iph->frag_off & IP_OFFSET))
/* IP fragment, so don't change cs */
swqe->tx_control |= EHEA_SWQE_CRC
| EHEA_SWQE_IMM_DATA_PRESENT;
@ -2407,7 +2408,7 @@ static void __devinit logical_port_release(struct device *dev)
}
static int ehea_driver_sysfs_add(struct device *dev,
struct device_driver *driver)
struct device_driver *driver)
{
int ret;
@ -2424,7 +2425,7 @@ static int ehea_driver_sysfs_add(struct device *dev,
}
static void ehea_driver_sysfs_remove(struct device *dev,
struct device_driver *driver)
struct device_driver *driver)
{
struct device_driver *drv = driver;
@ -2453,7 +2454,7 @@ static struct device *ehea_register_port(struct ehea_port *port,
}
ret = device_create_file(&port->ofdev.dev, &dev_attr_log_port_id);
if (ret) {
if (ret) {
ehea_error("failed to register attributes, ret=%d", ret);
goto out_unreg_of_dev;
}
@ -2601,6 +2602,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)
{
struct device_node *lhea_dn;
struct device_node *eth_dn = NULL;
const u32 *dn_log_port_id;
int i = 0;
@ -2608,7 +2610,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)
while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
NULL);
NULL);
if (!dn_log_port_id) {
ehea_error("bad device node: eth_dn name=%s",
eth_dn->full_name);
@ -2648,7 +2650,7 @@ static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter,
while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
NULL);
NULL);
if (dn_log_port_id)
if (*dn_log_port_id == logical_port_id)
return eth_dn;
@ -2789,7 +2791,7 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
adapter->ebus_dev = dev;
adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
NULL);
NULL);
if (adapter_handle)
adapter->handle = *adapter_handle;

View file

@ -211,7 +211,7 @@ u64 ehea_destroy_cq_res(struct ehea_cq *cq, u64 force)
u64 hret;
u64 adapter_handle = cq->adapter->handle;
/* deregister all previous registered pages */
/* deregister all previous registered pages */
hret = ehea_h_free_resource(adapter_handle, cq->fw_handle, force);
if (hret != H_SUCCESS)
return hret;
@ -362,7 +362,7 @@ int ehea_destroy_eq(struct ehea_eq *eq)
if (hret != H_SUCCESS) {
ehea_error("destroy EQ failed");
return -EIO;
}
}
return 0;
}
@ -507,44 +507,44 @@ out_freemem:
u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force)
{
u64 hret;
struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
u64 hret;
struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
if (hret != H_SUCCESS)
return hret;
ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
if (hret != H_SUCCESS)
return hret;
hw_queue_dtor(&qp->hw_squeue);
hw_queue_dtor(&qp->hw_rqueue1);
hw_queue_dtor(&qp->hw_squeue);
hw_queue_dtor(&qp->hw_rqueue1);
if (qp_attr->rq_count > 1)
hw_queue_dtor(&qp->hw_rqueue2);
if (qp_attr->rq_count > 2)
hw_queue_dtor(&qp->hw_rqueue3);
kfree(qp);
if (qp_attr->rq_count > 1)
hw_queue_dtor(&qp->hw_rqueue2);
if (qp_attr->rq_count > 2)
hw_queue_dtor(&qp->hw_rqueue3);
kfree(qp);
return hret;
return hret;
}
int ehea_destroy_qp(struct ehea_qp *qp)
{
u64 hret;
if (!qp)
return 0;
u64 hret;
if (!qp)
return 0;
if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
ehea_error_data(qp->adapter, qp->fw_handle);
hret = ehea_destroy_qp_res(qp, FORCE_FREE);
}
if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
ehea_error_data(qp->adapter, qp->fw_handle);
hret = ehea_destroy_qp_res(qp, FORCE_FREE);
}
if (hret != H_SUCCESS) {
ehea_error("destroy QP failed");
return -EIO;
}
if (hret != H_SUCCESS) {
ehea_error("destroy QP failed");
return -EIO;
}
return 0;
return 0;
}
int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)

View file

@ -1,6 +1,6 @@
config FEC_8XX
tristate "Motorola 8xx FEC driver"
depends on NET_ETHERNET && 8xx
depends on 8XX
select MII
config FEC_8XX_GENERIC_PHY

View file

@ -1,6 +1,6 @@
config FS_ENET
tristate "Freescale Ethernet Driver"
depends on NET_ETHERNET && (CPM1 || CPM2)
depends on CPM1 || CPM2
select MII
config FS_ENET_HAS_SCC

View file

@ -130,6 +130,9 @@ static int gfar_remove(struct platform_device *pdev);
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);
static void gfar_configure_serdes(struct net_device *dev);
extern int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value);
extern int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum);
#ifdef CONFIG_GFAR_NAPI
static int gfar_poll(struct net_device *dev, int *budget);
#endif
@ -451,6 +454,9 @@ static int init_phy(struct net_device *dev)
phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface);
if (interface == PHY_INTERFACE_MODE_SGMII)
gfar_configure_serdes(dev);
if (IS_ERR(phydev)) {
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
return PTR_ERR(phydev);
@ -465,6 +471,27 @@ static int init_phy(struct net_device *dev)
return 0;
}
static void gfar_configure_serdes(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
struct gfar_mii __iomem *regs =
(void __iomem *)&priv->regs->gfar_mii_regs;
/* Initialise TBI i/f to communicate with serdes (lynx phy) */
/* Single clk mode, mii mode off(for aerdes communication) */
gfar_local_mdio_write(regs, TBIPA_VALUE, MII_TBICON, TBICON_CLK_SELECT);
/* Supported pause and full-duplex, no half-duplex */
gfar_local_mdio_write(regs, TBIPA_VALUE, MII_ADVERTISE,
ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE |
ADVERTISE_1000XPSE_ASYM);
/* ANEG enable, restart ANEG, full duplex mode, speed[1] set */
gfar_local_mdio_write(regs, TBIPA_VALUE, MII_BMCR, BMCR_ANENABLE |
BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000);
}
static void init_registers(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);

View file

@ -136,6 +136,12 @@ extern const char gfar_driver_version[];
#define MIIMCFG_RESET 0x80000000
#define MIIMIND_BUSY 0x00000001
/* TBI register addresses */
#define MII_TBICON 0x11
/* TBICON register bit fields */
#define TBICON_CLK_SELECT 0x0020
/* MAC register bits */
#define MACCFG1_SOFT_RESET 0x80000000
#define MACCFG1_RESET_RX_MC 0x00080000

View file

@ -43,13 +43,18 @@
#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)
/*
* Write value to the PHY at mii_id at register regnum,
* on the bus attached to the local interface, which may be different from the
* generic mdio bus (tied to a single interface), waiting until the write is
* done before returning. This is helpful in programming interfaces like
* the TBI which control interfaces like onchip SERDES and are always tied to
* the local mdio pins, which may not be the same as system mdio bus, used for
* controlling the external PHYs, for example.
*/
int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id,
int regnum, u16 value)
{
struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
/* Set the PHY address and the register address we want to write */
gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
@ -63,12 +68,19 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
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)
/*
* Read the bus for PHY at addr mii_id, register regnum, and
* return the value. Clears miimcom first. All PHY operation
* done on the bus attached to the local interface,
* which may be different from the generic mdio bus
* This is helpful in programming interfaces like
* the TBI which, inturn, control interfaces like onchip SERDES
* and are always tied to the local mdio pins, which may not be the
* same as system mdio bus, used for controlling the external PHYs, for eg.
*/
int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum)
{
struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
u16 value;
/* Set the PHY address and the register address we want to read */
@ -88,6 +100,27 @@ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
return value;
}
/* 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 __iomem *regs = (void __iomem *)bus->priv;
/* Write to the local MII regs */
return(gfar_local_mdio_write(regs, mii_id, regnum, value));
}
/* 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 __iomem *regs = (void __iomem *)bus->priv;
/* Read the local MII regs */
return(gfar_local_mdio_read(regs, mii_id, regnum));
}
/* Reset the MIIM registers, and wait for the bus to free */
int gfar_mdio_reset(struct mii_bus *bus)

File diff suppressed because it is too large Load diff

1434
drivers/net/lib82596.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -113,8 +113,7 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
struct mlx4_cmd_mailbox *mailbox;
int ret = 0;
if (cur_state < 0 || cur_state >= MLX4_QP_NUM_STATE ||
new_state < 0 || cur_state >= MLX4_QP_NUM_STATE ||
if (cur_state >= MLX4_QP_NUM_STATE || cur_state >= MLX4_QP_NUM_STATE ||
!op[cur_state][new_state])
return -EINVAL;

View file

@ -724,7 +724,7 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter)
__u32 mac_cfg0;
u32 port = physical_port[adapter->portnum];
if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
if (port > NETXEN_NIU_MAX_GBE_PORTS)
return -EINVAL;
mac_cfg0 = 0;
netxen_gb_soft_reset(mac_cfg0);
@ -757,7 +757,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
__u32 reg;
u32 port = physical_port[adapter->portnum];
if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
if (port > NETXEN_NIU_MAX_GBE_PORTS)
return -EINVAL;
/* save previous contents */
@ -894,7 +894,7 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
__u32 reg;
u32 port = physical_port[adapter->portnum];
if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
if (port > NETXEN_NIU_MAX_XG_PORTS)
return -EINVAL;
if (netxen_nic_hw_read_wx(adapter,

View file

@ -755,7 +755,7 @@ static int pasemi_mac_open(struct net_device *dev)
flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
PAS_IOB_DMA_RXCH_CFG_CNTTH(1));
PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch),
PAS_IOB_DMA_TXCH_CFG_CNTTH(32));

View file

@ -521,6 +521,7 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value)
static int axnet_open(struct net_device *dev)
{
int ret;
axnet_dev_t *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
@ -529,9 +530,11 @@ static int axnet_open(struct net_device *dev)
if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
if (ret)
return ret;
request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
link->open++;
info->link_status = 0x00;
init_timer(&info->watchdog);

View file

@ -109,7 +109,7 @@ static const struct ethtool_ops netdev_ethtool_ops;
card type
*/
typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
XXX10304
XXX10304, NEC, KME
} cardtype_t;
/*
@ -374,6 +374,18 @@ static int fmvj18x_config(struct pcmcia_device *link)
link->io.NumPorts2 = 8;
}
break;
case MANFID_NEC:
cardtype = NEC; /* MultiFunction Card */
link->conf.ConfigBase = 0x800;
link->conf.ConfigIndex = 0x47;
link->io.NumPorts2 = 8;
break;
case MANFID_KME:
cardtype = KME; /* MultiFunction Card */
link->conf.ConfigBase = 0x800;
link->conf.ConfigIndex = 0x47;
link->io.NumPorts2 = 8;
break;
case MANFID_CONTEC:
cardtype = CONTEC;
break;
@ -450,6 +462,8 @@ static int fmvj18x_config(struct pcmcia_device *link)
case TDK:
case LA501:
case CONTEC:
case NEC:
case KME:
tuple.DesiredTuple = CISTPL_FUNCE;
tuple.TupleOffset = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
@ -469,6 +483,10 @@ static int fmvj18x_config(struct pcmcia_device *link)
card_name = "TDK LAK-CD021";
} else if( cardtype == LA501 ) {
card_name = "LA501";
} else if( cardtype == NEC ) {
card_name = "PK-UG-J001";
} else if( cardtype == KME ) {
card_name = "Panasonic";
} else {
card_name = "C-NET(PC)C";
}
@ -678,8 +696,11 @@ static struct pcmcia_device_id fmvj18x_ids[] = {
PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da),
PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a),
PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05),
PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101),
PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);

View file

@ -960,6 +960,7 @@ static void mii_phy_probe(struct net_device *dev)
static int pcnet_open(struct net_device *dev)
{
int ret;
pcnet_dev_t *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
@ -968,10 +969,12 @@ static int pcnet_open(struct net_device *dev)
if (!pcmcia_dev_present(link))
return -ENODEV;
link->open++;
set_misc_reg(dev);
request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev);
ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev);
if (ret)
return ret;
link->open++;
info->phy_id = info->eth_phy;
info->link_status = 0x00;
@ -1552,6 +1555,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c),

View file

@ -55,6 +55,11 @@ config BROADCOM_PHY
---help---
Currently supports the BCM5411, BCM5421 and BCM5461 PHYs.
config ICPLUS_PHY
tristate "Drivers for ICPlus PHYs"
---help---
Currently supports the IP175C PHY.
config FIXED_PHY
tristate "Drivers for PHY emulation on fixed speed/link"
---help---

View file

@ -11,4 +11,5 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_SMSC_PHY) += smsc.o
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
obj-$(CONFIG_FIXED_PHY) += fixed.o

134
drivers/net/phy/icplus.c Normal file
View file

@ -0,0 +1,134 @@
/*
* Driver for ICPlus PHYs
*
* Copyright (c) 2007 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/kernel.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/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
MODULE_DESCRIPTION("ICPlus IP175C PHY driver");
MODULE_AUTHOR("Michael Barkowski");
MODULE_LICENSE("GPL");
static int ip175c_config_init(struct phy_device *phydev)
{
int err, i;
static int full_reset_performed = 0;
if (full_reset_performed == 0) {
/* master reset */
err = phydev->bus->write(phydev->bus, 30, 0, 0x175c);
if (err < 0)
return err;
/* ensure no bus delays overlap reset period */
err = phydev->bus->read(phydev->bus, 30, 0);
/* data sheet specifies reset period is 2 msec */
mdelay(2);
/* enable IP175C mode */
err = phydev->bus->write(phydev->bus, 29, 31, 0x175c);
if (err < 0)
return err;
/* Set MII0 speed and duplex (in PHY mode) */
err = phydev->bus->write(phydev->bus, 29, 22, 0x420);
if (err < 0)
return err;
/* reset switch ports */
for (i = 0; i < 5; i++) {
err = phydev->bus->write(phydev->bus, i,
MII_BMCR, BMCR_RESET);
if (err < 0)
return err;
}
for (i = 0; i < 5; i++)
err = phydev->bus->read(phydev->bus, i, MII_BMCR);
mdelay(2);
full_reset_performed = 1;
}
if (phydev->addr != 4) {
phydev->state = PHY_RUNNING;
phydev->speed = SPEED_100;
phydev->duplex = DUPLEX_FULL;
phydev->link = 1;
netif_carrier_on(phydev->attached_dev);
}
return 0;
}
static int ip175c_read_status(struct phy_device *phydev)
{
if (phydev->addr == 4) /* WAN port */
genphy_read_status(phydev);
else
/* Don't need to read status for switch ports */
phydev->irq = PHY_IGNORE_INTERRUPT;
return 0;
}
static int ip175c_config_aneg(struct phy_device *phydev)
{
if (phydev->addr == 4) /* WAN port */
genphy_config_aneg(phydev);
return 0;
}
static struct phy_driver ip175c_driver = {
.phy_id = 0x02430d80,
.name = "ICPlus IP175C",
.phy_id_mask = 0x0ffffff0,
.features = PHY_BASIC_FEATURES,
.config_init = &ip175c_config_init,
.config_aneg = &ip175c_config_aneg,
.read_status = &ip175c_read_status,
.driver = { .owner = THIS_MODULE,},
};
static int __init ip175c_init(void)
{
return phy_driver_register(&ip175c_driver);
}
static void __exit ip175c_exit(void)
{
phy_driver_unregister(&ip175c_driver);
}
module_init(ip175c_init);
module_exit(ip175c_exit);

View file

@ -60,6 +60,7 @@
#define MII_M1111_PHY_EXT_SR 0x1b
#define MII_M1111_HWCFG_MODE_MASK 0xf
#define MII_M1111_HWCFG_MODE_RGMII 0xb
#define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4
MODULE_DESCRIPTION("Marvell PHY driver");
MODULE_AUTHOR("Andy Fleming");
@ -169,6 +170,21 @@ static int m88e1111_config_init(struct phy_device *phydev)
return err;
}
if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
int temp;
temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
if (temp < 0)
return temp;
temp &= ~(MII_M1111_HWCFG_MODE_MASK);
temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK;
err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
if (err < 0)
return err;
}
err = phy_write(phydev, MII_BMCR, BMCR_RESET);
if (err < 0)
return err;

View file

@ -2433,37 +2433,22 @@ static int ql_get_seg_count(struct ql3_adapter *qdev,
return -1;
}
static void ql_hw_csum_setup(struct sk_buff *skb,
static void ql_hw_csum_setup(const struct sk_buff *skb,
struct ob_mac_iocb_req *mac_iocb_ptr)
{
struct ethhdr *eth;
struct iphdr *ip = NULL;
u8 offset = ETH_HLEN;
const struct iphdr *ip = ip_hdr(skb);
eth = (struct ethhdr *)(skb->data);
mac_iocb_ptr->ip_hdr_off = skb_network_offset(skb);
mac_iocb_ptr->ip_hdr_len = ip->ihl;
if (eth->h_proto == __constant_htons(ETH_P_IP)) {
ip = (struct iphdr *)&skb->data[ETH_HLEN];
} else if (eth->h_proto == htons(ETH_P_8021Q) &&
((struct vlan_ethhdr *)skb->data)->
h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP)) {
ip = (struct iphdr *)&skb->data[VLAN_ETH_HLEN];
offset = VLAN_ETH_HLEN;
if (ip->protocol == IPPROTO_TCP) {
mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC |
OB_3032MAC_IOCB_REQ_IC;
} else {
mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC |
OB_3032MAC_IOCB_REQ_IC;
}
if (ip) {
if (ip->protocol == IPPROTO_TCP) {
mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC |
OB_3032MAC_IOCB_REQ_IC;
mac_iocb_ptr->ip_hdr_off = offset;
mac_iocb_ptr->ip_hdr_len = ip->ihl;
} else if (ip->protocol == IPPROTO_UDP) {
mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC |
OB_3032MAC_IOCB_REQ_IC;
mac_iocb_ptr->ip_hdr_off = offset;
mac_iocb_ptr->ip_hdr_len = ip->ihl;
}
}
}
/*

File diff suppressed because it is too large Load diff

View file

@ -469,11 +469,18 @@ static struct pci_device_id s2io_tbl[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, s2io_tbl);
static struct pci_error_handlers s2io_err_handler = {
.error_detected = s2io_io_error_detected,
.slot_reset = s2io_io_slot_reset,
.resume = s2io_io_resume,
};
static struct pci_driver s2io_driver = {
.name = "S2IO",
.id_table = s2io_tbl,
.probe = s2io_init_nic,
.remove = __devexit_p(s2io_rem_nic),
.err_handler = &s2io_err_handler,
};
/* A simplifier macro used both by init and free shared_mem Fns(). */
@ -2689,6 +2696,9 @@ static void s2io_netpoll(struct net_device *dev)
u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
int i;
if (pci_channel_offline(nic->pdev))
return;
disable_irq(dev->irq);
atomic_inc(&nic->isr_cnt);
@ -3215,6 +3225,8 @@ static void alarm_intr_handler(struct s2io_nic *nic)
int i;
if (atomic_read(&nic->card_state) == CARD_DOWN)
return;
if (pci_channel_offline(nic->pdev))
return;
nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0;
/* Handling the XPAK counters update */
if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) {
@ -3958,7 +3970,6 @@ static int s2io_close(struct net_device *dev)
/* Reset card, kill tasklet and free Tx and Rx buffers. */
s2io_card_down(sp);
sp->device_close_flag = TRUE; /* Device is shut down. */
return 0;
}
@ -4314,6 +4325,10 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
struct mac_info *mac_control;
struct config_param *config;
/* Pretend we handled any irq's from a disconnected card */
if (pci_channel_offline(sp->pdev))
return IRQ_NONE;
atomic_inc(&sp->isr_cnt);
mac_control = &sp->mac_control;
config = &sp->config;
@ -6569,7 +6584,7 @@ static void s2io_rem_isr(struct s2io_nic * sp)
} while(cnt < 5);
}
static void s2io_card_down(struct s2io_nic * sp)
static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
{
int cnt = 0;
struct XENA_dev_config __iomem *bar0 = sp->bar0;
@ -6584,7 +6599,8 @@ static void s2io_card_down(struct s2io_nic * sp)
atomic_set(&sp->card_state, CARD_DOWN);
/* disable Tx and Rx traffic on the NIC */
stop_nic(sp);
if (do_io)
stop_nic(sp);
s2io_rem_isr(sp);
@ -6592,7 +6608,7 @@ static void s2io_card_down(struct s2io_nic * sp)
tasklet_kill(&sp->task);
/* Check if the device is Quiescent and then Reset the NIC */
do {
while(do_io) {
/* As per the HW requirement we need to replenish the
* receive buffer to avoid the ring bump. Since there is
* no intention of processing the Rx frame at this pointwe are
@ -6617,8 +6633,9 @@ static void s2io_card_down(struct s2io_nic * sp)
(unsigned long long) val64);
break;
}
} while (1);
s2io_reset(sp);
}
if (do_io)
s2io_reset(sp);
spin_lock_irqsave(&sp->tx_lock, flags);
/* Free all Tx buffers */
@ -6633,6 +6650,11 @@ static void s2io_card_down(struct s2io_nic * sp)
clear_bit(0, &(sp->link_state));
}
static void s2io_card_down(struct s2io_nic * sp)
{
do_s2io_card_down(sp, 1);
}
static int s2io_card_up(struct s2io_nic * sp)
{
int i, ret = 0;
@ -8010,3 +8032,85 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++;
return;
}
/**
* s2io_io_error_detected - called when PCI error is detected
* @pdev: Pointer to PCI device
* @state: The current pci conneection state
*
* This function is called after a PCI bus error affecting
* this device has been detected.
*/
static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct s2io_nic *sp = netdev->priv;
netif_device_detach(netdev);
if (netif_running(netdev)) {
/* Bring down the card, while avoiding PCI I/O */
do_s2io_card_down(sp, 0);
}
pci_disable_device(pdev);
return PCI_ERS_RESULT_NEED_RESET;
}
/**
* s2io_io_slot_reset - called after the pci bus has been reset.
* @pdev: Pointer to PCI device
*
* Restart the card from scratch, as if from a cold-boot.
* At this point, the card has exprienced a hard reset,
* followed by fixups by BIOS, and has its config space
* set up identically to what it was at cold boot.
*/
static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct s2io_nic *sp = netdev->priv;
if (pci_enable_device(pdev)) {
printk(KERN_ERR "s2io: "
"Cannot re-enable PCI device after reset.\n");
return PCI_ERS_RESULT_DISCONNECT;
}
pci_set_master(pdev);
s2io_reset(sp);
return PCI_ERS_RESULT_RECOVERED;
}
/**
* s2io_io_resume - called when traffic can start flowing again.
* @pdev: Pointer to PCI device
*
* This callback is called when the error recovery driver tells
* us that its OK to resume normal operation.
*/
static void s2io_io_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct s2io_nic *sp = netdev->priv;
if (netif_running(netdev)) {
if (s2io_card_up(sp)) {
printk(KERN_ERR "s2io: "
"Can't bring device back up after reset.\n");
return;
}
if (s2io_set_mac_addr(netdev, netdev->dev_addr) == FAILURE) {
s2io_card_down(sp);
printk(KERN_ERR "s2io: "
"Can't resetore mac addr after reset.\n");
return;
}
}
netif_device_attach(netdev);
netif_wake_queue(netdev);
}

View file

@ -794,7 +794,6 @@ struct s2io_nic {
struct net_device_stats stats;
int high_dma_flag;
int device_close_flag;
int device_enabled_once;
char name[60];
@ -1052,6 +1051,11 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
struct sk_buff *skb, u32 tcp_len);
static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring);
static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state);
static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev);
static void s2io_io_resume(struct pci_dev *pdev);
#define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size
#define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size
#define s2io_offload_type(skb) skb_shinfo(skb)->gso_type

View file

@ -50,7 +50,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
#define DRV_VERSION "1.14"
#define DRV_VERSION "1.15"
#define PFX DRV_NAME " "
/*
@ -130,7 +130,7 @@ static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */
// { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
{ 0 }
};
@ -217,13 +217,24 @@ static void sky2_power_on(struct sky2_hw *hw)
sky2_write8(hw, B2_Y2_CLK_GATE, 0);
if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
u32 reg1;
u32 reg;
sky2_pci_write32(hw, PCI_DEV_REG3, 0);
reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
reg1 &= P_ASPM_CONTROL_MSK;
sky2_pci_write32(hw, PCI_DEV_REG4, reg1);
sky2_pci_write32(hw, PCI_DEV_REG5, 0);
reg = sky2_pci_read32(hw, PCI_DEV_REG4);
/* set all bits to 0 except bits 15..12 and 8 */
reg &= P_ASPM_CONTROL_MSK;
sky2_pci_write32(hw, PCI_DEV_REG4, reg);
reg = sky2_pci_read32(hw, PCI_DEV_REG5);
/* set all bits to 0 except bits 28 & 27 */
reg &= P_CTL_TIM_VMAIN_AV_MSK;
sky2_pci_write32(hw, PCI_DEV_REG5, reg);
sky2_pci_write32(hw, PCI_CFG_REG_1, 0);
/* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */
reg = sky2_read32(hw, B2_GP_IO);
reg |= GLB_GPIO_STAT_RACE_DIS;
sky2_write32(hw, B2_GP_IO, reg);
}
}
@ -650,6 +661,30 @@ static void sky2_wol_init(struct sky2_port *sky2)
}
static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
{
if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) {
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
TX_STFW_ENA |
(hw->dev[port]->mtu > ETH_DATA_LEN) ? TX_JUMBO_ENA : TX_JUMBO_DIS);
} else {
if (hw->dev[port]->mtu > ETH_DATA_LEN) {
/* set Tx GMAC FIFO Almost Empty Threshold */
sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
(ECU_JUMBO_WM << 16) | ECU_AE_THR);
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
TX_JUMBO_ENA | TX_STFW_DIS);
/* Can't do offload because of lack of store/forward */
hw->dev[port]->features &= ~(NETIF_F_TSO | NETIF_F_SG
| NETIF_F_ALL_CSUM);
} else
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
TX_JUMBO_DIS | TX_STFW_ENA);
}
}
static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
{
struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
@ -730,8 +765,11 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
/* Configure Rx MAC FIFO */
sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
GMF_OPER_ON | GMF_RX_F_FL_ON);
reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
if (hw->chip_id == CHIP_ID_YUKON_EX)
reg |= GMF_RX_OVER_ON;
sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
/* Flush Rx MAC FIFO on any flow control or error */
sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
@ -747,16 +785,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
/* set Tx GMAC FIFO Almost Empty Threshold */
sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
(ECU_JUMBO_WM << 16) | ECU_AE_THR);
if (hw->dev[port]->mtu > ETH_DATA_LEN)
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
TX_JUMBO_ENA | TX_STFW_DIS);
else
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
TX_JUMBO_DIS | TX_STFW_ENA);
sky2_set_tx_stfwd(hw, port);
}
}
@ -939,14 +968,16 @@ static void rx_set_checksum(struct sky2_port *sky2)
{
struct sky2_rx_le *le;
le = sky2_next_rx(sky2);
le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
le->ctrl = 0;
le->opcode = OP_TCPSTART | HW_OWNER;
if (sky2->hw->chip_id != CHIP_ID_YUKON_EX) {
le = sky2_next_rx(sky2);
le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
le->ctrl = 0;
le->opcode = OP_TCPSTART | HW_OWNER;
sky2_write32(sky2->hw,
Q_ADDR(rxqaddr[sky2->port], Q_CSR),
sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
sky2_write32(sky2->hw,
Q_ADDR(rxqaddr[sky2->port], Q_CSR),
sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
}
}
@ -1134,7 +1165,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
if (hw->chip_id == CHIP_ID_YUKON_EC_U &&
(hw->chip_rev == CHIP_REV_YU_EC_U_A1
|| hw->chip_rev == CHIP_REV_YU_EC_U_B0))
sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS);
sky2_write32(hw, Q_ADDR(rxq, Q_TEST), F_M_RX_RAM_DIS);
sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
@ -1285,6 +1316,10 @@ static int sky2_up(struct net_device *dev)
sky2_qset(hw, txqaddr[port]);
/* This is copied from sk98lin 10.0.5.3; no one tells me about erratta's */
if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev == CHIP_REV_YU_EX_B0)
sky2_write32(hw, Q_ADDR(txqaddr[port], Q_TEST), F_TX_CHK_AUTO_OFF);
/* Set almost empty threshold */
if (hw->chip_id == CHIP_ID_YUKON_EC_U
&& hw->chip_rev == CHIP_REV_YU_EC_U_A0)
@ -1393,14 +1428,16 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
/* Check for TCP Segmentation Offload */
mss = skb_shinfo(skb)->gso_size;
if (mss != 0) {
mss += tcp_optlen(skb); /* TCP options */
mss += ip_hdrlen(skb) + sizeof(struct tcphdr);
mss += ETH_HLEN;
if (hw->chip_id != CHIP_ID_YUKON_EX)
mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
if (mss != sky2->tx_last_mss) {
le = get_tx_le(sky2);
le->addr = cpu_to_le32(mss);
le->opcode = OP_LRGLEN | HW_OWNER;
if (mss != sky2->tx_last_mss) {
le = get_tx_le(sky2);
le->addr = cpu_to_le32(mss);
if (hw->chip_id == CHIP_ID_YUKON_EX)
le->opcode = OP_MSS | HW_OWNER;
else
le->opcode = OP_LRGLEN | HW_OWNER;
sky2->tx_last_mss = mss;
}
}
@ -1422,24 +1459,30 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
/* Handle TCP checksum offload */
if (skb->ip_summed == CHECKSUM_PARTIAL) {
const unsigned offset = skb_transport_offset(skb);
u32 tcpsum;
/* On Yukon EX (some versions) encoding change. */
if (hw->chip_id == CHIP_ID_YUKON_EX
&& hw->chip_rev != CHIP_REV_YU_EX_B0)
ctrl |= CALSUM; /* auto checksum */
else {
const unsigned offset = skb_transport_offset(skb);
u32 tcpsum;
tcpsum = offset << 16; /* sum start */
tcpsum |= offset + skb->csum_offset; /* sum write */
tcpsum = offset << 16; /* sum start */
tcpsum |= offset + skb->csum_offset; /* sum write */
ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
if (ip_hdr(skb)->protocol == IPPROTO_UDP)
ctrl |= UDPTCP;
ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
if (ip_hdr(skb)->protocol == IPPROTO_UDP)
ctrl |= UDPTCP;
if (tcpsum != sky2->tx_tcpsum) {
sky2->tx_tcpsum = tcpsum;
if (tcpsum != sky2->tx_tcpsum) {
sky2->tx_tcpsum = tcpsum;
le = get_tx_le(sky2);
le->addr = cpu_to_le32(tcpsum);
le->length = 0; /* initial checksum value */
le->ctrl = 1; /* one packet */
le->opcode = OP_TCPLISW | HW_OWNER;
le = get_tx_le(sky2);
le->addr = cpu_to_le32(tcpsum);
le->length = 0; /* initial checksum value */
le->ctrl = 1; /* one packet */
le->opcode = OP_TCPLISW | HW_OWNER;
}
}
}
@ -1913,15 +1956,8 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
synchronize_irq(hw->pdev->irq);
if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
if (new_mtu > ETH_DATA_LEN) {
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
TX_JUMBO_ENA | TX_STFW_DIS);
dev->features &= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
} else
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
TX_JUMBO_DIS | TX_STFW_ENA);
}
if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
sky2_set_tx_stfwd(hw, port);
ctl = gma_read16(hw, port, GM_GP_CTRL);
gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA);
@ -2118,6 +2154,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
while (hw->st_idx != hwidx) {
struct sky2_status_le *le = hw->st_le + hw->st_idx;
unsigned port = le->css & CSS_LINK_BIT;
struct net_device *dev;
struct sk_buff *skb;
u32 status;
@ -2125,9 +2162,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE);
BUG_ON(le->link >= 2);
dev = hw->dev[le->link];
dev = hw->dev[port];
sky2 = netdev_priv(dev);
length = le16_to_cpu(le->length);
status = le32_to_cpu(le->status);
@ -2140,6 +2175,16 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
goto force_update;
}
/* This chip reports checksum status differently */
if (hw->chip_id == CHIP_ID_YUKON_EX) {
if (sky2->rx_csum &&
(le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
(le->css & CSS_TCPUDPCSOK))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
}
skb->protocol = eth_type_trans(skb, dev);
sky2->net_stats.rx_packets++;
sky2->net_stats.rx_bytes += skb->len;
@ -2155,10 +2200,10 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
netif_receive_skb(skb);
/* Update receiver after 16 frames */
if (++buf_write[le->link] == RX_BUF_WRITE) {
if (++buf_write[port] == RX_BUF_WRITE) {
force_update:
sky2_put_idx(hw, rxqaddr[le->link], sky2->rx_put);
buf_write[le->link] = 0;
sky2_put_idx(hw, rxqaddr[port], sky2->rx_put);
buf_write[port] = 0;
}
/* Stop after net poll weight */
@ -2179,6 +2224,9 @@ force_update:
if (!sky2->rx_csum)
break;
if (hw->chip_id == CHIP_ID_YUKON_EX)
break;
/* Both checksum counters are programmed to start at
* the same offset, so unless there is a problem they
* should match. This failure is an early indication that
@ -2194,7 +2242,7 @@ force_update:
dev->name, status);
sky2->rx_csum = 0;
sky2_write32(sky2->hw,
Q_ADDR(rxqaddr[le->link], Q_CSR),
Q_ADDR(rxqaddr[port], Q_CSR),
BMU_DIS_RX_CHKSUM);
}
break;
@ -2513,6 +2561,9 @@ static int __devinit sky2_init(struct sky2_hw *hw)
{
u8 t8;
/* Enable all clocks */
sky2_pci_write32(hw, PCI_DEV_REG3, 0);
sky2_write8(hw, B0_CTST, CS_RST_CLR);
hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
@ -2522,14 +2573,6 @@ static int __devinit sky2_init(struct sky2_hw *hw)
return -EOPNOTSUPP;
}
if (hw->chip_id == CHIP_ID_YUKON_EX)
dev_warn(&hw->pdev->dev, "this driver not yet tested on this chip type\n"
"Please report success or failure to <[email protected]>\n");
/* Make sure and enable all clocks */
if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U)
sky2_pci_write32(hw, PCI_DEV_REG3, 0);
hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
/* This rev is really old, and requires untested workarounds */
@ -2589,6 +2632,11 @@ static void sky2_reset(struct sky2_hw *hw)
for (i = 0; i < hw->ports; i++) {
sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
if (hw->chip_id == CHIP_ID_YUKON_EX)
sky2_write16(hw, SK_REG(i, GMAC_CTRL),
GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON
| GMC_BYP_RETR_ON);
}
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
@ -2735,7 +2783,7 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
sky2->wol = wol->wolopts;
if (hw->chip_id == CHIP_ID_YUKON_EC_U)
if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
sky2_write32(hw, B0_CTST, sky2->wol
? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
@ -3330,7 +3378,7 @@ static int sky2_get_regs_len(struct net_device *dev)
/*
* Returns copy of control register region
* Note: access to the RAM address register set will cause timeouts.
* Note: ethtool_get_regs always provides full size (16k) buffer
*/
static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *p)
@ -3338,15 +3386,19 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
const struct sky2_port *sky2 = netdev_priv(dev);
const void __iomem *io = sky2->hw->regs;
BUG_ON(regs->len < B3_RI_WTO_R1);
regs->version = 1;
memset(p, 0, regs->len);
memcpy_fromio(p, io, B3_RAM_ADDR);
memcpy_fromio(p + B3_RI_WTO_R1,
io + B3_RI_WTO_R1,
regs->len - B3_RI_WTO_R1);
/* skip diagnostic ram region */
memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, 0x2000 - B3_RI_WTO_R1);
/* copy GMAC registers */
memcpy_fromio(p + BASE_GMAC_1, io + BASE_GMAC_1, 0x1000);
if (sky2->hw->ports > 1)
memcpy_fromio(p + BASE_GMAC_2, io + BASE_GMAC_2, 0x1000);
}
/* In order to do Jumbo packets on these chips, need to turn off the
@ -3357,9 +3409,7 @@ static int no_tx_offload(struct net_device *dev)
const struct sky2_port *sky2 = netdev_priv(dev);
const struct sky2_hw *hw = sky2->hw;
return dev->mtu > ETH_DATA_LEN &&
(hw->chip_id == CHIP_ID_YUKON_EX
|| hw->chip_id == CHIP_ID_YUKON_EC_U);
return dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U;
}
static int sky2_set_tx_csum(struct net_device *dev, u32 data)

View file

@ -14,6 +14,8 @@ enum {
PCI_DEV_REG3 = 0x80,
PCI_DEV_REG4 = 0x84,
PCI_DEV_REG5 = 0x88,
PCI_CFG_REG_0 = 0x90,
PCI_CFG_REG_1 = 0x94,
};
enum {
@ -28,6 +30,7 @@ enum {
enum pci_dev_reg_1 {
PCI_Y2_PIG_ENA = 1<<31, /* Enable Plug-in-Go (YUKON-2) */
PCI_Y2_DLL_DIS = 1<<30, /* Disable PCI DLL (YUKON-2) */
PCI_SW_PWR_ON_RST= 1<<30, /* SW Power on Reset (Yukon-EX) */
PCI_Y2_PHY2_COMA = 1<<29, /* Set PHY 2 to Coma Mode (YUKON-2) */
PCI_Y2_PHY1_COMA = 1<<28, /* Set PHY 1 to Coma Mode (YUKON-2) */
PCI_Y2_PHY2_POWD = 1<<27, /* Set PHY 2 to Power Down (YUKON-2) */
@ -67,6 +70,80 @@ enum pci_dev_reg_4 {
| P_ASPM_CLKRUN_REQUEST | P_ASPM_INT_FIFO_EMPTY,
};
/* PCI_OUR_REG_5 32 bit Our Register 5 (Yukon-ECU only) */
enum pci_dev_reg_5 {
/* Bit 31..27: for A3 & later */
P_CTL_DIV_CORE_CLK_ENA = 1<<31, /* Divide Core Clock Enable */
P_CTL_SRESET_VMAIN_AV = 1<<30, /* Soft Reset for Vmain_av De-Glitch */
P_CTL_BYPASS_VMAIN_AV = 1<<29, /* Bypass En. for Vmain_av De-Glitch */
P_CTL_TIM_VMAIN_AV_MSK = 3<<27, /* Bit 28..27: Timer Vmain_av Mask */
/* Bit 26..16: Release Clock on Event */
P_REL_PCIE_RST_DE_ASS = 1<<26, /* PCIe Reset De-Asserted */
P_REL_GPHY_REC_PACKET = 1<<25, /* GPHY Received Packet */
P_REL_INT_FIFO_N_EMPTY = 1<<24, /* Internal FIFO Not Empty */
P_REL_MAIN_PWR_AVAIL = 1<<23, /* Main Power Available */
P_REL_CLKRUN_REQ_REL = 1<<22, /* CLKRUN Request Release */
P_REL_PCIE_RESET_ASS = 1<<21, /* PCIe Reset Asserted */
P_REL_PME_ASSERTED = 1<<20, /* PME Asserted */
P_REL_PCIE_EXIT_L1_ST = 1<<19, /* PCIe Exit L1 State */
P_REL_LOADER_NOT_FIN = 1<<18, /* EPROM Loader Not Finished */
P_REL_PCIE_RX_EX_IDLE = 1<<17, /* PCIe Rx Exit Electrical Idle State */
P_REL_GPHY_LINK_UP = 1<<16, /* GPHY Link Up */
/* Bit 10.. 0: Mask for Gate Clock */
P_GAT_PCIE_RST_ASSERTED = 1<<10,/* PCIe Reset Asserted */
P_GAT_GPHY_N_REC_PACKET = 1<<9, /* GPHY Not Received Packet */
P_GAT_INT_FIFO_EMPTY = 1<<8, /* Internal FIFO Empty */
P_GAT_MAIN_PWR_N_AVAIL = 1<<7, /* Main Power Not Available */
P_GAT_CLKRUN_REQ_REL = 1<<6, /* CLKRUN Not Requested */
P_GAT_PCIE_RESET_ASS = 1<<5, /* PCIe Reset Asserted */
P_GAT_PME_DE_ASSERTED = 1<<4, /* PME De-Asserted */
P_GAT_PCIE_ENTER_L1_ST = 1<<3, /* PCIe Enter L1 State */
P_GAT_LOADER_FINISHED = 1<<2, /* EPROM Loader Finished */
P_GAT_PCIE_RX_EL_IDLE = 1<<1, /* PCIe Rx Electrical Idle State */
P_GAT_GPHY_LINK_DOWN = 1<<0, /* GPHY Link Down */
PCIE_OUR5_EVENT_CLK_D3_SET = P_REL_GPHY_REC_PACKET |
P_REL_INT_FIFO_N_EMPTY |
P_REL_PCIE_EXIT_L1_ST |
P_REL_PCIE_RX_EX_IDLE |
P_GAT_GPHY_N_REC_PACKET |
P_GAT_INT_FIFO_EMPTY |
P_GAT_PCIE_ENTER_L1_ST |
P_GAT_PCIE_RX_EL_IDLE,
};
#/* PCI_CFG_REG_1 32 bit Config Register 1 (Yukon-Ext only) */
enum pci_cfg_reg1 {
P_CF1_DIS_REL_EVT_RST = 1<<24, /* Dis. Rel. Event during PCIE reset */
/* Bit 23..21: Release Clock on Event */
P_CF1_REL_LDR_NOT_FIN = 1<<23, /* EEPROM Loader Not Finished */
P_CF1_REL_VMAIN_AVLBL = 1<<22, /* Vmain available */
P_CF1_REL_PCIE_RESET = 1<<21, /* PCI-E reset */
/* Bit 20..18: Gate Clock on Event */
P_CF1_GAT_LDR_NOT_FIN = 1<<20, /* EEPROM Loader Finished */
P_CF1_GAT_PCIE_RX_IDLE = 1<<19, /* PCI-E Rx Electrical idle */
P_CF1_GAT_PCIE_RESET = 1<<18, /* PCI-E Reset */
P_CF1_PRST_PHY_CLKREQ = 1<<17, /* Enable PCI-E rst & PM2PHY gen. CLKREQ */
P_CF1_PCIE_RST_CLKREQ = 1<<16, /* Enable PCI-E rst generate CLKREQ */
P_CF1_ENA_CFG_LDR_DONE = 1<<8, /* Enable core level Config loader done */
P_CF1_ENA_TXBMU_RD_IDLE = 1<<1, /* Enable TX BMU Read IDLE for ASPM */
P_CF1_ENA_TXBMU_WR_IDLE = 1<<0, /* Enable TX BMU Write IDLE for ASPM */
PCIE_CFG1_EVENT_CLK_D3_SET = P_CF1_DIS_REL_EVT_RST |
P_CF1_REL_LDR_NOT_FIN |
P_CF1_REL_VMAIN_AVLBL |
P_CF1_REL_PCIE_RESET |
P_CF1_GAT_LDR_NOT_FIN |
P_CF1_GAT_PCIE_RESET |
P_CF1_PRST_PHY_CLKREQ |
P_CF1_ENA_CFG_LDR_DONE |
P_CF1_ENA_TXBMU_RD_IDLE |
P_CF1_ENA_TXBMU_WR_IDLE,
};
#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
PCI_STATUS_SIG_SYSTEM_ERROR | \
@ -364,6 +441,20 @@ enum {
TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */
};
/* B2_GPIO */
enum {
GLB_GPIO_CLK_DEB_ENA = 1<<31, /* Clock Debug Enable */
GLB_GPIO_CLK_DBG_MSK = 0xf<<26, /* Clock Debug */
GLB_GPIO_INT_RST_D3_DIS = 1<<15, /* Disable Internal Reset After D3 to D0 */
GLB_GPIO_LED_PAD_SPEED_UP = 1<<14, /* LED PAD Speed Up */
GLB_GPIO_STAT_RACE_DIS = 1<<13, /* Status Race Disable */
GLB_GPIO_TEST_SEL_MSK = 3<<11, /* Testmode Select */
GLB_GPIO_TEST_SEL_BASE = 1<<11,
GLB_GPIO_RAND_ENA = 1<<10, /* Random Enable */
GLB_GPIO_RAND_BIT_1 = 1<<9, /* Random Bit 1 */
};
/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */
enum {
CFG_CHIP_R_MSK = 0xf<<4, /* Bit 7.. 4: Chip Revision */
@ -392,6 +483,11 @@ enum {
CHIP_REV_YU_FE_A2 = 2,
};
enum yukon_ex_rev {
CHIP_REV_YU_EX_A0 = 1,
CHIP_REV_YU_EX_B0 = 2,
};
/* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */
enum {
@ -515,23 +611,15 @@ enum {
enum {
B8_Q_REGS = 0x0400, /* base of Queue registers */
Q_D = 0x00, /* 8*32 bit Current Descriptor */
Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */
Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */
Q_VLAN = 0x20, /* 16 bit Current VLAN Tag */
Q_DONE = 0x24, /* 16 bit Done Index */
Q_AC_L = 0x28, /* 32 bit Current Address Counter Low dWord */
Q_AC_H = 0x2c, /* 32 bit Current Address Counter High dWord */
Q_BC = 0x30, /* 32 bit Current Byte Counter */
Q_CSR = 0x34, /* 32 bit BMU Control/Status Register */
Q_F = 0x38, /* 32 bit Flag Register */
Q_T1 = 0x3c, /* 32 bit Test Register 1 */
Q_T1_TR = 0x3c, /* 8 bit Test Register 1 Transfer SM */
Q_T1_WR = 0x3d, /* 8 bit Test Register 1 Write Descriptor SM */
Q_T1_RD = 0x3e, /* 8 bit Test Register 1 Read Descriptor SM */
Q_T1_SV = 0x3f, /* 8 bit Test Register 1 Supervisor SM */
Q_T2 = 0x40, /* 32 bit Test Register 2 */
Q_T3 = 0x44, /* 32 bit Test Register 3 */
Q_TEST = 0x38, /* 32 bit Test/Control Register */
/* Yukon-2 */
Q_DONE = 0x24, /* 16 bit Done Index (Yukon-2 only) */
Q_WM = 0x40, /* 16 bit FIFO Watermark */
Q_AL = 0x42, /* 8 bit FIFO Alignment */
Q_RSP = 0x44, /* 16 bit FIFO Read Shadow Pointer */
@ -545,15 +633,16 @@ enum {
};
#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
/* Q_F 32 bit Flag Register */
/* Q_TEST 32 bit Test Register */
enum {
F_ALM_FULL = 1<<27, /* Rx FIFO: almost full */
F_EMPTY = 1<<27, /* Tx FIFO: empty flag */
F_FIFO_EOF = 1<<26, /* Tag (EOF Flag) bit in FIFO */
F_WM_REACHED = 1<<25, /* Watermark reached */
/* Transmit */
F_TX_CHK_AUTO_OFF = 1<<31, /* Tx checksum auto calc off (Yukon EX) */
F_TX_CHK_AUTO_ON = 1<<30, /* Tx checksum auto calc off (Yukon EX) */
/* Receive */
F_M_RX_RAM_DIS = 1<<24, /* MAC Rx RAM Read Port disable */
F_FIFO_LEVEL = 0x1fL<<16, /* Bit 23..16: # of Qwords in FIFO */
F_WATER_MARK = 0x0007ffL, /* Bit 10.. 0: Watermark */
/* Hardware testbits not used */
};
/* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
@ -1608,6 +1697,16 @@ enum {
RX_VLAN_STRIP_ON = 1<<25, /* enable VLAN stripping */
RX_VLAN_STRIP_OFF = 1<<24, /* disable VLAN stripping */
RX_MACSEC_FLUSH_ON = 1<<23,
RX_MACSEC_FLUSH_OFF = 1<<22,
RX_MACSEC_ASF_FLUSH_ON = 1<<21,
RX_MACSEC_ASF_FLUSH_OFF = 1<<20,
GMF_RX_OVER_ON = 1<<19, /* enable flushing on receive overrun */
GMF_RX_OVER_OFF = 1<<18, /* disable flushing on receive overrun */
GMF_ASF_RX_OVER_ON = 1<<17, /* enable flushing of ASF when overrun */
GMF_ASF_RX_OVER_OFF = 1<<16, /* disable flushing of ASF when overrun */
GMF_WP_TST_ON = 1<<14, /* Write Pointer Test On */
GMF_WP_TST_OFF = 1<<13, /* Write Pointer Test Off */
GMF_WP_STEP = 1<<12, /* Write Pointer Step/Increment */
@ -1720,6 +1819,15 @@ enum {
/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */
enum {
GMC_SET_RST = 1<<15,/* MAC SEC RST */
GMC_SEC_RST_OFF = 1<<14,/* MAC SEC RSt OFF */
GMC_BYP_MACSECRX_ON = 1<<13,/* Bypass macsec RX */
GMC_BYP_MACSECRX_OFF= 1<<12,/* Bypass macsec RX off */
GMC_BYP_MACSECTX_ON = 1<<11,/* Bypass macsec TX */
GMC_BYP_MACSECTX_OFF= 1<<10,/* Bypass macsec TX off*/
GMC_BYP_RETR_ON = 1<<9, /* Bypass retransmit FIFO On */
GMC_BYP_RETR_OFF= 1<<8, /* Bypass retransmit FIFO Off */
GMC_H_BURST_ON = 1<<7, /* Half Duplex Burst Mode On */
GMC_H_BURST_OFF = 1<<6, /* Half Duplex Burst Mode Off */
GMC_F_LOOPB_ON = 1<<5, /* FIFO Loopback On */
@ -1805,9 +1913,13 @@ enum {
OP_ADDR64VLAN = OP_ADDR64 | OP_VLAN,
OP_LRGLEN = 0x24,
OP_LRGLENVLAN = OP_LRGLEN | OP_VLAN,
OP_MSS = 0x28,
OP_MSSVLAN = OP_MSS | OP_VLAN,
OP_BUFFER = 0x40,
OP_PACKET = 0x41,
OP_LARGESEND = 0x43,
OP_LSOV2 = 0x45,
/* YUKON-2 STATUS opcodes defines */
OP_RXSTAT = 0x60,
@ -1818,6 +1930,19 @@ enum {
OP_RXTIMEVLAN = OP_RXTIMESTAMP | OP_RXVLAN,
OP_RSS_HASH = 0x65,
OP_TXINDEXLE = 0x68,
OP_MACSEC = 0x6c,
OP_PUTIDX = 0x70,
};
enum status_css {
CSS_TCPUDPCSOK = 1<<7, /* TCP / UDP checksum is ok */
CSS_ISUDP = 1<<6, /* packet is a UDP packet */
CSS_ISTCP = 1<<5, /* packet is a TCP packet */
CSS_ISIPFRAG = 1<<4, /* packet is a TCP/UDP frag, CS calc not done */
CSS_ISIPV6 = 1<<3, /* packet is a IPv6 packet */
CSS_IPV4CSUMOK = 1<<2, /* IP v4: TCP header checksum is ok */
CSS_ISIPV4 = 1<<1, /* packet is a IPv4 packet */
CSS_LINK_BIT = 1<<0, /* port number (legacy) */
};
/* Yukon 2 hardware interface */
@ -1838,7 +1963,7 @@ struct sky2_rx_le {
struct sky2_status_le {
__le32 status; /* also checksum */
__le16 length; /* also vlan tag */
u8 link;
u8 css;
u8 opcode;
} __attribute((packed));

185
drivers/net/sni_82596.c Normal file
View file

@ -0,0 +1,185 @@
/*
* sni_82596.c -- driver for intel 82596 ethernet controller, as
* used in older SNI RM machines
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/irq.h>
#define SNI_82596_DRIVER_VERSION "SNI RM 82596 driver - Revision: 0.01"
static const char sni_82596_string[] = "snirm_82596";
#define DMA_ALLOC dma_alloc_coherent
#define DMA_FREE dma_free_coherent
#define DMA_WBACK(priv, addr, len) do { } while (0)
#define DMA_INV(priv, addr, len) do { } while (0)
#define DMA_WBACK_INV(priv, addr, len) do { } while (0)
#define SYSBUS 0x00004400
/* big endian CPU, 82596 little endian */
#define SWAP32(x) cpu_to_le32((u32)(x))
#define SWAP16(x) cpu_to_le16((u16)(x))
#define OPT_MPU_16BIT 0x01
#include "lib82596.c"
MODULE_AUTHOR("Thomas Bogendoerfer");
MODULE_DESCRIPTION("i82596 driver");
MODULE_LICENSE("GPL");
module_param(i596_debug, int, 0);
MODULE_PARM_DESC(i596_debug, "82596 debug mask");
static inline void ca(struct net_device *dev)
{
struct i596_private *lp = netdev_priv(dev);
writel(0, lp->ca);
}
static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
{
struct i596_private *lp = netdev_priv(dev);
u32 v = (u32) (c) | (u32) (x);
if (lp->options & OPT_MPU_16BIT) {
writew(v & 0xffff, lp->mpu_port);
wmb(); /* order writes to MPU port */
udelay(1);
writew(v >> 16, lp->mpu_port);
} else {
writel(v, lp->mpu_port);
wmb(); /* order writes to MPU port */
udelay(1);
writel(v, lp->mpu_port);
}
}
static int __devinit sni_82596_probe(struct platform_device *dev)
{
struct net_device *netdevice;
struct i596_private *lp;
struct resource *res, *ca, *idprom, *options;
int retval = -ENOMEM;
void __iomem *mpu_addr;
void __iomem *ca_addr;
u8 __iomem *eth_addr;
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
ca = platform_get_resource(dev, IORESOURCE_MEM, 1);
options = platform_get_resource(dev, 0, 0);
idprom = platform_get_resource(dev, IORESOURCE_MEM, 2);
if (!res || !ca || !options || !idprom)
return -ENODEV;
mpu_addr = ioremap_nocache(res->start, 4);
if (!mpu_addr)
return -ENOMEM;
ca_addr = ioremap_nocache(ca->start, 4);
if (!ca_addr)
goto probe_failed_free_mpu;
printk(KERN_INFO "Found i82596 at 0x%x\n", res->start);
netdevice = alloc_etherdev(sizeof(struct i596_private));
if (!netdevice)
goto probe_failed_free_ca;
SET_NETDEV_DEV(netdevice, &dev->dev);
platform_set_drvdata (dev, netdevice);
netdevice->base_addr = res->start;
netdevice->irq = platform_get_irq(dev, 0);
eth_addr = ioremap_nocache(idprom->start, 0x10);
if (!eth_addr)
goto probe_failed;
/* someone seems to like messed up stuff */
netdevice->dev_addr[0] = readb(eth_addr + 0x0b);
netdevice->dev_addr[1] = readb(eth_addr + 0x0a);
netdevice->dev_addr[2] = readb(eth_addr + 0x09);
netdevice->dev_addr[3] = readb(eth_addr + 0x08);
netdevice->dev_addr[4] = readb(eth_addr + 0x07);
netdevice->dev_addr[5] = readb(eth_addr + 0x06);
iounmap(eth_addr);
if (!netdevice->irq) {
printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
__FILE__, netdevice->base_addr);
goto probe_failed;
}
lp = netdev_priv(netdevice);
lp->options = options->flags & IORESOURCE_BITS;
lp->ca = ca_addr;
lp->mpu_port = mpu_addr;
retval = i82596_probe(netdevice);
if (retval == 0)
return 0;
probe_failed:
free_netdev(netdevice);
probe_failed_free_ca:
iounmap(ca_addr);
probe_failed_free_mpu:
iounmap(mpu_addr);
return retval;
}
static int __devexit sni_82596_driver_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct i596_private *lp = netdev_priv(dev);
unregister_netdev(dev);
DMA_FREE(dev->dev.parent, sizeof(struct i596_private),
lp->dma, lp->dma_addr);
iounmap(lp->ca);
iounmap(lp->mpu_port);
free_netdev (dev);
return 0;
}
static struct platform_driver sni_82596_driver = {
.probe = sni_82596_probe,
.remove = __devexit_p(sni_82596_driver_remove),
.driver = {
.name = sni_82596_string,
},
};
static int __devinit sni_82596_init(void)
{
printk(KERN_INFO SNI_82596_DRIVER_VERSION "\n");
return platform_driver_register(&sni_82596_driver);
}
static void __exit sni_82596_exit(void)
{
platform_driver_unregister(&sni_82596_driver);
}
module_init(sni_82596_init);
module_exit(sni_82596_exit);

View file

@ -434,7 +434,8 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
bufsize + SPIDER_NET_RXBUF_ALIGN - 1);
if (!descr->skb) {
if (netif_msg_rx_err(card) && net_ratelimit())
pr_err("Not enough memory to allocate rx buffer\n");
dev_err(&card->netdev->dev,
"Not enough memory to allocate rx buffer\n");
card->spider_stats.alloc_rx_skb_error++;
return -ENOMEM;
}
@ -455,7 +456,7 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
dev_kfree_skb_any(descr->skb);
descr->skb = NULL;
if (netif_msg_rx_err(card) && net_ratelimit())
pr_err("Could not iommu-map rx buffer\n");
dev_err(&card->netdev->dev, "Could not iommu-map rx buffer\n");
card->spider_stats.rx_iommu_map_error++;
hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
} else {
@ -499,6 +500,20 @@ spider_net_enable_rxdmac(struct spider_net_card *card)
SPIDER_NET_DMA_RX_VALUE);
}
/**
* spider_net_disable_rxdmac - disables the receive DMA controller
* @card: card structure
*
* spider_net_disable_rxdmac terminates processing on the DMA controller
* by turing off the DMA controller, with the force-end flag set.
*/
static inline void
spider_net_disable_rxdmac(struct spider_net_card *card)
{
spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
SPIDER_NET_DMA_RX_FEND_VALUE);
}
/**
* spider_net_refill_rx_chain - refills descriptors/skbs in the rx chains
* @card: card structure
@ -654,20 +669,6 @@ write_hash:
}
}
/**
* spider_net_disable_rxdmac - disables the receive DMA controller
* @card: card structure
*
* spider_net_disable_rxdmac terminates processing on the DMA controller by
* turing off DMA and issueing a force end
*/
static void
spider_net_disable_rxdmac(struct spider_net_card *card)
{
spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
SPIDER_NET_DMA_RX_FEND_VALUE);
}
/**
* spider_net_prepare_tx_descr - fill tx descriptor with skb data
* @card: card structure
@ -692,7 +693,7 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(buf)) {
if (netif_msg_tx_err(card) && net_ratelimit())
pr_err("could not iommu-map packet (%p, %i). "
dev_err(&card->netdev->dev, "could not iommu-map packet (%p, %i). "
"Dropping packet\n", skb->data, skb->len);
card->spider_stats.tx_iommu_map_error++;
return -ENOMEM;
@ -715,7 +716,7 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
hwdescr->data_status = 0;
hwdescr->dmac_cmd_status =
SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_TXFRMTL;
spin_unlock_irqrestore(&chain->lock, flags);
if (skb->ip_summed == CHECKSUM_PARTIAL)
@ -832,9 +833,8 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
case SPIDER_NET_DESCR_PROTECTION_ERROR:
case SPIDER_NET_DESCR_FORCE_END:
if (netif_msg_tx_err(card))
pr_err("%s: forcing end of tx descriptor "
"with status x%02x\n",
card->netdev->name, status);
dev_err(&card->netdev->dev, "forcing end of tx descriptor "
"with status x%02x\n", status);
card->netdev_stats.tx_errors++;
break;
@ -1022,34 +1022,94 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
netif_receive_skb(skb);
}
#ifdef DEBUG
static void show_rx_chain(struct spider_net_card *card)
{
struct spider_net_descr_chain *chain = &card->rx_chain;
struct spider_net_descr *start= chain->tail;
struct spider_net_descr *descr= start;
struct spider_net_hw_descr *hwd = start->hwdescr;
struct device *dev = &card->netdev->dev;
u32 curr_desc, next_desc;
int status;
int tot = 0;
int cnt = 0;
int cstat = spider_net_get_descr_status(descr);
printk(KERN_INFO "RX chain tail at descr=%ld\n",
(start - card->descr) - card->tx_chain.num_desc);
int off = start - chain->ring;
int cstat = hwd->dmac_cmd_status;
dev_info(dev, "Total number of descrs=%d\n",
chain->num_desc);
dev_info(dev, "Chain tail located at descr=%d, status=0x%x\n",
off, cstat);
curr_desc = spider_net_read_reg(card, SPIDER_NET_GDACTDPA);
next_desc = spider_net_read_reg(card, SPIDER_NET_GDACNEXTDA);
status = cstat;
do
{
status = spider_net_get_descr_status(descr);
hwd = descr->hwdescr;
off = descr - chain->ring;
status = hwd->dmac_cmd_status;
if (descr == chain->head)
dev_info(dev, "Chain head is at %d, head status=0x%x\n",
off, status);
if (curr_desc == descr->bus_addr)
dev_info(dev, "HW curr desc (GDACTDPA) is at %d, status=0x%x\n",
off, status);
if (next_desc == descr->bus_addr)
dev_info(dev, "HW next desc (GDACNEXTDA) is at %d, status=0x%x\n",
off, status);
if (hwd->next_descr_addr == 0)
dev_info(dev, "chain is cut at %d\n", off);
if (cstat != status) {
printk(KERN_INFO "Have %d descrs with stat=x%08x\n", cnt, cstat);
int from = (chain->num_desc + off - cnt) % chain->num_desc;
int to = (chain->num_desc + off - 1) % chain->num_desc;
dev_info(dev, "Have %d (from %d to %d) descrs "
"with stat=0x%08x\n", cnt, from, to, cstat);
cstat = status;
cnt = 0;
}
cnt ++;
tot ++;
descr = descr->next;
} while (descr != start);
dev_info(dev, "Last %d descrs with stat=0x%08x "
"for a total of %d descrs\n", cnt, cstat, tot);
#ifdef DEBUG
/* Now dump the whole ring */
descr = start;
do
{
struct spider_net_hw_descr *hwd = descr->hwdescr;
status = spider_net_get_descr_status(hwd);
cnt = descr - chain->ring;
dev_info(dev, "Descr %d stat=0x%08x skb=%p\n",
cnt, status, descr->skb);
dev_info(dev, "bus addr=%08x buf addr=%08x sz=%d\n",
descr->bus_addr, hwd->buf_addr, hwd->buf_size);
dev_info(dev, "next=%08x result sz=%d valid sz=%d\n",
hwd->next_descr_addr, hwd->result_size,
hwd->valid_size);
dev_info(dev, "dmac=%08x data stat=%08x data err=%08x\n",
hwd->dmac_cmd_status, hwd->data_status,
hwd->data_error);
dev_info(dev, "\n");
descr = descr->next;
} while (descr != start);
printk(KERN_INFO "Last %d descrs with stat=x%08x\n", cnt, cstat);
}
#endif
}
/**
* spider_net_resync_head_ptr - Advance head ptr past empty descrs
*
@ -1127,6 +1187,7 @@ spider_net_decode_one_descr(struct spider_net_card *card)
struct spider_net_descr_chain *chain = &card->rx_chain;
struct spider_net_descr *descr = chain->tail;
struct spider_net_hw_descr *hwdescr = descr->hwdescr;
u32 hw_buf_addr;
int status;
status = spider_net_get_descr_status(hwdescr);
@ -1140,15 +1201,17 @@ spider_net_decode_one_descr(struct spider_net_card *card)
chain->tail = descr->next;
/* unmap descriptor */
pci_unmap_single(card->pdev, hwdescr->buf_addr,
hw_buf_addr = hwdescr->buf_addr;
hwdescr->buf_addr = 0xffffffff;
pci_unmap_single(card->pdev, hw_buf_addr,
SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
if ( (status == SPIDER_NET_DESCR_RESPONSE_ERROR) ||
(status == SPIDER_NET_DESCR_PROTECTION_ERROR) ||
(status == SPIDER_NET_DESCR_FORCE_END) ) {
if (netif_msg_rx_err(card))
pr_err("%s: dropping RX descriptor with state %d\n",
card->netdev->name, status);
dev_err(&card->netdev->dev,
"dropping RX descriptor with state %d\n", status);
card->netdev_stats.rx_dropped++;
goto bad_desc;
}
@ -1156,8 +1219,8 @@ spider_net_decode_one_descr(struct spider_net_card *card)
if ( (status != SPIDER_NET_DESCR_COMPLETE) &&
(status != SPIDER_NET_DESCR_FRAME_END) ) {
if (netif_msg_rx_err(card))
pr_err("%s: RX descriptor with unknown state %d\n",
card->netdev->name, status);
dev_err(&card->netdev->dev,
"RX descriptor with unknown state %d\n", status);
card->spider_stats.rx_desc_unk_state++;
goto bad_desc;
}
@ -1165,18 +1228,17 @@ spider_net_decode_one_descr(struct spider_net_card *card)
/* The cases we'll throw away the packet immediately */
if (hwdescr->data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
if (netif_msg_rx_err(card))
pr_err("%s: error in received descriptor found, "
dev_err(&card->netdev->dev,
"error in received descriptor found, "
"data_status=x%08x, data_error=x%08x\n",
card->netdev->name,
hwdescr->data_status, hwdescr->data_error);
goto bad_desc;
}
if (hwdescr->dmac_cmd_status & 0xfcf4) {
pr_err("%s: bad status, cmd_status=x%08x\n",
card->netdev->name,
if (hwdescr->dmac_cmd_status & SPIDER_NET_DESCR_BAD_STATUS) {
dev_err(&card->netdev->dev, "bad status, cmd_status=x%08x\n",
hwdescr->dmac_cmd_status);
pr_err("buf_addr=x%08x\n", hwdescr->buf_addr);
pr_err("buf_addr=x%08x\n", hw_buf_addr);
pr_err("buf_size=x%08x\n", hwdescr->buf_size);
pr_err("next_descr_addr=x%08x\n", hwdescr->next_descr_addr);
pr_err("result_size=x%08x\n", hwdescr->result_size);
@ -1196,6 +1258,8 @@ spider_net_decode_one_descr(struct spider_net_card *card)
return 1;
bad_desc:
if (netif_msg_rx_err(card))
show_rx_chain(card);
dev_kfree_skb_irq(descr->skb);
descr->skb = NULL;
hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
@ -1221,7 +1285,6 @@ spider_net_poll(struct net_device *netdev, int *budget)
int packets_to_do, packets_done = 0;
int no_more_packets = 0;
spider_net_cleanup_tx_ring(card);
packets_to_do = min(*budget, netdev->quota);
while (packets_to_do) {
@ -1246,6 +1309,8 @@ spider_net_poll(struct net_device *netdev, int *budget)
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
spider_net_cleanup_tx_ring(card);
/* if all packets are in the stack, enable interrupts and return 0 */
/* if not, return 1 */
if (no_more_packets) {
@ -1415,7 +1480,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
case SPIDER_NET_GPWFFINT:
/* PHY command queue full */
if (netif_msg_intr(card))
pr_err("PHY write queue full\n");
dev_err(&card->netdev->dev, "PHY write queue full\n");
show_error = 0;
break;
@ -1582,9 +1647,8 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
}
if ((show_error) && (netif_msg_intr(card)) && net_ratelimit())
pr_err("Got error interrupt on %s, GHIINT0STS = 0x%08x, "
dev_err(&card->netdev->dev, "Error interrupt, GHIINT0STS = 0x%08x, "
"GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n",
card->netdev->name,
status_reg, error_reg1, error_reg2);
/* clear interrupt sources */
@ -1849,7 +1913,8 @@ spider_net_init_firmware(struct spider_net_card *card)
SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) {
if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) &&
netif_msg_probe(card) ) {
pr_err("Incorrect size of spidernet firmware in " \
dev_err(&card->netdev->dev,
"Incorrect size of spidernet firmware in " \
"filesystem. Looking in host firmware...\n");
goto try_host_fw;
}
@ -1873,8 +1938,8 @@ try_host_fw:
if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) &&
netif_msg_probe(card) ) {
pr_err("Incorrect size of spidernet firmware in " \
"host firmware\n");
dev_err(&card->netdev->dev,
"Incorrect size of spidernet firmware in host firmware\n");
goto done;
}
@ -1884,7 +1949,8 @@ done:
return err;
out_err:
if (netif_msg_probe(card))
pr_err("Couldn't find spidernet firmware in filesystem " \
dev_err(&card->netdev->dev,
"Couldn't find spidernet firmware in filesystem " \
"or host firmware\n");
return err;
}
@ -2279,13 +2345,14 @@ spider_net_setup_netdev(struct spider_net_card *card)
result = spider_net_set_mac(netdev, &addr);
if ((result) && (netif_msg_probe(card)))
pr_err("Failed to set MAC address: %i\n", result);
dev_err(&card->netdev->dev,
"Failed to set MAC address: %i\n", result);
result = register_netdev(netdev);
if (result) {
if (netif_msg_probe(card))
pr_err("Couldn't register net_device: %i\n",
result);
dev_err(&card->netdev->dev,
"Couldn't register net_device: %i\n", result);
return result;
}
@ -2363,17 +2430,19 @@ spider_net_setup_pci_dev(struct pci_dev *pdev)
unsigned long mmio_start, mmio_len;
if (pci_enable_device(pdev)) {
pr_err("Couldn't enable PCI device\n");
dev_err(&pdev->dev, "Couldn't enable PCI device\n");
return NULL;
}
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
pr_err("Couldn't find proper PCI device base address.\n");
dev_err(&pdev->dev,
"Couldn't find proper PCI device base address.\n");
goto out_disable_dev;
}
if (pci_request_regions(pdev, spider_net_driver_name)) {
pr_err("Couldn't obtain PCI resources, aborting.\n");
dev_err(&pdev->dev,
"Couldn't obtain PCI resources, aborting.\n");
goto out_disable_dev;
}
@ -2381,8 +2450,8 @@ spider_net_setup_pci_dev(struct pci_dev *pdev)
card = spider_net_alloc_card();
if (!card) {
pr_err("Couldn't allocate net_device structure, "
"aborting.\n");
dev_err(&pdev->dev,
"Couldn't allocate net_device structure, aborting.\n");
goto out_release_regions;
}
card->pdev = pdev;
@ -2396,7 +2465,8 @@ spider_net_setup_pci_dev(struct pci_dev *pdev)
card->regs = ioremap(mmio_start, mmio_len);
if (!card->regs) {
pr_err("Couldn't obtain PCI resources, aborting.\n");
dev_err(&pdev->dev,
"Couldn't obtain PCI resources, aborting.\n");
goto out_release_regions;
}

View file

@ -349,11 +349,23 @@ enum spider_net_int2_status {
#define SPIDER_NET_GPRDAT_MASK 0x0000ffff
#define SPIDER_NET_DMAC_NOINTR_COMPLETE 0x00800000
#define SPIDER_NET_DMAC_NOCS 0x00040000
#define SPIDER_NET_DMAC_TXFRMTL 0x00040000
#define SPIDER_NET_DMAC_TCP 0x00020000
#define SPIDER_NET_DMAC_UDP 0x00030000
#define SPIDER_NET_TXDCEST 0x08000000
#define SPIDER_NET_DESCR_RXFDIS 0x00000001
#define SPIDER_NET_DESCR_RXDCEIS 0x00000002
#define SPIDER_NET_DESCR_RXDEN0IS 0x00000004
#define SPIDER_NET_DESCR_RXINVDIS 0x00000008
#define SPIDER_NET_DESCR_RXRERRIS 0x00000010
#define SPIDER_NET_DESCR_RXFDCIMS 0x00000100
#define SPIDER_NET_DESCR_RXDCEIMS 0x00000200
#define SPIDER_NET_DESCR_RXDEN0IMS 0x00000400
#define SPIDER_NET_DESCR_RXINVDIMS 0x00000800
#define SPIDER_NET_DESCR_RXRERRMIS 0x00001000
#define SPIDER_NET_DESCR_UNUSED 0x077fe0e0
#define SPIDER_NET_DESCR_IND_PROC_MASK 0xF0000000
#define SPIDER_NET_DESCR_COMPLETE 0x00000000 /* used in rx and tx */
#define SPIDER_NET_DESCR_RESPONSE_ERROR 0x10000000 /* used in rx and tx */
@ -364,6 +376,13 @@ enum spider_net_int2_status {
#define SPIDER_NET_DESCR_NOT_IN_USE 0xF0000000
#define SPIDER_NET_DESCR_TXDESFLG 0x00800000
#define SPIDER_NET_DESCR_BAD_STATUS (SPIDER_NET_DESCR_RXDEN0IS | \
SPIDER_NET_DESCR_RXRERRIS | \
SPIDER_NET_DESCR_RXDEN0IMS | \
SPIDER_NET_DESCR_RXINVDIMS | \
SPIDER_NET_DESCR_RXRERRMIS | \
SPIDER_NET_DESCR_UNUSED)
/* Descriptor, as defined by the hardware */
struct spider_net_hw_descr {
u32 buf_addr;

View file

@ -2,17 +2,17 @@
# Tulip family network device configuration
#
menu "Tulip family network device support"
depends on NET_ETHERNET && (PCI || EISA || CARDBUS)
config NET_TULIP
menuconfig NET_TULIP
bool "\"Tulip\" family network device support"
depends on PCI || EISA || CARDBUS
help
This selects the "Tulip" family of EISA/PCI network cards.
if NET_TULIP
config DE2104X
tristate "Early DECchip Tulip (dc2104x) PCI support (EXPERIMENTAL)"
depends on NET_TULIP && PCI && EXPERIMENTAL
depends on PCI && EXPERIMENTAL
select CRC32
---help---
This driver is developed for the SMC EtherPower series Ethernet
@ -30,7 +30,7 @@ config DE2104X
config TULIP
tristate "DECchip Tulip (dc2114x) PCI support"
depends on NET_TULIP && PCI
depends on PCI
select CRC32
---help---
This driver is developed for the SMC EtherPower series Ethernet
@ -95,7 +95,7 @@ config TULIP_NAPI_HW_MITIGATION
config DE4X5
tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA"
depends on NET_TULIP && (PCI || EISA)
depends on PCI || EISA
select CRC32
---help---
This is support for the DIGITAL series of PCI/EISA Ethernet cards.
@ -112,7 +112,7 @@ config DE4X5
config WINBOND_840
tristate "Winbond W89c840 Ethernet support"
depends on NET_TULIP && PCI
depends on PCI
select CRC32
select MII
help
@ -123,7 +123,7 @@ config WINBOND_840
config DM9102
tristate "Davicom DM910x/DM980x support"
depends on NET_TULIP && PCI
depends on PCI
select CRC32
---help---
This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from
@ -137,7 +137,7 @@ config DM9102
config ULI526X
tristate "ULi M526x controller support"
depends on NET_TULIP && PCI
depends on PCI
select CRC32
---help---
This driver is for ULi M5261/M5263 10/100M Ethernet Controller
@ -149,7 +149,7 @@ config ULI526X
config PCMCIA_XIRCOM
tristate "Xircom CardBus support (new driver)"
depends on NET_TULIP && CARDBUS
depends on CARDBUS
---help---
This driver is for the Digital "Tulip" Ethernet CardBus adapters.
It should work with most DEC 21*4*-based chips/ethercards, as well
@ -162,7 +162,7 @@ config PCMCIA_XIRCOM
config PCMCIA_XIRTULIP
tristate "Xircom Tulip-like CardBus support (old driver)"
depends on NET_TULIP && CARDBUS && BROKEN_ON_SMP
depends on CARDBUS && BROKEN_ON_SMP
select CRC32
---help---
This driver is for the Digital "Tulip" Ethernet CardBus adapters.
@ -174,5 +174,4 @@ config PCMCIA_XIRTULIP
<file:Documentation/networking/net-modules.txt>. The module will
be called xircom_tulip_cb. If unsure, say N.
endmenu
endif # NET_TULIP

View file

@ -785,7 +785,6 @@ static void __de_set_rx_mode (struct net_device *dev)
de->tx_head = NEXT_TX(entry);
BUG_ON(TX_BUFFS_AVAIL(de) < 0);
if (TX_BUFFS_AVAIL(de) == 0)
netif_stop_queue(dev);

View file

@ -597,7 +597,7 @@ static char *args;
#endif
struct parameters {
int fdx;
bool fdx;
int autosense;
};
@ -809,10 +809,10 @@ struct de4x5_private {
s32 irq_en; /* Summary interrupt bits */
int media; /* Media (eg TP), mode (eg 100B)*/
int c_media; /* Remember the last media conn */
int fdx; /* media full duplex flag */
bool fdx; /* media full duplex flag */
int linkOK; /* Link is OK */
int autosense; /* Allow/disallow autosensing */
int tx_enable; /* Enable descriptor polling */
bool tx_enable; /* Enable descriptor polling */
int setup_f; /* Setup frame filtering type */
int local_state; /* State within a 'media' state */
struct mii_phy phy[DE4X5_MAX_PHY]; /* List of attached PHY devices */
@ -838,8 +838,8 @@ struct de4x5_private {
struct de4x5_srom srom; /* A copy of the SROM */
int cfrv; /* Card CFRV copy */
int rx_ovf; /* Check for 'RX overflow' tag */
int useSROM; /* For non-DEC card use SROM */
int useMII; /* Infoblock using the MII */
bool useSROM; /* For non-DEC card use SROM */
bool useMII; /* Infoblock using the MII */
int asBitValid; /* Autosense bits in GEP? */
int asPolarity; /* 0 => asserted high */
int asBit; /* Autosense bit number in GEP */
@ -928,7 +928,7 @@ static int dc21040_state(struct net_device *dev, int csr13, int csr14, int c
static int test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec);
static int test_for_100Mb(struct net_device *dev, int msec);
static int wait_for_link(struct net_device *dev);
static int test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec);
static int test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec);
static int is_spd_100(struct net_device *dev);
static int is_100_up(struct net_device *dev);
static int is_10_up(struct net_device *dev);
@ -1109,7 +1109,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
/*
** Now find out what kind of DC21040/DC21041/DC21140 board we have.
*/
lp->useSROM = FALSE;
lp->useSROM = false;
if (lp->bus == PCI) {
PCI_signature(name, lp);
} else {
@ -1137,7 +1137,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
lp->cache.gepc = GEP_INIT;
lp->asBit = GEP_SLNK;
lp->asPolarity = GEP_SLNK;
lp->asBitValid = TRUE;
lp->asBitValid = ~0;
lp->timeout = -1;
lp->gendev = gendev;
spin_lock_init(&lp->lock);
@ -1463,7 +1463,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev)
u_long flags = 0;
netif_stop_queue(dev);
if (lp->tx_enable == NO) { /* Cannot send for now */
if (!lp->tx_enable) { /* Cannot send for now */
return -1;
}
@ -2424,7 +2424,7 @@ dc21040_autoconf(struct net_device *dev)
switch (lp->media) {
case INIT:
DISABLE_IRQs;
lp->tx_enable = NO;
lp->tx_enable = false;
lp->timeout = -1;
de4x5_save_skbs(dev);
if ((lp->autosense == AUTO) || (lp->autosense == TP)) {
@ -2477,7 +2477,7 @@ dc21040_autoconf(struct net_device *dev)
lp->c_media = lp->media;
}
lp->media = INIT;
lp->tx_enable = NO;
lp->tx_enable = false;
break;
}
@ -2578,7 +2578,7 @@ dc21041_autoconf(struct net_device *dev)
switch (lp->media) {
case INIT:
DISABLE_IRQs;
lp->tx_enable = NO;
lp->tx_enable = false;
lp->timeout = -1;
de4x5_save_skbs(dev); /* Save non transmitted skb's */
if ((lp->autosense == AUTO) || (lp->autosense == TP_NW)) {
@ -2757,7 +2757,7 @@ dc21041_autoconf(struct net_device *dev)
lp->c_media = lp->media;
}
lp->media = INIT;
lp->tx_enable = NO;
lp->tx_enable = false;
break;
}
@ -2781,7 +2781,7 @@ dc21140m_autoconf(struct net_device *dev)
case INIT:
if (lp->timeout < 0) {
DISABLE_IRQs;
lp->tx_enable = FALSE;
lp->tx_enable = false;
lp->linkOK = 0;
de4x5_save_skbs(dev); /* Save non transmitted skb's */
}
@ -2830,7 +2830,7 @@ dc21140m_autoconf(struct net_device *dev)
if (lp->timeout < 0) {
mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
}
cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500);
cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500);
if (cr < 0) {
next_tick = cr & ~TIMER_CB;
} else {
@ -2845,7 +2845,7 @@ dc21140m_autoconf(struct net_device *dev)
break;
case 1:
if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000)) < 0) {
next_tick = sr & ~TIMER_CB;
} else {
lp->media = SPD_DET;
@ -2857,10 +2857,10 @@ dc21140m_autoconf(struct net_device *dev)
if (!(anlpa & MII_ANLPA_RF) &&
(cap = anlpa & MII_ANLPA_TAF & ana)) {
if (cap & MII_ANA_100M) {
lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0;
lp->media = _100Mb;
} else if (cap & MII_ANA_10M) {
lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE);
lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0;
lp->media = _10Mb;
}
@ -2932,7 +2932,7 @@ dc21140m_autoconf(struct net_device *dev)
lp->c_media = lp->media;
}
lp->media = INIT;
lp->tx_enable = FALSE;
lp->tx_enable = false;
break;
}
@ -2965,7 +2965,7 @@ dc2114x_autoconf(struct net_device *dev)
case INIT:
if (lp->timeout < 0) {
DISABLE_IRQs;
lp->tx_enable = FALSE;
lp->tx_enable = false;
lp->linkOK = 0;
lp->timeout = -1;
de4x5_save_skbs(dev); /* Save non transmitted skb's */
@ -3013,7 +3013,7 @@ dc2114x_autoconf(struct net_device *dev)
if (lp->timeout < 0) {
mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
}
cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500);
cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500);
if (cr < 0) {
next_tick = cr & ~TIMER_CB;
} else {
@ -3028,7 +3028,8 @@ dc2114x_autoconf(struct net_device *dev)
break;
case 1:
if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
sr = test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000);
if (sr < 0) {
next_tick = sr & ~TIMER_CB;
} else {
lp->media = SPD_DET;
@ -3040,10 +3041,10 @@ dc2114x_autoconf(struct net_device *dev)
if (!(anlpa & MII_ANLPA_RF) &&
(cap = anlpa & MII_ANLPA_TAF & ana)) {
if (cap & MII_ANA_100M) {
lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0;
lp->media = _100Mb;
} else if (cap & MII_ANA_10M) {
lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE);
lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0;
lp->media = _10Mb;
}
}
@ -3222,14 +3223,14 @@ srom_map_media(struct net_device *dev)
{
struct de4x5_private *lp = netdev_priv(dev);
lp->fdx = 0;
lp->fdx = false;
if (lp->infoblock_media == lp->media)
return 0;
switch(lp->infoblock_media) {
case SROM_10BASETF:
if (!lp->params.fdx) return -1;
lp->fdx = TRUE;
lp->fdx = true;
case SROM_10BASET:
if (lp->params.fdx && !lp->fdx) return -1;
if ((lp->chipset == DC21140) || ((lp->chipset & ~0x00ff) == DC2114x)) {
@ -3249,7 +3250,7 @@ srom_map_media(struct net_device *dev)
case SROM_100BASETF:
if (!lp->params.fdx) return -1;
lp->fdx = TRUE;
lp->fdx = true;
case SROM_100BASET:
if (lp->params.fdx && !lp->fdx) return -1;
lp->media = _100Mb;
@ -3261,7 +3262,7 @@ srom_map_media(struct net_device *dev)
case SROM_100BASEFF:
if (!lp->params.fdx) return -1;
lp->fdx = TRUE;
lp->fdx = true;
case SROM_100BASEF:
if (lp->params.fdx && !lp->fdx) return -1;
lp->media = _100Mb;
@ -3297,7 +3298,7 @@ de4x5_init_connection(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
de4x5_rst_desc_ring(dev);
de4x5_setup_intr(dev);
lp->tx_enable = YES;
lp->tx_enable = true;
spin_unlock_irqrestore(&lp->lock, flags);
outl(POLL_DEMAND, DE4X5_TPD);
@ -3336,7 +3337,7 @@ de4x5_reset_phy(struct net_device *dev)
}
}
if (lp->useMII) {
next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, FALSE, 500);
next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, false, 500);
}
} else if (lp->chipset == DC21140) {
PHY_HARD_RESET;
@ -3466,7 +3467,7 @@ wait_for_link(struct net_device *dev)
**
*/
static int
test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec)
test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec)
{
struct de4x5_private *lp = netdev_priv(dev);
int test;
@ -3476,9 +3477,8 @@ test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec)
lp->timeout = msec/100;
}
if (pol) pol = ~0;
reg = mii_rd((u_char)reg, lp->phy[lp->active].addr, DE4X5_MII) & mask;
test = (reg ^ pol) & mask;
test = (reg ^ (pol ? ~0 : 0)) & mask;
if (test && --lp->timeout) {
reg = 100 | TIMER_CB;
@ -3992,10 +3992,10 @@ PCI_signature(char *name, struct de4x5_private *lp)
)))))));
}
if (lp->chipset != DC21041) {
lp->useSROM = TRUE; /* card is not recognisably DEC */
lp->useSROM = true; /* card is not recognisably DEC */
}
} else if ((lp->chipset & ~0x00ff) == DC2114x) {
lp->useSROM = TRUE;
lp->useSROM = true;
}
return status;
@ -4216,7 +4216,7 @@ srom_repair(struct net_device *dev, int card)
memset((char *)&lp->srom, 0, sizeof(struct de4x5_srom));
memcpy(lp->srom.ieee_addr, (char *)dev->dev_addr, ETH_ALEN);
memcpy(lp->srom.info, (char *)&srom_repair_info[SMC-1], 100);
lp->useSROM = TRUE;
lp->useSROM = true;
break;
}
@ -4392,7 +4392,7 @@ srom_infoleaf_info(struct net_device *dev)
if (lp->chipset == infoleaf_array[i].chipset) break;
}
if (i == INFOLEAF_SIZE) {
lp->useSROM = FALSE;
lp->useSROM = false;
printk("%s: Cannot find correct chipset for SROM decoding!\n",
dev->name);
return -ENXIO;
@ -4409,7 +4409,7 @@ srom_infoleaf_info(struct net_device *dev)
if (lp->device == *p) break;
}
if (i == 0) {
lp->useSROM = FALSE;
lp->useSROM = false;
printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n",
dev->name, lp->device);
return -ENXIO;
@ -4542,7 +4542,7 @@ dc21140_infoleaf(struct net_device *dev)
}
lp->media = INIT;
lp->tcount = 0;
lp->tx_enable = FALSE;
lp->tx_enable = false;
}
return next_tick & ~TIMER_CB;
@ -4577,7 +4577,7 @@ dc21142_infoleaf(struct net_device *dev)
}
lp->media = INIT;
lp->tcount = 0;
lp->tx_enable = FALSE;
lp->tx_enable = false;
}
return next_tick & ~TIMER_CB;
@ -4611,7 +4611,7 @@ dc21143_infoleaf(struct net_device *dev)
}
lp->media = INIT;
lp->tcount = 0;
lp->tx_enable = FALSE;
lp->tx_enable = false;
}
return next_tick & ~TIMER_CB;
@ -4650,7 +4650,7 @@ compact_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->asBit = 1 << ((csr6 >> 1) & 0x07);
lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
lp->useMII = FALSE;
lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@ -4691,7 +4691,7 @@ type0_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->asBit = 1 << ((csr6 >> 1) & 0x07);
lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
lp->useMII = FALSE;
lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@ -4731,7 +4731,7 @@ type1_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->ibn = 1;
lp->active = *p;
lp->infoblock_csr6 = OMR_MII_100;
lp->useMII = TRUE;
lp->useMII = true;
lp->infoblock_media = ANS;
de4x5_switch_mac_port(dev);
@ -4773,7 +4773,7 @@ type2_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->cache.gepc = ((s32)(TWIDDLE(p)) << 16); p += 2;
lp->cache.gep = ((s32)(TWIDDLE(p)) << 16);
lp->infoblock_csr6 = OMR_SIA;
lp->useMII = FALSE;
lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@ -4814,7 +4814,7 @@ type3_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->active = *p;
if (MOTO_SROM_BUG) lp->active = 0;
lp->infoblock_csr6 = OMR_MII_100;
lp->useMII = TRUE;
lp->useMII = true;
lp->infoblock_media = ANS;
de4x5_switch_mac_port(dev);
@ -4856,7 +4856,7 @@ type4_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->asBit = 1 << ((csr6 >> 1) & 0x07);
lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
lp->useMII = FALSE;
lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@ -5077,7 +5077,7 @@ mii_get_phy(struct net_device *dev)
int id;
lp->active = 0;
lp->useMII = TRUE;
lp->useMII = true;
/* Search the MII address space for possible PHY devices */
for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(i+1)%DE4X5_MAX_MII) {
@ -5127,7 +5127,7 @@ mii_get_phy(struct net_device *dev)
de4x5_dbg_mii(dev, k);
}
}
if (!lp->mii_cnt) lp->useMII = FALSE;
if (!lp->mii_cnt) lp->useMII = false;
return lp->mii_cnt;
}

View file

@ -892,15 +892,6 @@
#define ALL 0 /* Clear out all the setup frame */
#define PHYS_ADDR_ONLY 1 /* Update the physical address only */
/*
** Booleans
*/
#define NO 0
#define FALSE 0
#define YES ~0
#define TRUE ~0
/*
** Adapter state
*/

View file

@ -192,7 +192,7 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
usb_pipeendpoint(pipe), maxp, period);
}
}
return 0;
return 0;
}
/* Passes this packet up the stack, updating its accounting.
@ -326,7 +326,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
if (netif_running (dev->net)
&& netif_device_present (dev->net)
&& !test_bit (EVENT_RX_HALT, &dev->flags)) {
switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){
switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) {
case -EPIPE:
usbnet_defer_kevent (dev, EVENT_RX_HALT);
break;
@ -393,8 +393,8 @@ static void rx_complete (struct urb *urb)
entry->urb = NULL;
switch (urb_status) {
// success
case 0:
/* success */
case 0:
if (skb->len < dev->net->hard_header_len) {
entry->state = rx_cleanup;
dev->stats.rx_errors++;
@ -404,28 +404,30 @@ static void rx_complete (struct urb *urb)
}
break;
// stalls need manual reset. this is rare ... except that
// when going through USB 2.0 TTs, unplug appears this way.
// we avoid the highspeed version of the ETIMEOUT/EILSEQ
// storm, recovering as needed.
case -EPIPE:
/* stalls need manual reset. this is rare ... except that
* when going through USB 2.0 TTs, unplug appears this way.
* we avoid the highspeed version of the ETIMEOUT/EILSEQ
* storm, recovering as needed.
*/
case -EPIPE:
dev->stats.rx_errors++;
usbnet_defer_kevent (dev, EVENT_RX_HALT);
// FALLTHROUGH
// software-driven interface shutdown
case -ECONNRESET: // async unlink
case -ESHUTDOWN: // hardware gone
/* software-driven interface shutdown */
case -ECONNRESET: /* async unlink */
case -ESHUTDOWN: /* hardware gone */
if (netif_msg_ifdown (dev))
devdbg (dev, "rx shutdown, code %d", urb_status);
goto block;
// we get controller i/o faults during khubd disconnect() delays.
// throttle down resubmits, to avoid log floods; just temporarily,
// so we still recover when the fault isn't a khubd delay.
case -EPROTO:
case -ETIME:
case -EILSEQ:
/* we get controller i/o faults during khubd disconnect() delays.
* throttle down resubmits, to avoid log floods; just temporarily,
* so we still recover when the fault isn't a khubd delay.
*/
case -EPROTO:
case -ETIME:
case -EILSEQ:
dev->stats.rx_errors++;
if (!timer_pending (&dev->delay)) {
mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
@ -438,12 +440,12 @@ block:
urb = NULL;
break;
// data overrun ... flush fifo?
case -EOVERFLOW:
/* data overrun ... flush fifo? */
case -EOVERFLOW:
dev->stats.rx_over_errors++;
// FALLTHROUGH
default:
default:
entry->state = rx_cleanup;
dev->stats.rx_errors++;
if (netif_msg_rx_err (dev))
@ -471,22 +473,22 @@ static void intr_complete (struct urb *urb)
int status = urb->status;
switch (status) {
/* success */
case 0:
/* success */
case 0:
dev->driver_info->status(dev, urb);
break;
/* software-driven interface shutdown */
case -ENOENT: // urb killed
case -ESHUTDOWN: // hardware gone
/* software-driven interface shutdown */
case -ENOENT: /* urb killed */
case -ESHUTDOWN: /* hardware gone */
if (netif_msg_ifdown (dev))
devdbg (dev, "intr shutdown, code %d", status);
return;
/* NOTE: not throttling like RX/TX, since this endpoint
* already polls infrequently
*/
default:
/* NOTE: not throttling like RX/TX, since this endpoint
* already polls infrequently
*/
default:
devdbg (dev, "intr status %d", status);
break;
}
@ -569,9 +571,9 @@ static int usbnet_stop (struct net_device *net)
temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq);
// maybe wait for deletions to finish.
while (!skb_queue_empty(&dev->rxq) &&
!skb_queue_empty(&dev->txq) &&
!skb_queue_empty(&dev->done)) {
while (!skb_queue_empty(&dev->rxq)
&& !skb_queue_empty(&dev->txq)
&& !skb_queue_empty(&dev->done)) {
msleep(UNLINK_TIMEOUT_MS);
if (netif_msg_ifdown (dev))
devdbg (dev, "waited for %d urb completions", temp);
@ -1011,16 +1013,16 @@ static void usbnet_bh (unsigned long param)
while ((skb = skb_dequeue (&dev->done))) {
entry = (struct skb_data *) skb->cb;
switch (entry->state) {
case rx_done:
case rx_done:
entry->state = rx_cleanup;
rx_process (dev, skb);
continue;
case tx_done:
case rx_cleanup:
case tx_done:
case rx_cleanup:
usb_free_urb (entry->urb);
dev_kfree_skb (skb);
continue;
default:
default:
devdbg (dev, "bogus skb state %d", entry->state);
}
}

View file

@ -47,7 +47,7 @@ struct usbnet {
unsigned long data [5];
u32 xid;
u32 hard_mtu; /* count any extra framing */
size_t rx_urb_size; /* size for rx urbs */
size_t rx_urb_size; /* size for rx urbs */
struct mii_if_info mii;
/* various kinds of pending driver work */
@ -85,7 +85,7 @@ struct driver_info {
#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */
#define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */
#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
/* init device ... can sleep, or cause probe() failure */
int (*bind)(struct usbnet *, struct usb_interface *);
@ -146,9 +146,9 @@ extern void usbnet_cdc_unbind (struct usbnet *, struct usb_interface *);
/* CDC and RNDIS support the same host-chosen packet filters for IN transfers */
#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
|USB_CDC_PACKET_TYPE_PROMISCUOUS \
|USB_CDC_PACKET_TYPE_DIRECTED)
|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
|USB_CDC_PACKET_TYPE_PROMISCUOUS \
|USB_CDC_PACKET_TYPE_DIRECTED)
/* we record the state for each of our queued skbs */

View file

@ -546,6 +546,18 @@ config USB_ZD1201
To compile this driver as a module, choose M here: the
module will be called zd1201.
config RTL8187
tristate "Realtek 8187 USB support"
depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL
select EEPROM_93CX6
---help---
This is a driver for RTL8187 based cards.
These are USB based chips found in cards such as:
Netgear WG111v2
Thanks to Realtek for their support!
source "drivers/net/wireless/hostap/Kconfig"
source "drivers/net/wireless/bcm43xx/Kconfig"
source "drivers/net/wireless/zd1211rw/Kconfig"

View file

@ -44,3 +44,6 @@ obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
obj-$(CONFIG_USB_ZD1201) += zd1201.o
obj-$(CONFIG_LIBERTAS_USB) += libertas/
rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o
obj-$(CONFIG_RTL8187) += rtl8187.o

View file

@ -1638,7 +1638,7 @@ void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
return;
}
if (phy->analog > 1) {
if (phy->analog == 1) {
value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
value |= (baseband_attenuation << 2) & 0x003C;
} else {

View file

@ -326,7 +326,6 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
char *p = page;
struct ap_data *ap = (struct ap_data *) data;
char *policy_txt;
struct list_head *ptr;
struct mac_entry *entry;
if (off != 0) {
@ -352,14 +351,12 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries);
p += sprintf(p, "MAC list:\n");
spin_lock_bh(&ap->mac_restrictions.lock);
for (ptr = ap->mac_restrictions.mac_list.next;
ptr != &ap->mac_restrictions.mac_list; ptr = ptr->next) {
list_for_each_entry(entry, &ap->mac_restrictions.mac_list, list) {
if (p - page > PAGE_SIZE - 80) {
p += sprintf(p, "All entries did not fit one page.\n");
break;
}
entry = list_entry(ptr, struct mac_entry, list);
p += sprintf(p, MACSTR "\n", MAC2STR(entry->addr));
}
spin_unlock_bh(&ap->mac_restrictions.lock);
@ -413,7 +410,6 @@ int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
u8 *mac)
{
struct list_head *ptr;
struct mac_entry *entry;
int found = 0;
@ -421,10 +417,7 @@ static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
return 0;
spin_lock_bh(&mac_restrictions->lock);
for (ptr = mac_restrictions->mac_list.next;
ptr != &mac_restrictions->mac_list; ptr = ptr->next) {
entry = list_entry(ptr, struct mac_entry, list);
list_for_each_entry(entry, &mac_restrictions->mac_list, list) {
if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
found = 1;
break;
@ -519,7 +512,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off,
{
char *p = page;
struct ap_data *ap = (struct ap_data *) data;
struct list_head *ptr;
struct sta_info *sta;
int i;
if (off > PROC_LIMIT) {
@ -529,9 +522,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off,
p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n");
spin_lock_bh(&ap->sta_table_lock);
for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
struct sta_info *sta = (struct sta_info *) ptr;
list_for_each_entry(sta, &ap->sta_list, list) {
if (!sta->ap)
continue;
@ -861,7 +852,7 @@ void hostap_init_ap_proc(local_info_t *local)
void hostap_free_data(struct ap_data *ap)
{
struct list_head *n, *ptr;
struct sta_info *n, *sta;
if (ap == NULL || !ap->initialized) {
printk(KERN_DEBUG "hostap_free_data: ap has not yet been "
@ -875,8 +866,7 @@ void hostap_free_data(struct ap_data *ap)
ap->crypt = ap->crypt_priv = NULL;
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
list_for_each_safe(ptr, n, &ap->sta_list) {
struct sta_info *sta = list_entry(ptr, struct sta_info, list);
list_for_each_entry_safe(sta, n, &ap->sta_list, list) {
ap_sta_hash_del(ap, sta);
list_del(&sta->list);
if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
@ -2704,6 +2694,8 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
if (hdr->addr1[0] & 0x01) {
/* broadcast/multicast frame - no AP related processing */
if (local->ap->num_sta <= 0)
ret = AP_TX_DROP;
goto out;
}
@ -3198,15 +3190,14 @@ int hostap_update_rx_stats(struct ap_data *ap,
void hostap_update_rates(local_info_t *local)
{
struct list_head *ptr;
struct sta_info *sta;
struct ap_data *ap = local->ap;
if (!ap)
return;
spin_lock_bh(&ap->sta_table_lock);
for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
struct sta_info *sta = (struct sta_info *) ptr;
list_for_each_entry(sta, &ap->sta_list, list) {
prism2_check_tx_rates(sta);
}
spin_unlock_bh(&ap->sta_table_lock);
@ -3242,11 +3233,10 @@ void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
void hostap_add_wds_links(local_info_t *local)
{
struct ap_data *ap = local->ap;
struct list_head *ptr;
struct sta_info *sta;
spin_lock_bh(&ap->sta_table_lock);
list_for_each(ptr, &ap->sta_list) {
struct sta_info *sta = list_entry(ptr, struct sta_info, list);
list_for_each_entry(sta, &ap->sta_list, list) {
if (sta->ap)
hostap_wds_link_oper(local, sta->addr, WDS_ADD);
}

View file

@ -1,8 +1,6 @@
#ifndef HOSTAP_CONFIG_H
#define HOSTAP_CONFIG_H
#define PRISM2_VERSION "0.4.4-kernel"
/* In the previous versions of Host AP driver, support for user space version
* of IEEE 802.11 management (hostapd) used to be disabled in the default
* configuration. From now on, support for hostapd is always included and it is

View file

@ -22,7 +22,6 @@
#include "hostap_wlan.h"
static char *version = PRISM2_VERSION " (Jouni Malinen <[email protected]>)";
static dev_info_t dev_info = "hostap_cs";
MODULE_AUTHOR("Jouni Malinen");
@ -30,7 +29,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
"cards (PC Card).");
MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)");
MODULE_LICENSE("GPL");
MODULE_VERSION(PRISM2_VERSION);
static int ignore_cis_vcc;
@ -910,14 +908,12 @@ static struct pcmcia_driver hostap_driver = {
static int __init init_prism2_pccard(void)
{
printk(KERN_INFO "%s: %s\n", dev_info, version);
return pcmcia_register_driver(&hostap_driver);
}
static void __exit exit_prism2_pccard(void)
{
pcmcia_unregister_driver(&hostap_driver);
printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
}

View file

@ -3893,8 +3893,6 @@ static void prism2_get_drvinfo(struct net_device *dev,
local = iface->local;
strncpy(info->driver, "hostap", sizeof(info->driver) - 1);
strncpy(info->version, PRISM2_VERSION,
sizeof(info->version) - 1);
snprintf(info->fw_version, sizeof(info->fw_version) - 1,
"%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff,
(local->sta_fw_ver >> 8) & 0xff,

View file

@ -37,7 +37,6 @@
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Host AP common routines");
MODULE_LICENSE("GPL");
MODULE_VERSION(PRISM2_VERSION);
#define TX_TIMEOUT (2 * HZ)

View file

@ -20,7 +20,6 @@
#include "hostap_wlan.h"
static char *version = PRISM2_VERSION " (Jouni Malinen <[email protected]>)";
static char *dev_info = "hostap_pci";
@ -29,7 +28,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN "
"PCI cards.");
MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards");
MODULE_LICENSE("GPL");
MODULE_VERSION(PRISM2_VERSION);
/* struct local_info::hw_priv */
@ -462,8 +460,6 @@ static struct pci_driver prism2_pci_drv_id = {
static int __init init_prism2_pci(void)
{
printk(KERN_INFO "%s: %s\n", dev_info, version);
return pci_register_driver(&prism2_pci_drv_id);
}
@ -471,7 +467,6 @@ static int __init init_prism2_pci(void)
static void __exit exit_prism2_pci(void)
{
pci_unregister_driver(&prism2_pci_drv_id);
printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
}

View file

@ -23,7 +23,6 @@
#include "hostap_wlan.h"
static char *version = PRISM2_VERSION " (Jouni Malinen <[email protected]>)";
static char *dev_info = "hostap_plx";
@ -32,7 +31,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
"cards (PLX).");
MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)");
MODULE_LICENSE("GPL");
MODULE_VERSION(PRISM2_VERSION);
static int ignore_cis;
@ -623,8 +621,6 @@ static struct pci_driver prism2_plx_drv_id = {
static int __init init_prism2_plx(void)
{
printk(KERN_INFO "%s: %s\n", dev_info, version);
return pci_register_driver(&prism2_plx_drv_id);
}
@ -632,7 +628,6 @@ static int __init init_prism2_plx(void)
static void __exit exit_prism2_plx(void)
{
pci_unregister_driver(&prism2_plx_drv_id);
printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
}

View file

@ -0,0 +1,145 @@
/*
* Definitions for RTL8187 hardware
*
* Copyright 2007 Michael Wu <flamingice@sourmilk.net>
* Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
*
* Based on the r8187 driver, which is:
* Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef RTL8187_H
#define RTL8187_H
#include "rtl818x.h"
#define RTL8187_EEPROM_TXPWR_BASE 0x05
#define RTL8187_EEPROM_MAC_ADDR 0x07
#define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */
#define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */
#define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */
#define RTL8187_REQT_READ 0xC0
#define RTL8187_REQT_WRITE 0x40
#define RTL8187_REQ_GET_REG 0x05
#define RTL8187_REQ_SET_REG 0x05
#define RTL8187_MAX_RX 0x9C4
struct rtl8187_rx_info {
struct urb *urb;
struct ieee80211_hw *dev;
};
struct rtl8187_rx_hdr {
__le16 len;
__le16 rate;
u8 noise;
u8 signal;
u8 agc;
u8 reserved;
__le64 mac_time;
} __attribute__((packed));
struct rtl8187_tx_info {
struct ieee80211_tx_control *control;
struct urb *urb;
struct ieee80211_hw *dev;
};
struct rtl8187_tx_hdr {
__le32 flags;
#define RTL8187_TX_FLAG_NO_ENCRYPT (1 << 15)
#define RTL8187_TX_FLAG_MORE_FRAG (1 << 17)
#define RTL8187_TX_FLAG_CTS (1 << 18)
#define RTL8187_TX_FLAG_RTS (1 << 23)
__le16 rts_duration;
__le16 len;
__le32 retry;
} __attribute__((packed));
struct rtl8187_priv {
/* common between rtl818x drivers */
struct rtl818x_csr *map;
void (*rf_init)(struct ieee80211_hw *);
int mode;
/* rtl8187 specific */
struct ieee80211_channel channels[14];
struct ieee80211_rate rates[12];
struct ieee80211_hw_mode modes[2];
struct usb_device *udev;
u8 *hwaddr;
u16 txpwr_base;
u8 asic_rev;
struct sk_buff_head rx_queue;
};
void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr)
{
u8 val;
usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
return val;
}
static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr)
{
__le16 val;
usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
return le16_to_cpu(val);
}
static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr)
{
__le32 val;
usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
return le32_to_cpu(val);
}
static inline void rtl818x_iowrite8(struct rtl8187_priv *priv,
u8 *addr, u8 val)
{
usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
}
static inline void rtl818x_iowrite16(struct rtl8187_priv *priv,
__le16 *addr, u16 val)
{
__le16 buf = cpu_to_le16(val);
usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
(unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
}
static inline void rtl818x_iowrite32(struct rtl8187_priv *priv,
__le32 *addr, u32 val)
{
__le32 buf = cpu_to_le32(val);
usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
(unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
}
#endif /* RTL8187_H */

View file

@ -0,0 +1,731 @@
/*
* Linux device driver for RTL8187
*
* Copyright 2007 Michael Wu <flamingice@sourmilk.net>
* Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
*
* Based on the r8187 driver, which is:
* Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
*
* Magic delays and register offsets below are taken from the original
* r8187 driver sources. Thanks to Realtek for their support!
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/usb.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/eeprom_93cx6.h>
#include <net/mac80211.h>
#include "rtl8187.h"
#include "rtl8187_rtl8225.h"
MODULE_AUTHOR("Michael Wu <[email protected]>");
MODULE_AUTHOR("Andrea Merello <[email protected]>");
MODULE_DESCRIPTION("RTL8187 USB wireless driver");
MODULE_LICENSE("GPL");
static struct usb_device_id rtl8187_table[] __devinitdata = {
/* Realtek */
{USB_DEVICE(0x0bda, 0x8187)},
/* Netgear */
{USB_DEVICE(0x0846, 0x6100)},
{USB_DEVICE(0x0846, 0x6a00)},
{}
};
MODULE_DEVICE_TABLE(usb, rtl8187_table);
void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
{
struct rtl8187_priv *priv = dev->priv;
data <<= 8;
data |= addr | 0x80;
rtl818x_iowrite8(priv, &priv->map->PHY[3], (data >> 24) & 0xFF);
rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF);
rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF);
rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF);
msleep(1);
}
static void rtl8187_tx_cb(struct urb *urb)
{
struct ieee80211_tx_status status = { {0} };
struct sk_buff *skb = (struct sk_buff *)urb->context;
struct rtl8187_tx_info *info = (struct rtl8187_tx_info *)skb->cb;
usb_free_urb(info->urb);
if (info->control)
memcpy(&status.control, info->control, sizeof(status.control));
kfree(info->control);
skb_pull(skb, sizeof(struct rtl8187_tx_hdr));
status.flags |= IEEE80211_TX_STATUS_ACK;
ieee80211_tx_status_irqsafe(info->dev, skb, &status);
}
static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct rtl8187_priv *priv = dev->priv;
struct rtl8187_tx_hdr *hdr;
struct rtl8187_tx_info *info;
struct urb *urb;
u32 tmp;
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
kfree_skb(skb);
return 0;
}
hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
tmp = skb->len - sizeof(*hdr);
tmp |= RTL8187_TX_FLAG_NO_ENCRYPT;
tmp |= control->rts_cts_rate << 19;
tmp |= control->tx_rate << 24;
if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb))
tmp |= RTL8187_TX_FLAG_MORE_FRAG;
if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
tmp |= RTL8187_TX_FLAG_RTS;
hdr->rts_duration =
ieee80211_rts_duration(dev, skb->len, control);
}
if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
tmp |= RTL8187_TX_FLAG_CTS;
hdr->flags = cpu_to_le32(tmp);
hdr->len = 0;
tmp = control->retry_limit << 8;
hdr->retry = cpu_to_le32(tmp);
info = (struct rtl8187_tx_info *)skb->cb;
info->control = kmemdup(control, sizeof(*control), GFP_ATOMIC);
info->urb = urb;
info->dev = dev;
usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2),
hdr, skb->len, rtl8187_tx_cb, skb);
usb_submit_urb(urb, GFP_ATOMIC);
return 0;
}
static void rtl8187_rx_cb(struct urb *urb)
{
struct sk_buff *skb = (struct sk_buff *)urb->context;
struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb;
struct ieee80211_hw *dev = info->dev;
struct rtl8187_priv *priv = dev->priv;
struct rtl8187_rx_hdr *hdr;
struct ieee80211_rx_status rx_status = { 0 };
int rate, signal;
spin_lock(&priv->rx_queue.lock);
if (skb->next)
__skb_unlink(skb, &priv->rx_queue);
else {
spin_unlock(&priv->rx_queue.lock);
return;
}
spin_unlock(&priv->rx_queue.lock);
if (unlikely(urb->status)) {
usb_free_urb(urb);
dev_kfree_skb_irq(skb);
return;
}
skb_put(skb, urb->actual_length);
hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr));
skb_trim(skb, le16_to_cpu(hdr->len) & 0x0FFF);
signal = hdr->agc >> 1;
rate = (le16_to_cpu(hdr->rate) >> 4) & 0xF;
if (rate > 3) { /* OFDM rate */
if (signal > 90)
signal = 90;
else if (signal < 25)
signal = 25;
signal = 90 - signal;
} else { /* CCK rate */
if (signal > 95)
signal = 95;
else if (signal < 30)
signal = 30;
signal = 95 - signal;
}
rx_status.antenna = (hdr->signal >> 7) & 1;
rx_status.signal = 64 - min(hdr->noise, (u8)64);
rx_status.ssi = signal;
rx_status.rate = rate;
rx_status.freq = dev->conf.freq;
rx_status.channel = dev->conf.channel;
rx_status.phymode = dev->conf.phymode;
rx_status.mactime = le64_to_cpu(hdr->mac_time);
ieee80211_rx_irqsafe(dev, skb, &rx_status);
skb = dev_alloc_skb(RTL8187_MAX_RX);
if (unlikely(!skb)) {
usb_free_urb(urb);
/* TODO check rx queue length and refill *somewhere* */
return;
}
info = (struct rtl8187_rx_info *)skb->cb;
info->urb = urb;
info->dev = dev;
urb->transfer_buffer = skb_tail_pointer(skb);
urb->context = skb;
skb_queue_tail(&priv->rx_queue, skb);
usb_submit_urb(urb, GFP_ATOMIC);
}
static int rtl8187_init_urbs(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
struct urb *entry;
struct sk_buff *skb;
struct rtl8187_rx_info *info;
while (skb_queue_len(&priv->rx_queue) < 8) {
skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
if (!skb)
break;
entry = usb_alloc_urb(0, GFP_KERNEL);
if (!entry) {
kfree_skb(skb);
break;
}
usb_fill_bulk_urb(entry, priv->udev,
usb_rcvbulkpipe(priv->udev, 1),
skb_tail_pointer(skb),
RTL8187_MAX_RX, rtl8187_rx_cb, skb);
info = (struct rtl8187_rx_info *)skb->cb;
info->urb = entry;
info->dev = dev;
skb_queue_tail(&priv->rx_queue, skb);
usb_submit_urb(entry, GFP_KERNEL);
}
return 0;
}
static int rtl8187_init_hw(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
u8 reg;
int i;
/* reset */
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
msleep(200);
rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10);
rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11);
rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00);
msleep(200);
reg = rtl818x_ioread8(priv, &priv->map->CMD);
reg &= (1 << 1);
reg |= RTL818X_CMD_RESET;
rtl818x_iowrite8(priv, &priv->map->CMD, reg);
i = 10;
do {
msleep(2);
if (!(rtl818x_ioread8(priv, &priv->map->CMD) &
RTL818X_CMD_RESET))
break;
} while (--i);
if (!i) {
printk(KERN_ERR "%s: Reset timeout!\n", wiphy_name(dev->wiphy));
return -ETIMEDOUT;
}
/* reload registers from eeprom */
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD);
i = 10;
do {
msleep(4);
if (!(rtl818x_ioread8(priv, &priv->map->EEPROM_CMD) &
RTL818X_EEPROM_CMD_CONFIG))
break;
} while (--i);
if (!i) {
printk(KERN_ERR "%s: eeprom reset timeout!\n",
wiphy_name(dev->wiphy));
return -ETIMEDOUT;
}
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
/* setup card */
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
rtl818x_iowrite8(priv, &priv->map->GPIO, 1);
rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
for (i = 0; i < ETH_ALEN; i++)
rtl818x_iowrite8(priv, &priv->map->MAC[i], priv->hwaddr[i]);
rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF);
reg = rtl818x_ioread8(priv, &priv->map->CONFIG1);
reg &= 0x3F;
reg |= 0x80;
rtl818x_iowrite8(priv, &priv->map->CONFIG1, reg);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0);
rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
// TODO: set RESP_RATE and BRSR properly
rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0);
rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
/* host_usb_init */
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
reg = rtl818x_ioread8(priv, (u8 *)0xFE53);
rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7));
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
rtl818x_iowrite8(priv, &priv->map->GPIO, 0x20);
rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80);
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80);
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x80);
msleep(100);
rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7);
msleep(100);
priv->rf_init(dev);
rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & 0xfffe;
rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 0x1);
rtl818x_iowrite16(priv, (__le16 *)0xFFFE, 0x10);
rtl818x_iowrite8(priv, &priv->map->TALLY_SEL, 0x80);
rtl818x_iowrite8(priv, (u8 *)0xFFFF, 0x60);
rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
return 0;
}
static void rtl8187_set_channel(struct ieee80211_hw *dev, int channel)
{
u32 reg;
struct rtl8187_priv *priv = dev->priv;
reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
/* Enable TX loopback on MAC level to avoid TX during channel
* changes, as this has be seen to causes problems and the
* card will stop work until next reset
*/
rtl818x_iowrite32(priv, &priv->map->TX_CONF,
reg | RTL818X_TX_CONF_LOOPBACK_MAC);
msleep(10);
rtl8225_rf_set_channel(dev, channel);
msleep(10);
rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
}
static int rtl8187_open(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
u32 reg;
int ret;
ret = rtl8187_init_hw(dev);
if (ret)
return ret;
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
rtl8187_init_urbs(dev);
reg = RTL818X_RX_CONF_ONLYERLPKT |
RTL818X_RX_CONF_RX_AUTORESETPHY |
RTL818X_RX_CONF_BSSID |
RTL818X_RX_CONF_MGMT |
RTL818X_RX_CONF_CTRL |
RTL818X_RX_CONF_DATA |
(7 << 13 /* RX FIFO threshold NONE */) |
(7 << 10 /* MAX RX DMA */) |
RTL818X_RX_CONF_BROADCAST |
RTL818X_RX_CONF_MULTICAST |
RTL818X_RX_CONF_NICMAC;
if (priv->mode == IEEE80211_IF_TYPE_MNTR)
reg |= RTL818X_RX_CONF_MONITOR;
rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT;
reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg);
reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL);
reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
reg = RTL818X_TX_CONF_CW_MIN |
(7 << 21 /* MAX TX DMA */) |
RTL818X_TX_CONF_NO_ICV;
rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
reg = rtl818x_ioread8(priv, &priv->map->CMD);
reg |= RTL818X_CMD_TX_ENABLE;
reg |= RTL818X_CMD_RX_ENABLE;
rtl818x_iowrite8(priv, &priv->map->CMD, reg);
return 0;
}
static int rtl8187_stop(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
struct rtl8187_rx_info *info;
struct sk_buff *skb;
u32 reg;
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
reg = rtl818x_ioread8(priv, &priv->map->CMD);
reg &= ~RTL818X_CMD_TX_ENABLE;
reg &= ~RTL818X_CMD_RX_ENABLE;
rtl818x_iowrite8(priv, &priv->map->CMD, reg);
rtl8225_rf_stop(dev);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
reg = rtl818x_ioread8(priv, &priv->map->CONFIG4);
rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
while ((skb = skb_dequeue(&priv->rx_queue))) {
info = (struct rtl8187_rx_info *)skb->cb;
usb_kill_urb(info->urb);
kfree_skb(skb);
}
return 0;
}
static int rtl8187_add_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
struct rtl8187_priv *priv = dev->priv;
/* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */
if (priv->mode != IEEE80211_IF_TYPE_MGMT)
return -1;
switch (conf->type) {
case IEEE80211_IF_TYPE_STA:
case IEEE80211_IF_TYPE_MNTR:
priv->mode = conf->type;
break;
default:
return -EOPNOTSUPP;
}
priv->hwaddr = conf->mac_addr;
return 0;
}
static void rtl8187_remove_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
struct rtl8187_priv *priv = dev->priv;
priv->mode = IEEE80211_IF_TYPE_MGMT;
}
static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
{
struct rtl8187_priv *priv = dev->priv;
rtl8187_set_channel(dev, conf->channel);
rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
} else {
rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
}
rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100);
rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100);
return 0;
}
static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id,
struct ieee80211_if_conf *conf)
{
struct rtl8187_priv *priv = dev->priv;
int i;
for (i = 0; i < ETH_ALEN; i++)
rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
if (is_valid_ether_addr(conf->bssid))
rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA);
else
rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK);
return 0;
}
static const struct ieee80211_ops rtl8187_ops = {
.tx = rtl8187_tx,
.open = rtl8187_open,
.stop = rtl8187_stop,
.add_interface = rtl8187_add_interface,
.remove_interface = rtl8187_remove_interface,
.config = rtl8187_config,
.config_interface = rtl8187_config_interface,
};
static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom)
{
struct ieee80211_hw *dev = eeprom->data;
struct rtl8187_priv *priv = dev->priv;
u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
}
static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom)
{
struct ieee80211_hw *dev = eeprom->data;
struct rtl8187_priv *priv = dev->priv;
u8 reg = RTL818X_EEPROM_CMD_PROGRAM;
if (eeprom->reg_data_in)
reg |= RTL818X_EEPROM_CMD_WRITE;
if (eeprom->reg_data_out)
reg |= RTL818X_EEPROM_CMD_READ;
if (eeprom->reg_data_clock)
reg |= RTL818X_EEPROM_CMD_CK;
if (eeprom->reg_chip_select)
reg |= RTL818X_EEPROM_CMD_CS;
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg);
udelay(10);
}
static int __devinit rtl8187_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct ieee80211_hw *dev;
struct rtl8187_priv *priv;
struct eeprom_93cx6 eeprom;
struct ieee80211_channel *channel;
u16 txpwr, reg;
int err, i;
dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
if (!dev) {
printk(KERN_ERR "rtl8187: ieee80211 alloc failed\n");
return -ENOMEM;
}
priv = dev->priv;
SET_IEEE80211_DEV(dev, &intf->dev);
usb_set_intfdata(intf, dev);
priv->udev = udev;
usb_get_dev(udev);
skb_queue_head_init(&priv->rx_queue);
memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
priv->map = (struct rtl818x_csr *)0xFF00;
priv->modes[0].mode = MODE_IEEE80211G;
priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
priv->modes[0].rates = priv->rates;
priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
priv->modes[0].channels = priv->channels;
priv->modes[1].mode = MODE_IEEE80211B;
priv->modes[1].num_rates = 4;
priv->modes[1].rates = priv->rates;
priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
priv->modes[1].channels = priv->channels;
priv->mode = IEEE80211_IF_TYPE_MGMT;
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_WEP_INCLUDE_IV |
IEEE80211_HW_DATA_NULLFUNC_ACK;
dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);
dev->queues = 1;
dev->max_rssi = 65;
dev->max_signal = 64;
for (i = 0; i < 2; i++)
if ((err = ieee80211_register_hwmode(dev, &priv->modes[i])))
goto err_free_dev;
eeprom.data = dev;
eeprom.register_read = rtl8187_eeprom_register_read;
eeprom.register_write = rtl8187_eeprom_register_write;
if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6))
eeprom.width = PCI_EEPROM_WIDTH_93C66;
else
eeprom.width = PCI_EEPROM_WIDTH_93C46;
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
udelay(10);
eeprom_93cx6_multiread(&eeprom, RTL8187_EEPROM_MAC_ADDR,
(__le16 __force *)dev->wiphy->perm_addr, 3);
if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly "
"generated MAC address\n");
random_ether_addr(dev->wiphy->perm_addr);
}
channel = priv->channels;
for (i = 0; i < 3; i++) {
eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i,
&txpwr);
(*channel++).val = txpwr & 0xFF;
(*channel++).val = txpwr >> 8;
}
for (i = 0; i < 2; i++) {
eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i,
&txpwr);
(*channel++).val = txpwr & 0xFF;
(*channel++).val = txpwr >> 8;
}
for (i = 0; i < 2; i++) {
eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i,
&txpwr);
(*channel++).val = txpwr & 0xFF;
(*channel++).val = txpwr >> 8;
}
eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE,
&priv->txpwr_base);
reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & ~1;
rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 1);
/* 0 means asic B-cut, we should use SW 3 wire
* bit-by-bit banging for radio. 1 means we can use
* USB specific request to write radio registers */
priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3;
rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
rtl8225_write(dev, 0, 0x1B7);
if (rtl8225_read(dev, 8) != 0x588 || rtl8225_read(dev, 9) != 0x700)
priv->rf_init = rtl8225_rf_init;
else
priv->rf_init = rtl8225z2_rf_init;
rtl8225_write(dev, 0, 0x0B7);
err = ieee80211_register_hw(dev);
if (err) {
printk(KERN_ERR "rtl8187: Cannot register device\n");
goto err_free_dev;
}
printk(KERN_INFO "%s: hwaddr " MAC_FMT ", rtl8187 V%d + %s\n",
wiphy_name(dev->wiphy), MAC_ARG(dev->wiphy->perm_addr),
priv->asic_rev, priv->rf_init == rtl8225_rf_init ?
"rtl8225" : "rtl8225z2");
return 0;
err_free_dev:
ieee80211_free_hw(dev);
usb_set_intfdata(intf, NULL);
usb_put_dev(udev);
return err;
}
static void __devexit rtl8187_disconnect(struct usb_interface *intf)
{
struct ieee80211_hw *dev = usb_get_intfdata(intf);
struct rtl8187_priv *priv;
if (!dev)
return;
ieee80211_unregister_hw(dev);
priv = dev->priv;
usb_put_dev(interface_to_usbdev(intf));
ieee80211_free_hw(dev);
}
static struct usb_driver rtl8187_driver = {
.name = KBUILD_MODNAME,
.id_table = rtl8187_table,
.probe = rtl8187_probe,
.disconnect = rtl8187_disconnect,
};
static int __init rtl8187_init(void)
{
return usb_register(&rtl8187_driver);
}
static void __exit rtl8187_exit(void)
{
usb_deregister(&rtl8187_driver);
}
module_init(rtl8187_init);
module_exit(rtl8187_exit);

View file

@ -0,0 +1,745 @@
/*
* Radio tuning for RTL8225 on RTL8187
*
* Copyright 2007 Michael Wu <flamingice@sourmilk.net>
* Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
*
* Based on the r8187 driver, which is:
* Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
*
* Magic delays, register offsets, and phy value tables below are
* taken from the original r8187 driver sources. Thanks to Realtek
* for their support!
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/usb.h>
#include <net/mac80211.h>
#include "rtl8187.h"
#include "rtl8187_rtl8225.h"
static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
{
struct rtl8187_priv *priv = dev->priv;
u16 reg80, reg84, reg82;
u32 bangdata;
int i;
bangdata = (data << 4) | (addr & 0xf);
reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
udelay(10);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
udelay(2);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
udelay(10);
for (i = 15; i >= 0; i--) {
u16 reg = reg80 | (bangdata & (1 << i)) >> i;
if (i & 1)
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
if (!(i & 1))
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
}
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
udelay(10);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
msleep(2);
}
static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, u16 data)
{
struct rtl8187_priv *priv = dev->priv;
u16 reg80, reg82, reg84;
reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
reg80 &= ~(0x3 << 2);
reg84 &= ~0xF;
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
udelay(10);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
udelay(2);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
udelay(10);
usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
addr, 0x8225, &data, sizeof(data), HZ / 2);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
udelay(10);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
msleep(2);
}
void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
{
struct rtl8187_priv *priv = dev->priv;
if (priv->asic_rev)
rtl8225_write_8051(dev, addr, data);
else
rtl8225_write_bitbang(dev, addr, data);
}
u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
{
struct rtl8187_priv *priv = dev->priv;
u16 reg80, reg82, reg84, out;
int i;
reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
reg80 &= ~0xF;
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
udelay(4);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
udelay(5);
for (i = 4; i >= 0; i--) {
u16 reg = reg80 | ((addr >> i) & 1);
if (!(i & 1)) {
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
udelay(1);
}
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
reg | (1 << 1));
udelay(2);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
reg | (1 << 1));
udelay(2);
if (i & 1) {
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
udelay(1);
}
}
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
reg80 | (1 << 3) | (1 << 1));
udelay(2);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
reg80 | (1 << 3));
udelay(2);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
reg80 | (1 << 3));
udelay(2);
out = 0;
for (i = 11; i >= 0; i--) {
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
reg80 | (1 << 3));
udelay(1);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
reg80 | (1 << 3) | (1 << 1));
udelay(2);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
reg80 | (1 << 3) | (1 << 1));
udelay(2);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
reg80 | (1 << 3) | (1 << 1));
udelay(2);
if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
out |= 1 << i;
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
reg80 | (1 << 3));
udelay(2);
}
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
reg80 | (1 << 3) | (1 << 2));
udelay(2);
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
return out;
}
static const u16 rtl8225bcd_rxgain[] = {
0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
};
static const u8 rtl8225_agc[] = {
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
};
static const u8 rtl8225_gain[] = {
0x23, 0x88, 0x7c, 0xa5, /* -82dBm */
0x23, 0x88, 0x7c, 0xb5, /* -82dBm */
0x23, 0x88, 0x7c, 0xc5, /* -82dBm */
0x33, 0x80, 0x79, 0xc5, /* -78dBm */
0x43, 0x78, 0x76, 0xc5, /* -74dBm */
0x53, 0x60, 0x73, 0xc5, /* -70dBm */
0x63, 0x58, 0x70, 0xc5, /* -66dBm */
};
static const u8 rtl8225_threshold[] = {
0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
};
static const u8 rtl8225_tx_gain_cck_ofdm[] = {
0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
};
static const u8 rtl8225_tx_power_cck[] = {
0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
};
static const u8 rtl8225_tx_power_cck_ch14[] = {
0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
};
static const u8 rtl8225_tx_power_ofdm[] = {
0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
};
static const u32 rtl8225_chan[] = {
0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
};
static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
{
struct rtl8187_priv *priv = dev->priv;
u8 cck_power, ofdm_power;
const u8 *tmp;
u32 reg;
int i;
cck_power = priv->channels[channel - 1].val & 0xF;
ofdm_power = priv->channels[channel - 1].val >> 4;
cck_power = min(cck_power, (u8)11);
ofdm_power = min(ofdm_power, (u8)35);
rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
if (channel == 14)
tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
else
tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
for (i = 0; i < 8; i++)
rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
msleep(1); // FIXME: optional?
/* anaparam2 on */
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
rtl8225_write_phy_ofdm(dev, 2, 0x42);
rtl8225_write_phy_ofdm(dev, 6, 0x00);
rtl8225_write_phy_ofdm(dev, 8, 0x00);
rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
rtl8225_write_phy_ofdm(dev, 5, *tmp);
rtl8225_write_phy_ofdm(dev, 7, *tmp);
msleep(1);
}
void rtl8225_rf_init(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
int i;
rtl8225_write(dev, 0x0, 0x067); msleep(1);
rtl8225_write(dev, 0x1, 0xFE0); msleep(1);
rtl8225_write(dev, 0x2, 0x44D); msleep(1);
rtl8225_write(dev, 0x3, 0x441); msleep(1);
rtl8225_write(dev, 0x4, 0x486); msleep(1);
rtl8225_write(dev, 0x5, 0xBC0); msleep(1);
rtl8225_write(dev, 0x6, 0xAE6); msleep(1);
rtl8225_write(dev, 0x7, 0x82A); msleep(1);
rtl8225_write(dev, 0x8, 0x01F); msleep(1);
rtl8225_write(dev, 0x9, 0x334); msleep(1);
rtl8225_write(dev, 0xA, 0xFD4); msleep(1);
rtl8225_write(dev, 0xB, 0x391); msleep(1);
rtl8225_write(dev, 0xC, 0x050); msleep(1);
rtl8225_write(dev, 0xD, 0x6DB); msleep(1);
rtl8225_write(dev, 0xE, 0x029); msleep(1);
rtl8225_write(dev, 0xF, 0x914); msleep(100);
rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
rtl8225_write(dev, 0x2, 0x44D); msleep(200);
if (!(rtl8225_read(dev, 6) & (1 << 7))) {
rtl8225_write(dev, 0x02, 0x0c4d);
msleep(200);
rtl8225_write(dev, 0x02, 0x044d);
msleep(100);
if (!(rtl8225_read(dev, 6) & (1 << 7)))
printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
}
rtl8225_write(dev, 0x0, 0x127);
for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
rtl8225_write(dev, 0x1, i + 1);
rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
}
rtl8225_write(dev, 0x0, 0x027);
rtl8225_write(dev, 0x0, 0x22F);
for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
msleep(1);
rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
msleep(1);
}
msleep(1);
rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
rtl8225_write_phy_cck(dev, 0x13, 0xd0);
rtl8225_write_phy_cck(dev, 0x19, 0x00);
rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
rtl8225_write_phy_cck(dev, 0x1b, 0x08);
rtl8225_write_phy_cck(dev, 0x40, 0x86);
rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
rtl8225_rf_set_tx_power(dev, 1);
/* RX antenna default to A */
rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
msleep(1);
rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
/* set sensitivity */
rtl8225_write(dev, 0x0c, 0x50);
rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
}
static const u8 rtl8225z2_tx_power_cck_ch14[] = {
0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
};
static const u8 rtl8225z2_tx_power_cck[] = {
0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
};
static const u8 rtl8225z2_tx_power_ofdm[] = {
0x42, 0x00, 0x40, 0x00, 0x40
};
static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
};
static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
{
struct rtl8187_priv *priv = dev->priv;
u8 cck_power, ofdm_power;
const u8 *tmp;
u32 reg;
int i;
cck_power = priv->channels[channel - 1].val & 0xF;
ofdm_power = priv->channels[channel - 1].val >> 4;
cck_power = min(cck_power, (u8)15);
cck_power += priv->txpwr_base & 0xF;
cck_power = min(cck_power, (u8)35);
ofdm_power = min(ofdm_power, (u8)15);
ofdm_power += priv->txpwr_base >> 4;
ofdm_power = min(ofdm_power, (u8)35);
if (channel == 14)
tmp = rtl8225z2_tx_power_cck_ch14;
else
tmp = rtl8225z2_tx_power_cck;
for (i = 0; i < 8; i++)
rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
rtl8225z2_tx_gain_cck_ofdm[cck_power]);
msleep(1);
/* anaparam2 on */
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
rtl8225_write_phy_ofdm(dev, 2, 0x42);
rtl8225_write_phy_ofdm(dev, 5, 0x00);
rtl8225_write_phy_ofdm(dev, 6, 0x40);
rtl8225_write_phy_ofdm(dev, 7, 0x00);
rtl8225_write_phy_ofdm(dev, 8, 0x40);
rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
msleep(1);
}
static const u16 rtl8225z2_rxgain[] = {
0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
};
static const u8 rtl8225z2_gain_bg[] = {
0x23, 0x15, 0xa5, /* -82-1dBm */
0x23, 0x15, 0xb5, /* -82-2dBm */
0x23, 0x15, 0xc5, /* -82-3dBm */
0x33, 0x15, 0xc5, /* -78dBm */
0x43, 0x15, 0xc5, /* -74dBm */
0x53, 0x15, 0xc5, /* -70dBm */
0x63, 0x15, 0xc5 /* -66dBm */
};
void rtl8225z2_rf_init(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
int i;
rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
rtl8225_write(dev, 0x2, 0x44D); msleep(1);
rtl8225_write(dev, 0x3, 0x441); msleep(1);
rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
rtl8225_write(dev, 0x5, 0xC72); msleep(1);
rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
rtl8225_write(dev, 0x7, 0x82A); msleep(1);
rtl8225_write(dev, 0x8, 0x03F); msleep(1);
rtl8225_write(dev, 0x9, 0x335); msleep(1);
rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
rtl8225_write(dev, 0xc, 0x850); msleep(1);
rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
rtl8225_write(dev, 0xe, 0x02B); msleep(1);
rtl8225_write(dev, 0xf, 0x114); msleep(100);
rtl8225_write(dev, 0x0, 0x1B7);
for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
rtl8225_write(dev, 0x1, i + 1);
rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
}
rtl8225_write(dev, 0x3, 0x080);
rtl8225_write(dev, 0x5, 0x004);
rtl8225_write(dev, 0x0, 0x0B7);
rtl8225_write(dev, 0x2, 0xc4D);
msleep(200);
rtl8225_write(dev, 0x2, 0x44D);
msleep(100);
if (!(rtl8225_read(dev, 6) & (1 << 7))) {
rtl8225_write(dev, 0x02, 0x0C4D);
msleep(200);
rtl8225_write(dev, 0x02, 0x044D);
msleep(100);
if (!(rtl8225_read(dev, 6) & (1 << 7)))
printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
}
msleep(200);
rtl8225_write(dev, 0x0, 0x2BF);
for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
msleep(1);
rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
msleep(1);
}
msleep(1);
rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x11, 0x07); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x21, 0x17); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); //FIXME: not needed?
rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x25, 0x00); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
rtl8225_write_phy_cck(dev, 0x13, 0xd0);
rtl8225_write_phy_cck(dev, 0x19, 0x00);
rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
rtl8225_write_phy_cck(dev, 0x1b, 0x08);
rtl8225_write_phy_cck(dev, 0x40, 0x86);
rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
rtl8225z2_rf_set_tx_power(dev, 1);
/* RX antenna default to A */
rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
msleep(1);
rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
}
void rtl8225_rf_stop(struct ieee80211_hw *dev)
{
u8 reg;
struct rtl8187_priv *priv = dev->priv;
rtl8225_write(dev, 0x4, 0x1f); msleep(1);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
}
void rtl8225_rf_set_channel(struct ieee80211_hw *dev, int channel)
{
struct rtl8187_priv *priv = dev->priv;
if (priv->rf_init == rtl8225_rf_init)
rtl8225_rf_set_tx_power(dev, channel);
else
rtl8225z2_rf_set_tx_power(dev, channel);
rtl8225_write(dev, 0x7, rtl8225_chan[channel - 1]);
msleep(10);
}

View file

@ -0,0 +1,44 @@
/*
* Radio tuning definitions for RTL8225 on RTL8187
*
* Copyright 2007 Michael Wu <flamingice@sourmilk.net>
* Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
*
* Based on the r8187 driver, which is:
* Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef RTL8187_RTL8225_H
#define RTL8187_RTL8225_H
#define RTL8225_ANAPARAM_ON 0xa0000a59
#define RTL8225_ANAPARAM2_ON 0x860c7312
#define RTL8225_ANAPARAM_OFF 0xa00beb59
#define RTL8225_ANAPARAM2_OFF 0x840dec11
void rtl8225_write(struct ieee80211_hw *, u8 addr, u16 data);
u16 rtl8225_read(struct ieee80211_hw *, u8 addr);
void rtl8225_rf_init(struct ieee80211_hw *);
void rtl8225z2_rf_init(struct ieee80211_hw *);
void rtl8225_rf_stop(struct ieee80211_hw *);
void rtl8225_rf_set_channel(struct ieee80211_hw *, int);
static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
u8 addr, u32 data)
{
rtl8187_write_phy(dev, addr, data);
}
static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev,
u8 addr, u32 data)
{
rtl8187_write_phy(dev, addr, data | 0x10000);
}
#endif /* RTL8187_RTL8225_H */

View file

@ -0,0 +1,226 @@
/*
* Definitions for RTL818x hardware
*
* Copyright 2007 Michael Wu <flamingice@sourmilk.net>
* Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
*
* Based on the r8187 driver, which is:
* Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef RTL818X_H
#define RTL818X_H
struct rtl818x_csr {
u8 MAC[6];
u8 reserved_0[2];
__le32 MAR[2];
u8 RX_FIFO_COUNT;
u8 reserved_1;
u8 TX_FIFO_COUNT;
u8 BQREQ;
u8 reserved_2[4];
__le32 TSFT[2];
__le32 TLPDA;
__le32 TNPDA;
__le32 THPDA;
__le16 BRSR;
u8 BSSID[6];
u8 RESP_RATE;
u8 EIFS;
u8 reserved_3[1];
u8 CMD;
#define RTL818X_CMD_TX_ENABLE (1 << 2)
#define RTL818X_CMD_RX_ENABLE (1 << 3)
#define RTL818X_CMD_RESET (1 << 4)
u8 reserved_4[4];
__le16 INT_MASK;
__le16 INT_STATUS;
#define RTL818X_INT_RX_OK (1 << 0)
#define RTL818X_INT_RX_ERR (1 << 1)
#define RTL818X_INT_TXL_OK (1 << 2)
#define RTL818X_INT_TXL_ERR (1 << 3)
#define RTL818X_INT_RX_DU (1 << 4)
#define RTL818X_INT_RX_FO (1 << 5)
#define RTL818X_INT_TXN_OK (1 << 6)
#define RTL818X_INT_TXN_ERR (1 << 7)
#define RTL818X_INT_TXH_OK (1 << 8)
#define RTL818X_INT_TXH_ERR (1 << 9)
#define RTL818X_INT_TXB_OK (1 << 10)
#define RTL818X_INT_TXB_ERR (1 << 11)
#define RTL818X_INT_ATIM (1 << 12)
#define RTL818X_INT_BEACON (1 << 13)
#define RTL818X_INT_TIME_OUT (1 << 14)
#define RTL818X_INT_TX_FO (1 << 15)
__le32 TX_CONF;
#define RTL818X_TX_CONF_LOOPBACK_MAC (1 << 17)
#define RTL818X_TX_CONF_NO_ICV (1 << 19)
#define RTL818X_TX_CONF_DISCW (1 << 20)
#define RTL818X_TX_CONF_R8180_ABCD (2 << 25)
#define RTL818X_TX_CONF_R8180_F (3 << 25)
#define RTL818X_TX_CONF_R8185_ABC (4 << 25)
#define RTL818X_TX_CONF_R8185_D (5 << 25)
#define RTL818X_TX_CONF_HWVER_MASK (7 << 25)
#define RTL818X_TX_CONF_CW_MIN (1 << 31)
__le32 RX_CONF;
#define RTL818X_RX_CONF_MONITOR (1 << 0)
#define RTL818X_RX_CONF_NICMAC (1 << 1)
#define RTL818X_RX_CONF_MULTICAST (1 << 2)
#define RTL818X_RX_CONF_BROADCAST (1 << 3)
#define RTL818X_RX_CONF_DATA (1 << 18)
#define RTL818X_RX_CONF_CTRL (1 << 19)
#define RTL818X_RX_CONF_MGMT (1 << 20)
#define RTL818X_RX_CONF_BSSID (1 << 23)
#define RTL818X_RX_CONF_RX_AUTORESETPHY (1 << 28)
#define RTL818X_RX_CONF_ONLYERLPKT (1 << 31)
__le32 INT_TIMEOUT;
__le32 TBDA;
u8 EEPROM_CMD;
#define RTL818X_EEPROM_CMD_READ (1 << 0)
#define RTL818X_EEPROM_CMD_WRITE (1 << 1)
#define RTL818X_EEPROM_CMD_CK (1 << 2)
#define RTL818X_EEPROM_CMD_CS (1 << 3)
#define RTL818X_EEPROM_CMD_NORMAL (0 << 6)
#define RTL818X_EEPROM_CMD_LOAD (1 << 6)
#define RTL818X_EEPROM_CMD_PROGRAM (2 << 6)
#define RTL818X_EEPROM_CMD_CONFIG (3 << 6)
u8 CONFIG0;
u8 CONFIG1;
u8 CONFIG2;
__le32 ANAPARAM;
u8 MSR;
#define RTL818X_MSR_NO_LINK (0 << 2)
#define RTL818X_MSR_ADHOC (1 << 2)
#define RTL818X_MSR_INFRA (2 << 2)
u8 CONFIG3;
#define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6)
u8 CONFIG4;
#define RTL818X_CONFIG4_POWEROFF (1 << 6)
#define RTL818X_CONFIG4_VCOOFF (1 << 7)
u8 TESTR;
u8 reserved_9[2];
__le16 PGSELECT;
__le32 ANAPARAM2;
u8 reserved_10[12];
__le16 BEACON_INTERVAL;
__le16 ATIM_WND;
__le16 BEACON_INTERVAL_TIME;
__le16 ATIMTR_INTERVAL;
u8 reserved_11[4];
u8 PHY[4];
__le16 RFPinsOutput;
__le16 RFPinsEnable;
__le16 RFPinsSelect;
__le16 RFPinsInput;
__le32 RF_PARA;
__le32 RF_TIMING;
u8 GP_ENABLE;
u8 GPIO;
u8 reserved_12[10];
u8 TX_AGC_CTL;
#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT (1 << 0)
#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT (1 << 1)
#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT (1 << 2)
u8 TX_GAIN_CCK;
u8 TX_GAIN_OFDM;
u8 TX_ANTENNA;
u8 reserved_13[16];
u8 WPA_CONF;
u8 reserved_14[3];
u8 SIFS;
u8 DIFS;
u8 SLOT;
u8 reserved_15[5];
u8 CW_CONF;
#define RTL818X_CW_CONF_PERPACKET_CW_SHIFT (1 << 0)
#define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT (1 << 1)
u8 CW_VAL;
u8 RATE_FALLBACK;
u8 reserved_16[25];
u8 CONFIG5;
u8 TX_DMA_POLLING;
u8 reserved_17[2];
__le16 CWR;
u8 RETRY_CTR;
u8 reserved_18[5];
__le32 RDSAR;
u8 reserved_19[18];
u16 TALLY_CNT;
u8 TALLY_SEL;
} __attribute__((packed));
static const struct ieee80211_rate rtl818x_rates[] = {
{ .rate = 10,
.val = 0,
.flags = IEEE80211_RATE_CCK },
{ .rate = 20,
.val = 1,
.flags = IEEE80211_RATE_CCK },
{ .rate = 55,
.val = 2,
.flags = IEEE80211_RATE_CCK },
{ .rate = 110,
.val = 3,
.flags = IEEE80211_RATE_CCK },
{ .rate = 60,
.val = 4,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 90,
.val = 5,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 120,
.val = 6,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 180,
.val = 7,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 240,
.val = 8,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 360,
.val = 9,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 480,
.val = 10,
.flags = IEEE80211_RATE_OFDM },
{ .rate = 540,
.val = 11,
.flags = IEEE80211_RATE_OFDM },
};
static const struct ieee80211_channel rtl818x_channels[] = {
{ .chan = 1,
.freq = 2412},
{ .chan = 2,
.freq = 2417},
{ .chan = 3,
.freq = 2422},
{ .chan = 4,
.freq = 2427},
{ .chan = 5,
.freq = 2432},
{ .chan = 6,
.freq = 2437},
{ .chan = 7,
.freq = 2442},
{ .chan = 8,
.freq = 2447},
{ .chan = 9,
.freq = 2452},
{ .chan = 10,
.freq = 2457},
{ .chan = 11,
.freq = 2462},
{ .chan = 12,
.freq = 2467},
{ .chan = 13,
.freq = 2472},
{ .chan = 14,
.freq = 2484}
};
#endif /* RTL818X_H */

View file

@ -3,7 +3,7 @@ obj-$(CONFIG_ZD1211RW) += zd1211rw.o
zd1211rw-objs := zd_chip.o zd_ieee80211.o \
zd_mac.o zd_netdev.o \
zd_rf_al2230.o zd_rf_rf2959.o \
zd_rf_al7230b.o \
zd_rf_al7230b.o zd_rf_uw2453.o \
zd_rf.o zd_usb.o zd_util.o
ifeq ($(CONFIG_ZD1211RW_DEBUG),y)

View file

@ -1253,6 +1253,9 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip,
{
int r;
if (!zd_rf_should_update_pwr_int(&chip->rf))
return 0;
r = update_pwr_int(chip, channel);
if (r)
return r;
@ -1283,7 +1286,7 @@ static int patch_cck_gain(struct zd_chip *chip)
int r;
u32 value;
if (!chip->patch_cck_gain)
if (!chip->patch_cck_gain || !zd_rf_should_patch_cck_gain(&chip->rf))
return 0;
ZD_ASSERT(mutex_is_locked(&chip->mutex));

View file

@ -608,6 +608,9 @@ enum {
#define CR_ZD1211B_TXOP CTL_REG(0x0b20)
#define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28)
/* Used to detect PLL lock */
#define UW2453_INTR_REG ((zd_addr_t)0x85c1)
#define CWIN_SIZE 0x007f043f

View file

@ -52,34 +52,38 @@ const char *zd_rf_name(u8 type)
void zd_rf_init(struct zd_rf *rf)
{
memset(rf, 0, sizeof(*rf));
/* default to update channel integration, as almost all RF's do want
* this */
rf->update_channel_int = 1;
}
void zd_rf_clear(struct zd_rf *rf)
{
if (rf->clear)
rf->clear(rf);
ZD_MEMCLEAR(rf, sizeof(*rf));
}
int zd_rf_init_hw(struct zd_rf *rf, u8 type)
{
int r, t;
int r = 0;
int t;
struct zd_chip *chip = zd_rf_to_chip(rf);
ZD_ASSERT(mutex_is_locked(&chip->mutex));
switch (type) {
case RF2959_RF:
r = zd_rf_init_rf2959(rf);
if (r)
return r;
break;
case AL2230_RF:
r = zd_rf_init_al2230(rf);
if (r)
return r;
break;
case AL7230B_RF:
r = zd_rf_init_al7230b(rf);
if (r)
return r;
break;
case UW2453_RF:
r = zd_rf_init_uw2453(rf);
break;
default:
dev_err(zd_chip_dev(chip),
@ -88,6 +92,9 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type)
return -ENODEV;
}
if (r)
return r;
rf->type = type;
r = zd_chip_lock_phy_regs(chip);

View file

@ -48,12 +48,26 @@ struct zd_rf {
u8 channel;
/* whether channel integration and calibration should be updated
* defaults to 1 (yes) */
u8 update_channel_int:1;
/* whether CR47 should be patched from the EEPROM, if the appropriate
* flag is set in the POD. The vendor driver suggests that this should
* be done for all RF's, but a bug in their code prevents but their
* HW_OverWritePhyRegFromE2P() routine from ever taking effect. */
u8 patch_cck_gain:1;
/* private RF driver data */
void *priv;
/* RF-specific functions */
int (*init_hw)(struct zd_rf *rf);
int (*set_channel)(struct zd_rf *rf, u8 channel);
int (*switch_radio_on)(struct zd_rf *rf);
int (*switch_radio_off)(struct zd_rf *rf);
int (*patch_6m_band_edge)(struct zd_rf *rf, u8 channel);
void (*clear)(struct zd_rf *rf);
};
const char *zd_rf_name(u8 type);
@ -71,10 +85,24 @@ int zd_switch_radio_off(struct zd_rf *rf);
int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
static inline int zd_rf_should_update_pwr_int(struct zd_rf *rf)
{
return rf->update_channel_int;
}
static inline int zd_rf_should_patch_cck_gain(struct zd_rf *rf)
{
return rf->patch_cck_gain;
}
int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
/* Functions for individual RF chips */
int zd_rf_init_rf2959(struct zd_rf *rf);
int zd_rf_init_al2230(struct zd_rf *rf);
int zd_rf_init_al7230b(struct zd_rf *rf);
int zd_rf_init_uw2453(struct zd_rf *rf);
#endif /* _ZD_RF_H */

View file

@ -432,5 +432,6 @@ int zd_rf_init_al2230(struct zd_rf *rf)
rf->switch_radio_on = zd1211_al2230_switch_radio_on;
}
rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
rf->patch_cck_gain = 1;
return 0;
}

View file

@ -483,6 +483,7 @@ int zd_rf_init_al7230b(struct zd_rf *rf)
rf->switch_radio_on = zd1211_al7230b_switch_radio_on;
rf->set_channel = zd1211_al7230b_set_channel;
rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
rf->patch_cck_gain = 1;
}
rf->switch_radio_off = al7230b_switch_radio_off;

View file

@ -0,0 +1,534 @@
/* zd_rf_uw2453.c: Functions for the UW2453 RF controller
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include "zd_rf.h"
#include "zd_usb.h"
#include "zd_chip.h"
/* This RF programming code is based upon the code found in v2.16.0.0 of the
* ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs
* for this RF on their website, so we're able to understand more than
* usual as to what is going on. Thumbs up for Ubec for doing that. */
/* The 3-wire serial interface provides access to 8 write-only registers.
* The data format is a 4 bit register address followed by a 20 bit value. */
#define UW2453_REGWRITE(reg, val) ((((reg) & 0xf) << 20) | ((val) & 0xfffff))
/* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth
* fractional divide ratio) and 3 (VCO config).
*
* We configure the RF to produce an interrupt when the PLL is locked onto
* the configured frequency. During initialization, we run through a variety
* of different VCO configurations on channel 1 until we detect a PLL lock.
* When this happens, we remember which VCO configuration produced the lock
* and use it later. Actually, we use the configuration *after* the one that
* produced the lock, which seems odd, but it works.
*
* If we do not see a PLL lock on any standard VCO config, we fall back on an
* autocal configuration, which has a fixed (as opposed to per-channel) VCO
* config and different synth values from the standard set (divide ratio
* is still shared with the standard set). */
/* The per-channel synth values for all standard VCO configurations. These get
* written to register 1. */
static const u8 uw2453_std_synth[] = {
RF_CHANNEL( 1) = 0x47,
RF_CHANNEL( 2) = 0x47,
RF_CHANNEL( 3) = 0x67,
RF_CHANNEL( 4) = 0x67,
RF_CHANNEL( 5) = 0x67,
RF_CHANNEL( 6) = 0x67,
RF_CHANNEL( 7) = 0x57,
RF_CHANNEL( 8) = 0x57,
RF_CHANNEL( 9) = 0x57,
RF_CHANNEL(10) = 0x57,
RF_CHANNEL(11) = 0x77,
RF_CHANNEL(12) = 0x77,
RF_CHANNEL(13) = 0x77,
RF_CHANNEL(14) = 0x4f,
};
/* This table stores the synthesizer fractional divide ratio for *all* VCO
* configurations (both standard and autocal). These get written to register 2.
*/
static const u16 uw2453_synth_divide[] = {
RF_CHANNEL( 1) = 0x999,
RF_CHANNEL( 2) = 0x99b,
RF_CHANNEL( 3) = 0x998,
RF_CHANNEL( 4) = 0x99a,
RF_CHANNEL( 5) = 0x999,
RF_CHANNEL( 6) = 0x99b,
RF_CHANNEL( 7) = 0x998,
RF_CHANNEL( 8) = 0x99a,
RF_CHANNEL( 9) = 0x999,
RF_CHANNEL(10) = 0x99b,
RF_CHANNEL(11) = 0x998,
RF_CHANNEL(12) = 0x99a,
RF_CHANNEL(13) = 0x999,
RF_CHANNEL(14) = 0xccc,
};
/* Here is the data for all the standard VCO configurations. We shrink our
* table a little by observing that both channels in a consecutive pair share
* the same value. We also observe that the high 4 bits ([0:3] in the specs)
* are all 'Reserved' and are always set to 0x4 - we chop them off in the data
* below. */
#define CHAN_TO_PAIRIDX(a) ((a - 1) / 2)
#define RF_CHANPAIR(a,b) [CHAN_TO_PAIRIDX(a)]
static const u16 uw2453_std_vco_cfg[][7] = {
{ /* table 1 */
RF_CHANPAIR( 1, 2) = 0x664d,
RF_CHANPAIR( 3, 4) = 0x604d,
RF_CHANPAIR( 5, 6) = 0x6675,
RF_CHANPAIR( 7, 8) = 0x6475,
RF_CHANPAIR( 9, 10) = 0x6655,
RF_CHANPAIR(11, 12) = 0x6455,
RF_CHANPAIR(13, 14) = 0x6665,
},
{ /* table 2 */
RF_CHANPAIR( 1, 2) = 0x666d,
RF_CHANPAIR( 3, 4) = 0x606d,
RF_CHANPAIR( 5, 6) = 0x664d,
RF_CHANPAIR( 7, 8) = 0x644d,
RF_CHANPAIR( 9, 10) = 0x6675,
RF_CHANPAIR(11, 12) = 0x6475,
RF_CHANPAIR(13, 14) = 0x6655,
},
{ /* table 3 */
RF_CHANPAIR( 1, 2) = 0x665d,
RF_CHANPAIR( 3, 4) = 0x605d,
RF_CHANPAIR( 5, 6) = 0x666d,
RF_CHANPAIR( 7, 8) = 0x646d,
RF_CHANPAIR( 9, 10) = 0x664d,
RF_CHANPAIR(11, 12) = 0x644d,
RF_CHANPAIR(13, 14) = 0x6675,
},
{ /* table 4 */
RF_CHANPAIR( 1, 2) = 0x667d,
RF_CHANPAIR( 3, 4) = 0x607d,
RF_CHANPAIR( 5, 6) = 0x665d,
RF_CHANPAIR( 7, 8) = 0x645d,
RF_CHANPAIR( 9, 10) = 0x666d,
RF_CHANPAIR(11, 12) = 0x646d,
RF_CHANPAIR(13, 14) = 0x664d,
},
{ /* table 5 */
RF_CHANPAIR( 1, 2) = 0x6643,
RF_CHANPAIR( 3, 4) = 0x6043,
RF_CHANPAIR( 5, 6) = 0x667d,
RF_CHANPAIR( 7, 8) = 0x647d,
RF_CHANPAIR( 9, 10) = 0x665d,
RF_CHANPAIR(11, 12) = 0x645d,
RF_CHANPAIR(13, 14) = 0x666d,
},
{ /* table 6 */
RF_CHANPAIR( 1, 2) = 0x6663,
RF_CHANPAIR( 3, 4) = 0x6063,
RF_CHANPAIR( 5, 6) = 0x6643,
RF_CHANPAIR( 7, 8) = 0x6443,
RF_CHANPAIR( 9, 10) = 0x667d,
RF_CHANPAIR(11, 12) = 0x647d,
RF_CHANPAIR(13, 14) = 0x665d,
},
{ /* table 7 */
RF_CHANPAIR( 1, 2) = 0x6653,
RF_CHANPAIR( 3, 4) = 0x6053,
RF_CHANPAIR( 5, 6) = 0x6663,
RF_CHANPAIR( 7, 8) = 0x6463,
RF_CHANPAIR( 9, 10) = 0x6643,
RF_CHANPAIR(11, 12) = 0x6443,
RF_CHANPAIR(13, 14) = 0x667d,
},
{ /* table 8 */
RF_CHANPAIR( 1, 2) = 0x6673,
RF_CHANPAIR( 3, 4) = 0x6073,
RF_CHANPAIR( 5, 6) = 0x6653,
RF_CHANPAIR( 7, 8) = 0x6453,
RF_CHANPAIR( 9, 10) = 0x6663,
RF_CHANPAIR(11, 12) = 0x6463,
RF_CHANPAIR(13, 14) = 0x6643,
},
{ /* table 9 */
RF_CHANPAIR( 1, 2) = 0x664b,
RF_CHANPAIR( 3, 4) = 0x604b,
RF_CHANPAIR( 5, 6) = 0x6673,
RF_CHANPAIR( 7, 8) = 0x6473,
RF_CHANPAIR( 9, 10) = 0x6653,
RF_CHANPAIR(11, 12) = 0x6453,
RF_CHANPAIR(13, 14) = 0x6663,
},
{ /* table 10 */
RF_CHANPAIR( 1, 2) = 0x666b,
RF_CHANPAIR( 3, 4) = 0x606b,
RF_CHANPAIR( 5, 6) = 0x664b,
RF_CHANPAIR( 7, 8) = 0x644b,
RF_CHANPAIR( 9, 10) = 0x6673,
RF_CHANPAIR(11, 12) = 0x6473,
RF_CHANPAIR(13, 14) = 0x6653,
},
{ /* table 11 */
RF_CHANPAIR( 1, 2) = 0x665b,
RF_CHANPAIR( 3, 4) = 0x605b,
RF_CHANPAIR( 5, 6) = 0x666b,
RF_CHANPAIR( 7, 8) = 0x646b,
RF_CHANPAIR( 9, 10) = 0x664b,
RF_CHANPAIR(11, 12) = 0x644b,
RF_CHANPAIR(13, 14) = 0x6673,
},
};
/* The per-channel synth values for autocal. These get written to register 1. */
static const u16 uw2453_autocal_synth[] = {
RF_CHANNEL( 1) = 0x6847,
RF_CHANNEL( 2) = 0x6847,
RF_CHANNEL( 3) = 0x6867,
RF_CHANNEL( 4) = 0x6867,
RF_CHANNEL( 5) = 0x6867,
RF_CHANNEL( 6) = 0x6867,
RF_CHANNEL( 7) = 0x6857,
RF_CHANNEL( 8) = 0x6857,
RF_CHANNEL( 9) = 0x6857,
RF_CHANNEL(10) = 0x6857,
RF_CHANNEL(11) = 0x6877,
RF_CHANNEL(12) = 0x6877,
RF_CHANNEL(13) = 0x6877,
RF_CHANNEL(14) = 0x684f,
};
/* The VCO configuration for autocal (all channels) */
static const u16 UW2453_AUTOCAL_VCO_CFG = 0x6662;
/* TX gain settings. The array index corresponds to the TX power integration
* values found in the EEPROM. The values get written to register 7. */
static u32 uw2453_txgain[] = {
[0x00] = 0x0e313,
[0x01] = 0x0fb13,
[0x02] = 0x0e093,
[0x03] = 0x0f893,
[0x04] = 0x0ea93,
[0x05] = 0x1f093,
[0x06] = 0x1f493,
[0x07] = 0x1f693,
[0x08] = 0x1f393,
[0x09] = 0x1f35b,
[0x0a] = 0x1e6db,
[0x0b] = 0x1ff3f,
[0x0c] = 0x1ffff,
[0x0d] = 0x361d7,
[0x0e] = 0x37fbf,
[0x0f] = 0x3ff8b,
[0x10] = 0x3ff33,
[0x11] = 0x3fb3f,
[0x12] = 0x3ffff,
};
/* RF-specific structure */
struct uw2453_priv {
/* index into synth/VCO config tables where PLL lock was found
* -1 means autocal */
int config;
};
#define UW2453_PRIV(rf) ((struct uw2453_priv *) (rf)->priv)
static int uw2453_synth_set_channel(struct zd_chip *chip, int channel,
bool autocal)
{
int r;
int idx = channel - 1;
u32 val;
if (autocal)
val = UW2453_REGWRITE(1, uw2453_autocal_synth[idx]);
else
val = UW2453_REGWRITE(1, uw2453_std_synth[idx]);
r = zd_rfwrite_locked(chip, val, RF_RV_BITS);
if (r)
return r;
return zd_rfwrite_locked(chip,
UW2453_REGWRITE(2, uw2453_synth_divide[idx]), RF_RV_BITS);
}
static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value)
{
/* vendor driver always sets these upper bits even though the specs say
* they are reserved */
u32 val = 0x40000 | value;
return zd_rfwrite_locked(chip, UW2453_REGWRITE(3, val), RF_RV_BITS);
}
static int uw2453_init_mode(struct zd_chip *chip)
{
static const u32 rv[] = {
UW2453_REGWRITE(0, 0x25f98), /* enter IDLE mode */
UW2453_REGWRITE(0, 0x25f9a), /* enter CAL_VCO mode */
UW2453_REGWRITE(0, 0x25f94), /* enter RX/TX mode */
UW2453_REGWRITE(0, 0x27fd4), /* power down RSSI circuit */
};
return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
}
static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel)
{
u8 int_value = chip->pwr_int_values[channel - 1];
if (int_value >= ARRAY_SIZE(uw2453_txgain)) {
dev_dbg_f(zd_chip_dev(chip), "can't configure TX gain for "
"int value %x on channel %d\n", int_value, channel);
return 0;
}
return zd_rfwrite_locked(chip,
UW2453_REGWRITE(7, uw2453_txgain[int_value]), RF_RV_BITS);
}
static int uw2453_init_hw(struct zd_rf *rf)
{
int i, r;
int found_config = -1;
u16 intr_status;
struct zd_chip *chip = zd_rf_to_chip(rf);
static const struct zd_ioreq16 ioreqs[] = {
{ CR10, 0x89 }, { CR15, 0x20 },
{ CR17, 0x28 }, /* 6112 no change */
{ CR23, 0x38 }, { CR24, 0x20 }, { CR26, 0x93 },
{ CR27, 0x15 }, { CR28, 0x3e }, { CR29, 0x00 },
{ CR33, 0x28 }, { CR34, 0x30 },
{ CR35, 0x43 }, /* 6112 3e->43 */
{ CR41, 0x24 }, { CR44, 0x32 },
{ CR46, 0x92 }, /* 6112 96->92 */
{ CR47, 0x1e },
{ CR48, 0x04 }, /* 5602 Roger */
{ CR49, 0xfa }, { CR79, 0x58 }, { CR80, 0x30 },
{ CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 },
{ CR91, 0x00 }, { CR92, 0x0a }, { CR98, 0x8d },
{ CR99, 0x28 }, { CR100, 0x02 },
{ CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */
{ CR102, 0x27 },
{ CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 6221 1f->1c */
{ CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */
{ CR109, 0x13 },
{ CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */
{ CR111, 0x13 }, { CR112, 0x1f }, { CR113, 0x27 },
{ CR114, 0x23 }, /* 6221 27->23 */
{ CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */
{ CR116, 0x24 }, /* 6220 1c->24 */
{ CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */
{ CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */
{ CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */
{ CR120, 0x4f },
{ CR121, 0x1f }, /* 6220 4f->1f */
{ CR122, 0xf0 }, { CR123, 0x57 }, { CR125, 0xad },
{ CR126, 0x6c }, { CR127, 0x03 },
{ CR128, 0x14 }, /* 6302 12->11 */
{ CR129, 0x12 }, /* 6301 10->0f */
{ CR130, 0x10 }, { CR137, 0x50 }, { CR138, 0xa8 },
{ CR144, 0xac }, { CR146, 0x20 }, { CR252, 0xff },
{ CR253, 0xff },
};
static const u32 rv[] = {
UW2453_REGWRITE(4, 0x2b), /* configure reciever gain */
UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */
UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */
UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */
/* enter CAL_FIL mode, TX gain set by registers, RX gain set by pins,
* RSSI circuit powered down, reduced RSSI range */
UW2453_REGWRITE(0, 0x25f9c), /* 5d01 cal_fil */
/* synthesizer configuration for channel 1 */
UW2453_REGWRITE(1, 0x47),
UW2453_REGWRITE(2, 0x999),
/* disable manual VCO band selection */
UW2453_REGWRITE(3, 0x7602),
/* enable manual VCO band selection, configure current level */
UW2453_REGWRITE(3, 0x46063),
};
r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
if (r)
return r;
r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
if (r)
return r;
r = uw2453_init_mode(chip);
if (r)
return r;
/* Try all standard VCO configuration settings on channel 1 */
for (i = 0; i < ARRAY_SIZE(uw2453_std_vco_cfg) - 1; i++) {
/* Configure synthesizer for channel 1 */
r = uw2453_synth_set_channel(chip, 1, false);
if (r)
return r;
/* Write VCO config */
r = uw2453_write_vco_cfg(chip, uw2453_std_vco_cfg[i][0]);
if (r)
return r;
/* ack interrupt event */
r = zd_iowrite16_locked(chip, 0x0f, UW2453_INTR_REG);
if (r)
return r;
/* check interrupt status */
r = zd_ioread16_locked(chip, &intr_status, UW2453_INTR_REG);
if (r)
return r;
if (!intr_status & 0xf) {
dev_dbg_f(zd_chip_dev(chip),
"PLL locked on configuration %d\n", i);
found_config = i;
break;
}
}
if (found_config == -1) {
/* autocal */
dev_dbg_f(zd_chip_dev(chip),
"PLL did not lock, using autocal\n");
r = uw2453_synth_set_channel(chip, 1, true);
if (r)
return r;
r = uw2453_write_vco_cfg(chip, UW2453_AUTOCAL_VCO_CFG);
if (r)
return r;
}
/* To match the vendor driver behaviour, we use the configuration after
* the one that produced a lock. */
UW2453_PRIV(rf)->config = found_config + 1;
return zd_iowrite16_locked(chip, 0x06, CR203);
}
static int uw2453_set_channel(struct zd_rf *rf, u8 channel)
{
int r;
u16 vco_cfg;
int config = UW2453_PRIV(rf)->config;
bool autocal = (config == -1);
struct zd_chip *chip = zd_rf_to_chip(rf);
static const struct zd_ioreq16 ioreqs[] = {
{ CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 },
{ CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 },
};
r = uw2453_synth_set_channel(chip, channel, autocal);
if (r)
return r;
if (autocal)
vco_cfg = UW2453_AUTOCAL_VCO_CFG;
else
vco_cfg = uw2453_std_vco_cfg[config][CHAN_TO_PAIRIDX(channel)];
r = uw2453_write_vco_cfg(chip, vco_cfg);
if (r)
return r;
r = uw2453_init_mode(chip);
if (r)
return r;
r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
if (r)
return r;
r = uw2453_set_tx_gain_level(chip, channel);
if (r)
return r;
return zd_iowrite16_locked(chip, 0x06, CR203);
}
static int uw2453_switch_radio_on(struct zd_rf *rf)
{
int r;
struct zd_chip *chip = zd_rf_to_chip(rf);
struct zd_ioreq16 ioreqs[] = {
{ CR11, 0x00 }, { CR251, 0x3f },
};
/* enter RXTX mode */
r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f94), RF_RV_BITS);
if (r)
return r;
if (chip->is_zd1211b)
ioreqs[1].value = 0x7f;
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
}
static int uw2453_switch_radio_off(struct zd_rf *rf)
{
int r;
struct zd_chip *chip = zd_rf_to_chip(rf);
static const struct zd_ioreq16 ioreqs[] = {
{ CR11, 0x04 }, { CR251, 0x2f },
};
/* enter IDLE mode */
/* FIXME: shouldn't we go to SLEEP? sent email to zydas */
r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f90), RF_RV_BITS);
if (r)
return r;
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
}
static void uw2453_clear(struct zd_rf *rf)
{
kfree(rf->priv);
}
int zd_rf_init_uw2453(struct zd_rf *rf)
{
rf->init_hw = uw2453_init_hw;
rf->set_channel = uw2453_set_channel;
rf->switch_radio_on = uw2453_switch_radio_on;
rf->switch_radio_off = uw2453_switch_radio_off;
rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
rf->clear = uw2453_clear;
/* we have our own TX integration code */
rf->update_channel_int = 0;
rf->priv = kmalloc(sizeof(struct uw2453_priv), GFP_KERNEL);
if (rf->priv == NULL)
return -ENOMEM;
return 0;
}

View file

@ -54,6 +54,7 @@ static struct usb_device_id usb_ids[] = {
{ USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
/* ZD1211B */
{ USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },

View file

@ -842,12 +842,16 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05),
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101),
PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),