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 6791 additions and 2681 deletions

View File

@ -0,0 +1,204 @@
The Spidernet Device Driver
===========================
Written by Linas Vepstas <linas@austin.ibm.com>
Version of 7 June 2007
Abstract
========
This document sketches the structure of portions of the spidernet
device driver in the Linux kernel tree. The spidernet is a gigabit
ethernet device built into the Toshiba southbridge commonly used
in the SONY Playstation 3 and the IBM QS20 Cell blade.
The Structure of the RX Ring.
=============================
The receive (RX) ring is a circular linked list of RX descriptors,
together with three pointers into the ring that are used to manage its
contents.
The elements of the ring are called "descriptors" or "descrs"; they
describe the received data. This includes a pointer to a buffer
containing the received data, the buffer size, and various status bits.
There are three primary states that a descriptor can be in: "empty",
"full" and "not-in-use". An "empty" or "ready" descriptor is ready
to receive data from the hardware. A "full" descriptor has data in it,
and is waiting to be emptied and processed by the OS. A "not-in-use"
descriptor is neither empty or full; it is simply not ready. It may
not even have a data buffer in it, or is otherwise unusable.
During normal operation, on device startup, the OS (specifically, the
spidernet device driver) allocates a set of RX descriptors and RX
buffers. These are all marked "empty", ready to receive data. This
ring is handed off to the hardware, which sequentially fills in the
buffers, and marks them "full". The OS follows up, taking the full
buffers, processing them, and re-marking them empty.
This filling and emptying is managed by three pointers, the "head"
and "tail" pointers, managed by the OS, and a hardware current
descriptor pointer (GDACTDPA). The GDACTDPA points at the descr
currently being filled. When this descr is filled, the hardware
marks it full, and advances the GDACTDPA by one. Thus, when there is
flowing RX traffic, every descr behind it should be marked "full",
and everything in front of it should be "empty". If the hardware
discovers that the current descr is not empty, it will signal an
interrupt, and halt processing.
The tail pointer tails or trails the hardware pointer. When the
hardware is ahead, the tail pointer will be pointing at a "full"
descr. The OS will process this descr, and then mark it "not-in-use",
and advance the tail pointer. Thus, when there is flowing RX traffic,
all of the descrs in front of the tail pointer should be "full", and
all of those behind it should be "not-in-use". When RX traffic is not
flowing, then the tail pointer can catch up to the hardware pointer.
The OS will then note that the current tail is "empty", and halt
processing.
The head pointer (somewhat mis-named) follows after the tail pointer.
When traffic is flowing, then the head pointer will be pointing at
a "not-in-use" descr. The OS will perform various housekeeping duties
on this descr. This includes allocating a new data buffer and
dma-mapping it so as to make it visible to the hardware. The OS will
then mark the descr as "empty", ready to receive data. Thus, when there
is flowing RX traffic, everything in front of the head pointer should
be "not-in-use", and everything behind it should be "empty". If no
RX traffic is flowing, then the head pointer can catch up to the tail
pointer, at which point the OS will notice that the head descr is
"empty", and it will halt processing.
Thus, in an idle system, the GDACTDPA, tail and head pointers will
all be pointing at the same descr, which should be "empty". All of the
other descrs in the ring should be "empty" as well.
The show_rx_chain() routine will print out the the locations of the
GDACTDPA, tail and head pointers. It will also summarize the contents
of the ring, starting at the tail pointer, and listing the status
of the descrs that follow.
A typical example of the output, for a nearly idle system, might be
net eth1: Total number of descrs=256
net eth1: Chain tail located at descr=20
net eth1: Chain head is at 20
net eth1: HW curr desc (GDACTDPA) is at 21
net eth1: Have 1 descrs with stat=x40800101
net eth1: HW next desc (GDACNEXTDA) is at 22
net eth1: Last 255 descrs with stat=xa0800000
In the above, the hardware has filled in one descr, number 20. Both
head and tail are pointing at 20, because it has not yet been emptied.
Meanwhile, hw is pointing at 21, which is free.
The "Have nnn decrs" refers to the descr starting at the tail: in this
case, nnn=1 descr, starting at descr 20. The "Last nnn descrs" refers
to all of the rest of the descrs, from the last status change. The "nnn"
is a count of how many descrs have exactly the same status.
The status x4... corresponds to "full" and status xa... corresponds
to "empty". The actual value printed is RXCOMST_A.
In the device driver source code, a different set of names are
used for these same concepts, so that
"empty" == SPIDER_NET_DESCR_CARDOWNED == 0xa
"full" == SPIDER_NET_DESCR_FRAME_END == 0x4
"not in use" == SPIDER_NET_DESCR_NOT_IN_USE == 0xf
The RX RAM full bug/feature
===========================
As long as the OS can empty out the RX buffers at a rate faster than
the hardware can fill them, there is no problem. If, for some reason,
the OS fails to empty the RX ring fast enough, the hardware GDACTDPA
pointer will catch up to the head, notice the not-empty condition,
ad stop. However, RX packets may still continue arriving on the wire.
The spidernet chip can save some limited number of these in local RAM.
When this local ram fills up, the spider chip will issue an interrupt
indicating this (GHIINT0STS will show ERRINT, and the GRMFLLINT bit
will be set in GHIINT1STS). When the RX ram full condition occurs,
a certain bug/feature is triggered that has to be specially handled.
This section describes the special handling for this condition.
When the OS finally has a chance to run, it will empty out the RX ring.
In particular, it will clear the descriptor on which the hardware had
stopped. However, once the hardware has decided that a certain
descriptor is invalid, it will not restart at that descriptor; instead
it will restart at the next descr. This potentially will lead to a
deadlock condition, as the tail pointer will be pointing at this descr,
which, from the OS point of view, is empty; the OS will be waiting for
this descr to be filled. However, the hardware has skipped this descr,
and is filling the next descrs. Since the OS doesn't see this, there
is a potential deadlock, with the OS waiting for one descr to fill,
while the hardware is waiting for a different set of descrs to become
empty.
A call to show_rx_chain() at this point indicates the nature of the
problem. A typical print when the network is hung shows the following:
net eth1: Spider RX RAM full, incoming packets might be discarded!
net eth1: Total number of descrs=256
net eth1: Chain tail located at descr=255
net eth1: Chain head is at 255
net eth1: HW curr desc (GDACTDPA) is at 0
net eth1: Have 1 descrs with stat=xa0800000
net eth1: HW next desc (GDACNEXTDA) is at 1
net eth1: Have 127 descrs with stat=x40800101
net eth1: Have 1 descrs with stat=x40800001
net eth1: Have 126 descrs with stat=x40800101
net eth1: Last 1 descrs with stat=xa0800000
Both the tail and head pointers are pointing at descr 255, which is
marked xa... which is "empty". Thus, from the OS point of view, there
is nothing to be done. In particular, there is the implicit assumption
that everything in front of the "empty" descr must surely also be empty,
as explained in the last section. The OS is waiting for descr 255 to
become non-empty, which, in this case, will never happen.
The HW pointer is at descr 0. This descr is marked 0x4.. or "full".
Since its already full, the hardware can do nothing more, and thus has
halted processing. Notice that descrs 0 through 254 are all marked
"full", while descr 254 and 255 are empty. (The "Last 1 descrs" is
descr 254, since tail was at 255.) Thus, the system is deadlocked,
and there can be no forward progress; the OS thinks there's nothing
to do, and the hardware has nowhere to put incoming data.
This bug/feature is worked around with the spider_net_resync_head_ptr()
routine. When the driver receives RX interrupts, but an examination
of the RX chain seems to show it is empty, then it is probable that
the hardware has skipped a descr or two (sometimes dozens under heavy
network conditions). The spider_net_resync_head_ptr() subroutine will
search the ring for the next full descr, and the driver will resume
operations there. Since this will leave "holes" in the ring, there
is also a spider_net_resync_tail_ptr() that will skip over such holes.
As of this writing, the spider_net_resync() strategy seems to work very
well, even under heavy network loads.
The TX ring
===========
The TX ring uses a low-watermark interrupt scheme to make sure that
the TX queue is appropriately serviced for large packet sizes.
For packet sizes greater than about 1KBytes, the kernel can fill
the TX ring quicker than the device can drain it. Once the ring
is full, the netdev is stopped. When there is room in the ring,
the netdev needs to be reawakened, so that more TX packets are placed
in the ring. The hardware can empty the ring about four times per jiffy,
so its not appropriate to wait for the poll routine to refill, since
the poll routine runs only once per jiffy. The low-watermark mechanism
marks a descr about 1/4th of the way from the bottom of the queue, so
that an interrupt is generated when the descr is processed. This
interrupt wakes up the netdev, which can then refill the queue.
For large packets, this mechanism generates a relatively small number
of interrupts, about 1K/sec. For smaller packets, this will drop to zero
interrupts, as the hardware can empty the queue faster than the kernel
can fill it.
======= END OF DOCUMENT ========

