dect
/
linux-2.6
Archived
13
0
Fork 0

Merge branch 'master'

This commit is contained in:
Steven Whitehouse 2006-07-06 08:57:15 -04:00
commit 71ec63c5d6
103 changed files with 9131 additions and 1775 deletions

View File

@ -2057,9 +2057,10 @@ L: linux-kernel@vger.kernel.org
S: Maintained
NI5010 NETWORK DRIVER
P: Jan-Pascal van Best and Andreas Mohr
M: Jan-Pascal van Best <jvbest@qv3pluto.leidenuniv.nl>
M: Andreas Mohr <100.30936@germany.net>
P: Jan-Pascal van Best
M: janpascal@vanbest.org
P: Andreas Mohr
M: andi@lisas.de
L: netdev@vger.kernel.org
S: Maintained

View File

@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 17
EXTRAVERSION =
SUBLEVEL = 18
EXTRAVERSION = -rc1
NAME=Crazed Snow-Weasel
# *DOCUMENTATION*
@ -528,7 +528,7 @@ export MODLIB
ifdef INSTALL_MOD_STRIP
ifeq ($(INSTALL_MOD_STRIP),1)
mod_strip_cmd = $STRIP) --strip-debug
mod_strip_cmd = $(STRIP) --strip-debug
else
mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
endif # INSTALL_MOD_STRIP=1

View File

@ -107,3 +107,48 @@ void __init at91rm9200_map_io(void)
iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
}
/*
* The default interrupt priority levels (0 = lowest, 7 = highest).
*/
static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
7, /* Advanced Interrupt Controller (FIQ) */
7, /* System Peripherals */
0, /* Parallel IO Controller A */
0, /* Parallel IO Controller B */
0, /* Parallel IO Controller C */
0, /* Parallel IO Controller D */
6, /* USART 0 */
6, /* USART 1 */
6, /* USART 2 */
6, /* USART 3 */
0, /* Multimedia Card Interface */
4, /* USB Device Port */
0, /* Two-Wire Interface */
6, /* Serial Peripheral Interface */
5, /* Serial Synchronous Controller 0 */
5, /* Serial Synchronous Controller 1 */
5, /* Serial Synchronous Controller 2 */
0, /* Timer Counter 0 */
0, /* Timer Counter 1 */
0, /* Timer Counter 2 */
0, /* Timer Counter 3 */
0, /* Timer Counter 4 */
0, /* Timer Counter 5 */
3, /* USB Host port */
3, /* Ethernet MAC */
0, /* Advanced Interrupt Controller (IRQ0) */
0, /* Advanced Interrupt Controller (IRQ1) */
0, /* Advanced Interrupt Controller (IRQ2) */
0, /* Advanced Interrupt Controller (IRQ3) */
0, /* Advanced Interrupt Controller (IRQ4) */
0, /* Advanced Interrupt Controller (IRQ5) */
0 /* Advanced Interrupt Controller (IRQ6) */
};
void __init at91rm9200_init_irq(unsigned int priority[NR_AIC_IRQS])
{
if (!priority)
priority = at91rm9200_default_irq_priority;
at91_aic_init(priority);
}

View File

@ -8,13 +8,19 @@
* published by the Free Software Foundation.
*/
void at91_gpio_irq_setup(unsigned banks);
/* Interrupts */
extern void __init at91rm9200_init_irq(unsigned int priority[]);
extern void __init at91_aic_init(unsigned int priority[]);
extern void __init at91_gpio_irq_setup(unsigned banks);
/* Timer */
struct sys_timer;
extern struct sys_timer at91rm9200_timer;
/* Memory Map */
extern void __init at91rm9200_map_io(void);
/* Clocks */
extern int __init at91_clock_init(unsigned long main_clock);
struct device;
extern void __init at91_clock_associate(const char *id, struct device *dev, const char *func);

View File

@ -36,58 +36,20 @@
#include "generic.h"
/*
* The default interrupt priority levels (0 = lowest, 7 = highest).
*/
static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
7, /* Advanced Interrupt Controller */
7, /* System Peripheral */
0, /* Parallel IO Controller A */
0, /* Parallel IO Controller B */
0, /* Parallel IO Controller C */
0, /* Parallel IO Controller D */
6, /* USART 0 */
6, /* USART 1 */
6, /* USART 2 */
6, /* USART 3 */
0, /* Multimedia Card Interface */
4, /* USB Device Port */
0, /* Two-Wire Interface */
6, /* Serial Peripheral Interface */
5, /* Serial Synchronous Controller */
5, /* Serial Synchronous Controller */
5, /* Serial Synchronous Controller */
0, /* Timer Counter 0 */
0, /* Timer Counter 1 */
0, /* Timer Counter 2 */
0, /* Timer Counter 3 */
0, /* Timer Counter 4 */
0, /* Timer Counter 5 */
3, /* USB Host port */
3, /* Ethernet MAC */
0, /* Advanced Interrupt Controller */
0, /* Advanced Interrupt Controller */
0, /* Advanced Interrupt Controller */
0, /* Advanced Interrupt Controller */
0, /* Advanced Interrupt Controller */
0, /* Advanced Interrupt Controller */
0 /* Advanced Interrupt Controller */
};
static void at91rm9200_mask_irq(unsigned int irq)
static void at91_aic_mask_irq(unsigned int irq)
{
/* Disable interrupt on AIC */
at91_sys_write(AT91_AIC_IDCR, 1 << irq);
}
static void at91rm9200_unmask_irq(unsigned int irq)
static void at91_aic_unmask_irq(unsigned int irq)
{
/* Enable interrupt on AIC */
at91_sys_write(AT91_AIC_IECR, 1 << irq);
}
static int at91rm9200_irq_type(unsigned irq, unsigned type)
static int at91_aic_set_type(unsigned irq, unsigned type)
{
unsigned int smr, srctype;
@ -122,7 +84,7 @@ static int at91rm9200_irq_type(unsigned irq, unsigned type)
static u32 wakeups;
static u32 backups;
static int at91rm9200_irq_set_wake(unsigned irq, unsigned value)
static int at91_aic_set_wake(unsigned irq, unsigned value)
{
if (unlikely(irq >= 32))
return -EINVAL;
@ -149,28 +111,24 @@ void at91_irq_resume(void)
}
#else
#define at91rm9200_irq_set_wake NULL
#define at91_aic_set_wake NULL
#endif
static struct irqchip at91rm9200_irq_chip = {
.ack = at91rm9200_mask_irq,
.mask = at91rm9200_mask_irq,
.unmask = at91rm9200_unmask_irq,
.set_type = at91rm9200_irq_type,
.set_wake = at91rm9200_irq_set_wake,
static struct irqchip at91_aic_chip = {
.ack = at91_aic_mask_irq,
.mask = at91_aic_mask_irq,
.unmask = at91_aic_unmask_irq,
.set_type = at91_aic_set_type,
.set_wake = at91_aic_set_wake,
};
/*
* Initialize the AIC interrupt controller.
*/
void __init at91rm9200_init_irq(unsigned int priority[NR_AIC_IRQS])
void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
{
unsigned int i;
/* No priority list specified for this board -> use defaults */
if (priority == NULL)
priority = at91rm9200_default_irq_priority;
/*
* The IVR is used by macro get_irqnr_and_base to read and verify.
* The irq number is NR_AIC_IRQS when a spurious interrupt has occurred.
@ -178,10 +136,10 @@ void __init at91rm9200_init_irq(unsigned int priority[NR_AIC_IRQS])
for (i = 0; i < NR_AIC_IRQS; i++) {
/* Put irq number in Source Vector Register: */
at91_sys_write(AT91_AIC_SVR(i), i);
/* Store the Source Mode Register as defined in table above */
/* Active Low interrupt, with the specified priority */
at91_sys_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
set_irq_chip(i, &at91rm9200_irq_chip);
set_irq_chip(i, &at91_aic_chip);
set_irq_handler(i, do_level_IRQ);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);

View File

@ -27,7 +27,6 @@
#include <linux/spi/spi.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
@ -36,7 +35,6 @@
#include <asm/system.h>
#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>

View File

@ -23,7 +23,6 @@
#include <linux/clk.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/dma.h>
#include <asm/dma-mapping.h>

View File

@ -22,8 +22,8 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/irq.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
@ -96,26 +96,24 @@ void __init pnx4008_init_irq(void)
{
unsigned int i;
/* configure and enable IRQ 0,1,30,31 (cascade interrupts) mask all others */
/* configure IRQ's */
for (i = 0; i < NR_IRQS; i++) {
set_irq_flags(i, IRQF_VALID);
set_irq_chip(i, &pnx4008_irq_chip);
pnx4008_set_irq_type(i, pnx4008_irq_type[i]);
}
/* configure and enable IRQ 0,1,30,31 (cascade interrupts) */
pnx4008_set_irq_type(SUB1_IRQ_N, pnx4008_irq_type[SUB1_IRQ_N]);
pnx4008_set_irq_type(SUB2_IRQ_N, pnx4008_irq_type[SUB2_IRQ_N]);
pnx4008_set_irq_type(SUB1_FIQ_N, pnx4008_irq_type[SUB1_FIQ_N]);
pnx4008_set_irq_type(SUB2_FIQ_N, pnx4008_irq_type[SUB2_FIQ_N]);
/* mask all others */
__raw_writel((1 << SUB2_FIQ_N) | (1 << SUB1_FIQ_N) |
(1 << SUB2_IRQ_N) | (1 << SUB1_IRQ_N),
INTC_ER(MAIN_BASE_INT));
__raw_writel(0, INTC_ER(SIC1_BASE_INT));
__raw_writel(0, INTC_ER(SIC2_BASE_INT));
/* configure all other IRQ's */
for (i = 0; i < NR_IRQS; i++) {
if (i == SUB2_FIQ_N || i == SUB1_FIQ_N ||
i == SUB2_IRQ_N || i == SUB1_IRQ_N)
continue;
set_irq_flags(i, IRQF_VALID);
set_irq_chip(i, &pnx4008_irq_chip);
pnx4008_set_irq_type(i, pnx4008_irq_type[i]);
}
}

View File

@ -20,17 +20,15 @@
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/irq.h>
#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/leds.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <linux/time.h>
#include <linux/timex.h>
#include <asm/errno.h>
/*! Note: all timers are UPCOUNTING */

View File

@ -405,20 +405,22 @@ static void mpic_unmask_irq(unsigned int irq)
unsigned int loops = 100000;
struct mpic *mpic = mpic_from_irq(irq);
unsigned int src = mpic_irq_to_hw(irq);
unsigned long flags;
DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
spin_lock_irqsave(&mpic_lock, flags);
mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
~MPIC_VECPRI_MASK);
/* make sure mask gets to controller before we return to user */
do {
if (!loops--) {
printk(KERN_ERR "mpic_enable_irq timeout\n");
break;
}
} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
spin_unlock_irqrestore(&mpic_lock, flags);
}
static void mpic_mask_irq(unsigned int irq)
@ -426,9 +428,11 @@ static void mpic_mask_irq(unsigned int irq)
unsigned int loops = 100000;
struct mpic *mpic = mpic_from_irq(irq);
unsigned int src = mpic_irq_to_hw(irq);
unsigned long flags;
DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
spin_lock_irqsave(&mpic_lock, flags);
mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
MPIC_VECPRI_MASK);
@ -440,6 +444,7 @@ static void mpic_mask_irq(unsigned int irq)
break;
}
} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
spin_unlock_irqrestore(&mpic_lock, flags);
}
static void mpic_end_irq(unsigned int irq)
@ -624,9 +629,10 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
struct irq_desc *desc = get_irq_desc(virq);
struct irq_chip *chip;
struct mpic *mpic = h->host_data;
unsigned int vecpri = MPIC_VECPRI_SENSE_LEVEL |
u32 v, vecpri = MPIC_VECPRI_SENSE_LEVEL |
MPIC_VECPRI_POLARITY_NEGATIVE;
int level;
unsigned long iflags;
pr_debug("mpic: map virq %d, hwirq 0x%lx, flags: 0x%x\n",
virq, hw, flags);
@ -668,11 +674,21 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
}
#endif
/* Reconfigure irq */
vecpri |= MPIC_VECPRI_MASK | hw | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri);
/* Reconfigure irq. We must preserve the mask bit as we can be called
* while the interrupt is still active (This may change in the future
* but for now, it is the case).
*/
spin_lock_irqsave(&mpic_lock, iflags);
v = mpic_irq_read(hw, MPIC_IRQ_VECTOR_PRI);
vecpri = (v &
~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK)) |
vecpri;
if (vecpri != v)
mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri);
spin_unlock_irqrestore(&mpic_lock, iflags);
pr_debug("mpic: mapping as IRQ\n");
pr_debug("mpic: mapping as IRQ, vecpri = 0x%08x (was 0x%08x)\n",
vecpri, v);
set_irq_chip_data(virq, mpic);
set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq);
@ -904,8 +920,8 @@ void __init mpic_init(struct mpic *mpic)
/* do senses munging */
if (mpic->senses && i < mpic->senses_count)
vecpri = mpic_flags_to_vecpri(mpic->senses[i],
&level);
vecpri |= mpic_flags_to_vecpri(mpic->senses[i],
&level);
else
vecpri |= MPIC_VECPRI_SENSE_LEVEL;
@ -955,14 +971,17 @@ void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
void __init mpic_set_serial_int(struct mpic *mpic, int enable)
{
unsigned long flags;
u32 v;
spin_lock_irqsave(&mpic_lock, flags);
v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1);
if (enable)
v |= MPIC_GREG_GLOBAL_CONF_1_SIE;
else
v &= ~MPIC_GREG_GLOBAL_CONF_1_SIE;
mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v);
spin_unlock_irqrestore(&mpic_lock, flags);
}
void mpic_irq_set_priority(unsigned int irq, unsigned int pri)

View File

@ -1032,7 +1032,9 @@ static void sun4v_vdev_irq_trans_init(struct device_node *dp)
static void irq_trans_init(struct device_node *dp)
{
const char *model;
#ifdef CONFIG_PCI
int i;
#endif
model = of_get_property(dp, "model", NULL);
if (!model)

View File

@ -124,11 +124,6 @@ EXPORT_SYMBOL(__write_lock);
EXPORT_SYMBOL(__write_unlock);
EXPORT_SYMBOL(__write_trylock);
#if defined(CONFIG_MCOUNT)
extern void _mcount(void);
EXPORT_SYMBOL(_mcount);
#endif
/* CPU online map and active count. */
EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL(phys_cpu_present_map);
@ -136,6 +131,11 @@ EXPORT_SYMBOL(phys_cpu_present_map);
EXPORT_SYMBOL(smp_call_function);
#endif /* CONFIG_SMP */
#if defined(CONFIG_MCOUNT)
extern void _mcount(void);
EXPORT_SYMBOL(_mcount);
#endif
EXPORT_SYMBOL(sparc64_get_clock_tick);
/* semaphores */

View File

@ -788,12 +788,15 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id
if (!regs)
return -ENOMEM;
#ifdef CONFIG_PCI
if (!strcmp(model, "ds1287") ||
!strcmp(model, "m5819") ||
!strcmp(model, "m5819p") ||
!strcmp(model, "m5823")) {
ds1287_regs = (unsigned long) regs;
} else if (model[5] == '0' && model[6] == '2') {
} else
#endif
if (model[5] == '0' && model[6] == '2') {
mstk48t02_regs = regs;
} else if(model[5] == '0' && model[6] == '8') {
mstk48t08_regs = regs;

View File

@ -1836,9 +1836,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev < 0x20) {
printk(KERN_ERR PFX "pci dev %s (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n",
pci_name(pdev), pdev->vendor, pdev->device, pci_rev);
printk(KERN_ERR PFX "Try the \"8139too\" driver instead.\n");
dev_err(&pdev->dev,
"This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n",
pdev->vendor, pdev->device, pci_rev);
dev_err(&pdev->dev, "Try the \"8139too\" driver instead.\n");
return -ENODEV;
}
@ -1876,14 +1877,13 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
pciaddr = pci_resource_start(pdev, 1);
if (!pciaddr) {
rc = -EIO;
printk(KERN_ERR PFX "no MMIO resource for pci dev %s\n",
pci_name(pdev));
dev_err(&pdev->dev, "no MMIO resource\n");
goto err_out_res;
}
if (pci_resource_len(pdev, 1) < CP_REGS_SIZE) {
rc = -EIO;
printk(KERN_ERR PFX "MMIO resource (%llx) too small on pci dev %s\n",
(unsigned long long)pci_resource_len(pdev, 1), pci_name(pdev));
dev_err(&pdev->dev, "MMIO resource (%llx) too small\n",
(unsigned long long)pci_resource_len(pdev, 1));
goto err_out_res;
}
@ -1897,14 +1897,15 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
printk(KERN_ERR PFX "No usable DMA configuration, "
"aborting.\n");
dev_err(&pdev->dev,
"No usable DMA configuration, aborting.\n");
goto err_out_res;
}
rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
printk(KERN_ERR PFX "No usable consistent DMA configuration, "
"aborting.\n");
dev_err(&pdev->dev,
"No usable consistent DMA configuration, "
"aborting.\n");
goto err_out_res;
}
}
@ -1915,9 +1916,9 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
regs = ioremap(pciaddr, CP_REGS_SIZE);
if (!regs) {
rc = -EIO;
printk(KERN_ERR PFX "Cannot map PCI MMIO (%llx@%llx) on pci dev %s\n",
(unsigned long long)pci_resource_len(pdev, 1),
(unsigned long long)pciaddr, pci_name(pdev));
dev_err(&pdev->dev, "Cannot map PCI MMIO (%lx@%lx)\n",
(unsigned long long)pci_resource_len(pdev, 1),
(unsigned long long)pciaddr);
goto err_out_res;
}
dev->base_addr = (unsigned long) regs;
@ -1986,7 +1987,8 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
/* enable busmastering and memory-write-invalidate */
pci_set_master(pdev);
if (cp->wol_enabled) cp_set_d3_state (cp);
if (cp->wol_enabled)
cp_set_d3_state (cp);
return 0;
@ -2011,7 +2013,8 @@ static void cp_remove_one (struct pci_dev *pdev)
BUG_ON(!dev);
unregister_netdev(dev);
iounmap(cp->regs);
if (cp->wol_enabled) pci_set_power_state (pdev, PCI_D0);
if (cp->wol_enabled)
pci_set_power_state (pdev, PCI_D0);
pci_release_regions(pdev);
pci_clear_mwi(pdev);
pci_disable_device(pdev);

View File

@ -768,7 +768,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
/* dev and priv zeroed in alloc_etherdev */
dev = alloc_etherdev (sizeof (*tp));
if (dev == NULL) {
printk (KERN_ERR PFX "%s: Unable to alloc new net device\n", pci_name(pdev));
dev_err(&pdev->dev, "Unable to alloc new net device\n");
return -ENOMEM;
}
SET_MODULE_OWNER(dev);
@ -800,31 +800,31 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
#ifdef USE_IO_OPS
/* make sure PCI base addr 0 is PIO */
if (!(pio_flags & IORESOURCE_IO)) {
printk (KERN_ERR PFX "%s: region #0 not a PIO resource, aborting\n", pci_name(pdev));
dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n");
rc = -ENODEV;
goto err_out;
}
/* check for weird/broken PCI region reporting */
if (pio_len < RTL_MIN_IO_SIZE) {
printk (KERN_ERR PFX "%s: Invalid PCI I/O region size(s), aborting\n", pci_name(pdev));
dev_err(&pdev->dev, "Invalid PCI I/O region size(s), aborting\n");
rc = -ENODEV;
goto err_out;
}
#else
/* make sure PCI base addr 1 is MMIO */
if (!(mmio_flags & IORESOURCE_MEM)) {
printk (KERN_ERR PFX "%s: region #1 not an MMIO resource, aborting\n", pci_name(pdev));
dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
rc = -ENODEV;
goto err_out;
}
if (mmio_len < RTL_MIN_IO_SIZE) {
printk (KERN_ERR PFX "%s: Invalid PCI mem region size(s), aborting\n", pci_name(pdev));
dev_err(&pdev->dev, "Invalid PCI mem region size(s), aborting\n");
rc = -ENODEV;
goto err_out;
}
#endif
rc = pci_request_regions (pdev, "8139too");
rc = pci_request_regions (pdev, DRV_NAME);
if (rc)
goto err_out;
disable_dev_on_err = 1;
@ -835,7 +835,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
#ifdef USE_IO_OPS
ioaddr = ioport_map(pio_start, pio_len);
if (!ioaddr) {
printk (KERN_ERR PFX "%s: cannot map PIO, aborting\n", pci_name(pdev));
dev_err(&pdev->dev, "cannot map PIO, aborting\n");
rc = -EIO;
goto err_out;
}
@ -846,7 +846,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
/* ioremap MMIO region */
ioaddr = pci_iomap(pdev, 1, 0);
if (ioaddr == NULL) {
printk (KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pci_name(pdev));
dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
rc = -EIO;
goto err_out;
}
@ -860,8 +860,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
/* check for missing/broken hardware */
if (RTL_R32 (TxConfig) == 0xFFFFFFFF) {
printk (KERN_ERR PFX "%s: Chip not responding, ignoring board\n",
pci_name(pdev));
dev_err(&pdev->dev, "Chip not responding, ignoring board\n");
rc = -EIO;
goto err_out;
}
@ -875,9 +874,10 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
}
/* if unknown chip, assume array element #0, original RTL-8139 in this case */
printk (KERN_DEBUG PFX "%s: unknown chip version, assuming RTL-8139\n",
pci_name(pdev));
printk (KERN_DEBUG PFX "%s: TxConfig = 0x%lx\n", pci_name(pdev), RTL_R32 (TxConfig));
dev_printk (KERN_DEBUG, &pdev->dev,
"unknown chip version, assuming RTL-8139\n");
dev_printk (KERN_DEBUG, &pdev->dev,
"TxConfig = 0x%lx\n", RTL_R32 (TxConfig));
tp->chipset = 0;
match:
@ -954,9 +954,11 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) {
printk(KERN_INFO PFX "pci dev %s (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n",
pci_name(pdev), pdev->vendor, pdev->device, pci_rev);
printk(KERN_INFO PFX "Use the \"8139cp\" driver for improved performance and stability.\n");
dev_info(&pdev->dev,
"This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n",
pdev->vendor, pdev->device, pci_rev);
dev_info(&pdev->dev,
"Use the \"8139cp\" driver for improved performance and stability.\n");
}
i = rtl8139_init_board (pdev, &dev);

View File

@ -2120,13 +2120,14 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
err = pci_enable_device(pdev);
if (err) {
printk(KERN_ERR PFX "Cannot enable PCI device, "
dev_err(&pdev->dev, "Cannot enable PCI device, "
"aborting.\n");
return err;
}
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
printk(KERN_ERR PFX "Cannot find proper PCI device "
dev_err(&pdev->dev,
"Cannot find proper PCI device "
"base address, aborting.\n");
err = -ENODEV;
goto err_out_disable_pdev;
@ -2134,8 +2135,8 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
err = pci_request_regions(pdev, DRV_MODULE_NAME);
if (err) {
printk(KERN_ERR PFX "Cannot obtain PCI resources, "
"aborting.\n");
dev_err(&pdev->dev,
"Cannot obtain PCI resources, aborting.\n");
goto err_out_disable_pdev;
}
@ -2143,15 +2144,13 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
err = pci_set_dma_mask(pdev, (u64) B44_DMA_MASK);
if (err) {
printk(KERN_ERR PFX "No usable DMA configuration, "
"aborting.\n");
dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n");
goto err_out_free_res;
}
err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
if (err) {
printk(KERN_ERR PFX "No usable DMA configuration, "
"aborting.\n");
dev_err(&pdev->dev, "No usable DMA configuration, aborting.\n");
goto err_out_free_res;
}
@ -2160,7 +2159,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
dev = alloc_etherdev(sizeof(*bp));
if (!dev) {
printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
dev_err(&pdev->dev, "Etherdev alloc failed, aborting.\n");
err = -ENOMEM;
goto err_out_free_res;
}
@ -2181,8 +2180,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
bp->regs = ioremap(b44reg_base, b44reg_len);
if (bp->regs == 0UL) {
printk(KERN_ERR PFX "Cannot map device registers, "
"aborting.\n");
dev_err(&pdev->dev, "Cannot map device registers, aborting.\n");
err = -ENOMEM;
goto err_out_free_dev;
}
@ -2212,8 +2210,8 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
err = b44_get_invariants(bp);
if (err) {
printk(KERN_ERR PFX "Problem fetching invariants of chip, "
"aborting.\n");
dev_err(&pdev->dev,
"Problem fetching invariants of chip, aborting.\n");
goto err_out_iounmap;
}
@ -2233,8 +2231,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
err = register_netdev(dev);
if (err) {
printk(KERN_ERR PFX "Cannot register net device, "
"aborting.\n");
dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
goto err_out_iounmap;
}

View File

@ -5575,20 +5575,20 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
/* enable device (incl. PCI PM wakeup), and bus-mastering */
rc = pci_enable_device(pdev);
if (rc) {
printk(KERN_ERR PFX "Cannot enable PCI device, aborting.");
dev_err(&pdev->dev, "Cannot enable PCI device, aborting.");
goto err_out;
}
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
printk(KERN_ERR PFX "Cannot find PCI device base address, "
"aborting.\n");
dev_err(&pdev->dev,
"Cannot find PCI device base address, aborting.\n");
rc = -ENODEV;
goto err_out_disable;
}
rc = pci_request_regions(pdev, DRV_MODULE_NAME);
if (rc) {
printk(KERN_ERR PFX "Cannot obtain PCI resources, aborting.\n");
dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting.\n");
goto err_out_disable;
}
@ -5596,15 +5596,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
if (bp->pm_cap == 0) {
printk(KERN_ERR PFX "Cannot find power management capability, "
"aborting.\n");
dev_err(&pdev->dev,
"Cannot find power management capability, aborting.\n");
rc = -EIO;
goto err_out_release;
}
bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
if (bp->pcix_cap == 0) {
printk(KERN_ERR PFX "Cannot find PCIX capability, aborting.\n");
dev_err(&pdev->dev, "Cannot find PCIX capability, aborting.\n");
rc = -EIO;
goto err_out_release;
}
@ -5612,14 +5612,14 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
bp->flags |= USING_DAC_FLAG;
if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) != 0) {
printk(KERN_ERR PFX "pci_set_consistent_dma_mask "
"failed, aborting.\n");
dev_err(&pdev->dev,
"pci_set_consistent_dma_mask failed, aborting.\n");
rc = -EIO;
goto err_out_release;
}
}
else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) {
printk(KERN_ERR PFX "System does not support DMA, aborting.\n");
dev_err(&pdev->dev, "System does not support DMA, aborting.\n");
rc = -EIO;
goto err_out_release;
}
@ -5639,7 +5639,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
bp->regview = ioremap_nocache(dev->base_addr, mem_len);
if (!bp->regview) {
printk(KERN_ERR PFX "Cannot map register space, aborting.\n");
dev_err(&pdev->dev, "Cannot map register space, aborting.\n");
rc = -ENOMEM;
goto err_out_release;
}
@ -5711,8 +5711,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) &&
!(bp->flags & PCIX_FLAG)) {
printk(KERN_ERR PFX "5706 A1 can only be used in a PCIX bus, "
"aborting.\n");
dev_err(&pdev->dev,
"5706 A1 can only be used in a PCIX bus, aborting.\n");
goto err_out_unmap;
}
@ -5733,7 +5733,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
BNX2_DEV_INFO_SIGNATURE_MAGIC) {
printk(KERN_ERR PFX "Firmware not running, aborting.\n");
dev_err(&pdev->dev, "Firmware not running, aborting.\n");
rc = -ENODEV;
goto err_out_unmap;
}
@ -5895,7 +5895,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
#endif
if ((rc = register_netdev(dev))) {
printk(KERN_ERR PFX "Cannot register net device\n");
dev_err(&pdev->dev, "Cannot register net device\n");
if (bp->regview)
iounmap(bp->regview);
pci_release_regions(pdev);

View File

@ -4887,13 +4887,12 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
err = pci_enable_device(pdev);
if (err) {
printk(KERN_ERR PFX "Cannot enable PCI device, "
"aborting.\n");
dev_err(&pdev->dev, "Cannot enable PCI device, aborting.\n");
return err;
}
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
printk(KERN_ERR PFX "Cannot find proper PCI device "
dev_err(&pdev->dev, "Cannot find proper PCI device "
"base address, aborting.\n");
err = -ENODEV;
goto err_out_disable_pdev;
@ -4901,7 +4900,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
dev = alloc_etherdev(sizeof(*cp));
if (!dev) {
printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
dev_err(&pdev->dev, "Etherdev alloc failed, aborting.\n");
err = -ENOMEM;
goto err_out_disable_pdev;
}
@ -4910,8 +4909,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
err = pci_request_regions(pdev, dev->name);
if (err) {
printk(KERN_ERR PFX "Cannot obtain PCI resources, "
"aborting.\n");
dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting.\n");
goto err_out_free_netdev;
}
pci_set_master(pdev);
@ -4941,7 +4939,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
if (pci_write_config_byte(pdev,
PCI_CACHE_LINE_SIZE,
cas_cacheline_size)) {
printk(KERN_ERR PFX "Could not set PCI cache "
dev_err(&pdev->dev, "Could not set PCI cache "
"line size\n");
goto err_write_cacheline;
}
@ -4955,7 +4953,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
err = pci_set_consistent_dma_mask(pdev,
DMA_64BIT_MASK);
if (err < 0) {
printk(KERN_ERR PFX "Unable to obtain 64-bit DMA "
dev_err(&pdev->dev, "Unable to obtain 64-bit DMA "
"for consistent allocations\n");
goto err_out_free_res;
}
@ -4963,7 +4961,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
} else {
err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (err) {
printk(KERN_ERR PFX "No usable DMA configuration, "
dev_err(&pdev->dev, "No usable DMA configuration, "
"aborting.\n");
goto err_out_free_res;
}
@ -5023,8 +5021,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
/* give us access to cassini registers */
cp->regs = pci_iomap(pdev, 0, casreg_len);
if (cp->regs == 0UL) {
printk(KERN_ERR PFX "Cannot map device registers, "
"aborting.\n");
dev_err(&pdev->dev, "Cannot map device registers, aborting.\n");
goto err_out_free_res;
}
cp->casreg_len = casreg_len;
@ -5040,8 +5037,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
pci_alloc_consistent(pdev, sizeof(struct cas_init_block),
&cp->block_dvma);
if (!cp->init_block) {
printk(KERN_ERR PFX "Cannot allocate init block, "
"aborting.\n");
dev_err(&pdev->dev, "Cannot allocate init block, aborting.\n");
goto err_out_iounmap;
}
@ -5085,8 +5081,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
dev->features |= NETIF_F_HIGHDMA;
if (register_netdev(dev)) {
printk(KERN_ERR PFX "Cannot register net device, "
"aborting.\n");
dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
goto err_out_free_consistent;
}

View File

@ -703,8 +703,8 @@ static irqreturn_t lance_dma_merr_int(const int irq, void *dev_id,
return IRQ_HANDLED;
}
static irqreturn_t
lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t lance_interrupt(const int irq, void *dev_id,
struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
struct lance_private *lp = netdev_priv(dev);
@ -1253,7 +1253,7 @@ static int __init dec_lance_init(const int type, const int slot)
return 0;
err_out_free_dev:
kfree(dev);
free_netdev(dev);
err_out:
return ret;
@ -1299,6 +1299,7 @@ static void __exit dec_lance_cleanup(void)
while (root_lance_dev) {
struct net_device *dev = root_lance_dev;
struct lance_private *lp = netdev_priv(dev);
unregister_netdev(dev);
#ifdef CONFIG_TC
if (lp->slot >= 0)

View File

@ -9,49 +9,10 @@
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/
/*
Rev Date Description
==========================================================================
0.01 2001/05/03 Created DL2000-based linux driver
0.02 2001/05/21 Added VLAN and hardware checksum support.
1.00 2001/06/26 Added jumbo frame support.
1.01 2001/08/21 Added two parameters, rx_coalesce and rx_timeout.
1.02 2001/10/08 Supported fiber media.
Added flow control parameters.
1.03 2001/10/12 Changed the default media to 1000mbps_fd for
the fiber devices.
1.04 2001/11/08 Fixed Tx stopped when tx very busy.
1.05 2001/11/22 Fixed Tx stopped when unidirectional tx busy.
1.06 2001/12/13 Fixed disconnect bug at 10Mbps mode.
Fixed tx_full flag incorrect.
Added tx_coalesce paramter.
1.07 2002/01/03 Fixed miscount of RX frame error.
1.08 2002/01/17 Fixed the multicast bug.
1.09 2002/03/07 Move rx-poll-now to re-fill loop.
Added rio_timer() to watch rx buffers.
1.10 2002/04/16 Fixed miscount of carrier error.
1.11 2002/05/23 Added ISR schedule scheme
Fixed miscount of rx frame error for DGE-550SX.
Fixed VLAN bug.
1.12 2002/06/13 Lock tx_coalesce=1 on 10/100Mbps mode.
1.13 2002/08/13 1. Fix disconnection (many tx:carrier/rx:frame
errs) with some mainboards.
2. Use definition "DRV_NAME" "DRV_VERSION"
"DRV_RELDATE" for flexibility.
1.14 2002/08/14 Support ethtool.
1.15 2002/08/27 Changed the default media to Auto-Negotiation
for the fiber devices.
1.16 2002/09/04 More power down time for fiber devices auto-
negotiation.
Fix disconnect bug after ifup and ifdown.
1.17 2002/10/03 Fix RMON statistics overflow.
Always use I/O mapping to access eeprom,
avoid system freezing with some chipsets.
*/
#define DRV_NAME "D-Link DL2000-based linux driver"
#define DRV_VERSION "v1.17b"
#define DRV_RELDATE "2006/03/10"
#define DRV_VERSION "v1.18"
#define DRV_RELDATE "2006/06/27"
#include "dl2k.h"
#include <linux/dma-mapping.h>

View File

@ -555,12 +555,12 @@ static int __devinit eepro100_init_one (struct pci_dev *pdev,
if (!request_region(pci_resource_start(pdev, 1),
pci_resource_len(pdev, 1), "eepro100")) {
printk (KERN_ERR "eepro100: cannot reserve I/O ports\n");
dev_err(&pdev->dev, "eepro100: cannot reserve I/O ports\n");
goto err_out_none;
}
if (!request_mem_region(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0), "eepro100")) {
printk (KERN_ERR "eepro100: cannot reserve MMIO region\n");
dev_err(&pdev->dev, "eepro100: cannot reserve MMIO region\n");
goto err_out_free_pio_region;
}
@ -573,7 +573,7 @@ static int __devinit eepro100_init_one (struct pci_dev *pdev,
ioaddr = pci_iomap(pdev, pci_bar, 0);
if (!ioaddr) {
printk (KERN_ERR "eepro100: cannot remap IO\n");
dev_err(&pdev->dev, "eepro100: cannot remap IO\n");
goto err_out_free_mmio_region;
}

View File

@ -19,62 +19,15 @@
Information and updates available at
http://www.scyld.com/network/epic100.html
[this link no longer provides anything useful -jgarzik]
---------------------------------------------------------------------
Linux kernel-specific changes:
LK1.1.2 (jgarzik):
* Merge becker version 1.09 (4/08/2000)
LK1.1.3:
* Major bugfix to 1.09 driver (Francis Romieu)
LK1.1.4 (jgarzik):
* Merge becker test version 1.09 (5/29/2000)
LK1.1.5:
* Fix locking (jgarzik)
* Limit 83c175 probe to ethernet-class PCI devices (rgooch)
LK1.1.6:
* Merge becker version 1.11
* Move pci_enable_device before any PCI BAR len checks
LK1.1.7:
* { fill me in }
LK1.1.8:
* ethtool driver info support (jgarzik)
LK1.1.9:
* ethtool media get/set support (jgarzik)
LK1.1.10:
* revert MII transceiver init change (jgarzik)
LK1.1.11:
* implement ETHTOOL_[GS]SET, _NWAY_RST, _[GS]MSGLVL, _GLINK (jgarzik)
* replace some MII-related magic numbers with constants
LK1.1.12:
* fix power-up sequence
LK1.1.13:
* revert version 1.1.12, power-up sequence "fix"
LK1.1.14 (Kryzsztof Halasa):
* fix spurious bad initializations
* pound phy a la SMSC's app note on the subject
AC1.1.14ac
* fix power up/down for ethtool that broke in 1.11
*/
#define DRV_NAME "epic100"
#define DRV_VERSION "1.11+LK1.1.14+AC1.1.14"
#define DRV_RELDATE "June 2, 2004"
#define DRV_VERSION "2.0"
#define DRV_RELDATE "June 27, 2006"
/* The user-configurable values.
These may be modified when a driver module is loaded.*/
@ -204,19 +157,15 @@ typedef enum {
struct epic_chip_info {
const char *name;
int io_size; /* Needed for I/O region check or ioremap(). */
int drv_flags; /* Driver use, intended as capability flags. */
};
/* indexed by chip_t */
static const struct epic_chip_info pci_id_tbl[] = {
{ "SMSC EPIC/100 83c170",
EPIC_TOTAL_SIZE, TYPE2_INTR | NO_MII | MII_PWRDWN },
{ "SMSC EPIC/100 83c170",
EPIC_TOTAL_SIZE, TYPE2_INTR },
{ "SMSC EPIC/C 83c175",
EPIC_TOTAL_SIZE, TYPE2_INTR | MII_PWRDWN },
{ "SMSC EPIC/100 83c170", TYPE2_INTR | NO_MII | MII_PWRDWN },
{ "SMSC EPIC/100 83c170", TYPE2_INTR },
{ "SMSC EPIC/C 83c175", TYPE2_INTR | MII_PWRDWN },
};
@ -385,8 +334,8 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
goto out;
irq = pdev->irq;
if (pci_resource_len(pdev, 0) < pci_id_tbl[chip_idx].io_size) {
printk (KERN_ERR "card %d: no PCI region space\n", card_idx);
if (pci_resource_len(pdev, 0) < EPIC_TOTAL_SIZE) {
dev_err(&pdev->dev, "no PCI region space\n");
ret = -ENODEV;
goto err_out_disable;
}
@ -401,7 +350,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
dev = alloc_etherdev(sizeof (*ep));
if (!dev) {
printk (KERN_ERR "card %d: no memory for eth device\n", card_idx);
dev_err(&pdev->dev, "no memory for eth device\n");
goto err_out_free_res;
}
SET_MODULE_OWNER(dev);
@ -413,7 +362,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
ioaddr = pci_resource_start (pdev, 1);
ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1));
if (!ioaddr) {
printk (KERN_ERR DRV_NAME " %d: ioremap failed\n", card_idx);
dev_err(&pdev->dev, "ioremap failed\n");
goto err_out_free_netdev;
}
#endif
@ -473,8 +422,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
((u16 *)dev->dev_addr)[i] = le16_to_cpu(inw(ioaddr + LAN0 + i*4));
if (debug > 2) {
printk(KERN_DEBUG DRV_NAME "(%s): EEPROM contents\n",
pci_name(pdev));
dev_printk(KERN_DEBUG, &pdev->dev, "EEPROM contents:\n");
for (i = 0; i < 64; i++)
printk(" %4.4x%s", read_eeprom(ioaddr, i),
i % 16 == 15 ? "\n" : "");
@ -496,21 +444,23 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
int mii_status = mdio_read(dev, phy, MII_BMSR);
if (mii_status != 0xffff && mii_status != 0x0000) {
ep->phys[phy_idx++] = phy;
printk(KERN_INFO DRV_NAME "(%s): MII transceiver #%d control "
"%4.4x status %4.4x.\n",
pci_name(pdev), phy, mdio_read(dev, phy, 0), mii_status);
dev_info(&pdev->dev,
"MII transceiver #%d control "
"%4.4x status %4.4x.\n",
phy, mdio_read(dev, phy, 0), mii_status);
}
}
ep->mii_phy_cnt = phy_idx;
if (phy_idx != 0) {
phy = ep->phys[0];
ep->mii.advertising = mdio_read(dev, phy, MII_ADVERTISE);
printk(KERN_INFO DRV_NAME "(%s): Autonegotiation advertising %4.4x link "
dev_info(&pdev->dev,
"Autonegotiation advertising %4.4x link "
"partner %4.4x.\n",
pci_name(pdev), ep->mii.advertising, mdio_read(dev, phy, 5));
ep->mii.advertising, mdio_read(dev, phy, 5));
} else if ( ! (ep->chip_flags & NO_MII)) {
printk(KERN_WARNING DRV_NAME "(%s): ***WARNING***: No MII transceiver found!\n",
pci_name(pdev));
dev_warn(&pdev->dev,
"***WARNING***: No MII transceiver found!\n");
/* Use the known PHY address of the EPII. */
ep->phys[0] = 3;
}
@ -525,8 +475,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
/* The lower four bits are the media type. */
if (duplex) {
ep->mii.force_media = ep->mii.full_duplex = 1;
printk(KERN_INFO DRV_NAME "(%s): Forced full duplex operation requested.\n",
pci_name(pdev));
dev_info(&pdev->dev, "Forced full duplex requested.\n");
}
dev->if_port = ep->default_port = option;

View File

@ -124,7 +124,9 @@ MODULE_PARM_DESC(multicast_filter_limit, "fealnx maximum number of filtered mult
MODULE_PARM_DESC(options, "fealnx: Bits 0-3: media type, bit 17: full duplex");
MODULE_PARM_DESC(full_duplex, "fealnx full duplex setting(s) (1)");
#define MIN_REGION_SIZE 136
enum {
MIN_REGION_SIZE = 136,
};
/* A chip capabilities table, matching the entries in pci_tbl[] above. */
enum chip_capability_flags {
@ -146,14 +148,13 @@ enum phy_type_flags {
struct chip_info {
char *chip_name;
int io_size;
int flags;
};
static const struct chip_info skel_netdrv_tbl[] = {
{"100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR},
{"100/10M Ethernet PCI Adapter", 136, HAS_CHIP_XCVR},
{"1000/100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR},
static const struct chip_info skel_netdrv_tbl[] __devinitdata = {
{ "100/10M Ethernet PCI Adapter", HAS_MII_XCVR },
{ "100/10M Ethernet PCI Adapter", HAS_CHIP_XCVR },
{ "1000/100/10M Ethernet PCI Adapter", HAS_MII_XCVR },
};
/* Offsets to the Command and Status Registers. */
@ -504,13 +505,14 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
len = pci_resource_len(pdev, bar);
if (len < MIN_REGION_SIZE) {
printk(KERN_ERR "%s: region size %ld too small, aborting\n",
boardname, len);
dev_err(&pdev->dev,
"region size %ld too small, aborting\n", len);
return -ENODEV;
}
i = pci_request_regions(pdev, boardname);
if (i) return i;
if (i)
return i;
irq = pdev->irq;
@ -576,9 +578,9 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
if (mii_status != 0xffff && mii_status != 0x0000) {
np->phys[phy_idx++] = phy;
printk(KERN_INFO
"%s: MII PHY found at address %d, status "
"0x%4.4x.\n", dev->name, phy, mii_status);
dev_info(&pdev->dev,
"MII PHY found at address %d, status "
"0x%4.4x.\n", phy, mii_status);
/* get phy type */
{
unsigned int data;
@ -601,10 +603,10 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
}
np->mii_cnt = phy_idx;
if (phy_idx == 0) {
printk(KERN_WARNING "%s: MII PHY not found -- this device may "
"not operate correctly.\n", dev->name);
}
if (phy_idx == 0)
dev_warn(&pdev->dev,
"MII PHY not found -- this device may "
"not operate correctly.\n");
} else {
np->phys[0] = 32;
/* 89/6/23 add, (begin) */
@ -630,7 +632,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
np->mii.full_duplex = full_duplex[card_idx];
if (np->mii.full_duplex) {
printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
dev_info(&pdev->dev, "Media type forced to Full Duplex.\n");
/* 89/6/13 add, (begin) */
// if (np->PHYType==MarvellPHY)
if ((np->PHYType == MarvellPHY) || (np->PHYType == LevelOnePHY)) {

View File

@ -699,7 +699,6 @@ static int __init gt96100_probe1(struct pci_dev *pci, int port_num)
memset(gp, 0, sizeof(*gp)); // clear it
gp->port_num = port_num;
gp->io_size = GT96100_ETH_IO_SIZE;
gp->port_offset = port_num * GT96100_ETH_IO_SIZE;
gp->phy_addr = phy_addr;
gp->chip_rev = chip_rev;
@ -1531,7 +1530,7 @@ static void gt96100_cleanup_module(void)
+ sizeof(gt96100_td_t) * TX_RING_SIZE,
gp->rx_ring);
free_netdev(gtif->dev);
release_region(gtif->iobase, gp->io_size);
release_region(gtif->iobase, GT96100_ETH_IO_SIZE);
}
}
}

View File

@ -331,7 +331,6 @@ struct gt96100_private {
mib_counters_t mib;
struct net_device_stats stats;
int io_size;
int port_num; // 0 or 1
int chip_rev;
u32 port_offset;
@ -340,7 +339,6 @@ struct gt96100_private {
u32 last_psr; // last value of the port status register
int options; /* User-settable misc. driver options. */
int drv_flags;
struct timer_list timer;
spinlock_t lock; /* Serialise access to device */
};

View File

@ -20,22 +20,15 @@
Support and updates available at
http://www.scyld.com/network/hamachi.html
[link no longer provides useful info -jgarzik]
or
http://www.parl.clemson.edu/~keithu/hamachi.html
Linux kernel changelog:
LK1.0.1:
- fix lack of pci_dev<->dev association
- ethtool support (jgarzik)
*/
#define DRV_NAME "hamachi"
#define DRV_VERSION "1.01+LK1.0.1"
#define DRV_RELDATE "5/18/2001"
#define DRV_VERSION "2.0"
#define DRV_RELDATE "June 27, 2006"
/* A few user-configurable values. */
@ -608,7 +601,8 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
pci_set_master(pdev);
i = pci_request_regions(pdev, DRV_NAME);
if (i) return i;
if (i)
return i;
irq = pdev->irq;
ioaddr = ioremap(base, 0x400);

View File

@ -188,7 +188,6 @@ struct myri10ge_priv {
int vendor_specific_offset;
u32 devctl;
u16 msi_flags;
u32 pm_state[16];
u32 read_dma;
u32 write_dma;
u32 read_write_dma;
@ -1289,6 +1288,7 @@ static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = {
"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
"tx_heartbeat_errors", "tx_window_errors",
/* device-specific stats */
"tx_boundary", "WC", "irq", "MSI",
"read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs",
"serial_number", "tx_pkt_start", "tx_pkt_done",
"tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt",
@ -1327,6 +1327,10 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++)
data[i] = ((unsigned long *)&mgp->stats)[i];
data[i++] = (unsigned int)mgp->tx.boundary;
data[i++] = (unsigned int)(mgp->mtrr >= 0);
data[i++] = (unsigned int)mgp->pdev->irq;
data[i++] = (unsigned int)mgp->msi_enabled;
data[i++] = (unsigned int)mgp->read_dma;
data[i++] = (unsigned int)mgp->write_dma;
data[i++] = (unsigned int)mgp->read_write_dma;
@ -2197,8 +2201,6 @@ static int myri10ge_change_mtu(struct net_device *dev, int new_mtu)
* any other device, except if forced with myri10ge_ecrc_enable > 1.
*/
#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_PCIE 0x005d
static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
{
struct pci_dev *bridge = mgp->pdev->bus->self;
@ -2737,11 +2739,10 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_err(&pdev->dev, "register_netdev failed: %d\n", status);
goto abort_with_irq;
}
printk(KERN_INFO "myri10ge: %s: %s IRQ %d, tx bndry %d, fw %s, WC %s\n",
netdev->name, (mgp->msi_enabled ? "MSI" : "xPIC"),
pdev->irq, mgp->tx.boundary, mgp->fw_name,
(mgp->mtrr >= 0 ? "Enabled" : "Disabled"));
dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n",
(mgp->msi_enabled ? "MSI" : "xPIC"),
pdev->irq, mgp->tx.boundary, mgp->fw_name,
(mgp->mtrr >= 0 ? "Enabled" : "Disabled"));
return 0;

View File

@ -20,120 +20,9 @@
Support information and updates available at
http://www.scyld.com/network/netsemi.html
[link no longer provides useful info -jgarzik]
Linux kernel modifications:
Version 1.0.1:
- Spinlock fixes
- Bug fixes and better intr performance (Tjeerd)
Version 1.0.2:
- Now reads correct MAC address from eeprom
Version 1.0.3:
- Eliminate redundant priv->tx_full flag
- Call netif_start_queue from dev->tx_timeout
- wmb() in start_tx() to flush data
- Update Tx locking
- Clean up PCI enable (davej)
Version 1.0.4:
- Merge Donald Becker's natsemi.c version 1.07
Version 1.0.5:
- { fill me in }
Version 1.0.6:
* ethtool support (jgarzik)
* Proper initialization of the card (which sometimes
fails to occur and leaves the card in a non-functional
state). (uzi)
* Some documented register settings to optimize some
of the 100Mbit autodetection circuitry in rev C cards. (uzi)
* Polling of the PHY intr for stuff like link state
change and auto- negotiation to finally work properly. (uzi)
* One-liner removal of a duplicate declaration of
netdev_error(). (uzi)
Version 1.0.7: (Manfred Spraul)
* pci dma
* SMP locking update
* full reset added into tx_timeout
* correct multicast hash generation (both big and little endian)
[copied from a natsemi driver version
from Myrio Corporation, Greg Smith]
* suspend/resume
version 1.0.8 (Tim Hockin <thockin@sun.com>)
* ETHTOOL_* support
* Wake on lan support (Erik Gilling)
* MXDMA fixes for serverworks
* EEPROM reload
version 1.0.9 (Manfred Spraul)
* Main change: fix lack of synchronize
netif_close/netif_suspend against a last interrupt
or packet.
* do not enable superflous interrupts (e.g. the
drivers relies on TxDone - TxIntr not needed)
* wait that the hardware has really stopped in close
and suspend.
* workaround for the (at least) gcc-2.95.1 compiler
problem. Also simplifies the code a bit.
* disable_irq() in tx_timeout - needed to protect
against rx interrupts.
* stop the nic before switching into silent rx mode
for wol (required according to docu).
version 1.0.10:
* use long for ee_addr (various)
* print pointers properly (DaveM)
* include asm/irq.h (?)
version 1.0.11:
* check and reset if PHY errors appear (Adrian Sun)
* WoL cleanup (Tim Hockin)
* Magic number cleanup (Tim Hockin)
* Don't reload EEPROM on every reset (Tim Hockin)
* Save and restore EEPROM state across reset (Tim Hockin)
* MDIO Cleanup (Tim Hockin)
* Reformat register offsets/bits (jgarzik)
version 1.0.12:
* ETHTOOL_* further support (Tim Hockin)
version 1.0.13:
* ETHTOOL_[G]EEPROM support (Tim Hockin)
version 1.0.13:
* crc cleanup (Matt Domsch <Matt_Domsch@dell.com>)
version 1.0.14:
* Cleanup some messages and autoneg in ethtool (Tim Hockin)
version 1.0.15:
* Get rid of cable_magic flag
* use new (National provided) solution for cable magic issue
version 1.0.16:
* call netdev_rx() for RxErrors (Manfred Spraul)
* formatting and cleanups
* change options and full_duplex arrays to be zero
initialized
* enable only the WoL and PHY interrupts in wol mode
version 1.0.17:
* only do cable_magic on 83815 and early 83816 (Tim Hockin)
* create a function for rx refill (Manfred Spraul)
* combine drain_ring and init_ring (Manfred Spraul)
* oom handling (Manfred Spraul)
* hands_off instead of playing with netif_device_{de,a}ttach
(Manfred Spraul)
* be sure to write the MAC back to the chip (Manfred Spraul)
* lengthen EEPROM timeout, and always warn about timeouts
(Manfred Spraul)
* comments update (Manfred)
* do the right thing on a phy-reset (Manfred and Tim)
TODO:
* big endian support with CFG:BEM instead of cpu_to_le32
*/
@ -165,8 +54,8 @@
#include <asm/uaccess.h>
#define DRV_NAME "natsemi"
#define DRV_VERSION "1.07+LK1.0.17"
#define DRV_RELDATE "Sep 27, 2002"
#define DRV_VERSION "2.0"
#define DRV_RELDATE "June 27, 2006"
#define RX_OFFSET 2

View File

@ -231,12 +231,12 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
irq = pdev->irq;
if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_IO) == 0)) {
printk (KERN_ERR PFX "no I/O resource at PCI BAR #0\n");
dev_err(&pdev->dev, "no I/O resource at PCI BAR #0\n");
return -ENODEV;
}
if (request_region (ioaddr, NE_IO_EXTENT, DRV_NAME) == NULL) {
printk (KERN_ERR PFX "I/O resource 0x%x @ 0x%lx busy\n",
dev_err(&pdev->dev, "I/O resource 0x%x @ 0x%lx busy\n",
NE_IO_EXTENT, ioaddr);
return -EBUSY;
}
@ -263,7 +263,7 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
/* Allocate net_device, dev->priv; fill in 8390 specific dev fields. */
dev = alloc_ei_netdev();
if (!dev) {
printk (KERN_ERR PFX "cannot allocate ethernet device\n");
dev_err(&pdev->dev, "cannot allocate ethernet device\n");
goto err_out_free_res;
}
SET_MODULE_OWNER(dev);
@ -281,7 +281,8 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
while ((inb(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
/* Limit wait: '2' avoids jiffy roll-over. */
if (jiffies - reset_start_time > 2) {
printk(KERN_ERR PFX "Card failure (no reset ack).\n");
dev_err(&pdev->dev,
"Card failure (no reset ack).\n");
goto err_out_free_netdev;
}

View File

@ -1,17 +1,12 @@
/* ni5010.c: A network driver for the MiCom-Interlan NI5010 ethercard.
*
* Copyright 1996,1997 Jan-Pascal van Best and Andreas Mohr.
* Copyright 1996,1997,2006 Jan-Pascal van Best and Andreas Mohr.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* The authors may be reached as:
* jvbest@wi.leidenuniv.nl a.mohr@mailto.de
* or by snail mail as
* Jan-Pascal van Best Andreas Mohr
* Klikspaanweg 58-4 Stauferstr. 6
* 2324 LZ Leiden D-71272 Renningen
* The Netherlands Germany
* janpascal@vanbest.org andi@lisas.de
*
* Sources:
* Donald Becker's "skeleton.c"
@ -27,8 +22,9 @@
* 970503 v0.93: Fixed auto-irq failure on warm reboot (JB)
* 970623 v1.00: First kernel version (AM)
* 970814 v1.01: Added detection of onboard receive buffer size (AM)
* 060611 v1.02: slight cleanup: email addresses, driver modernization.
* Bugs:
* - None known...
* - not SMP-safe (no locking of I/O accesses)
* - Note that you have to patch ifconfig for the new /proc/net/dev
* format. It gives incorrect stats otherwise.
*
@ -39,7 +35,7 @@
* Complete merge with Andreas' driver
* Implement ring buffers (Is this useful? You can't squeeze
* too many packet in a 2k buffer!)
* Implement DMA (Again, is this useful? Some docs says DMA is
* Implement DMA (Again, is this useful? Some docs say DMA is
* slower than programmed I/O)
*
* Compile with:
@ -47,7 +43,7 @@
* -DMODULE -c ni5010.c
*
* Insert with e.g.:
* insmod ni5010.o io=0x300 irq=5
* insmod ni5010.ko io=0x300 irq=5
*/
#include <linux/module.h>
@ -69,15 +65,15 @@
#include "ni5010.h"
static const char *boardname = "NI5010";
static char *version =
"ni5010.c: v1.00 06/23/97 Jan-Pascal van Best and Andreas Mohr\n";
static const char boardname[] = "NI5010";
static char version[] __initdata =
"ni5010.c: v1.02 20060611 Jan-Pascal van Best and Andreas Mohr\n";
/* bufsize_rcv == 0 means autoprobing */
static unsigned int bufsize_rcv;
#define jumpered_interrupts /* IRQ line jumpered on board */
#undef jumpered_dma /* No DMA used */
#define JUMPERED_INTERRUPTS /* IRQ line jumpered on board */
#undef JUMPERED_DMA /* No DMA used */
#undef FULL_IODETECT /* Only detect in portlist */
#ifndef FULL_IODETECT
@ -281,7 +277,7 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
PRINTK2((KERN_DEBUG "%s: I/O #4 passed!\n", dev->name));
#ifdef jumpered_interrupts
#ifdef JUMPERED_INTERRUPTS
if (dev->irq == 0xff)
;
else if (dev->irq < 2) {
@ -305,7 +301,7 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
} else if (dev->irq == 2) {
dev->irq = 9;
}
#endif /* jumpered_irq */
#endif /* JUMPERED_INTERRUPTS */
PRINTK2((KERN_DEBUG "%s: I/O #9 passed!\n", dev->name));
/* DMA is not supported (yet?), so no use detecting it */
@ -334,7 +330,7 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
outw(0, IE_GP); /* Point GP at start of packet */
outb(0, IE_RBUF); /* set buffer byte 0 to 0 again */
}
printk("// bufsize rcv/xmt=%d/%d\n", bufsize_rcv, NI5010_BUFSIZE);
printk("-> bufsize rcv/xmt=%d/%d\n", bufsize_rcv, NI5010_BUFSIZE);
memset(dev->priv, 0, sizeof(struct ni5010_local));
dev->open = ni5010_open;
@ -354,11 +350,9 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
outb(0xff, EDLC_XCLR); /* Kill all pending xmt interrupts */
printk(KERN_INFO "%s: NI5010 found at 0x%x, using IRQ %d", dev->name, ioaddr, dev->irq);
if (dev->dma) printk(" & DMA %d", dev->dma);
if (dev->dma)
printk(" & DMA %d", dev->dma);
printk(".\n");
printk(KERN_INFO "Join the NI5010 driver development team!\n");
printk(KERN_INFO "Mail to a.mohr@mailto.de or jvbest@wi.leidenuniv.nl\n");
return 0;
out:
release_region(dev->base_addr, NI5010_IO_EXTENT);
@ -371,7 +365,7 @@ out:
*
* This routine should set everything up anew at each open, even
* registers that "should" only need to be set once at boot, so that
* there is non-reboot way to recover if something goes wrong.
* there is a non-reboot way to recover if something goes wrong.
*/
static int ni5010_open(struct net_device *dev)
@ -390,13 +384,13 @@ static int ni5010_open(struct net_device *dev)
* Always allocate the DMA channel after the IRQ,
* and clean up on failure.
*/
#ifdef jumpered_dma
#ifdef JUMPERED_DMA
if (request_dma(dev->dma, cardname)) {
printk(KERN_WARNING "%s: Cannot get dma %#2x\n", dev->name, dev->dma);
free_irq(dev->irq, NULL);
return -EAGAIN;
}
#endif /* jumpered_dma */
#endif /* JUMPERED_DMA */
PRINTK3((KERN_DEBUG "%s: passed open() #2\n", dev->name));
/* Reset the hardware here. Don't forget to set the station address. */
@ -633,7 +627,7 @@ static int ni5010_close(struct net_device *dev)
int ioaddr = dev->base_addr;
PRINTK2((KERN_DEBUG "%s: entering ni5010_close\n", dev->name));
#ifdef jumpered_interrupts
#ifdef JUMPERED_INTERRUPTS
free_irq(dev->irq, NULL);
#endif
/* Put card in held-RESET state */
@ -771,7 +765,7 @@ module_param(irq, int, 0);
MODULE_PARM_DESC(io, "ni5010 I/O base address");
MODULE_PARM_DESC(irq, "ni5010 IRQ number");
int init_module(void)
static int __init ni5010_init_module(void)
{
PRINTK2((KERN_DEBUG "%s: entering init_module\n", boardname));
/*
@ -792,13 +786,15 @@ int init_module(void)
return 0;
}
void cleanup_module(void)
static void __exit ni5010_cleanup_module(void)
{
PRINTK2((KERN_DEBUG "%s: entering cleanup_module\n", boardname));
unregister_netdev(dev_ni5010);
release_region(dev_ni5010->base_addr, NI5010_IO_EXTENT);
free_netdev(dev_ni5010);
}
module_init(ni5010_init_module);
module_exit(ni5010_cleanup_module);
#endif /* MODULE */
MODULE_LICENSE("GPL");

View File

@ -803,7 +803,7 @@ static int ns83820_setup_rx(struct net_device *ndev)
writel(dev->IMR_cache, dev->base + IMR);
writel(1, dev->base + IER);
spin_unlock_irq(&dev->misc_lock);
spin_unlock(&dev->misc_lock);
kick_rx(ndev);
@ -1012,8 +1012,6 @@ static void do_tx_done(struct net_device *ndev)
struct ns83820 *dev = PRIV(ndev);
u32 cmdsts, tx_done_idx, *desc;
spin_lock_irq(&dev->tx_lock);
dprintk("do_tx_done(%p)\n", ndev);
tx_done_idx = dev->tx_done_idx;
desc = dev->tx_descs + (tx_done_idx * DESC_SIZE);
@ -1069,7 +1067,6 @@ static void do_tx_done(struct net_device *ndev)
netif_start_queue(ndev);
netif_wake_queue(ndev);
}
spin_unlock_irq(&dev->tx_lock);
}
static void ns83820_cleanup_tx(struct ns83820 *dev)
@ -1281,11 +1278,13 @@ static struct ethtool_ops ops = {
.get_link = ns83820_get_link
};
/* this function is called in irq context from the ISR */
static void ns83820_mib_isr(struct ns83820 *dev)
{
spin_lock(&dev->misc_lock);
unsigned long flags;
spin_lock_irqsave(&dev->misc_lock, flags);
ns83820_update_stats(dev);
spin_unlock(&dev->misc_lock);
spin_unlock_irqrestore(&dev->misc_lock, flags);
}
static void ns83820_do_isr(struct net_device *ndev, u32 isr);
@ -1307,6 +1306,8 @@ static irqreturn_t ns83820_irq(int foo, void *data, struct pt_regs *regs)
static void ns83820_do_isr(struct net_device *ndev, u32 isr)
{
struct ns83820 *dev = PRIV(ndev);
unsigned long flags;
#ifdef DEBUG
if (isr & ~(ISR_PHY | ISR_RXDESC | ISR_RXEARLY | ISR_RXOK | ISR_RXERR | ISR_TXIDLE | ISR_TXOK | ISR_TXDESC))
Dprintk("odd isr? 0x%08x\n", isr);
@ -1321,10 +1322,10 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr)
if ((ISR_RXDESC | ISR_RXOK) & isr) {
prefetch(dev->rx_info.next_rx_desc);
spin_lock_irq(&dev->misc_lock);
spin_lock_irqsave(&dev->misc_lock, flags);
dev->IMR_cache &= ~(ISR_RXDESC | ISR_RXOK);
writel(dev->IMR_cache, dev->base + IMR);
spin_unlock_irq(&dev->misc_lock);
spin_unlock_irqrestore(&dev->misc_lock, flags);
tasklet_schedule(&dev->rx_tasklet);
//rx_irq(ndev);
@ -1370,16 +1371,18 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr)
* work has accumulated
*/
if ((ISR_TXDESC | ISR_TXIDLE | ISR_TXOK | ISR_TXERR) & isr) {
spin_lock_irqsave(&dev->tx_lock, flags);
do_tx_done(ndev);
spin_unlock_irqrestore(&dev->tx_lock, flags);
/* Disable TxOk if there are no outstanding tx packets.
*/
if ((dev->tx_done_idx == dev->tx_free_idx) &&
(dev->IMR_cache & ISR_TXOK)) {
spin_lock_irq(&dev->misc_lock);
spin_lock_irqsave(&dev->misc_lock, flags);
dev->IMR_cache &= ~ISR_TXOK;
writel(dev->IMR_cache, dev->base + IMR);
spin_unlock_irq(&dev->misc_lock);
spin_unlock_irqrestore(&dev->misc_lock, flags);
}
}
@ -1390,10 +1393,10 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr)
* nature are expected, we must enable TxOk.
*/
if ((ISR_TXIDLE & isr) && (dev->tx_done_idx != dev->tx_free_idx)) {
spin_lock_irq(&dev->misc_lock);
spin_lock_irqsave(&dev->misc_lock, flags);
dev->IMR_cache |= ISR_TXOK;
writel(dev->IMR_cache, dev->base + IMR);
spin_unlock_irq(&dev->misc_lock);
spin_unlock_irqrestore(&dev->misc_lock, flags);
}
/* MIB interrupt: one of the statistics counters is about to overflow */
@ -1455,7 +1458,7 @@ static void ns83820_tx_timeout(struct net_device *ndev)
u32 tx_done_idx, *desc;
unsigned long flags;
local_irq_save(flags);
spin_lock_irqsave(&dev->tx_lock, flags);
tx_done_idx = dev->tx_done_idx;
desc = dev->tx_descs + (tx_done_idx * DESC_SIZE);
@ -1482,7 +1485,7 @@ static void ns83820_tx_timeout(struct net_device *ndev)
ndev->name,
tx_done_idx, dev->tx_free_idx, le32_to_cpu(desc[DESC_CMDSTS]));
local_irq_restore(flags);
spin_unlock_irqrestore(&dev->tx_lock, flags);
}
static void ns83820_tx_watch(unsigned long data)
@ -1832,7 +1835,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
} else if (!pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)) {
using_dac = 0;
} else {
printk(KERN_WARNING "ns83820.c: pci_set_dma_mask failed!\n");
dev_warn(&pci_dev->dev, "pci_set_dma_mask failed!\n");
return -ENODEV;
}
@ -1855,7 +1858,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
err = pci_enable_device(pci_dev);
if (err) {
printk(KERN_INFO "ns83820: pci_enable_dev failed: %d\n", err);
dev_info(&pci_dev->dev, "pci_enable_dev failed: %d\n", err);
goto out_free;
}
@ -1884,8 +1887,8 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
err = request_irq(pci_dev->irq, ns83820_irq, IRQF_SHARED,
DRV_NAME, ndev);
if (err) {
printk(KERN_INFO "ns83820: unable to register irq %d\n",
pci_dev->irq);
dev_info(&pci_dev->dev, "unable to register irq %d, err %d\n",
pci_dev->irq, err);
goto out_disable;
}
@ -1899,7 +1902,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
rtnl_lock();
err = dev_alloc_name(ndev, ndev->name);
if (err < 0) {
printk(KERN_INFO "ns83820: unable to get netdev name: %d\n", err);
dev_info(&pci_dev->dev, "unable to get netdev name: %d\n", err);
goto out_free_irq;
}

View File

@ -601,7 +601,7 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
/* dev zeroed in alloc_etherdev */
dev = alloc_etherdev (sizeof (*tp));
if (dev == NULL) {
printk (KERN_ERR PFX "unable to alloc new ethernet\n");
dev_err(&pdev->dev, "unable to alloc new ethernet\n");
DPRINTK ("EXIT, returning -ENOMEM\n");
return -ENOMEM;
}
@ -631,14 +631,14 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
/* make sure PCI base addr 0 is PIO */
if (!(pio_flags & IORESOURCE_IO)) {
printk (KERN_ERR PFX "region #0 not a PIO resource, aborting\n");
dev_err(&pdev->dev, "region #0 not a PIO resource, aborting\n");
rc = -ENODEV;
goto err_out;
}
/* make sure PCI base addr 1 is MMIO */
if (!(mmio_flags & IORESOURCE_MEM)) {
printk (KERN_ERR PFX "region #1 not an MMIO resource, aborting\n");
dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n");
rc = -ENODEV;
goto err_out;
}
@ -646,12 +646,12 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
/* check for weird/broken PCI region reporting */
if ((pio_len < NETDRV_MIN_IO_SIZE) ||
(mmio_len < NETDRV_MIN_IO_SIZE)) {
printk (KERN_ERR PFX "Invalid PCI region size(s), aborting\n");
dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n");
rc = -ENODEV;
goto err_out;
}
rc = pci_request_regions (pdev, "pci-skeleton");
rc = pci_request_regions (pdev, MODNAME);
if (rc)
goto err_out;
@ -663,7 +663,7 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
/* ioremap MMIO region */
ioaddr = ioremap (mmio_start, mmio_len);
if (ioaddr == NULL) {
printk (KERN_ERR PFX "cannot remap MMIO, aborting\n");
dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
rc = -EIO;
goto err_out_free_res;
}
@ -699,9 +699,10 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
}
/* if unknown chip, assume array element #0, original RTL-8139 in this case */
printk (KERN_DEBUG PFX "PCI device %s: unknown chip version, assuming RTL-8139\n",
pci_name(pdev));
printk (KERN_DEBUG PFX "PCI device %s: TxConfig = 0x%lx\n", pci_name(pdev), NETDRV_R32 (TxConfig));
dev_printk (KERN_DEBUG, &pdev->dev,
"unknown chip version, assuming RTL-8139\n");
dev_printk (KERN_DEBUG, &pdev->dev, "TxConfig = 0x%lx\n",
NETDRV_R32 (TxConfig));
tp->chipset = 0;
match:

View File

@ -58,18 +58,15 @@ static const char *const version =
* PCI device identifiers for "new style" Linux PCI Device Drivers
*/
static struct pci_device_id pcnet32_pci_tbl[] = {
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME), },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE), },
/*
* Adapters that were sold with IBM's RS/6000 or pSeries hardware have
* the incorrect vendor id.
*/
{ PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE,
PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0},
{ PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE),
.class = (PCI_CLASS_NETWORK_ETHERNET << 8), .class_mask = 0xffff00, },
{ } /* terminate list */
};
@ -188,6 +185,23 @@ static int homepna[MAX_UNITS];
#define PCNET32_TOTAL_SIZE 0x20
#define CSR0 0
#define CSR0_INIT 0x1
#define CSR0_START 0x2
#define CSR0_STOP 0x4
#define CSR0_TXPOLL 0x8
#define CSR0_INTEN 0x40
#define CSR0_IDON 0x0100
#define CSR0_NORMAL (CSR0_START | CSR0_INTEN)
#define PCNET32_INIT_LOW 1
#define PCNET32_INIT_HIGH 2
#define CSR3 3
#define CSR4 4
#define CSR5 5
#define CSR5_SUSPEND 0x0001
#define CSR15 15
#define PCNET32_MC_FILTER 8
/* The PCNET32 Rx and Tx ring descriptors. */
struct pcnet32_rx_head {
u32 base;
@ -277,7 +291,6 @@ struct pcnet32_private {
u32 phymask;
};
static void pcnet32_probe_vlbus(void);
static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
static int pcnet32_probe1(unsigned long, int, struct pci_dev *);
static int pcnet32_open(struct net_device *);
@ -419,6 +432,238 @@ static struct pcnet32_access pcnet32_dwio = {
.reset = pcnet32_dwio_reset
};
static void pcnet32_netif_stop(struct net_device *dev)
{
dev->trans_start = jiffies;
netif_poll_disable(dev);
netif_tx_disable(dev);
}
static void pcnet32_netif_start(struct net_device *dev)
{
netif_wake_queue(dev);
netif_poll_enable(dev);
}
/*
* Allocate space for the new sized tx ring.
* Free old resources
* Save new resources.
* Any failure keeps old resources.
* Must be called with lp->lock held.
*/
static void pcnet32_realloc_tx_ring(struct net_device *dev,
struct pcnet32_private *lp,
unsigned int size)
{
dma_addr_t new_ring_dma_addr;
dma_addr_t *new_dma_addr_list;
struct pcnet32_tx_head *new_tx_ring;
struct sk_buff **new_skb_list;
pcnet32_purge_tx_ring(dev);
new_tx_ring = pci_alloc_consistent(lp->pci_dev,
sizeof(struct pcnet32_tx_head) *
(1 << size),
&new_ring_dma_addr);
if (new_tx_ring == NULL) {
if (netif_msg_drv(lp))
printk("\n" KERN_ERR
"%s: Consistent memory allocation failed.\n",
dev->name);
return;
}
memset(new_tx_ring, 0, sizeof(struct pcnet32_tx_head) * (1 << size));
new_dma_addr_list = kcalloc((1 << size), sizeof(dma_addr_t),
GFP_ATOMIC);
if (!new_dma_addr_list) {
if (netif_msg_drv(lp))
printk("\n" KERN_ERR
"%s: Memory allocation failed.\n", dev->name);
goto free_new_tx_ring;
}
new_skb_list = kcalloc((1 << size), sizeof(struct sk_buff *),
GFP_ATOMIC);
if (!new_skb_list) {
if (netif_msg_drv(lp))
printk("\n" KERN_ERR
"%s: Memory allocation failed.\n", dev->name);
goto free_new_lists;
}
kfree(lp->tx_skbuff);
kfree(lp->tx_dma_addr);
pci_free_consistent(lp->pci_dev,
sizeof(struct pcnet32_tx_head) *
lp->tx_ring_size, lp->tx_ring,
lp->tx_ring_dma_addr);
lp->tx_ring_size = (1 << size);
lp->tx_mod_mask = lp->tx_ring_size - 1;
lp->tx_len_bits = (size << 12);
lp->tx_ring = new_tx_ring;
lp->tx_ring_dma_addr = new_ring_dma_addr;
lp->tx_dma_addr = new_dma_addr_list;
lp->tx_skbuff = new_skb_list;
return;
free_new_lists:
kfree(new_dma_addr_list);
free_new_tx_ring:
pci_free_consistent(lp->pci_dev,
sizeof(struct pcnet32_tx_head) *
(1 << size),
new_tx_ring,
new_ring_dma_addr);
return;
}
/*
* Allocate space for the new sized rx ring.
* Re-use old receive buffers.
* alloc extra buffers
* free unneeded buffers
* free unneeded buffers
* Save new resources.
* Any failure keeps old resources.
* Must be called with lp->lock held.
*/
static void pcnet32_realloc_rx_ring(struct net_device *dev,
struct pcnet32_private *lp,
unsigned int size)
{
dma_addr_t new_ring_dma_addr;
dma_addr_t *new_dma_addr_list;
struct pcnet32_rx_head *new_rx_ring;
struct sk_buff **new_skb_list;
int new, overlap;
new_rx_ring = pci_alloc_consistent(lp->pci_dev,
sizeof(struct pcnet32_rx_head) *
(1 << size),
&new_ring_dma_addr);
if (new_rx_ring == NULL) {
if (netif_msg_drv(lp))
printk("\n" KERN_ERR
"%s: Consistent memory allocation failed.\n",
dev->name);
return;
}
memset(new_rx_ring, 0, sizeof(struct pcnet32_rx_head) * (1 << size));
new_dma_addr_list = kcalloc((1 << size), sizeof(dma_addr_t),
GFP_ATOMIC);
if (!new_dma_addr_list) {
if (netif_msg_drv(lp))
printk("\n" KERN_ERR
"%s: Memory allocation failed.\n", dev->name);
goto free_new_rx_ring;
}
new_skb_list = kcalloc((1 << size), sizeof(struct sk_buff *),
GFP_ATOMIC);
if (!new_skb_list) {
if (netif_msg_drv(lp))
printk("\n" KERN_ERR
"%s: Memory allocation failed.\n", dev->name);
goto free_new_lists;
}
/* first copy the current receive buffers */
overlap = min(size, lp->rx_ring_size);
for (new = 0; new < overlap; new++) {
new_rx_ring[new] = lp->rx_ring[new];
new_dma_addr_list[new] = lp->rx_dma_addr[new];
new_skb_list[new] = lp->rx_skbuff[new];
}
/* now allocate any new buffers needed */
for (; new < size; new++ ) {
struct sk_buff *rx_skbuff;
new_skb_list[new] = dev_alloc_skb(PKT_BUF_SZ);
if (!(rx_skbuff = new_skb_list[new])) {
/* keep the original lists and buffers */
if (netif_msg_drv(lp))
printk(KERN_ERR
"%s: pcnet32_realloc_rx_ring dev_alloc_skb failed.\n",
dev->name);
goto free_all_new;
}
skb_reserve(rx_skbuff, 2);
new_dma_addr_list[new] =
pci_map_single(lp->pci_dev, rx_skbuff->data,
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
new_rx_ring[new].base = (u32) le32_to_cpu(new_dma_addr_list[new]);
new_rx_ring[new].buf_length = le16_to_cpu(2 - PKT_BUF_SZ);
new_rx_ring[new].status = le16_to_cpu(0x8000);
}
/* and free any unneeded buffers */
for (; new < lp->rx_ring_size; new++) {
if (lp->rx_skbuff[new]) {
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[new],
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
dev_kfree_skb(lp->rx_skbuff[new]);
}
}
kfree(lp->rx_skbuff);
kfree(lp->rx_dma_addr);
pci_free_consistent(lp->pci_dev,
sizeof(struct pcnet32_rx_head) *
lp->rx_ring_size, lp->rx_ring,
lp->rx_ring_dma_addr);
lp->rx_ring_size = (1 << size);
lp->rx_mod_mask = lp->rx_ring_size - 1;
lp->rx_len_bits = (size << 4);
lp->rx_ring = new_rx_ring;
lp->rx_ring_dma_addr = new_ring_dma_addr;
lp->rx_dma_addr = new_dma_addr_list;
lp->rx_skbuff = new_skb_list;
return;
free_all_new:
for (; --new >= lp->rx_ring_size; ) {
if (new_skb_list[new]) {
pci_unmap_single(lp->pci_dev, new_dma_addr_list[new],
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
dev_kfree_skb(new_skb_list[new]);
}
}
kfree(new_skb_list);
free_new_lists:
kfree(new_dma_addr_list);
free_new_rx_ring:
pci_free_consistent(lp->pci_dev,
sizeof(struct pcnet32_rx_head) *
(1 << size),
new_rx_ring,
new_ring_dma_addr);
return;
}
static void pcnet32_purge_rx_ring(struct net_device *dev)
{
struct pcnet32_private *lp = dev->priv;
int i;
/* free all allocated skbuffs */
for (i = 0; i < lp->rx_ring_size; i++) {
lp->rx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
if (lp->rx_skbuff[i]) {
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i],
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(lp->rx_skbuff[i]);
}
lp->rx_skbuff[i] = NULL;
lp->rx_dma_addr[i] = 0;
}
}
#ifdef CONFIG_NET_POLL_CONTROLLER
static void pcnet32_poll_controller(struct net_device *dev)
{
@ -519,10 +764,10 @@ static void pcnet32_get_ringparam(struct net_device *dev,
{
struct pcnet32_private *lp = dev->priv;
ering->tx_max_pending = TX_MAX_RING_SIZE - 1;
ering->tx_pending = lp->tx_ring_size - 1;
ering->rx_max_pending = RX_MAX_RING_SIZE - 1;
ering->rx_pending = lp->rx_ring_size - 1;
ering->tx_max_pending = TX_MAX_RING_SIZE;
ering->tx_pending = lp->tx_ring_size;
ering->rx_max_pending = RX_MAX_RING_SIZE;
ering->rx_pending = lp->rx_ring_size;
}
static int pcnet32_set_ringparam(struct net_device *dev,
@ -530,56 +775,53 @@ static int pcnet32_set_ringparam(struct net_device *dev,
{
struct pcnet32_private *lp = dev->priv;
unsigned long flags;
unsigned int size;
ulong ioaddr = dev->base_addr;
int i;
if (ering->rx_mini_pending || ering->rx_jumbo_pending)
return -EINVAL;
if (netif_running(dev))
pcnet32_close(dev);
pcnet32_netif_stop(dev);
spin_lock_irqsave(&lp->lock, flags);
pcnet32_free_ring(dev);
lp->tx_ring_size =
min(ering->tx_pending, (unsigned int)TX_MAX_RING_SIZE);
lp->rx_ring_size =
min(ering->rx_pending, (unsigned int)RX_MAX_RING_SIZE);
lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */
size = min(ering->tx_pending, (unsigned int)TX_MAX_RING_SIZE);
/* set the minimum ring size to 4, to allow the loopback test to work
* unchanged.
*/
for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) {
if (lp->tx_ring_size <= (1 << i))
if (size <= (1 << i))
break;
}
lp->tx_ring_size = (1 << i);
lp->tx_mod_mask = lp->tx_ring_size - 1;
lp->tx_len_bits = (i << 12);
if ((1 << i) != lp->tx_ring_size)
pcnet32_realloc_tx_ring(dev, lp, i);
size = min(ering->rx_pending, (unsigned int)RX_MAX_RING_SIZE);
for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) {
if (lp->rx_ring_size <= (1 << i))
if (size <= (1 << i))
break;
}
lp->rx_ring_size = (1 << i);
lp->rx_mod_mask = lp->rx_ring_size - 1;
lp->rx_len_bits = (i << 4);
if ((1 << i) != lp->rx_ring_size)
pcnet32_realloc_rx_ring(dev, lp, i);
dev->weight = lp->rx_ring_size / 2;
if (pcnet32_alloc_ring(dev, dev->name)) {
pcnet32_free_ring(dev);
spin_unlock_irqrestore(&lp->lock, flags);
return -ENOMEM;
if (netif_running(dev)) {
pcnet32_netif_start(dev);
pcnet32_restart(dev, CSR0_NORMAL);
}
spin_unlock_irqrestore(&lp->lock, flags);
if (pcnet32_debug & NETIF_MSG_DRV)
printk(KERN_INFO PFX
if (netif_msg_drv(lp))
printk(KERN_INFO
"%s: Ring Param Settings: RX: %d, TX: %d\n", dev->name,
lp->rx_ring_size, lp->tx_ring_size);
if (netif_running(dev))
pcnet32_open(dev);
return 0;
}
@ -633,29 +875,27 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
unsigned long flags;
unsigned long ticks;
*data1 = 1; /* status of test, default to fail */
rc = 1; /* default to fail */
if (netif_running(dev))
pcnet32_close(dev);
spin_lock_irqsave(&lp->lock, flags);
lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */
numbuffs = min(numbuffs, (int)min(lp->rx_ring_size, lp->tx_ring_size));
/* Reset the PCNET32 */
lp->a.reset(ioaddr);
lp->a.write_csr(ioaddr, CSR4, 0x0915);
/* switch pcnet32 to 32bit mode */
lp->a.write_bcr(ioaddr, 20, 2);
lp->init_block.mode =
le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
lp->init_block.filter[0] = 0;
lp->init_block.filter[1] = 0;
/* purge & init rings but don't actually restart */
pcnet32_restart(dev, 0x0000);
lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */
lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */
/* Initialize Transmit buffers. */
size = data_len + 15;
@ -697,14 +937,15 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
}
}
x = a->read_bcr(ioaddr, 32); /* set internal loopback in BSR32 */
x = x | 0x0002;
a->write_bcr(ioaddr, 32, x);
x = a->read_bcr(ioaddr, 32); /* set internal loopback in BCR32 */
a->write_bcr(ioaddr, 32, x | 0x0002);
lp->a.write_csr(ioaddr, 15, 0x0044); /* set int loopback in CSR15 */
/* set int loopback in CSR15 */
x = a->read_csr(ioaddr, CSR15) & 0xfffc;
lp->a.write_csr(ioaddr, CSR15, x | 0x0044);
teststatus = le16_to_cpu(0x8000);
lp->a.write_csr(ioaddr, 0, 0x0002); /* Set STRT bit */
lp->a.write_csr(ioaddr, CSR0, CSR0_START); /* Set STRT bit */
/* Check status of descriptors */
for (x = 0; x < numbuffs; x++) {
@ -712,7 +953,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
rmb();
while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) {
spin_unlock_irqrestore(&lp->lock, flags);
mdelay(1);
msleep(1);
spin_lock_irqsave(&lp->lock, flags);
rmb();
ticks++;
@ -725,7 +966,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
}
}
lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */
lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */
wmb();
if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {
printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name);
@ -758,25 +999,24 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
}
x++;
}
if (!rc) {
*data1 = 0;
}
clean_up:
*data1 = rc;
pcnet32_purge_tx_ring(dev);
x = a->read_csr(ioaddr, 15) & 0xFFFF;
a->write_csr(ioaddr, 15, (x & ~0x0044)); /* reset bits 6 and 2 */
x = a->read_csr(ioaddr, CSR15);
a->write_csr(ioaddr, CSR15, (x & ~0x0044)); /* reset bits 6 and 2 */
x = a->read_bcr(ioaddr, 32); /* reset internal loopback */
x = x & ~0x0002;
a->write_bcr(ioaddr, 32, x);
spin_unlock_irqrestore(&lp->lock, flags);
a->write_bcr(ioaddr, 32, (x & ~0x0002));
if (netif_running(dev)) {
spin_unlock_irqrestore(&lp->lock, flags);
pcnet32_open(dev);
} else {
pcnet32_purge_rx_ring(dev);
lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
spin_unlock_irqrestore(&lp->lock, flags);
}
return (rc);
@ -839,6 +1079,43 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data)
return 0;
}
/*
* lp->lock must be held.
*/
static int pcnet32_suspend(struct net_device *dev, unsigned long *flags,
int can_sleep)
{
int csr5;
struct pcnet32_private *lp = dev->priv;
struct pcnet32_access *a = &lp->a;
ulong ioaddr = dev->base_addr;
int ticks;
/* set SUSPEND (SPND) - CSR5 bit 0 */
csr5 = a->read_csr(ioaddr, CSR5);
a->write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND);
/* poll waiting for bit to be set */
ticks = 0;
while (!(a->read_csr(ioaddr, CSR5) & CSR5_SUSPEND)) {
spin_unlock_irqrestore(&lp->lock, *flags);
if (can_sleep)
msleep(1);
else
mdelay(1);
spin_lock_irqsave(&lp->lock, *flags);
ticks++;
if (ticks > 200) {
if (netif_msg_hw(lp))
printk(KERN_DEBUG
"%s: Error getting into suspend!\n",
dev->name);
return 0;
}
}
return 1;
}
#define PCNET32_REGS_PER_PHY 32
#define PCNET32_MAX_PHYS 32
static int pcnet32_get_regs_len(struct net_device *dev)
@ -857,32 +1134,13 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
struct pcnet32_private *lp = dev->priv;
struct pcnet32_access *a = &lp->a;
ulong ioaddr = dev->base_addr;
int ticks;
unsigned long flags;
spin_lock_irqsave(&lp->lock, flags);
csr0 = a->read_csr(ioaddr, 0);
if (!(csr0 & 0x0004)) { /* If not stopped */
/* set SUSPEND (SPND) - CSR5 bit 0 */
a->write_csr(ioaddr, 5, 0x0001);
/* poll waiting for bit to be set */
ticks = 0;
while (!(a->read_csr(ioaddr, 5) & 0x0001)) {
spin_unlock_irqrestore(&lp->lock, flags);
mdelay(1);
spin_lock_irqsave(&lp->lock, flags);
ticks++;
if (ticks > 200) {
if (netif_msg_hw(lp))
printk(KERN_DEBUG
"%s: Error getting into suspend!\n",
dev->name);
break;
}
}
}
csr0 = a->read_csr(ioaddr, CSR0);
if (!(csr0 & CSR0_STOP)) /* If not stopped */
pcnet32_suspend(dev, &flags, 1);
/* read address PROM */
for (i = 0; i < 16; i += 2)
@ -919,9 +1177,12 @@ static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
}
}
if (!(csr0 & 0x0004)) { /* If not stopped */
if (!(csr0 & CSR0_STOP)) { /* If not stopped */
int csr5;
/* clear SUSPEND (SPND) - CSR5 bit 0 */
a->write_csr(ioaddr, 5, 0x0000);
csr5 = a->read_csr(ioaddr, CSR5);
a->write_csr(ioaddr, CSR5, csr5 & (~CSR5_SUSPEND));
}
spin_unlock_irqrestore(&lp->lock, flags);
@ -952,7 +1213,7 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
/* only probes for non-PCI devices, the rest are handled by
* pci_register_driver via pcnet32_probe_pci */
static void __devinit pcnet32_probe_vlbus(void)
static void __devinit pcnet32_probe_vlbus(unsigned int *pcnet32_portlist)
{
unsigned int *port, ioaddr;
@ -1436,7 +1697,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, char *name)
lp->tx_ring_size,
&lp->tx_ring_dma_addr);
if (lp->tx_ring == NULL) {
if (pcnet32_debug & NETIF_MSG_DRV)
if (netif_msg_drv(lp))
printk("\n" KERN_ERR PFX
"%s: Consistent memory allocation failed.\n",
name);
@ -1448,52 +1709,48 @@ static int pcnet32_alloc_ring(struct net_device *dev, char *name)
lp->rx_ring_size,
&lp->rx_ring_dma_addr);
if (lp->rx_ring == NULL) {
if (pcnet32_debug & NETIF_MSG_DRV)
if (netif_msg_drv(lp))
printk("\n" KERN_ERR PFX
"%s: Consistent memory allocation failed.\n",
name);
return -ENOMEM;
}
lp->tx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->tx_ring_size,
lp->tx_dma_addr = kcalloc(lp->tx_ring_size, sizeof(dma_addr_t),
GFP_ATOMIC);
if (!lp->tx_dma_addr) {
if (pcnet32_debug & NETIF_MSG_DRV)
if (netif_msg_drv(lp))
printk("\n" KERN_ERR PFX
"%s: Memory allocation failed.\n", name);
return -ENOMEM;
}
memset(lp->tx_dma_addr, 0, sizeof(dma_addr_t) * lp->tx_ring_size);
lp->rx_dma_addr = kmalloc(sizeof(dma_addr_t) * lp->rx_ring_size,
lp->rx_dma_addr = kcalloc(lp->rx_ring_size, sizeof(dma_addr_t),
GFP_ATOMIC);
if (!lp->rx_dma_addr) {
if (pcnet32_debug & NETIF_MSG_DRV)
if (netif_msg_drv(lp))
printk("\n" KERN_ERR PFX
"%s: Memory allocation failed.\n", name);
return -ENOMEM;
}
memset(lp->rx_dma_addr, 0, sizeof(dma_addr_t) * lp->rx_ring_size);
lp->tx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->tx_ring_size,
lp->tx_skbuff = kcalloc(lp->tx_ring_size, sizeof(struct sk_buff *),
GFP_ATOMIC);
if (!lp->tx_skbuff) {
if (pcnet32_debug & NETIF_MSG_DRV)
if (netif_msg_drv(lp))
printk("\n" KERN_ERR PFX
"%s: Memory allocation failed.\n", name);
return -ENOMEM;
}
memset(lp->tx_skbuff, 0, sizeof(struct sk_buff *) * lp->tx_ring_size);
lp->rx_skbuff = kmalloc(sizeof(struct sk_buff *) * lp->rx_ring_size,
lp->rx_skbuff = kcalloc(lp->rx_ring_size, sizeof(struct sk_buff *),
GFP_ATOMIC);
if (!lp->rx_skbuff) {
if (pcnet32_debug & NETIF_MSG_DRV)
if (netif_msg_drv(lp))
printk("\n" KERN_ERR PFX
"%s: Memory allocation failed.\n", name);
return -ENOMEM;
}
memset(lp->rx_skbuff, 0, sizeof(struct sk_buff *) * lp->rx_ring_size);
return 0;
}
@ -1757,16 +2014,7 @@ static int pcnet32_open(struct net_device *dev)
err_free_ring:
/* free any allocated skbuffs */
for (i = 0; i < lp->rx_ring_size; i++) {
lp->rx_ring[i].status = 0;
if (lp->rx_skbuff[i]) {
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i],
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
dev_kfree_skb(lp->rx_skbuff[i]);
}
lp->rx_skbuff[i] = NULL;
lp->rx_dma_addr[i] = 0;
}
pcnet32_purge_rx_ring(dev);
/*
* Switch back to 16bit mode to avoid problems with dumb
@ -2348,7 +2596,6 @@ static int pcnet32_close(struct net_device *dev)
{
unsigned long ioaddr = dev->base_addr;
struct pcnet32_private *lp = dev->priv;
int i;
unsigned long flags;
del_timer_sync(&lp->watchdog_timer);
@ -2379,31 +2626,8 @@ static int pcnet32_close(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
/* free all allocated skbuffs */
for (i = 0; i < lp->rx_ring_size; i++) {
lp->rx_ring[i].status = 0;
wmb(); /* Make sure adapter sees owner change */
if (lp->rx_skbuff[i]) {
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i],
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
dev_kfree_skb(lp->rx_skbuff[i]);
}
lp->rx_skbuff[i] = NULL;
lp->rx_dma_addr[i] = 0;
}
for (i = 0; i < lp->tx_ring_size; i++) {
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
if (lp->tx_skbuff[i]) {
pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i],
lp->tx_skbuff[i]->len,
PCI_DMA_TODEVICE);
dev_kfree_skb(lp->tx_skbuff[i]);
}
lp->tx_skbuff[i] = NULL;
lp->tx_dma_addr[i] = 0;
}
pcnet32_purge_rx_ring(dev);
pcnet32_purge_tx_ring(dev);
spin_unlock_irqrestore(&lp->lock, flags);
@ -2433,6 +2657,7 @@ static void pcnet32_load_multicast(struct net_device *dev)
volatile struct pcnet32_init_block *ib = &lp->init_block;
volatile u16 *mcast_table = (u16 *) & ib->filter;
struct dev_mc_list *dmi = dev->mc_list;
unsigned long ioaddr = dev->base_addr;
char *addrs;
int i;
u32 crc;
@ -2441,6 +2666,10 @@ static void pcnet32_load_multicast(struct net_device *dev)
if (dev->flags & IFF_ALLMULTI) {
ib->filter[0] = 0xffffffff;
ib->filter[1] = 0xffffffff;
lp->a.write_csr(ioaddr, PCNET32_MC_FILTER, 0xffff);
lp->a.write_csr(ioaddr, PCNET32_MC_FILTER+1, 0xffff);
lp->a.write_csr(ioaddr, PCNET32_MC_FILTER+2, 0xffff);
lp->a.write_csr(ioaddr, PCNET32_MC_FILTER+3, 0xffff);
return;
}
/* clear the multicast filter */
@ -2462,6 +2691,9 @@ static void pcnet32_load_multicast(struct net_device *dev)
le16_to_cpu(le16_to_cpu(mcast_table[crc >> 4]) |
(1 << (crc & 0xf)));
}
for (i = 0; i < 4; i++)
lp->a.write_csr(ioaddr, PCNET32_MC_FILTER + i,
le16_to_cpu(mcast_table[i]));
return;
}
@ -2472,8 +2704,11 @@ static void pcnet32_set_multicast_list(struct net_device *dev)
{
unsigned long ioaddr = dev->base_addr, flags;
struct pcnet32_private *lp = dev->priv;
int csr15, suspended;
spin_lock_irqsave(&lp->lock, flags);
suspended = pcnet32_suspend(dev, &flags, 0);
csr15 = lp->a.read_csr(ioaddr, CSR15);
if (dev->flags & IFF_PROMISC) {
/* Log any net taps. */
if (netif_msg_hw(lp))
@ -2482,15 +2717,24 @@ static void pcnet32_set_multicast_list(struct net_device *dev)
lp->init_block.mode =
le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) <<
7);
lp->a.write_csr(ioaddr, CSR15, csr15 | 0x8000);
} else {
lp->init_block.mode =
le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
lp->a.write_csr(ioaddr, CSR15, csr15 & 0x7fff);
pcnet32_load_multicast(dev);
}
lp->a.write_csr(ioaddr, 0, 0x0004); /* Temporarily stop the lance. */
pcnet32_restart(dev, 0x0042); /* Resume normal operation */
netif_wake_queue(dev);
if (suspended) {
int csr5;
/* clear SUSPEND (SPND) - CSR5 bit 0 */
csr5 = lp->a.read_csr(ioaddr, CSR5);
lp->a.write_csr(ioaddr, CSR5, csr5 & (~CSR5_SUSPEND));
} else {
lp->a.write_csr(ioaddr, CSR0, CSR0_STOP);
pcnet32_restart(dev, CSR0_NORMAL);
netif_wake_queue(dev);
}
spin_unlock_irqrestore(&lp->lock, flags);
}
@ -2730,7 +2974,7 @@ static int __init pcnet32_init_module(void)
/* should we find any remaining VLbus devices ? */
if (pcnet32vlb)
pcnet32_probe_vlbus();
pcnet32_probe_vlbus(pcnet32_portlist);
if (cards_found && (pcnet32_debug & NETIF_MSG_PROBE))
printk(KERN_INFO PFX "%d cards_found.\n", cards_found);

View File

@ -103,7 +103,22 @@ static int cis820x_config_intr(struct phy_device *phydev)
return err;
}
/* Cicada 820x */
/* Cicada 8201, a.k.a Vitesse VSC8201 */
static struct phy_driver cis8201_driver = {
.phy_id = 0x000fc410,
.name = "Cicada Cis8201",
.phy_id_mask = 0x000ffff0,
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = &cis820x_config_init,
.config_aneg = &genphy_config_aneg,
.read_status = &genphy_read_status,
.ack_interrupt = &cis820x_ack_interrupt,
.config_intr = &cis820x_config_intr,
.driver = { .owner = THIS_MODULE,},
};
/* Cicada 8204 */
static struct phy_driver cis8204_driver = {
.phy_id = 0x000fc440,
.name = "Cicada Cis8204",
@ -118,15 +133,30 @@ static struct phy_driver cis8204_driver = {
.driver = { .owner = THIS_MODULE,},
};
static int __init cis8204_init(void)
static int __init cicada_init(void)
{
return phy_driver_register(&cis8204_driver);
int ret;
ret = phy_driver_register(&cis8204_driver);
if (ret)
goto err1;
ret = phy_driver_register(&cis8201_driver);
if (ret)
goto err2;
return 0;
err2:
phy_driver_unregister(&cis8204_driver);
err1:
return ret;
}
static void __exit cis8204_exit(void)
static void __exit cicada_exit(void)
{
phy_driver_unregister(&cis8204_driver);
phy_driver_unregister(&cis8201_driver);
}
module_init(cis8204_init);
module_exit(cis8204_exit);
module_init(cicada_init);
module_exit(cicada_exit);

View File

@ -1406,7 +1406,7 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
dev = alloc_etherdev(sizeof (*tp));
if (dev == NULL) {
if (netif_msg_drv(&debug))
printk(KERN_ERR PFX "unable to alloc new ethernet\n");
dev_err(&pdev->dev, "unable to alloc new ethernet\n");
goto err_out;
}
@ -1418,10 +1418,8 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
/* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pci_enable_device(pdev);
if (rc < 0) {
if (netif_msg_probe(tp)) {
printk(KERN_ERR PFX "%s: enable failure\n",
pci_name(pdev));
}
if (netif_msg_probe(tp))
dev_err(&pdev->dev, "enable failure\n");
goto err_out_free_dev;
}
@ -1437,37 +1435,32 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
} else {
if (netif_msg_probe(tp)) {
printk(KERN_ERR PFX
if (netif_msg_probe(tp))
dev_err(&pdev->dev,
"PowerManagement capability not found.\n");
}
}
/* make sure PCI base addr 1 is MMIO */
if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
if (netif_msg_probe(tp)) {
printk(KERN_ERR PFX
if (netif_msg_probe(tp))
dev_err(&pdev->dev,
"region #1 not an MMIO resource, aborting\n");
}
rc = -ENODEV;
goto err_out_mwi;
}
/* check for weird/broken PCI region reporting */
if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) {
if (netif_msg_probe(tp)) {
printk(KERN_ERR PFX
if (netif_msg_probe(tp))
dev_err(&pdev->dev,
"Invalid PCI region size(s), aborting\n");
}
rc = -ENODEV;
goto err_out_mwi;
}
rc = pci_request_regions(pdev, MODULENAME);
if (rc < 0) {
if (netif_msg_probe(tp)) {
printk(KERN_ERR PFX "%s: could not request regions.\n",
pci_name(pdev));
}
if (netif_msg_probe(tp))
dev_err(&pdev->dev, "could not request regions.\n");
goto err_out_mwi;
}
@ -1480,10 +1473,9 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
} else {
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc < 0) {
if (netif_msg_probe(tp)) {
printk(KERN_ERR PFX
if (netif_msg_probe(tp))
dev_err(&pdev->dev,
"DMA configuration failed.\n");
}
goto err_out_free_res;
}
}
@ -1494,7 +1486,7 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE);
if (ioaddr == NULL) {
if (netif_msg_probe(tp))
printk(KERN_ERR PFX "cannot remap MMIO, aborting\n");
dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
rc = -EIO;
goto err_out_free_res;
}
@ -1526,9 +1518,9 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
if (i < 0) {
/* Unknown chip: assume array element #0, original RTL-8169 */
if (netif_msg_probe(tp)) {
printk(KERN_DEBUG PFX "PCI device %s: "
dev_printk(KERN_DEBUG, &pdev->dev,
"unknown chip version, assuming %s\n",
pci_name(pdev), rtl_chip_info[0].name);
rtl_chip_info[0].name);
}
i++;
}

View File

@ -22,129 +22,13 @@
Support and updates available at
http://www.scyld.com/network/starfire.html
[link no longer provides useful info -jgarzik]
-----------------------------------------------------------
Linux kernel-specific changes:
LK1.1.1 (jgarzik):
- Use PCI driver interface
- Fix MOD_xxx races
- softnet fixups
LK1.1.2 (jgarzik):
- Merge Becker version 0.15
LK1.1.3 (Andrew Morton)
- Timer cleanups
LK1.1.4 (jgarzik):
- Merge Becker version 1.03
LK1.2.1 (Ion Badulescu <ionut@cs.columbia.edu>)
- Support hardware Rx/Tx checksumming
- Use the GFP firmware taken from Adaptec's Netware driver
LK1.2.2 (Ion Badulescu)
- Backported to 2.2.x
LK1.2.3 (Ion Badulescu)
- Fix the flaky mdio interface
- More compat clean-ups
LK1.2.4 (Ion Badulescu)
- More 2.2.x initialization fixes
LK1.2.5 (Ion Badulescu)
- Several fixes from Manfred Spraul
LK1.2.6 (Ion Badulescu)
- Fixed ifup/ifdown/ifup problem in 2.4.x
LK1.2.7 (Ion Badulescu)
- Removed unused code
- Made more functions static and __init
LK1.2.8 (Ion Badulescu)
- Quell bogus error messages, inform about the Tx threshold
- Removed #ifdef CONFIG_PCI, this driver is PCI only
LK1.2.9 (Ion Badulescu)
- Merged Jeff Garzik's changes from 2.4.4-pre5
- Added 2.2.x compatibility stuff required by the above changes
LK1.2.9a (Ion Badulescu)
- More updates from Jeff Garzik
LK1.3.0 (Ion Badulescu)
- Merged zerocopy support
LK1.3.1 (Ion Badulescu)
- Added ethtool support
- Added GPIO (media change) interrupt support
LK1.3.2 (Ion Badulescu)
- Fixed 2.2.x compatibility issues introduced in 1.3.1
- Fixed ethtool ioctl returning uninitialized memory
LK1.3.3 (Ion Badulescu)
- Initialize the TxMode register properly
- Don't dereference dev->priv after freeing it
LK1.3.4 (Ion Badulescu)
- Fixed initialization timing problems
- Fixed interrupt mask definitions
LK1.3.5 (jgarzik)
- ethtool NWAY_RST, GLINK, [GS]MSGLVL support
LK1.3.6:
- Sparc64 support and fixes (Ion Badulescu)
- Better stats and error handling (Ion Badulescu)
- Use new pci_set_mwi() PCI API function (jgarzik)
LK1.3.7 (Ion Badulescu)
- minimal implementation of tx_timeout()
- correctly shutdown the Rx/Tx engines in netdev_close()
- added calls to netif_carrier_on/off
(patch from Stefan Rompf <srompf@isg.de>)
- VLAN support
LK1.3.8 (Ion Badulescu)
- adjust DMA burst size on sparc64
- 64-bit support
- reworked zerocopy support for 64-bit buffers
- working and usable interrupt mitigation/latency
- reduced Tx interrupt frequency for lower interrupt overhead
LK1.3.9 (Ion Badulescu)
- bugfix for mcast filter
- enable the right kind of Tx interrupts (TxDMADone, not TxDone)
LK1.4.0 (Ion Badulescu)
- NAPI support
LK1.4.1 (Ion Badulescu)
- flush PCI posting buffers after disabling Rx interrupts
- put the chip to a D3 slumber on driver unload
- added config option to enable/disable NAPI
LK1.4.2 (Ion Badulescu)
- finally added firmware (GPL'ed by Adaptec)
- removed compatibility code for 2.2.x
LK1.4.2.1 (Ion Badulescu)
- fixed 32/64 bit issues on i386 + CONFIG_HIGHMEM
- added 32-bit padding to outgoing skb's, removed previous workaround
TODO: - fix forced speed/duplexing code (broken a long time ago, when
somebody converted the driver to use the generic MII code)
- fix VLAN support
*/
#define DRV_NAME "starfire"
#define DRV_VERSION "1.03+LK1.4.2.1"
#define DRV_RELDATE "October 3, 2005"
#define DRV_VERSION "2.0"
#define DRV_RELDATE "June 27, 2006"
#include <linux/module.h>
#include <linux/kernel.h>
@ -846,7 +730,6 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
goto err_out_free_netdev;
}
/* ioremap is borken in Linux-2.2.x/sparc64 */
base = ioremap(ioaddr, io_size);
if (!base) {
printk(KERN_ERR DRV_NAME " %d: cannot remap %#x @ %#lx, aborting\n",

View File

@ -16,91 +16,13 @@
Support and updates available at
http://www.scyld.com/network/sundance.html
[link no longer provides useful info -jgarzik]
Version LK1.01a (jgarzik):
- Replace some MII-related magic numbers with constants
Version LK1.02 (D-Link):
- Add new board to PCI ID list
- Fix multicast bug
Version LK1.03 (D-Link):
- New Rx scheme, reduce Rx congestion
- Option to disable flow control
Version LK1.04 (D-Link):
- Tx timeout recovery
- More support for ethtool.
Version LK1.04a:
- Remove unused/constant members from struct pci_id_info
(which then allows removal of 'drv_flags' from private struct)
(jgarzik)
- If no phy is found, fail to load that board (jgarzik)
- Always start phy id scan at id 1 to avoid problems (Donald Becker)
- Autodetect where mii_preable_required is needed,
default to not needed. (Donald Becker)
Version LK1.04b:
- Remove mii_preamble_required module parameter (Donald Becker)
- Add per-interface mii_preamble_required (setting is autodetected)
(Donald Becker)
- Remove unnecessary cast from void pointer (jgarzik)
- Re-align comments in private struct (jgarzik)
Version LK1.04c (jgarzik):
- Support bitmapped message levels (NETIF_MSG_xxx), and the
two ethtool ioctls that get/set them
- Don't hand-code MII ethtool support, use standard API/lib
Version LK1.04d:
- Merge from Donald Becker's sundance.c: (Jason Lunz)
* proper support for variably-sized MTUs
* default to PIO, to fix chip bugs
- Add missing unregister_netdev (Jason Lunz)
- Add CONFIG_SUNDANCE_MMIO config option (jgarzik)
- Better rx buf size calculation (Donald Becker)
Version LK1.05 (D-Link):
- Fix DFE-580TX packet drop issue (for DL10050C)
- Fix reset_tx logic
Version LK1.06 (D-Link):
- Fix crash while unloading driver
Versin LK1.06b (D-Link):
- New tx scheme, adaptive tx_coalesce
Version LK1.07 (D-Link):
- Fix tx bugs in big-endian machines
- Remove unused max_interrupt_work module parameter, the new
NAPI-like rx scheme doesn't need it.
- Remove redundancy get_stats() in intr_handler(), those
I/O access could affect performance in ARM-based system
- Add Linux software VLAN support
Version LK1.08 (Philippe De Muyter phdm@macqel.be):
- Fix bug of custom mac address
(StationAddr register only accept word write)
Version LK1.09 (D-Link):
- Fix the flowctrl bug.
- Set Pause bit in MII ANAR if flow control enabled.
Version LK1.09a (ICPlus):
- Add the delay time in reading the contents of EEPROM
Version LK1.10 (Philippe De Muyter phdm@macqel.be):
- Make 'unblock interface after Tx underrun' work
Version LK1.11 (Pedro Alejandro Lopez-Valencia palopezv at gmail.com):
- Add support for IC Plus Corporation IP100A chipset
*/
#define DRV_NAME "sundance"
#define DRV_VERSION "1.01+LK1.11"
#define DRV_RELDATE "14-Jun-2006"
#define DRV_VERSION "1.1"
#define DRV_RELDATE "27-Jun-2006"
/* The user-configurable values.
@ -282,15 +204,15 @@ IVc. Errata
#define USE_IO_OPS 1
#endif
static struct pci_device_id sundance_pci_tbl[] = {
{0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0},
{0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1},
{0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2},
{0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3},
{0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
{0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
{0x13F0, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
{0,}
static const struct pci_device_id sundance_pci_tbl[] = {
{ 0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0 },
{ 0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1 },
{ 0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2 },
{ 0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3 },
{ 0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
{ 0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
{ 0x13F0, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
{ }
};
MODULE_DEVICE_TABLE(pci, sundance_pci_tbl);
@ -301,7 +223,7 @@ enum {
struct pci_id_info {
const char *name;
};
static const struct pci_id_info pci_id_tbl[] = {
static const struct pci_id_info pci_id_tbl[] __devinitdata = {
{"D-Link DFE-550TX FAST Ethernet Adapter"},
{"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"},
{"D-Link DFE-580TX 4 port Server Adapter"},
@ -309,7 +231,7 @@ static const struct pci_id_info pci_id_tbl[] = {
{"D-Link DL10050-based FAST Ethernet Adapter"},
{"Sundance Technology Alta"},
{"IC Plus Corporation IP100A FAST Ethernet Adapter"},
{NULL,}, /* 0 terminated list. */
{ } /* terminate list. */
};
/* This driver was written to use PCI memory space, however x86-oriented

View File

@ -224,24 +224,21 @@ static const struct pci_device_id w840_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, w840_pci_tbl);
enum {
netdev_res_size = 128, /* size of PCI BAR resource */
};
struct pci_id_info {
const char *name;
struct match_info {
int pci, pci_mask, subsystem, subsystem_mask;
int revision, revision_mask; /* Only 8 bits. */
} id;
int io_size; /* Needed for I/O region check or ioremap(). */
int drv_flags; /* Driver use, intended as capability flags. */
int drv_flags; /* Driver use, intended as capability flags. */
};
static struct pci_id_info pci_id_tbl[] = {
{"Winbond W89c840", /* Sometime a Level-One switch card. */
{ 0x08401050, 0xffffffff, 0x81530000, 0xffff0000 },
128, CanHaveMII | HasBrokenTx | FDXOnNoMII},
{"Winbond W89c840", { 0x08401050, 0xffffffff, },
128, CanHaveMII | HasBrokenTx},
{"Compex RL100-ATX", { 0x201111F6, 0xffffffff,},
128, CanHaveMII | HasBrokenTx},
{NULL,}, /* 0 terminated list. */
static const struct pci_id_info pci_id_tbl[] __devinitdata = {
{ /* Sometime a Level-One switch card. */
"Winbond W89c840", CanHaveMII | HasBrokenTx | FDXOnNoMII},
{ "Winbond W89c840", CanHaveMII | HasBrokenTx},
{ "Compex RL100-ATX", CanHaveMII | HasBrokenTx},
{ } /* terminate list. */
};
/* This driver was written to use PCI memory space, however some x86 systems
@ -399,7 +396,7 @@ static int __devinit w840_probe1 (struct pci_dev *pdev,
#ifdef USE_IO_OPS
bar = 0;
#endif
ioaddr = pci_iomap(pdev, bar, pci_id_tbl[chip_idx].io_size);
ioaddr = pci_iomap(pdev, bar, netdev_res_size);
if (!ioaddr)
goto err_out_free_res;

View File

@ -10,26 +10,11 @@
410 Severn Ave., Suite 210
Annapolis MD 21403
-----------------------------------------------------------
Linux kernel-specific changes:
LK1.0 (Ion Badulescu)
- Major cleanup
- Use 2.4 PCI API
- Support ethtool
- Rewrite perfect filter/hash code
- Use interrupts for media changes
LK1.1 (Ion Badulescu)
- Disallow negotiation of unsupported full-duplex modes
*/
#define DRV_NAME "xircom_tulip_cb"
#define DRV_VERSION "0.91+LK1.1"
#define DRV_RELDATE "October 11, 2001"
#define CARDBUS 1
#define DRV_VERSION "0.92"
#define DRV_RELDATE "June 27, 2006"
/* A few user-configurable values. */
@ -306,10 +291,10 @@ struct xircom_private {
struct xircom_tx_desc tx_ring[TX_RING_SIZE];
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
struct sk_buff* tx_skbuff[TX_RING_SIZE];
#ifdef CARDBUS
/* The X3201-3 requires 4-byte aligned tx bufs */
struct sk_buff* tx_aligned_skbuff[TX_RING_SIZE];
#endif
/* The addresses of receive-in-place skbuffs. */
struct sk_buff* rx_skbuff[RX_RING_SIZE];
u16 setup_frame[PKT_SETUP_SZ / sizeof(u16)]; /* Pseudo-Tx frame to init address table. */
@ -908,10 +893,8 @@ static void xircom_init_ring(struct net_device *dev)
tp->tx_skbuff[i] = NULL;
tp->tx_ring[i].status = 0;
tp->tx_ring[i].buffer2 = virt_to_bus(&tp->tx_ring[i+1]);
#ifdef CARDBUS
if (tp->chip_id == X3201_3)
tp->tx_aligned_skbuff[i] = dev_alloc_skb(PKT_BUF_SZ);
#endif /* CARDBUS */
}
tp->tx_ring[i-1].buffer2 = virt_to_bus(&tp->tx_ring[0]);
}
@ -931,12 +914,10 @@ xircom_start_xmit(struct sk_buff *skb, struct net_device *dev)
entry = tp->cur_tx % TX_RING_SIZE;
tp->tx_skbuff[entry] = skb;
#ifdef CARDBUS
if (tp->chip_id == X3201_3) {
memcpy(tp->tx_aligned_skbuff[entry]->data,skb->data,skb->len);
tp->tx_ring[entry].buffer1 = virt_to_bus(tp->tx_aligned_skbuff[entry]->data);
} else
#endif
tp->tx_ring[entry].buffer1 = virt_to_bus(skb->data);
if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */

View File

@ -25,117 +25,13 @@
version. He may or may not be interested in bug reports on this
code. You can find his versions at:
http://www.scyld.com/network/via-rhine.html
Linux kernel version history:
LK1.1.0:
- Jeff Garzik: softnet 'n stuff
LK1.1.1:
- Justin Guyett: softnet and locking fixes
- Jeff Garzik: use PCI interface
LK1.1.2:
- Urban Widmark: minor cleanups, merges from Becker 1.03a/1.04 versions
LK1.1.3:
- Urban Widmark: use PCI DMA interface (with thanks to the eepro100.c
code) update "Theory of Operation" with
softnet/locking changes
- Dave Miller: PCI DMA and endian fixups
- Jeff Garzik: MOD_xxx race fixes, updated PCI resource allocation
LK1.1.4:
- Urban Widmark: fix gcc 2.95.2 problem and
remove writel's to fixed address 0x7c
LK1.1.5:
- Urban Widmark: mdio locking, bounce buffer changes
merges from Beckers 1.05 version
added netif_running_on/off support
LK1.1.6:
- Urban Widmark: merges from Beckers 1.08b version (VT6102 + mdio)
set netif_running_on/off on startup, del_timer_sync
LK1.1.7:
- Manfred Spraul: added reset into tx_timeout
LK1.1.9:
- Urban Widmark: merges from Beckers 1.10 version
(media selection + eeprom reload)
- David Vrabel: merges from D-Link "1.11" version
(disable WOL and PME on startup)
LK1.1.10:
- Manfred Spraul: use "singlecopy" for unaligned buffers
don't allocate bounce buffers for !ReqTxAlign cards
LK1.1.11:
- David Woodhouse: Set dev->base_addr before the first time we call
wait_for_reset(). It's a lot happier that way.
Free np->tx_bufs only if we actually allocated it.
LK1.1.12:
- Martin Eriksson: Allow Memory-Mapped IO to be enabled.
LK1.1.13 (jgarzik):
- Add ethtool support
- Replace some MII-related magic numbers with constants
LK1.1.14 (Ivan G.):
- fixes comments for Rhine-III
- removes W_MAX_TIMEOUT (unused)
- adds HasDavicomPhy for Rhine-I (basis: linuxfet driver; my card
is R-I and has Davicom chip, flag is referenced in kernel driver)
- sends chip_id as a parameter to wait_for_reset since np is not
initialized on first call
- changes mmio "else if (chip_id==VT6102)" to "else" so it will work
for Rhine-III's (documentation says same bit is correct)
- transmit frame queue message is off by one - fixed
- adds IntrNormalSummary to "Something Wicked" exclusion list
so normal interrupts will not trigger the message (src: Donald Becker)
(Roger Luethi)
- show confused chip where to continue after Tx error
- location of collision counter is chip specific
- allow selecting backoff algorithm (module parameter)
LK1.1.15 (jgarzik):
- Use new MII lib helper generic_mii_ioctl
LK1.1.16 (Roger Luethi)
- Etherleak fix
- Handle Tx buffer underrun
- Fix bugs in full duplex handling
- New reset code uses "force reset" cmd on Rhine-II
- Various clean ups
LK1.1.17 (Roger Luethi)
- Fix race in via_rhine_start_tx()
- On errors, wait for Tx engine to turn off before scavenging
- Handle Tx descriptor write-back race on Rhine-II
- Force flushing for PCI posted writes
- More reset code changes
LK1.1.18 (Roger Luethi)
- No filtering multicast in promisc mode (Edward Peng)
- Fix for Rhine-I Tx timeouts
LK1.1.19 (Roger Luethi)
- Increase Tx threshold for unspecified errors
LK1.2.0-2.6 (Roger Luethi)
- Massive clean-up
- Rewrite PHY, media handling (remove options, full_duplex, backoff)
- Fix Tx engine race for good
- Craig Brind: Zero padded aligned buffers for short packets.
[link no longer provides useful info -jgarzik]
*/
#define DRV_NAME "via-rhine"
#define DRV_VERSION "1.2.0-2.6"
#define DRV_RELDATE "June-10-2004"
#define DRV_VERSION "1.4.0"
#define DRV_RELDATE "June-27-2006"
/* A few user-configurable values.
@ -356,12 +252,11 @@ enum rhine_quirks {
/* Beware of PCI posted writes */
#define IOSYNC do { ioread8(ioaddr + StationAddr); } while (0)
static struct pci_device_id rhine_pci_tbl[] =
{
{0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT86C100A */
{0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT6102 */
{0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* 6105{,L,LOM} */
{0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, /* VT6105M */
static const struct pci_device_id rhine_pci_tbl[] = {
{ 0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, }, /* VT86C100A */
{ 0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, }, /* VT6102 */
{ 0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, }, /* 6105{,L,LOM} */
{ 0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, }, /* VT6105M */
{ } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, rhine_pci_tbl);

View File

@ -229,7 +229,8 @@ static int rx_copybreak = 200;
module_param(rx_copybreak, int, 0644);
MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, struct velocity_info_tbl *info);
static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr,
const struct velocity_info_tbl *info);
static int velocity_get_pci_info(struct velocity_info *, struct pci_dev *pdev);
static void velocity_print_info(struct velocity_info *vptr);
static int velocity_open(struct net_device *dev);
@ -294,9 +295,9 @@ static void velocity_unregister_notifier(void)
* Internal board variants. At the moment we have only one
*/
static struct velocity_info_tbl chip_info_table[] = {
{CHIP_TYPE_VT6110, "VIA Networking Velocity Family Gigabit Ethernet Adapter", 256, 1, 0x00FFFFFFUL},
{0, NULL}
static const struct velocity_info_tbl chip_info_table[] __devinitdata = {
{CHIP_TYPE_VT6110, "VIA Networking Velocity Family Gigabit Ethernet Adapter", 1, 0x00FFFFFFUL},
{ }
};
/*
@ -304,10 +305,9 @@ static struct velocity_info_tbl chip_info_table[] = {
* device driver. Used for hotplug autoloading.
*/
static struct pci_device_id velocity_id_table[] __devinitdata = {
{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) chip_info_table},
{0, }
static const struct pci_device_id velocity_id_table[] __devinitdata = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X) },
{ }
};
MODULE_DEVICE_TABLE(pci, velocity_id_table);
@ -341,7 +341,7 @@ static char __devinit *get_chip_name(enum chip_type chip_id)
static void __devexit velocity_remove1(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
#ifdef CONFIG_PM
unsigned long flags;
@ -686,21 +686,23 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
static int first = 1;
struct net_device *dev;
int i;
struct velocity_info_tbl *info = (struct velocity_info_tbl *) ent->driver_data;
const struct velocity_info_tbl *info = &chip_info_table[ent->driver_data];
struct velocity_info *vptr;
struct mac_regs __iomem * regs;
int ret = -ENOMEM;
/* FIXME: this driver, like almost all other ethernet drivers,
* can support more than MAX_UNITS.
*/
if (velocity_nics >= MAX_UNITS) {
printk(KERN_NOTICE VELOCITY_NAME ": already found %d NICs.\n",
velocity_nics);
dev_notice(&pdev->dev, "already found %d NICs.\n",
velocity_nics);
return -ENODEV;
}
dev = alloc_etherdev(sizeof(struct velocity_info));
if (dev == NULL) {
printk(KERN_ERR VELOCITY_NAME ": allocate net device failed.\n");
if (!dev) {
dev_err(&pdev->dev, "allocate net device failed.\n");
goto out;
}
@ -708,7 +710,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
vptr = dev->priv;
vptr = netdev_priv(dev);
if (first) {
@ -731,17 +733,17 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
ret = velocity_get_pci_info(vptr, pdev);
if (ret < 0) {
printk(KERN_ERR VELOCITY_NAME ": Failed to find PCI device.\n");
/* error message already printed */
goto err_disable;
}
ret = pci_request_regions(pdev, VELOCITY_NAME);
if (ret < 0) {
printk(KERN_ERR VELOCITY_NAME ": Failed to find PCI device.\n");
dev_err(&pdev->dev, "No PCI resources.\n");
goto err_disable;
}
regs = ioremap(vptr->memaddr, vptr->io_size);
regs = ioremap(vptr->memaddr, VELOCITY_IO_SIZE);
if (regs == NULL) {
ret = -EIO;
goto err_release_res;
@ -859,13 +861,14 @@ static void __devinit velocity_print_info(struct velocity_info *vptr)
* discovered.
*/
static void __devinit velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, struct velocity_info_tbl *info)
static void __devinit velocity_init_info(struct pci_dev *pdev,
struct velocity_info *vptr,
const struct velocity_info_tbl *info)
{
memset(vptr, 0, sizeof(struct velocity_info));
vptr->pdev = pdev;
vptr->chip_id = info->chip_id;
vptr->io_size = info->io_size;
vptr->num_txq = info->txqueue;
vptr->multicast_limit = MCAM_SIZE;
spin_lock_init(&vptr->lock);
@ -883,8 +886,7 @@ static void __devinit velocity_init_info(struct pci_dev *pdev, struct velocity_i
static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev)
{
if(pci_read_config_byte(pdev, PCI_REVISION_ID, &vptr->rev_id) < 0)
if (pci_read_config_byte(pdev, PCI_REVISION_ID, &vptr->rev_id) < 0)
return -EIO;
pci_set_master(pdev);
@ -892,24 +894,20 @@ static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pc
vptr->ioaddr = pci_resource_start(pdev, 0);
vptr->memaddr = pci_resource_start(pdev, 1);
if(!(pci_resource_flags(pdev, 0) & IORESOURCE_IO))
{
printk(KERN_ERR "%s: region #0 is not an I/O resource, aborting.\n",
pci_name(pdev));
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) {
dev_err(&pdev->dev,
"region #0 is not an I/O resource, aborting.\n");
return -EINVAL;
}
if((pci_resource_flags(pdev, 1) & IORESOURCE_IO))
{
printk(KERN_ERR "%s: region #1 is an I/O resource, aborting.\n",
pci_name(pdev));
if ((pci_resource_flags(pdev, 1) & IORESOURCE_IO)) {
dev_err(&pdev->dev,
"region #1 is an I/O resource, aborting.\n");
return -EINVAL;
}
if(pci_resource_len(pdev, 1) < 256)
{
printk(KERN_ERR "%s: region #1 is too small.\n",
pci_name(pdev));
if (pci_resource_len(pdev, 1) < VELOCITY_IO_SIZE) {
dev_err(&pdev->dev, "region #1 is too small.\n");
return -EINVAL;
}
vptr->pdev = pdev;
@ -1728,7 +1726,7 @@ static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_
static int velocity_open(struct net_device *dev)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
int ret;
vptr->rx_buf_sz = (dev->mtu <= 1504 ? PKT_BUF_SZ : dev->mtu + 32);
@ -1785,7 +1783,7 @@ err_free_desc_rings:
static int velocity_change_mtu(struct net_device *dev, int new_mtu)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
unsigned long flags;
int oldmtu = dev->mtu;
int ret = 0;
@ -1861,7 +1859,7 @@ static void velocity_shutdown(struct velocity_info *vptr)
static int velocity_close(struct net_device *dev)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
netif_stop_queue(dev);
velocity_shutdown(vptr);
@ -1894,7 +1892,7 @@ static int velocity_close(struct net_device *dev)
static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
int qnum = 0;
struct tx_desc *td_ptr;
struct velocity_td_info *tdinfo;
@ -2049,7 +2047,7 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
static int velocity_intr(int irq, void *dev_instance, struct pt_regs *regs)
{
struct net_device *dev = dev_instance;
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
u32 isr_status;
int max_count = 0;
@ -2104,7 +2102,7 @@ static int velocity_intr(int irq, void *dev_instance, struct pt_regs *regs)
static void velocity_set_multi(struct net_device *dev)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
struct mac_regs __iomem * regs = vptr->mac_regs;
u8 rx_mode;
int i;
@ -2153,7 +2151,7 @@ static void velocity_set_multi(struct net_device *dev)
static struct net_device_stats *velocity_get_stats(struct net_device *dev)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
/* If the hardware is down, don't touch MII */
if(!netif_running(dev))
@ -2196,7 +2194,7 @@ static struct net_device_stats *velocity_get_stats(struct net_device *dev)
static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
int ret;
/* If we are asked for information and the device is power
@ -2825,7 +2823,7 @@ static void enable_flow_control_ability(struct velocity_info *vptr)
static int velocity_ethtool_up(struct net_device *dev)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
if (!netif_running(dev))
pci_set_power_state(vptr->pdev, PCI_D0);
return 0;
@ -2841,14 +2839,14 @@ static int velocity_ethtool_up(struct net_device *dev)
static void velocity_ethtool_down(struct net_device *dev)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
if (!netif_running(dev))
pci_set_power_state(vptr->pdev, PCI_D3hot);
}
static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
struct mac_regs __iomem * regs = vptr->mac_regs;
u32 status;
status = check_connection_type(vptr->mac_regs);
@ -2873,7 +2871,7 @@ static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd
static int velocity_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
u32 curr_status;
u32 new_status = 0;
int ret = 0;
@ -2896,14 +2894,14 @@ static int velocity_set_settings(struct net_device *dev, struct ethtool_cmd *cmd
static u32 velocity_get_link(struct net_device *dev)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
struct mac_regs __iomem * regs = vptr->mac_regs;
return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, &regs->PHYSR0) ? 0 : 1;
}
static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
strcpy(info->driver, VELOCITY_NAME);
strcpy(info->version, VELOCITY_VERSION);
strcpy(info->bus_info, pci_name(vptr->pdev));
@ -2911,7 +2909,7 @@ static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo
static void velocity_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
wol->supported = WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_ARP;
wol->wolopts |= WAKE_MAGIC;
/*
@ -2927,7 +2925,7 @@ static void velocity_ethtool_get_wol(struct net_device *dev, struct ethtool_woli
static int velocity_ethtool_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
if (!(wol->wolopts & (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_ARP)))
return -EFAULT;
@ -2992,7 +2990,7 @@ static struct ethtool_ops velocity_ethtool_ops = {
static int velocity_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct velocity_info *vptr = dev->priv;
struct velocity_info *vptr = netdev_priv(dev);
struct mac_regs __iomem * regs = vptr->mac_regs;
unsigned long flags;
struct mii_ioctl_data *miidata = if_mii(ifr);

View File

@ -31,6 +31,8 @@
#define VELOCITY_FULL_DRV_NAM "VIA Networking Velocity Family Gigabit Ethernet Adapter Driver"
#define VELOCITY_VERSION "1.13"
#define VELOCITY_IO_SIZE 256
#define PKT_BUF_SZ 1540
#define MAX_UNITS 8
@ -1191,7 +1193,6 @@ enum chip_type {
struct velocity_info_tbl {
enum chip_type chip_id;
char *name;
int io_size;
int txqueue;
u32 flags;
};
@ -1751,7 +1752,6 @@ struct velocity_info {
struct mac_regs __iomem * mac_regs;
unsigned long memaddr;
unsigned long ioaddr;
u32 io_size;
u8 rev_id;

View File

@ -134,18 +134,6 @@ config SEALEVEL_4021
The driver will be compiled as a module: the
module will be called sealevel.
config SYNCLINK_SYNCPPP
tristate "SyncLink HDLC/SYNCPPP support"
depends on WAN
help
Enables HDLC/SYNCPPP support for the SyncLink WAN driver.
Normally the SyncLink WAN driver works with the main PPP driver
<file:drivers/net/ppp_generic.c> and pppd program.
HDLC/SYNCPPP support allows use of the Cisco HDLC/PPP driver
<file:drivers/net/wan/syncppp.c>. The SyncLink WAN driver (in
character devices) must also be enabled.
# Generic HDLC
config HDLC
tristate "Generic HDLC layer"

View File

@ -28,7 +28,6 @@ obj-$(CONFIG_COSA) += syncppp.o cosa.o
obj-$(CONFIG_FARSYNC) += syncppp.o farsync.o
obj-$(CONFIG_DSCC4) += dscc4.o
obj-$(CONFIG_LANMEDIA) += syncppp.o
obj-$(CONFIG_SYNCLINK_SYNCPPP) += syncppp.o
obj-$(CONFIG_X25_ASY) += x25_asy.o
obj-$(CONFIG_LANMEDIA) += lmc/

View File

@ -550,6 +550,7 @@ config USB_ZD1201
source "drivers/net/wireless/hostap/Kconfig"
source "drivers/net/wireless/bcm43xx/Kconfig"
source "drivers/net/wireless/zd1211rw/Kconfig"
# yes, this works even when no drivers are selected
config NET_WIRELESS

View File

@ -36,6 +36,7 @@ obj-$(CONFIG_PRISM54) += prism54/
obj-$(CONFIG_HOSTAP) += hostap/
obj-$(CONFIG_BCM43XX) += bcm43xx/
obj-$(CONFIG_ZD1211RW) += zd1211rw/
# 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o

View File

@ -1885,6 +1885,15 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re
spin_lock(&bcm->irq_lock);
/* Only accept IRQs, if we are initialized properly.
* This avoids an RX race while initializing.
* We should probably not enable IRQs before we are initialized
* completely, but some careful work is needed to fix this. I think it
* is best to stay with this cheap workaround for now... .
*/
if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED))
goto out;
reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
if (reason == 0xffffffff) {
/* irq not for us (shared irq) */
@ -1906,19 +1915,11 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re
bcm43xx_interrupt_ack(bcm, reason);
/* Only accept IRQs, if we are initialized properly.
* This avoids an RX race while initializing.
* We should probably not enable IRQs before we are initialized
* completely, but some careful work is needed to fix this. I think it
* is best to stay with this cheap workaround for now... .
*/
if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
/* disable all IRQs. They are enabled again in the bottom half. */
bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
/* save the reason code and call our bottom half. */
bcm->irq_reason = reason;
tasklet_schedule(&bcm->isr_tasklet);
}
/* disable all IRQs. They are enabled again in the bottom half. */
bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
/* save the reason code and call our bottom half. */
bcm->irq_reason = reason;
tasklet_schedule(&bcm->isr_tasklet);
out:
mmiowb();
@ -3698,6 +3699,10 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
secinfo->encrypt = sec->encrypt;
dprintk(", .encrypt = %d", sec->encrypt);
}
if (sec->flags & SEC_AUTH_MODE) {
secinfo->auth_mode = sec->auth_mode;
dprintk(", .auth_mode = %d\n", sec->auth_mode);
}
dprintk("\n");
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED &&
!bcm->ieee->host_encrypt) {

View File

@ -112,30 +112,6 @@ int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm,
return bcm43xx_channel_to_freq_bg(channel);
}
/* Lightweight function to check if a channel number is valid.
* Note that this does _NOT_ check for geographical restrictions!
*/
static inline
int bcm43xx_is_valid_channel_a(u8 channel)
{
return (channel >= IEEE80211_52GHZ_MIN_CHANNEL
&& channel <= IEEE80211_52GHZ_MAX_CHANNEL);
}
static inline
int bcm43xx_is_valid_channel_bg(u8 channel)
{
return (channel >= IEEE80211_24GHZ_MIN_CHANNEL
&& channel <= IEEE80211_24GHZ_MAX_CHANNEL);
}
static inline
int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm,
u8 channel)
{
if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
return bcm43xx_is_valid_channel_a(channel);
return bcm43xx_is_valid_channel_bg(channel);
}
void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf);
void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf);

View File

@ -1594,11 +1594,11 @@ int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,
u16 r8, tmp;
u16 freq;
if (!ieee80211_is_valid_channel(bcm->ieee, channel))
return -EINVAL;
if ((radio->manufact == 0x17F) &&
(radio->version == 0x2060) &&
(radio->revision == 1)) {
if (channel > 200)
return -EINVAL;
freq = channel2freq_a(channel);
r8 = bcm43xx_radio_read16(bcm, 0x0008);
@ -1651,9 +1651,6 @@ int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,
TODO(); //TODO: TSSI2dbm workaround
bcm43xx_phy_xmitpower(bcm);//FIXME correct?
} else {
if ((channel < 1) || (channel > 14))
return -EINVAL;
if (synthetic_pu_workaround)
bcm43xx_synth_pu_workaround(bcm, channel);

View File

@ -119,7 +119,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
channel = bcm43xx_freq_to_channel(bcm, data->freq.m);
freq = data->freq.m;
}
if (!bcm43xx_is_valid_channel(bcm, channel))
if (!ieee80211_is_valid_channel(bcm->ieee, channel))
goto out_unlock;
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
//ieee80211softmac_disassoc(softmac, $REASON);

View File

@ -296,11 +296,14 @@ void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
u16 control = 0;
u16 wsec_rate = 0;
u16 encrypt_frame;
const u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(wireless_header->frame_ctl));
const int is_mgt = (ftype == IEEE80211_FTYPE_MGMT);
/* Now construct the TX header. */
memset(txhdr, 0, sizeof(*txhdr));
bitrate = bcm->softmac->txrates.default_rate;
bitrate = ieee80211softmac_suggest_txrate(bcm->softmac,
is_multicast_ether_addr(wireless_header->addr1), is_mgt);
ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));

View File

@ -66,10 +66,12 @@ static struct pci_device_id prism2_plx_id_table[] __devinitdata = {
PLXDEV(0x10b7, 0x7770, "3Com AirConnect PCI 777A"),
PLXDEV(0x111a, 0x1023, "Siemens SpeedStream SS1023"),
PLXDEV(0x126c, 0x8030, "Nortel emobility"),
PLXDEV(0x1562, 0x0001, "Symbol LA-4123"),
PLXDEV(0x1385, 0x4100, "Netgear MA301"),
PLXDEV(0x15e8, 0x0130, "National Datacomm NCP130 (PLX9052)"),
PLXDEV(0x15e8, 0x0131, "National Datacomm NCP130 (TMD7160)"),
PLXDEV(0x1638, 0x1100, "Eumitcom WL11000"),
PLXDEV(0x16ab, 0x1100, "Global Sun Tech GL24110P"),
PLXDEV(0x16ab, 0x1101, "Global Sun Tech GL24110P (?)"),
PLXDEV(0x16ab, 0x1102, "Linksys WPC11 with WDT11"),
PLXDEV(0x16ab, 0x1103, "Longshine 8031"),

View File

@ -0,0 +1,19 @@
config ZD1211RW
tristate "ZyDAS ZD1211/ZD1211B USB-wireless support"
depends on USB && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL
select FW_LOADER
---help---
This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless
chip, present in many USB-wireless adapters.
Device firmware is required alongside this driver. You can download the
firmware distribution from http://zd1211.ath.cx/get-firmware
config ZD1211RW_DEBUG
bool "ZyDAS ZD1211 debugging"
depends on ZD1211RW
---help---
ZD1211 debugging messages. Choosing Y will result in additional debug
messages being saved to your kernel logs, which may help debug any
problems.

View File

@ -0,0 +1,11 @@
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.o zd_usb.o zd_util.o
ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,825 @@
/* zd_chip.h
*
* 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
*/
#ifndef _ZD_CHIP_H
#define _ZD_CHIP_H
#include "zd_types.h"
#include "zd_rf.h"
#include "zd_usb.h"
/* Header for the Media Access Controller (MAC) and the Baseband Processor
* (BBP). It appears that the ZD1211 wraps the old ZD1205 with USB glue and
* adds a processor for handling the USB protocol.
*/
/* 8-bit hardware registers */
#define CR0 CTL_REG(0x0000)
#define CR1 CTL_REG(0x0004)
#define CR2 CTL_REG(0x0008)
#define CR3 CTL_REG(0x000C)
#define CR5 CTL_REG(0x0010)
/* bit 5: if set short preamble used
* bit 6: filter band - Japan channel 14 on, else off
*/
#define CR6 CTL_REG(0x0014)
#define CR7 CTL_REG(0x0018)
#define CR8 CTL_REG(0x001C)
#define CR4 CTL_REG(0x0020)
#define CR9 CTL_REG(0x0024)
/* bit 2: antenna switch (together with CR10) */
#define CR10 CTL_REG(0x0028)
/* bit 1: antenna switch (together with CR9)
* RF2959 controls with CR11 radion on and off
*/
#define CR11 CTL_REG(0x002C)
/* bit 6: TX power control for OFDM
* RF2959 controls with CR10 radio on and off
*/
#define CR12 CTL_REG(0x0030)
#define CR13 CTL_REG(0x0034)
#define CR14 CTL_REG(0x0038)
#define CR15 CTL_REG(0x003C)
#define CR16 CTL_REG(0x0040)
#define CR17 CTL_REG(0x0044)
#define CR18 CTL_REG(0x0048)
#define CR19 CTL_REG(0x004C)
#define CR20 CTL_REG(0x0050)
#define CR21 CTL_REG(0x0054)
#define CR22 CTL_REG(0x0058)
#define CR23 CTL_REG(0x005C)
#define CR24 CTL_REG(0x0060) /* CCA threshold */
#define CR25 CTL_REG(0x0064)
#define CR26 CTL_REG(0x0068)
#define CR27 CTL_REG(0x006C)
#define CR28 CTL_REG(0x0070)
#define CR29 CTL_REG(0x0074)
#define CR30 CTL_REG(0x0078)
#define CR31 CTL_REG(0x007C) /* TX power control for RF in CCK mode */
#define CR32 CTL_REG(0x0080)
#define CR33 CTL_REG(0x0084)
#define CR34 CTL_REG(0x0088)
#define CR35 CTL_REG(0x008C)
#define CR36 CTL_REG(0x0090)
#define CR37 CTL_REG(0x0094)
#define CR38 CTL_REG(0x0098)
#define CR39 CTL_REG(0x009C)
#define CR40 CTL_REG(0x00A0)
#define CR41 CTL_REG(0x00A4)
#define CR42 CTL_REG(0x00A8)
#define CR43 CTL_REG(0x00AC)
#define CR44 CTL_REG(0x00B0)
#define CR45 CTL_REG(0x00B4)
#define CR46 CTL_REG(0x00B8)
#define CR47 CTL_REG(0x00BC) /* CCK baseband gain
* (patch value might be in EEPROM)
*/
#define CR48 CTL_REG(0x00C0)
#define CR49 CTL_REG(0x00C4)
#define CR50 CTL_REG(0x00C8)
#define CR51 CTL_REG(0x00CC) /* TX power control for RF in 6-36M modes */
#define CR52 CTL_REG(0x00D0) /* TX power control for RF in 48M mode */
#define CR53 CTL_REG(0x00D4) /* TX power control for RF in 54M mode */
#define CR54 CTL_REG(0x00D8)
#define CR55 CTL_REG(0x00DC)
#define CR56 CTL_REG(0x00E0)
#define CR57 CTL_REG(0x00E4)
#define CR58 CTL_REG(0x00E8)
#define CR59 CTL_REG(0x00EC)
#define CR60 CTL_REG(0x00F0)
#define CR61 CTL_REG(0x00F4)
#define CR62 CTL_REG(0x00F8)
#define CR63 CTL_REG(0x00FC)
#define CR64 CTL_REG(0x0100)
#define CR65 CTL_REG(0x0104) /* OFDM 54M calibration */
#define CR66 CTL_REG(0x0108) /* OFDM 48M calibration */
#define CR67 CTL_REG(0x010C) /* OFDM 36M calibration */
#define CR68 CTL_REG(0x0110) /* CCK calibration */
#define CR69 CTL_REG(0x0114)
#define CR70 CTL_REG(0x0118)
#define CR71 CTL_REG(0x011C)
#define CR72 CTL_REG(0x0120)
#define CR73 CTL_REG(0x0124)
#define CR74 CTL_REG(0x0128)
#define CR75 CTL_REG(0x012C)
#define CR76 CTL_REG(0x0130)
#define CR77 CTL_REG(0x0134)
#define CR78 CTL_REG(0x0138)
#define CR79 CTL_REG(0x013C)
#define CR80 CTL_REG(0x0140)
#define CR81 CTL_REG(0x0144)
#define CR82 CTL_REG(0x0148)
#define CR83 CTL_REG(0x014C)
#define CR84 CTL_REG(0x0150)
#define CR85 CTL_REG(0x0154)
#define CR86 CTL_REG(0x0158)
#define CR87 CTL_REG(0x015C)
#define CR88 CTL_REG(0x0160)
#define CR89 CTL_REG(0x0164)
#define CR90 CTL_REG(0x0168)
#define CR91 CTL_REG(0x016C)
#define CR92 CTL_REG(0x0170)
#define CR93 CTL_REG(0x0174)
#define CR94 CTL_REG(0x0178)
#define CR95 CTL_REG(0x017C)
#define CR96 CTL_REG(0x0180)
#define CR97 CTL_REG(0x0184)
#define CR98 CTL_REG(0x0188)
#define CR99 CTL_REG(0x018C)
#define CR100 CTL_REG(0x0190)
#define CR101 CTL_REG(0x0194)
#define CR102 CTL_REG(0x0198)
#define CR103 CTL_REG(0x019C)
#define CR104 CTL_REG(0x01A0)
#define CR105 CTL_REG(0x01A4)
#define CR106 CTL_REG(0x01A8)
#define CR107 CTL_REG(0x01AC)
#define CR108 CTL_REG(0x01B0)
#define CR109 CTL_REG(0x01B4)
#define CR110 CTL_REG(0x01B8)
#define CR111 CTL_REG(0x01BC)
#define CR112 CTL_REG(0x01C0)
#define CR113 CTL_REG(0x01C4)
#define CR114 CTL_REG(0x01C8)
#define CR115 CTL_REG(0x01CC)
#define CR116 CTL_REG(0x01D0)
#define CR117 CTL_REG(0x01D4)
#define CR118 CTL_REG(0x01D8)
#define CR119 CTL_REG(0x01DC)
#define CR120 CTL_REG(0x01E0)
#define CR121 CTL_REG(0x01E4)
#define CR122 CTL_REG(0x01E8)
#define CR123 CTL_REG(0x01EC)
#define CR124 CTL_REG(0x01F0)
#define CR125 CTL_REG(0x01F4)
#define CR126 CTL_REG(0x01F8)
#define CR127 CTL_REG(0x01FC)
#define CR128 CTL_REG(0x0200)
#define CR129 CTL_REG(0x0204)
#define CR130 CTL_REG(0x0208)
#define CR131 CTL_REG(0x020C)
#define CR132 CTL_REG(0x0210)
#define CR133 CTL_REG(0x0214)
#define CR134 CTL_REG(0x0218)
#define CR135 CTL_REG(0x021C)
#define CR136 CTL_REG(0x0220)
#define CR137 CTL_REG(0x0224)
#define CR138 CTL_REG(0x0228)
#define CR139 CTL_REG(0x022C)
#define CR140 CTL_REG(0x0230)
#define CR141 CTL_REG(0x0234)
#define CR142 CTL_REG(0x0238)
#define CR143 CTL_REG(0x023C)
#define CR144 CTL_REG(0x0240)
#define CR145 CTL_REG(0x0244)
#define CR146 CTL_REG(0x0248)
#define CR147 CTL_REG(0x024C)
#define CR148 CTL_REG(0x0250)
#define CR149 CTL_REG(0x0254)
#define CR150 CTL_REG(0x0258)
#define CR151 CTL_REG(0x025C)
#define CR152 CTL_REG(0x0260)
#define CR153 CTL_REG(0x0264)
#define CR154 CTL_REG(0x0268)
#define CR155 CTL_REG(0x026C)
#define CR156 CTL_REG(0x0270)
#define CR157 CTL_REG(0x0274)
#define CR158 CTL_REG(0x0278)
#define CR159 CTL_REG(0x027C)
#define CR160 CTL_REG(0x0280)
#define CR161 CTL_REG(0x0284)
#define CR162 CTL_REG(0x0288)
#define CR163 CTL_REG(0x028C)
#define CR164 CTL_REG(0x0290)
#define CR165 CTL_REG(0x0294)
#define CR166 CTL_REG(0x0298)
#define CR167 CTL_REG(0x029C)
#define CR168 CTL_REG(0x02A0)
#define CR169 CTL_REG(0x02A4)
#define CR170 CTL_REG(0x02A8)
#define CR171 CTL_REG(0x02AC)
#define CR172 CTL_REG(0x02B0)
#define CR173 CTL_REG(0x02B4)
#define CR174 CTL_REG(0x02B8)
#define CR175 CTL_REG(0x02BC)
#define CR176 CTL_REG(0x02C0)
#define CR177 CTL_REG(0x02C4)
#define CR178 CTL_REG(0x02C8)
#define CR179 CTL_REG(0x02CC)
#define CR180 CTL_REG(0x02D0)
#define CR181 CTL_REG(0x02D4)
#define CR182 CTL_REG(0x02D8)
#define CR183 CTL_REG(0x02DC)
#define CR184 CTL_REG(0x02E0)
#define CR185 CTL_REG(0x02E4)
#define CR186 CTL_REG(0x02E8)
#define CR187 CTL_REG(0x02EC)
#define CR188 CTL_REG(0x02F0)
#define CR189 CTL_REG(0x02F4)
#define CR190 CTL_REG(0x02F8)
#define CR191 CTL_REG(0x02FC)
#define CR192 CTL_REG(0x0300)
#define CR193 CTL_REG(0x0304)
#define CR194 CTL_REG(0x0308)
#define CR195 CTL_REG(0x030C)
#define CR196 CTL_REG(0x0310)
#define CR197 CTL_REG(0x0314)
#define CR198 CTL_REG(0x0318)
#define CR199 CTL_REG(0x031C)
#define CR200 CTL_REG(0x0320)
#define CR201 CTL_REG(0x0324)
#define CR202 CTL_REG(0x0328)
#define CR203 CTL_REG(0x032C) /* I2C bus template value & flash control */
#define CR204 CTL_REG(0x0330)
#define CR205 CTL_REG(0x0334)
#define CR206 CTL_REG(0x0338)
#define CR207 CTL_REG(0x033C)
#define CR208 CTL_REG(0x0340)
#define CR209 CTL_REG(0x0344)
#define CR210 CTL_REG(0x0348)
#define CR211 CTL_REG(0x034C)
#define CR212 CTL_REG(0x0350)
#define CR213 CTL_REG(0x0354)
#define CR214 CTL_REG(0x0358)
#define CR215 CTL_REG(0x035C)
#define CR216 CTL_REG(0x0360)
#define CR217 CTL_REG(0x0364)
#define CR218 CTL_REG(0x0368)
#define CR219 CTL_REG(0x036C)
#define CR220 CTL_REG(0x0370)
#define CR221 CTL_REG(0x0374)
#define CR222 CTL_REG(0x0378)
#define CR223 CTL_REG(0x037C)
#define CR224 CTL_REG(0x0380)
#define CR225 CTL_REG(0x0384)
#define CR226 CTL_REG(0x0388)
#define CR227 CTL_REG(0x038C)
#define CR228 CTL_REG(0x0390)
#define CR229 CTL_REG(0x0394)
#define CR230 CTL_REG(0x0398)
#define CR231 CTL_REG(0x039C)
#define CR232 CTL_REG(0x03A0)
#define CR233 CTL_REG(0x03A4)
#define CR234 CTL_REG(0x03A8)
#define CR235 CTL_REG(0x03AC)
#define CR236 CTL_REG(0x03B0)
#define CR240 CTL_REG(0x03C0)
/* bit 7: host-controlled RF register writes
* CR241-CR245: for hardware controlled writing of RF bits, not needed for
* USB
*/
#define CR241 CTL_REG(0x03C4)
#define CR242 CTL_REG(0x03C8)
#define CR243 CTL_REG(0x03CC)
#define CR244 CTL_REG(0x03D0)
#define CR245 CTL_REG(0x03D4)
#define CR251 CTL_REG(0x03EC) /* only used for activation and deactivation of
* Airoha RFs AL2230 and AL7230B
*/
#define CR252 CTL_REG(0x03F0)
#define CR253 CTL_REG(0x03F4)
#define CR254 CTL_REG(0x03F8)
#define CR255 CTL_REG(0x03FC)
#define CR_MAX_PHY_REG 255
/* Taken from the ZYDAS driver, not all of them are relevant for the ZSD1211
* driver.
*/
#define CR_RF_IF_CLK CTL_REG(0x0400)
#define CR_RF_IF_DATA CTL_REG(0x0404)
#define CR_PE1_PE2 CTL_REG(0x0408)
#define CR_PE2_DLY CTL_REG(0x040C)
#define CR_LE1 CTL_REG(0x0410)
#define CR_LE2 CTL_REG(0x0414)
/* Seems to enable/disable GPI (General Purpose IO?) */
#define CR_GPI_EN CTL_REG(0x0418)
#define CR_RADIO_PD CTL_REG(0x042C)
#define CR_RF2948_PD CTL_REG(0x042C)
#define CR_ENABLE_PS_MANUAL_AGC CTL_REG(0x043C)
#define CR_CONFIG_PHILIPS CTL_REG(0x0440)
#define CR_SA2400_SER_AP CTL_REG(0x0444)
#define CR_I2C_WRITE CTL_REG(0x0444)
#define CR_SA2400_SER_RP CTL_REG(0x0448)
#define CR_RADIO_PE CTL_REG(0x0458)
#define CR_RST_BUS_MASTER CTL_REG(0x045C)
#define CR_RFCFG CTL_REG(0x0464)
#define CR_HSTSCHG CTL_REG(0x046C)
#define CR_PHY_ON CTL_REG(0x0474)
#define CR_RX_DELAY CTL_REG(0x0478)
#define CR_RX_PE_DELAY CTL_REG(0x047C)
#define CR_GPIO_1 CTL_REG(0x0490)
#define CR_GPIO_2 CTL_REG(0x0494)
#define CR_EncryBufMux CTL_REG(0x04A8)
#define CR_PS_CTRL CTL_REG(0x0500)
#define CR_ADDA_PWR_DWN CTL_REG(0x0504)
#define CR_ADDA_MBIAS_WARMTIME CTL_REG(0x0508)
#define CR_MAC_PS_STATE CTL_REG(0x050C)
#define CR_INTERRUPT CTL_REG(0x0510)
#define INT_TX_COMPLETE 0x00000001
#define INT_RX_COMPLETE 0x00000002
#define INT_RETRY_FAIL 0x00000004
#define INT_WAKEUP 0x00000008
#define INT_DTIM_NOTIFY 0x00000020
#define INT_CFG_NEXT_BCN 0x00000040
#define INT_BUS_ABORT 0x00000080
#define INT_TX_FIFO_READY 0x00000100
#define INT_UART 0x00000200
#define INT_TX_COMPLETE_EN 0x00010000
#define INT_RX_COMPLETE_EN 0x00020000
#define INT_RETRY_FAIL_EN 0x00040000
#define INT_WAKEUP_EN 0x00080000
#define INT_DTIM_NOTIFY_EN 0x00200000
#define INT_CFG_NEXT_BCN_EN 0x00400000
#define INT_BUS_ABORT_EN 0x00800000
#define INT_TX_FIFO_READY_EN 0x01000000
#define INT_UART_EN 0x02000000
#define CR_TSF_LOW_PART CTL_REG(0x0514)
#define CR_TSF_HIGH_PART CTL_REG(0x0518)
/* Following three values are in time units (1024us)
* Following condition must be met:
* atim < tbtt < bcn
*/
#define CR_ATIM_WND_PERIOD CTL_REG(0x051C)
#define CR_BCN_INTERVAL CTL_REG(0x0520)
#define CR_PRE_TBTT CTL_REG(0x0524)
/* in units of TU(1024us) */
/* for UART support */
#define CR_UART_RBR_THR_DLL CTL_REG(0x0540)
#define CR_UART_DLM_IER CTL_REG(0x0544)
#define CR_UART_IIR_FCR CTL_REG(0x0548)
#define CR_UART_LCR CTL_REG(0x054c)
#define CR_UART_MCR CTL_REG(0x0550)
#define CR_UART_LSR CTL_REG(0x0554)
#define CR_UART_MSR CTL_REG(0x0558)
#define CR_UART_ECR CTL_REG(0x055c)
#define CR_UART_STATUS CTL_REG(0x0560)
#define CR_PCI_TX_ADDR_P1 CTL_REG(0x0600)
#define CR_PCI_TX_AddR_P2 CTL_REG(0x0604)
#define CR_PCI_RX_AddR_P1 CTL_REG(0x0608)
#define CR_PCI_RX_AddR_P2 CTL_REG(0x060C)
/* must be overwritten if custom MAC address will be used */
#define CR_MAC_ADDR_P1 CTL_REG(0x0610)
#define CR_MAC_ADDR_P2 CTL_REG(0x0614)
#define CR_BSSID_P1 CTL_REG(0x0618)
#define CR_BSSID_P2 CTL_REG(0x061C)
#define CR_BCN_PLCP_CFG CTL_REG(0x0620)
#define CR_GROUP_HASH_P1 CTL_REG(0x0624)
#define CR_GROUP_HASH_P2 CTL_REG(0x0628)
#define CR_RX_TIMEOUT CTL_REG(0x062C)
/* Basic rates supported by the BSS. When producing ACK or CTS messages, the
* device will use a rate in this table that is less than or equal to the rate
* of the incoming frame which prompted the response */
#define CR_BASIC_RATE_TBL CTL_REG(0x0630)
#define CR_RATE_1M 0x0001 /* 802.11b */
#define CR_RATE_2M 0x0002 /* 802.11b */
#define CR_RATE_5_5M 0x0004 /* 802.11b */
#define CR_RATE_11M 0x0008 /* 802.11b */
#define CR_RATE_6M 0x0100 /* 802.11g */
#define CR_RATE_9M 0x0200 /* 802.11g */
#define CR_RATE_12M 0x0400 /* 802.11g */
#define CR_RATE_18M 0x0800 /* 802.11g */
#define CR_RATE_24M 0x1000 /* 802.11g */
#define CR_RATE_36M 0x2000 /* 802.11g */
#define CR_RATE_48M 0x4000 /* 802.11g */
#define CR_RATE_54M 0x8000 /* 802.11g */
#define CR_RATES_80211G 0xff00
#define CR_RATES_80211B 0x000f
/* Mandatory rates required in the BSS. When producing ACK or CTS messages, if
* the device could not find an appropriate rate in CR_BASIC_RATE_TBL, it will
* look for a rate in this table that is less than or equal to the rate of
* the incoming frame. */
#define CR_MANDATORY_RATE_TBL CTL_REG(0x0634)
#define CR_RTS_CTS_RATE CTL_REG(0x0638)
#define CR_WEP_PROTECT CTL_REG(0x063C)
#define CR_RX_THRESHOLD CTL_REG(0x0640)
/* register for controlling the LEDS */
#define CR_LED CTL_REG(0x0644)
/* masks for controlling LEDs */
#define LED1 0x0100
#define LED2 0x0200
/* Seems to indicate that the configuration is over.
*/
#define CR_AFTER_PNP CTL_REG(0x0648)
#define CR_ACK_TIME_80211 CTL_REG(0x0658)
#define CR_RX_OFFSET CTL_REG(0x065c)
#define CR_PHY_DELAY CTL_REG(0x066C)
#define CR_BCN_FIFO CTL_REG(0x0670)
#define CR_SNIFFER_ON CTL_REG(0x0674)
#define CR_ENCRYPTION_TYPE CTL_REG(0x0678)
#define NO_WEP 0
#define WEP64 1
#define WEP128 5
#define WEP256 6
#define ENC_SNIFFER 8
#define CR_ZD1211_RETRY_MAX CTL_REG(0x067C)
#define CR_REG1 CTL_REG(0x0680)
/* Setting the bit UNLOCK_PHY_REGS disallows the write access to physical
* registers, so one could argue it is a LOCK bit. But calling it
* LOCK_PHY_REGS makes it confusing.
*/
#define UNLOCK_PHY_REGS 0x0080
#define CR_DEVICE_STATE CTL_REG(0x0684)
#define CR_UNDERRUN_CNT CTL_REG(0x0688)
#define CR_RX_FILTER CTL_REG(0x068c)
#define RX_FILTER_ASSOC_RESPONSE 0x0002
#define RX_FILTER_PROBE_RESPONSE 0x0020
#define RX_FILTER_BEACON 0x0100
#define RX_FILTER_AUTH 0x0800
/* Sniff modus sets filter to 0xfffff */
#define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690)
#define CR_BCN_FIFO_SEMAPHORE CTL_REG(0x0694)
#define CR_IFS_VALUE CTL_REG(0x0698)
#define CR_RX_TIME_OUT CTL_REG(0x069C)
#define CR_TOTAL_RX_FRM CTL_REG(0x06A0)
#define CR_CRC32_CNT CTL_REG(0x06A4)
#define CR_CRC16_CNT CTL_REG(0x06A8)
#define CR_DECRYPTION_ERR_UNI CTL_REG(0x06AC)
#define CR_RX_FIFO_OVERRUN CTL_REG(0x06B0)
#define CR_DECRYPTION_ERR_MUL CTL_REG(0x06BC)
#define CR_NAV_CNT CTL_REG(0x06C4)
#define CR_NAV_CCA CTL_REG(0x06C8)
#define CR_RETRY_CNT CTL_REG(0x06CC)
#define CR_READ_TCB_ADDR CTL_REG(0x06E8)
#define CR_READ_RFD_ADDR CTL_REG(0x06EC)
#define CR_CWMIN_CWMAX CTL_REG(0x06F0)
#define CR_TOTAL_TX_FRM CTL_REG(0x06F4)
/* CAM: Continuous Access Mode (power management) */
#define CR_CAM_MODE CTL_REG(0x0700)
#define CR_CAM_ROLL_TB_LOW CTL_REG(0x0704)
#define CR_CAM_ROLL_TB_HIGH CTL_REG(0x0708)
#define CR_CAM_ADDRESS CTL_REG(0x070C)
#define CR_CAM_DATA CTL_REG(0x0710)
#define CR_ROMDIR CTL_REG(0x0714)
#define CR_DECRY_ERR_FLG_LOW CTL_REG(0x0714)
#define CR_DECRY_ERR_FLG_HIGH CTL_REG(0x0718)
#define CR_WEPKEY0 CTL_REG(0x0720)
#define CR_WEPKEY1 CTL_REG(0x0724)
#define CR_WEPKEY2 CTL_REG(0x0728)
#define CR_WEPKEY3 CTL_REG(0x072C)
#define CR_WEPKEY4 CTL_REG(0x0730)
#define CR_WEPKEY5 CTL_REG(0x0734)
#define CR_WEPKEY6 CTL_REG(0x0738)
#define CR_WEPKEY7 CTL_REG(0x073C)
#define CR_WEPKEY8 CTL_REG(0x0740)
#define CR_WEPKEY9 CTL_REG(0x0744)
#define CR_WEPKEY10 CTL_REG(0x0748)
#define CR_WEPKEY11 CTL_REG(0x074C)
#define CR_WEPKEY12 CTL_REG(0x0750)
#define CR_WEPKEY13 CTL_REG(0x0754)
#define CR_WEPKEY14 CTL_REG(0x0758)
#define CR_WEPKEY15 CTL_REG(0x075c)
#define CR_TKIP_MODE CTL_REG(0x0760)
#define CR_EEPROM_PROTECT0 CTL_REG(0x0758)
#define CR_EEPROM_PROTECT1 CTL_REG(0x075C)
#define CR_DBG_FIFO_RD CTL_REG(0x0800)
#define CR_DBG_SELECT CTL_REG(0x0804)
#define CR_FIFO_Length CTL_REG(0x0808)
#define CR_RSSI_MGC CTL_REG(0x0810)
#define CR_PON CTL_REG(0x0818)
#define CR_RX_ON CTL_REG(0x081C)
#define CR_TX_ON CTL_REG(0x0820)
#define CR_CHIP_EN CTL_REG(0x0824)
#define CR_LO_SW CTL_REG(0x0828)
#define CR_TXRX_SW CTL_REG(0x082C)
#define CR_S_MD CTL_REG(0x0830)
#define CR_USB_DEBUG_PORT CTL_REG(0x0888)
#define CR_ZD1211B_TX_PWR_CTL1 CTL_REG(0x0b00)
#define CR_ZD1211B_TX_PWR_CTL2 CTL_REG(0x0b04)
#define CR_ZD1211B_TX_PWR_CTL3 CTL_REG(0x0b08)
#define CR_ZD1211B_TX_PWR_CTL4 CTL_REG(0x0b0c)
#define CR_ZD1211B_AIFS_CTL1 CTL_REG(0x0b10)
#define CR_ZD1211B_AIFS_CTL2 CTL_REG(0x0b14)
#define CR_ZD1211B_TXOP CTL_REG(0x0b20)
#define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28)
#define AP_RX_FILTER 0x0400feff
#define STA_RX_FILTER 0x0000ffff
#define CWIN_SIZE 0x007f043f
#define HWINT_ENABLED 0x004f0000
#define HWINT_DISABLED 0
#define E2P_PWR_INT_GUARD 8
#define E2P_CHANNEL_COUNT 14
/* If you compare this addresses with the ZYDAS orignal driver, please notify
* that we use word mapping for the EEPROM.
*/
/*
* Upper 16 bit contains the regulatory domain.
*/
#define E2P_SUBID E2P_REG(0x00)
#define E2P_POD E2P_REG(0x02)
#define E2P_MAC_ADDR_P1 E2P_REG(0x04)
#define E2P_MAC_ADDR_P2 E2P_REG(0x06)
#define E2P_PWR_CAL_VALUE1 E2P_REG(0x08)
#define E2P_PWR_CAL_VALUE2 E2P_REG(0x0a)
#define E2P_PWR_CAL_VALUE3 E2P_REG(0x0c)
#define E2P_PWR_CAL_VALUE4 E2P_REG(0x0e)
#define E2P_PWR_INT_VALUE1 E2P_REG(0x10)
#define E2P_PWR_INT_VALUE2 E2P_REG(0x12)
#define E2P_PWR_INT_VALUE3 E2P_REG(0x14)
#define E2P_PWR_INT_VALUE4 E2P_REG(0x16)
/* Contains a bit for each allowed channel. It gives for Europe (ETSI 0x30)
* also only 11 channels. */
#define E2P_ALLOWED_CHANNEL E2P_REG(0x18)
#define E2P_PHY_REG E2P_REG(0x1a)
#define E2P_DEVICE_VER E2P_REG(0x20)
#define E2P_36M_CAL_VALUE1 E2P_REG(0x28)
#define E2P_36M_CAL_VALUE2 E2P_REG(0x2a)
#define E2P_36M_CAL_VALUE3 E2P_REG(0x2c)
#define E2P_36M_CAL_VALUE4 E2P_REG(0x2e)
#define E2P_11A_INT_VALUE1 E2P_REG(0x30)
#define E2P_11A_INT_VALUE2 E2P_REG(0x32)
#define E2P_11A_INT_VALUE3 E2P_REG(0x34)
#define E2P_11A_INT_VALUE4 E2P_REG(0x36)
#define E2P_48M_CAL_VALUE1 E2P_REG(0x38)
#define E2P_48M_CAL_VALUE2 E2P_REG(0x3a)
#define E2P_48M_CAL_VALUE3 E2P_REG(0x3c)
#define E2P_48M_CAL_VALUE4 E2P_REG(0x3e)
#define E2P_48M_INT_VALUE1 E2P_REG(0x40)
#define E2P_48M_INT_VALUE2 E2P_REG(0x42)
#define E2P_48M_INT_VALUE3 E2P_REG(0x44)
#define E2P_48M_INT_VALUE4 E2P_REG(0x46)
#define E2P_54M_CAL_VALUE1 E2P_REG(0x48) /* ??? */
#define E2P_54M_CAL_VALUE2 E2P_REG(0x4a)
#define E2P_54M_CAL_VALUE3 E2P_REG(0x4c)
#define E2P_54M_CAL_VALUE4 E2P_REG(0x4e)
#define E2P_54M_INT_VALUE1 E2P_REG(0x50)
#define E2P_54M_INT_VALUE2 E2P_REG(0x52)
#define E2P_54M_INT_VALUE3 E2P_REG(0x54)
#define E2P_54M_INT_VALUE4 E2P_REG(0x56)
/* All 16 bit values */
#define FW_FIRMWARE_VER FW_REG(0)
/* non-zero if USB high speed connection */
#define FW_USB_SPEED FW_REG(1)
#define FW_FIX_TX_RATE FW_REG(2)
/* Seems to be able to control LEDs over the firmware */
#define FW_LINK_STATUS FW_REG(3)
#define FW_SOFT_RESET FW_REG(4)
#define FW_FLASH_CHK FW_REG(5)
enum {
CR_BASE_OFFSET = 0x9000,
FW_START_OFFSET = 0xee00,
FW_BASE_ADDR_OFFSET = FW_START_OFFSET + 0x1d,
EEPROM_START_OFFSET = 0xf800,
EEPROM_SIZE = 0x800, /* words */
LOAD_CODE_SIZE = 0xe, /* words */
LOAD_VECT_SIZE = 0x10000 - 0xfff7, /* words */
EEPROM_REGS_OFFSET = LOAD_CODE_SIZE + LOAD_VECT_SIZE,
E2P_BASE_OFFSET = EEPROM_START_OFFSET +
EEPROM_REGS_OFFSET,
};
#define FW_REG_TABLE_ADDR USB_ADDR(FW_START_OFFSET + 0x1d)
enum {
/* indices for ofdm_cal_values */
OFDM_36M_INDEX = 0,
OFDM_48M_INDEX = 1,
OFDM_54M_INDEX = 2,
};
struct zd_chip {
struct zd_usb usb;
struct zd_rf rf;
struct mutex mutex;
u8 e2p_mac[ETH_ALEN];
/* EepSetPoint in the vendor driver */
u8 pwr_cal_values[E2P_CHANNEL_COUNT];
/* integration values in the vendor driver */
u8 pwr_int_values[E2P_CHANNEL_COUNT];
/* SetPointOFDM in the vendor driver */
u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT];
u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
is_zd1211b:1;
};
static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb)
{
return container_of(usb, struct zd_chip, usb);
}
static inline struct zd_chip *zd_rf_to_chip(struct zd_rf *rf)
{
return container_of(rf, struct zd_chip, rf);
}
#define zd_chip_dev(chip) (&(chip)->usb.intf->dev)
void zd_chip_init(struct zd_chip *chip,
struct net_device *netdev,
struct usb_interface *intf);
void zd_chip_clear(struct zd_chip *chip);
int zd_chip_init_hw(struct zd_chip *chip, u8 device_type);
int zd_chip_reset(struct zd_chip *chip);
static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values,
const zd_addr_t *addresses,
unsigned int count)
{
ZD_ASSERT(mutex_is_locked(&chip->mutex));
return zd_usb_ioread16v(&chip->usb, values, addresses, count);
}
static inline int zd_ioread16_locked(struct zd_chip *chip, u16 *value,
const zd_addr_t addr)
{
ZD_ASSERT(mutex_is_locked(&chip->mutex));
return zd_usb_ioread16(&chip->usb, value, addr);
}
int zd_ioread32v_locked(struct zd_chip *chip, u32 *values,
const zd_addr_t *addresses, unsigned int count);
static inline int zd_ioread32_locked(struct zd_chip *chip, u32 *value,
const zd_addr_t addr)
{
return zd_ioread32v_locked(chip, value, (const zd_addr_t *)&addr, 1);
}
static inline int zd_iowrite16_locked(struct zd_chip *chip, u16 value,
zd_addr_t addr)
{
struct zd_ioreq16 ioreq;
ZD_ASSERT(mutex_is_locked(&chip->mutex));
ioreq.addr = addr;
ioreq.value = value;
return zd_usb_iowrite16v(&chip->usb, &ioreq, 1);
}
int zd_iowrite16a_locked(struct zd_chip *chip,
const struct zd_ioreq16 *ioreqs, unsigned int count);
int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
unsigned int count);
static inline int zd_iowrite32_locked(struct zd_chip *chip, u32 value,
zd_addr_t addr)
{
struct zd_ioreq32 ioreq;
ioreq.addr = addr;
ioreq.value = value;
return _zd_iowrite32v_locked(chip, &ioreq, 1);
}
int zd_iowrite32a_locked(struct zd_chip *chip,
const struct zd_ioreq32 *ioreqs, unsigned int count);
static inline int zd_rfwrite_locked(struct zd_chip *chip, u32 value, u8 bits)
{
ZD_ASSERT(mutex_is_locked(&chip->mutex));
return zd_usb_rfwrite(&chip->usb, value, bits);
}
int zd_rfwritev_locked(struct zd_chip *chip,
const u32* values, unsigned int count, u8 bits);
/* Locking functions for reading and writing registers.
* The different parameters are intentional.
*/
int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value);
int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value);
int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value);
int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value);
int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses,
u32 *values, unsigned int count);
int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
unsigned int count);
int zd_chip_set_channel(struct zd_chip *chip, u8 channel);
static inline u8 _zd_chip_get_channel(struct zd_chip *chip)
{
return chip->rf.channel;
}
u8 zd_chip_get_channel(struct zd_chip *chip);
int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain);
void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr);
int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr);
int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr);
int zd_chip_switch_radio_on(struct zd_chip *chip);
int zd_chip_switch_radio_off(struct zd_chip *chip);
int zd_chip_enable_int(struct zd_chip *chip);
void zd_chip_disable_int(struct zd_chip *chip);
int zd_chip_enable_rx(struct zd_chip *chip);
void zd_chip_disable_rx(struct zd_chip *chip);
int zd_chip_enable_hwint(struct zd_chip *chip);
int zd_chip_disable_hwint(struct zd_chip *chip);
static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type)
{
return zd_ioread32(chip, CR_ENCRYPTION_TYPE, type);
}
static inline int zd_set_encryption_type(struct zd_chip *chip, u32 type)
{
return zd_iowrite32(chip, CR_ENCRYPTION_TYPE, type);
}
static inline int zd_chip_get_basic_rates(struct zd_chip *chip, u16 *cr_rates)
{
return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates);
}
int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates);
static inline int zd_chip_set_rx_filter(struct zd_chip *chip, u32 filter)
{
return zd_iowrite32(chip, CR_RX_FILTER, filter);
}
int zd_chip_lock_phy_regs(struct zd_chip *chip);
int zd_chip_unlock_phy_regs(struct zd_chip *chip);
enum led_status {
LED_OFF = 0,
LED_ON = 1,
LED_FLIP = 2,
LED_STATUS = 3,
};
int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status);
int zd_chip_led_flip(struct zd_chip *chip, int led,
const unsigned int *phases_msecs, unsigned int count);
int zd_set_beacon_interval(struct zd_chip *chip, u32 interval);
static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval)
{
return zd_ioread32(chip, CR_BCN_INTERVAL, interval);
}
struct rx_status;
u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size,
const struct rx_status *status);
u8 zd_rx_strength_percent(u8 rssi);
u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
#endif /* _ZD_CHIP_H */

View File

@ -0,0 +1,48 @@
/* zd_def.h
*
* 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
*/
#ifndef _ZD_DEF_H
#define _ZD_DEF_H
#include <linux/kernel.h>
#include <linux/stringify.h>
#include <linux/device.h>
#include <linux/kernel.h>
#define dev_printk_f(level, dev, fmt, args...) \
dev_printk(level, dev, "%s() " fmt, __func__, ##args)
#ifdef DEBUG
# define dev_dbg_f(dev, fmt, args...) \
dev_printk_f(KERN_DEBUG, dev, fmt, ## args)
#else
# define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)
#endif /* DEBUG */
#ifdef DEBUG
# define ZD_ASSERT(x) \
do { \
if (!(x)) { \
pr_debug("%s:%d ASSERT %s VIOLATED!\n", \
__FILE__, __LINE__, __stringify(x)); \
} \
} while (0)
#else
# define ZD_ASSERT(x) do { } while (0)
#endif
#endif /* _ZD_DEF_H */

View File

@ -0,0 +1,191 @@
/* zd_ieee80211.c
*
* 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
*/
/*
* A lot of this code is generic and should be moved into the upper layers
* at some point.
*/
#include <linux/errno.h>
#include <linux/wireless.h>
#include <linux/kernel.h>
#include <net/ieee80211.h>
#include "zd_def.h"
#include "zd_ieee80211.h"
#include "zd_mac.h"
static const struct channel_range channel_ranges[] = {
[0] = { 0, 0},
[ZD_REGDOMAIN_FCC] = { 1, 12},
[ZD_REGDOMAIN_IC] = { 1, 12},
[ZD_REGDOMAIN_ETSI] = { 1, 14},
[ZD_REGDOMAIN_JAPAN] = { 1, 14},
[ZD_REGDOMAIN_SPAIN] = { 1, 14},
[ZD_REGDOMAIN_FRANCE] = { 1, 14},
[ZD_REGDOMAIN_JAPAN_ADD] = {14, 15},
};
const struct channel_range *zd_channel_range(u8 regdomain)
{
if (regdomain >= ARRAY_SIZE(channel_ranges))
regdomain = 0;
return &channel_ranges[regdomain];
}
int zd_regdomain_supports_channel(u8 regdomain, u8 channel)
{
const struct channel_range *range = zd_channel_range(regdomain);
return range->start <= channel && channel < range->end;
}
int zd_regdomain_supported(u8 regdomain)
{
const struct channel_range *range = zd_channel_range(regdomain);
return range->start != 0;
}
/* Stores channel frequencies in MHz. */
static const u16 channel_frequencies[] = {
2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447,
2452, 2457, 2462, 2467, 2472, 2484,
};
#define NUM_CHANNELS ARRAY_SIZE(channel_frequencies)
static int compute_freq(struct iw_freq *freq, u32 mhz, u32 hz)
{
u32 factor;
freq->e = 0;
if (mhz >= 1000000000U) {
pr_debug("zd1211 mhz %u to large\n", mhz);
freq->m = 0;
return -EINVAL;
}
factor = 1000;
while (mhz >= factor) {
freq->e += 1;
factor *= 10;
}
factor /= 1000U;
freq->m = mhz * (1000000U/factor) + hz/factor;
return 0;
}
int zd_channel_to_freq(struct iw_freq *freq, u8 channel)
{
if (channel > NUM_CHANNELS) {
freq->m = 0;
freq->e = 0;
return -EINVAL;
}
if (!channel) {
freq->m = 0;
freq->e = 0;
return -EINVAL;
}
return compute_freq(freq, channel_frequencies[channel-1], 0);
}
static int freq_to_mhz(const struct iw_freq *freq)
{
u32 factor;
int e;
/* Such high frequencies are not supported. */
if (freq->e > 6)
return -EINVAL;
factor = 1;
for (e = freq->e; e > 0; --e) {
factor *= 10;
}
factor = 1000000U / factor;
if (freq->m % factor) {
return -EINVAL;
}
return freq->m / factor;
}
int zd_find_channel(u8 *channel, const struct iw_freq *freq)
{
int i, r;
u32 mhz;
if (!(freq->flags & IW_FREQ_FIXED))
return 0;
if (freq->m < 1000) {
if (freq->m > NUM_CHANNELS || freq->m == 0)
return -EINVAL;
*channel = freq->m;
return 1;
}
r = freq_to_mhz(freq);
if (r < 0)
return r;
mhz = r;
for (i = 0; i < NUM_CHANNELS; i++) {
if (mhz == channel_frequencies[i]) {
*channel = i+1;
return 1;
}
}
return -EINVAL;
}
int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain)
{
struct ieee80211_geo geo;
const struct channel_range *range;
int i;
u8 channel;
dev_dbg(zd_mac_dev(zd_netdev_mac(ieee->dev)),
"regdomain %#04x\n", regdomain);
range = zd_channel_range(regdomain);
if (range->start == 0) {
dev_err(zd_mac_dev(zd_netdev_mac(ieee->dev)),
"zd1211 regdomain %#04x not supported\n",
regdomain);
return -EINVAL;
}
memset(&geo, 0, sizeof(geo));
for (i = 0, channel = range->start; channel < range->end; channel++) {
struct ieee80211_channel *chan = &geo.bg[i++];
chan->freq = channel_frequencies[channel - 1];
chan->channel = channel;
}
geo.bg_channels = i;
memcpy(geo.name, "XX ", 4);
ieee80211_set_geo(ieee, &geo);
return 0;
}

View File

@ -0,0 +1,85 @@
#ifndef _ZD_IEEE80211_H
#define _ZD_IEEE80211_H
#include <net/ieee80211.h>
#include "zd_types.h"
/* Additional definitions from the standards.
*/
#define ZD_REGDOMAIN_FCC 0x10
#define ZD_REGDOMAIN_IC 0x20
#define ZD_REGDOMAIN_ETSI 0x30
#define ZD_REGDOMAIN_SPAIN 0x31
#define ZD_REGDOMAIN_FRANCE 0x32
#define ZD_REGDOMAIN_JAPAN_ADD 0x40
#define ZD_REGDOMAIN_JAPAN 0x41
enum {
MIN_CHANNEL24 = 1,
MAX_CHANNEL24 = 14,
};
struct channel_range {
u8 start;
u8 end; /* exclusive (channel must be less than end) */
};
struct iw_freq;
int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain);
const struct channel_range *zd_channel_range(u8 regdomain);
int zd_regdomain_supports_channel(u8 regdomain, u8 channel);
int zd_regdomain_supported(u8 regdomain);
/* for 2.4 GHz band */
int zd_channel_to_freq(struct iw_freq *freq, u8 channel);
int zd_find_channel(u8 *channel, const struct iw_freq *freq);
#define ZD_PLCP_SERVICE_LENGTH_EXTENSION 0x80
struct ofdm_plcp_header {
u8 prefix[3];
__le16 service;
} __attribute__((packed));
static inline u8 zd_ofdm_plcp_header_rate(
const struct ofdm_plcp_header *header)
{
return header->prefix[0] & 0xf;
}
#define ZD_OFDM_RATE_6M 0xb
#define ZD_OFDM_RATE_9M 0xf
#define ZD_OFDM_RATE_12M 0xa
#define ZD_OFDM_RATE_18M 0xe
#define ZD_OFDM_RATE_24M 0x9
#define ZD_OFDM_RATE_36M 0xd
#define ZD_OFDM_RATE_48M 0x8
#define ZD_OFDM_RATE_54M 0xc
struct cck_plcp_header {
u8 signal;
u8 service;
__le16 length;
__le16 crc16;
} __attribute__((packed));
static inline u8 zd_cck_plcp_header_rate(const struct cck_plcp_header *header)
{
return header->signal;
}
#define ZD_CCK_SIGNAL_1M 0x0a
#define ZD_CCK_SIGNAL_2M 0x14
#define ZD_CCK_SIGNAL_5M5 0x37
#define ZD_CCK_SIGNAL_11M 0x6e
enum ieee80211_std {
IEEE80211B = 0x01,
IEEE80211A = 0x02,
IEEE80211G = 0x04,
};
#endif /* _ZD_IEEE80211_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,190 @@
/* zd_mac.c
*
* 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
*/
#ifndef _ZD_MAC_H
#define _ZD_MAC_H
#include <linux/wireless.h>
#include <linux/kernel.h>
#include <net/ieee80211.h>
#include <net/ieee80211softmac.h>
#include "zd_chip.h"
#include "zd_netdev.h"
struct zd_ctrlset {
u8 modulation;
__le16 tx_length;
u8 control;
/* stores only the difference to tx_length on ZD1211B */
__le16 packet_length;
__le16 current_length;
u8 service;
__le16 next_frame_length;
} __attribute__((packed));
#define ZD_CS_RESERVED_SIZE 25
/* zd_crtlset field modulation */
#define ZD_CS_RATE_MASK 0x0f
#define ZD_CS_TYPE_MASK 0x10
#define ZD_CS_RATE(modulation) ((modulation) & ZD_CS_RATE_MASK)
#define ZD_CS_TYPE(modulation) ((modulation) & ZD_CS_TYPE_MASK)
#define ZD_CS_CCK 0x00
#define ZD_CS_OFDM 0x10
#define ZD_CS_CCK_RATE_1M 0x00
#define ZD_CS_CCK_RATE_2M 0x01
#define ZD_CS_CCK_RATE_5_5M 0x02
#define ZD_CS_CCK_RATE_11M 0x03
/* The rates for OFDM are encoded as in the PLCP header. Use ZD_OFDM_RATE_*.
*/
/* bit 5 is preamble (when in CCK mode), or a/g selection (when in OFDM mode) */
#define ZD_CS_CCK_PREA_LONG 0x00
#define ZD_CS_CCK_PREA_SHORT 0x20
#define ZD_CS_OFDM_MODE_11G 0x00
#define ZD_CS_OFDM_MODE_11A 0x20
/* zd_ctrlset control field */
#define ZD_CS_NEED_RANDOM_BACKOFF 0x01
#define ZD_CS_MULTICAST 0x02
#define ZD_CS_FRAME_TYPE_MASK 0x0c
#define ZD_CS_DATA_FRAME 0x00
#define ZD_CS_PS_POLL_FRAME 0x04
#define ZD_CS_MANAGEMENT_FRAME 0x08
#define ZD_CS_NO_SEQUENCE_CTL_FRAME 0x0c
#define ZD_CS_WAKE_DESTINATION 0x10
#define ZD_CS_RTS 0x20
#define ZD_CS_ENCRYPT 0x40
#define ZD_CS_SELF_CTS 0x80
/* Incoming frames are prepended by a PLCP header */
#define ZD_PLCP_HEADER_SIZE 5
struct rx_length_info {
__le16 length[3];
__le16 tag;
} __attribute__((packed));
#define RX_LENGTH_INFO_TAG 0x697e
struct rx_status {
/* rssi */
u8 signal_strength;
u8 signal_quality_cck;
u8 signal_quality_ofdm;
u8 decryption_type;
u8 frame_status;
} __attribute__((packed));
/* rx_status field decryption_type */
#define ZD_RX_NO_WEP 0
#define ZD_RX_WEP64 1
#define ZD_RX_TKIP 2
#define ZD_RX_AES 4
#define ZD_RX_WEP128 5
#define ZD_RX_WEP256 6
/* rx_status field frame_status */
#define ZD_RX_FRAME_MODULATION_MASK 0x01
#define ZD_RX_CCK 0x00
#define ZD_RX_OFDM 0x01
#define ZD_RX_TIMEOUT_ERROR 0x02
#define ZD_RX_FIFO_OVERRUN_ERROR 0x04
#define ZD_RX_DECRYPTION_ERROR 0x08
#define ZD_RX_CRC32_ERROR 0x10
#define ZD_RX_NO_ADDR1_MATCH_ERROR 0x20
#define ZD_RX_CRC16_ERROR 0x40
#define ZD_RX_ERROR 0x80
enum mac_flags {
MAC_FIXED_CHANNEL = 0x01,
};
struct zd_mac {
struct net_device *netdev;
struct zd_chip chip;
spinlock_t lock;
/* Unlocked reading possible */
struct iw_statistics iw_stats;
u8 qual_average;
u8 rssi_average;
u8 regdomain;
u8 default_regdomain;
u8 requested_channel;
};
static inline struct ieee80211_device *zd_mac_to_ieee80211(struct zd_mac *mac)
{
return zd_netdev_ieee80211(mac->netdev);
}
static inline struct zd_mac *zd_netdev_mac(struct net_device *netdev)
{
return ieee80211softmac_priv(netdev);
}
static inline struct zd_mac *zd_chip_to_mac(struct zd_chip *chip)
{
return container_of(chip, struct zd_mac, chip);
}
static inline struct zd_mac *zd_usb_to_mac(struct zd_usb *usb)
{
return zd_chip_to_mac(zd_usb_to_chip(usb));
}
#define zd_mac_dev(mac) (zd_chip_dev(&(mac)->chip))
int zd_mac_init(struct zd_mac *mac,
struct net_device *netdev,
struct usb_interface *intf);
void zd_mac_clear(struct zd_mac *mac);
int zd_mac_init_hw(struct zd_mac *mac, u8 device_type);
int zd_mac_open(struct net_device *netdev);
int zd_mac_stop(struct net_device *netdev);
int zd_mac_set_mac_address(struct net_device *dev, void *p);
int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length);
int zd_mac_set_regdomain(struct zd_mac *zd_mac, u8 regdomain);
u8 zd_mac_get_regdomain(struct zd_mac *zd_mac);
int zd_mac_request_channel(struct zd_mac *mac, u8 channel);
int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags);
int zd_mac_set_mode(struct zd_mac *mac, u32 mode);
int zd_mac_get_mode(struct zd_mac *mac, u32 *mode);
int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range);
struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev);
#ifdef DEBUG
void zd_dump_rx_status(const struct rx_status *status);
#else
#define zd_dump_rx_status(status)
#endif /* DEBUG */
#endif /* _ZD_MAC_H */

View File

@ -0,0 +1,267 @@
/* zd_netdev.c
*
* 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/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <net/ieee80211.h>
#include <net/ieee80211softmac.h>
#include <net/ieee80211softmac_wx.h>
#include <net/iw_handler.h>
#include "zd_def.h"
#include "zd_netdev.h"
#include "zd_mac.h"
#include "zd_ieee80211.h"
/* Region 0 means reset regdomain to default. */
static int zd_set_regdomain(struct net_device *netdev,
struct iw_request_info *info,
union iwreq_data *req, char *extra)
{
const u8 *regdomain = (u8 *)req;
return zd_mac_set_regdomain(zd_netdev_mac(netdev), *regdomain);
}
static int zd_get_regdomain(struct net_device *netdev,
struct iw_request_info *info,
union iwreq_data *req, char *extra)
{
u8 *regdomain = (u8 *)req;
if (!regdomain)
return -EINVAL;
*regdomain = zd_mac_get_regdomain(zd_netdev_mac(netdev));
return 0;
}
static const struct iw_priv_args zd_priv_args[] = {
{
.cmd = ZD_PRIV_SET_REGDOMAIN,
.set_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
.name = "set_regdomain",
},
{
.cmd = ZD_PRIV_GET_REGDOMAIN,
.get_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
.name = "get_regdomain",
},
};
#define PRIV_OFFSET(x) [(x)-SIOCIWFIRSTPRIV]
static const iw_handler zd_priv_handler[] = {
PRIV_OFFSET(ZD_PRIV_SET_REGDOMAIN) = zd_set_regdomain,
PRIV_OFFSET(ZD_PRIV_GET_REGDOMAIN) = zd_get_regdomain,
};
static int iw_get_name(struct net_device *netdev,
struct iw_request_info *info,
union iwreq_data *req, char *extra)
{
/* FIXME: check whether 802.11a will also supported, add also
* zd1211B, if we support it.
*/
strlcpy(req->name, "802.11g zd1211", IFNAMSIZ);
return 0;
}
static int iw_set_freq(struct net_device *netdev,
struct iw_request_info *info,
union iwreq_data *req, char *extra)
{
int r;
struct zd_mac *mac = zd_netdev_mac(netdev);
struct iw_freq *freq = &req->freq;
u8 channel;
r = zd_find_channel(&channel, freq);
if (r < 0)
return r;
r = zd_mac_request_channel(mac, channel);
return r;
}
static int iw_get_freq(struct net_device *netdev,
struct iw_request_info *info,
union iwreq_data *req, char *extra)
{
int r;
struct zd_mac *mac = zd_netdev_mac(netdev);
struct iw_freq *freq = &req->freq;
u8 channel;
u8 flags;
r = zd_mac_get_channel(mac, &channel, &flags);
if (r)
return r;
freq->flags = (flags & MAC_FIXED_CHANNEL) ?
IW_FREQ_FIXED : IW_FREQ_AUTO;
dev_dbg_f(zd_mac_dev(mac), "channel %s\n",
(flags & MAC_FIXED_CHANNEL) ? "fixed" : "auto");
return zd_channel_to_freq(freq, channel);
}
static int iw_set_mode(struct net_device *netdev,
struct iw_request_info *info,
union iwreq_data *req, char *extra)
{
return zd_mac_set_mode(zd_netdev_mac(netdev), req->mode);
}
static int iw_get_mode(struct net_device *netdev,
struct iw_request_info *info,
union iwreq_data *req, char *extra)
{
return zd_mac_get_mode(zd_netdev_mac(netdev), &req->mode);
}
static int iw_get_range(struct net_device *netdev,
struct iw_request_info *info,
union iwreq_data *req, char *extra)
{
struct iw_range *range = (struct iw_range *)extra;
dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n");
req->data.length = sizeof(*range);
return zd_mac_get_range(zd_netdev_mac(netdev), range);
}
static int iw_set_encode(struct net_device *netdev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra)
{
return ieee80211_wx_set_encode(zd_netdev_ieee80211(netdev), info,
data, extra);
}
static int iw_get_encode(struct net_device *netdev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra)
{
return ieee80211_wx_get_encode(zd_netdev_ieee80211(netdev), info,
data, extra);
}
static int iw_set_encodeext(struct net_device *netdev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra)
{
return ieee80211_wx_set_encodeext(zd_netdev_ieee80211(netdev), info,
data, extra);
}
static int iw_get_encodeext(struct net_device *netdev,
struct iw_request_info *info,
union iwreq_data *data,
char *extra)
{
return ieee80211_wx_get_encodeext(zd_netdev_ieee80211(netdev), info,
data, extra);
}
#define WX(x) [(x)-SIOCIWFIRST]
static const iw_handler zd_standard_iw_handlers[] = {
WX(SIOCGIWNAME) = iw_get_name,
WX(SIOCSIWFREQ) = iw_set_freq,
WX(SIOCGIWFREQ) = iw_get_freq,
WX(SIOCSIWMODE) = iw_set_mode,
WX(SIOCGIWMODE) = iw_get_mode,
WX(SIOCGIWRANGE) = iw_get_range,
WX(SIOCSIWENCODE) = iw_set_encode,
WX(SIOCGIWENCODE) = iw_get_encode,
WX(SIOCSIWENCODEEXT) = iw_set_encodeext,
WX(SIOCGIWENCODEEXT) = iw_get_encodeext,
WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
WX(SIOCSIWMLME) = ieee80211softmac_wx_set_mlme,
};
static const struct iw_handler_def iw_handler_def = {
.standard = zd_standard_iw_handlers,
.num_standard = ARRAY_SIZE(zd_standard_iw_handlers),
.private = zd_priv_handler,
.num_private = ARRAY_SIZE(zd_priv_handler),
.private_args = zd_priv_args,
.num_private_args = ARRAY_SIZE(zd_priv_args),
.get_wireless_stats = zd_mac_get_wireless_stats,
};
struct net_device *zd_netdev_alloc(struct usb_interface *intf)
{
int r;
struct net_device *netdev;
struct zd_mac *mac;
netdev = alloc_ieee80211softmac(sizeof(struct zd_mac));
if (!netdev) {
dev_dbg_f(&intf->dev, "out of memory\n");
return NULL;
}
mac = zd_netdev_mac(netdev);
r = zd_mac_init(mac, netdev, intf);
if (r) {
usb_set_intfdata(intf, NULL);
free_ieee80211(netdev);
return NULL;
}
SET_MODULE_OWNER(netdev);
SET_NETDEV_DEV(netdev, &intf->dev);
dev_dbg_f(&intf->dev, "netdev->flags %#06hx\n", netdev->flags);
dev_dbg_f(&intf->dev, "netdev->features %#010lx\n", netdev->features);
netdev->open = zd_mac_open;
netdev->stop = zd_mac_stop;
/* netdev->get_stats = */
/* netdev->set_multicast_list = */
netdev->set_mac_address = zd_mac_set_mac_address;
netdev->wireless_handlers = &iw_handler_def;
/* netdev->ethtool_ops = */
return netdev;
}
void zd_netdev_free(struct net_device *netdev)
{
if (!netdev)
return;
zd_mac_clear(zd_netdev_mac(netdev));
free_ieee80211(netdev);
}
void zd_netdev_disconnect(struct net_device *netdev)
{
unregister_netdev(netdev);
}

View File

@ -0,0 +1,45 @@
/* zd_netdev.h: Header for net device related functions.
*
* 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
*/
#ifndef _ZD_NETDEV_H
#define _ZD_NETDEV_H
#include <linux/usb.h>
#include <linux/netdevice.h>
#include <net/ieee80211.h>
#define ZD_PRIV_SET_REGDOMAIN (SIOCIWFIRSTPRIV)
#define ZD_PRIV_GET_REGDOMAIN (SIOCIWFIRSTPRIV+1)
static inline struct ieee80211_device *zd_netdev_ieee80211(
struct net_device *ndev)
{
return netdev_priv(ndev);
}
static inline struct net_device *zd_ieee80211_to_netdev(
struct ieee80211_device *ieee)
{
return ieee->dev;
}
struct net_device *zd_netdev_alloc(struct usb_interface *intf);
void zd_netdev_free(struct net_device *netdev);
void zd_netdev_disconnect(struct net_device *netdev);
#endif /* _ZD_NETDEV_H */

View File

@ -0,0 +1,151 @@
/* zd_rf.c
*
* 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/errno.h>
#include <linux/string.h>
#include "zd_def.h"
#include "zd_rf.h"
#include "zd_ieee80211.h"
#include "zd_chip.h"
static const char *rfs[] = {
[0] = "unknown RF0",
[1] = "unknown RF1",
[UW2451_RF] = "UW2451_RF",
[UCHIP_RF] = "UCHIP_RF",
[AL2230_RF] = "AL2230_RF",
[AL7230B_RF] = "AL7230B_RF",
[THETA_RF] = "THETA_RF",
[AL2210_RF] = "AL2210_RF",
[MAXIM_NEW_RF] = "MAXIM_NEW_RF",
[UW2453_RF] = "UW2453_RF",
[AL2230S_RF] = "AL2230S_RF",
[RALINK_RF] = "RALINK_RF",
[INTERSIL_RF] = "INTERSIL_RF",
[RF2959_RF] = "RF2959_RF",
[MAXIM_NEW2_RF] = "MAXIM_NEW2_RF",
[PHILIPS_RF] = "PHILIPS_RF",
};
const char *zd_rf_name(u8 type)
{
if (type & 0xf0)
type = 0;
return rfs[type];
}
void zd_rf_init(struct zd_rf *rf)
{
memset(rf, 0, sizeof(*rf));
}
void zd_rf_clear(struct zd_rf *rf)
{
memset(rf, 0, sizeof(*rf));
}
int zd_rf_init_hw(struct zd_rf *rf, u8 type)
{
int r, 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;
default:
dev_err(zd_chip_dev(chip),
"RF %s %#x is not supported\n", zd_rf_name(type), type);
rf->type = 0;
return -ENODEV;
}
rf->type = type;
r = zd_chip_lock_phy_regs(chip);
if (r)
return r;
t = rf->init_hw(rf);
r = zd_chip_unlock_phy_regs(chip);
if (t)
r = t;
return r;
}
int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size)
{
return scnprintf(buffer, size, "%s", zd_rf_name(rf->type));
}
int zd_rf_set_channel(struct zd_rf *rf, u8 channel)
{
int r;
ZD_ASSERT(mutex_is_locked(&zd_rf_to_chip(rf)->mutex));
if (channel < MIN_CHANNEL24)
return -EINVAL;
if (channel > MAX_CHANNEL24)
return -EINVAL;
dev_dbg_f(zd_chip_dev(zd_rf_to_chip(rf)), "channel: %d\n", channel);
r = rf->set_channel(rf, channel);
if (r >= 0)
rf->channel = channel;
return r;
}
int zd_switch_radio_on(struct zd_rf *rf)
{
int r, t;
struct zd_chip *chip = zd_rf_to_chip(rf);
ZD_ASSERT(mutex_is_locked(&chip->mutex));
r = zd_chip_lock_phy_regs(chip);
if (r)
return r;
t = rf->switch_radio_on(rf);
r = zd_chip_unlock_phy_regs(chip);
if (t)
r = t;
return r;
}
int zd_switch_radio_off(struct zd_rf *rf)
{
int r, t;
struct zd_chip *chip = zd_rf_to_chip(rf);
/* TODO: move phy regs handling to zd_chip */
ZD_ASSERT(mutex_is_locked(&chip->mutex));
r = zd_chip_lock_phy_regs(chip);
if (r)
return r;
t = rf->switch_radio_off(rf);
r = zd_chip_unlock_phy_regs(chip);
if (t)
r = t;
return r;
}

View File

@ -0,0 +1,82 @@
/* zd_rf.h
*
* 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
*/
#ifndef _ZD_RF_H
#define _ZD_RF_H
#include "zd_types.h"
#define UW2451_RF 0x2
#define UCHIP_RF 0x3
#define AL2230_RF 0x4
#define AL7230B_RF 0x5 /* a,b,g */
#define THETA_RF 0x6
#define AL2210_RF 0x7
#define MAXIM_NEW_RF 0x8
#define UW2453_RF 0x9
#define AL2230S_RF 0xa
#define RALINK_RF 0xb
#define INTERSIL_RF 0xc
#define RF2959_RF 0xd
#define MAXIM_NEW2_RF 0xe
#define PHILIPS_RF 0xf
#define RF_CHANNEL(ch) [(ch)-1]
/* Provides functions of the RF transceiver. */
enum {
RF_REG_BITS = 6,
RF_VALUE_BITS = 18,
RF_RV_BITS = RF_REG_BITS + RF_VALUE_BITS,
};
struct zd_rf {
u8 type;
u8 channel;
/*
* Whether this RF should patch the 6M band edge
* (assuming E2P_POD agrees)
*/
u8 patch_6m_band_edge:1;
/* 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);
};
const char *zd_rf_name(u8 type);
void zd_rf_init(struct zd_rf *rf);
void zd_rf_clear(struct zd_rf *rf);
int zd_rf_init_hw(struct zd_rf *rf, u8 type);
int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size);
int zd_rf_set_channel(struct zd_rf *rf, u8 channel);
int zd_switch_radio_on(struct zd_rf *rf);
int zd_switch_radio_off(struct zd_rf *rf);
/* Functions for individual RF chips */
int zd_rf_init_rf2959(struct zd_rf *rf);
int zd_rf_init_al2230(struct zd_rf *rf);
#endif /* _ZD_RF_H */

View File

@ -0,0 +1,308 @@
/* zd_rf_al2230.c: Functions for the AL2230 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"
static const u32 al2230_table[][3] = {
RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, },
RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, },
RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, },
RF_CHANNEL( 4) = { 0x03e790, 0x0b3331, 0x00000d, },
RF_CHANNEL( 5) = { 0x03f7a0, 0x033331, 0x00000d, },
RF_CHANNEL( 6) = { 0x03f7a0, 0x0b3331, 0x00000d, },
RF_CHANNEL( 7) = { 0x03e7a0, 0x033331, 0x00000d, },
RF_CHANNEL( 8) = { 0x03e7a0, 0x0b3331, 0x00000d, },
RF_CHANNEL( 9) = { 0x03f7b0, 0x033331, 0x00000d, },
RF_CHANNEL(10) = { 0x03f7b0, 0x0b3331, 0x00000d, },
RF_CHANNEL(11) = { 0x03e7b0, 0x033331, 0x00000d, },
RF_CHANNEL(12) = { 0x03e7b0, 0x0b3331, 0x00000d, },
RF_CHANNEL(13) = { 0x03f7c0, 0x033331, 0x00000d, },
RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, },
};
static int zd1211_al2230_init_hw(struct zd_rf *rf)
{
int r;
struct zd_chip *chip = zd_rf_to_chip(rf);
static const struct zd_ioreq16 ioreqs[] = {
{ CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 },
{ CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 },
{ CR44, 0x33 }, { CR106, 0x2a }, { CR107, 0x1a },
{ CR109, 0x09 }, { CR110, 0x27 }, { CR111, 0x2b },
{ CR112, 0x2b }, { CR119, 0x0a }, { CR10, 0x89 },
/* for newest (3rd cut) AL2300 */
{ CR17, 0x28 },
{ CR26, 0x93 }, { CR34, 0x30 },
/* for newest (3rd cut) AL2300 */
{ CR35, 0x3e },
{ CR41, 0x24 }, { CR44, 0x32 },
/* for newest (3rd cut) AL2300 */
{ CR46, 0x96 },
{ CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 },
{ CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 },
{ CR92, 0x0a }, { CR99, 0x28 }, { CR100, 0x00 },
{ CR101, 0x13 }, { CR102, 0x27 }, { CR106, 0x24 },
{ CR107, 0x2a }, { CR109, 0x09 }, { CR110, 0x13 },
{ CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 },
{ CR114, 0x27 },
/* for newest (3rd cut) AL2300 */
{ CR115, 0x24 },
{ CR116, 0x24 }, { CR117, 0xf4 }, { CR118, 0xfc },
{ CR119, 0x10 }, { CR120, 0x4f }, { CR121, 0x77 },
{ CR122, 0xe0 }, { CR137, 0x88 }, { CR252, 0xff },
{ CR253, 0xff },
/* These following happen separately in the vendor driver */
{ },
/* shdnb(PLL_ON)=0 */
{ CR251, 0x2f },
/* shdnb(PLL_ON)=1 */
{ CR251, 0x3f },
{ CR138, 0x28 }, { CR203, 0x06 },
};
static const u32 rv[] = {
/* Channel 1 */
0x03f790,
0x033331,
0x00000d,
0x0b3331,
0x03b812,
0x00fff3,
0x000da4,
0x0f4dc5, /* fix freq shift, 0x04edc5 */
0x0805b6,
0x011687,
0x000688,
0x0403b9, /* external control TX power (CR31) */
0x00dbba,
0x00099b,
0x0bdffc,
0x00000d,
0x00500f,
/* These writes happen separately in the vendor driver */
0x00d00f,
0x004c0f,
0x00540f,
0x00700f,
0x00500f,
};
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;
return 0;
}
static int zd1211b_al2230_init_hw(struct zd_rf *rf)
{
int r;
struct zd_chip *chip = zd_rf_to_chip(rf);
static const struct zd_ioreq16 ioreqs1[] = {
{ CR10, 0x89 }, { CR15, 0x20 },
{ CR17, 0x2B }, /* for newest(3rd cut) AL2230 */
{ CR23, 0x40 }, { CR24, 0x20 }, { CR26, 0x93 },
{ CR28, 0x3e }, { CR29, 0x00 },
{ CR33, 0x28 }, /* 5621 */
{ CR34, 0x30 },
{ CR35, 0x3e }, /* for newest(3rd cut) AL2230 */
{ CR41, 0x24 }, { CR44, 0x32 },
{ CR46, 0x99 }, /* for newest(3rd cut) AL2230 */
{ CR47, 0x1e },
/* ZD1211B 05.06.10 */
{ CR48, 0x00 }, { CR49, 0x00 }, { CR51, 0x01 },
{ CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 },
{ CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 },
{ CR69, 0x28 },
{ CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 },
{ CR87, 0x0a }, { CR89, 0x04 },
{ CR91, 0x00 }, /* 5621 */
{ CR92, 0x0a },
{ CR98, 0x8d }, /* 4804, for 1212 new algorithm */
{ CR99, 0x00 }, /* 5621 */
{ CR101, 0x13 }, { CR102, 0x27 },
{ CR106, 0x24 }, /* for newest(3rd cut) AL2230 */
{ CR107, 0x2a },
{ CR109, 0x13 }, /* 4804, for 1212 new algorithm */
{ CR110, 0x1f }, /* 4804, for 1212 new algorithm */
{ CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 },
{ CR114, 0x27 },
{ CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut) AL2230 */
{ CR116, 0x24 },
{ CR117, 0xfa }, /* for 1211b */
{ CR118, 0xfa }, /* for 1211b */
{ CR119, 0x10 },
{ CR120, 0x4f },
{ CR121, 0x6c }, /* for 1211b */
{ CR122, 0xfc }, /* E0->FC at 4902 */
{ CR123, 0x57 }, /* 5623 */
{ CR125, 0xad }, /* 4804, for 1212 new algorithm */
{ CR126, 0x6c }, /* 5614 */
{ CR127, 0x03 }, /* 4804, for 1212 new algorithm */
{ CR137, 0x50 }, /* 5614 */
{ CR138, 0xa8 },
{ CR144, 0xac }, /* 5621 */
{ CR150, 0x0d }, { CR252, 0x00 }, { CR253, 0x00 },
};
static const u32 rv1[] = {
/* channel 1 */
0x03f790,
0x033331,
0x00000d,
0x0b3331,
0x03b812,
0x00fff3,
0x0005a4,
0x0f4dc5, /* fix freq shift 0x044dc5 */
0x0805b6,
0x0146c7,
0x000688,
0x0403b9, /* External control TX power (CR31) */
0x00dbba,
0x00099b,
0x0bdffc,
0x00000d,
0x00580f,
};
static const struct zd_ioreq16 ioreqs2[] = {
{ CR47, 0x1e }, { CR_RFCFG, 0x03 },
};
static const u32 rv2[] = {
0x00880f,
0x00080f,
};
static const struct zd_ioreq16 ioreqs3[] = {
{ CR_RFCFG, 0x00 }, { CR47, 0x1e }, { CR251, 0x7f },
};
static const u32 rv3[] = {
0x00d80f,
0x00780f,
0x00580f,
};
static const struct zd_ioreq16 ioreqs4[] = {
{ CR138, 0x28 }, { CR203, 0x06 },
};
r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1));
if (r)
return r;
r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS);
if (r)
return r;
r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2));
if (r)
return r;
r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS);
if (r)
return r;
r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3));
if (r)
return r;
r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS);
if (r)
return r;
return zd_iowrite16a_locked(chip, ioreqs4, ARRAY_SIZE(ioreqs4));
}
static int al2230_set_channel(struct zd_rf *rf, u8 channel)
{
int r;
const u32 *rv = al2230_table[channel-1];
struct zd_chip *chip = zd_rf_to_chip(rf);
static const struct zd_ioreq16 ioreqs[] = {
{ CR138, 0x28 },
{ CR203, 0x06 },
};
r = zd_rfwritev_locked(chip, rv, 3, RF_RV_BITS);
if (r)
return r;
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
}
static int zd1211_al2230_switch_radio_on(struct zd_rf *rf)
{
struct zd_chip *chip = zd_rf_to_chip(rf);
static const struct zd_ioreq16 ioreqs[] = {
{ CR11, 0x00 },
{ CR251, 0x3f },
};
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
}
static int zd1211b_al2230_switch_radio_on(struct zd_rf *rf)
{
struct zd_chip *chip = zd_rf_to_chip(rf);
static const struct zd_ioreq16 ioreqs[] = {
{ CR11, 0x00 },
{ CR251, 0x7f },
};
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
}
static int al2230_switch_radio_off(struct zd_rf *rf)
{
struct zd_chip *chip = zd_rf_to_chip(rf);
static const struct zd_ioreq16 ioreqs[] = {
{ CR11, 0x04 },
{ CR251, 0x2f },
};
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
}
int zd_rf_init_al2230(struct zd_rf *rf)
{
struct zd_chip *chip = zd_rf_to_chip(rf);
rf->set_channel = al2230_set_channel;
rf->switch_radio_off = al2230_switch_radio_off;
if (chip->is_zd1211b) {
rf->init_hw = zd1211b_al2230_init_hw;
rf->switch_radio_on = zd1211b_al2230_switch_radio_on;
} else {
rf->init_hw = zd1211_al2230_init_hw;
rf->switch_radio_on = zd1211_al2230_switch_radio_on;
}
rf->patch_6m_band_edge = 1;
return 0;
}

View File

@ -0,0 +1,279 @@
/* zd_rf_rfmd.c: Functions for the RFMD 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"
static u32 rf2959_table[][2] = {
RF_CHANNEL( 1) = { 0x181979, 0x1e6666 },
RF_CHANNEL( 2) = { 0x181989, 0x1e6666 },
RF_CHANNEL( 3) = { 0x181999, 0x1e6666 },
RF_CHANNEL( 4) = { 0x1819a9, 0x1e6666 },
RF_CHANNEL( 5) = { 0x1819b9, 0x1e6666 },
RF_CHANNEL( 6) = { 0x1819c9, 0x1e6666 },
RF_CHANNEL( 7) = { 0x1819d9, 0x1e6666 },
RF_CHANNEL( 8) = { 0x1819e9, 0x1e6666 },
RF_CHANNEL( 9) = { 0x1819f9, 0x1e6666 },
RF_CHANNEL(10) = { 0x181a09, 0x1e6666 },
RF_CHANNEL(11) = { 0x181a19, 0x1e6666 },
RF_CHANNEL(12) = { 0x181a29, 0x1e6666 },
RF_CHANNEL(13) = { 0x181a39, 0x1e6666 },
RF_CHANNEL(14) = { 0x181a60, 0x1c0000 },
};
#if 0
static int bits(u32 rw, int from, int to)
{
rw &= ~(0xffffffffU << (to+1));
rw >>= from;
return rw;
}
static int bit(u32 rw, int bit)
{
return bits(rw, bit, bit);
}
static void dump_regwrite(u32 rw)
{
int reg = bits(rw, 18, 22);
int rw_flag = bits(rw, 23, 23);
PDEBUG("rf2959 %#010x reg %d rw %d", rw, reg, rw_flag);
switch (reg) {
case 0:
PDEBUG("reg0 CFG1 ref_sel %d hybernate %d rf_vco_reg_en %d"
" if_vco_reg_en %d if_vga_en %d",
bits(rw, 14, 15), bit(rw, 3), bit(rw, 2), bit(rw, 1),
bit(rw, 0));
break;
case 1:
PDEBUG("reg1 IFPLL1 pll_en1 %d kv_en1 %d vtc_en1 %d lpf1 %d"
" cpl1 %d pdp1 %d autocal_en1 %d ld_en1 %d ifloopr %d"
" ifloopc %d dac1 %d",
bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14),
bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10),
bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0, 3));
break;
case 2:
PDEBUG("reg2 IFPLL2 n1 %d num1 %d",
bits(rw, 6, 17), bits(rw, 0, 5));
break;
case 3:
PDEBUG("reg3 IFPLL3 num %d", bits(rw, 0, 17));
break;
case 4:
PDEBUG("reg4 IFPLL4 dn1 %#04x ct_def1 %d kv_def1 %d",
bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3));
break;
case 5:
PDEBUG("reg5 RFPLL1 pll_en %d kv_en %d vtc_en %d lpf %d cpl %d"
" pdp %d autocal_en %d ld_en %d rfloopr %d rfloopc %d"
" dac %d",
bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14),
bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10),
bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0,3));
break;
case 6:
PDEBUG("reg6 RFPLL2 n %d num %d",
bits(rw, 6, 17), bits(rw, 0, 5));
break;
case 7:
PDEBUG("reg7 RFPLL3 num2 %d", bits(rw, 0, 17));
break;
case 8:
PDEBUG("reg8 RFPLL4 dn %#06x ct_def %d kv_def %d",
bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3));
break;
case 9:
PDEBUG("reg9 CAL1 tvco %d tlock %d m_ct_value %d ld_window %d",
bits(rw, 13, 17), bits(rw, 8, 12), bits(rw, 3, 7),
bits(rw, 0, 2));
break;
case 10:
PDEBUG("reg10 TXRX1 rxdcfbbyps %d pcontrol %d txvgc %d"
" rxlpfbw %d txlpfbw %d txdiffmode %d txenmode %d"
" intbiasen %d tybypass %d",
bit(rw, 17), bits(rw, 15, 16), bits(rw, 10, 14),
bits(rw, 7, 9), bits(rw, 4, 6), bit(rw, 3), bit(rw, 2),
bit(rw, 1), bit(rw, 0));
break;
case 11:
PDEBUG("reg11 PCNT1 mid_bias %d p_desired %d pc_offset %d"
" tx_delay %d",
bits(rw, 15, 17), bits(rw, 9, 14), bits(rw, 3, 8),
bits(rw, 0, 2));
break;
case 12:
PDEBUG("reg12 PCNT2 max_power %d mid_power %d min_power %d",
bits(rw, 12, 17), bits(rw, 6, 11), bits(rw, 0, 5));
break;
case 13:
PDEBUG("reg13 VCOT1 rfpll vco comp %d ifpll vco comp %d"
" lobias %d if_biasbuf %d if_biasvco %d rf_biasbuf %d"
" rf_biasvco %d",
bit(rw, 17), bit(rw, 16), bit(rw, 15),
bits(rw, 8, 9), bits(rw, 5, 7), bits(rw, 3, 4),
bits(rw, 0, 2));
break;
case 14:
PDEBUG("reg14 IQCAL rx_acal %d rx_pcal %d"
" tx_acal %d tx_pcal %d",
bits(rw, 13, 17), bits(rw, 9, 12), bits(rw, 4, 8),
bits(rw, 0, 3));
break;
}
}
#endif /* 0 */
static int rf2959_init_hw(struct zd_rf *rf)
{
int r;
struct zd_chip *chip = zd_rf_to_chip(rf);
static const struct zd_ioreq16 ioreqs[] = {
{ CR2, 0x1E }, { CR9, 0x20 }, { CR10, 0x89 },
{ CR11, 0x00 }, { CR15, 0xD0 }, { CR17, 0x68 },
{ CR19, 0x4a }, { CR20, 0x0c }, { CR21, 0x0E },
{ CR23, 0x48 },
/* normal size for cca threshold */
{ CR24, 0x14 },
/* { CR24, 0x20 }, */
{ CR26, 0x90 }, { CR27, 0x30 }, { CR29, 0x20 },
{ CR31, 0xb2 }, { CR32, 0x43 }, { CR33, 0x28 },
{ CR38, 0x30 }, { CR34, 0x0f }, { CR35, 0xF0 },
{ CR41, 0x2a }, { CR46, 0x7F }, { CR47, 0x1E },
{ CR51, 0xc5 }, { CR52, 0xc5 }, { CR53, 0xc5 },
{ CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 },
{ CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 },
{ CR85, 0x00 }, { CR86, 0x10 }, { CR87, 0x2A },
{ CR88, 0x10 }, { CR89, 0x24 }, { CR90, 0x18 },
/* { CR91, 0x18 }, */
/* should solve continous CTS frame problems */
{ CR91, 0x00 },
{ CR92, 0x0a }, { CR93, 0x00 }, { CR94, 0x01 },
{ CR95, 0x00 }, { CR96, 0x40 }, { CR97, 0x37 },
{ CR98, 0x05 }, { CR99, 0x28 }, { CR100, 0x00 },
{ CR101, 0x13 }, { CR102, 0x27 }, { CR103, 0x27 },
{ CR104, 0x18 }, { CR105, 0x12 },
/* normal size */
{ CR106, 0x1a },
/* { CR106, 0x22 }, */
{ CR107, 0x24 }, { CR108, 0x0a }, { CR109, 0x13 },
{ CR110, 0x2F }, { CR111, 0x27 }, { CR112, 0x27 },
{ CR113, 0x27 }, { CR114, 0x27 }, { CR115, 0x40 },
{ CR116, 0x40 }, { CR117, 0xF0 }, { CR118, 0xF0 },
{ CR119, 0x16 },
/* no TX continuation */
{ CR122, 0x00 },
/* { CR122, 0xff }, */
{ CR127, 0x03 }, { CR131, 0x08 }, { CR138, 0x28 },
{ CR148, 0x44 }, { CR150, 0x10 }, { CR169, 0xBB },
{ CR170, 0xBB },
};
static const u32 rv[] = {
0x000007, /* REG0(CFG1) */
0x07dd43, /* REG1(IFPLL1) */
0x080959, /* REG2(IFPLL2) */
0x0e6666,
0x116a57, /* REG4 */
0x17dd43, /* REG5 */
0x1819f9, /* REG6 */
0x1e6666,
0x214554,
0x25e7fa,
0x27fffa,
/* The Zydas driver somehow forgets to set this value. It's
* only set for Japan. We are using internal power control
* for now.
*/
0x294128, /* internal power */
/* 0x28252c, */ /* External control TX power */
/* CR31_CCK, CR51_6-36M, CR52_48M, CR53_54M */
0x2c0000,
0x300000,
0x340000, /* REG13(0xD) */
0x381e0f, /* REG14(0xE) */
/* Bogus, RF2959's data sheet doesn't know register 27, which is
* actually referenced here. The commented 0x11 is 17.
*/
0x6c180f, /* REG27(0x11) */
};
r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
if (r)
return r;
return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
}
static int rf2959_set_channel(struct zd_rf *rf, u8 channel)
{
int i, r;
u32 *rv = rf2959_table[channel-1];
struct zd_chip *chip = zd_rf_to_chip(rf);
for (i = 0; i < 2; i++) {
r = zd_rfwrite_locked(chip, rv[i], RF_RV_BITS);
if (r)
return r;
}
return 0;
}
static int rf2959_switch_radio_on(struct zd_rf *rf)
{
static const struct zd_ioreq16 ioreqs[] = {
{ CR10, 0x89 },
{ CR11, 0x00 },
};
struct zd_chip *chip = zd_rf_to_chip(rf);
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
}
static int rf2959_switch_radio_off(struct zd_rf *rf)
{
static const struct zd_ioreq16 ioreqs[] = {
{ CR10, 0x15 },
{ CR11, 0x81 },
};
struct zd_chip *chip = zd_rf_to_chip(rf);
return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
}
int zd_rf_init_rf2959(struct zd_rf *rf)
{
struct zd_chip *chip = zd_rf_to_chip(rf);
if (chip->is_zd1211b) {
dev_err(zd_chip_dev(chip),
"RF2959 is currently not supported for ZD1211B"
" devices\n");
return -ENODEV;
}
rf->init_hw = rf2959_init_hw;
rf->set_channel = rf2959_set_channel;
rf->switch_radio_on = rf2959_switch_radio_on;
rf->switch_radio_off = rf2959_switch_radio_off;
return 0;
}

View File

@ -0,0 +1,71 @@
/* zd_types.h
*
* 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
*/
#ifndef _ZD_TYPES_H
#define _ZD_TYPES_H
#include <linux/types.h>
/* We have three register spaces mapped into the overall USB address space of
* 64K words (16-bit values). There is the control register space of
* double-word registers, the eeprom register space and the firmware register
* space. The control register space is byte mapped, the others are word
* mapped.
*
* For that reason, we are using byte offsets for control registers and word
* offsets for everything else.
*/
typedef u32 __nocast zd_addr_t;
enum {
ADDR_BASE_MASK = 0xff000000,
ADDR_OFFSET_MASK = 0x0000ffff,
ADDR_ZERO_MASK = 0x00ff0000,
NULL_BASE = 0x00000000,
USB_BASE = 0x01000000,
CR_BASE = 0x02000000,
CR_MAX_OFFSET = 0x0b30,
E2P_BASE = 0x03000000,
E2P_MAX_OFFSET = 0x007e,
FW_BASE = 0x04000000,
FW_MAX_OFFSET = 0x0005,
};
#define ZD_ADDR_BASE(addr) ((u32)(addr) & ADDR_BASE_MASK)
#define ZD_OFFSET(addr) ((u32)(addr) & ADDR_OFFSET_MASK)
#define ZD_ADDR(base, offset) \
((zd_addr_t)(((base) & ADDR_BASE_MASK) | ((offset) & ADDR_OFFSET_MASK)))
#define ZD_NULL_ADDR ((zd_addr_t)0)
#define USB_REG(offset) ZD_ADDR(USB_BASE, offset) /* word addressing */
#define CTL_REG(offset) ZD_ADDR(CR_BASE, offset) /* byte addressing */
#define E2P_REG(offset) ZD_ADDR(E2P_BASE, offset) /* word addressing */
#define FW_REG(offset) ZD_ADDR(FW_BASE, offset) /* word addressing */
static inline zd_addr_t zd_inc_word(zd_addr_t addr)
{
u32 base = ZD_ADDR_BASE(addr);
u32 offset = ZD_OFFSET(addr);
offset += base == CR_BASE ? 2 : 1;
return base | offset;
}
#endif /* _ZD_TYPES_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,240 @@
/* zd_usb.h: Header for USB interface implemented by ZD1211 chip
*
* 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
*/
#ifndef _ZD_USB_H
#define _ZD_USB_H
#include <linux/completion.h>
#include <linux/netdevice.h>
#include <linux/spinlock.h>
#include <linux/skbuff.h>
#include <linux/usb.h>
#include "zd_def.h"
#include "zd_types.h"
enum devicetype {
DEVICE_ZD1211 = 0,
DEVICE_ZD1211B = 1,
};
enum endpoints {
EP_CTRL = 0,
EP_DATA_OUT = 1,
EP_DATA_IN = 2,
EP_INT_IN = 3,
EP_REGS_OUT = 4,
};
enum {
USB_MAX_TRANSFER_SIZE = 4096, /* bytes */
/* FIXME: The original driver uses this value. We have to check,
* whether the MAX_TRANSFER_SIZE is sufficient and this needs only be
* used if one combined frame is split over two USB transactions.
*/
USB_MAX_RX_SIZE = 4800, /* bytes */
USB_MAX_IOWRITE16_COUNT = 15,
USB_MAX_IOWRITE32_COUNT = USB_MAX_IOWRITE16_COUNT/2,
USB_MAX_IOREAD16_COUNT = 15,
USB_MAX_IOREAD32_COUNT = USB_MAX_IOREAD16_COUNT/2,
USB_MIN_RFWRITE_BIT_COUNT = 16,
USB_MAX_RFWRITE_BIT_COUNT = 28,
USB_MAX_EP_INT_BUFFER = 64,
USB_ZD1211B_BCD_DEVICE = 0x4810,
};
enum control_requests {
USB_REQ_WRITE_REGS = 0x21,
USB_REQ_READ_REGS = 0x22,
USB_REQ_WRITE_RF = 0x23,
USB_REQ_PROG_FLASH = 0x24,
USB_REQ_EEPROM_START = 0x0128, /* ? request is a byte */
USB_REQ_EEPROM_MID = 0x28,
USB_REQ_EEPROM_END = 0x0228, /* ? request is a byte */
USB_REQ_FIRMWARE_DOWNLOAD = 0x30,
USB_REQ_FIRMWARE_CONFIRM = 0x31,
USB_REQ_FIRMWARE_READ_DATA = 0x32,
};
struct usb_req_read_regs {
__le16 id;
__le16 addr[0];
} __attribute__((packed));
struct reg_data {
__le16 addr;
__le16 value;
} __attribute__((packed));
struct usb_req_write_regs {
__le16 id;
struct reg_data reg_writes[0];
} __attribute__((packed));
enum {
RF_IF_LE = 0x02,
RF_CLK = 0x04,
RF_DATA = 0x08,
};
struct usb_req_rfwrite {
__le16 id;
__le16 value;
/* 1: 3683a */
/* 2: other (default) */
__le16 bits;
/* RF2595: 24 */
__le16 bit_values[0];
/* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */
} __attribute__((packed));
/* USB interrupt */
enum usb_int_id {
USB_INT_TYPE = 0x01,
USB_INT_ID_REGS = 0x90,
USB_INT_ID_RETRY_FAILED = 0xa0,
};
enum usb_int_flags {
USB_INT_READ_REGS_EN = 0x01,
};
struct usb_int_header {
u8 type; /* must always be 1 */
u8 id;
} __attribute__((packed));
struct usb_int_regs {
struct usb_int_header hdr;
struct reg_data regs[0];
} __attribute__((packed));
struct usb_int_retry_fail {
struct usb_int_header hdr;
u8 new_rate;
u8 _dummy;
u8 addr[ETH_ALEN];
u8 ibss_wakeup_dest;
} __attribute__((packed));
struct read_regs_int {
struct completion completion;
/* Stores the USB int structure and contains the USB address of the
* first requested register before request.
*/
u8 buffer[USB_MAX_EP_INT_BUFFER];
int length;
__le16 cr_int_addr;
};
struct zd_ioreq16 {
zd_addr_t addr;
u16 value;
};
struct zd_ioreq32 {
zd_addr_t addr;
u32 value;
};
struct zd_usb_interrupt {
struct read_regs_int read_regs;
spinlock_t lock;
struct urb *urb;
int interval;
u8 read_regs_enabled:1;
};
static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)
{
return (struct usb_int_regs *)intr->read_regs.buffer;
}
#define URBS_COUNT 5
struct zd_usb_rx {
spinlock_t lock;
u8 fragment[2*USB_MAX_RX_SIZE];
unsigned int fragment_length;
unsigned int usb_packet_size;
struct urb **urbs;
int urbs_count;
};
struct zd_usb_tx {
spinlock_t lock;
};
/* Contains the usb parts. The structure doesn't require a lock, because intf
* and fw_base_offset, will not be changed after initialization.
*/
struct zd_usb {
struct zd_usb_interrupt intr;
struct zd_usb_rx rx;
struct zd_usb_tx tx;
struct usb_interface *intf;
u16 fw_base_offset;
};
#define zd_usb_dev(usb) (&usb->intf->dev)
static inline struct usb_device *zd_usb_to_usbdev(struct zd_usb *usb)
{
return interface_to_usbdev(usb->intf);
}
static inline struct net_device *zd_intf_to_netdev(struct usb_interface *intf)
{
return usb_get_intfdata(intf);
}
static inline struct net_device *zd_usb_to_netdev(struct zd_usb *usb)
{
return zd_intf_to_netdev(usb->intf);
}
void zd_usb_init(struct zd_usb *usb, struct net_device *netdev,
struct usb_interface *intf);
int zd_usb_init_hw(struct zd_usb *usb);
void zd_usb_clear(struct zd_usb *usb);
int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size);
int zd_usb_enable_int(struct zd_usb *usb);
void zd_usb_disable_int(struct zd_usb *usb);
int zd_usb_enable_rx(struct zd_usb *usb);
void zd_usb_disable_rx(struct zd_usb *usb);
int zd_usb_tx(struct zd_usb *usb, const u8 *frame, unsigned int length);
int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
const zd_addr_t *addresses, unsigned int count);
static inline int zd_usb_ioread16(struct zd_usb *usb, u16 *value,
const zd_addr_t addr)
{
return zd_usb_ioread16v(usb, value, (const zd_addr_t *)&addr, 1);
}
int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
unsigned int count);
int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits);
#endif /* _ZD_USB_H */

View File

@ -0,0 +1,82 @@
/* zd_util.c
*
* 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
*
* Utility program
*/
#include "zd_def.h"
#include "zd_util.h"
#ifdef DEBUG
static char hex(u8 v)
{
v &= 0xf;
return (v < 10 ? '0' : 'a' - 10) + v;
}
static char hex_print(u8 c)
{
return (0x20 <= c && c < 0x7f) ? c : '.';
}
static void dump_line(const u8 *bytes, size_t size)
{
char c;
size_t i;
size = size <= 8 ? size : 8;
printk(KERN_DEBUG "zd1211 %p ", bytes);
for (i = 0; i < 8; i++) {
switch (i) {
case 1:
case 5:
c = '.';
break;
case 3:
c = ':';
break;
default:
c = ' ';
}
if (i < size) {
printk("%c%c%c", hex(bytes[i] >> 4), hex(bytes[i]), c);
} else {
printk(" %c", c);
}
}
for (i = 0; i < size; i++)
printk("%c", hex_print(bytes[i]));
printk("\n");
}
void zd_hexdump(const void *bytes, size_t size)
{
size_t i = 0;
do {
dump_line((u8 *)bytes + i, size-i);
i += 8;
} while (i < size);
}
#endif /* DEBUG */
void *zd_tail(const void *buffer, size_t buffer_size, size_t tail_size)
{
if (buffer_size < tail_size)
return NULL;
return (u8 *)buffer + (buffer_size - tail_size);
}

View File

@ -0,0 +1,29 @@
/* zd_util.h
*
* 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
*/
#ifndef _ZD_UTIL_H
#define _ZD_UTIL_H
void *zd_tail(const void *buffer, size_t buffer_size, size_t tail_size);
#ifdef DEBUG
void zd_hexdump(const void *bytes, size_t size);
#else
#define zd_hexdump(bytes, size)
#endif /* DEBUG */
#endif /* _ZD_UTIL_H */

View File

@ -19,37 +19,13 @@
Support and updates available at
http://www.scyld.com/network/yellowfin.html
[link no longer provides useful info -jgarzik]
Linux kernel changelog:
-----------------------
LK1.1.1 (jgarzik): Port to 2.4 kernel
LK1.1.2 (jgarzik):
* Merge in becker version 1.05
LK1.1.3 (jgarzik):
* Various cleanups
* Update yellowfin_timer to correctly calculate duplex.
(suggested by Manfred Spraul)
LK1.1.4 (val@nmt.edu):
* Fix three endian-ness bugs
* Support dual function SYM53C885E ethernet chip
LK1.1.5 (val@nmt.edu):
* Fix forced full-duplex bug I introduced
LK1.1.6 (val@nmt.edu):
* Only print warning on truly "oversized" packets
* Fix theoretical bug on gigabit cards - return to 1.1.3 behavior
*/
#define DRV_NAME "yellowfin"
#define DRV_VERSION "1.05+LK1.1.6"
#define DRV_RELDATE "Feb 11, 2002"
#define DRV_VERSION "2.0"
#define DRV_RELDATE "Jun 27, 2006"
#define PFX DRV_NAME ": "
@ -239,8 +215,11 @@ enum capability_flags {
HasMACAddrBug=32, /* Only on early revs. */
DontUseEeprom=64, /* Don't read the MAC from the EEPROm. */
};
/* The PCI I/O space extent. */
#define YELLOWFIN_SIZE 0x100
enum {
YELLOWFIN_SIZE = 0x100,
};
struct pci_id_info {
const char *name;
@ -248,16 +227,14 @@ struct pci_id_info {
int pci, pci_mask, subsystem, subsystem_mask;
int revision, revision_mask; /* Only 8 bits. */
} id;
int io_size; /* Needed for I/O region check or ioremap(). */
int drv_flags; /* Driver use, intended as capability flags. */
};
static const struct pci_id_info pci_id_tbl[] = {
{"Yellowfin G-NIC Gigabit Ethernet", { 0x07021000, 0xffffffff},
YELLOWFIN_SIZE,
FullTxStatus | IsGigabit | HasMulticastBug | HasMACAddrBug | DontUseEeprom},
{"Symbios SYM83C885", { 0x07011000, 0xffffffff},
YELLOWFIN_SIZE, HasMII | DontUseEeprom },
HasMII | DontUseEeprom },
{ }
};

View File

@ -1052,7 +1052,7 @@ static void ahci_thaw(struct ata_port *ap)
static void ahci_error_handler(struct ata_port *ap)
{
if (!(ap->flags & ATA_FLAG_FROZEN)) {
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
/* restart engine */
ahci_stop_engine(ap);
ahci_start_engine(ap);
@ -1323,6 +1323,17 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
/* JMicron-specific fixup: make sure we're in AHCI mode */
/* This is protected from races with ata_jmicron by the pci probe
locking */
if (pdev->vendor == PCI_VENDOR_ID_JMICRON) {
/* AHCI enable, AHCI on function 0 */
pci_write_config_byte(pdev, 0x41, 0xa1);
/* Function 1 is the PATA controller */
if (PCI_FUNC(pdev->devfn))
return -ENODEV;
}
rc = pci_enable_device(pdev);
if (rc)
return rc;
@ -1378,10 +1389,6 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (have_msi)
hpriv->flags |= AHCI_FLAG_MSI;
/* JMicron-specific fixup: make sure we're in AHCI mode */
if (pdev->vendor == 0x197b)
pci_write_config_byte(pdev, 0x41, 0xa1);
/* initialize adapter */
rc = ahci_host_init(probe_ent);
if (rc)

View File

@ -61,9 +61,9 @@
#include "libata.h"
/* debounce timing parameters in msecs { interval, duration, timeout } */
const unsigned long sata_deb_timing_boot[] = { 5, 100, 2000 };
const unsigned long sata_deb_timing_eh[] = { 25, 500, 2000 };
const unsigned long sata_deb_timing_before_fsrst[] = { 100, 2000, 5000 };
const unsigned long sata_deb_timing_normal[] = { 5, 100, 2000 };
const unsigned long sata_deb_timing_hotplug[] = { 25, 500, 2000 };
const unsigned long sata_deb_timing_long[] = { 100, 2000, 5000 };
static unsigned int ata_dev_init_params(struct ata_device *dev,
u16 heads, u16 sectors);
@ -907,7 +907,7 @@ void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data,
{
int rc;
if (ap->flags & ATA_FLAG_FLUSH_PORT_TASK)
if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK)
return;
PREPARE_WORK(&ap->port_task, fn, data);
@ -938,7 +938,7 @@ void ata_port_flush_task(struct ata_port *ap)
DPRINTK("ENTER\n");
spin_lock_irqsave(ap->lock, flags);
ap->flags |= ATA_FLAG_FLUSH_PORT_TASK;
ap->pflags |= ATA_PFLAG_FLUSH_PORT_TASK;
spin_unlock_irqrestore(ap->lock, flags);
DPRINTK("flush #1\n");
@ -957,7 +957,7 @@ void ata_port_flush_task(struct ata_port *ap)
}
spin_lock_irqsave(ap->lock, flags);
ap->flags &= ~ATA_FLAG_FLUSH_PORT_TASK;
ap->pflags &= ~ATA_PFLAG_FLUSH_PORT_TASK;
spin_unlock_irqrestore(ap->lock, flags);
if (ata_msg_ctl(ap))
@ -1009,7 +1009,7 @@ unsigned ata_exec_internal(struct ata_device *dev,
spin_lock_irqsave(ap->lock, flags);
/* no internal command while frozen */
if (ap->flags & ATA_FLAG_FROZEN) {
if (ap->pflags & ATA_PFLAG_FROZEN) {
spin_unlock_irqrestore(ap->lock, flags);
return AC_ERR_SYSTEM;
}
@ -1325,6 +1325,19 @@ static void ata_dev_config_ncq(struct ata_device *dev,
snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth);
}
static void ata_set_port_max_cmd_len(struct ata_port *ap)
{
int i;
if (ap->host) {
ap->host->max_cmd_len = 0;
for (i = 0; i < ATA_MAX_DEVICES; i++)
ap->host->max_cmd_len = max_t(unsigned int,
ap->host->max_cmd_len,
ap->device[i].cdb_len);
}
}
/**
* ata_dev_configure - Configure the specified ATA/ATAPI device
* @dev: Target device to configure
@ -1344,7 +1357,7 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
struct ata_port *ap = dev->ap;
const u16 *id = dev->id;
unsigned int xfer_mask;
int i, rc;
int rc;
if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
ata_dev_printk(dev, KERN_INFO,
@ -1404,7 +1417,7 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc));
/* print device info to dmesg */
if (ata_msg_info(ap))
if (ata_msg_drv(ap) && print_info)
ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
"max %s, %Lu sectors: %s %s\n",
ata_id_major_version(id),
@ -1427,7 +1440,7 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
}
/* print device info to dmesg */
if (ata_msg_info(ap))
if (ata_msg_drv(ap) && print_info)
ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
"max %s, %Lu sectors: CHS %u/%u/%u\n",
ata_id_major_version(id),
@ -1439,7 +1452,7 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
if (dev->id[59] & 0x100) {
dev->multi_count = dev->id[59] & 0xff;
if (ata_msg_info(ap))
if (ata_msg_drv(ap) && print_info)
ata_dev_printk(dev, KERN_INFO,
"ata%u: dev %u multi count %u\n",
ap->id, dev->devno, dev->multi_count);
@ -1468,21 +1481,17 @@ int ata_dev_configure(struct ata_device *dev, int print_info)
}
/* print device info to dmesg */
if (ata_msg_info(ap))
if (ata_msg_drv(ap) && print_info)
ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s%s\n",
ata_mode_string(xfer_mask),
cdb_intr_string);
}
ap->host->max_cmd_len = 0;
for (i = 0; i < ATA_MAX_DEVICES; i++)
ap->host->max_cmd_len = max_t(unsigned int,
ap->host->max_cmd_len,
ap->device[i].cdb_len);
ata_set_port_max_cmd_len(ap);
/* limit bridge transfers to udma5, 200 sectors */
if (ata_dev_knobble(dev)) {
if (ata_msg_info(ap))
if (ata_msg_drv(ap) && print_info)
ata_dev_printk(dev, KERN_INFO,
"applying bridge limits\n");
dev->udma_mask &= ATA_UDMA5;
@ -2137,7 +2146,7 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
* return error code and failing device on failure.
*/
for (i = 0; i < ATA_MAX_DEVICES; i++) {
if (ata_dev_enabled(&ap->device[i])) {
if (ata_dev_ready(&ap->device[i])) {
ap->ops->set_mode(ap);
break;
}
@ -2203,7 +2212,8 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
for (i = 0; i < ATA_MAX_DEVICES; i++) {
dev = &ap->device[i];
if (!ata_dev_enabled(dev))
/* don't udpate suspended devices' xfer mode */
if (!ata_dev_ready(dev))
continue;
rc = ata_dev_set_mode(dev);
@ -2579,7 +2589,7 @@ static void ata_wait_spinup(struct ata_port *ap)
/* first, debounce phy if SATA */
if (ap->cbl == ATA_CBL_SATA) {
rc = sata_phy_debounce(ap, sata_deb_timing_eh);
rc = sata_phy_debounce(ap, sata_deb_timing_hotplug);
/* if debounced successfully and offline, no need to wait */
if ((rc == 0 || rc == -EOPNOTSUPP) && ata_port_offline(ap))
@ -2615,16 +2625,17 @@ static void ata_wait_spinup(struct ata_port *ap)
int ata_std_prereset(struct ata_port *ap)
{
struct ata_eh_context *ehc = &ap->eh_context;
const unsigned long *timing;
const unsigned long *timing = sata_ehc_deb_timing(ehc);
int rc;
/* hotplug? */
if (ehc->i.flags & ATA_EHI_HOTPLUGGED) {
if (ap->flags & ATA_FLAG_HRST_TO_RESUME)
ehc->i.action |= ATA_EH_HARDRESET;
if (ap->flags & ATA_FLAG_SKIP_D2H_BSY)
ata_wait_spinup(ap);
}
/* handle link resume & hotplug spinup */
if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
(ap->flags & ATA_FLAG_HRST_TO_RESUME))
ehc->i.action |= ATA_EH_HARDRESET;
if ((ehc->i.flags & ATA_EHI_HOTPLUGGED) &&
(ap->flags & ATA_FLAG_SKIP_D2H_BSY))
ata_wait_spinup(ap);
/* if we're about to do hardreset, nothing more to do */
if (ehc->i.action & ATA_EH_HARDRESET)
@ -2632,11 +2643,6 @@ int ata_std_prereset(struct ata_port *ap)
/* if SATA, resume phy */
if (ap->cbl == ATA_CBL_SATA) {
if (ap->flags & ATA_FLAG_LOADING)
timing = sata_deb_timing_boot;
else
timing = sata_deb_timing_eh;
rc = sata_phy_resume(ap, timing);
if (rc && rc != -EOPNOTSUPP) {
/* phy resume failed */
@ -2724,6 +2730,8 @@ int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
*/
int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
{
struct ata_eh_context *ehc = &ap->eh_context;
const unsigned long *timing = sata_ehc_deb_timing(ehc);
u32 scontrol;
int rc;
@ -2761,7 +2769,7 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
msleep(1);
/* bring phy back */
sata_phy_resume(ap, sata_deb_timing_eh);
sata_phy_resume(ap, timing);
/* TODO: phy layer with polling, timeouts, etc. */
if (ata_port_offline(ap)) {
@ -4285,7 +4293,7 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
unsigned int i;
/* no command while frozen */
if (unlikely(ap->flags & ATA_FLAG_FROZEN))
if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
return NULL;
/* the last tag is reserved for internal command. */
@ -4407,7 +4415,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
* taken care of.
*/
if (ap->ops->error_handler) {
WARN_ON(ap->flags & ATA_FLAG_FROZEN);
WARN_ON(ap->pflags & ATA_PFLAG_FROZEN);
if (unlikely(qc->err_mask))
qc->flags |= ATA_QCFLAG_FAILED;
@ -5001,86 +5009,120 @@ int ata_flush_cache(struct ata_device *dev)
return 0;
}
static int ata_standby_drive(struct ata_device *dev)
static int ata_host_set_request_pm(struct ata_host_set *host_set,
pm_message_t mesg, unsigned int action,
unsigned int ehi_flags, int wait)
{
unsigned int err_mask;
unsigned long flags;
int i, rc;
err_mask = ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1);
if (err_mask) {
ata_dev_printk(dev, KERN_ERR, "failed to standby drive "
"(err_mask=0x%x)\n", err_mask);
return -EIO;
}
for (i = 0; i < host_set->n_ports; i++) {
struct ata_port *ap = host_set->ports[i];
return 0;
}
/* Previous resume operation might still be in
* progress. Wait for PM_PENDING to clear.
*/
if (ap->pflags & ATA_PFLAG_PM_PENDING) {
ata_port_wait_eh(ap);
WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
}
static int ata_start_drive(struct ata_device *dev)
{
unsigned int err_mask;
/* request PM ops to EH */
spin_lock_irqsave(ap->lock, flags);
err_mask = ata_do_simple_cmd(dev, ATA_CMD_IDLEIMMEDIATE);
if (err_mask) {
ata_dev_printk(dev, KERN_ERR, "failed to start drive "
"(err_mask=0x%x)\n", err_mask);
return -EIO;
ap->pm_mesg = mesg;
if (wait) {
rc = 0;
ap->pm_result = &rc;
}
ap->pflags |= ATA_PFLAG_PM_PENDING;
ap->eh_info.action |= action;
ap->eh_info.flags |= ehi_flags;
ata_port_schedule_eh(ap);
spin_unlock_irqrestore(ap->lock, flags);
/* wait and check result */
if (wait) {
ata_port_wait_eh(ap);
WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
if (rc)
return rc;
}
}
return 0;
}
/**
* ata_device_resume - wakeup a previously suspended devices
* @dev: the device to resume
* ata_host_set_suspend - suspend host_set
* @host_set: host_set to suspend
* @mesg: PM message
*
* Kick the drive back into action, by sending it an idle immediate
* command and making sure its transfer mode matches between drive
* and host.
* Suspend @host_set. Actual operation is performed by EH. This
* function requests EH to perform PM operations and waits for EH
* to finish.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* 0 on success, -errno on failure.
*/
int ata_device_resume(struct ata_device *dev)
int ata_host_set_suspend(struct ata_host_set *host_set, pm_message_t mesg)
{
struct ata_port *ap = dev->ap;
int i, j, rc;
if (ap->flags & ATA_FLAG_SUSPENDED) {
struct ata_device *failed_dev;
rc = ata_host_set_request_pm(host_set, mesg, 0, ATA_EHI_QUIET, 1);
if (rc)
goto fail;
ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 200000);
/* EH is quiescent now. Fail if we have any ready device.
* This happens if hotplug occurs between completion of device
* suspension and here.
*/
for (i = 0; i < host_set->n_ports; i++) {
struct ata_port *ap = host_set->ports[i];
ap->flags &= ~ATA_FLAG_SUSPENDED;
while (ata_set_mode(ap, &failed_dev))
ata_dev_disable(failed_dev);
for (j = 0; j < ATA_MAX_DEVICES; j++) {
struct ata_device *dev = &ap->device[j];
if (ata_dev_ready(dev)) {
ata_port_printk(ap, KERN_WARNING,
"suspend failed, device %d "
"still active\n", dev->devno);
rc = -EBUSY;
goto fail;
}
}
}
if (!ata_dev_enabled(dev))
return 0;
if (dev->class == ATA_DEV_ATA)
ata_start_drive(dev);
host_set->dev->power.power_state = mesg;
return 0;
fail:
ata_host_set_resume(host_set);
return rc;
}
/**
* ata_device_suspend - prepare a device for suspend
* @dev: the device to suspend
* @state: target power management state
* ata_host_set_resume - resume host_set
* @host_set: host_set to resume
*
* Flush the cache on the drive, if appropriate, then issue a
* standbynow command.
* Resume @host_set. Actual operation is performed by EH. This
* function requests EH to perform PM operations and returns.
* Note that all resume operations are performed parallely.
*
* LOCKING:
* Kernel thread context (may sleep).
*/
int ata_device_suspend(struct ata_device *dev, pm_message_t state)
void ata_host_set_resume(struct ata_host_set *host_set)
{
struct ata_port *ap = dev->ap;
if (!ata_dev_enabled(dev))
return 0;
if (dev->class == ATA_DEV_ATA)
ata_flush_cache(dev);
if (state.event != PM_EVENT_FREEZE)
ata_standby_drive(dev);
ap->flags |= ATA_FLAG_SUSPENDED;
return 0;
ata_host_set_request_pm(host_set, PMSG_ON, ATA_EH_SOFTRESET,
ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
host_set->dev->power.power_state = PMSG_ON;
}
/**
@ -5440,6 +5482,7 @@ int ata_device_add(const struct ata_probe_ent *ent)
}
if (ap->ops->error_handler) {
struct ata_eh_info *ehi = &ap->eh_info;
unsigned long flags;
ata_port_probe(ap);
@ -5447,10 +5490,11 @@ int ata_device_add(const struct ata_probe_ent *ent)
/* kick EH for boot probing */
spin_lock_irqsave(ap->lock, flags);
ap->eh_info.probe_mask = (1 << ATA_MAX_DEVICES) - 1;
ap->eh_info.action |= ATA_EH_SOFTRESET;
ehi->probe_mask = (1 << ATA_MAX_DEVICES) - 1;
ehi->action |= ATA_EH_SOFTRESET;
ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
ap->flags |= ATA_FLAG_LOADING;
ap->pflags |= ATA_PFLAG_LOADING;
ata_port_schedule_eh(ap);
spin_unlock_irqrestore(ap->lock, flags);
@ -5518,7 +5562,7 @@ void ata_port_detach(struct ata_port *ap)
/* tell EH we're leaving & flush EH */
spin_lock_irqsave(ap->lock, flags);
ap->flags |= ATA_FLAG_UNLOADING;
ap->pflags |= ATA_PFLAG_UNLOADING;
spin_unlock_irqrestore(ap->lock, flags);
ata_port_wait_eh(ap);
@ -5723,20 +5767,55 @@ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
return (tmp == bits->val) ? 1 : 0;
}
int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state)
void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t state)
{
pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
return 0;
if (state.event == PM_EVENT_SUSPEND) {
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
}
}
int ata_pci_device_resume(struct pci_dev *pdev)
void ata_pci_device_do_resume(struct pci_dev *pdev)
{
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
pci_enable_device(pdev);
pci_set_master(pdev);
}
int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
int rc = 0;
rc = ata_host_set_suspend(host_set, state);
if (rc)
return rc;
if (host_set->next) {
rc = ata_host_set_suspend(host_set->next, state);
if (rc) {
ata_host_set_resume(host_set);
return rc;
}
}
ata_pci_device_do_suspend(pdev, state);
return 0;
}
int ata_pci_device_resume(struct pci_dev *pdev)
{
struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
ata_pci_device_do_resume(pdev);
ata_host_set_resume(host_set);
if (host_set->next)
ata_host_set_resume(host_set->next);
return 0;
}
#endif /* CONFIG_PCI */
@ -5842,9 +5921,9 @@ u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
* Do not depend on ABI/API stability.
*/
EXPORT_SYMBOL_GPL(sata_deb_timing_boot);
EXPORT_SYMBOL_GPL(sata_deb_timing_eh);
EXPORT_SYMBOL_GPL(sata_deb_timing_before_fsrst);
EXPORT_SYMBOL_GPL(sata_deb_timing_normal);
EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug);
EXPORT_SYMBOL_GPL(sata_deb_timing_long);
EXPORT_SYMBOL_GPL(ata_std_bios_param);
EXPORT_SYMBOL_GPL(ata_std_ports);
EXPORT_SYMBOL_GPL(ata_device_add);
@ -5916,6 +5995,8 @@ EXPORT_SYMBOL_GPL(sata_scr_write);
EXPORT_SYMBOL_GPL(sata_scr_write_flush);
EXPORT_SYMBOL_GPL(ata_port_online);
EXPORT_SYMBOL_GPL(ata_port_offline);
EXPORT_SYMBOL_GPL(ata_host_set_suspend);
EXPORT_SYMBOL_GPL(ata_host_set_resume);
EXPORT_SYMBOL_GPL(ata_id_string);
EXPORT_SYMBOL_GPL(ata_id_c_string);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
@ -5930,14 +6011,14 @@ EXPORT_SYMBOL_GPL(ata_pci_host_stop);
EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
EXPORT_SYMBOL_GPL(ata_pci_init_one);
EXPORT_SYMBOL_GPL(ata_pci_remove_one);
EXPORT_SYMBOL_GPL(ata_pci_device_do_suspend);
EXPORT_SYMBOL_GPL(ata_pci_device_do_resume);
EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
EXPORT_SYMBOL_GPL(ata_pci_device_resume);
EXPORT_SYMBOL_GPL(ata_pci_default_filter);
EXPORT_SYMBOL_GPL(ata_pci_clear_simplex);
#endif /* CONFIG_PCI */
EXPORT_SYMBOL_GPL(ata_device_suspend);
EXPORT_SYMBOL_GPL(ata_device_resume);
EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
EXPORT_SYMBOL_GPL(ata_scsi_device_resume);

View File

@ -47,6 +47,8 @@
static void __ata_port_freeze(struct ata_port *ap);
static void ata_eh_finish(struct ata_port *ap);
static void ata_eh_handle_port_suspend(struct ata_port *ap);
static void ata_eh_handle_port_resume(struct ata_port *ap);
static void ata_ering_record(struct ata_ering *ering, int is_io,
unsigned int err_mask)
@ -190,7 +192,6 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
void ata_scsi_error(struct Scsi_Host *host)
{
struct ata_port *ap = ata_shost_to_port(host);
spinlock_t *ap_lock = ap->lock;
int i, repeat_cnt = ATA_EH_MAX_REPEAT;
unsigned long flags;
@ -217,7 +218,7 @@ void ata_scsi_error(struct Scsi_Host *host)
struct scsi_cmnd *scmd, *tmp;
int nr_timedout = 0;
spin_lock_irqsave(ap_lock, flags);
spin_lock_irqsave(ap->lock, flags);
list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
struct ata_queued_cmd *qc;
@ -256,43 +257,49 @@ void ata_scsi_error(struct Scsi_Host *host)
if (nr_timedout)
__ata_port_freeze(ap);
spin_unlock_irqrestore(ap_lock, flags);
spin_unlock_irqrestore(ap->lock, flags);
} else
spin_unlock_wait(ap_lock);
spin_unlock_wait(ap->lock);
repeat:
/* invoke error handler */
if (ap->ops->error_handler) {
/* process port resume request */
ata_eh_handle_port_resume(ap);
/* fetch & clear EH info */
spin_lock_irqsave(ap_lock, flags);
spin_lock_irqsave(ap->lock, flags);
memset(&ap->eh_context, 0, sizeof(ap->eh_context));
ap->eh_context.i = ap->eh_info;
memset(&ap->eh_info, 0, sizeof(ap->eh_info));
ap->flags |= ATA_FLAG_EH_IN_PROGRESS;
ap->flags &= ~ATA_FLAG_EH_PENDING;
ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS;
ap->pflags &= ~ATA_PFLAG_EH_PENDING;
spin_unlock_irqrestore(ap_lock, flags);
spin_unlock_irqrestore(ap->lock, flags);
/* invoke EH. if unloading, just finish failed qcs */
if (!(ap->flags & ATA_FLAG_UNLOADING))
/* invoke EH, skip if unloading or suspended */
if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED)))
ap->ops->error_handler(ap);
else
ata_eh_finish(ap);
/* process port suspend request */
ata_eh_handle_port_suspend(ap);
/* Exception might have happend after ->error_handler
* recovered the port but before this point. Repeat
* EH in such case.
*/
spin_lock_irqsave(ap_lock, flags);
spin_lock_irqsave(ap->lock, flags);
if (ap->flags & ATA_FLAG_EH_PENDING) {
if (ap->pflags & ATA_PFLAG_EH_PENDING) {
if (--repeat_cnt) {
ata_port_printk(ap, KERN_INFO,
"EH pending after completion, "
"repeating EH (cnt=%d)\n", repeat_cnt);
spin_unlock_irqrestore(ap_lock, flags);
spin_unlock_irqrestore(ap->lock, flags);
goto repeat;
}
ata_port_printk(ap, KERN_ERR, "EH pending after %d "
@ -302,14 +309,14 @@ void ata_scsi_error(struct Scsi_Host *host)
/* this run is complete, make sure EH info is clear */
memset(&ap->eh_info, 0, sizeof(ap->eh_info));
/* Clear host_eh_scheduled while holding ap_lock such
/* Clear host_eh_scheduled while holding ap->lock such
* that if exception occurs after this point but
* before EH completion, SCSI midlayer will
* re-initiate EH.
*/
host->host_eh_scheduled = 0;
spin_unlock_irqrestore(ap_lock, flags);
spin_unlock_irqrestore(ap->lock, flags);
} else {
WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
ap->ops->eng_timeout(ap);
@ -321,24 +328,23 @@ void ata_scsi_error(struct Scsi_Host *host)
scsi_eh_flush_done_q(&ap->eh_done_q);
/* clean up */
spin_lock_irqsave(ap_lock, flags);
spin_lock_irqsave(ap->lock, flags);
if (ap->flags & ATA_FLAG_LOADING) {
ap->flags &= ~ATA_FLAG_LOADING;
} else {
if (ap->flags & ATA_FLAG_SCSI_HOTPLUG)
queue_work(ata_aux_wq, &ap->hotplug_task);
if (ap->flags & ATA_FLAG_RECOVERED)
ata_port_printk(ap, KERN_INFO, "EH complete\n");
}
if (ap->pflags & ATA_PFLAG_LOADING)
ap->pflags &= ~ATA_PFLAG_LOADING;
else if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG)
queue_work(ata_aux_wq, &ap->hotplug_task);
ap->flags &= ~(ATA_FLAG_SCSI_HOTPLUG | ATA_FLAG_RECOVERED);
if (ap->pflags & ATA_PFLAG_RECOVERED)
ata_port_printk(ap, KERN_INFO, "EH complete\n");
ap->pflags &= ~(ATA_PFLAG_SCSI_HOTPLUG | ATA_PFLAG_RECOVERED);
/* tell wait_eh that we're done */
ap->flags &= ~ATA_FLAG_EH_IN_PROGRESS;
ap->pflags &= ~ATA_PFLAG_EH_IN_PROGRESS;
wake_up_all(&ap->eh_wait_q);
spin_unlock_irqrestore(ap_lock, flags);
spin_unlock_irqrestore(ap->lock, flags);
DPRINTK("EXIT\n");
}
@ -360,7 +366,7 @@ void ata_port_wait_eh(struct ata_port *ap)
retry:
spin_lock_irqsave(ap->lock, flags);
while (ap->flags & (ATA_FLAG_EH_PENDING | ATA_FLAG_EH_IN_PROGRESS)) {
while (ap->pflags & (ATA_PFLAG_EH_PENDING | ATA_PFLAG_EH_IN_PROGRESS)) {
prepare_to_wait(&ap->eh_wait_q, &wait, TASK_UNINTERRUPTIBLE);
spin_unlock_irqrestore(ap->lock, flags);
schedule();
@ -489,7 +495,7 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
WARN_ON(!ap->ops->error_handler);
qc->flags |= ATA_QCFLAG_FAILED;
qc->ap->flags |= ATA_FLAG_EH_PENDING;
qc->ap->pflags |= ATA_PFLAG_EH_PENDING;
/* The following will fail if timeout has already expired.
* ata_scsi_error() takes care of such scmds on EH entry.
@ -513,7 +519,7 @@ void ata_port_schedule_eh(struct ata_port *ap)
{
WARN_ON(!ap->ops->error_handler);
ap->flags |= ATA_FLAG_EH_PENDING;
ap->pflags |= ATA_PFLAG_EH_PENDING;
scsi_schedule_eh(ap->host);
DPRINTK("port EH scheduled\n");
@ -578,7 +584,7 @@ static void __ata_port_freeze(struct ata_port *ap)
if (ap->ops->freeze)
ap->ops->freeze(ap);
ap->flags |= ATA_FLAG_FROZEN;
ap->pflags |= ATA_PFLAG_FROZEN;
DPRINTK("ata%u port frozen\n", ap->id);
}
@ -646,7 +652,7 @@ void ata_eh_thaw_port(struct ata_port *ap)
spin_lock_irqsave(ap->lock, flags);
ap->flags &= ~ATA_FLAG_FROZEN;
ap->pflags &= ~ATA_PFLAG_FROZEN;
if (ap->ops->thaw)
ap->ops->thaw(ap);
@ -731,7 +737,7 @@ static void ata_eh_detach_dev(struct ata_device *dev)
if (ata_scsi_offline_dev(dev)) {
dev->flags |= ATA_DFLAG_DETACHED;
ap->flags |= ATA_FLAG_SCSI_HOTPLUG;
ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
}
/* clear per-dev EH actions */
@ -760,8 +766,12 @@ static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev,
unsigned long flags;
spin_lock_irqsave(ap->lock, flags);
ata_eh_clear_action(dev, &ap->eh_info, action);
ap->flags |= ATA_FLAG_RECOVERED;
if (!(ap->eh_context.i.flags & ATA_EHI_QUIET))
ap->pflags |= ATA_PFLAG_RECOVERED;
spin_unlock_irqrestore(ap->lock, flags);
}
@ -1027,7 +1037,7 @@ static void ata_eh_analyze_ncq_error(struct ata_port *ap)
int tag, rc;
/* if frozen, we can't do much */
if (ap->flags & ATA_FLAG_FROZEN)
if (ap->pflags & ATA_PFLAG_FROZEN)
return;
/* is it NCQ device error? */
@ -1275,6 +1285,9 @@ static void ata_eh_autopsy(struct ata_port *ap)
DPRINTK("ENTER\n");
if (ehc->i.flags & ATA_EHI_NO_AUTOPSY)
return;
/* obtain and analyze SError */
rc = sata_scr_read(ap, SCR_ERROR, &serror);
if (rc == 0) {
@ -1327,7 +1340,7 @@ static void ata_eh_autopsy(struct ata_port *ap)
}
/* enforce default EH actions */
if (ap->flags & ATA_FLAG_FROZEN ||
if (ap->pflags & ATA_PFLAG_FROZEN ||
all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
action |= ATA_EH_SOFTRESET;
else if (all_err_mask)
@ -1346,7 +1359,7 @@ static void ata_eh_autopsy(struct ata_port *ap)
/* record autopsy result */
ehc->i.dev = failed_dev;
ehc->i.action = action;
ehc->i.action |= action;
DPRINTK("EXIT\n");
}
@ -1385,7 +1398,7 @@ static void ata_eh_report(struct ata_port *ap)
return;
frozen = "";
if (ap->flags & ATA_FLAG_FROZEN)
if (ap->pflags & ATA_PFLAG_FROZEN)
frozen = " frozen";
if (ehc->i.dev) {
@ -1465,7 +1478,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
struct ata_eh_context *ehc = &ap->eh_context;
unsigned int *classes = ehc->classes;
int tries = ATA_EH_RESET_TRIES;
int verbose = !(ap->flags & ATA_FLAG_LOADING);
int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
unsigned int action;
ata_reset_fn_t reset;
int i, did_followup_srst, rc;
@ -1605,7 +1618,7 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
dev = &ap->device[i];
action = ata_eh_dev_action(dev);
if (action & ATA_EH_REVALIDATE && ata_dev_enabled(dev)) {
if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) {
if (ata_port_offline(ap)) {
rc = -EIO;
break;
@ -1636,7 +1649,7 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
}
spin_lock_irqsave(ap->lock, flags);
ap->flags |= ATA_FLAG_SCSI_HOTPLUG;
ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
spin_unlock_irqrestore(ap->lock, flags);
}
}
@ -1648,6 +1661,164 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
return rc;
}
/**
* ata_eh_suspend - handle suspend EH action
* @ap: target host port
* @r_failed_dev: result parameter to indicate failing device
*
* Handle suspend EH action. Disk devices are spinned down and
* other types of devices are just marked suspended. Once
* suspended, no EH action to the device is allowed until it is
* resumed.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* 0 on success, -errno otherwise
*/
static int ata_eh_suspend(struct ata_port *ap, struct ata_device **r_failed_dev)
{
struct ata_device *dev;
int i, rc = 0;
DPRINTK("ENTER\n");
for (i = 0; i < ATA_MAX_DEVICES; i++) {
unsigned long flags;
unsigned int action, err_mask;
dev = &ap->device[i];
action = ata_eh_dev_action(dev);
if (!ata_dev_enabled(dev) || !(action & ATA_EH_SUSPEND))
continue;
WARN_ON(dev->flags & ATA_DFLAG_SUSPENDED);
ata_eh_about_to_do(ap, dev, ATA_EH_SUSPEND);
if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) {
/* flush cache */
rc = ata_flush_cache(dev);
if (rc)
break;
/* spin down */
err_mask = ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1);
if (err_mask) {
ata_dev_printk(dev, KERN_ERR, "failed to "
"spin down (err_mask=0x%x)\n",
err_mask);
rc = -EIO;
break;
}
}
spin_lock_irqsave(ap->lock, flags);
dev->flags |= ATA_DFLAG_SUSPENDED;
spin_unlock_irqrestore(ap->lock, flags);
ata_eh_done(ap, dev, ATA_EH_SUSPEND);
}
if (rc)
*r_failed_dev = dev;
DPRINTK("EXIT\n");
return 0;
}
/**
* ata_eh_prep_resume - prep for resume EH action
* @ap: target host port
*
* Clear SUSPENDED in preparation for scheduled resume actions.
* This allows other parts of EH to access the devices being
* resumed.
*
* LOCKING:
* Kernel thread context (may sleep).
*/
static void ata_eh_prep_resume(struct ata_port *ap)
{
struct ata_device *dev;
unsigned long flags;
int i;
DPRINTK("ENTER\n");
for (i = 0; i < ATA_MAX_DEVICES; i++) {
unsigned int action;
dev = &ap->device[i];
action = ata_eh_dev_action(dev);
if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME))
continue;
spin_lock_irqsave(ap->lock, flags);
dev->flags &= ~ATA_DFLAG_SUSPENDED;
spin_unlock_irqrestore(ap->lock, flags);
}
DPRINTK("EXIT\n");
}
/**
* ata_eh_resume - handle resume EH action
* @ap: target host port
* @r_failed_dev: result parameter to indicate failing device
*
* Handle resume EH action. Target devices are already reset and
* revalidated. Spinning up is the only operation left.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* 0 on success, -errno otherwise
*/
static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev)
{
struct ata_device *dev;
int i, rc = 0;
DPRINTK("ENTER\n");
for (i = 0; i < ATA_MAX_DEVICES; i++) {
unsigned int action, err_mask;
dev = &ap->device[i];
action = ata_eh_dev_action(dev);
if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME))
continue;
ata_eh_about_to_do(ap, dev, ATA_EH_RESUME);
if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) {
err_mask = ata_do_simple_cmd(dev,
ATA_CMD_IDLEIMMEDIATE);
if (err_mask) {
ata_dev_printk(dev, KERN_ERR, "failed to "
"spin up (err_mask=0x%x)\n",
err_mask);
rc = -EIO;
break;
}
}
ata_eh_done(ap, dev, ATA_EH_RESUME);
}
if (rc)
*r_failed_dev = dev;
DPRINTK("EXIT\n");
return 0;
}
static int ata_port_nr_enabled(struct ata_port *ap)
{
int i, cnt = 0;
@ -1673,7 +1844,19 @@ static int ata_eh_skip_recovery(struct ata_port *ap)
struct ata_eh_context *ehc = &ap->eh_context;
int i;
if (ap->flags & ATA_FLAG_FROZEN || ata_port_nr_enabled(ap))
/* skip if all possible devices are suspended */
for (i = 0; i < ata_port_max_devices(ap); i++) {
struct ata_device *dev = &ap->device[i];
if (ata_dev_absent(dev) || ata_dev_ready(dev))
break;
}
if (i == ata_port_max_devices(ap))
return 1;
/* always thaw frozen port and recover failed devices */
if (ap->pflags & ATA_PFLAG_FROZEN || ata_port_nr_enabled(ap))
return 0;
/* skip if class codes for all vacant slots are ATA_DEV_NONE */
@ -1744,9 +1927,12 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
rc = 0;
/* if UNLOADING, finish immediately */
if (ap->flags & ATA_FLAG_UNLOADING)
if (ap->pflags & ATA_PFLAG_UNLOADING)
goto out;
/* prep for resume */
ata_eh_prep_resume(ap);
/* skip EH if possible. */
if (ata_eh_skip_recovery(ap))
ehc->i.action = 0;
@ -1774,6 +1960,11 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
if (rc)
goto dev_fail;
/* resume devices */
rc = ata_eh_resume(ap, &dev);
if (rc)
goto dev_fail;
/* configure transfer mode if the port has been reset */
if (ehc->i.flags & ATA_EHI_DID_RESET) {
rc = ata_set_mode(ap, &dev);
@ -1783,6 +1974,11 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
}
}
/* suspend devices */
rc = ata_eh_suspend(ap, &dev);
if (rc)
goto dev_fail;
goto out;
dev_fail:
@ -1908,11 +2104,124 @@ void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
ata_postreset_fn_t postreset)
{
if (!(ap->flags & ATA_FLAG_LOADING)) {
ata_eh_autopsy(ap);
ata_eh_report(ap);
}
ata_eh_autopsy(ap);
ata_eh_report(ap);
ata_eh_recover(ap, prereset, softreset, hardreset, postreset);
ata_eh_finish(ap);
}
/**
* ata_eh_handle_port_suspend - perform port suspend operation
* @ap: port to suspend
*
* Suspend @ap.
*
* LOCKING:
* Kernel thread context (may sleep).
*/
static void ata_eh_handle_port_suspend(struct ata_port *ap)
{
unsigned long flags;
int rc = 0;
/* are we suspending? */
spin_lock_irqsave(ap->lock, flags);
if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
ap->pm_mesg.event == PM_EVENT_ON) {
spin_unlock_irqrestore(ap->lock, flags);
return;
}
spin_unlock_irqrestore(ap->lock, flags);
WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED);
/* suspend */
ata_eh_freeze_port(ap);
if (ap->ops->port_suspend)
rc = ap->ops->port_suspend(ap, ap->pm_mesg);
/* report result */
spin_lock_irqsave(ap->lock, flags);
ap->pflags &= ~ATA_PFLAG_PM_PENDING;
if (rc == 0)
ap->pflags |= ATA_PFLAG_SUSPENDED;
else
ata_port_schedule_eh(ap);
if (ap->pm_result) {
*ap->pm_result = rc;
ap->pm_result = NULL;
}
spin_unlock_irqrestore(ap->lock, flags);
return;
}
/**
* ata_eh_handle_port_resume - perform port resume operation
* @ap: port to resume
*
* Resume @ap.
*
* This function also waits upto one second until all devices
* hanging off this port requests resume EH action. This is to
* prevent invoking EH and thus reset multiple times on resume.
*
* On DPM resume, where some of devices might not be resumed
* together, this may delay port resume upto one second, but such
* DPM resumes are rare and 1 sec delay isn't too bad.
*
* LOCKING:
* Kernel thread context (may sleep).
*/
static void ata_eh_handle_port_resume(struct ata_port *ap)
{
unsigned long timeout;
unsigned long flags;
int i, rc = 0;
/* are we resuming? */
spin_lock_irqsave(ap->lock, flags);
if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
ap->pm_mesg.event != PM_EVENT_ON) {
spin_unlock_irqrestore(ap->lock, flags);
return;
}
spin_unlock_irqrestore(ap->lock, flags);
/* spurious? */
if (!(ap->pflags & ATA_PFLAG_SUSPENDED))
goto done;
if (ap->ops->port_resume)
rc = ap->ops->port_resume(ap);
/* give devices time to request EH */
timeout = jiffies + HZ; /* 1s max */
while (1) {
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->device[i];
unsigned int action = ata_eh_dev_action(dev);
if ((dev->flags & ATA_DFLAG_SUSPENDED) &&
!(action & ATA_EH_RESUME))
break;
}
if (i == ATA_MAX_DEVICES || time_after(jiffies, timeout))
break;
msleep(10);
}
done:
spin_lock_irqsave(ap->lock, flags);
ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED);
if (ap->pm_result) {
*ap->pm_result = rc;
ap->pm_result = NULL;
}
spin_unlock_irqrestore(ap->lock, flags);
}

View File

@ -397,20 +397,129 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf)
}
}
int ata_scsi_device_resume(struct scsi_device *sdev)
{
struct ata_port *ap = ata_shost_to_port(sdev->host);
struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
return ata_device_resume(dev);
}
/**
* ata_scsi_device_suspend - suspend ATA device associated with sdev
* @sdev: the SCSI device to suspend
* @state: target power management state
*
* Request suspend EH action on the ATA device associated with
* @sdev and wait for the operation to complete.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* 0 on success, -errno otherwise.
*/
int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
{
struct ata_port *ap = ata_shost_to_port(sdev->host);
struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
unsigned long flags;
unsigned int action;
int rc = 0;
return ata_device_suspend(dev, state);
if (!dev)
goto out;
spin_lock_irqsave(ap->lock, flags);
/* wait for the previous resume to complete */
while (dev->flags & ATA_DFLAG_SUSPENDED) {
spin_unlock_irqrestore(ap->lock, flags);
ata_port_wait_eh(ap);
spin_lock_irqsave(ap->lock, flags);
}
/* if @sdev is already detached, nothing to do */
if (sdev->sdev_state == SDEV_OFFLINE ||
sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL)
goto out_unlock;
/* request suspend */
action = ATA_EH_SUSPEND;
if (state.event != PM_EVENT_SUSPEND)
action |= ATA_EH_PM_FREEZE;
ap->eh_info.dev_action[dev->devno] |= action;
ap->eh_info.flags |= ATA_EHI_QUIET;
ata_port_schedule_eh(ap);
spin_unlock_irqrestore(ap->lock, flags);
/* wait for EH to do the job */
ata_port_wait_eh(ap);
spin_lock_irqsave(ap->lock, flags);
/* If @sdev is still attached but the associated ATA device
* isn't suspended, the operation failed.
*/
if (sdev->sdev_state != SDEV_OFFLINE &&
sdev->sdev_state != SDEV_CANCEL && sdev->sdev_state != SDEV_DEL &&
!(dev->flags & ATA_DFLAG_SUSPENDED))
rc = -EIO;
out_unlock:
spin_unlock_irqrestore(ap->lock, flags);
out:
if (rc == 0)
sdev->sdev_gendev.power.power_state = state;
return rc;
}
/**
* ata_scsi_device_resume - resume ATA device associated with sdev
* @sdev: the SCSI device to resume
*
* Request resume EH action on the ATA device associated with
* @sdev and return immediately. This enables parallel
* wakeup/spinup of devices.
*
* LOCKING:
* Kernel thread context (may sleep).
*
* RETURNS:
* 0.
*/
int ata_scsi_device_resume(struct scsi_device *sdev)
{
struct ata_port *ap = ata_shost_to_port(sdev->host);
struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
struct ata_eh_info *ehi = &ap->eh_info;
unsigned long flags;
unsigned int action;
if (!dev)
goto out;
spin_lock_irqsave(ap->lock, flags);
/* if @sdev is already detached, nothing to do */
if (sdev->sdev_state == SDEV_OFFLINE ||
sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL)
goto out_unlock;
/* request resume */
action = ATA_EH_RESUME;
if (sdev->sdev_gendev.power.power_state.event == PM_EVENT_SUSPEND)
__ata_ehi_hotplugged(ehi);
else
action |= ATA_EH_PM_FREEZE | ATA_EH_SOFTRESET;
ehi->dev_action[dev->devno] |= action;
/* We don't want autopsy and verbose EH messages. Disable
* those if we're the only device on this link.
*/
if (ata_port_max_devices(ap) == 1)
ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
ata_port_schedule_eh(ap);
out_unlock:
spin_unlock_irqrestore(ap->lock, flags);
out:
sdev->sdev_gendev.power.power_state = PMSG_ON;
return 0;
}
/**
@ -2930,7 +3039,7 @@ void ata_scsi_hotplug(void *data)
struct ata_port *ap = data;
int i;
if (ap->flags & ATA_FLAG_UNLOADING) {
if (ap->pflags & ATA_PFLAG_UNLOADING) {
DPRINTK("ENTER/EXIT - unloading\n");
return;
}
@ -3011,6 +3120,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
if (dev) {
ap->eh_info.probe_mask |= 1 << dev->devno;
ap->eh_info.action |= ATA_EH_SOFTRESET;
ap->eh_info.flags |= ATA_EHI_RESUME_LINK;
} else
rc = -EINVAL;
}

View File

@ -109,6 +109,7 @@ enum {
};
static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
static int sil_pci_device_resume(struct pci_dev *pdev);
static void sil_dev_config(struct ata_port *ap, struct ata_device *dev);
static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
@ -160,6 +161,8 @@ static struct pci_driver sil_pci_driver = {
.id_table = sil_pci_tbl,
.probe = sil_init_one,
.remove = ata_pci_remove_one,
.suspend = ata_pci_device_suspend,
.resume = sil_pci_device_resume,
};
static struct scsi_host_template sil_sht = {
@ -178,6 +181,8 @@ static struct scsi_host_template sil_sht = {
.slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
.suspend = ata_scsi_device_suspend,
.resume = ata_scsi_device_resume,
};
static const struct ata_port_operations sil_ops = {
@ -370,7 +375,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
* during hardreset makes controllers with broken SIEN
* repeat probing needlessly.
*/
if (!(ap->flags & ATA_FLAG_FROZEN)) {
if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
ata_ehi_hotplugged(&ap->eh_info);
ap->eh_info.serror |= serror;
}
@ -561,6 +566,52 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
}
}
static void sil_init_controller(struct pci_dev *pdev,
int n_ports, unsigned long host_flags,
void __iomem *mmio_base)
{
u8 cls;
u32 tmp;
int i;
/* Initialize FIFO PCI bus arbitration */
cls = sil_get_device_cache_line(pdev);
if (cls) {
cls >>= 3;
cls++; /* cls = (line_size/8)+1 */
for (i = 0; i < n_ports; i++)
writew(cls << 8 | cls,
mmio_base + sil_port[i].fifo_cfg);
} else
dev_printk(KERN_WARNING, &pdev->dev,
"cache line size not set. Driver may not function\n");
/* Apply R_ERR on DMA activate FIS errata workaround */
if (host_flags & SIL_FLAG_RERR_ON_DMA_ACT) {
int cnt;
for (i = 0, cnt = 0; i < n_ports; i++) {
tmp = readl(mmio_base + sil_port[i].sfis_cfg);
if ((tmp & 0x3) != 0x01)
continue;
if (!cnt)
dev_printk(KERN_INFO, &pdev->dev,
"Applying R_ERR on DMA activate "
"FIS errata fix\n");
writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg);
cnt++;
}
}
if (n_ports == 4) {
/* flip the magic "make 4 ports work" bit */
tmp = readl(mmio_base + sil_port[2].bmdma);
if ((tmp & SIL_INTR_STEERING) == 0)
writel(tmp | SIL_INTR_STEERING,
mmio_base + sil_port[2].bmdma);
}
}
static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
@ -570,8 +621,6 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
int rc;
unsigned int i;
int pci_dev_busy = 0;
u32 tmp;
u8 cls;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
@ -630,42 +679,8 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
ata_std_ports(&probe_ent->port[i]);
}
/* Initialize FIFO PCI bus arbitration */
cls = sil_get_device_cache_line(pdev);
if (cls) {
cls >>= 3;
cls++; /* cls = (line_size/8)+1 */
for (i = 0; i < probe_ent->n_ports; i++)
writew(cls << 8 | cls,
mmio_base + sil_port[i].fifo_cfg);
} else
dev_printk(KERN_WARNING, &pdev->dev,
"cache line size not set. Driver may not function\n");
/* Apply R_ERR on DMA activate FIS errata workaround */
if (probe_ent->host_flags & SIL_FLAG_RERR_ON_DMA_ACT) {
int cnt;
for (i = 0, cnt = 0; i < probe_ent->n_ports; i++) {
tmp = readl(mmio_base + sil_port[i].sfis_cfg);
if ((tmp & 0x3) != 0x01)
continue;
if (!cnt)
dev_printk(KERN_INFO, &pdev->dev,
"Applying R_ERR on DMA activate "
"FIS errata fix\n");
writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg);
cnt++;
}
}
if (ent->driver_data == sil_3114) {
/* flip the magic "make 4 ports work" bit */
tmp = readl(mmio_base + sil_port[2].bmdma);
if ((tmp & SIL_INTR_STEERING) == 0)
writel(tmp | SIL_INTR_STEERING,
mmio_base + sil_port[2].bmdma);
}
sil_init_controller(pdev, probe_ent->n_ports, probe_ent->host_flags,
mmio_base);
pci_set_master(pdev);
@ -685,6 +700,18 @@ err_out:
return rc;
}
static int sil_pci_device_resume(struct pci_dev *pdev)
{
struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
ata_pci_device_do_resume(pdev);
sil_init_controller(pdev, host_set->n_ports, host_set->ports[0]->flags,
host_set->mmio_base);
ata_host_set_resume(host_set);
return 0;
}
static int __init sil_init(void)
{
return pci_module_init(&sil_pci_driver);

View File

@ -92,6 +92,7 @@ enum {
HOST_CTRL_STOP = (1 << 18), /* latched PCI STOP */
HOST_CTRL_DEVSEL = (1 << 19), /* latched PCI DEVSEL */
HOST_CTRL_REQ64 = (1 << 20), /* latched PCI REQ64 */
HOST_CTRL_GLOBAL_RST = (1 << 31), /* global reset */
/*
* Port registers
@ -338,6 +339,7 @@ static int sil24_port_start(struct ata_port *ap);
static void sil24_port_stop(struct ata_port *ap);
static void sil24_host_stop(struct ata_host_set *host_set);
static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int sil24_pci_device_resume(struct pci_dev *pdev);
static const struct pci_device_id sil24_pci_tbl[] = {
{ 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
@ -353,6 +355,8 @@ static struct pci_driver sil24_pci_driver = {
.id_table = sil24_pci_tbl,
.probe = sil24_init_one,
.remove = ata_pci_remove_one, /* safe? */
.suspend = ata_pci_device_suspend,
.resume = sil24_pci_device_resume,
};
static struct scsi_host_template sil24_sht = {
@ -372,6 +376,8 @@ static struct scsi_host_template sil24_sht = {
.slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
.suspend = ata_scsi_device_suspend,
.resume = ata_scsi_device_resume,
};
static const struct ata_port_operations sil24_ops = {
@ -607,7 +613,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
/* SStatus oscillates between zero and valid status after
* DEV_RST, debounce it.
*/
rc = sata_phy_debounce(ap, sata_deb_timing_before_fsrst);
rc = sata_phy_debounce(ap, sata_deb_timing_long);
if (rc) {
reason = "PHY debouncing failed";
goto err;
@ -988,6 +994,64 @@ static void sil24_host_stop(struct ata_host_set *host_set)
kfree(hpriv);
}
static void sil24_init_controller(struct pci_dev *pdev, int n_ports,
unsigned long host_flags,
void __iomem *host_base,
void __iomem *port_base)
{
u32 tmp;
int i;
/* GPIO off */
writel(0, host_base + HOST_FLASH_CMD);
/* clear global reset & mask interrupts during initialization */
writel(0, host_base + HOST_CTRL);
/* init ports */
for (i = 0; i < n_ports; i++) {
void __iomem *port = port_base + i * PORT_REGS_SIZE;
/* Initial PHY setting */
writel(0x20c, port + PORT_PHY_CFG);
/* Clear port RST */
tmp = readl(port + PORT_CTRL_STAT);
if (tmp & PORT_CS_PORT_RST) {
writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
tmp = ata_wait_register(port + PORT_CTRL_STAT,
PORT_CS_PORT_RST,
PORT_CS_PORT_RST, 10, 100);
if (tmp & PORT_CS_PORT_RST)
dev_printk(KERN_ERR, &pdev->dev,
"failed to clear port RST\n");
}
/* Configure IRQ WoC */
if (host_flags & SIL24_FLAG_PCIX_IRQ_WOC)
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
else
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
/* Zero error counters. */
writel(0x8000, port + PORT_DECODE_ERR_THRESH);
writel(0x8000, port + PORT_CRC_ERR_THRESH);
writel(0x8000, port + PORT_HSHK_ERR_THRESH);
writel(0x0000, port + PORT_DECODE_ERR_CNT);
writel(0x0000, port + PORT_CRC_ERR_CNT);
writel(0x0000, port + PORT_HSHK_ERR_CNT);
/* Always use 64bit activation */
writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
/* Clear port multiplier enable and resume bits */
writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
}
/* Turn on interrupts */
writel(IRQ_STAT_4PORTS, host_base + HOST_CTRL);
}
static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version = 0;
@ -1076,9 +1140,6 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
}
/* GPIO off */
writel(0, host_base + HOST_FLASH_CMD);
/* Apply workaround for completion IRQ loss on PCI-X errata */
if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC) {
tmp = readl(host_base + HOST_CTRL);
@ -1090,56 +1151,18 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->host_flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;
}
/* clear global reset & mask interrupts during initialization */
writel(0, host_base + HOST_CTRL);
for (i = 0; i < probe_ent->n_ports; i++) {
void __iomem *port = port_base + i * PORT_REGS_SIZE;
unsigned long portu = (unsigned long)port;
unsigned long portu =
(unsigned long)port_base + i * PORT_REGS_SIZE;
probe_ent->port[i].cmd_addr = portu;
probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
ata_std_ports(&probe_ent->port[i]);
/* Initial PHY setting */
writel(0x20c, port + PORT_PHY_CFG);
/* Clear port RST */
tmp = readl(port + PORT_CTRL_STAT);
if (tmp & PORT_CS_PORT_RST) {
writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
tmp = ata_wait_register(port + PORT_CTRL_STAT,
PORT_CS_PORT_RST,
PORT_CS_PORT_RST, 10, 100);
if (tmp & PORT_CS_PORT_RST)
dev_printk(KERN_ERR, &pdev->dev,
"failed to clear port RST\n");
}
/* Configure IRQ WoC */
if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC)
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
else
writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
/* Zero error counters. */
writel(0x8000, port + PORT_DECODE_ERR_THRESH);
writel(0x8000, port + PORT_CRC_ERR_THRESH);
writel(0x8000, port + PORT_HSHK_ERR_THRESH);
writel(0x0000, port + PORT_DECODE_ERR_CNT);
writel(0x0000, port + PORT_CRC_ERR_CNT);
writel(0x0000, port + PORT_HSHK_ERR_CNT);
/* Always use 64bit activation */
writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
/* Clear port multiplier enable and resume bits */
writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
}
/* Turn on interrupts */
writel(IRQ_STAT_4PORTS, host_base + HOST_CTRL);
sil24_init_controller(pdev, probe_ent->n_ports, probe_ent->host_flags,
host_base, port_base);
pci_set_master(pdev);
@ -1162,6 +1185,25 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return rc;
}
static int sil24_pci_device_resume(struct pci_dev *pdev)
{
struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
struct sil24_host_priv *hpriv = host_set->private_data;
ata_pci_device_do_resume(pdev);
if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND)
writel(HOST_CTRL_GLOBAL_RST, hpriv->host_base + HOST_CTRL);
sil24_init_controller(pdev, host_set->n_ports,
host_set->ports[0]->flags,
hpriv->host_base, hpriv->port_base);
ata_host_set_resume(host_set);
return 0;
}
static int __init sil24_init(void)
{
return pci_module_init(&sil24_pci_driver);

View File

@ -297,7 +297,7 @@ static const struct ata_port_operations vsc_sata_ops = {
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.data_xfer = ata_pio_data_xfer,
.data_xfer = ata_mmio_data_xfer,
.freeze = ata_bmdma_freeze,
.thaw = ata_bmdma_thaw,
.error_handler = ata_bmdma_error_handler,

View File

@ -41,6 +41,7 @@
#include <asm/mach/serial_at91.h>
#include <asm/arch/board.h>
#include <asm/arch/system.h>
#include <asm/arch/gpio.h>
#if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@ -140,9 +141,9 @@ static void at91_set_mctrl(struct uart_port *port, u_int mctrl)
*/
if (port->mapbase == AT91_BASE_US0) {
if (mctrl & TIOCM_RTS)
at91_sys_write(AT91_PIOA + PIO_CODR, AT91_PA21_RTS0);
at91_set_gpio_value(AT91_PIN_PA21, 0);
else
at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0);
at91_set_gpio_value(AT91_PIN_PA21, 1);
}
}

View File

@ -454,7 +454,7 @@ static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *ho
fl->fl_ops = &nlmclnt_lock_ops;
}
static void do_vfs_lock(struct file_lock *fl)
static int do_vfs_lock(struct file_lock *fl)
{
int res = 0;
switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
@ -467,9 +467,7 @@ static void do_vfs_lock(struct file_lock *fl)
default:
BUG();
}
if (res < 0)
printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
__FUNCTION__);
return res;
}
/*
@ -498,6 +496,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
struct nlm_host *host = req->a_host;
struct nlm_res *resp = &req->a_res;
struct nlm_wait *block = NULL;
unsigned char fl_flags = fl->fl_flags;
int status = -ENOLCK;
if (!host->h_monitored && nsm_monitor(host) < 0) {
@ -505,6 +504,10 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
host->h_name);
goto out;
}
fl->fl_flags |= FL_ACCESS;
status = do_vfs_lock(fl);
if (status < 0)
goto out;
block = nlmclnt_prepare_block(host, fl);
again:
@ -539,9 +542,10 @@ again:
up_read(&host->h_rwsem);
goto again;
}
fl->fl_flags |= FL_SLEEP;
/* Ensure the resulting lock will get added to granted list */
do_vfs_lock(fl);
fl->fl_flags = fl_flags | FL_SLEEP;
if (do_vfs_lock(fl) < 0)
printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
up_read(&host->h_rwsem);
}
status = nlm_stat_to_errno(resp->status);
@ -552,6 +556,7 @@ out_unblock:
nlmclnt_cancel(host, req->a_args.block, fl);
out:
nlm_release_call(req);
fl->fl_flags = fl_flags;
return status;
}
@ -606,15 +611,19 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
{
struct nlm_host *host = req->a_host;
struct nlm_res *resp = &req->a_res;
int status;
int status = 0;
/*
* Note: the server is supposed to either grant us the unlock
* request, or to deny it with NLM_LCK_DENIED_GRACE_PERIOD. In either
* case, we want to unlock.
*/
fl->fl_flags |= FL_EXISTS;
down_read(&host->h_rwsem);
do_vfs_lock(fl);
if (do_vfs_lock(fl) == -ENOENT) {
up_read(&host->h_rwsem);
goto out;
}
up_read(&host->h_rwsem);
if (req->a_flags & RPC_TASK_ASYNC)
@ -624,7 +633,6 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
if (status < 0)
goto out;
status = 0;
if (resp->status == NLM_LCK_GRANTED)
goto out;

View File

@ -725,6 +725,10 @@ next_task:
/* Try to create a FLOCK lock on filp. We always insert new FLOCK locks
* at the head of the list, but that's secret knowledge known only to
* flock_lock_file and posix_lock_file.
*
* Note that if called with an FL_EXISTS argument, the caller may determine
* whether or not a lock was successfully freed by testing the return
* value for -ENOENT.
*/
static int flock_lock_file(struct file *filp, struct file_lock *request)
{
@ -735,6 +739,8 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
int found = 0;
lock_kernel();
if (request->fl_flags & FL_ACCESS)
goto find_conflict;
for_each_lock(inode, before) {
struct file_lock *fl = *before;
if (IS_POSIX(fl))
@ -750,8 +756,11 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
break;
}
if (request->fl_type == F_UNLCK)
if (request->fl_type == F_UNLCK) {
if ((request->fl_flags & FL_EXISTS) && !found)
error = -ENOENT;
goto out;
}
error = -ENOMEM;
new_fl = locks_alloc_lock();
@ -764,6 +773,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
if (found)
cond_resched();
find_conflict:
for_each_lock(inode, before) {
struct file_lock *fl = *before;
if (IS_POSIX(fl))
@ -777,6 +787,8 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
locks_insert_block(fl, request);
goto out;
}
if (request->fl_flags & FL_ACCESS)
goto out;
locks_copy_lock(new_fl, request);
locks_insert_lock(&inode->i_flock, new_fl);
new_fl = NULL;
@ -948,8 +960,11 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
error = 0;
if (!added) {
if (request->fl_type == F_UNLCK)
if (request->fl_type == F_UNLCK) {
if (request->fl_flags & FL_EXISTS)
error = -ENOENT;
goto out;
}
if (!new_fl) {
error = -ENOLCK;
@ -996,6 +1011,10 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request
* Add a POSIX style lock to a file.
* We merge adjacent & overlapping locks whenever possible.
* POSIX locks are sorted by owner task, then by starting address
*
* Note that if called with an FL_EXISTS argument, the caller may determine
* whether or not a lock was successfully freed by testing the return
* value for -ENOENT.
*/
int posix_lock_file(struct file *filp, struct file_lock *fl)
{

View File

@ -690,7 +690,9 @@ int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
goto out_force;
/* This is an open(2) */
if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 &&
!(server->flags & NFS_MOUNT_NOCTO))
!(server->flags & NFS_MOUNT_NOCTO) &&
(S_ISREG(inode->i_mode) ||
S_ISDIR(inode->i_mode)))
goto out_force;
}
return nfs_revalidate_inode(server, inode);

View File

@ -67,25 +67,19 @@ struct nfs_direct_req {
struct kref kref; /* release manager */
/* I/O parameters */
struct list_head list, /* nfs_read/write_data structs */
rewrite_list; /* saved nfs_write_data structs */
struct nfs_open_context *ctx; /* file open context info */
struct kiocb * iocb; /* controlling i/o request */
struct inode * inode; /* target file of i/o */
unsigned long user_addr; /* location of user's buffer */
size_t user_count; /* total bytes to move */
loff_t pos; /* starting offset in file */
struct page ** pages; /* pages in our buffer */
unsigned int npages; /* count of pages */
/* completion state */
atomic_t io_count; /* i/os we're waiting for */
spinlock_t lock; /* protect completion state */
int outstanding; /* i/os we're waiting for */
ssize_t count, /* bytes actually processed */
error; /* any reported error */
struct completion completion; /* wait for i/o completion */
/* commit state */
struct list_head rewrite_list; /* saved nfs_write_data structs */
struct nfs_write_data * commit_data; /* special write_data for commits */
int flags;
#define NFS_ODIRECT_DO_COMMIT (1) /* an unstable reply was received */
@ -93,8 +87,37 @@ struct nfs_direct_req {
struct nfs_writeverf verf; /* unstable write verifier */
};
static void nfs_direct_write_schedule(struct nfs_direct_req *dreq, int sync);
static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode);
static const struct rpc_call_ops nfs_write_direct_ops;
static inline void get_dreq(struct nfs_direct_req *dreq)
{
atomic_inc(&dreq->io_count);
}
static inline int put_dreq(struct nfs_direct_req *dreq)
{
return atomic_dec_and_test(&dreq->io_count);
}
/*
* "size" is never larger than rsize or wsize.
*/
static inline int nfs_direct_count_pages(unsigned long user_addr, size_t size)
{
int page_count;
page_count = (user_addr + size + PAGE_SIZE - 1) >> PAGE_SHIFT;
page_count -= user_addr >> PAGE_SHIFT;
BUG_ON(page_count < 0);
return page_count;
}
static inline unsigned int nfs_max_pages(unsigned int size)
{
return (size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
}
/**
* nfs_direct_IO - NFS address space operation for direct I/O
@ -118,50 +141,21 @@ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_
return -EINVAL;
}
static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty)
static void nfs_direct_dirty_pages(struct page **pages, int npages)
{
int i;
for (i = 0; i < npages; i++) {
struct page *page = pages[i];
if (do_dirty && !PageCompound(page))
if (!PageCompound(page))
set_page_dirty_lock(page);
page_cache_release(page);
}
kfree(pages);
}
static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t size, struct page ***pages)
static void nfs_direct_release_pages(struct page **pages, int npages)
{
int result = -ENOMEM;
unsigned long page_count;
size_t array_size;
page_count = (user_addr + size + PAGE_SIZE - 1) >> PAGE_SHIFT;
page_count -= user_addr >> PAGE_SHIFT;
array_size = (page_count * sizeof(struct page *));
*pages = kmalloc(array_size, GFP_KERNEL);
if (*pages) {
down_read(&current->mm->mmap_sem);
result = get_user_pages(current, current->mm, user_addr,
page_count, (rw == READ), 0,
*pages, NULL);
up_read(&current->mm->mmap_sem);
if (result != page_count) {
/*
* If we got fewer pages than expected from
* get_user_pages(), the user buffer runs off the
* end of a mapping; return EFAULT.
*/
if (result >= 0) {
nfs_free_user_pages(*pages, result, 0);
result = -EFAULT;
} else
kfree(*pages);
*pages = NULL;
}
}
return result;
int i;
for (i = 0; i < npages; i++)
page_cache_release(pages[i]);
}
static inline struct nfs_direct_req *nfs_direct_req_alloc(void)
@ -173,13 +167,13 @@ static inline struct nfs_direct_req *nfs_direct_req_alloc(void)
return NULL;
kref_init(&dreq->kref);
kref_get(&dreq->kref);
init_completion(&dreq->completion);
INIT_LIST_HEAD(&dreq->list);
INIT_LIST_HEAD(&dreq->rewrite_list);
dreq->iocb = NULL;
dreq->ctx = NULL;
spin_lock_init(&dreq->lock);
dreq->outstanding = 0;
atomic_set(&dreq->io_count, 0);
dreq->count = 0;
dreq->error = 0;
dreq->flags = 0;
@ -220,18 +214,11 @@ out:
}
/*
* We must hold a reference to all the pages in this direct read request
* until the RPCs complete. This could be long *after* we are woken up in
* nfs_direct_wait (for instance, if someone hits ^C on a slow server).
*
* In addition, synchronous I/O uses a stack-allocated iocb. Thus we
* can't trust the iocb is still valid here if this is a synchronous
* request. If the waiter is woken prematurely, the iocb is long gone.
* Synchronous I/O uses a stack-allocated iocb. Thus we can't trust
* the iocb is still valid here if this is a synchronous request.
*/
static void nfs_direct_complete(struct nfs_direct_req *dreq)
{
nfs_free_user_pages(dreq->pages, dreq->npages, 1);
if (dreq->iocb) {
long res = (long) dreq->error;
if (!res)
@ -244,48 +231,10 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq)
}
/*
* Note we also set the number of requests we have in the dreq when we are
* done. This prevents races with I/O completion so we will always wait
* until all requests have been dispatched and completed.
* We must hold a reference to all the pages in this direct read request
* until the RPCs complete. This could be long *after* we are woken up in
* nfs_direct_wait (for instance, if someone hits ^C on a slow server).
*/
static struct nfs_direct_req *nfs_direct_read_alloc(size_t nbytes, size_t rsize)
{
struct list_head *list;
struct nfs_direct_req *dreq;
unsigned int rpages = (rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
dreq = nfs_direct_req_alloc();
if (!dreq)
return NULL;
list = &dreq->list;
for(;;) {
struct nfs_read_data *data = nfs_readdata_alloc(rpages);
if (unlikely(!data)) {
while (!list_empty(list)) {
data = list_entry(list->next,
struct nfs_read_data, pages);
list_del(&data->pages);
nfs_readdata_free(data);
}
kref_put(&dreq->kref, nfs_direct_req_release);
return NULL;
}
INIT_LIST_HEAD(&data->pages);
list_add(&data->pages, list);
data->req = (struct nfs_page *) dreq;
dreq->outstanding++;
if (nbytes <= rsize)
break;
nbytes -= rsize;
}
kref_get(&dreq->kref);
return dreq;
}
static void nfs_direct_read_result(struct rpc_task *task, void *calldata)
{
struct nfs_read_data *data = calldata;
@ -294,6 +243,9 @@ static void nfs_direct_read_result(struct rpc_task *task, void *calldata)
if (nfs_readpage_result(task, data) != 0)
return;
nfs_direct_dirty_pages(data->pagevec, data->npages);
nfs_direct_release_pages(data->pagevec, data->npages);
spin_lock(&dreq->lock);
if (likely(task->tk_status >= 0))
@ -301,13 +253,10 @@ static void nfs_direct_read_result(struct rpc_task *task, void *calldata)
else
dreq->error = task->tk_status;
if (--dreq->outstanding) {
spin_unlock(&dreq->lock);
return;
}
spin_unlock(&dreq->lock);
nfs_direct_complete(dreq);
if (put_dreq(dreq))
nfs_direct_complete(dreq);
}
static const struct rpc_call_ops nfs_read_direct_ops = {
@ -316,41 +265,60 @@ static const struct rpc_call_ops nfs_read_direct_ops = {
};
/*
* For each nfs_read_data struct that was allocated on the list, dispatch
* an NFS READ operation
* For each rsize'd chunk of the user's buffer, dispatch an NFS READ
* operation. If nfs_readdata_alloc() or get_user_pages() fails,
* bail and stop sending more reads. Read length accounting is
* handled automatically by nfs_direct_read_result(). Otherwise, if
* no requests have been sent, just return an error.
*/
static void nfs_direct_read_schedule(struct nfs_direct_req *dreq)
static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos)
{
struct nfs_open_context *ctx = dreq->ctx;
struct inode *inode = ctx->dentry->d_inode;
struct list_head *list = &dreq->list;
struct page **pages = dreq->pages;
size_t count = dreq->user_count;
loff_t pos = dreq->pos;
size_t rsize = NFS_SERVER(inode)->rsize;
unsigned int curpage, pgbase;
unsigned int rpages = nfs_max_pages(rsize);
unsigned int pgbase;
int result;
ssize_t started = 0;
curpage = 0;
pgbase = dreq->user_addr & ~PAGE_MASK;
get_dreq(dreq);
pgbase = user_addr & ~PAGE_MASK;
do {
struct nfs_read_data *data;
size_t bytes;
result = -ENOMEM;
data = nfs_readdata_alloc(rpages);
if (unlikely(!data))
break;
bytes = rsize;
if (count < rsize)
bytes = count;
BUG_ON(list_empty(list));
data = list_entry(list->next, struct nfs_read_data, pages);
list_del_init(&data->pages);
data->npages = nfs_direct_count_pages(user_addr, bytes);
down_read(&current->mm->mmap_sem);
result = get_user_pages(current, current->mm, user_addr,
data->npages, 1, 0, data->pagevec, NULL);
up_read(&current->mm->mmap_sem);
if (unlikely(result < data->npages)) {
if (result > 0)
nfs_direct_release_pages(data->pagevec, result);
nfs_readdata_release(data);
break;
}
get_dreq(dreq);
data->req = (struct nfs_page *) dreq;
data->inode = inode;
data->cred = ctx->cred;
data->args.fh = NFS_FH(inode);
data->args.context = ctx;
data->args.offset = pos;
data->args.pgbase = pgbase;
data->args.pages = &pages[curpage];
data->args.pages = data->pagevec;
data->args.count = bytes;
data->res.fattr = &data->fattr;
data->res.eof = 0;
@ -373,33 +341,35 @@ static void nfs_direct_read_schedule(struct nfs_direct_req *dreq)
bytes,
(unsigned long long)data->args.offset);
started += bytes;
user_addr += bytes;
pos += bytes;
pgbase += bytes;
curpage += pgbase >> PAGE_SHIFT;
pgbase &= ~PAGE_MASK;
count -= bytes;
} while (count != 0);
BUG_ON(!list_empty(list));
if (put_dreq(dreq))
nfs_direct_complete(dreq);
if (started)
return 0;
return result < 0 ? (ssize_t) result : -EFAULT;
}
static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos, struct page **pages, unsigned int nr_pages)
static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos)
{
ssize_t result;
ssize_t result = 0;
sigset_t oldset;
struct inode *inode = iocb->ki_filp->f_mapping->host;
struct rpc_clnt *clnt = NFS_CLIENT(inode);
struct nfs_direct_req *dreq;
dreq = nfs_direct_read_alloc(count, NFS_SERVER(inode)->rsize);
dreq = nfs_direct_req_alloc();
if (!dreq)
return -ENOMEM;
dreq->user_addr = user_addr;
dreq->user_count = count;
dreq->pos = pos;
dreq->pages = pages;
dreq->npages = nr_pages;
dreq->inode = inode;
dreq->ctx = get_nfs_open_context((struct nfs_open_context *)iocb->ki_filp->private_data);
if (!is_sync_kiocb(iocb))
@ -407,8 +377,9 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size
nfs_add_stats(inode, NFSIOS_DIRECTREADBYTES, count);
rpc_clnt_sigmask(clnt, &oldset);
nfs_direct_read_schedule(dreq);
result = nfs_direct_wait(dreq);
result = nfs_direct_read_schedule(dreq, user_addr, count, pos);
if (!result)
result = nfs_direct_wait(dreq);
rpc_clnt_sigunmask(clnt, &oldset);
return result;
@ -416,10 +387,10 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size
static void nfs_direct_free_writedata(struct nfs_direct_req *dreq)
{
list_splice_init(&dreq->rewrite_list, &dreq->list);
while (!list_empty(&dreq->list)) {
struct nfs_write_data *data = list_entry(dreq->list.next, struct nfs_write_data, pages);
while (!list_empty(&dreq->rewrite_list)) {
struct nfs_write_data *data = list_entry(dreq->rewrite_list.next, struct nfs_write_data, pages);
list_del(&data->pages);
nfs_direct_release_pages(data->pagevec, data->npages);
nfs_writedata_release(data);
}
}
@ -427,14 +398,51 @@ static void nfs_direct_free_writedata(struct nfs_direct_req *dreq)
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq)
{
struct list_head *pos;
struct inode *inode = dreq->inode;
struct list_head *p;
struct nfs_write_data *data;
list_splice_init(&dreq->rewrite_list, &dreq->list);
list_for_each(pos, &dreq->list)
dreq->outstanding++;
dreq->count = 0;
get_dreq(dreq);
nfs_direct_write_schedule(dreq, FLUSH_STABLE);
list_for_each(p, &dreq->rewrite_list) {
data = list_entry(p, struct nfs_write_data, pages);
get_dreq(dreq);
/*
* Reset data->res.
*/
nfs_fattr_init(&data->fattr);
data->res.count = data->args.count;
memset(&data->verf, 0, sizeof(data->verf));
/*
* Reuse data->task; data->args should not have changed
* since the original request was sent.
*/
rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC,
&nfs_write_direct_ops, data);
NFS_PROTO(inode)->write_setup(data, FLUSH_STABLE);
data->task.tk_priority = RPC_PRIORITY_NORMAL;
data->task.tk_cookie = (unsigned long) inode;
/*
* We're called via an RPC callback, so BKL is already held.
*/
rpc_execute(&data->task);
dprintk("NFS: %5u rescheduled direct write call (req %s/%Ld, %u bytes @ offset %Lu)\n",
data->task.tk_pid,
inode->i_sb->s_id,
(long long)NFS_FILEID(inode),
data->args.count,
(unsigned long long)data->args.offset);
}
if (put_dreq(dreq))
nfs_direct_write_complete(dreq, inode);
}
static void nfs_direct_commit_result(struct rpc_task *task, void *calldata)
@ -471,8 +479,8 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
data->cred = dreq->ctx->cred;
data->args.fh = NFS_FH(data->inode);
data->args.offset = dreq->pos;
data->args.count = dreq->user_count;
data->args.offset = 0;
data->args.count = 0;
data->res.count = 0;
data->res.fattr = &data->fattr;
data->res.verf = &data->verf;
@ -534,47 +542,6 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
}
#endif
static struct nfs_direct_req *nfs_direct_write_alloc(size_t nbytes, size_t wsize)
{
struct list_head *list;
struct nfs_direct_req *dreq;
unsigned int wpages = (wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
dreq = nfs_direct_req_alloc();
if (!dreq)
return NULL;
list = &dreq->list;
for(;;) {
struct nfs_write_data *data = nfs_writedata_alloc(wpages);
if (unlikely(!data)) {
while (!list_empty(list)) {
data = list_entry(list->next,
struct nfs_write_data, pages);
list_del(&data->pages);
nfs_writedata_free(data);
}
kref_put(&dreq->kref, nfs_direct_req_release);
return NULL;
}
INIT_LIST_HEAD(&data->pages);
list_add(&data->pages, list);
data->req = (struct nfs_page *) dreq;
dreq->outstanding++;
if (nbytes <= wsize)
break;
nbytes -= wsize;
}
nfs_alloc_commit_data(dreq);
kref_get(&dreq->kref);
return dreq;
}
static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
{
struct nfs_write_data *data = calldata;
@ -604,8 +571,6 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
}
}
}
/* In case we have to resend */
data->args.stable = NFS_FILE_SYNC;
spin_unlock(&dreq->lock);
}
@ -619,14 +584,8 @@ static void nfs_direct_write_release(void *calldata)
struct nfs_write_data *data = calldata;
struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req;
spin_lock(&dreq->lock);
if (--dreq->outstanding) {
spin_unlock(&dreq->lock);
return;
}
spin_unlock(&dreq->lock);
nfs_direct_write_complete(dreq, data->inode);
if (put_dreq(dreq))
nfs_direct_write_complete(dreq, data->inode);
}
static const struct rpc_call_ops nfs_write_direct_ops = {
@ -635,41 +594,62 @@ static const struct rpc_call_ops nfs_write_direct_ops = {
};
/*
* For each nfs_write_data struct that was allocated on the list, dispatch
* an NFS WRITE operation
* For each wsize'd chunk of the user's buffer, dispatch an NFS WRITE
* operation. If nfs_writedata_alloc() or get_user_pages() fails,
* bail and stop sending more writes. Write length accounting is
* handled automatically by nfs_direct_write_result(). Otherwise, if
* no requests have been sent, just return an error.
*/
static void nfs_direct_write_schedule(struct nfs_direct_req *dreq, int sync)
static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos, int sync)
{
struct nfs_open_context *ctx = dreq->ctx;
struct inode *inode = ctx->dentry->d_inode;
struct list_head *list = &dreq->list;
struct page **pages = dreq->pages;
size_t count = dreq->user_count;
loff_t pos = dreq->pos;
size_t wsize = NFS_SERVER(inode)->wsize;
unsigned int curpage, pgbase;
unsigned int wpages = nfs_max_pages(wsize);
unsigned int pgbase;
int result;
ssize_t started = 0;
curpage = 0;
pgbase = dreq->user_addr & ~PAGE_MASK;
get_dreq(dreq);
pgbase = user_addr & ~PAGE_MASK;
do {
struct nfs_write_data *data;
size_t bytes;
result = -ENOMEM;
data = nfs_writedata_alloc(wpages);
if (unlikely(!data))
break;
bytes = wsize;
if (count < wsize)
bytes = count;
BUG_ON(list_empty(list));
data = list_entry(list->next, struct nfs_write_data, pages);
data->npages = nfs_direct_count_pages(user_addr, bytes);
down_read(&current->mm->mmap_sem);
result = get_user_pages(current, current->mm, user_addr,
data->npages, 0, 0, data->pagevec, NULL);
up_read(&current->mm->mmap_sem);
if (unlikely(result < data->npages)) {
if (result > 0)
nfs_direct_release_pages(data->pagevec, result);
nfs_writedata_release(data);
break;
}
get_dreq(dreq);
list_move_tail(&data->pages, &dreq->rewrite_list);
data->req = (struct nfs_page *) dreq;
data->inode = inode;
data->cred = ctx->cred;
data->args.fh = NFS_FH(inode);
data->args.context = ctx;
data->args.offset = pos;
data->args.pgbase = pgbase;
data->args.pages = &pages[curpage];
data->args.pages = data->pagevec;
data->args.count = bytes;
data->res.fattr = &data->fattr;
data->res.count = bytes;
@ -693,19 +673,26 @@ static void nfs_direct_write_schedule(struct nfs_direct_req *dreq, int sync)
bytes,
(unsigned long long)data->args.offset);
started += bytes;
user_addr += bytes;
pos += bytes;
pgbase += bytes;
curpage += pgbase >> PAGE_SHIFT;
pgbase &= ~PAGE_MASK;
count -= bytes;
} while (count != 0);
BUG_ON(!list_empty(list));
if (put_dreq(dreq))
nfs_direct_write_complete(dreq, inode);
if (started)
return 0;
return result < 0 ? (ssize_t) result : -EFAULT;
}
static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos, struct page **pages, int nr_pages)
static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos)
{
ssize_t result;
ssize_t result = 0;
sigset_t oldset;
struct inode *inode = iocb->ki_filp->f_mapping->host;
struct rpc_clnt *clnt = NFS_CLIENT(inode);
@ -713,17 +700,14 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz
size_t wsize = NFS_SERVER(inode)->wsize;
int sync = 0;
dreq = nfs_direct_write_alloc(count, wsize);
dreq = nfs_direct_req_alloc();
if (!dreq)
return -ENOMEM;
nfs_alloc_commit_data(dreq);
if (dreq->commit_data == NULL || count < wsize)
sync = FLUSH_STABLE;
dreq->user_addr = user_addr;
dreq->user_count = count;
dreq->pos = pos;
dreq->pages = pages;
dreq->npages = nr_pages;
dreq->inode = inode;
dreq->ctx = get_nfs_open_context((struct nfs_open_context *)iocb->ki_filp->private_data);
if (!is_sync_kiocb(iocb))
@ -734,8 +718,9 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz
nfs_begin_data_update(inode);
rpc_clnt_sigmask(clnt, &oldset);
nfs_direct_write_schedule(dreq, sync);
result = nfs_direct_wait(dreq);
result = nfs_direct_write_schedule(dreq, user_addr, count, pos, sync);
if (!result)
result = nfs_direct_wait(dreq);
rpc_clnt_sigunmask(clnt, &oldset);
return result;
@ -765,8 +750,6 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz
ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
{
ssize_t retval = -EINVAL;
int page_count;
struct page **pages;
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
@ -788,14 +771,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count,
if (retval)
goto out;
retval = nfs_get_user_pages(READ, (unsigned long) buf,
count, &pages);
if (retval < 0)
goto out;
page_count = retval;
retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos,
pages, page_count);
retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos);
if (retval > 0)
iocb->ki_pos = pos + retval;
@ -831,8 +807,6 @@ out:
ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
{
ssize_t retval;
int page_count;
struct page **pages;
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
@ -860,14 +834,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t
if (retval)
goto out;
retval = nfs_get_user_pages(WRITE, (unsigned long) buf,
count, &pages);
if (retval < 0)
goto out;
page_count = retval;
retval = nfs_direct_write(iocb, (unsigned long) buf, count,
pos, pages, page_count);
retval = nfs_direct_write(iocb, (unsigned long) buf, count, pos);
/*
* XXX: nfs_end_data_update() already ensures this file's

View File

@ -3144,9 +3144,6 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl)
default:
BUG();
}
if (res < 0)
printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
__FUNCTION__);
return res;
}
@ -3258,8 +3255,6 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
return ERR_PTR(-ENOMEM);
}
/* Unlock _before_ we do the RPC call */
do_vfs_lock(fl->fl_file, fl);
return rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data);
}
@ -3270,30 +3265,28 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *
struct rpc_task *task;
int status = 0;
status = nfs4_set_lock_state(state, request);
/* Unlock _before_ we do the RPC call */
request->fl_flags |= FL_EXISTS;
if (do_vfs_lock(request->fl_file, request) == -ENOENT)
goto out;
if (status != 0)
goto out;
/* Is this a delegated lock? */
if (test_bit(NFS_DELEGATED_STATE, &state->flags))
goto out_unlock;
/* Is this open_owner holding any locks on the server? */
if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
goto out_unlock;
status = nfs4_set_lock_state(state, request);
if (status != 0)
goto out_unlock;
goto out;
lsp = request->fl_u.nfs4_fl.owner;
status = -ENOMEM;
seqid = nfs_alloc_seqid(&lsp->ls_seqid);
status = -ENOMEM;
if (seqid == NULL)
goto out_unlock;
goto out;
task = nfs4_do_unlck(request, request->fl_file->private_data, lsp, seqid);
status = PTR_ERR(task);
if (IS_ERR(task))
goto out_unlock;
goto out;
status = nfs4_wait_for_completion_rpc_task(task);
rpc_release_task(task);
return status;
out_unlock:
do_vfs_lock(request->fl_file, request);
out:
return status;
}
@ -3461,10 +3454,10 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
struct nfs4_exception exception = { };
int err;
/* Cache the lock if possible... */
if (test_bit(NFS_DELEGATED_STATE, &state->flags))
return 0;
do {
/* Cache the lock if possible... */
if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
return 0;
err = _nfs4_do_setlk(state, F_SETLK, request, 1);
if (err != -NFS4ERR_DELAY)
break;
@ -3483,6 +3476,8 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
if (err != 0)
return err;
do {
if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
return 0;
err = _nfs4_do_setlk(state, F_SETLK, request, 0);
if (err != -NFS4ERR_DELAY)
break;
@ -3494,29 +3489,42 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
struct nfs4_client *clp = state->owner->so_client;
unsigned char fl_flags = request->fl_flags;
int status;
/* Is this a delegated open? */
if (NFS_I(state->inode)->delegation_state != 0) {
/* Yes: cache locks! */
status = do_vfs_lock(request->fl_file, request);
/* ...but avoid races with delegation recall... */
if (status < 0 || test_bit(NFS_DELEGATED_STATE, &state->flags))
return status;
}
down_read(&clp->cl_sem);
status = nfs4_set_lock_state(state, request);
if (status != 0)
goto out;
request->fl_flags |= FL_ACCESS;
status = do_vfs_lock(request->fl_file, request);
if (status < 0)
goto out;
down_read(&clp->cl_sem);
if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
struct nfs_inode *nfsi = NFS_I(state->inode);
/* Yes: cache locks! */
down_read(&nfsi->rwsem);
/* ...but avoid races with delegation recall... */
if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
request->fl_flags = fl_flags & ~FL_SLEEP;
status = do_vfs_lock(request->fl_file, request);
up_read(&nfsi->rwsem);
goto out_unlock;
}
up_read(&nfsi->rwsem);
}
status = _nfs4_do_setlk(state, cmd, request, 0);
if (status != 0)
goto out;
goto out_unlock;
/* Note: we always want to sleep here! */
request->fl_flags |= FL_SLEEP;
request->fl_flags = fl_flags | FL_SLEEP;
if (do_vfs_lock(request->fl_file, request) < 0)
printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
out:
out_unlock:
up_read(&clp->cl_sem);
out:
request->fl_flags = fl_flags;
return status;
}

View File

@ -578,7 +578,7 @@ static int nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, un
return ret;
}
static void nfs_cancel_requests(struct list_head *head)
static void nfs_cancel_dirty_list(struct list_head *head)
{
struct nfs_page *req;
while(!list_empty(head)) {
@ -589,6 +589,19 @@ static void nfs_cancel_requests(struct list_head *head)
}
}
static void nfs_cancel_commit_list(struct list_head *head)
{
struct nfs_page *req;
while(!list_empty(head)) {
req = nfs_list_entry(head->next);
nfs_list_remove_request(req);
nfs_inode_remove_request(req);
nfs_clear_page_writeback(req);
dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
}
}
/*
* nfs_scan_dirty - Scan an inode for dirty requests
* @inode: NFS inode to scan
@ -1381,6 +1394,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
nfs_list_remove_request(req);
nfs_mark_request_commit(req);
nfs_clear_page_writeback(req);
dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
}
return -ENOMEM;
}
@ -1499,7 +1513,7 @@ int nfs_sync_inode_wait(struct inode *inode, unsigned long idx_start,
if (pages != 0) {
spin_unlock(&nfsi->req_lock);
if (how & FLUSH_INVALIDATE)
nfs_cancel_requests(&head);
nfs_cancel_dirty_list(&head);
else
ret = nfs_flush_list(inode, &head, pages, how);
spin_lock(&nfsi->req_lock);
@ -1512,7 +1526,7 @@ int nfs_sync_inode_wait(struct inode *inode, unsigned long idx_start,
break;
if (how & FLUSH_INVALIDATE) {
spin_unlock(&nfsi->req_lock);
nfs_cancel_requests(&head);
nfs_cancel_commit_list(&head);
spin_lock(&nfsi->req_lock);
continue;
}

View File

@ -39,12 +39,4 @@
*/
#define NR_IRQS (NR_AIC_IRQS + (4 * 32))
#ifndef __ASSEMBLY__
/*
* Initialize the IRQ controller.
*/
extern void at91rm9200_init_irq(unsigned int priority[]);
#endif
#endif

View File

@ -43,6 +43,7 @@ typedef u64 cputime64_t;
#define cputime64_zero ((cputime64_t)0)
#define cputime64_add(__a, __b) ((__a) + (__b))
#define cputime64_sub(__a, __b) ((__a) - (__b))
#define cputime_to_cputime64(__ct) (__ct)
#ifdef __KERNEL__
@ -74,6 +75,23 @@ static inline cputime_t jiffies_to_cputime(const unsigned long jif)
return ct;
}
static inline cputime64_t jiffies64_to_cputime64(const u64 jif)
{
cputime_t ct;
u64 sec;
/* have to be a little careful about overflow */
ct = jif % HZ;
sec = jif / HZ;
if (ct) {
ct *= tb_ticks_per_sec;
do_div(ct, HZ);
}
if (sec)
ct += (cputime_t) sec * tb_ticks_per_sec;
return ct;
}
static inline u64 cputime64_to_jiffies64(const cputime_t ct)
{
return mulhdu(ct, __cputime_jiffies_factor);

View File

@ -160,6 +160,20 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
BUG();
}
static inline void
dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
enum dma_data_direction direction)
{
BUG();
}
static inline void
dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
enum dma_data_direction direction)
{
BUG();
}
#endif /* PCI */

View File

@ -716,6 +716,7 @@ extern spinlock_t files_lock;
#define FL_POSIX 1
#define FL_FLOCK 2
#define FL_ACCESS 8 /* not trying to lock, just looking */
#define FL_EXISTS 16 /* when unlocking, test for existence */
#define FL_LEASE 32 /* lease held on this file */
#define FL_CLOSE 64 /* unlock on close */
#define FL_SLEEP 128 /* A blocking lock */

View File

@ -131,6 +131,7 @@ enum {
ATA_DFLAG_CFG_MASK = (1 << 8) - 1,
ATA_DFLAG_PIO = (1 << 8), /* device currently in PIO mode */
ATA_DFLAG_SUSPENDED = (1 << 9), /* device suspended */
ATA_DFLAG_INIT_MASK = (1 << 16) - 1,
ATA_DFLAG_DETACH = (1 << 16),
@ -160,22 +161,28 @@ enum {
ATA_FLAG_HRST_TO_RESUME = (1 << 11), /* hardreset to resume phy */
ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H
* Register FIS clearing BSY */
ATA_FLAG_DEBUGMSG = (1 << 13),
ATA_FLAG_FLUSH_PORT_TASK = (1 << 14), /* flush port task */
ATA_FLAG_EH_PENDING = (1 << 15), /* EH pending */
ATA_FLAG_EH_IN_PROGRESS = (1 << 16), /* EH in progress */
ATA_FLAG_FROZEN = (1 << 17), /* port is frozen */
ATA_FLAG_RECOVERED = (1 << 18), /* recovery action performed */
ATA_FLAG_LOADING = (1 << 19), /* boot/loading probe */
ATA_FLAG_UNLOADING = (1 << 20), /* module is unloading */
ATA_FLAG_SCSI_HOTPLUG = (1 << 21), /* SCSI hotplug scheduled */
/* The following flag belongs to ap->pflags but is kept in
* ap->flags because it's referenced in many LLDs and will be
* removed in not-too-distant future.
*/
ATA_FLAG_DISABLED = (1 << 23), /* port is disabled, ignore it */
ATA_FLAG_DISABLED = (1 << 22), /* port is disabled, ignore it */
ATA_FLAG_SUSPENDED = (1 << 23), /* port is suspended (power) */
/* bits 24:31 of ap->flags are reserved for LLD specific flags */
/* bits 24:31 of ap->flags are reserved for LLDD specific flags */
/* struct ata_port pflags */
ATA_PFLAG_EH_PENDING = (1 << 0), /* EH pending */
ATA_PFLAG_EH_IN_PROGRESS = (1 << 1), /* EH in progress */
ATA_PFLAG_FROZEN = (1 << 2), /* port is frozen */
ATA_PFLAG_RECOVERED = (1 << 3), /* recovery action performed */
ATA_PFLAG_LOADING = (1 << 4), /* boot/loading probe */
ATA_PFLAG_UNLOADING = (1 << 5), /* module is unloading */
ATA_PFLAG_SCSI_HOTPLUG = (1 << 6), /* SCSI hotplug scheduled */
ATA_PFLAG_FLUSH_PORT_TASK = (1 << 16), /* flush port task */
ATA_PFLAG_SUSPENDED = (1 << 17), /* port is suspended (power) */
ATA_PFLAG_PM_PENDING = (1 << 18), /* PM operation pending */
/* struct ata_queued_cmd flags */
ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */
@ -248,12 +255,19 @@ enum {
ATA_EH_REVALIDATE = (1 << 0),
ATA_EH_SOFTRESET = (1 << 1),
ATA_EH_HARDRESET = (1 << 2),
ATA_EH_SUSPEND = (1 << 3),
ATA_EH_RESUME = (1 << 4),
ATA_EH_PM_FREEZE = (1 << 5),
ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE,
ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_SUSPEND |
ATA_EH_RESUME | ATA_EH_PM_FREEZE,
/* ata_eh_info->flags */
ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */
ATA_EHI_RESUME_LINK = (1 << 1), /* need to resume link */
ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */
ATA_EHI_QUIET = (1 << 3), /* be quiet */
ATA_EHI_DID_RESET = (1 << 16), /* already reset this port */
@ -486,6 +500,7 @@ struct ata_port {
const struct ata_port_operations *ops;
spinlock_t *lock;
unsigned long flags; /* ATA_FLAG_xxx */
unsigned int pflags; /* ATA_PFLAG_xxx */
unsigned int id; /* unique id req'd by scsi midlyr */
unsigned int port_no; /* unique port #; from zero */
unsigned int hard_port_no; /* hardware port #; from zero */
@ -535,6 +550,9 @@ struct ata_port {
struct list_head eh_done_q;
wait_queue_head_t eh_wait_q;
pm_message_t pm_mesg;
int *pm_result;
void *private_data;
u8 sector_buf[ATA_SECT_SIZE]; /* owned by EH */
@ -589,6 +607,9 @@ struct ata_port_operations {
void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
u32 val);
int (*port_suspend) (struct ata_port *ap, pm_message_t mesg);
int (*port_resume) (struct ata_port *ap);
int (*port_start) (struct ata_port *ap);
void (*port_stop) (struct ata_port *ap);
@ -622,9 +643,18 @@ struct ata_timing {
#define FIT(v,vmin,vmax) max_t(short,min_t(short,v,vmax),vmin)
extern const unsigned long sata_deb_timing_boot[];
extern const unsigned long sata_deb_timing_eh[];
extern const unsigned long sata_deb_timing_before_fsrst[];
extern const unsigned long sata_deb_timing_normal[];
extern const unsigned long sata_deb_timing_hotplug[];
extern const unsigned long sata_deb_timing_long[];
static inline const unsigned long *
sata_ehc_deb_timing(struct ata_eh_context *ehc)
{
if (ehc->i.flags & ATA_EHI_HOTPLUGGED)
return sata_deb_timing_hotplug;
else
return sata_deb_timing_normal;
}
extern void ata_port_probe(struct ata_port *);
extern void __sata_phy_reset(struct ata_port *ap);
@ -644,6 +674,8 @@ extern void ata_std_ports(struct ata_ioports *ioaddr);
extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
unsigned int n_ports);
extern void ata_pci_remove_one (struct pci_dev *pdev);
extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t state);
extern void ata_pci_device_do_resume(struct pci_dev *pdev);
extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state);
extern int ata_pci_device_resume(struct pci_dev *pdev);
extern int ata_pci_clear_simplex(struct pci_dev *pdev);
@ -664,8 +696,9 @@ extern int ata_port_online(struct ata_port *ap);
extern int ata_port_offline(struct ata_port *ap);
extern int ata_scsi_device_resume(struct scsi_device *);
extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state);
extern int ata_device_resume(struct ata_device *);
extern int ata_device_suspend(struct ata_device *, pm_message_t state);
extern int ata_host_set_suspend(struct ata_host_set *host_set,
pm_message_t mesg);
extern void ata_host_set_resume(struct ata_host_set *host_set);
extern int ata_ratelimit(void);
extern unsigned int ata_busy_sleep(struct ata_port *ap,
unsigned long timeout_pat,
@ -825,19 +858,24 @@ extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
(ehi)->desc_len = 0; \
} while (0)
static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi)
static inline void __ata_ehi_hotplugged(struct ata_eh_info *ehi)
{
if (ehi->flags & ATA_EHI_HOTPLUGGED)
return;
ehi->flags |= ATA_EHI_HOTPLUGGED;
ehi->flags |= ATA_EHI_HOTPLUGGED | ATA_EHI_RESUME_LINK;
ehi->hotplug_timestamp = jiffies;
ehi->err_mask |= AC_ERR_ATA_BUS;
ehi->action |= ATA_EH_SOFTRESET;
ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
}
static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi)
{
__ata_ehi_hotplugged(ehi);
ehi->err_mask |= AC_ERR_ATA_BUS;
}
/*
* qc helpers
*/
@ -921,6 +959,11 @@ static inline unsigned int ata_dev_absent(const struct ata_device *dev)
return ata_class_absent(dev->class);
}
static inline unsigned int ata_dev_ready(const struct ata_device *dev)
{
return ata_dev_enabled(dev) && !(dev->flags & ATA_DFLAG_SUSPENDED);
}
/*
* port helpers
*/

View File

@ -729,6 +729,7 @@ struct nfs_read_data {
struct list_head pages; /* Coalesced read requests */
struct nfs_page *req; /* multi ops per nfs_page */
struct page **pagevec;
unsigned int npages; /* active pages in pagevec */
struct nfs_readargs args;
struct nfs_readres res;
#ifdef CONFIG_NFS_V4
@ -747,6 +748,7 @@ struct nfs_write_data {
struct list_head pages; /* Coalesced requests we wish to flush */
struct nfs_page *req; /* multi ops per nfs_page */
struct page **pagevec;
unsigned int npages; /* active pages in pagevec */
struct nfs_writeargs args; /* argument struct */
struct nfs_writeres res; /* result struct */
#ifdef CONFIG_NFS_V4

View File

@ -2019,6 +2019,13 @@
#define PCI_VENDOR_ID_TDI 0x192E
#define PCI_DEVICE_ID_TDI_EHCI 0x0101
#define PCI_VENDOR_ID_JMICRON 0x197B
#define PCI_DEVICE_ID_JMICRON_JMB360 0x2360
#define PCI_DEVICE_ID_JMICRON_JMB361 0x2361
#define PCI_DEVICE_ID_JMICRON_JMB363 0x2363
#define PCI_DEVICE_ID_JMICRON_JMB365 0x2365
#define PCI_DEVICE_ID_JMICRON_JMB366 0x2366
#define PCI_DEVICE_ID_JMICRON_JMB368 0x2368
#define PCI_VENDOR_ID_TEKRAM 0x1de1
#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29

View File

@ -104,6 +104,7 @@ struct ieee80211softmac_assoc_info {
*/
u8 static_essid:1,
associating:1,
assoc_wait:1,
bssvalid:1,
bssfixed:1;

View File

@ -368,6 +368,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
/* Put this code here so that we avoid duplicating it in all
* Rx paths. - Jean II */
#ifdef CONFIG_WIRELESS_EXT
#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
/* If spy monitoring on */
if (ieee->spy_data.spy_number > 0) {
@ -396,15 +397,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
}
#endif /* IW_WIRELESS_SPY */
#endif /* CONFIG_WIRELESS_EXT */
#ifdef NOT_YET
hostap_update_rx_stats(local->ap, hdr, rx_stats);
#endif
if (ieee->iw_mode == IW_MODE_MONITOR) {
ieee80211_monitor_rx(ieee, skb, rx_stats);
stats->rx_packets++;
stats->rx_bytes += skb->len;
ieee80211_monitor_rx(ieee, skb, rx_stats);
return 1;
}

View File

@ -562,10 +562,13 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
struct net_device_stats *stats = &ieee->stats;
struct sk_buff *skb_frag;
int priority = -1;
int fraglen = total_len;
int headroom = ieee->tx_headroom;
struct ieee80211_crypt_data *crypt = ieee->crypt[ieee->tx_keyidx];
spin_lock_irqsave(&ieee->lock, flags);
if (encrypt_mpdu && !ieee->sec.encrypt)
if (encrypt_mpdu && (!ieee->sec.encrypt || !crypt))
encrypt_mpdu = 0;
/* If there is no driver handler to take the TXB, dont' bother
@ -581,20 +584,24 @@ int ieee80211_tx_frame(struct ieee80211_device *ieee,
goto success;
}
if (encrypt_mpdu)
if (encrypt_mpdu) {
frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
fraglen += crypt->ops->extra_mpdu_prefix_len +
crypt->ops->extra_mpdu_postfix_len;
headroom += crypt->ops->extra_mpdu_prefix_len;
}
/* When we allocate the TXB we allocate enough space for the reserve
* and full fragment bytes (bytes_per_frag doesn't include prefix,
* postfix, header, FCS, etc.) */
txb = ieee80211_alloc_txb(1, total_len, ieee->tx_headroom, GFP_ATOMIC);
txb = ieee80211_alloc_txb(1, fraglen, headroom, GFP_ATOMIC);
if (unlikely(!txb)) {
printk(KERN_WARNING "%s: Could not allocate TXB\n",
ieee->dev->name);
goto failed;
}
txb->encrypted = 0;
txb->payload_size = total_len;
txb->payload_size = fraglen;
skb_frag = txb->fragments[0];

View File

@ -47,9 +47,7 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft
dprintk(KERN_INFO PFX "sent association request!\n");
/* Change the state to associating */
spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.associating = 1;
mac->associated = 0; /* just to make sure */
/* Set a timer for timeout */
@ -63,6 +61,7 @@ void
ieee80211softmac_assoc_timeout(void *d)
{
struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
struct ieee80211softmac_network *n;
unsigned long flags;
spin_lock_irqsave(&mac->lock, flags);
@ -75,11 +74,12 @@ ieee80211softmac_assoc_timeout(void *d)
mac->associnfo.associating = 0;
mac->associnfo.bssvalid = 0;
mac->associated = 0;
n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid);
spin_unlock_irqrestore(&mac->lock, flags);
dprintk(KERN_INFO PFX "assoc request timed out!\n");
/* FIXME: we need to know the network here. that requires a bit of restructuring */
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL);
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n);
}
void
@ -203,6 +203,10 @@ ieee80211softmac_assoc_work(void *d)
if (mac->associated)
ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.associating = 1;
spin_unlock_irqrestore(&mac->lock, flags);
/* try to find the requested network in our list, if we found one already */
if (bssvalid || mac->associnfo.bssfixed)
found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
@ -295,19 +299,32 @@ ieee80211softmac_assoc_work(void *d)
memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1);
/* we found a network! authenticate (if necessary) and associate to it. */
if (!found->authenticated) {
if (found->authenticating) {
dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n");
if(!mac->associnfo.assoc_wait) {
mac->associnfo.assoc_wait = 1;
ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
}
return;
}
if (!found->authenticated && !found->authenticating) {
/* This relies on the fact that _auth_req only queues the work,
* otherwise adding the notification would be racy. */
if (!ieee80211softmac_auth_req(mac, found)) {
dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n");
ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
if(!mac->associnfo.assoc_wait) {
dprintk(KERN_INFO PFX "Cannot associate without being authenticated, requested authentication\n");
mac->associnfo.assoc_wait = 1;
ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
}
} else {
printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
mac->associnfo.assoc_wait = 0;
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
}
return;
}
/* finally! now we can start associating */
mac->associnfo.assoc_wait = 0;
ieee80211softmac_assoc(mac, found);
}

View File

@ -36,8 +36,9 @@ ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
struct ieee80211softmac_auth_queue_item *auth;
unsigned long flags;
if (net->authenticating)
if (net->authenticating || net->authenticated)
return 0;
net->authenticating = 1;
/* Add the network if it's not already added */
ieee80211softmac_add_network(mac, net);
@ -92,7 +93,6 @@ ieee80211softmac_auth_queue(void *data)
return;
}
net->authenticated = 0;
net->authenticating = 1;
/* add a timeout call so we eventually give up waiting for an auth reply */
schedule_delayed_work(&auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT);
auth->retry--;

View File

@ -229,6 +229,9 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
return 0;
ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
/* Fill in the capabilities */
(*pkt)->capability = ieee80211softmac_capabilities(mac, net);
/* Fill in Listen Interval (?) */
(*pkt)->listen_interval = cpu_to_le16(10);

Some files were not shown because too many files have changed in this diff Show More