mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 08:40:53 +07:00
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:
commit
71ba22fa73
204
Documentation/networking/spider_net.txt
Normal file
204
Documentation/networking/spider_net.txt
Normal 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 ========
|
||||
|
10
MAINTAINERS
10
MAINTAINERS
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
241
drivers/misc/eeprom_93cx6.c
Normal 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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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(®s->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
1434
drivers/net/lib82596.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
@ -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---
|
||||
|
@ -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
134
drivers/net/phy/icplus.c
Normal 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);
|
@ -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;
|
||||
|
@ -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
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
185
drivers/net/sni_82596.c
Normal 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);
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
145
drivers/net/wireless/rtl8187.h
Normal file
145
drivers/net/wireless/rtl8187.h
Normal 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 */
|
731
drivers/net/wireless/rtl8187_dev.c
Normal file
731
drivers/net/wireless/rtl8187_dev.c
Normal 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);
|
745
drivers/net/wireless/rtl8187_rtl8225.c
Normal file
745
drivers/net/wireless/rtl8187_rtl8225.c
Normal 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);
|
||||
}
|
44
drivers/net/wireless/rtl8187_rtl8225.h
Normal file
44
drivers/net/wireless/rtl8187_rtl8225.h
Normal 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 */
|
226
drivers/net/wireless/rtl818x.h
Normal file
226
drivers/net/wireless/rtl818x.h
Normal 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 */
|
@ -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)
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
534
drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
Normal file
534
drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
Normal 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;
|
||||
}
|
||||
|
@ -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 },
|
||||
|
@ -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),
|
||||
|
72
include/linux/eeprom_93cx6.h
Normal file
72
include/linux/eeprom_93cx6.h
Normal 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);
|
@ -126,4 +126,6 @@
|
||||
#define MANFID_POSSIO 0x030c
|
||||
#define PRODID_POSSIO_GCC 0x0003
|
||||
|
||||
#define MANFID_NEC 0x0010
|
||||
|
||||
#endif /* _LINUX_CISCODE_H */
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user