View File

@ -3049,6 +3049,16 @@ S: Maintained
RISCOM8 DRIVER
S: Orphan
RTL818X WIRELESS DRIVER
P: Michael Wu
M: flamingice@sourmilk.net
P: Andrea Merello
M: andreamrl@tiscali.it
L: linux-wireless@vger.kernel.org
W: http://linuxwireless.org/
T: git kernel.org:/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git
S: Maintained
S3 SAVAGE FRAMEBUFFER DRIVER
P: Antonino Daplas
M: adaplas@gmail.com

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 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
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 @@ struct ehea_qp *ehea_create_qp(struct ehea_adapter *adapter,
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 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
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 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
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 <netdev@vger.kernel.org>\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 @@ spider_net_set_multi(struct net_device *netdev)
}
}
/**
* 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 @@ spider_net_init_firmware(struct spider_net_card *card)
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 @@ spider_net_init_firmware(struct spider_net_card *card)
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 @@ static void rx_complete (struct urb *urb)
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 <j@w1.fi>)";
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 <j@w1.fi>)";
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 <j@w1.fi>)";
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 <flamingice@sourmilk.net>");
MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
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),

View File

@ -0,0 +1,72 @@
/*
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 datastructures for 93cx6 chipsets.
Supported chipsets: 93c46 & 93c66.
*/
/*
* EEPROM operation defines.
*/
#define PCI_EEPROM_WIDTH_93C46 6
#define PCI_EEPROM_WIDTH_93C66 8
#define PCI_EEPROM_WIDTH_OPCODE 3
#define PCI_EEPROM_WRITE_OPCODE 0x05
#define PCI_EEPROM_READ_OPCODE 0x06
#define PCI_EEPROM_EWDS_OPCODE 0x10
#define PCI_EEPROM_EWEN_OPCODE 0x13
/**
* struct eeprom_93cx6 - control structure for setting the commands
* for reading the eeprom data.
* @data: private pointer for the driver.
* @register_read(struct eeprom_93cx6 *eeprom): handler to
* read the eeprom register, this function should set all reg_* fields.
* @register_write(struct eeprom_93cx6 *eeprom): handler to
* write to the eeprom register by using all reg_* fields.
* @width: eeprom width, should be one of the PCI_EEPROM_WIDTH_* defines
* @reg_data_in: register field to indicate data input
* @reg_data_out: register field to indicate data output
* @reg_data_clock: register field to set the data clock
* @reg_chip_select: register field to set the chip select
*
* This structure is used for the communication between the driver
* and the eeprom_93cx6 handlers for reading the eeprom.
*/
struct eeprom_93cx6 {
void *data;
void (*register_read)(struct eeprom_93cx6 *eeprom);
void (*register_write)(struct eeprom_93cx6 *eeprom);
int width;
char reg_data_in;
char reg_data_out;
char reg_data_clock;
char reg_chip_select;
};
extern void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom,
const u8 word, u16 *data);
extern void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom,
const u8 word, __le16 *data, const u16 words);

View File

@ -126,4 +126,6 @@
#define MANFID_POSSIO 0x030c
#define PRODID_POSSIO_GCC 0x0003
#define MANFID_NEC 0x0010
#endif /* _LINUX_CISCODE_H */

View File

@ -456,18 +456,13 @@ void
ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
struct ieee80211softmac_network *add_net)
{
struct list_head *list_ptr;
struct ieee80211softmac_network *softmac_net = NULL;
struct ieee80211softmac_network *softmac_net;
list_for_each(list_ptr, &mac->network_list) {
softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
list_for_each_entry(softmac_net, &mac->network_list, list) {
if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN))
break;
else
softmac_net = NULL;
return;
}
if(softmac_net == NULL)
list_add(&(add_net->list), &mac->network_list);
list_add(&(add_net->list), &mac->network_list);
}
/* Add a network to the list, with locking */
@ -506,16 +501,13 @@ struct ieee80211softmac_network *
ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac,
u8 *bssid)
{
struct list_head *list_ptr;
struct ieee80211softmac_network *softmac_net = NULL;
list_for_each(list_ptr, &mac->network_list) {
softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
struct ieee80211softmac_network *softmac_net;
list_for_each_entry(softmac_net, &mac->network_list, list) {
if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN))
break;
else
softmac_net = NULL;
return softmac_net;
}
return softmac_net;
return NULL;
}
/* Get a network from the list by BSSID with locking */
@ -537,11 +529,9 @@ struct ieee80211softmac_network *
ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
struct ieee80211softmac_essid *essid)
{
struct list_head *list_ptr;
struct ieee80211softmac_network *softmac_net = NULL;
struct ieee80211softmac_network *softmac_net;
list_for_each(list_ptr, &mac->network_list) {
softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
list_for_each_entry(softmac_net, &mac->network_list, list) {
if (softmac_net->essid.len == essid->len &&
!memcmp(softmac_net->essid.data, essid->data, essid->len))
return softmac_net;