When sending patches to Linus, always follow step #7.
Large changes are not appropriate for mailing lists, and some
-maintainers. If your patch, uncompressed, exceeds 40 kB in size,
+maintainers. If your patch, uncompressed, exceeds 300 kB in size,
it is preferred that you store your patch on an Internet-accessible
server, and provide instead a URL (link) pointing to your patch.
to use for allocation size and alignment. For RAID5/6
systems this should be the number of data
disks * RAID chunk size in file system blocks.
-delalloc (*) Deferring block allocation until write-out time.
-nodelalloc Disable delayed allocation. Blocks are allocation
- when data is copied from user to page cache.
+
+delalloc (*) Defer block allocation until just before ext4
+ writes out the block(s) in question. This
+ allows ext4 to better allocation decisions
+ more efficiently.
+nodelalloc Disable delayed allocation. Blocks are allocated
+ when the data is copied from userspace to the
+ page cache, either via the write(2) system call
+ or when an mmap'ed page which was previously
+ unallocated is written for the first time.
max_batch_time=usec Maximum amount of time ext4 should wait for
additional filesystem operations to be batch
..............................................................................
File Content
mb_groups details of multiblock allocator buddy cache of free blocks
- mb_history multiblock allocation history
..............................................................................
winnt: emulate the Windows NT rule for display/create.
mixed: emulate the Windows NT rule for display,
emulate the Windows 95 rule for create.
- Default setting is `lower'.
+ Default setting is `mixed'.
tz=UTC -- Interpret timestamps as UTC rather than local time.
This option disables the conversion of timestamps
S: Maintained
ARM/PALMTX,PALMT5,PALMLD,PALMTE2,PALMTC SUPPORT
-P: Marek Vasut
-M: marek.vasut@gmail.com
+M: Marek Vasut <marek.vasut@gmail.com>
L: linux-arm-kernel@lists.infradead.org
W: http://hackndev.com
S: Maintained
+F: arch/arm/mach-pxa/include/mach/palmtx.h
+F: arch/arm/mach-pxa/palmtx.c
+F: arch/arm/mach-pxa/include/mach/palmt5.h
+F: arch/arm/mach-pxa/palmt5.c
+F: arch/arm/mach-pxa/include/mach/palmld.h
+F: arch/arm/mach-pxa/palmld.c
+F: arch/arm/mach-pxa/include/mach/palmte2.h
+F: arch/arm/mach-pxa/palmte2.c
+F: arch/arm/mach-pxa/include/mach/palmtc.h
+F: arch/arm/mach-pxa/palmtc.c
ARM/PALM TREO 680 SUPPORT
M: Tomas Cech <sleep_walker@suse.cz>
L: linux-arm-kernel@lists.infradead.org
W: http://hackndev.com
S: Maintained
+F: arch/arm/mach-pxa/include/mach/treo680.h
+F: arch/arm/mach-pxa/treo680.c
ARM/PALMZ72 SUPPORT
M: Sergey Lapin <slapin@ossfans.org>
L: linux-arm-kernel@lists.infradead.org
W: http://hackndev.com
S: Maintained
+F: arch/arm/mach-pxa/include/mach/palmz72.h
+F: arch/arm/mach-pxa/palmz72.c
ARM/PLEB SUPPORT
M: Peter Chubb <pleb@gelato.unsw.edu.au>
return single_open(file, clk_debugfs_show, NULL);
}
-static struct file_operations clk_debugfs_operations = {
+static const struct file_operations clk_debugfs_operations = {
.open = clk_debugfs_open,
.read = seq_read,
.llseek = seq_lseek,
{ .jtag_id = 0xb574, .die_rev = 0x2, .omap_id = 0x03310315, .type = 0x03100000},
{ .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100},
{ .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300},
- { .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320500, .type = 0x08500000},
+ { .jtag_id = 0xb62c, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x08500000},
{ .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000},
{ .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000},
{ .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000},
#define TWL4030_MSECURE_GPIO 22
-static int sdp3430_keymap[] = {
+static int board_keymap[] = {
KEY(0, 0, KEY_LEFT),
KEY(0, 1, KEY_RIGHT),
KEY(0, 2, KEY_A),
0
};
+static struct matrix_keymap_data board_map_data = {
+ .keymap = board_keymap,
+ .keymap_size = ARRAY_SIZE(board_keymap),
+};
+
static struct twl4030_keypad_data sdp3430_kp_data = {
+ .keymap_data = &board_map_data,
.rows = 5,
.cols = 6,
- .keymap = sdp3430_keymap,
- .keymapsize = ARRAY_SIZE(sdp3430_keymap),
.rep = 1,
};
},
};
-static int ldp_twl4030_keymap[] = {
+static int board_keymap[] = {
KEY(0, 0, KEY_1),
KEY(1, 0, KEY_2),
KEY(2, 0, KEY_3),
0
};
+static struct matrix_keymap_data board_map_data = {
+ .keymap = board_keymap,
+ .keymap_size = ARRAY_SIZE(board_keymap),
+};
+
static struct twl4030_keypad_data ldp_kp_twl4030_data = {
+ .keymap_data = &board_map_data,
.rows = 6,
.cols = 6,
- .keymap = ldp_twl4030_keymap,
- .keymapsize = ARRAY_SIZE(ldp_twl4030_keymap),
.rep = 1,
};
static int beagle_twl_gpio_setup(struct device *dev,
unsigned gpio, unsigned ngpio)
{
+ if (system_rev >= 0x20 && system_rev <= 0x34301000) {
+ omap_cfg_reg(AG9_34XX_GPIO23);
+ mmc[0].gpio_wp = 23;
+ } else {
+ omap_cfg_reg(AH8_34XX_GPIO29);
+ }
/* gpio + 0 is "mmc0_cd" (input/IRQ) */
- omap_cfg_reg(AH8_34XX_GPIO29);
mmc[0].gpio_cd = gpio + 0;
twl4030_mmc_init(mmc);
.usb_mode = T2_USB_MODE_ULPI,
};
-static int omap3evm_keymap[] = {
+static int board_keymap[] = {
KEY(0, 0, KEY_LEFT),
KEY(0, 1, KEY_RIGHT),
KEY(0, 2, KEY_A),
KEY(3, 3, KEY_P)
};
+static struct matrix_keymap_data board_map_data = {
+ .keymap = board_keymap,
+ .keymap_size = ARRAY_SIZE(board_keymap),
+};
+
static struct twl4030_keypad_data omap3evm_kp_data = {
+ .keymap_data = &board_map_data,
.rows = 4,
.cols = 4,
- .keymap = omap3evm_keymap,
- .keymapsize = ARRAY_SIZE(omap3evm_keymap),
.rep = 1,
};
omap_set_gpio_debounce_time(32 * 5, GPIO_DEBOUNCE_TIME);
}
-static int pandora_keypad_map[] = {
+static int board_keymap[] = {
/* col, row, code */
KEY(0, 0, KEY_9),
KEY(0, 1, KEY_0),
KEY(5, 2, KEY_FN),
};
+static struct matrix_keymap_data board_map_data = {
+ .keymap = board_keymap,
+ .keymap_size = ARRAY_SIZE(board_keymap),
+};
+
static struct twl4030_keypad_data pandora_kp_data = {
+ .keymap_data = &board_map_data,
.rows = 8,
.cols = 6,
- .keymap = pandora_keypad_map,
- .keymapsize = ARRAY_SIZE(pandora_keypad_map),
.rep = 1,
};
#define SYSTEM_REV_B_USES_VAUX3 0x1699
#define SYSTEM_REV_S_USES_VAUX3 0x8
-static int rx51_keymap[] = {
+static int board_keymap[] = {
KEY(0, 0, KEY_Q),
KEY(0, 1, KEY_W),
KEY(0, 2, KEY_E),
KEY(0xff, 5, KEY_F10),
};
+static struct matrix_keymap_data board_map_data = {
+ .keymap = board_keymap,
+ .keymap_size = ARRAY_SIZE(board_keymap),
+};
+
static struct twl4030_keypad_data rx51_kp_data = {
+ .keymap_data = &board_map_data,
.rows = 8,
.cols = 8,
- .keymap = rx51_keymap,
- .keymapsize = ARRAY_SIZE(rx51_keymap),
.rep = 1,
};
#include "mmc-twl4030.h"
/* Zoom2 has Qwerty keyboard*/
-static int zoom2_twl4030_keymap[] = {
+static int board_keymap[] = {
KEY(0, 0, KEY_E),
KEY(1, 0, KEY_R),
KEY(2, 0, KEY_T),
0
};
+static struct matrix_keymap_data board_map_data = {
+ .keymap = board_keymap,
+ .keymap_size = ARRAY_SIZE(board_keymap),
+};
+
static struct twl4030_keypad_data zoom2_kp_twl4030_data = {
+ .keymap_data = &board_map_data,
.rows = 8,
.cols = 8,
- .keymap = zoom2_twl4030_keymap,
- .keymapsize = ARRAY_SIZE(zoom2_twl4030_keymap),
.rep = 1,
};
#include <asm/atomic.h>
#include "cm.h"
-#include "cm-regbits-4xxx.h"
/* XXX move this to cm.h */
/* MAX_MODULE_READY_TIME: max milliseconds for module to leave idle */
*/
int omap4_cm_wait_idlest_ready(u32 prcm_mod, u8 prcm_dev_offs)
{
- int i = 0;
- u8 cm_id;
- u16 prcm_mod_offs;
- u32 mask = OMAP4_PRCM_CM_CLKCTRL_IDLEST_MASK;
-
- cm_id = prcm_mod >> OMAP4_PRCM_MOD_CM_ID_SHIFT;
- prcm_mod_offs = prcm_mod & OMAP4_PRCM_MOD_OFFS_MASK;
-
- while (((omap4_cm_read_mod_reg(cm_id, prcm_mod_offs, prcm_dev_offs,
- OMAP4_CM_CLKCTRL_DREG) & mask) != 0) &&
- (i++ < MAX_MODULE_READY_TIME))
- udelay(1);
-
- return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
+ /* FIXME: Add clock manager related code */
+ return 0;
}
};
#endif
-static void omap_init_mcspi(void)
+#ifdef CONFIG_ARCH_OMAP4
+static inline void omap4_mcspi_fixup(void)
{
- if (cpu_is_omap44xx()) {
- omap2_mcspi1_resources[0].start = OMAP4_MCSPI1_BASE;
- omap2_mcspi1_resources[0].end = OMAP4_MCSPI1_BASE + 0xff;
- omap2_mcspi2_resources[0].start = OMAP4_MCSPI2_BASE;
- omap2_mcspi2_resources[0].end = OMAP4_MCSPI2_BASE + 0xff;
- omap2_mcspi3_resources[0].start = OMAP4_MCSPI3_BASE;
- omap2_mcspi3_resources[0].end = OMAP4_MCSPI3_BASE + 0xff;
- omap2_mcspi4_resources[0].start = OMAP4_MCSPI4_BASE;
- omap2_mcspi4_resources[0].end = OMAP4_MCSPI4_BASE + 0xff;
- }
- platform_device_register(&omap2_mcspi1);
- platform_device_register(&omap2_mcspi2);
+ omap2_mcspi1_resources[0].start = OMAP4_MCSPI1_BASE;
+ omap2_mcspi1_resources[0].end = OMAP4_MCSPI1_BASE + 0xff;
+ omap2_mcspi2_resources[0].start = OMAP4_MCSPI2_BASE;
+ omap2_mcspi2_resources[0].end = OMAP4_MCSPI2_BASE + 0xff;
+ omap2_mcspi3_resources[0].start = OMAP4_MCSPI3_BASE;
+ omap2_mcspi3_resources[0].end = OMAP4_MCSPI3_BASE + 0xff;
+ omap2_mcspi4_resources[0].start = OMAP4_MCSPI4_BASE;
+ omap2_mcspi4_resources[0].end = OMAP4_MCSPI4_BASE + 0xff;
+}
+#else
+static inline void omap4_mcspi_fixup(void)
+{
+}
+#endif
+
#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
defined(CONFIG_ARCH_OMAP4)
- if (cpu_is_omap2430() || cpu_is_omap343x() || cpu_is_omap44xx())
- platform_device_register(&omap2_mcspi3);
+static inline void omap2_mcspi3_init(void)
+{
+ platform_device_register(&omap2_mcspi3);
+}
+#else
+static inline void omap2_mcspi3_init(void)
+{
+}
#endif
+
#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
- if (cpu_is_omap343x() || cpu_is_omap44xx())
- platform_device_register(&omap2_mcspi4);
+static inline void omap2_mcspi4_init(void)
+{
+ platform_device_register(&omap2_mcspi4);
+}
+#else
+static inline void omap2_mcspi4_init(void)
+{
+}
#endif
+
+static void omap_init_mcspi(void)
+{
+ if (cpu_is_omap44xx())
+ omap4_mcspi_fixup();
+
+ platform_device_register(&omap2_mcspi1);
+ platform_device_register(&omap2_mcspi2);
+
+ if (cpu_is_omap2430() || cpu_is_omap343x() || cpu_is_omap44xx())
+ omap2_mcspi3_init();
+
+ if (cpu_is_omap343x() || cpu_is_omap44xx())
+ omap2_mcspi4_init();
}
#else
else if (cpu_is_omap34xx())
hwmods = omap34xx_hwmods;
- omap_hwmod_init(hwmods);
- omap2_mux_init();
#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once the clkdev is ready */
/* The OPP tables have to be registered before a clk init */
+ omap_hwmod_init(hwmods);
+ omap2_mux_init();
omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps);
pwrdm_init(powerdomains_omap);
clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
l = iommu_read_reg(obj, MMU_SYSSTATUS);
if (l & MMU_SYS_RESETDONE)
break;
- } while (time_after(jiffies, timeout));
+ } while (!time_after(jiffies, timeout));
if (!(l & MMU_SYS_RESETDONE)) {
dev_err(obj->dev, "can't take mmu out of reset\n");
#define MAILBOX_IRQ_NEWMSG(u) (1 << (2 * (u)))
#define MAILBOX_IRQ_NOTFULL(u) (1 << (2 * (u) + 1))
+/* SYSCONFIG: register bit definition */
+#define AUTOIDLE (1 << 0)
+#define SOFTRESET (1 << 1)
+#define SMARTIDLE (2 << 3)
+
+/* SYSSTATUS: register bit definition */
+#define RESETDONE (1 << 0)
+
#define MBOX_REG_SIZE 0x120
#define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32))
/* Mailbox H/W preparations */
static int omap2_mbox_startup(struct omap_mbox *mbox)
{
- unsigned int l;
+ u32 l;
+ unsigned long timeout;
mbox_ick_handle = clk_get(NULL, "mailboxes_ick");
if (IS_ERR(mbox_ick_handle)) {
- printk("Could not get mailboxes_ick\n");
+ pr_err("Can't get mailboxes_ick\n");
return -ENODEV;
}
clk_enable(mbox_ick_handle);
+ mbox_write_reg(SOFTRESET, MAILBOX_SYSCONFIG);
+ timeout = jiffies + msecs_to_jiffies(20);
+ do {
+ l = mbox_read_reg(MAILBOX_SYSSTATUS);
+ if (l & RESETDONE)
+ break;
+ } while (!time_after(jiffies, timeout));
+
+ if (!(l & RESETDONE)) {
+ pr_err("Can't take mmu out of reset\n");
+ return -ENODEV;
+ }
+
l = mbox_read_reg(MAILBOX_REVISION);
pr_info("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
- /* set smart-idle & autoidle */
- l = mbox_read_reg(MAILBOX_SYSCONFIG);
- l |= 0x00000011;
+ l = SMARTIDLE | AUTOIDLE;
mbox_write_reg(l, MAILBOX_SYSCONFIG);
omap2_mbox_enable_irq(mbox, IRQ_RX);
u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
mbox_write_reg(bit, p->irqstatus);
+
+ /* Flush posted write for irq status to avoid spurious interrupts */
+ mbox_read_reg(p->irqstatus);
}
static int omap2_mbox_is_irq(struct omap_mbox *mbox,
OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
MUX_CFG_34XX("AF22_34XX_GPIO9", 0xa18,
OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
+MUX_CFG_34XX("AG9_34XX_GPIO23", 0x5ee,
+ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
MUX_CFG_34XX("AH8_34XX_GPIO29", 0x5fa,
OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
MUX_CFG_34XX("U8_34XX_GPIO54_OUT", 0x0b4,
OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("AG4_34XX_GPIO134_OUT", 0x160,
OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("AF4_34XX_GPIO135_OUT", 0x162,
+ OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("AE4_34XX_GPIO136_OUT", 0x164,
OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
MUX_CFG_34XX("AF6_34XX_GPIO140_UP", 0x16c,
.uartclk = OMAP24XX_BASE_BAUD * 16,
}, {
#ifdef CONFIG_ARCH_OMAP4
- .membase = IO_ADDRESS(OMAP_UART4_BASE),
+ .membase = OMAP2_IO_ADDRESS(OMAP_UART4_BASE),
.mapbase = OMAP_UART4_BASE,
.irq = 70,
.flags = UPF_BOOT_AUTOCONF,
#ifdef CONFIG_ARCH_OMAP4
static struct plat_serial8250_port serial_platform_data3[] = {
{
- .membase = IO_ADDRESS(OMAP_UART4_BASE),
+ .membase = OMAP2_IO_ADDRESS(OMAP_UART4_BASE),
.mapbase = OMAP_UART4_BASE,
.irq = 70,
.flags = UPF_BOOT_AUTOCONF,
{
.pdev = {
.name = "serial8250",
- .id = 3
+ .id = 3,
.dev = {
.platform_data = serial_platform_data3,
},
#ifdef CONFIG_ARCH_OMAP850
static struct gpio_bank gpio_bank_850[7] = {
- { OMAP1_MPUIO_BASE, INT_850_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO },
+ { OMAP1_MPUIO_VBASE, INT_850_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO },
{ OMAP850_GPIO1_BASE, INT_850_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_850 },
{ OMAP850_GPIO2_BASE, INT_850_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_850 },
{ OMAP850_GPIO3_BASE, INT_850_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_850 },
#ifndef ASMARM_ARCH_KEYPAD_H
#define ASMARM_ARCH_KEYPAD_H
+#include <linux/input/matrix_keypad.h>
+
struct omap_kp_platform_data {
int rows;
int cols;
#define KEY_PERSISTENT 0x00800000
#define KEYNUM_MASK 0x00EFFFFF
-#define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val))
-#define PERSISTENT_KEY(col, row) (((col) << 28) | ((row) << 24) | \
- KEY_PERSISTENT)
#endif
*/
AF26_34XX_GPIO0,
AF22_34XX_GPIO9,
+ AG9_34XX_GPIO23,
AH8_34XX_GPIO29,
U8_34XX_GPIO54_OUT,
U8_34XX_GPIO54_DOWN,
L8_34XX_GPIO63,
G25_34XX_GPIO86_OUT,
AG4_34XX_GPIO134_OUT,
+ AF4_34XX_GPIO135_OUT,
AE4_34XX_GPIO136_OUT,
AF6_34XX_GPIO140_UP,
AE6_34XX_GPIO141,
va += bytes;
}
- flush_cache_vmap(new->addr, new->addr + total);
+ flush_cache_vmap((unsigned long)new->addr,
+ (unsigned long)(new->addr + total));
return new->addr;
err_out:
}
va_end = _va + PAGE_SIZE * i;
- flush_cache_vmap(_va, va_end);
+ flush_cache_vmap((unsigned long)_va, (unsigned long)va_end);
}
static inline void sgtable_drain_vmalloc(struct sg_table *sgt)
#define _ARCH_MCI_H
struct s3c24xx_mci_pdata {
+ unsigned int no_wprotect : 1;
+ unsigned int no_detect : 1;
unsigned int wprotect_invert : 1;
unsigned int detect_invert : 1; /* set => detect active high. */
+ unsigned int use_dma : 1;
unsigned int gpio_detect;
unsigned int gpio_wprotect;
return ret;
}
-static struct file_operations coreb_fops = {
+static const struct file_operations coreb_fops = {
.owner = THIS_MODULE,
.ioctl = coreb_ioctl,
};
#define NUMBER_OF_PORTS 2
-static struct file_operations sync_serial_fops = {
+static const struct file_operations sync_serial_fops = {
.owner = THIS_MODULE,
.write = sync_serial_write,
.read = sync_serial_read,
return 0;
}
-struct file_operations gpio_fops = {
+static const struct file_operations gpio_fops = {
.owner = THIS_MODULE,
.poll = gpio_poll,
.ioctl = gpio_ioctl,
bool
default y
-config HAVE_LEGACY_PER_CPU_AREA
- def_bool y
-
config HAVE_SETUP_PER_CPU_AREA
def_bool y
#ifdef CONFIG_VIRTUAL_MEM_MAP
# define LARGE_GAP 0x40000000 /* Use virtual mem map if hole is > than this */
- extern unsigned long vmalloc_end;
+ extern unsigned long VMALLOC_END;
extern struct page *vmem_map;
extern int find_largest_hole(u64 start, u64 end, void *arg);
extern int create_mem_map_page_table(u64 start, u64 end, void *arg);
#define VMALLOC_START (RGN_BASE(RGN_GATE) + 0x200000000UL)
#ifdef CONFIG_VIRTUAL_MEM_MAP
# define VMALLOC_END_INIT (RGN_BASE(RGN_GATE) + (1UL << (4*PAGE_SHIFT - 9)))
-# define VMALLOC_END vmalloc_end
- extern unsigned long vmalloc_end;
+extern unsigned long VMALLOC_END;
#else
#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_SPARSEMEM_VMEMMAP)
/* SPARSEMEM_VMEMMAP uses half of vmalloc... */
printk(KERN_ERR PREFIX
"Error parsing MADT - no LAPIC entries\n");
+#ifdef CONFIG_SMP
+ if (available_cpus == 0) {
+ printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n");
+ printk(KERN_INFO "CPU 0 (0x%04x)", hard_smp_processor_id());
+ smp_boot_data.cpu_phys_id[available_cpus] =
+ hard_smp_processor_id();
+ available_cpus = 1; /* We've got at least one of these, no? */
+ }
+ smp_boot_data.cpu_count = available_cpus;
+#endif
+ /* Make boot-up look pretty */
+ printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus,
+ total_cpus);
+
return 0;
}
-
-
int __init acpi_boot_init(void)
{
if (acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt))
printk(KERN_ERR PREFIX "Can't find FADT\n");
+#ifdef CONFIG_ACPI_NUMA
#ifdef CONFIG_SMP
- if (available_cpus == 0) {
- printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n");
- printk(KERN_INFO "CPU 0 (0x%04x)", hard_smp_processor_id());
- smp_boot_data.cpu_phys_id[available_cpus] =
- hard_smp_processor_id();
- available_cpus = 1; /* We've got at least one of these, no? */
- }
- smp_boot_data.cpu_count = available_cpus;
-
- smp_build_cpu_map();
-# ifdef CONFIG_ACPI_NUMA
if (srat_num_cpus == 0) {
int cpu, i = 1;
for (cpu = 0; cpu < smp_boot_data.cpu_count; cpu++)
node_cpuid[i++].phys_id =
smp_boot_data.cpu_phys_id[cpu];
}
-# endif
#endif
-#ifdef CONFIG_ACPI_NUMA
build_cpu_to_node_map();
#endif
- /* Make boot-up look pretty */
- printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus,
- total_cpus);
return 0;
}
early_acpi_boot_init();
# ifdef CONFIG_ACPI_NUMA
acpi_numa_init();
-#ifdef CONFIG_ACPI_HOTPLUG_CPU
+# ifdef CONFIG_ACPI_HOTPLUG_CPU
prefill_possible_map();
-#endif
+# endif
per_cpu_scan_finalize((cpus_weight(early_cpu_possible_map) == 0 ?
32 : cpus_weight(early_cpu_possible_map)),
additional_cpus > 0 ? additional_cpus : 0);
# endif
-#else
-# ifdef CONFIG_SMP
- smp_build_cpu_map(); /* happens, e.g., with the Ski simulator */
-# endif
#endif /* CONFIG_APCI_BOOT */
+#ifdef CONFIG_SMP
+ smp_build_cpu_map();
+#endif
find_memory();
/* process SAL system table: */
c->unimpl_pa_mask = ~((1L<<63) | ((1L << phys_addr_size) - 1));
}
-/*
- * In UP configuration, setup_per_cpu_areas() is defined in
- * include/linux/percpu.h
- */
-#ifdef CONFIG_SMP
-void __init
-setup_per_cpu_areas (void)
-{
- /* start_kernel() requires this... */
-}
-#endif
-
/*
* Do the following calculations:
*
}
#endif
+#ifdef CONFIG_SMP
+ . = ALIGN(PERCPU_PAGE_SIZE);
+ __cpu0_per_cpu = .;
+ . = . + PERCPU_PAGE_SIZE; /* cpu0 per-cpu space */
+#endif
+
. = ALIGN(PAGE_SIZE);
__init_end = .;
data : { } :data
.data : AT(ADDR(.data) - LOAD_OFFSET)
{
-#ifdef CONFIG_SMP
- . = ALIGN(PERCPU_PAGE_SIZE);
- __cpu0_per_cpu = .;
- . = . + PERCPU_PAGE_SIZE; /* cpu0 per-cpu space */
-#endif
INIT_TASK_DATA(PAGE_SIZE)
CACHELINE_ALIGNED_DATA(SMP_CACHE_BYTES)
READ_MOSTLY_DATA(SMP_CACHE_BYTES)
void * __cpuinit
per_cpu_init (void)
{
- int cpu;
- static int first_time=1;
+ static bool first_time = true;
+ void *cpu0_data = __cpu0_per_cpu;
+ unsigned int cpu;
+
+ if (!first_time)
+ goto skip;
+ first_time = false;
/*
- * get_free_pages() cannot be used before cpu_init() done. BSP
- * allocates "NR_CPUS" pages for all CPUs to avoid that AP calls
- * get_zeroed_page().
+ * get_free_pages() cannot be used before cpu_init() done.
+ * BSP allocates PERCPU_PAGE_SIZE bytes for all possible CPUs
+ * to avoid that AP calls get_zeroed_page().
*/
- if (first_time) {
- void *cpu0_data = __cpu0_per_cpu;
+ for_each_possible_cpu(cpu) {
+ void *src = cpu == 0 ? cpu0_data : __phys_per_cpu_start;
- first_time=0;
+ memcpy(cpu_data, src, __per_cpu_end - __per_cpu_start);
+ __per_cpu_offset[cpu] = (char *)cpu_data - __per_cpu_start;
+ per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
- __per_cpu_offset[0] = (char *) cpu0_data - __per_cpu_start;
- per_cpu(local_per_cpu_offset, 0) = __per_cpu_offset[0];
+ /*
+ * percpu area for cpu0 is moved from the __init area
+ * which is setup by head.S and used till this point.
+ * Update ar.k3. This move is ensures that percpu
+ * area for cpu0 is on the correct node and its
+ * virtual address isn't insanely far from other
+ * percpu areas which is important for congruent
+ * percpu allocator.
+ */
+ if (cpu == 0)
+ ia64_set_kr(IA64_KR_PER_CPU_DATA, __pa(cpu_data) -
+ (unsigned long)__per_cpu_start);
- for (cpu = 1; cpu < NR_CPUS; cpu++) {
- memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
- __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start;
- cpu_data += PERCPU_PAGE_SIZE;
- per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu];
- }
+ cpu_data += PERCPU_PAGE_SIZE;
}
+skip:
return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
}
static inline void
alloc_per_cpu_data(void)
{
- cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS-1,
+ cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * num_possible_cpus(),
PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
}
+
+/**
+ * setup_per_cpu_areas - setup percpu areas
+ *
+ * Arch code has already allocated and initialized percpu areas. All
+ * this function has to do is to teach the determined layout to the
+ * dynamic percpu allocator, which happens to be more complex than
+ * creating whole new ones using helpers.
+ */
+void __init
+setup_per_cpu_areas(void)
+{
+ struct pcpu_alloc_info *ai;
+ struct pcpu_group_info *gi;
+ unsigned int cpu;
+ ssize_t static_size, reserved_size, dyn_size;
+ int rc;
+
+ ai = pcpu_alloc_alloc_info(1, num_possible_cpus());
+ if (!ai)
+ panic("failed to allocate pcpu_alloc_info");
+ gi = &ai->groups[0];
+
+ /* units are assigned consecutively to possible cpus */
+ for_each_possible_cpu(cpu)
+ gi->cpu_map[gi->nr_units++] = cpu;
+
+ /* set parameters */
+ static_size = __per_cpu_end - __per_cpu_start;
+ reserved_size = PERCPU_MODULE_RESERVE;
+ dyn_size = PERCPU_PAGE_SIZE - static_size - reserved_size;
+ if (dyn_size < 0)
+ panic("percpu area overflow static=%zd reserved=%zd\n",
+ static_size, reserved_size);
+
+ ai->static_size = static_size;
+ ai->reserved_size = reserved_size;
+ ai->dyn_size = dyn_size;
+ ai->unit_size = PERCPU_PAGE_SIZE;
+ ai->atom_size = PAGE_SIZE;
+ ai->alloc_size = PERCPU_PAGE_SIZE;
+
+ rc = pcpu_setup_first_chunk(ai, __per_cpu_start + __per_cpu_offset[0]);
+ if (rc)
+ panic("failed to setup percpu area (err=%d)", rc);
+
+ pcpu_free_alloc_info(ai);
+}
#else
#define alloc_per_cpu_data() do { } while (0)
#endif /* CONFIG_SMP */
map_size = PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) *
sizeof(struct page));
- vmalloc_end -= map_size;
- vmem_map = (struct page *) vmalloc_end;
+ VMALLOC_END -= map_size;
+ vmem_map = (struct page *) VMALLOC_END;
efi_memmap_walk(create_mem_map_page_table, NULL);
/*
int cpu;
for_each_possible_early_cpu(cpu) {
- if (cpu == 0) {
- void *cpu0_data = __cpu0_per_cpu;
- __per_cpu_offset[cpu] = (char*)cpu0_data -
- __per_cpu_start;
- } else if (node == node_cpuid[cpu].nid) {
- memcpy(__va(cpu_data), __phys_per_cpu_start,
- __per_cpu_end - __per_cpu_start);
- __per_cpu_offset[cpu] = (char*)__va(cpu_data) -
- __per_cpu_start;
- cpu_data += PERCPU_PAGE_SIZE;
- }
+ void *src = cpu == 0 ? __cpu0_per_cpu : __phys_per_cpu_start;
+
+ if (node != node_cpuid[cpu].nid)
+ continue;
+
+ memcpy(__va(cpu_data), src, __per_cpu_end - __per_cpu_start);
+ __per_cpu_offset[cpu] = (char *)__va(cpu_data) -
+ __per_cpu_start;
+
+ /*
+ * percpu area for cpu0 is moved from the __init area
+ * which is setup by head.S and used till this point.
+ * Update ar.k3. This move is ensures that percpu
+ * area for cpu0 is on the correct node and its
+ * virtual address isn't insanely far from other
+ * percpu areas which is important for congruent
+ * percpu allocator.
+ */
+ if (cpu == 0)
+ ia64_set_kr(IA64_KR_PER_CPU_DATA,
+ (unsigned long)cpu_data -
+ (unsigned long)__per_cpu_start);
+
+ cpu_data += PERCPU_PAGE_SIZE;
}
#endif
return cpu_data;
}
+#ifdef CONFIG_SMP
+/**
+ * setup_per_cpu_areas - setup percpu areas
+ *
+ * Arch code has already allocated and initialized percpu areas. All
+ * this function has to do is to teach the determined layout to the
+ * dynamic percpu allocator, which happens to be more complex than
+ * creating whole new ones using helpers.
+ */
+void __init setup_per_cpu_areas(void)
+{
+ struct pcpu_alloc_info *ai;
+ struct pcpu_group_info *uninitialized_var(gi);
+ unsigned int *cpu_map;
+ void *base;
+ unsigned long base_offset;
+ unsigned int cpu;
+ ssize_t static_size, reserved_size, dyn_size;
+ int node, prev_node, unit, nr_units, rc;
+
+ ai = pcpu_alloc_alloc_info(MAX_NUMNODES, nr_cpu_ids);
+ if (!ai)
+ panic("failed to allocate pcpu_alloc_info");
+ cpu_map = ai->groups[0].cpu_map;
+
+ /* determine base */
+ base = (void *)ULONG_MAX;
+ for_each_possible_cpu(cpu)
+ base = min(base,
+ (void *)(__per_cpu_offset[cpu] + __per_cpu_start));
+ base_offset = (void *)__per_cpu_start - base;
+
+ /* build cpu_map, units are grouped by node */
+ unit = 0;
+ for_each_node(node)
+ for_each_possible_cpu(cpu)
+ if (node == node_cpuid[cpu].nid)
+ cpu_map[unit++] = cpu;
+ nr_units = unit;
+
+ /* set basic parameters */
+ static_size = __per_cpu_end - __per_cpu_start;
+ reserved_size = PERCPU_MODULE_RESERVE;
+ dyn_size = PERCPU_PAGE_SIZE - static_size - reserved_size;
+ if (dyn_size < 0)
+ panic("percpu area overflow static=%zd reserved=%zd\n",
+ static_size, reserved_size);
+
+ ai->static_size = static_size;
+ ai->reserved_size = reserved_size;
+ ai->dyn_size = dyn_size;
+ ai->unit_size = PERCPU_PAGE_SIZE;
+ ai->atom_size = PAGE_SIZE;
+ ai->alloc_size = PERCPU_PAGE_SIZE;
+
+ /*
+ * CPUs are put into groups according to node. Walk cpu_map
+ * and create new groups at node boundaries.
+ */
+ prev_node = -1;
+ ai->nr_groups = 0;
+ for (unit = 0; unit < nr_units; unit++) {
+ cpu = cpu_map[unit];
+ node = node_cpuid[cpu].nid;
+
+ if (node == prev_node) {
+ gi->nr_units++;
+ continue;
+ }
+ prev_node = node;
+
+ gi = &ai->groups[ai->nr_groups++];
+ gi->nr_units = 1;
+ gi->base_offset = __per_cpu_offset[cpu] + base_offset;
+ gi->cpu_map = &cpu_map[unit];
+ }
+
+ rc = pcpu_setup_first_chunk(ai, base);
+ if (rc)
+ panic("failed to setup percpu area (err=%d)", rc);
+
+ pcpu_free_alloc_info(ai);
+}
+#endif
+
/**
* fill_pernode - initialize pernode data.
* @node: the node id.
sparse_init();
#ifdef CONFIG_VIRTUAL_MEM_MAP
- vmalloc_end -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) *
+ VMALLOC_END -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) *
sizeof(struct page));
- vmem_map = (struct page *) vmalloc_end;
+ vmem_map = (struct page *) VMALLOC_END;
efi_memmap_walk(create_mem_map_page_table, NULL);
printk("Virtual mem_map starts at 0x%p\n", vmem_map);
#endif
unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL;
#ifdef CONFIG_VIRTUAL_MEM_MAP
-unsigned long vmalloc_end = VMALLOC_END_INIT;
-EXPORT_SYMBOL(vmalloc_end);
+unsigned long VMALLOC_END = VMALLOC_END_INIT;
+EXPORT_SYMBOL(VMALLOC_END);
struct page *vmem_map;
EXPORT_SYMBOL(vmem_map);
#endif
#ifndef __M68K_HARDIRQ_H
#define __M68K_HARDIRQ_H
-#define HARDIRQ_BITS 8
+#include <linux/threads.h>
+#include <linux/cache.h>
+
+/* entry.S is sensitive to the offsets of these fields */
+typedef struct {
+ unsigned int __softirq_pending;
+} ____cacheline_aligned irq_cpustat_t;
-#include <asm-generic/hardirq.h>
+#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+
+#define HARDIRQ_BITS 8
#endif
#define DBDEV_TAB_SIZE ARRAY_SIZE(dbdev_tab)
#ifdef CONFIG_PM
-static u32 au1xxx_dbdma_pm_regs[NUM_DBDMA_CHANS + 1][8];
+static u32 au1xxx_dbdma_pm_regs[NUM_DBDMA_CHANS + 1][6];
#endif
au1xxx_dbdma_pm_regs[0][3] = au_readl(addr + 0x0c);
/* save channel configurations */
- for (i = 1, addr = DDMA_CHANNEL_BASE; i < NUM_DBDMA_CHANS; i++) {
+ for (i = 1, addr = DDMA_CHANNEL_BASE; i <= NUM_DBDMA_CHANS; i++) {
au1xxx_dbdma_pm_regs[i][0] = au_readl(addr + 0x00);
au1xxx_dbdma_pm_regs[i][1] = au_readl(addr + 0x04);
au1xxx_dbdma_pm_regs[i][2] = au_readl(addr + 0x08);
au1xxx_dbdma_pm_regs[i][3] = au_readl(addr + 0x0c);
au1xxx_dbdma_pm_regs[i][4] = au_readl(addr + 0x10);
au1xxx_dbdma_pm_regs[i][5] = au_readl(addr + 0x14);
- au1xxx_dbdma_pm_regs[i][6] = au_readl(addr + 0x18);
/* halt channel */
au_writel(au1xxx_dbdma_pm_regs[i][0] & ~1, addr + 0x00);
au_writel(au1xxx_dbdma_pm_regs[0][3], addr + 0x0c);
/* restore channel configurations */
- for (i = 1, addr = DDMA_CHANNEL_BASE; i < NUM_DBDMA_CHANS; i++) {
+ for (i = 1, addr = DDMA_CHANNEL_BASE; i <= NUM_DBDMA_CHANS; i++) {
au_writel(au1xxx_dbdma_pm_regs[i][0], addr + 0x00);
au_writel(au1xxx_dbdma_pm_regs[i][1], addr + 0x04);
au_writel(au1xxx_dbdma_pm_regs[i][2], addr + 0x08);
au_writel(au1xxx_dbdma_pm_regs[i][3], addr + 0x0c);
au_writel(au1xxx_dbdma_pm_regs[i][4], addr + 0x10);
au_writel(au1xxx_dbdma_pm_regs[i][5], addr + 0x14);
- au_writel(au1xxx_dbdma_pm_regs[i][6], addr + 0x18);
au_sync();
addr += 0x100; /* next channel base */
}
{
int ret;
- lock_kernel();
ret = request_irq(iodev_irq, iodev_irqhdl, IRQF_DISABLED,
iodev_name, &miscdev);
- unlock_kernel();
return ret;
}
obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
- dev-dsp.o dev-enet.o
+ dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/
#include <bcm63xx_cpu.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
-#include <bcm63xx_board.h>
#include <bcm63xx_dev_pci.h>
#include <bcm63xx_dev_enet.h>
#include <bcm63xx_dev_dsp.h>
+#include <bcm63xx_dev_pcmcia.h>
+#include <bcm63xx_dev_uart.h>
#include <board_bcm963xx.h>
#define PFX "board_bcm963xx: "
{
u32 val;
+ bcm63xx_uart_register();
+
+ if (board.has_pccard)
+ bcm63xx_pcmcia_register();
+
if (board.has_enet0 &&
!board_get_mac_address(board.enet0.mac_addr))
bcm63xx_enet_register(0, &board.enet0);
--- /dev/null
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/bootinfo.h>
+#include <linux/platform_device.h>
+#include <bcm63xx_cs.h>
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_dev_pcmcia.h>
+#include <bcm63xx_io.h>
+#include <bcm63xx_regs.h>
+
+static struct resource pcmcia_resources[] = {
+ /* pcmcia registers */
+ {
+ /* start & end filled at runtime */
+ .flags = IORESOURCE_MEM,
+ },
+
+ /* pcmcia memory zone resources */
+ {
+ .start = BCM_PCMCIA_COMMON_BASE_PA,
+ .end = BCM_PCMCIA_COMMON_END_PA,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = BCM_PCMCIA_ATTR_BASE_PA,
+ .end = BCM_PCMCIA_ATTR_END_PA,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = BCM_PCMCIA_IO_BASE_PA,
+ .end = BCM_PCMCIA_IO_END_PA,
+ .flags = IORESOURCE_MEM,
+ },
+
+ /* PCMCIA irq */
+ {
+ /* start filled at runtime */
+ .flags = IORESOURCE_IRQ,
+ },
+
+ /* declare PCMCIA IO resource also */
+ {
+ .start = BCM_PCMCIA_IO_BASE_PA,
+ .end = BCM_PCMCIA_IO_END_PA,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static struct bcm63xx_pcmcia_platform_data pd;
+
+static struct platform_device bcm63xx_pcmcia_device = {
+ .name = "bcm63xx_pcmcia",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(pcmcia_resources),
+ .resource = pcmcia_resources,
+ .dev = {
+ .platform_data = &pd,
+ },
+};
+
+static int __init config_pcmcia_cs(unsigned int cs,
+ u32 base, unsigned int size)
+{
+ int ret;
+
+ ret = bcm63xx_set_cs_status(cs, 0);
+ if (!ret)
+ ret = bcm63xx_set_cs_base(cs, base, size);
+ if (!ret)
+ ret = bcm63xx_set_cs_status(cs, 1);
+ return ret;
+}
+
+static const __initdata struct {
+ unsigned int cs;
+ unsigned int base;
+ unsigned int size;
+} pcmcia_cs[3] = {
+ {
+ .cs = MPI_CS_PCMCIA_COMMON,
+ .base = BCM_PCMCIA_COMMON_BASE_PA,
+ .size = BCM_PCMCIA_COMMON_SIZE
+ },
+ {
+ .cs = MPI_CS_PCMCIA_ATTR,
+ .base = BCM_PCMCIA_ATTR_BASE_PA,
+ .size = BCM_PCMCIA_ATTR_SIZE
+ },
+ {
+ .cs = MPI_CS_PCMCIA_IO,
+ .base = BCM_PCMCIA_IO_BASE_PA,
+ .size = BCM_PCMCIA_IO_SIZE
+ },
+};
+
+int __init bcm63xx_pcmcia_register(void)
+{
+ int ret, i;
+
+ if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358())
+ return 0;
+
+ /* use correct pcmcia ready gpio depending on processor */
+ switch (bcm63xx_get_cpu_id()) {
+ case BCM6348_CPU_ID:
+ pd.ready_gpio = 22;
+ break;
+
+ case BCM6358_CPU_ID:
+ pd.ready_gpio = 18;
+ break;
+
+ default:
+ return -ENODEV;
+ }
+
+ pcmcia_resources[0].start = bcm63xx_regset_address(RSET_PCMCIA);
+ pcmcia_resources[0].end = pcmcia_resources[0].start +
+ RSET_PCMCIA_SIZE - 1;
+ pcmcia_resources[4].start = bcm63xx_get_irq_number(IRQ_PCMCIA);
+
+ /* configure pcmcia chip selects */
+ for (i = 0; i < 3; i++) {
+ ret = config_pcmcia_cs(pcmcia_cs[i].cs,
+ pcmcia_cs[i].base,
+ pcmcia_cs[i].size);
+ if (ret)
+ goto out_err;
+ }
+
+ return platform_device_register(&bcm63xx_pcmcia_device);
+
+out_err:
+ printk(KERN_ERR "unable to set pcmcia chip select\n");
+ return ret;
+}
--- /dev/null
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <bcm63xx_cpu.h>
+#include <bcm63xx_dev_uart.h>
+
+static struct resource uart_resources[] = {
+ {
+ .start = -1, /* filled at runtime */
+ .end = -1, /* filled at runtime */
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = -1, /* filled at runtime */
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bcm63xx_uart_device = {
+ .name = "bcm63xx_uart",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(uart_resources),
+ .resource = uart_resources,
+};
+
+int __init bcm63xx_uart_register(void)
+{
+ uart_resources[0].start = bcm63xx_regset_address(RSET_UART0);
+ uart_resources[0].end = uart_resources[0].start;
+ uart_resources[0].end += RSET_UART_SIZE - 1;
+ uart_resources[1].start = bcm63xx_get_irq_number(IRQ_UART0);
+ return platform_device_register(&bcm63xx_uart_device);
+}
--- /dev/null
+#ifndef BCM63XX_DEV_PCMCIA_H_
+#define BCM63XX_DEV_PCMCIA_H_
+
+/*
+ * PCMCIA driver platform data
+ */
+struct bcm63xx_pcmcia_platform_data {
+ unsigned int ready_gpio;
+};
+
+int bcm63xx_pcmcia_register(void);
+
+#endif /* BCM63XX_DEV_PCMCIA_H_ */
--- /dev/null
+#ifndef BCM63XX_DEV_UART_H_
+#define BCM63XX_DEV_UART_H_
+
+int bcm63xx_uart_register(void);
+
+#endif /* BCM63XX_DEV_UART_H_ */
extern asmlinkage void smp_call_function_interrupt(void);
-extern void arch_send_call_function_single_ipi(int cpu);
-extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+static inline void arch_send_call_function_single_ipi(int cpu)
+{
+ extern struct plat_smp_ops *mp_ops; /* private */
+
+ mp_ops->send_ipi_mask(&cpumask_of_cpu(cpu), SMP_CALL_FUNCTION);
+}
+
+static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+ extern struct plat_smp_ops *mp_ops; /* private */
+
+ mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
+}
#endif /* __ASM_SMP_H */
#if defined(__MIPSEB__)
# include <linux/unaligned/be_struct.h>
# include <linux/unaligned/le_byteshift.h>
-# include <linux/unaligned/generic.h>
# define get_unaligned __get_unaligned_be
# define put_unaligned __put_unaligned_be
#elif defined(__MIPSEL__)
# include <linux/unaligned/le_struct.h>
# include <linux/unaligned/be_byteshift.h>
-# include <linux/unaligned/generic.h>
# define get_unaligned __get_unaligned_le
# define put_unaligned __put_unaligned_le
#else
# error "MIPS, but neither __MIPSEB__, nor __MIPSEL__???"
#endif
+# include <linux/unaligned/generic.h>
+
#endif /* _ASM_MIPS_UNALIGNED_H */
}
-static void sp_setfsuidgid( uid_t uid, gid_t gid)
+static int sp_setfsuidgid(uid_t uid, gid_t gid)
{
- current->cred->fsuid = uid;
- current->cred->fsgid = gid;
+ struct cred *new;
- key_fsuid_changed(current);
- key_fsgid_changed(current);
+ new = prepare_creds();
+ if (!new)
+ return -ENOMEM;
+
+ new->fsuid = uid;
+ new->fsgid = gid;
+
+ commit_creds(new);
+
+ return 0;
}
/*
mm_segment_t old_fs;
struct timeval tv;
struct timezone tz;
- int cmd;
+ int err, cmd;
char *vcwd;
int size;
/* Run the syscall at the privilege of the user who loaded the
SP program */
- if (vpe_getuid(tclimit))
- sp_setfsuidgid(vpe_getuid(tclimit), vpe_getgid(tclimit));
+ if (vpe_getuid(tclimit)) {
+ err = sp_setfsuidgid(vpe_getuid(tclimit), vpe_getgid(tclimit));
+ if (!err)
+ pr_err("Change of creds failed\n");
+ }
switch (sc.cmd) {
/* needs the flags argument translating from SDE kit to
break;
} /* switch */
- if (vpe_getuid(tclimit))
- sp_setfsuidgid( 0, 0);
+ if (vpe_getuid(tclimit)) {
+ err = sp_setfsuidgid(0, 0);
+ if (!err)
+ pr_err("restoring old creds failed\n");
+ }
old_fs = get_fs();
set_fs(KERNEL_DS);
*/
static irqreturn_t rtlx_interrupt(int irq, void *dev_id)
{
+ unsigned int vpeflags;
+ unsigned long flags;
int i;
- unsigned int flags, vpeflags;
/* Ought not to be strictly necessary for SMTC builds */
local_irq_save(flags);
static int file_open(struct inode *inode, struct file *filp)
{
- int minor = iminor(inode);
- int err;
-
- lock_kernel();
- err = rtlx_open(minor, (filp->f_flags & O_NONBLOCK) ? 0 : 1);
- unlock_kernel();
- return err;
+ return rtlx_open(iminor(inode), (filp->f_flags & O_NONBLOCK) ? 0 : 1);
}
static int file_release(struct inode *inode, struct file *filp)
{
- int minor = iminor(inode);
-
- return rtlx_release(minor);
+ return rtlx_release(iminor(inode));
}
static unsigned int file_poll(struct file *file, poll_table * wait)
#include <linux/cpumask.h>
#include <linux/cpu.h>
#include <linux/err.h>
-#include <linux/smp.h>
#include <asm/atomic.h>
#include <asm/cpu.h>
cpu_idle();
}
-void arch_send_call_function_ipi_mask(const struct cpumask *mask)
-{
- mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
-}
-
-/*
- * We reuse the same vector for the single IPI
- */
-void arch_send_call_function_single_ipi(int cpu)
-{
- mp_ops->send_ipi_mask(cpumask_of_cpu(cpu), SMP_CALL_FUNCTION);
-}
-
/*
* Call into both interrupt handlers, as we share the IPI for them
*/
static struct irqaction irq_ipi = {
.handler = ipi_interrupt,
- .flags = IRQF_DISABLED,
- .name = "SMTC_IPI",
- .flags = IRQF_PERCPU
+ .flags = IRQF_DISABLED | IRQF_PERCPU,
+ .name = "SMTC_IPI"
};
static void setup_cross_vpe_interrupts(unsigned int nvpe)
};
struct {
- /* Virtual processing elements */
- struct list_head vpe_list;
-
- /* Thread contexts */
- struct list_head tc_list;
+ spinlock_t vpe_list_lock;
+ struct list_head vpe_list; /* Virtual processing elements */
+ spinlock_t tc_list_lock;
+ struct list_head tc_list; /* Thread contexts */
} vpecontrol = {
- .vpe_list = LIST_HEAD_INIT(vpecontrol.vpe_list),
- .tc_list = LIST_HEAD_INIT(vpecontrol.tc_list)
+ .vpe_list_lock = SPIN_LOCK_UNLOCKED,
+ .vpe_list = LIST_HEAD_INIT(vpecontrol.vpe_list),
+ .tc_list_lock = SPIN_LOCK_UNLOCKED,
+ .tc_list = LIST_HEAD_INIT(vpecontrol.tc_list)
};
static void release_progmem(void *ptr);
/* get the vpe associated with this minor */
static struct vpe *get_vpe(int minor)
{
- struct vpe *v;
+ struct vpe *res, *v;
if (!cpu_has_mipsmt)
return NULL;
+ res = NULL;
+ spin_lock(&vpecontrol.vpe_list_lock);
list_for_each_entry(v, &vpecontrol.vpe_list, list) {
- if (v->minor == minor)
- return v;
+ if (v->minor == minor) {
+ res = v;
+ break;
+ }
}
+ spin_unlock(&vpecontrol.vpe_list_lock);
- return NULL;
+ return res;
}
/* get the vpe associated with this minor */
static struct tc *get_tc(int index)
{
- struct tc *t;
+ struct tc *res, *t;
+ res = NULL;
+ spin_lock(&vpecontrol.tc_list_lock);
list_for_each_entry(t, &vpecontrol.tc_list, list) {
- if (t->index == index)
- return t;
+ if (t->index == index) {
+ res = t;
+ break;
+ }
}
+ spin_unlock(&vpecontrol.tc_list_lock);
return NULL;
}
{
struct vpe *v;
- if ((v = kzalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL) {
+ if ((v = kzalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL)
return NULL;
- }
INIT_LIST_HEAD(&v->tc);
+ spin_lock(&vpecontrol.vpe_list_lock);
list_add_tail(&v->list, &vpecontrol.vpe_list);
+ spin_unlock(&vpecontrol.vpe_list_lock);
INIT_LIST_HEAD(&v->notify);
v->minor = minor;
+
return v;
}
INIT_LIST_HEAD(&tc->tc);
tc->index = index;
+
+ spin_lock(&vpecontrol.tc_list_lock);
list_add_tail(&tc->list, &vpecontrol.tc_list);
+ spin_unlock(&vpecontrol.tc_list_lock);
out:
return tc;
kfree(v);
}
-static void dump_mtregs(void)
+static void __maybe_unused dump_mtregs(void)
{
unsigned long val;
enum vpe_state state;
struct vpe_notifications *not;
struct vpe *v;
- int ret, err = 0;
+ int ret;
- lock_kernel();
if (minor != iminor(inode)) {
/* assume only 1 device at the moment. */
- printk(KERN_WARNING "VPE loader: only vpe1 is supported\n");
- err = -ENODEV;
- goto out;
+ pr_warning("VPE loader: only vpe1 is supported\n");
+
+ return -ENODEV;
}
if ((v = get_vpe(tclimit)) == NULL) {
- printk(KERN_WARNING "VPE loader: unable to get vpe\n");
- err = -ENODEV;
- goto out;
+ pr_warning("VPE loader: unable to get vpe\n");
+
+ return -ENODEV;
}
state = xchg(&v->state, VPE_STATE_INUSE);
v->shared_ptr = NULL;
v->__start = 0;
-out:
unlock_kernel();
+
return 0;
}
{
struct vpe *v, *n;
+ device_del(&vpe_device);
+ unregister_chrdev(major, module_name);
+
+ /* No locking needed here */
list_for_each_entry_safe(v, n, &vpecontrol.vpe_list, list) {
- if (v->state != VPE_STATE_UNUSED) {
+ if (v->state != VPE_STATE_UNUSED)
release_vpe(v);
- }
}
-
- device_del(&vpe_device);
- unregister_chrdev(major, module_name);
}
module_init(vpe_module_init);
*/
static void mips_sc_inv(unsigned long addr, unsigned long size)
{
+ unsigned long lsize = cpu_scache_line_size();
+ unsigned long almask = ~(lsize - 1);
+
+ cache_op(Hit_Writeback_Inv_SD, addr & almask);
+ cache_op(Hit_Writeback_Inv_SD, (addr + size - 1) & almask);
blast_inv_scache_range(addr, addr + size);
}
unsigned int ctrl;
unsigned long long reset_counter1;
unsigned long long reset_counter2;
- int cnt1_enalbed, cnt2_enalbed;
+ int cnt1_enabled, cnt2_enabled;
} reg;
DEFINE_SPINLOCK(sample_lock);
reg.ctrl = ctrl;
- reg.cnt1_enalbed = cfg[0].enabled;
- reg.cnt2_enalbed = cfg[1].enabled;
+ reg.cnt1_enabled = cfg[0].enabled;
+ reg.cnt2_enabled = cfg[1].enabled;
}
static void loongson2_cpu_start(void *args)
{
/* Start all counters on current CPU */
- if (reg.cnt1_enalbed || reg.cnt2_enalbed)
+ if (reg.cnt1_enabled || reg.cnt2_enabled)
write_c0_perfctrl(reg.ctrl);
}
*/
/* Check whether the irq belongs to me */
- enabled = reg.cnt1_enalbed | reg.cnt2_enalbed;
+ enabled = reg.cnt1_enabled | reg.cnt2_enabled;
if (!enabled)
return IRQ_NONE;
spin_lock_irqsave(&sample_lock, flags);
if (counter1 & LOONGSON2_PERFCNT_OVERFLOW) {
- if (reg.cnt1_enalbed)
+ if (reg.cnt1_enabled)
oprofile_add_sample(regs, 0);
counter1 = reg.reset_counter1;
}
if (counter2 & LOONGSON2_PERFCNT_OVERFLOW) {
- if (reg.cnt2_enalbed)
+ if (reg.cnt2_enabled)
oprofile_add_sample(regs, 1);
counter2 = reg.reset_counter2;
}
unsigned long intr;
unsigned long value;
static char pciirqflag;
+ int ret;
#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
unsigned int vpe_status;
#endif
* allocation assigns an interrupt handler to the interrupt.
*/
if (pciirqflag == 0) {
- request_irq(MSP_INT_PCI,/* Hardcoded internal MSP7120 wiring */
+ ret = request_irq(MSP_INT_PCI,/* Hardcoded internal MSP7120 wiring */
bpci_interrupt,
IRQF_SHARED | IRQF_DISABLED,
"PMC MSP PCI Host",
preg);
+ if (ret != 0)
+ return ret;
pciirqflag = ~0;
}
REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cpu_to_node(destid)), irq);
}
-static void ip27_send_ipi(const struct cpumask *mask, unsigned int action)
+static void ip27_send_ipi_mask(const struct cpumask *mask, unsigned int action)
{
unsigned int i;
unsigned long flags;
unsigned int irq_dirty;
- if (cpumask_weight(mask) != 1) {
- printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
- return -1;
- }
i = cpumask_first(mask);
/* Convert logical CPU to physical CPU */
static int sbprof_tb_open(struct inode *inode, struct file *filp)
{
int minor;
- int err = 0;
- lock_kernel();
minor = iminor(inode);
- if (minor != 0) {
- err = -ENODEV;
- goto out;
- }
+ if (minor != 0)
+ return -ENODEV;
- if (xchg(&sbp.open, SB_OPENING) != SB_CLOSED) {
- err = -EBUSY;
- goto out;
- }
+ if (xchg(&sbp.open, SB_OPENING) != SB_CLOSED)
+ return -EBUSY;
memset(&sbp, 0, sizeof(struct sbprof_tb));
sbp.sbprof_tbbuf = vmalloc(MAX_TBSAMPLE_BYTES);
if (!sbp.sbprof_tbbuf) {
- err = -ENOMEM;
- goto out;
+ sbp.open = SB_CLOSED;
+ wmb();
+ return -ENOMEM;
}
+
memset(sbp.sbprof_tbbuf, 0, MAX_TBSAMPLE_BYTES);
init_waitqueue_head(&sbp.tb_sync);
init_waitqueue_head(&sbp.tb_read);
mutex_init(&sbp.lock);
sbp.open = SB_OPEN;
+ wmb();
- out:
- unlock_kernel();
- return err;
+ return 0;
}
static int sbprof_tb_release(struct inode *inode, struct file *filp)
int minor;
minor = iminor(inode);
- if (minor != 0 || !sbp.open)
+ if (minor != 0 || sbp.open != SB_CLOSED)
return -ENODEV;
mutex_lock(&sbp.lock);
sbprof_zbprof_stop();
vfree(sbp.sbprof_tbbuf);
- sbp.open = 0;
+ sbp.open = SB_CLOSED;
+ wmb();
mutex_unlock(&sbp.lock);
}
tb_dev = dev;
- sbp.open = 0;
+ sbp.open = SB_CLOSED;
+ wmb();
tb_period = zbbus_mhz * 10000LL;
pr_info(DEVNAME ": initialized - tb_period = %lld\n",
(long long) tb_period);
break;
}
ts->tv_sec = sec;
- tv->tv_nsec = 0;
+ ts->tv_nsec = 0;
}
int rtc_mips_set_time(unsigned long sec)
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct *)(x))
-#define __get_user_nocheck(x, ptr, size) \
-({ \
- __typeof(*(ptr)) __gu_val; \
- unsigned long __gu_addr; \
- int __gu_err; \
- __gu_addr = (unsigned long) (ptr); \
- switch (size) { \
- case 1: __get_user_asm("bu"); break; \
- case 2: __get_user_asm("hu"); break; \
- case 4: __get_user_asm("" ); break; \
- default: __get_user_unknown(); break; \
- } \
- x = (__typeof__(*(ptr))) __gu_val; \
- __gu_err; \
+#define __get_user_nocheck(x, ptr, size) \
+({ \
+ unsigned long __gu_addr; \
+ int __gu_err; \
+ __gu_addr = (unsigned long) (ptr); \
+ switch (size) { \
+ case 1: { \
+ unsigned char __gu_val; \
+ __get_user_asm("bu"); \
+ (x) = *(__force __typeof__(*(ptr))*) &__gu_val; \
+ break; \
+ } \
+ case 2: { \
+ unsigned short __gu_val; \
+ __get_user_asm("hu"); \
+ (x) = *(__force __typeof__(*(ptr))*) &__gu_val; \
+ break; \
+ } \
+ case 4: { \
+ unsigned int __gu_val; \
+ __get_user_asm(""); \
+ (x) = *(__force __typeof__(*(ptr))*) &__gu_val; \
+ break; \
+ } \
+ default: \
+ __get_user_unknown(); \
+ break; \
+ } \
+ __gu_err; \
})
-#define __get_user_check(x, ptr, size) \
-({ \
- __typeof__(*(ptr)) __gu_val; \
- unsigned long __gu_addr; \
- int __gu_err; \
- __gu_addr = (unsigned long) (ptr); \
- if (likely(__access_ok(__gu_addr,size))) { \
- switch (size) { \
- case 1: __get_user_asm("bu"); break; \
- case 2: __get_user_asm("hu"); break; \
- case 4: __get_user_asm("" ); break; \
- default: __get_user_unknown(); break; \
- } \
- } \
- else { \
- __gu_err = -EFAULT; \
- __gu_val = 0; \
- } \
- x = (__typeof__(*(ptr))) __gu_val; \
- __gu_err; \
+#define __get_user_check(x, ptr, size) \
+({ \
+ int _e; \
+ if (likely(__access_ok((unsigned long) (ptr), (size)))) \
+ _e = __get_user_nocheck((x), (ptr), (size)); \
+ else { \
+ _e = -EFAULT; \
+ (x) = (__typeof__(x))0; \
+ } \
+ _e; \
})
#define __get_user_asm(INSN) \
extern unsigned long mn10300_iobclk;
extern unsigned long mn10300_tsc_per_HZ;
-#define MN10300_IOCLK ((unsigned long)mn10300_ioclk)
+#define MN10300_IOCLK mn10300_ioclk
/* If this processors has a another clock, uncomment the below. */
-/* #define MN10300_IOBCLK ((unsigned long)mn10300_iobclk) */
+/* #define MN10300_IOBCLK mn10300_iobclk */
#else /* !CONFIG_MN10300_RTC */
#define MN10300_TSCCLK MN10300_IOCLK
#ifdef CONFIG_MN10300_RTC
-#define MN10300_TSC_PER_HZ ((unsigned long)mn10300_tsc_per_HZ)
+#define MN10300_TSC_PER_HZ mn10300_tsc_per_HZ
#else /* !CONFIG_MN10300_RTC */
#define MN10300_TSC_PER_HZ (MN10300_TSCCLK/HZ)
#endif /* !CONFIG_MN10300_RTC */
extern unsigned long mn10300_iobclk;
extern unsigned long mn10300_tsc_per_HZ;
-#define MN10300_IOCLK ((unsigned long)mn10300_ioclk)
+#define MN10300_IOCLK mn10300_ioclk
/* If this processors has a another clock, uncomment the below. */
-/* #define MN10300_IOBCLK ((unsigned long)mn10300_iobclk) */
+/* #define MN10300_IOBCLK mn10300_iobclk */
#else /* !CONFIG_MN10300_RTC */
#define MN10300_TSCCLK MN10300_IOCLK
#ifdef CONFIG_MN10300_RTC
-#define MN10300_TSC_PER_HZ ((unsigned long)mn10300_tsc_per_HZ)
+#define MN10300_TSC_PER_HZ mn10300_tsc_per_HZ
#else /* !CONFIG_MN10300_RTC */
#define MN10300_TSC_PER_HZ (MN10300_TSCCLK/HZ)
#endif /* !CONFIG_MN10300_RTC */
return single_open(file, kvmppc_exit_timing_show, inode->i_private);
}
-static struct file_operations kvmppc_exit_timing_fops = {
+static const struct file_operations kvmppc_exit_timing_fops = {
.owner = THIS_MODULE,
.open = kvmppc_exit_timing_open,
.read = seq_read,
__simple_attr_check_format(__fmt, 0ull); \
return spufs_attr_open(inode, file, __get, __set, __fmt); \
} \
-static struct file_operations __fops = { \
+static const struct file_operations __fops = { \
.owner = THIS_MODULE, \
.open = __fops ## _open, \
.release = spufs_attr_release, \
return n_read * sizeof(struct dtl_entry);
}
-static struct file_operations dtl_fops = {
+static const struct file_operations dtl_fops = {
.open = dtl_file_open,
.release = dtl_file_release,
.read = dtl_file_read,
"adcl $0, %0 ;\n"
: "=&r" (sum)
: "r" (saddr), "r" (daddr),
- "r" (htonl(len)), "r" (htonl(proto)), "0" (sum));
+ "r" (htonl(len)), "r" (htonl(proto)), "0" (sum)
+ : "memory");
return csum_fold(sum);
}
extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64);
-#define cmpxchg64(ptr, o, n) \
-({ \
- __typeof__(*(ptr)) __ret; \
- if (likely(boot_cpu_data.x86 > 4)) \
- __ret = (__typeof__(*(ptr)))__cmpxchg64((ptr), \
- (unsigned long long)(o), \
- (unsigned long long)(n)); \
- else \
- __ret = (__typeof__(*(ptr)))cmpxchg_486_u64((ptr), \
- (unsigned long long)(o), \
- (unsigned long long)(n)); \
- __ret; \
-})
+#define cmpxchg64(ptr, o, n) \
+({ \
+ __typeof__(*(ptr)) __ret; \
+ __typeof__(*(ptr)) __old = (o); \
+ __typeof__(*(ptr)) __new = (n); \
+ alternative_io("call cmpxchg8b_emu", \
+ "lock; cmpxchg8b (%%esi)" , \
+ X86_FEATURE_CX8, \
+ "=A" (__ret), \
+ "S" ((ptr)), "0" (__old), \
+ "b" ((unsigned int)__new), \
+ "c" ((unsigned int)(__new>>32)) \
+ : "memory"); \
+ __ret; })
+
+
+
#define cmpxchg64_local(ptr, o, n) \
({ \
__typeof__(*(ptr)) __ret; \
#define percpu_or(var, val) percpu_to_op("or", per_cpu__##var, val)
#define percpu_xor(var, val) percpu_to_op("xor", per_cpu__##var, val)
+#define __this_cpu_read_1(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
+#define __this_cpu_read_2(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
+#define __this_cpu_read_4(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
+
+#define __this_cpu_write_1(pcp, val) percpu_to_op("mov", (pcp), val)
+#define __this_cpu_write_2(pcp, val) percpu_to_op("mov", (pcp), val)
+#define __this_cpu_write_4(pcp, val) percpu_to_op("mov", (pcp), val)
+#define __this_cpu_add_1(pcp, val) percpu_to_op("add", (pcp), val)
+#define __this_cpu_add_2(pcp, val) percpu_to_op("add", (pcp), val)
+#define __this_cpu_add_4(pcp, val) percpu_to_op("add", (pcp), val)
+#define __this_cpu_and_1(pcp, val) percpu_to_op("and", (pcp), val)
+#define __this_cpu_and_2(pcp, val) percpu_to_op("and", (pcp), val)
+#define __this_cpu_and_4(pcp, val) percpu_to_op("and", (pcp), val)
+#define __this_cpu_or_1(pcp, val) percpu_to_op("or", (pcp), val)
+#define __this_cpu_or_2(pcp, val) percpu_to_op("or", (pcp), val)
+#define __this_cpu_or_4(pcp, val) percpu_to_op("or", (pcp), val)
+#define __this_cpu_xor_1(pcp, val) percpu_to_op("xor", (pcp), val)
+#define __this_cpu_xor_2(pcp, val) percpu_to_op("xor", (pcp), val)
+#define __this_cpu_xor_4(pcp, val) percpu_to_op("xor", (pcp), val)
+
+#define this_cpu_read_1(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
+#define this_cpu_read_2(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
+#define this_cpu_read_4(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
+#define this_cpu_write_1(pcp, val) percpu_to_op("mov", (pcp), val)
+#define this_cpu_write_2(pcp, val) percpu_to_op("mov", (pcp), val)
+#define this_cpu_write_4(pcp, val) percpu_to_op("mov", (pcp), val)
+#define this_cpu_add_1(pcp, val) percpu_to_op("add", (pcp), val)
+#define this_cpu_add_2(pcp, val) percpu_to_op("add", (pcp), val)
+#define this_cpu_add_4(pcp, val) percpu_to_op("add", (pcp), val)
+#define this_cpu_and_1(pcp, val) percpu_to_op("and", (pcp), val)
+#define this_cpu_and_2(pcp, val) percpu_to_op("and", (pcp), val)
+#define this_cpu_and_4(pcp, val) percpu_to_op("and", (pcp), val)
+#define this_cpu_or_1(pcp, val) percpu_to_op("or", (pcp), val)
+#define this_cpu_or_2(pcp, val) percpu_to_op("or", (pcp), val)
+#define this_cpu_or_4(pcp, val) percpu_to_op("or", (pcp), val)
+#define this_cpu_xor_1(pcp, val) percpu_to_op("xor", (pcp), val)
+#define this_cpu_xor_2(pcp, val) percpu_to_op("xor", (pcp), val)
+#define this_cpu_xor_4(pcp, val) percpu_to_op("xor", (pcp), val)
+
+#define irqsafe_cpu_add_1(pcp, val) percpu_to_op("add", (pcp), val)
+#define irqsafe_cpu_add_2(pcp, val) percpu_to_op("add", (pcp), val)
+#define irqsafe_cpu_add_4(pcp, val) percpu_to_op("add", (pcp), val)
+#define irqsafe_cpu_and_1(pcp, val) percpu_to_op("and", (pcp), val)
+#define irqsafe_cpu_and_2(pcp, val) percpu_to_op("and", (pcp), val)
+#define irqsafe_cpu_and_4(pcp, val) percpu_to_op("and", (pcp), val)
+#define irqsafe_cpu_or_1(pcp, val) percpu_to_op("or", (pcp), val)
+#define irqsafe_cpu_or_2(pcp, val) percpu_to_op("or", (pcp), val)
+#define irqsafe_cpu_or_4(pcp, val) percpu_to_op("or", (pcp), val)
+#define irqsafe_cpu_xor_1(pcp, val) percpu_to_op("xor", (pcp), val)
+#define irqsafe_cpu_xor_2(pcp, val) percpu_to_op("xor", (pcp), val)
+#define irqsafe_cpu_xor_4(pcp, val) percpu_to_op("xor", (pcp), val)
+
+/*
+ * Per cpu atomic 64 bit operations are only available under 64 bit.
+ * 32 bit must fall back to generic operations.
+ */
+#ifdef CONFIG_X86_64
+#define __this_cpu_read_8(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
+#define __this_cpu_write_8(pcp, val) percpu_to_op("mov", (pcp), val)
+#define __this_cpu_add_8(pcp, val) percpu_to_op("add", (pcp), val)
+#define __this_cpu_and_8(pcp, val) percpu_to_op("and", (pcp), val)
+#define __this_cpu_or_8(pcp, val) percpu_to_op("or", (pcp), val)
+#define __this_cpu_xor_8(pcp, val) percpu_to_op("xor", (pcp), val)
+
+#define this_cpu_read_8(pcp) percpu_from_op("mov", (pcp), "m"(pcp))
+#define this_cpu_write_8(pcp, val) percpu_to_op("mov", (pcp), val)
+#define this_cpu_add_8(pcp, val) percpu_to_op("add", (pcp), val)
+#define this_cpu_and_8(pcp, val) percpu_to_op("and", (pcp), val)
+#define this_cpu_or_8(pcp, val) percpu_to_op("or", (pcp), val)
+#define this_cpu_xor_8(pcp, val) percpu_to_op("xor", (pcp), val)
+
+#define irqsafe_cpu_add_8(pcp, val) percpu_to_op("add", (pcp), val)
+#define irqsafe_cpu_and_8(pcp, val) percpu_to_op("and", (pcp), val)
+#define irqsafe_cpu_or_8(pcp, val) percpu_to_op("or", (pcp), val)
+#define irqsafe_cpu_xor_8(pcp, val) percpu_to_op("xor", (pcp), val)
+
+#endif
+
/* This is not atomic against other CPUs -- CPU preemption needs to be off */
#define x86_test_and_clear_bit_percpu(bit, var) \
({ \
static void print_mce_tail(void)
{
printk(KERN_EMERG "This is not a software problem!\n"
-#if (!defined(CONFIG_EDAC) || !defined(CONFIG_CPU_SUP_AMD))
- "Run through mcelog --ascii to decode and contact your hardware vendor\n"
-#endif
- );
+ "Run through mcelog --ascii to decode and contact your hardware vendor\n");
}
#define PANIC_TIMEOUT 5 /* 5 seconds */
EXPORT_SYMBOL(mcount);
#endif
+/*
+ * Note, this is a prototype to get at the symbol for
+ * the export, but dont use it from C code, it is used
+ * by assembly code and is not using C calling convention!
+ */
+extern void cmpxchg8b_emu(void);
+EXPORT_SYMBOL(cmpxchg8b_emu);
+
/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial_copy_generic);
obj-y += atomic64_32.o
lib-y += checksum_32.o
lib-y += strstr_32.o
- lib-y += semaphore_32.o string_32.o
+ lib-y += semaphore_32.o string_32.o cmpxchg8b_emu.o
lib-$(CONFIG_X86_USE_3DNOW) += mmx_32.o
else
--- /dev/null
+/*
+ * 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; version 2
+ * of the License.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/frame.h>
+#include <asm/dwarf2.h>
+
+
+.text
+
+/*
+ * Inputs:
+ * %esi : memory location to compare
+ * %eax : low 32 bits of old value
+ * %edx : high 32 bits of old value
+ * %ebx : low 32 bits of new value
+ * %ecx : high 32 bits of new value
+ */
+ENTRY(cmpxchg8b_emu)
+CFI_STARTPROC
+
+#
+# Emulate 'cmpxchg8b (%esi)' on UP except we don't
+# set the whole ZF thing (caller will just compare
+# eax:edx with the expected value)
+#
+cmpxchg8b_emu:
+ pushfl
+ cli
+
+ cmpl (%esi), %eax
+ jne not_same
+ cmpl 4(%esi), %edx
+ jne half_same
+
+ movl %ebx, (%esi)
+ movl %ecx, 4(%esi)
+
+ popfl
+ ret
+
+ not_same:
+ movl (%esi), %eax
+ half_same:
+ movl 4(%esi), %edx
+
+ popfl
+ ret
+
+CFI_ENDPROC
+ENDPROC(cmpxchg8b_emu)
return 0;
}
-static struct file_operations u32_array_fops = {
+static const struct file_operations u32_array_fops = {
.owner = THIS_MODULE,
.open = u32_array_open,
.release= xen_array_release,
struct cryptd_cpu_queue *cpu_queue;
cpu = get_cpu();
- cpu_queue = per_cpu_ptr(queue->cpu_queue, cpu);
+ cpu_queue = this_cpu_ptr(queue->cpu_queue);
err = crypto_enqueue_request(&cpu_queue->queue, request);
queue_work_on(cpu, kcrypto_wq, &cpu_queue->work);
put_cpu();
struct file *file);
static ssize_t acpi_video_device_write_brightness(struct file *file,
const char __user *buffer, size_t count, loff_t *data);
-static struct file_operations acpi_video_device_brightness_fops = {
+static const struct file_operations acpi_video_device_brightness_fops = {
.owner = THIS_MODULE,
.open = acpi_video_device_brightness_open_fs,
.read = seq_read,
return;
}
-/********** Set socket options for a VC **********/
-
-// int amb_getsockopt (struct atm_vcc * atm_vcc, int level, int optname, void * optval, int optlen);
-
-/********** Set socket options for a VC **********/
-
-// int amb_setsockopt (struct atm_vcc * atm_vcc, int level, int optname, void * optval, int optlen);
-
/********** Send **********/
static int amb_send (struct atm_vcc * atm_vcc, struct sk_buff * skb) {
static int eni_setsockopt(struct atm_vcc *vcc,int level,int optname,
- void __user *optval,int optlen)
+ void __user *optval,unsigned int optlen)
{
return -EINVAL;
}
static int fs_setsockopt(struct atm_vcc *vcc,int level,int optname,
- void __user *optval,int optlen)
+ void __user *optval,unsigned int optlen)
{
func_enter ();
func_exit ();
static int
-fore200e_setsockopt(struct atm_vcc* vcc, int level, int optname, void __user *optval, int optlen)
+fore200e_setsockopt(struct atm_vcc* vcc, int level, int optname, void __user *optval, unsigned int optlen)
{
/* struct fore200e* fore200e = FORE200E_DEV(vcc->dev); */
he_dev->rbrq_phys);
i = CONFIG_RBPL_SIZE;
out_free_rbpl_virt:
- while (--i)
- pci_pool_free(he_dev->rbps_pool, he_dev->rbpl_virt[i].virt,
- he_dev->rbps_base[i].phys);
+ while (i--)
+ pci_pool_free(he_dev->rbpl_pool, he_dev->rbpl_virt[i].virt,
+ he_dev->rbpl_base[i].phys);
kfree(he_dev->rbpl_virt);
out_free_rbpl_base:
out_destroy_rbpl_pool:
pci_pool_destroy(he_dev->rbpl_pool);
- i = CONFIG_RBPL_SIZE;
+ i = CONFIG_RBPS_SIZE;
out_free_rbps_virt:
- while (--i)
- pci_pool_free(he_dev->rbpl_pool, he_dev->rbps_virt[i].virt,
- he_dev->rbpl_base[i].phys);
+ while (i--)
+ pci_pool_free(he_dev->rbps_pool, he_dev->rbps_virt[i].virt,
+ he_dev->rbps_base[i].phys);
kfree(he_dev->rbps_virt);
out_free_rbps_base:
}
static int hrz_setsockopt (struct atm_vcc * atm_vcc, int level, int optname,
- void *optval, int optlen) {
+ void *optval, unsigned int optlen) {
hrz_dev * dev = HRZ_DEV(atm_vcc->dev);
PRINTD (DBG_FLOW|DBG_VCC, "hrz_setsockopt");
switch (level) {
}
static int ia_setsockopt(struct atm_vcc *vcc, int level, int optname,
- void __user *optval, int optlen)
+ void __user *optval, unsigned int optlen)
{
IF_EVENT(printk(">ia_setsockopt\n");)
return -EINVAL;
static int zatm_setsockopt(struct atm_vcc *vcc,int level,int optname,
- void __user *optval,int optlen)
+ void __user *optval,unsigned int optlen)
{
return -EINVAL;
}
return err;
}
-static struct file_operations cciss_proc_fops = {
+static const struct file_operations cciss_proc_fops = {
.owner = THIS_MODULE,
.open = cciss_seq_open,
.read = seq_read,
return as ? 0 : -ENOMEM;
}
-static struct file_operations apm_bios_fops = {
+static const struct file_operations apm_bios_fops = {
.owner = THIS_MODULE,
.read = apm_read,
.poll = apm_poll,
# define bfin_otp_ioctl NULL
#endif
-static struct file_operations bfin_otp_fops = {
+static const struct file_operations bfin_otp_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = bfin_otp_ioctl,
.read = bfin_otp_read,
continue;
}
#ifdef MODULE
- if (isparam && irq[i])
+ if (isparam && i < NR_CARDS && irq[i])
cy_isa_irq = irq[i];
else
#endif
if (!res)
return -ENOENT;
- mem = request_mem_region(res->start, res->end - res->start + 1,
+ mem = request_mem_region(res->start, resource_size(res),
pdev->name);
if (mem == NULL) {
ret = -EBUSY;
}
dev_set_drvdata(&pdev->dev, mem);
- rng_base = ioremap(res->start, res->end - res->start + 1);
+ rng_base = ioremap(res->start, resource_size(res));
if (!rng_base) {
ret = -ENOMEM;
goto err_ioremap;
return 0;
}
+/* Traditional BSD devices */
+#ifdef CONFIG_LEGACY_PTYS
+
static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct tty_struct *o_tty;
return -ENOMEM;
}
-
-static const struct tty_operations pty_ops = {
- .install = pty_install,
- .open = pty_open,
- .close = pty_close,
- .write = pty_write,
- .write_room = pty_write_room,
- .flush_buffer = pty_flush_buffer,
- .chars_in_buffer = pty_chars_in_buffer,
- .unthrottle = pty_unthrottle,
- .set_termios = pty_set_termios,
- .resize = pty_resize
-};
-
-/* Traditional BSD devices */
-#ifdef CONFIG_LEGACY_PTYS
-static struct tty_driver *pty_driver, *pty_slave_driver;
-
static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
module_param(legacy_count, int, 0);
-static const struct tty_operations pty_ops_bsd = {
+/*
+ * The master side of a pty can do TIOCSPTLCK and thus
+ * has pty_bsd_ioctl.
+ */
+static const struct tty_operations master_pty_ops_bsd = {
+ .install = pty_install,
.open = pty_open,
.close = pty_close,
.write = pty_write,
.resize = pty_resize
};
+static const struct tty_operations slave_pty_ops_bsd = {
+ .install = pty_install,
+ .open = pty_open,
+ .close = pty_close,
+ .write = pty_write,
+ .write_room = pty_write_room,
+ .flush_buffer = pty_flush_buffer,
+ .chars_in_buffer = pty_chars_in_buffer,
+ .unthrottle = pty_unthrottle,
+ .set_termios = pty_set_termios,
+ .resize = pty_resize
+};
+
static void __init legacy_pty_init(void)
{
+ struct tty_driver *pty_driver, *pty_slave_driver;
+
if (legacy_count <= 0)
return;
pty_driver->init_termios.c_ospeed = 38400;
pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
pty_driver->other = pty_slave_driver;
- tty_set_operations(pty_driver, &pty_ops);
+ tty_set_operations(pty_driver, &master_pty_ops_bsd);
pty_slave_driver->owner = THIS_MODULE;
pty_slave_driver->driver_name = "pty_slave";
pty_slave_driver->flags = TTY_DRIVER_RESET_TERMIOS |
TTY_DRIVER_REAL_RAW;
pty_slave_driver->other = pty_driver;
- tty_set_operations(pty_slave_driver, &pty_ops);
+ tty_set_operations(pty_slave_driver, &slave_pty_ops_bsd);
if (tty_register_driver(pty_driver))
panic("Couldn't register pty driver");
return 1;
}
- if ((long)info < (long)(&cy_port[0])
- || (long)(&cy_port[NR_PORTS]) < (long)info) {
+ if (info < &cy_port[0] || info >= &cy_port[NR_PORTS]) {
printk("Warning: cyclades_port out of range for (%s) in %s\n",
name, routine);
return 1;
panic("TxInt on debug port!!!");
}
#endif
-
- info = &cy_port[channel];
-
/* validate the port number (as configured and open) */
if ((channel < 0) || (NR_PORTS <= channel)) {
base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
base_addr[CyTEOIR] = CyNOTRANS;
return IRQ_HANDLED;
}
+ info = &cy_port[channel];
info->last_active = jiffies;
if (info->tty == 0) {
base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
goto eperm;
if (copy_from_user(&vsa, (struct vt_setactivate __user *)arg,
- sizeof(struct vt_setactivate)))
- return -EFAULT;
+ sizeof(struct vt_setactivate))) {
+ ret = -EFAULT;
+ goto out;
+ }
if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES)
ret = -ENXIO;
else {
return status;
}
-static struct file_operations hwicap_fops = {
+static const struct file_operations hwicap_fops = {
.owner = THIS_MODULE,
.write = hwicap_write,
.read = hwicap_read,
*/
struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type)
{
- struct dma_chan *chan;
- int cpu;
-
- cpu = get_cpu();
- chan = per_cpu_ptr(channel_table[tx_type], cpu)->chan;
- put_cpu();
-
- return chan;
+ return this_cpu_read(channel_table[tx_type]->chan);
}
EXPORT_SYMBOL(dma_find_channel);
struct dma_async_tx_descriptor *tx;
dma_addr_t dma_dest, dma_src;
dma_cookie_t cookie;
- int cpu;
unsigned long flags;
dma_src = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
tx->callback = NULL;
cookie = tx->tx_submit(tx);
- cpu = get_cpu();
- per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
- per_cpu_ptr(chan->local, cpu)->memcpy_count++;
- put_cpu();
+ preempt_disable();
+ __this_cpu_add(chan->local->bytes_transferred, len);
+ __this_cpu_inc(chan->local->memcpy_count);
+ preempt_enable();
return cookie;
}
struct dma_async_tx_descriptor *tx;
dma_addr_t dma_dest, dma_src;
dma_cookie_t cookie;
- int cpu;
unsigned long flags;
dma_src = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
tx->callback = NULL;
cookie = tx->tx_submit(tx);
- cpu = get_cpu();
- per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
- per_cpu_ptr(chan->local, cpu)->memcpy_count++;
- put_cpu();
+ preempt_disable();
+ __this_cpu_add(chan->local->bytes_transferred, len);
+ __this_cpu_inc(chan->local->memcpy_count);
+ preempt_enable();
return cookie;
}
struct dma_async_tx_descriptor *tx;
dma_addr_t dma_dest, dma_src;
dma_cookie_t cookie;
- int cpu;
unsigned long flags;
dma_src = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
tx->callback = NULL;
cookie = tx->tx_submit(tx);
- cpu = get_cpu();
- per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
- per_cpu_ptr(chan->local, cpu)->memcpy_count++;
- put_cpu();
+ preempt_disable();
+ __this_cpu_add(chan->local->bytes_transferred, len);
+ __this_cpu_inc(chan->local->memcpy_count);
+ preempt_enable();
return cookie;
}
return single_open(file, gpiolib_show, NULL);
}
-static struct file_operations gpiolib_operations = {
+static const struct file_operations gpiolib_operations = {
.open = gpiolib_open,
.read = seq_read,
.llseek = seq_lseek,
list_for_each_entry_safe(mode, t, &connector->user_modes, head)
drm_mode_remove(connector, mode);
+ kfree(connector->fb_helper_private);
mutex_lock(&dev->mode_config.mutex);
drm_mode_object_put(dev, &connector->base);
list_del(&connector->head);
#include "drmP.h"
#include "drm_crtc.h"
#include "drm_crtc_helper.h"
+#include "drm_fb_helper.h"
static void drm_mode_validate_flag(struct drm_connector *connector,
int flags)
list_for_each_entry_safe(mode, t, &connector->modes, head)
mode->status = MODE_UNVERIFIED;
- connector->status = connector->funcs->detect(connector);
+ if (connector->force) {
+ if (connector->force == DRM_FORCE_ON)
+ connector->status = connector_status_connected;
+ else
+ connector->status = connector_status_disconnected;
+ if (connector->funcs->force)
+ connector->funcs->force(connector);
+ } else
+ connector->status = connector->funcs->detect(connector);
if (connector->status == connector_status_disconnected) {
DRM_DEBUG_KMS("%s is disconnected\n",
return NULL;
}
+static bool drm_has_cmdline_mode(struct drm_connector *connector)
+{
+ struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
+ struct drm_fb_helper_cmdline_mode *cmdline_mode;
+
+ if (!fb_help_conn)
+ return false;
+
+ cmdline_mode = &fb_help_conn->cmdline_mode;
+ return cmdline_mode->specified;
+}
+
+static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_connector *connector, int width, int height)
+{
+ struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
+ struct drm_fb_helper_cmdline_mode *cmdline_mode;
+ struct drm_display_mode *mode = NULL;
+
+ if (!fb_help_conn)
+ return mode;
+
+ cmdline_mode = &fb_help_conn->cmdline_mode;
+ if (cmdline_mode->specified == false)
+ return mode;
+
+ /* attempt to find a matching mode in the list of modes
+ * we have gotten so far, if not add a CVT mode that conforms
+ */
+ if (cmdline_mode->rb || cmdline_mode->margins)
+ goto create_mode;
+
+ list_for_each_entry(mode, &connector->modes, head) {
+ /* check width/height */
+ if (mode->hdisplay != cmdline_mode->xres ||
+ mode->vdisplay != cmdline_mode->yres)
+ continue;
+
+ if (cmdline_mode->refresh_specified) {
+ if (mode->vrefresh != cmdline_mode->refresh)
+ continue;
+ }
+
+ if (cmdline_mode->interlace) {
+ if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
+ continue;
+ }
+ return mode;
+ }
+
+create_mode:
+ mode = drm_cvt_mode(connector->dev, cmdline_mode->xres,
+ cmdline_mode->yres,
+ cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
+ cmdline_mode->rb, cmdline_mode->interlace,
+ cmdline_mode->margins);
+ list_add(&mode->head, &connector->modes);
+ return mode;
+}
+
static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
{
bool enable;
continue;
}
- DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
- connector->base.id);
+ DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
+ connector->base.id);
- modes[i] = drm_has_preferred_mode(connector, width, height);
+ /* got for command line mode first */
+ modes[i] = drm_pick_cmdline_mode(connector, width, height);
+ if (!modes[i]) {
+ DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
+ connector->base.id);
+ modes[i] = drm_has_preferred_mode(connector, width, height);
+ }
/* No preferred modes, pick one off the list */
if (!modes[i] && !list_empty(&connector->modes)) {
list_for_each_entry(modes[i], &connector->modes, head)
my_score = 1;
if (connector->status == connector_status_connected)
my_score++;
+ if (drm_has_cmdline_mode(connector))
+ my_score++;
if (drm_has_preferred_mode(connector, width, height))
my_score++;
{
int count = 0;
+ drm_fb_helper_parse_command_line(dev);
+
count = drm_helper_probe_connector_modes(dev,
dev->mode_config.max_width,
dev->mode_config.max_height);
/*
* we shouldn't end up with no modes here.
*/
- WARN(!count, "Connected connector with 0 modes\n");
+ WARN(!count, "No connectors reported connected with modes\n");
drm_setup_crtcs(dev);
/* Valid EDID header has these bytes */
-static u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
+static const u8 edid_header[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
+};
/**
* edid_is_valid - sanity check EDID data
}
return mode;
}
+
+/*
+ * 0 is reserved. The spec says 0x01 fill for unused timings. Some old
+ * monitors fill with ascii space (0x20) instead.
+ */
+static int
+bad_std_timing(u8 a, u8 b)
+{
+ return (a == 0x00 && b == 0x00) ||
+ (a == 0x01 && b == 0x01) ||
+ (a == 0x20 && b == 0x20);
+}
+
/**
* drm_mode_std - convert standard mode info (width, height, refresh) into mode
* @t: standard timing params
*/
struct drm_display_mode *drm_mode_std(struct drm_device *dev,
struct std_timing *t,
+ int revision,
int timing_level)
{
struct drm_display_mode *mode;
unsigned vfreq = (t->vfreq_aspect & EDID_TIMING_VFREQ_MASK)
>> EDID_TIMING_VFREQ_SHIFT;
+ if (bad_std_timing(t->hsize, t->vfreq_aspect))
+ return NULL;
+
/* According to the EDID spec, the hdisplay = hsize * 8 + 248 */
hsize = t->hsize * 8 + 248;
/* vrefresh_rate = vfreq + 60 */
vrefresh_rate = vfreq + 60;
/* the vdisplay is calculated based on the aspect ratio */
- if (aspect_ratio == 0)
- vsize = (hsize * 10) / 16;
- else if (aspect_ratio == 1)
+ if (aspect_ratio == 0) {
+ if (revision < 3)
+ vsize = hsize;
+ else
+ vsize = (hsize * 10) / 16;
+ } else if (aspect_ratio == 1)
vsize = (hsize * 3) / 4;
else if (aspect_ratio == 2)
vsize = (hsize * 4) / 5;
vsize = (hsize * 9) / 16;
/* HDTV hack */
if (hsize == 1360 && vsize == 765 && vrefresh_rate == 60) {
- mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
+ mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0,
+ false);
mode->hdisplay = 1366;
mode->vsync_start = mode->vsync_start - 1;
mode->vsync_end = mode->vsync_end - 1;
mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
break;
case LEVEL_CVT:
- mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
+ mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0,
+ false);
break;
}
return mode;
continue;
newmode = drm_mode_std(dev, &edid->standard_timings[i],
- timing_level);
+ edid->revision, timing_level);
if (newmode) {
drm_mode_probed_add(connector, newmode);
modes++;
case EDID_DETAIL_MONITOR_CPDATA:
break;
case EDID_DETAIL_STD_MODES:
- /* Five modes per detailed section */
- for (j = 0; j < 5; i++) {
+ for (j = 0; j < 6; i++) {
struct std_timing *std;
struct drm_display_mode *newmode;
std = &data->data.timings[j];
newmode = drm_mode_std(dev, std,
+ edid->revision,
timing_level);
if (newmode) {
drm_mode_probed_add(connector, newmode);
struct drm_display_mode *newmode;
std = &data->data.timings[j];
- newmode = drm_mode_std(dev, std, timing_level);
+ newmode = drm_mode_std(dev, std,
+ edid->revision,
+ timing_level);
if (newmode) {
drm_mode_probed_add(connector, newmode);
modes++;
static LIST_HEAD(kernel_fb_helper_list);
+int drm_fb_helper_add_connector(struct drm_connector *connector)
+{
+ connector->fb_helper_private = kzalloc(sizeof(struct drm_fb_helper_connector), GFP_KERNEL);
+ if (!connector->fb_helper_private)
+ return -ENOMEM;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_fb_helper_add_connector);
+
+static int my_atoi(const char *name)
+{
+ int val = 0;
+
+ for (;; name++) {
+ switch (*name) {
+ case '0' ... '9':
+ val = 10*val+(*name-'0');
+ break;
+ default:
+ return val;
+ }
+ }
+}
+
+/**
+ * drm_fb_helper_connector_parse_command_line - parse command line for connector
+ * @connector - connector to parse line for
+ * @mode_option - per connector mode option
+ *
+ * This parses the connector specific then generic command lines for
+ * modes and options to configure the connector.
+ *
+ * This uses the same parameters as the fb modedb.c, except for extra
+ * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
+ *
+ * enable/enable Digital/disable bit at the end
+ */
+static bool drm_fb_helper_connector_parse_command_line(struct drm_connector *connector,
+ const char *mode_option)
+{
+ const char *name;
+ unsigned int namelen;
+ int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
+ unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
+ int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
+ int i;
+ enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
+ struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
+ struct drm_fb_helper_cmdline_mode *cmdline_mode;
+
+ if (!fb_help_conn)
+ return false;
+
+ cmdline_mode = &fb_help_conn->cmdline_mode;
+ if (!mode_option)
+ mode_option = fb_mode_option;
+
+ if (!mode_option) {
+ cmdline_mode->specified = false;
+ return false;
+ }
+
+ name = mode_option;
+ namelen = strlen(name);
+ for (i = namelen-1; i >= 0; i--) {
+ switch (name[i]) {
+ case '@':
+ namelen = i;
+ if (!refresh_specified && !bpp_specified &&
+ !yres_specified) {
+ refresh = my_atoi(&name[i+1]);
+ refresh_specified = 1;
+ if (cvt || rb)
+ cvt = 0;
+ } else
+ goto done;
+ break;
+ case '-':
+ namelen = i;
+ if (!bpp_specified && !yres_specified) {
+ bpp = my_atoi(&name[i+1]);
+ bpp_specified = 1;
+ if (cvt || rb)
+ cvt = 0;
+ } else
+ goto done;
+ break;
+ case 'x':
+ if (!yres_specified) {
+ yres = my_atoi(&name[i+1]);
+ yres_specified = 1;
+ } else
+ goto done;
+ case '0' ... '9':
+ break;
+ case 'M':
+ if (!yres_specified)
+ cvt = 1;
+ break;
+ case 'R':
+ if (!cvt)
+ rb = 1;
+ break;
+ case 'm':
+ if (!cvt)
+ margins = 1;
+ break;
+ case 'i':
+ if (!cvt)
+ interlace = 1;
+ break;
+ case 'e':
+ force = DRM_FORCE_ON;
+ break;
+ case 'D':
+ if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) ||
+ (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
+ force = DRM_FORCE_ON;
+ else
+ force = DRM_FORCE_ON_DIGITAL;
+ break;
+ case 'd':
+ force = DRM_FORCE_OFF;
+ break;
+ default:
+ goto done;
+ }
+ }
+ if (i < 0 && yres_specified) {
+ xres = my_atoi(name);
+ res_specified = 1;
+ }
+done:
+
+ DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
+ drm_get_connector_name(connector), xres, yres,
+ (refresh) ? refresh : 60, (rb) ? " reduced blanking" :
+ "", (margins) ? " with margins" : "", (interlace) ?
+ " interlaced" : "");
+
+ if (force) {
+ const char *s;
+ switch (force) {
+ case DRM_FORCE_OFF: s = "OFF"; break;
+ case DRM_FORCE_ON_DIGITAL: s = "ON - dig"; break;
+ default:
+ case DRM_FORCE_ON: s = "ON"; break;
+ }
+
+ DRM_INFO("forcing %s connector %s\n",
+ drm_get_connector_name(connector), s);
+ connector->force = force;
+ }
+
+ if (res_specified) {
+ cmdline_mode->specified = true;
+ cmdline_mode->xres = xres;
+ cmdline_mode->yres = yres;
+ }
+
+ if (refresh_specified) {
+ cmdline_mode->refresh_specified = true;
+ cmdline_mode->refresh = refresh;
+ }
+
+ if (bpp_specified) {
+ cmdline_mode->bpp_specified = true;
+ cmdline_mode->bpp = bpp;
+ }
+ cmdline_mode->rb = rb ? true : false;
+ cmdline_mode->cvt = cvt ? true : false;
+ cmdline_mode->interlace = interlace ? true : false;
+
+ return true;
+}
+
+int drm_fb_helper_parse_command_line(struct drm_device *dev)
+{
+ struct drm_connector *connector;
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ char *option = NULL;
+
+ /* do something on return - turn off connector maybe */
+ if (fb_get_options(drm_get_connector_name(connector), &option))
+ continue;
+
+ drm_fb_helper_connector_parse_command_line(connector, option);
+ }
+ return 0;
+}
+
bool drm_fb_helper_force_kernel_mode(void)
{
int i = 0;
}
EXPORT_SYMBOL(drm_fb_helper_restore);
+#ifdef CONFIG_MAGIC_SYSRQ
static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
{
drm_fb_helper_restore();
.help_msg = "force-fb(V)",
.action_msg = "Restore framebuffer console",
};
+#endif
static void drm_fb_helper_on(struct fb_info *info)
{
uint32_t fb_height,
uint32_t surface_width,
uint32_t surface_height,
+ uint32_t surface_depth,
+ uint32_t surface_bpp,
struct drm_framebuffer **fb_ptr))
{
struct drm_crtc *crtc;
struct drm_framebuffer *fb;
struct drm_mode_set *modeset = NULL;
struct drm_fb_helper *fb_helper;
+ uint32_t surface_depth = 24, surface_bpp = 32;
/* first up get a count of crtcs now in use and new min/maxes width/heights */
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
+
+ struct drm_fb_helper_cmdline_mode *cmdline_mode;
+
+ if (!fb_help_conn)
+ continue;
+
+ cmdline_mode = &fb_help_conn->cmdline_mode;
+
+ if (cmdline_mode->bpp_specified) {
+ switch (cmdline_mode->bpp) {
+ case 8:
+ surface_depth = surface_bpp = 8;
+ break;
+ case 15:
+ surface_depth = 15;
+ surface_bpp = 16;
+ break;
+ case 16:
+ surface_depth = surface_bpp = 16;
+ break;
+ case 24:
+ surface_depth = surface_bpp = 24;
+ break;
+ case 32:
+ surface_depth = 24;
+ surface_bpp = 32;
+ break;
+ }
+ break;
+ }
+ }
+
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
if (drm_helper_crtc_in_use(crtc)) {
if (crtc->desired_mode) {
/* do we have an fb already? */
if (list_empty(&dev->mode_config.fb_kernel_list)) {
ret = (*fb_create)(dev, fb_width, fb_height, surface_width,
- surface_height, &fb);
+ surface_height, surface_depth, surface_bpp,
+ &fb);
if (ret)
return -EINVAL;
new_fb = 1;
#define HV_FACTOR 1000
struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
int vdisplay, int vrefresh,
- bool reduced, bool interlaced)
+ bool reduced, bool interlaced, bool margins)
{
/* 1) top/bottom margin size (% of height) - default: 1.8, */
#define CVT_MARGIN_PERCENTAGE 18
/* Pixel Clock step (kHz) */
#define CVT_CLOCK_STEP 250
struct drm_display_mode *drm_mode;
- bool margins = false;
unsigned int vfieldrate, hperiod;
int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync;
int interlace;
static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
uint32_t fb_height, uint32_t surface_width,
uint32_t surface_height,
+ uint32_t surface_depth, uint32_t surface_bpp,
struct drm_framebuffer **fb_p)
{
struct fb_info *info;
mode_cmd.width = surface_width;
mode_cmd.height = surface_height;
- mode_cmd.bpp = 32;
+ mode_cmd.bpp = surface_bpp;
mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64);
- mode_cmd.depth = 24;
+ mode_cmd.depth = surface_depth;
size = mode_cmd.pitch * mode_cmd.height;
size = ALIGN(size, PAGE_SIZE);
--- /dev/null
+mkregtable
+*_reg_safe.h
+
#define VGA_RENDER_CONTROL 0x0300
#define VGA_VSTATUS_CNTL_MASK 0x00030000
-/* AVIVO disable VGA rendering */
-static inline void radeon_avivo_vga_render_disable(struct radeon_device *rdev)
-{
- u32 vga_render;
- vga_render = RREG32(VGA_RENDER_CONTROL);
- vga_render &= ~VGA_VSTATUS_CNTL_MASK;
- WREG32(VGA_RENDER_CONTROL, vga_render);
-}
-
#endif
void r100_cs_dump_packet(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt)
{
- struct radeon_cs_chunk *ib_chunk;
volatile uint32_t *ib;
unsigned i;
unsigned idx;
ib = p->ib->ptr;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
idx = pkt->idx;
for (i = 0; i <= (pkt->count + 1); i++, idx++) {
DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]);
idx, ib_chunk->length_dw);
return -EINVAL;
}
- header = ib_chunk->kdata[idx];
+ header = radeon_get_ib_value(p, idx);
pkt->idx = idx;
pkt->type = CP_PACKET_GET_TYPE(header);
pkt->count = CP_PACKET_GET_COUNT(header);
*/
int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
{
- struct radeon_cs_chunk *ib_chunk;
struct drm_mode_object *obj;
struct drm_crtc *crtc;
struct radeon_crtc *radeon_crtc;
int crtc_id;
int r;
uint32_t header, h_idx, reg;
+ volatile uint32_t *ib;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
+ ib = p->ib->ptr;
/* parse the wait until */
r = r100_cs_packet_parse(p, &waitreloc, p->idx);
return r;
}
- if (ib_chunk->kdata[waitreloc.idx + 1] != RADEON_WAIT_CRTC_VLINE) {
+ if (radeon_get_ib_value(p, waitreloc.idx + 1) != RADEON_WAIT_CRTC_VLINE) {
DRM_ERROR("vline wait had illegal wait until\n");
r = -EINVAL;
return r;
}
/* jump over the NOP */
- r = r100_cs_packet_parse(p, &p3reloc, p->idx);
+ r = r100_cs_packet_parse(p, &p3reloc, p->idx + waitreloc.count + 2);
if (r)
return r;
h_idx = p->idx - 2;
- p->idx += waitreloc.count;
- p->idx += p3reloc.count;
+ p->idx += waitreloc.count + 2;
+ p->idx += p3reloc.count + 2;
- header = ib_chunk->kdata[h_idx];
- crtc_id = ib_chunk->kdata[h_idx + 5];
- reg = ib_chunk->kdata[h_idx] >> 2;
+ header = radeon_get_ib_value(p, h_idx);
+ crtc_id = radeon_get_ib_value(p, h_idx + 5);
+ reg = header >> 2;
mutex_lock(&p->rdev->ddev->mode_config.mutex);
obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
if (!obj) {
if (!crtc->enabled) {
/* if the CRTC isn't enabled - we need to nop out the wait until */
- ib_chunk->kdata[h_idx + 2] = PACKET2(0);
- ib_chunk->kdata[h_idx + 3] = PACKET2(0);
+ ib[h_idx + 2] = PACKET2(0);
+ ib[h_idx + 3] = PACKET2(0);
} else if (crtc_id == 1) {
switch (reg) {
case AVIVO_D1MODE_VLINE_START_END:
- header &= R300_CP_PACKET0_REG_MASK;
+ header &= ~R300_CP_PACKET0_REG_MASK;
header |= AVIVO_D2MODE_VLINE_START_END >> 2;
break;
case RADEON_CRTC_GUI_TRIG_VLINE:
- header &= R300_CP_PACKET0_REG_MASK;
+ header &= ~R300_CP_PACKET0_REG_MASK;
header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2;
break;
default:
r = -EINVAL;
goto out;
}
- ib_chunk->kdata[h_idx] = header;
- ib_chunk->kdata[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1;
+ ib[h_idx] = header;
+ ib[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1;
}
out:
mutex_unlock(&p->rdev->ddev->mode_config.mutex);
int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc)
{
- struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_chunk *relocs_chunk;
struct radeon_cs_packet p3reloc;
unsigned idx;
return -EINVAL;
}
*cs_reloc = NULL;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
relocs_chunk = &p->chunks[p->chunk_relocs_idx];
r = r100_cs_packet_parse(p, &p3reloc, p->idx);
if (r) {
r100_cs_dump_packet(p, &p3reloc);
return -EINVAL;
}
- idx = ib_chunk->kdata[p3reloc.idx + 1];
+ idx = radeon_get_ib_value(p, p3reloc.idx + 1);
if (idx >= relocs_chunk->length_dw) {
DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
idx, relocs_chunk->length_dw);
struct radeon_cs_packet *pkt,
unsigned idx, unsigned reg)
{
- struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc;
struct r100_cs_track *track;
volatile uint32_t *ib;
int r;
int i, face;
u32 tile_flags = 0;
+ u32 idx_value;
ib = p->ib->ptr;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
track = (struct r100_cs_track *)p->track;
+ idx_value = radeon_get_ib_value(p, idx);
+
switch (reg) {
case RADEON_CRTC_GUI_TRIG_VLINE:
r = r100_cs_packet_parse_vline(p);
return r;
}
track->zb.robj = reloc->robj;
- track->zb.offset = ib_chunk->kdata[idx];
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ track->zb.offset = idx_value;
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break;
case RADEON_RB3D_COLOROFFSET:
r = r100_cs_packet_next_reloc(p, &reloc);
return r;
}
track->cb[0].robj = reloc->robj;
- track->cb[0].offset = ib_chunk->kdata[idx];
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ track->cb[0].offset = idx_value;
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break;
case RADEON_PP_TXOFFSET_0:
case RADEON_PP_TXOFFSET_1:
r100_cs_dump_packet(p, pkt);
return r;
}
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
track->textures[i].robj = reloc->robj;
break;
case RADEON_PP_CUBIC_OFFSET_T0_0:
r100_cs_dump_packet(p, pkt);
return r;
}
- track->textures[0].cube_info[i].offset = ib_chunk->kdata[idx];
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ track->textures[0].cube_info[i].offset = idx_value;
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
track->textures[0].cube_info[i].robj = reloc->robj;
break;
case RADEON_PP_CUBIC_OFFSET_T1_0:
r100_cs_dump_packet(p, pkt);
return r;
}
- track->textures[1].cube_info[i].offset = ib_chunk->kdata[idx];
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ track->textures[1].cube_info[i].offset = idx_value;
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
track->textures[1].cube_info[i].robj = reloc->robj;
break;
case RADEON_PP_CUBIC_OFFSET_T2_0:
r100_cs_dump_packet(p, pkt);
return r;
}
- track->textures[2].cube_info[i].offset = ib_chunk->kdata[idx];
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ track->textures[2].cube_info[i].offset = idx_value;
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
track->textures[2].cube_info[i].robj = reloc->robj;
break;
case RADEON_RE_WIDTH_HEIGHT:
- track->maxy = ((ib_chunk->kdata[idx] >> 16) & 0x7FF);
+ track->maxy = ((idx_value >> 16) & 0x7FF);
break;
case RADEON_RB3D_COLORPITCH:
r = r100_cs_packet_next_reloc(p, &reloc);
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
- tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
+ tmp = idx_value & ~(0x7 << 16);
tmp |= tile_flags;
ib[idx] = tmp;
- track->cb[0].pitch = ib_chunk->kdata[idx] & RADEON_COLORPITCH_MASK;
+ track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
break;
case RADEON_RB3D_DEPTHPITCH:
- track->zb.pitch = ib_chunk->kdata[idx] & RADEON_DEPTHPITCH_MASK;
+ track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
break;
case RADEON_RB3D_CNTL:
- switch ((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
+ switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
case 7:
case 8:
case 9:
break;
default:
DRM_ERROR("Invalid color buffer format (%d) !\n",
- ((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
+ ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
return -EINVAL;
}
- track->z_enabled = !!(ib_chunk->kdata[idx] & RADEON_Z_ENABLE);
+ track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
break;
case RADEON_RB3D_ZSTENCILCNTL:
- switch (ib_chunk->kdata[idx] & 0xf) {
+ switch (idx_value & 0xf) {
case 0:
track->zb.cpp = 2;
break;
r100_cs_dump_packet(p, pkt);
return r;
}
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break;
case RADEON_PP_CNTL:
{
- uint32_t temp = ib_chunk->kdata[idx] >> 4;
+ uint32_t temp = idx_value >> 4;
for (i = 0; i < track->num_texture; i++)
track->textures[i].enabled = !!(temp & (1 << i));
}
break;
case RADEON_SE_VF_CNTL:
- track->vap_vf_cntl = ib_chunk->kdata[idx];
+ track->vap_vf_cntl = idx_value;
break;
case RADEON_SE_VTX_FMT:
- track->vtx_size = r100_get_vtx_size(ib_chunk->kdata[idx]);
+ track->vtx_size = r100_get_vtx_size(idx_value);
break;
case RADEON_PP_TEX_SIZE_0:
case RADEON_PP_TEX_SIZE_1:
case RADEON_PP_TEX_SIZE_2:
i = (reg - RADEON_PP_TEX_SIZE_0) / 8;
- track->textures[i].width = (ib_chunk->kdata[idx] & RADEON_TEX_USIZE_MASK) + 1;
- track->textures[i].height = ((ib_chunk->kdata[idx] & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
+ track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1;
+ track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
break;
case RADEON_PP_TEX_PITCH_0:
case RADEON_PP_TEX_PITCH_1:
case RADEON_PP_TEX_PITCH_2:
i = (reg - RADEON_PP_TEX_PITCH_0) / 8;
- track->textures[i].pitch = ib_chunk->kdata[idx] + 32;
+ track->textures[i].pitch = idx_value + 32;
break;
case RADEON_PP_TXFILTER_0:
case RADEON_PP_TXFILTER_1:
case RADEON_PP_TXFILTER_2:
i = (reg - RADEON_PP_TXFILTER_0) / 24;
- track->textures[i].num_levels = ((ib_chunk->kdata[idx] & RADEON_MAX_MIP_LEVEL_MASK)
+ track->textures[i].num_levels = ((idx_value & RADEON_MAX_MIP_LEVEL_MASK)
>> RADEON_MAX_MIP_LEVEL_SHIFT);
- tmp = (ib_chunk->kdata[idx] >> 23) & 0x7;
+ tmp = (idx_value >> 23) & 0x7;
if (tmp == 2 || tmp == 6)
track->textures[i].roundup_w = false;
- tmp = (ib_chunk->kdata[idx] >> 27) & 0x7;
+ tmp = (idx_value >> 27) & 0x7;
if (tmp == 2 || tmp == 6)
track->textures[i].roundup_h = false;
break;
case RADEON_PP_TXFORMAT_1:
case RADEON_PP_TXFORMAT_2:
i = (reg - RADEON_PP_TXFORMAT_0) / 24;
- if (ib_chunk->kdata[idx] & RADEON_TXFORMAT_NON_POWER2) {
+ if (idx_value & RADEON_TXFORMAT_NON_POWER2) {
track->textures[i].use_pitch = 1;
} else {
track->textures[i].use_pitch = 0;
- track->textures[i].width = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
- track->textures[i].height = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
+ track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
+ track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
}
- if (ib_chunk->kdata[idx] & RADEON_TXFORMAT_CUBIC_MAP_ENABLE)
+ if (idx_value & RADEON_TXFORMAT_CUBIC_MAP_ENABLE)
track->textures[i].tex_coord_type = 2;
- switch ((ib_chunk->kdata[idx] & RADEON_TXFORMAT_FORMAT_MASK)) {
+ switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) {
case RADEON_TXFORMAT_I8:
case RADEON_TXFORMAT_RGB332:
case RADEON_TXFORMAT_Y8:
track->textures[i].cpp = 4;
break;
}
- track->textures[i].cube_info[4].width = 1 << ((ib_chunk->kdata[idx] >> 16) & 0xf);
- track->textures[i].cube_info[4].height = 1 << ((ib_chunk->kdata[idx] >> 20) & 0xf);
+ track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
+ track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
break;
case RADEON_PP_CUBIC_FACES_0:
case RADEON_PP_CUBIC_FACES_1:
case RADEON_PP_CUBIC_FACES_2:
- tmp = ib_chunk->kdata[idx];
+ tmp = idx_value;
i = (reg - RADEON_PP_CUBIC_FACES_0) / 4;
for (face = 0; face < 4; face++) {
track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
struct radeon_cs_packet *pkt,
struct radeon_object *robj)
{
- struct radeon_cs_chunk *ib_chunk;
unsigned idx;
-
- ib_chunk = &p->chunks[p->chunk_ib_idx];
+ u32 value;
idx = pkt->idx + 1;
- if ((ib_chunk->kdata[idx+2] + 1) > radeon_object_size(robj)) {
+ value = radeon_get_ib_value(p, idx + 2);
+ if ((value + 1) > radeon_object_size(robj)) {
DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER "
"(need %u have %lu) !\n",
- ib_chunk->kdata[idx+2] + 1,
+ value + 1,
radeon_object_size(robj));
return -EINVAL;
}
static int r100_packet3_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt)
{
- struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc;
struct r100_cs_track *track;
unsigned idx;
- unsigned i, c;
volatile uint32_t *ib;
int r;
ib = p->ib->ptr;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
idx = pkt->idx + 1;
track = (struct r100_cs_track *)p->track;
switch (pkt->opcode) {
case PACKET3_3D_LOAD_VBPNTR:
- c = ib_chunk->kdata[idx++];
- track->num_arrays = c;
- for (i = 0; i < (c - 1); i += 2, idx += 3) {
- r = r100_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("No reloc for packet3 %d\n",
- pkt->opcode);
- r100_cs_dump_packet(p, pkt);
- return r;
- }
- ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
- track->arrays[i + 0].robj = reloc->robj;
- track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8;
- track->arrays[i + 0].esize &= 0x7F;
- r = r100_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("No reloc for packet3 %d\n",
- pkt->opcode);
- r100_cs_dump_packet(p, pkt);
- return r;
- }
- ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset);
- track->arrays[i + 1].robj = reloc->robj;
- track->arrays[i + 1].esize = ib_chunk->kdata[idx] >> 24;
- track->arrays[i + 1].esize &= 0x7F;
- }
- if (c & 1) {
- r = r100_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("No reloc for packet3 %d\n",
- pkt->opcode);
- r100_cs_dump_packet(p, pkt);
- return r;
- }
- ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
- track->arrays[i + 0].robj = reloc->robj;
- track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8;
- track->arrays[i + 0].esize &= 0x7F;
- }
+ r = r100_packet3_load_vbpntr(p, pkt, idx);
+ if (r)
+ return r;
break;
case PACKET3_INDX_BUFFER:
r = r100_cs_packet_next_reloc(p, &reloc);
r100_cs_dump_packet(p, pkt);
return r;
}
- ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
+ ib[idx+1] = radeon_get_ib_value(p, idx+1) + ((u32)reloc->lobj.gpu_offset);
r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj);
if (r) {
return r;
r100_cs_dump_packet(p, pkt);
return r;
}
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ ib[idx] = radeon_get_ib_value(p, idx) + ((u32)reloc->lobj.gpu_offset);
track->num_arrays = 1;
- track->vtx_size = r100_get_vtx_size(ib_chunk->kdata[idx+2]);
+ track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 2));
track->arrays[0].robj = reloc->robj;
track->arrays[0].esize = track->vtx_size;
- track->max_indx = ib_chunk->kdata[idx+1];
+ track->max_indx = radeon_get_ib_value(p, idx+1);
- track->vap_vf_cntl = ib_chunk->kdata[idx+3];
+ track->vap_vf_cntl = radeon_get_ib_value(p, idx+3);
track->immd_dwords = pkt->count - 1;
r = r100_cs_track_check(p->rdev, track);
if (r)
return r;
break;
case PACKET3_3D_DRAW_IMMD:
- if (((ib_chunk->kdata[idx+1] >> 4) & 0x3) != 3) {
+ if (((radeon_get_ib_value(p, idx + 1) >> 4) & 0x3) != 3) {
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
return -EINVAL;
}
- track->vap_vf_cntl = ib_chunk->kdata[idx+1];
+ track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
track->immd_dwords = pkt->count - 1;
r = r100_cs_track_check(p->rdev, track);
if (r)
break;
/* triggers drawing using in-packet vertex data */
case PACKET3_3D_DRAW_IMMD_2:
- if (((ib_chunk->kdata[idx] >> 4) & 0x3) != 3) {
+ if (((radeon_get_ib_value(p, idx) >> 4) & 0x3) != 3) {
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
return -EINVAL;
}
- track->vap_vf_cntl = ib_chunk->kdata[idx];
+ track->vap_vf_cntl = radeon_get_ib_value(p, idx);
track->immd_dwords = pkt->count;
r = r100_cs_track_check(p->rdev, track);
if (r)
break;
/* triggers drawing using in-packet vertex data */
case PACKET3_3D_DRAW_VBUF_2:
- track->vap_vf_cntl = ib_chunk->kdata[idx];
+ track->vap_vf_cntl = radeon_get_ib_value(p, idx);
r = r100_cs_track_check(p->rdev, track);
if (r)
return r;
break;
/* triggers drawing of vertex buffers setup elsewhere */
case PACKET3_3D_DRAW_INDX_2:
- track->vap_vf_cntl = ib_chunk->kdata[idx];
+ track->vap_vf_cntl = radeon_get_ib_value(p, idx);
r = r100_cs_track_check(p->rdev, track);
if (r)
return r;
break;
/* triggers drawing using indices to vertex buffer */
case PACKET3_3D_DRAW_VBUF:
- track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
+ track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
r = r100_cs_track_check(p->rdev, track);
if (r)
return r;
break;
/* triggers drawing of vertex buffers setup elsewhere */
case PACKET3_3D_DRAW_INDX:
- track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
+ track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
r = r100_cs_track_check(p->rdev, track);
if (r)
return r;
struct radeon_cs_packet *pkt,
unsigned idx, unsigned reg);
+
+
static inline int r100_reloc_pitch_offset(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt,
unsigned idx,
u32 tile_flags = 0;
u32 tmp;
struct radeon_cs_reloc *reloc;
- struct radeon_cs_chunk *ib_chunk;
-
- ib_chunk = &p->chunks[p->chunk_ib_idx];
+ u32 value;
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
r100_cs_dump_packet(p, pkt);
return r;
}
- tmp = ib_chunk->kdata[idx] & 0x003fffff;
+ value = radeon_get_ib_value(p, idx);
+ tmp = value & 0x003fffff;
tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
}
tmp |= tile_flags;
- p->ib->ptr[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp;
+ p->ib->ptr[idx] = (value & 0x3fc00000) | tmp;
return 0;
}
+
+static inline int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
+ struct radeon_cs_packet *pkt,
+ int idx)
+{
+ unsigned c, i;
+ struct radeon_cs_reloc *reloc;
+ struct r100_cs_track *track;
+ int r = 0;
+ volatile uint32_t *ib;
+ u32 idx_value;
+
+ ib = p->ib->ptr;
+ track = (struct r100_cs_track *)p->track;
+ c = radeon_get_ib_value(p, idx++) & 0x1F;
+ track->num_arrays = c;
+ for (i = 0; i < (c - 1); i+=2, idx+=3) {
+ r = r100_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("No reloc for packet3 %d\n",
+ pkt->opcode);
+ r100_cs_dump_packet(p, pkt);
+ return r;
+ }
+ idx_value = radeon_get_ib_value(p, idx);
+ ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
+
+ track->arrays[i + 0].esize = idx_value >> 8;
+ track->arrays[i + 0].robj = reloc->robj;
+ track->arrays[i + 0].esize &= 0x7F;
+ r = r100_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("No reloc for packet3 %d\n",
+ pkt->opcode);
+ r100_cs_dump_packet(p, pkt);
+ return r;
+ }
+ ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset);
+ track->arrays[i + 1].robj = reloc->robj;
+ track->arrays[i + 1].esize = idx_value >> 24;
+ track->arrays[i + 1].esize &= 0x7F;
+ }
+ if (c & 1) {
+ r = r100_cs_packet_next_reloc(p, &reloc);
+ if (r) {
+ DRM_ERROR("No reloc for packet3 %d\n",
+ pkt->opcode);
+ r100_cs_dump_packet(p, pkt);
+ return r;
+ }
+ idx_value = radeon_get_ib_value(p, idx);
+ ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
+ track->arrays[i + 0].robj = reloc->robj;
+ track->arrays[i + 0].esize = idx_value >> 8;
+ track->arrays[i + 0].esize &= 0x7F;
+ }
+ return r;
+}
struct radeon_cs_packet *pkt,
unsigned idx, unsigned reg)
{
- struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc;
struct r100_cs_track *track;
volatile uint32_t *ib;
int i;
int face;
u32 tile_flags = 0;
+ u32 idx_value;
ib = p->ib->ptr;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
track = (struct r100_cs_track *)p->track;
-
+ idx_value = radeon_get_ib_value(p, idx);
switch (reg) {
case RADEON_CRTC_GUI_TRIG_VLINE:
r = r100_cs_packet_parse_vline(p);
return r;
}
track->zb.robj = reloc->robj;
- track->zb.offset = ib_chunk->kdata[idx];
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ track->zb.offset = idx_value;
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break;
case RADEON_RB3D_COLOROFFSET:
r = r100_cs_packet_next_reloc(p, &reloc);
return r;
}
track->cb[0].robj = reloc->robj;
- track->cb[0].offset = ib_chunk->kdata[idx];
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ track->cb[0].offset = idx_value;
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break;
case R200_PP_TXOFFSET_0:
case R200_PP_TXOFFSET_1:
r100_cs_dump_packet(p, pkt);
return r;
}
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
track->textures[i].robj = reloc->robj;
break;
case R200_PP_CUBIC_OFFSET_F1_0:
r100_cs_dump_packet(p, pkt);
return r;
}
- track->textures[i].cube_info[face - 1].offset = ib_chunk->kdata[idx];
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ track->textures[i].cube_info[face - 1].offset = idx_value;
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
track->textures[i].cube_info[face - 1].robj = reloc->robj;
break;
case RADEON_RE_WIDTH_HEIGHT:
- track->maxy = ((ib_chunk->kdata[idx] >> 16) & 0x7FF);
+ track->maxy = ((idx_value >> 16) & 0x7FF);
break;
case RADEON_RB3D_COLORPITCH:
r = r100_cs_packet_next_reloc(p, &reloc);
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
- tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
+ tmp = idx_value & ~(0x7 << 16);
tmp |= tile_flags;
ib[idx] = tmp;
- track->cb[0].pitch = ib_chunk->kdata[idx] & RADEON_COLORPITCH_MASK;
+ track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
break;
case RADEON_RB3D_DEPTHPITCH:
- track->zb.pitch = ib_chunk->kdata[idx] & RADEON_DEPTHPITCH_MASK;
+ track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
break;
case RADEON_RB3D_CNTL:
- switch ((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
+ switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
case 7:
case 8:
case 9:
break;
default:
DRM_ERROR("Invalid color buffer format (%d) !\n",
- ((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
+ ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
return -EINVAL;
}
- if (ib_chunk->kdata[idx] & RADEON_DEPTHXY_OFFSET_ENABLE) {
+ if (idx_value & RADEON_DEPTHXY_OFFSET_ENABLE) {
DRM_ERROR("No support for depth xy offset in kms\n");
return -EINVAL;
}
- track->z_enabled = !!(ib_chunk->kdata[idx] & RADEON_Z_ENABLE);
+ track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
break;
case RADEON_RB3D_ZSTENCILCNTL:
- switch (ib_chunk->kdata[idx] & 0xf) {
+ switch (idx_value & 0xf) {
case 0:
track->zb.cpp = 2;
break;
r100_cs_dump_packet(p, pkt);
return r;
}
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break;
case RADEON_PP_CNTL:
{
- uint32_t temp = ib_chunk->kdata[idx] >> 4;
+ uint32_t temp = idx_value >> 4;
for (i = 0; i < track->num_texture; i++)
track->textures[i].enabled = !!(temp & (1 << i));
}
break;
case RADEON_SE_VF_CNTL:
- track->vap_vf_cntl = ib_chunk->kdata[idx];
+ track->vap_vf_cntl = idx_value;
break;
case 0x210c:
/* VAP_VF_MAX_VTX_INDX */
- track->max_indx = ib_chunk->kdata[idx] & 0x00FFFFFFUL;
+ track->max_indx = idx_value & 0x00FFFFFFUL;
break;
case R200_SE_VTX_FMT_0:
- track->vtx_size = r200_get_vtx_size_0(ib_chunk->kdata[idx]);
+ track->vtx_size = r200_get_vtx_size_0(idx_value);
break;
case R200_SE_VTX_FMT_1:
- track->vtx_size += r200_get_vtx_size_1(ib_chunk->kdata[idx]);
+ track->vtx_size += r200_get_vtx_size_1(idx_value);
break;
case R200_PP_TXSIZE_0:
case R200_PP_TXSIZE_1:
case R200_PP_TXSIZE_4:
case R200_PP_TXSIZE_5:
i = (reg - R200_PP_TXSIZE_0) / 32;
- track->textures[i].width = (ib_chunk->kdata[idx] & RADEON_TEX_USIZE_MASK) + 1;
- track->textures[i].height = ((ib_chunk->kdata[idx] & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
+ track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1;
+ track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
break;
case R200_PP_TXPITCH_0:
case R200_PP_TXPITCH_1:
case R200_PP_TXPITCH_4:
case R200_PP_TXPITCH_5:
i = (reg - R200_PP_TXPITCH_0) / 32;
- track->textures[i].pitch = ib_chunk->kdata[idx] + 32;
+ track->textures[i].pitch = idx_value + 32;
break;
case R200_PP_TXFILTER_0:
case R200_PP_TXFILTER_1:
case R200_PP_TXFILTER_4:
case R200_PP_TXFILTER_5:
i = (reg - R200_PP_TXFILTER_0) / 32;
- track->textures[i].num_levels = ((ib_chunk->kdata[idx] & R200_MAX_MIP_LEVEL_MASK)
+ track->textures[i].num_levels = ((idx_value & R200_MAX_MIP_LEVEL_MASK)
>> R200_MAX_MIP_LEVEL_SHIFT);
- tmp = (ib_chunk->kdata[idx] >> 23) & 0x7;
+ tmp = (idx_value >> 23) & 0x7;
if (tmp == 2 || tmp == 6)
track->textures[i].roundup_w = false;
- tmp = (ib_chunk->kdata[idx] >> 27) & 0x7;
+ tmp = (idx_value >> 27) & 0x7;
if (tmp == 2 || tmp == 6)
track->textures[i].roundup_h = false;
break;
case R200_PP_TXFORMAT_X_4:
case R200_PP_TXFORMAT_X_5:
i = (reg - R200_PP_TXFORMAT_X_0) / 32;
- track->textures[i].txdepth = ib_chunk->kdata[idx] & 0x7;
- tmp = (ib_chunk->kdata[idx] >> 16) & 0x3;
+ track->textures[i].txdepth = idx_value & 0x7;
+ tmp = (idx_value >> 16) & 0x3;
/* 2D, 3D, CUBE */
switch (tmp) {
case 0:
case R200_PP_TXFORMAT_4:
case R200_PP_TXFORMAT_5:
i = (reg - R200_PP_TXFORMAT_0) / 32;
- if (ib_chunk->kdata[idx] & R200_TXFORMAT_NON_POWER2) {
+ if (idx_value & R200_TXFORMAT_NON_POWER2) {
track->textures[i].use_pitch = 1;
} else {
track->textures[i].use_pitch = 0;
- track->textures[i].width = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
- track->textures[i].height = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
+ track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
+ track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
}
- switch ((ib_chunk->kdata[idx] & RADEON_TXFORMAT_FORMAT_MASK)) {
+ switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) {
case R200_TXFORMAT_I8:
case R200_TXFORMAT_RGB332:
case R200_TXFORMAT_Y8:
track->textures[i].cpp = 4;
break;
}
- track->textures[i].cube_info[4].width = 1 << ((ib_chunk->kdata[idx] >> 16) & 0xf);
- track->textures[i].cube_info[4].height = 1 << ((ib_chunk->kdata[idx] >> 20) & 0xf);
+ track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
+ track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
break;
case R200_PP_CUBIC_FACES_0:
case R200_PP_CUBIC_FACES_1:
case R200_PP_CUBIC_FACES_3:
case R200_PP_CUBIC_FACES_4:
case R200_PP_CUBIC_FACES_5:
- tmp = ib_chunk->kdata[idx];
+ tmp = idx_value;
i = (reg - R200_PP_CUBIC_FACES_0) / 32;
for (face = 0; face < 4; face++) {
track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
struct radeon_cs_packet *pkt,
unsigned idx, unsigned reg)
{
- struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc;
struct r100_cs_track *track;
volatile uint32_t *ib;
uint32_t tmp, tile_flags = 0;
unsigned i;
int r;
+ u32 idx_value;
ib = p->ib->ptr;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
track = (struct r100_cs_track *)p->track;
+ idx_value = radeon_get_ib_value(p, idx);
+
switch(reg) {
case AVIVO_D1MODE_VLINE_START_END:
case RADEON_CRTC_GUI_TRIG_VLINE:
return r;
}
track->cb[i].robj = reloc->robj;
- track->cb[i].offset = ib_chunk->kdata[idx];
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ track->cb[i].offset = idx_value;
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break;
case R300_ZB_DEPTHOFFSET:
r = r100_cs_packet_next_reloc(p, &reloc);
return r;
}
track->zb.robj = reloc->robj;
- track->zb.offset = ib_chunk->kdata[idx];
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ track->zb.offset = idx_value;
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break;
case R300_TX_OFFSET_0:
case R300_TX_OFFSET_0+4:
r100_cs_dump_packet(p, pkt);
return r;
}
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
track->textures[i].robj = reloc->robj;
break;
/* Tracked registers */
case 0x2084:
/* VAP_VF_CNTL */
- track->vap_vf_cntl = ib_chunk->kdata[idx];
+ track->vap_vf_cntl = idx_value;
break;
case 0x20B4:
/* VAP_VTX_SIZE */
- track->vtx_size = ib_chunk->kdata[idx] & 0x7F;
+ track->vtx_size = idx_value & 0x7F;
break;
case 0x2134:
/* VAP_VF_MAX_VTX_INDX */
- track->max_indx = ib_chunk->kdata[idx] & 0x00FFFFFFUL;
+ track->max_indx = idx_value & 0x00FFFFFFUL;
break;
case 0x43E4:
/* SC_SCISSOR1 */
- track->maxy = ((ib_chunk->kdata[idx] >> 13) & 0x1FFF) + 1;
+ track->maxy = ((idx_value >> 13) & 0x1FFF) + 1;
if (p->rdev->family < CHIP_RV515) {
track->maxy -= 1440;
}
break;
case 0x4E00:
/* RB3D_CCTL */
- track->num_cb = ((ib_chunk->kdata[idx] >> 5) & 0x3) + 1;
+ track->num_cb = ((idx_value >> 5) & 0x3) + 1;
break;
case 0x4E38:
case 0x4E3C:
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= R300_COLOR_MICROTILE_ENABLE;
- tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
+ tmp = idx_value & ~(0x7 << 16);
tmp |= tile_flags;
ib[idx] = tmp;
i = (reg - 0x4E38) >> 2;
- track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE;
- switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) {
+ track->cb[i].pitch = idx_value & 0x3FFE;
+ switch (((idx_value >> 21) & 0xF)) {
case 9:
case 11:
case 12:
break;
default:
DRM_ERROR("Invalid color buffer format (%d) !\n",
- ((ib_chunk->kdata[idx] >> 21) & 0xF));
+ ((idx_value >> 21) & 0xF));
return -EINVAL;
}
break;
case 0x4F00:
/* ZB_CNTL */
- if (ib_chunk->kdata[idx] & 2) {
+ if (idx_value & 2) {
track->z_enabled = true;
} else {
track->z_enabled = false;
break;
case 0x4F10:
/* ZB_FORMAT */
- switch ((ib_chunk->kdata[idx] & 0xF)) {
+ switch ((idx_value & 0xF)) {
case 0:
case 1:
track->zb.cpp = 2;
break;
default:
DRM_ERROR("Invalid z buffer format (%d) !\n",
- (ib_chunk->kdata[idx] & 0xF));
+ (idx_value & 0xF));
return -EINVAL;
}
break;
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= R300_DEPTHMICROTILE_TILED;;
- tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
+ tmp = idx_value & ~(0x7 << 16);
tmp |= tile_flags;
ib[idx] = tmp;
- track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC;
+ track->zb.pitch = idx_value & 0x3FFC;
break;
case 0x4104:
for (i = 0; i < 16; i++) {
bool enabled;
- enabled = !!(ib_chunk->kdata[idx] & (1 << i));
+ enabled = !!(idx_value & (1 << i));
track->textures[i].enabled = enabled;
}
break;
case 0x44FC:
/* TX_FORMAT1_[0-15] */
i = (reg - 0x44C0) >> 2;
- tmp = (ib_chunk->kdata[idx] >> 25) & 0x3;
+ tmp = (idx_value >> 25) & 0x3;
track->textures[i].tex_coord_type = tmp;
- switch ((ib_chunk->kdata[idx] & 0x1F)) {
+ switch ((idx_value & 0x1F)) {
case R300_TX_FORMAT_X8:
case R300_TX_FORMAT_Y4X4:
case R300_TX_FORMAT_Z3Y3X2:
break;
default:
DRM_ERROR("Invalid texture format %u\n",
- (ib_chunk->kdata[idx] & 0x1F));
+ (idx_value & 0x1F));
return -EINVAL;
break;
}
case 0x443C:
/* TX_FILTER0_[0-15] */
i = (reg - 0x4400) >> 2;
- tmp = ib_chunk->kdata[idx] & 0x7;
+ tmp = idx_value & 0x7;
if (tmp == 2 || tmp == 4 || tmp == 6) {
track->textures[i].roundup_w = false;
}
- tmp = (ib_chunk->kdata[idx] >> 3) & 0x7;
+ tmp = (idx_value >> 3) & 0x7;
if (tmp == 2 || tmp == 4 || tmp == 6) {
track->textures[i].roundup_h = false;
}
case 0x453C:
/* TX_FORMAT2_[0-15] */
i = (reg - 0x4500) >> 2;
- tmp = ib_chunk->kdata[idx] & 0x3FFF;
+ tmp = idx_value & 0x3FFF;
track->textures[i].pitch = tmp + 1;
if (p->rdev->family >= CHIP_RV515) {
- tmp = ((ib_chunk->kdata[idx] >> 15) & 1) << 11;
+ tmp = ((idx_value >> 15) & 1) << 11;
track->textures[i].width_11 = tmp;
- tmp = ((ib_chunk->kdata[idx] >> 16) & 1) << 11;
+ tmp = ((idx_value >> 16) & 1) << 11;
track->textures[i].height_11 = tmp;
}
break;
case 0x44BC:
/* TX_FORMAT0_[0-15] */
i = (reg - 0x4480) >> 2;
- tmp = ib_chunk->kdata[idx] & 0x7FF;
+ tmp = idx_value & 0x7FF;
track->textures[i].width = tmp + 1;
- tmp = (ib_chunk->kdata[idx] >> 11) & 0x7FF;
+ tmp = (idx_value >> 11) & 0x7FF;
track->textures[i].height = tmp + 1;
- tmp = (ib_chunk->kdata[idx] >> 26) & 0xF;
+ tmp = (idx_value >> 26) & 0xF;
track->textures[i].num_levels = tmp;
- tmp = ib_chunk->kdata[idx] & (1 << 31);
+ tmp = idx_value & (1 << 31);
track->textures[i].use_pitch = !!tmp;
- tmp = (ib_chunk->kdata[idx] >> 22) & 0xF;
+ tmp = (idx_value >> 22) & 0xF;
track->textures[i].txdepth = tmp;
break;
case R300_ZB_ZPASS_ADDR:
r100_cs_dump_packet(p, pkt);
return r;
}
- ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+ ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
break;
case 0x4be8:
/* valid register only on RV530 */
static int r300_packet3_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt)
{
- struct radeon_cs_chunk *ib_chunk;
-
struct radeon_cs_reloc *reloc;
struct r100_cs_track *track;
volatile uint32_t *ib;
unsigned idx;
- unsigned i, c;
int r;
ib = p->ib->ptr;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
idx = pkt->idx + 1;
track = (struct r100_cs_track *)p->track;
switch(pkt->opcode) {
case PACKET3_3D_LOAD_VBPNTR:
- c = ib_chunk->kdata[idx++] & 0x1F;
- track->num_arrays = c;
- for (i = 0; i < (c - 1); i+=2, idx+=3) {
- r = r100_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("No reloc for packet3 %d\n",
- pkt->opcode);
- r100_cs_dump_packet(p, pkt);
- return r;
- }
- ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
- track->arrays[i + 0].robj = reloc->robj;
- track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8;
- track->arrays[i + 0].esize &= 0x7F;
- r = r100_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("No reloc for packet3 %d\n",
- pkt->opcode);
- r100_cs_dump_packet(p, pkt);
- return r;
- }
- ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset);
- track->arrays[i + 1].robj = reloc->robj;
- track->arrays[i + 1].esize = ib_chunk->kdata[idx] >> 24;
- track->arrays[i + 1].esize &= 0x7F;
- }
- if (c & 1) {
- r = r100_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("No reloc for packet3 %d\n",
- pkt->opcode);
- r100_cs_dump_packet(p, pkt);
- return r;
- }
- ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
- track->arrays[i + 0].robj = reloc->robj;
- track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8;
- track->arrays[i + 0].esize &= 0x7F;
- }
+ r = r100_packet3_load_vbpntr(p, pkt, idx);
+ if (r)
+ return r;
break;
case PACKET3_INDX_BUFFER:
r = r100_cs_packet_next_reloc(p, &reloc);
r100_cs_dump_packet(p, pkt);
return r;
}
- ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
+ ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset);
r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj);
if (r) {
return r;
/* Number of dwords is vtx_size * (num_vertices - 1)
* PRIM_WALK must be equal to 3 vertex data in embedded
* in cmd stream */
- if (((ib_chunk->kdata[idx+1] >> 4) & 0x3) != 3) {
+ if (((radeon_get_ib_value(p, idx + 1) >> 4) & 0x3) != 3) {
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
return -EINVAL;
}
- track->vap_vf_cntl = ib_chunk->kdata[idx+1];
+ track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
track->immd_dwords = pkt->count - 1;
r = r100_cs_track_check(p->rdev, track);
if (r) {
/* Number of dwords is vtx_size * (num_vertices - 1)
* PRIM_WALK must be equal to 3 vertex data in embedded
* in cmd stream */
- if (((ib_chunk->kdata[idx] >> 4) & 0x3) != 3) {
+ if (((radeon_get_ib_value(p, idx) >> 4) & 0x3) != 3) {
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
return -EINVAL;
}
- track->vap_vf_cntl = ib_chunk->kdata[idx];
+ track->vap_vf_cntl = radeon_get_ib_value(p, idx);
track->immd_dwords = pkt->count;
r = r100_cs_track_check(p->rdev, track);
if (r) {
}
break;
case PACKET3_3D_DRAW_VBUF:
- track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
+ track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
r = r100_cs_track_check(p->rdev, track);
if (r) {
return r;
}
break;
case PACKET3_3D_DRAW_VBUF_2:
- track->vap_vf_cntl = ib_chunk->kdata[idx];
+ track->vap_vf_cntl = radeon_get_ib_value(p, idx);
r = r100_cs_track_check(p->rdev, track);
if (r) {
return r;
}
break;
case PACKET3_3D_DRAW_INDX:
- track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
+ track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
r = r100_cs_track_check(p->rdev, track);
if (r) {
return r;
}
break;
case PACKET3_3D_DRAW_INDX_2:
- track->vap_vf_cntl = ib_chunk->kdata[idx];
+ track->vap_vf_cntl = radeon_get_ib_value(p, idx);
r = r100_cs_track_check(p->rdev, track);
if (r) {
return r;
#define AVIVO_D1MODE_VBLANK_STATUS 0x6534
# define AVIVO_VBLANK_ACK (1 << 4)
#define AVIVO_D1MODE_VLINE_START_END 0x6538
+#define AVIVO_D1MODE_VLINE_STATUS 0x653c
+# define AVIVO_D1MODE_VLINE_STAT (1 << 12)
#define AVIVO_DxMODE_INT_MASK 0x6540
# define AVIVO_D1MODE_INT_MASK (1 << 0)
# define AVIVO_D2MODE_INT_MASK (1 << 8)
#define AVIVO_D2MODE_VBLANK_STATUS 0x6d34
#define AVIVO_D2MODE_VLINE_START_END 0x6d38
+#define AVIVO_D2MODE_VLINE_STATUS 0x6d3c
#define AVIVO_D2MODE_VIEWPORT_START 0x6d80
#define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84
#define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88
* Jerome Glisse
*/
#include "drmP.h"
-#include "radeon_reg.h"
#include "radeon.h"
+#include "atom.h"
+#include "r520d.h"
-/* r520,rv530,rv560,rv570,r580 depends on : */
-void r100_hdp_reset(struct radeon_device *rdev);
-void r420_pipes_init(struct radeon_device *rdev);
-void rs600_mc_disable_clients(struct radeon_device *rdev);
-void rs600_disable_vga(struct radeon_device *rdev);
-int rv515_debugfs_pipes_info_init(struct radeon_device *rdev);
-int rv515_debugfs_ga_info_init(struct radeon_device *rdev);
+/* This files gather functions specifics to: r520,rv530,rv560,rv570,r580 */
-/* This files gather functions specifics to:
- * r520,rv530,rv560,rv570,r580
- *
- * Some of these functions might be used by newer ASICs.
- */
-void r520_gpu_init(struct radeon_device *rdev);
-int r520_mc_wait_for_idle(struct radeon_device *rdev);
-
-
-/*
- * MC
- */
-int r520_mc_init(struct radeon_device *rdev)
-{
- uint32_t tmp;
- int r;
-
- if (r100_debugfs_rbbm_init(rdev)) {
- DRM_ERROR("Failed to register debugfs file for RBBM !\n");
- }
- if (rv515_debugfs_pipes_info_init(rdev)) {
- DRM_ERROR("Failed to register debugfs file for pipes !\n");
- }
- if (rv515_debugfs_ga_info_init(rdev)) {
- DRM_ERROR("Failed to register debugfs file for pipes !\n");
- }
-
- r520_gpu_init(rdev);
- rv370_pcie_gart_disable(rdev);
-
- /* Setup GPU memory space */
- rdev->mc.vram_location = 0xFFFFFFFFUL;
- rdev->mc.gtt_location = 0xFFFFFFFFUL;
- if (rdev->flags & RADEON_IS_AGP) {
- r = radeon_agp_init(rdev);
- if (r) {
- printk(KERN_WARNING "[drm] Disabling AGP\n");
- rdev->flags &= ~RADEON_IS_AGP;
- rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
- } else {
- rdev->mc.gtt_location = rdev->mc.agp_base;
- }
- }
- r = radeon_mc_setup(rdev);
- if (r) {
- return r;
- }
-
- /* Program GPU memory space */
- rs600_mc_disable_clients(rdev);
- if (r520_mc_wait_for_idle(rdev)) {
- printk(KERN_WARNING "Failed to wait MC idle while "
- "programming pipes. Bad things might happen.\n");
- }
- /* Write VRAM size in case we are limiting it */
- WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
- tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
- tmp = REG_SET(R520_MC_FB_TOP, tmp >> 16);
- tmp |= REG_SET(R520_MC_FB_START, rdev->mc.vram_location >> 16);
- WREG32_MC(R520_MC_FB_LOCATION, tmp);
- WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16);
- WREG32(0x310, rdev->mc.vram_location);
- if (rdev->flags & RADEON_IS_AGP) {
- tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
- tmp = REG_SET(R520_MC_AGP_TOP, tmp >> 16);
- tmp |= REG_SET(R520_MC_AGP_START, rdev->mc.gtt_location >> 16);
- WREG32_MC(R520_MC_AGP_LOCATION, tmp);
- WREG32_MC(R520_MC_AGP_BASE, rdev->mc.agp_base);
- WREG32_MC(R520_MC_AGP_BASE_2, 0);
- } else {
- WREG32_MC(R520_MC_AGP_LOCATION, 0x0FFFFFFF);
- WREG32_MC(R520_MC_AGP_BASE, 0);
- WREG32_MC(R520_MC_AGP_BASE_2, 0);
- }
- return 0;
-}
-
-void r520_mc_fini(struct radeon_device *rdev)
-{
-}
-
-
-/*
- * Global GPU functions
- */
-void r520_errata(struct radeon_device *rdev)
-{
- rdev->pll_errata = 0;
-}
-
-int r520_mc_wait_for_idle(struct radeon_device *rdev)
+static int r520_mc_wait_for_idle(struct radeon_device *rdev)
{
unsigned i;
uint32_t tmp;
return -1;
}
-void r520_gpu_init(struct radeon_device *rdev)
+static void r520_gpu_init(struct radeon_device *rdev)
{
unsigned pipe_select_current, gb_pipe_select, tmp;
r100_hdp_reset(rdev);
- rs600_disable_vga(rdev);
+ rv515_vga_render_disable(rdev);
/*
* DST_PIPE_CONFIG 0x170C
* GB_TILE_CONFIG 0x4018
}
}
-
-/*
- * VRAM info
- */
static void r520_vram_get_type(struct radeon_device *rdev)
{
uint32_t tmp;
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
}
-void r520_bandwidth_update(struct radeon_device *rdev)
+void r520_mc_program(struct radeon_device *rdev)
+{
+ struct rv515_mc_save save;
+
+ /* Stops all mc clients */
+ rv515_mc_stop(rdev, &save);
+
+ /* Wait for mc idle */
+ if (r520_mc_wait_for_idle(rdev))
+ dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");
+ /* Write VRAM size in case we are limiting it */
+ WREG32(R_0000F8_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
+ /* Program MC, should be a 32bits limited address space */
+ WREG32_MC(R_000004_MC_FB_LOCATION,
+ S_000004_MC_FB_START(rdev->mc.vram_start >> 16) |
+ S_000004_MC_FB_TOP(rdev->mc.vram_end >> 16));
+ WREG32(R_000134_HDP_FB_LOCATION,
+ S_000134_HDP_FB_START(rdev->mc.vram_start >> 16));
+ if (rdev->flags & RADEON_IS_AGP) {
+ WREG32_MC(R_000005_MC_AGP_LOCATION,
+ S_000005_MC_AGP_START(rdev->mc.gtt_start >> 16) |
+ S_000005_MC_AGP_TOP(rdev->mc.gtt_end >> 16));
+ WREG32_MC(R_000006_AGP_BASE, lower_32_bits(rdev->mc.agp_base));
+ WREG32_MC(R_000007_AGP_BASE_2,
+ S_000007_AGP_BASE_ADDR_2(upper_32_bits(rdev->mc.agp_base)));
+ } else {
+ WREG32_MC(R_000005_MC_AGP_LOCATION, 0xFFFFFFFF);
+ WREG32_MC(R_000006_AGP_BASE, 0);
+ WREG32_MC(R_000007_AGP_BASE_2, 0);
+ }
+
+ rv515_mc_resume(rdev, &save);
+}
+
+static int r520_startup(struct radeon_device *rdev)
+{
+ int r;
+
+ r520_mc_program(rdev);
+ /* Resume clock */
+ rv515_clock_startup(rdev);
+ /* Initialize GPU configuration (# pipes, ...) */
+ r520_gpu_init(rdev);
+ /* Initialize GART (initialize after TTM so we can allocate
+ * memory through TTM but finalize after TTM) */
+ if (rdev->flags & RADEON_IS_PCIE) {
+ r = rv370_pcie_gart_enable(rdev);
+ if (r)
+ return r;
+ }
+ /* Enable IRQ */
+ rdev->irq.sw_int = true;
+ r100_irq_set(rdev);
+ /* 1M ring buffer */
+ r = r100_cp_init(rdev, 1024 * 1024);
+ if (r) {
+ dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+ return r;
+ }
+ r = r100_wb_init(rdev);
+ if (r)
+ dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
+ r = r100_ib_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+ return r;
+ }
+ return 0;
+}
+
+int r520_resume(struct radeon_device *rdev)
{
- rv515_bandwidth_avivo_update(rdev);
+ /* Make sur GART are not working */
+ if (rdev->flags & RADEON_IS_PCIE)
+ rv370_pcie_gart_disable(rdev);
+ /* Resume clock before doing reset */
+ rv515_clock_startup(rdev);
+ /* Reset gpu before posting otherwise ATOM will enter infinite loop */
+ if (radeon_gpu_reset(rdev)) {
+ dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
+ RREG32(R_000E40_RBBM_STATUS),
+ RREG32(R_0007C0_CP_STAT));
+ }
+ /* post */
+ atom_asic_init(rdev->mode_info.atom_context);
+ /* Resume clock after posting */
+ rv515_clock_startup(rdev);
+ return r520_startup(rdev);
+}
+
+int r520_init(struct radeon_device *rdev)
+{
+ int r;
+
+ rdev->new_init_path = true;
+ /* Initialize scratch registers */
+ radeon_scratch_init(rdev);
+ /* Initialize surface registers */
+ radeon_surface_init(rdev);
+ /* TODO: disable VGA need to use VGA request */
+ /* BIOS*/
+ if (!radeon_get_bios(rdev)) {
+ if (ASIC_IS_AVIVO(rdev))
+ return -EINVAL;
+ }
+ if (rdev->is_atom_bios) {
+ r = radeon_atombios_init(rdev);
+ if (r)
+ return r;
+ } else {
+ dev_err(rdev->dev, "Expecting atombios for RV515 GPU\n");
+ return -EINVAL;
+ }
+ /* Reset gpu before posting otherwise ATOM will enter infinite loop */
+ if (radeon_gpu_reset(rdev)) {
+ dev_warn(rdev->dev,
+ "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
+ RREG32(R_000E40_RBBM_STATUS),
+ RREG32(R_0007C0_CP_STAT));
+ }
+ /* check if cards are posted or not */
+ if (!radeon_card_posted(rdev) && rdev->bios) {
+ DRM_INFO("GPU not posted. posting now...\n");
+ atom_asic_init(rdev->mode_info.atom_context);
+ }
+ /* Initialize clocks */
+ radeon_get_clock_info(rdev->ddev);
+ /* Get vram informations */
+ r520_vram_info(rdev);
+ /* Initialize memory controller (also test AGP) */
+ r = r420_mc_init(rdev);
+ if (r)
+ return r;
+ rv515_debugfs(rdev);
+ /* Fence driver */
+ r = radeon_fence_driver_init(rdev);
+ if (r)
+ return r;
+ r = radeon_irq_kms_init(rdev);
+ if (r)
+ return r;
+ /* Memory manager */
+ r = radeon_object_init(rdev);
+ if (r)
+ return r;
+ r = rv370_pcie_gart_init(rdev);
+ if (r)
+ return r;
+ rv515_set_safe_registers(rdev);
+ rdev->accel_working = true;
+ r = r520_startup(rdev);
+ if (r) {
+ /* Somethings want wront with the accel init stop accel */
+ dev_err(rdev->dev, "Disabling GPU acceleration\n");
+ rv515_suspend(rdev);
+ r100_cp_fini(rdev);
+ r100_wb_fini(rdev);
+ r100_ib_fini(rdev);
+ rv370_pcie_gart_fini(rdev);
+ radeon_agp_fini(rdev);
+ radeon_irq_kms_fini(rdev);
+ rdev->accel_working = false;
+ }
+ return 0;
}
--- /dev/null
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Dave Airlie
+ * Alex Deucher
+ * Jerome Glisse
+ */
+#ifndef __R520D_H__
+#define __R520D_H__
+
+/* Registers */
+#define R_0000F8_CONFIG_MEMSIZE 0x0000F8
+#define S_0000F8_CONFIG_MEMSIZE(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_0000F8_CONFIG_MEMSIZE(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_0000F8_CONFIG_MEMSIZE 0x00000000
+#define R_000134_HDP_FB_LOCATION 0x000134
+#define S_000134_HDP_FB_START(x) (((x) & 0xFFFF) << 0)
+#define G_000134_HDP_FB_START(x) (((x) >> 0) & 0xFFFF)
+#define C_000134_HDP_FB_START 0xFFFF0000
+#define R_0007C0_CP_STAT 0x0007C0
+#define S_0007C0_MRU_BUSY(x) (((x) & 0x1) << 0)
+#define G_0007C0_MRU_BUSY(x) (((x) >> 0) & 0x1)
+#define C_0007C0_MRU_BUSY 0xFFFFFFFE
+#define S_0007C0_MWU_BUSY(x) (((x) & 0x1) << 1)
+#define G_0007C0_MWU_BUSY(x) (((x) >> 1) & 0x1)
+#define C_0007C0_MWU_BUSY 0xFFFFFFFD
+#define S_0007C0_RSIU_BUSY(x) (((x) & 0x1) << 2)
+#define G_0007C0_RSIU_BUSY(x) (((x) >> 2) & 0x1)
+#define C_0007C0_RSIU_BUSY 0xFFFFFFFB
+#define S_0007C0_RCIU_BUSY(x) (((x) & 0x1) << 3)
+#define G_0007C0_RCIU_BUSY(x) (((x) >> 3) & 0x1)
+#define C_0007C0_RCIU_BUSY 0xFFFFFFF7
+#define S_0007C0_CSF_PRIMARY_BUSY(x) (((x) & 0x1) << 9)
+#define G_0007C0_CSF_PRIMARY_BUSY(x) (((x) >> 9) & 0x1)
+#define C_0007C0_CSF_PRIMARY_BUSY 0xFFFFFDFF
+#define S_0007C0_CSF_INDIRECT_BUSY(x) (((x) & 0x1) << 10)
+#define G_0007C0_CSF_INDIRECT_BUSY(x) (((x) >> 10) & 0x1)
+#define C_0007C0_CSF_INDIRECT_BUSY 0xFFFFFBFF
+#define S_0007C0_CSQ_PRIMARY_BUSY(x) (((x) & 0x1) << 11)
+#define G_0007C0_CSQ_PRIMARY_BUSY(x) (((x) >> 11) & 0x1)
+#define C_0007C0_CSQ_PRIMARY_BUSY 0xFFFFF7FF
+#define S_0007C0_CSQ_INDIRECT_BUSY(x) (((x) & 0x1) << 12)
+#define G_0007C0_CSQ_INDIRECT_BUSY(x) (((x) >> 12) & 0x1)
+#define C_0007C0_CSQ_INDIRECT_BUSY 0xFFFFEFFF
+#define S_0007C0_CSI_BUSY(x) (((x) & 0x1) << 13)
+#define G_0007C0_CSI_BUSY(x) (((x) >> 13) & 0x1)
+#define C_0007C0_CSI_BUSY 0xFFFFDFFF
+#define S_0007C0_CSF_INDIRECT2_BUSY(x) (((x) & 0x1) << 14)
+#define G_0007C0_CSF_INDIRECT2_BUSY(x) (((x) >> 14) & 0x1)
+#define C_0007C0_CSF_INDIRECT2_BUSY 0xFFFFBFFF
+#define S_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) & 0x1) << 15)
+#define G_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) >> 15) & 0x1)
+#define C_0007C0_CSQ_INDIRECT2_BUSY 0xFFFF7FFF
+#define S_0007C0_GUIDMA_BUSY(x) (((x) & 0x1) << 28)
+#define G_0007C0_GUIDMA_BUSY(x) (((x) >> 28) & 0x1)
+#define C_0007C0_GUIDMA_BUSY 0xEFFFFFFF
+#define S_0007C0_VIDDMA_BUSY(x) (((x) & 0x1) << 29)
+#define G_0007C0_VIDDMA_BUSY(x) (((x) >> 29) & 0x1)
+#define C_0007C0_VIDDMA_BUSY 0xDFFFFFFF
+#define S_0007C0_CMDSTRM_BUSY(x) (((x) & 0x1) << 30)
+#define G_0007C0_CMDSTRM_BUSY(x) (((x) >> 30) & 0x1)
+#define C_0007C0_CMDSTRM_BUSY 0xBFFFFFFF
+#define S_0007C0_CP_BUSY(x) (((x) & 0x1) << 31)
+#define G_0007C0_CP_BUSY(x) (((x) >> 31) & 0x1)
+#define C_0007C0_CP_BUSY 0x7FFFFFFF
+#define R_000E40_RBBM_STATUS 0x000E40
+#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0)
+#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F)
+#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80
+#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8)
+#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1)
+#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF
+#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9)
+#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1)
+#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF
+#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10)
+#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1)
+#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF
+#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11)
+#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1)
+#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF
+#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12)
+#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1)
+#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF
+#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13)
+#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1)
+#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF
+#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14)
+#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1)
+#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF
+#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15)
+#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1)
+#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF
+#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16)
+#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1)
+#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF
+#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17)
+#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1)
+#define C_000E40_E2_BUSY 0xFFFDFFFF
+#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18)
+#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1)
+#define C_000E40_RB2D_BUSY 0xFFFBFFFF
+#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19)
+#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1)
+#define C_000E40_RB3D_BUSY 0xFFF7FFFF
+#define S_000E40_VAP_BUSY(x) (((x) & 0x1) << 20)
+#define G_000E40_VAP_BUSY(x) (((x) >> 20) & 0x1)
+#define C_000E40_VAP_BUSY 0xFFEFFFFF
+#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21)
+#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1)
+#define C_000E40_RE_BUSY 0xFFDFFFFF
+#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22)
+#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1)
+#define C_000E40_TAM_BUSY 0xFFBFFFFF
+#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23)
+#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1)
+#define C_000E40_TDM_BUSY 0xFF7FFFFF
+#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24)
+#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1)
+#define C_000E40_PB_BUSY 0xFEFFFFFF
+#define S_000E40_TIM_BUSY(x) (((x) & 0x1) << 25)
+#define G_000E40_TIM_BUSY(x) (((x) >> 25) & 0x1)
+#define C_000E40_TIM_BUSY 0xFDFFFFFF
+#define S_000E40_GA_BUSY(x) (((x) & 0x1) << 26)
+#define G_000E40_GA_BUSY(x) (((x) >> 26) & 0x1)
+#define C_000E40_GA_BUSY 0xFBFFFFFF
+#define S_000E40_CBA2D_BUSY(x) (((x) & 0x1) << 27)
+#define G_000E40_CBA2D_BUSY(x) (((x) >> 27) & 0x1)
+#define C_000E40_CBA2D_BUSY 0xF7FFFFFF
+#define S_000E40_RBBM_HIBUSY(x) (((x) & 0x1) << 28)
+#define G_000E40_RBBM_HIBUSY(x) (((x) >> 28) & 0x1)
+#define C_000E40_RBBM_HIBUSY 0xEFFFFFFF
+#define S_000E40_SKID_CFBUSY(x) (((x) & 0x1) << 29)
+#define G_000E40_SKID_CFBUSY(x) (((x) >> 29) & 0x1)
+#define C_000E40_SKID_CFBUSY 0xDFFFFFFF
+#define S_000E40_VAP_VF_BUSY(x) (((x) & 0x1) << 30)
+#define G_000E40_VAP_VF_BUSY(x) (((x) >> 30) & 0x1)
+#define C_000E40_VAP_VF_BUSY 0xBFFFFFFF
+#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31)
+#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1)
+#define C_000E40_GUI_ACTIVE 0x7FFFFFFF
+
+
+#define R_000004_MC_FB_LOCATION 0x000004
+#define S_000004_MC_FB_START(x) (((x) & 0xFFFF) << 0)
+#define G_000004_MC_FB_START(x) (((x) >> 0) & 0xFFFF)
+#define C_000004_MC_FB_START 0xFFFF0000
+#define S_000004_MC_FB_TOP(x) (((x) & 0xFFFF) << 16)
+#define G_000004_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF)
+#define C_000004_MC_FB_TOP 0x0000FFFF
+#define R_000005_MC_AGP_LOCATION 0x000005
+#define S_000005_MC_AGP_START(x) (((x) & 0xFFFF) << 0)
+#define G_000005_MC_AGP_START(x) (((x) >> 0) & 0xFFFF)
+#define C_000005_MC_AGP_START 0xFFFF0000
+#define S_000005_MC_AGP_TOP(x) (((x) & 0xFFFF) << 16)
+#define G_000005_MC_AGP_TOP(x) (((x) >> 16) & 0xFFFF)
+#define C_000005_MC_AGP_TOP 0x0000FFFF
+#define R_000006_AGP_BASE 0x000006
+#define S_000006_AGP_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_000006_AGP_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_000006_AGP_BASE_ADDR 0x00000000
+#define R_000007_AGP_BASE_2 0x000007
+#define S_000007_AGP_BASE_ADDR_2(x) (((x) & 0xF) << 0)
+#define G_000007_AGP_BASE_ADDR_2(x) (((x) >> 0) & 0xF)
+#define C_000007_AGP_BASE_ADDR_2 0xFFFFFFF0
+
+#endif
#include "radeon.h"
#include "radeon_mode.h"
#include "r600d.h"
-#include "avivod.h"
#include "atom.h"
+#include "avivod.h"
#define PFP_UCODE_SIZE 576
#define PM4_UCODE_SIZE 1792
/* we need to own VRAM, so turn off the VGA renderer here
* to stop it overwriting our objects */
- radeon_avivo_vga_render_disable(rdev);
+ rv515_vga_render_disable(rdev);
}
int r600_mc_init(struct radeon_device *rdev)
/* Setup GPU memory space */
rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
+
+ if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
+ rdev->mc.mc_vram_size = rdev->mc.aper_size;
+
+ if (rdev->mc.real_vram_size > rdev->mc.aper_size)
+ rdev->mc.real_vram_size = rdev->mc.aper_size;
+
if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev);
if (r)
#include "drmP.h"
#include "radeon.h"
#include "r600d.h"
-#include "avivod.h"
static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc);
idx, ib_chunk->length_dw);
return -EINVAL;
}
- header = ib_chunk->kdata[idx];
+ header = radeon_get_ib_value(p, idx);
pkt->idx = idx;
pkt->type = CP_PACKET_GET_TYPE(header);
pkt->count = CP_PACKET_GET_COUNT(header);
static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc)
{
- struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_chunk *relocs_chunk;
struct radeon_cs_packet p3reloc;
unsigned idx;
return -EINVAL;
}
*cs_reloc = NULL;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
relocs_chunk = &p->chunks[p->chunk_relocs_idx];
r = r600_cs_packet_parse(p, &p3reloc, p->idx);
if (r) {
p3reloc.idx);
return -EINVAL;
}
- idx = ib_chunk->kdata[p3reloc.idx + 1];
+ idx = radeon_get_ib_value(p, p3reloc.idx + 1);
if (idx >= relocs_chunk->length_dw) {
DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
idx, relocs_chunk->length_dw);
static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc)
{
- struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_chunk *relocs_chunk;
struct radeon_cs_packet p3reloc;
unsigned idx;
return -EINVAL;
}
*cs_reloc = NULL;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
relocs_chunk = &p->chunks[p->chunk_relocs_idx];
r = r600_cs_packet_parse(p, &p3reloc, p->idx);
if (r) {
p3reloc.idx);
return -EINVAL;
}
- idx = ib_chunk->kdata[p3reloc.idx + 1];
+ idx = radeon_get_ib_value(p, p3reloc.idx + 1);
if (idx >= relocs_chunk->length_dw) {
DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
idx, relocs_chunk->length_dw);
return 0;
}
+/**
+ * r600_cs_packet_next_vline() - parse userspace VLINE packet
+ * @parser: parser structure holding parsing context.
+ *
+ * Userspace sends a special sequence for VLINE waits.
+ * PACKET0 - VLINE_START_END + value
+ * PACKET3 - WAIT_REG_MEM poll vline status reg
+ * RELOC (P3) - crtc_id in reloc.
+ *
+ * This function parses this and relocates the VLINE START END
+ * and WAIT_REG_MEM packets to the correct crtc.
+ * It also detects a switched off crtc and nulls out the
+ * wait in that case.
+ */
+static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
+{
+ struct drm_mode_object *obj;
+ struct drm_crtc *crtc;
+ struct radeon_crtc *radeon_crtc;
+ struct radeon_cs_packet p3reloc, wait_reg_mem;
+ int crtc_id;
+ int r;
+ uint32_t header, h_idx, reg, wait_reg_mem_info;
+ volatile uint32_t *ib;
+
+ ib = p->ib->ptr;
+
+ /* parse the WAIT_REG_MEM */
+ r = r600_cs_packet_parse(p, &wait_reg_mem, p->idx);
+ if (r)
+ return r;
+
+ /* check its a WAIT_REG_MEM */
+ if (wait_reg_mem.type != PACKET_TYPE3 ||
+ wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
+ DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
+ r = -EINVAL;
+ return r;
+ }
+
+ wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
+ /* bit 4 is reg (0) or mem (1) */
+ if (wait_reg_mem_info & 0x10) {
+ DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
+ r = -EINVAL;
+ return r;
+ }
+ /* waiting for value to be equal */
+ if ((wait_reg_mem_info & 0x7) != 0x3) {
+ DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
+ r = -EINVAL;
+ return r;
+ }
+ if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != AVIVO_D1MODE_VLINE_STATUS) {
+ DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
+ r = -EINVAL;
+ return r;
+ }
+
+ if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != AVIVO_D1MODE_VLINE_STAT) {
+ DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
+ r = -EINVAL;
+ return r;
+ }
+
+ /* jump over the NOP */
+ r = r600_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
+ if (r)
+ return r;
+
+ h_idx = p->idx - 2;
+ p->idx += wait_reg_mem.count + 2;
+ p->idx += p3reloc.count + 2;
+
+ header = radeon_get_ib_value(p, h_idx);
+ crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
+ reg = header >> 2;
+ mutex_lock(&p->rdev->ddev->mode_config.mutex);
+ obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
+ if (!obj) {
+ DRM_ERROR("cannot find crtc %d\n", crtc_id);
+ r = -EINVAL;
+ goto out;
+ }
+ crtc = obj_to_crtc(obj);
+ radeon_crtc = to_radeon_crtc(crtc);
+ crtc_id = radeon_crtc->crtc_id;
+
+ if (!crtc->enabled) {
+ /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
+ ib[h_idx + 2] = PACKET2(0);
+ ib[h_idx + 3] = PACKET2(0);
+ ib[h_idx + 4] = PACKET2(0);
+ ib[h_idx + 5] = PACKET2(0);
+ ib[h_idx + 6] = PACKET2(0);
+ ib[h_idx + 7] = PACKET2(0);
+ ib[h_idx + 8] = PACKET2(0);
+ } else if (crtc_id == 1) {
+ switch (reg) {
+ case AVIVO_D1MODE_VLINE_START_END:
+ header &= ~R600_CP_PACKET0_REG_MASK;
+ header |= AVIVO_D2MODE_VLINE_START_END >> 2;
+ break;
+ default:
+ DRM_ERROR("unknown crtc reloc\n");
+ r = -EINVAL;
+ goto out;
+ }
+ ib[h_idx] = header;
+ ib[h_idx + 4] = AVIVO_D2MODE_VLINE_STATUS >> 2;
+ }
+out:
+ mutex_unlock(&p->rdev->ddev->mode_config.mutex);
+ return r;
+}
+
static int r600_packet0_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt,
unsigned idx, unsigned reg)
{
+ int r;
+
switch (reg) {
case AVIVO_D1MODE_VLINE_START_END:
- case AVIVO_D2MODE_VLINE_START_END:
+ r = r600_cs_packet_parse_vline(p);
+ if (r) {
+ DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+ idx, reg);
+ return r;
+ }
break;
default:
printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
static int r600_packet3_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt)
{
- struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc;
volatile u32 *ib;
unsigned idx;
unsigned i;
unsigned start_reg, end_reg, reg;
int r;
+ u32 idx_value;
ib = p->ib->ptr;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
idx = pkt->idx + 1;
+ idx_value = radeon_get_ib_value(p, idx);
+
switch (pkt->opcode) {
case PACKET3_START_3D_CMDBUF:
if (p->family >= CHIP_RV770 || pkt->count) {
DRM_ERROR("bad DRAW_INDEX\n");
return -EINVAL;
}
- ib[idx+0] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+1] = upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+ ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+ ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
break;
case PACKET3_DRAW_INDEX_AUTO:
if (pkt->count != 1) {
return -EINVAL;
}
/* bit 4 is reg (0) or mem (1) */
- if (ib_chunk->kdata[idx+0] & 0x10) {
+ if (idx_value & 0x10) {
r = r600_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("bad WAIT_REG_MEM\n");
return -EINVAL;
}
ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] = upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+ ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
}
break;
case PACKET3_SURFACE_SYNC:
return -EINVAL;
}
/* 0xffffffff/0x0 is flush all cache flag */
- if (ib_chunk->kdata[idx+1] != 0xffffffff ||
- ib_chunk->kdata[idx+2] != 0) {
+ if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
+ radeon_get_ib_value(p, idx + 2) != 0) {
r = r600_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("bad SURFACE_SYNC\n");
return -EINVAL;
}
ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] |= upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+ ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
}
break;
case PACKET3_EVENT_WRITE_EOP:
return -EINVAL;
}
ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] |= upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+ ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
break;
case PACKET3_SET_CONFIG_REG:
- start_reg = (ib[idx+0] << 2) + PACKET3_SET_CONFIG_REG_OFFSET;
+ start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_CONFIG_REG_OFFSET) ||
(start_reg >= PACKET3_SET_CONFIG_REG_END) ||
}
break;
case PACKET3_SET_CONTEXT_REG:
- start_reg = (ib[idx+0] << 2) + PACKET3_SET_CONTEXT_REG_OFFSET;
+ start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_CONTEXT_REG_OFFSET) ||
(start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
DRM_ERROR("bad SET_RESOURCE\n");
return -EINVAL;
}
- start_reg = (ib[idx+0] << 2) + PACKET3_SET_RESOURCE_OFFSET;
+ start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_RESOURCE_OFFSET) ||
(start_reg >= PACKET3_SET_RESOURCE_END) ||
return -EINVAL;
}
for (i = 0; i < (pkt->count / 7); i++) {
- switch (G__SQ_VTX_CONSTANT_TYPE(ib[idx+(i*7)+6+1])) {
+ switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
case SQ_TEX_VTX_VALID_TEXTURE:
/* tex base */
r = r600_cs_packet_next_reloc(p, &reloc);
return -EINVAL;
}
ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
- ib[idx+1+(i*7)+2] |= upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
+ ib[idx+1+(i*7)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
break;
case SQ_TEX_VTX_INVALID_TEXTURE:
case SQ_TEX_VTX_INVALID_BUFFER:
}
break;
case PACKET3_SET_ALU_CONST:
- start_reg = (ib[idx+0] << 2) + PACKET3_SET_ALU_CONST_OFFSET;
+ start_reg = (idx_value << 2) + PACKET3_SET_ALU_CONST_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_ALU_CONST_OFFSET) ||
(start_reg >= PACKET3_SET_ALU_CONST_END) ||
}
break;
case PACKET3_SET_BOOL_CONST:
- start_reg = (ib[idx+0] << 2) + PACKET3_SET_BOOL_CONST_OFFSET;
+ start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_BOOL_CONST_OFFSET) ||
(start_reg >= PACKET3_SET_BOOL_CONST_END) ||
}
break;
case PACKET3_SET_LOOP_CONST:
- start_reg = (ib[idx+0] << 2) + PACKET3_SET_LOOP_CONST_OFFSET;
+ start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_LOOP_CONST_OFFSET) ||
(start_reg >= PACKET3_SET_LOOP_CONST_END) ||
}
break;
case PACKET3_SET_CTL_CONST:
- start_reg = (ib[idx+0] << 2) + PACKET3_SET_CTL_CONST_OFFSET;
+ start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_CTL_CONST_OFFSET) ||
(start_reg >= PACKET3_SET_CTL_CONST_END) ||
DRM_ERROR("bad SET_SAMPLER\n");
return -EINVAL;
}
- start_reg = (ib[idx+0] << 2) + PACKET3_SET_SAMPLER_OFFSET;
+ start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_OFFSET;
end_reg = 4 * pkt->count + start_reg - 4;
if ((start_reg < PACKET3_SET_SAMPLER_OFFSET) ||
(start_reg >= PACKET3_SET_SAMPLER_END) ||
kfree(parser->relocs);
for (i = 0; i < parser->nchunks; i++) {
kfree(parser->chunks[i].kdata);
+ kfree(parser->chunks[i].kpage[0]);
+ kfree(parser->chunks[i].kpage[1]);
}
kfree(parser->chunks);
kfree(parser->chunks_array);
* uncached). */
ib_chunk = &parser.chunks[parser.chunk_ib_idx];
parser.ib->length_dw = ib_chunk->length_dw;
- memcpy((void *)parser.ib->ptr, ib_chunk->kdata, ib_chunk->length_dw*4);
*l = parser.ib->length_dw;
r = r600_cs_parse(&parser);
if (r) {
r600_cs_parser_fini(&parser, r);
return r;
}
+ r = radeon_cs_finish_pages(&parser);
+ if (r) {
+ DRM_ERROR("Invalid command stream !\n");
+ r600_cs_parser_fini(&parser, r);
+ return r;
+ }
r600_cs_parser_fini(&parser, r);
return r;
}
* - TESTING, TESTING, TESTING
*/
+/* Initialization path:
+ * We expect that acceleration initialization might fail for various
+ * reasons even thought we work hard to make it works on most
+ * configurations. In order to still have a working userspace in such
+ * situation the init path must succeed up to the memory controller
+ * initialization point. Failure before this point are considered as
+ * fatal error. Here is the init callchain :
+ * radeon_device_init perform common structure, mutex initialization
+ * asic_init setup the GPU memory layout and perform all
+ * one time initialization (failure in this
+ * function are considered fatal)
+ * asic_startup setup the GPU acceleration, in order to
+ * follow guideline the first thing this
+ * function should do is setting the GPU
+ * memory controller (only MC setup failure
+ * are considered as fatal)
+ */
+
#include <asm/atomic.h>
#include <linux/wait.h>
#include <linux/list.h>
unsigned long idx;
uint64_t gpu_addr;
struct radeon_fence *fence;
- volatile uint32_t *ptr;
+ uint32_t *ptr;
uint32_t length_dw;
};
struct radeon_cs_chunk {
uint32_t chunk_id;
uint32_t length_dw;
+ int kpage_idx[2];
+ uint32_t *kpage[2];
uint32_t *kdata;
+ void __user *user_ptr;
+ int last_copied_page;
+ int last_page_index;
};
struct radeon_cs_parser {
struct radeon_ib *ib;
void *track;
unsigned family;
+ int parser_error;
};
+extern int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx);
+extern int radeon_cs_finish_pages(struct radeon_cs_parser *p);
+
+
+static inline u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx)
+{
+ struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
+ u32 pg_idx, pg_offset;
+ u32 idx_value = 0;
+ int new_page;
+
+ pg_idx = (idx * 4) / PAGE_SIZE;
+ pg_offset = (idx * 4) % PAGE_SIZE;
+
+ if (ibc->kpage_idx[0] == pg_idx)
+ return ibc->kpage[0][pg_offset/4];
+ if (ibc->kpage_idx[1] == pg_idx)
+ return ibc->kpage[1][pg_offset/4];
+
+ new_page = radeon_cs_update_pages(p, pg_idx);
+ if (new_page < 0) {
+ p->parser_error = new_page;
+ return 0;
+ }
+
+ idx_value = ibc->kpage[new_page][pg_offset/4];
+ return idx_value;
+}
+
struct radeon_cs_packet {
unsigned idx;
unsigned type;
extern void radeon_scratch_init(struct radeon_device *rdev);
extern void radeon_surface_init(struct radeon_device *rdev);
extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data);
+extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
/* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */
struct r100_mc_save {
extern void r100_wb_disable(struct radeon_device *rdev);
extern void r100_wb_fini(struct radeon_device *rdev);
extern int r100_wb_init(struct radeon_device *rdev);
+extern void r100_hdp_reset(struct radeon_device *rdev);
+extern int r100_rb2d_reset(struct radeon_device *rdev);
+extern int r100_cp_reset(struct radeon_device *rdev);
/* r300,r350,rv350,rv370,rv380 */
extern void r300_set_reg_safe(struct radeon_device *rdev);
extern void rv370_pcie_gart_disable(struct radeon_device *rdev);
/* r420,r423,rv410 */
+extern int r420_mc_init(struct radeon_device *rdev);
extern u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg);
extern void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v);
extern int r420_debugfs_pipes_info_init(struct radeon_device *rdev);
+extern void r420_pipes_init(struct radeon_device *rdev);
/* rv515 */
+struct rv515_mc_save {
+ u32 d1vga_control;
+ u32 d2vga_control;
+ u32 vga_render_control;
+ u32 vga_hdp_control;
+ u32 d1crtc_control;
+ u32 d2crtc_control;
+};
extern void rv515_bandwidth_avivo_update(struct radeon_device *rdev);
+extern void rv515_vga_render_disable(struct radeon_device *rdev);
+extern void rv515_set_safe_registers(struct radeon_device *rdev);
+extern void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save);
+extern void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save);
+extern void rv515_clock_startup(struct radeon_device *rdev);
+extern void rv515_debugfs(struct radeon_device *rdev);
+extern int rv515_suspend(struct radeon_device *rdev);
/* rs690, rs740 */
extern void rs690_line_buffer_adjust(struct radeon_device *rdev,
* rv515
*/
int rv515_init(struct radeon_device *rdev);
-void rv515_errata(struct radeon_device *rdev);
-void rv515_vram_info(struct radeon_device *rdev);
+void rv515_fini(struct radeon_device *rdev);
int rv515_gpu_reset(struct radeon_device *rdev);
-int rv515_mc_init(struct radeon_device *rdev);
-void rv515_mc_fini(struct radeon_device *rdev);
uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg);
void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void rv515_ring_start(struct radeon_device *rdev);
uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void rv515_bandwidth_update(struct radeon_device *rdev);
+int rv515_resume(struct radeon_device *rdev);
+int rv515_suspend(struct radeon_device *rdev);
static struct radeon_asic rv515_asic = {
.init = &rv515_init,
- .errata = &rv515_errata,
- .vram_info = &rv515_vram_info,
+ .fini = &rv515_fini,
+ .suspend = &rv515_suspend,
+ .resume = &rv515_resume,
+ .errata = NULL,
+ .vram_info = NULL,
.vga_set_state = &r100_vga_set_state,
.gpu_reset = &rv515_gpu_reset,
- .mc_init = &rv515_mc_init,
- .mc_fini = &rv515_mc_fini,
- .wb_init = &r100_wb_init,
- .wb_fini = &r100_wb_fini,
+ .mc_init = NULL,
+ .mc_fini = NULL,
+ .wb_init = NULL,
+ .wb_fini = NULL,
.gart_init = &rv370_pcie_gart_init,
.gart_fini = &rv370_pcie_gart_fini,
- .gart_enable = &rv370_pcie_gart_enable,
- .gart_disable = &rv370_pcie_gart_disable,
+ .gart_enable = NULL,
+ .gart_disable = NULL,
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
.gart_set_page = &rv370_pcie_gart_set_page,
- .cp_init = &r100_cp_init,
- .cp_fini = &r100_cp_fini,
- .cp_disable = &r100_cp_disable,
+ .cp_init = NULL,
+ .cp_fini = NULL,
+ .cp_disable = NULL,
.cp_commit = &r100_cp_commit,
.ring_start = &rv515_ring_start,
.ring_test = &r100_ring_test,
.ring_ib_execute = &r100_ring_ib_execute,
- .ib_test = &r100_ib_test,
+ .ib_test = NULL,
.irq_set = &rs600_irq_set,
.irq_process = &rs600_irq_process,
.get_vblank_counter = &rs600_get_vblank_counter,
/*
* r520,rv530,rv560,rv570,r580
*/
-void r520_errata(struct radeon_device *rdev);
-void r520_vram_info(struct radeon_device *rdev);
-int r520_mc_init(struct radeon_device *rdev);
-void r520_mc_fini(struct radeon_device *rdev);
-void r520_bandwidth_update(struct radeon_device *rdev);
+int r520_init(struct radeon_device *rdev);
+int r520_resume(struct radeon_device *rdev);
static struct radeon_asic r520_asic = {
- .init = &rv515_init,
- .errata = &r520_errata,
- .vram_info = &r520_vram_info,
+ .init = &r520_init,
+ .fini = &rv515_fini,
+ .suspend = &rv515_suspend,
+ .resume = &r520_resume,
+ .errata = NULL,
+ .vram_info = NULL,
.vga_set_state = &r100_vga_set_state,
.gpu_reset = &rv515_gpu_reset,
- .mc_init = &r520_mc_init,
- .mc_fini = &r520_mc_fini,
- .wb_init = &r100_wb_init,
- .wb_fini = &r100_wb_fini,
- .gart_init = &rv370_pcie_gart_init,
- .gart_fini = &rv370_pcie_gart_fini,
- .gart_enable = &rv370_pcie_gart_enable,
- .gart_disable = &rv370_pcie_gart_disable,
+ .mc_init = NULL,
+ .mc_fini = NULL,
+ .wb_init = NULL,
+ .wb_fini = NULL,
+ .gart_init = NULL,
+ .gart_fini = NULL,
+ .gart_enable = NULL,
+ .gart_disable = NULL,
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
.gart_set_page = &rv370_pcie_gart_set_page,
- .cp_init = &r100_cp_init,
- .cp_fini = &r100_cp_fini,
- .cp_disable = &r100_cp_disable,
+ .cp_init = NULL,
+ .cp_fini = NULL,
+ .cp_disable = NULL,
.cp_commit = &r100_cp_commit,
.ring_start = &rv515_ring_start,
.ring_test = &r100_ring_test,
.ring_ib_execute = &r100_ring_ib_execute,
- .ib_test = &r100_ib_test,
+ .ib_test = NULL,
.irq_set = &rs600_irq_set,
.irq_process = &rs600_irq_process,
.get_vblank_counter = &rs600_get_vblank_counter,
.set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
- .bandwidth_update = &r520_bandwidth_update,
+ .bandwidth_update = &rv515_bandwidth_update,
};
/*
.set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r600_set_surface_reg,
.clear_surface_reg = r600_clear_surface_reg,
- .bandwidth_update = &r520_bandwidth_update,
+ .bandwidth_update = &rv515_bandwidth_update,
};
/*
.set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r600_set_surface_reg,
.clear_surface_reg = r600_clear_surface_reg,
- .bandwidth_update = &r520_bandwidth_update,
+ .bandwidth_update = &rv515_bandwidth_update,
};
#endif
(le16_to_cpu(path->usConnObjectId) &
OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
- if ((le16_to_cpu(path->usDeviceTag) ==
- ATOM_DEVICE_TV1_SUPPORT)
- || (le16_to_cpu(path->usDeviceTag) ==
- ATOM_DEVICE_TV2_SUPPORT)
- || (le16_to_cpu(path->usDeviceTag) ==
- ATOM_DEVICE_CV_SUPPORT))
+ /* TODO CV support */
+ if (le16_to_cpu(path->usDeviceTag) ==
+ ATOM_DEVICE_CV_SUPPORT)
continue;
if ((rdev->family == CHIP_RS780) &&
#include "drmP.h"
#include "drm_edid.h"
#include "drm_crtc_helper.h"
+#include "drm_fb_helper.h"
#include "radeon_drm.h"
#include "radeon.h"
#include "atom.h"
if (common_modes[i].w < 320 || common_modes[i].h < 200)
continue;
- mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false);
+ mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
drm_mode_probed_add(connector, mode);
}
}
radeon_add_common_modes(encoder, connector);
else {
/* only 800x600 is supported right now on pre-avivo chips */
- tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false);
+ tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false, false);
tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, tv_mode);
}
return NULL;
}
+static void radeon_dvi_force(struct drm_connector *connector)
+{
+ struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+ if (connector->force == DRM_FORCE_ON)
+ radeon_connector->use_digital = false;
+ if (connector->force == DRM_FORCE_ON_DIGITAL)
+ radeon_connector->use_digital = true;
+}
+
struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = {
.get_modes = radeon_dvi_get_modes,
.mode_valid = radeon_vga_mode_valid,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = radeon_connector_set_property,
.destroy = radeon_connector_destroy,
+ .force = radeon_dvi_force,
};
void
struct radeon_connector *radeon_connector;
struct radeon_connector_atom_dig *radeon_dig_connector;
uint32_t subpixel_order = SubPixelNone;
+ int ret;
/* fixme - tv/cv/din */
if (connector_type == DRM_MODE_CONNECTOR_Unknown)
switch (connector_type) {
case DRM_MODE_CONNECTOR_VGA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
- drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
+ ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
+ if (ret)
+ goto failed;
if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA");
if (!radeon_connector->ddc_bus)
goto failed;
}
+ radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
break;
case DRM_MODE_CONNECTOR_DVIA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
- drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
+ ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
+ if (ret)
+ goto failed;
if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
if (!radeon_connector->ddc_bus)
goto failed;
}
+ radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
radeon_dig_connector->igp_lane_info = igp_lane_info;
radeon_connector->con_priv = radeon_dig_connector;
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
- drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
+ ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
+ if (ret)
+ goto failed;
if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
if (!radeon_connector->ddc_bus)
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.coherent_mode_property,
1);
+ radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
radeon_dig_connector->igp_lane_info = igp_lane_info;
radeon_connector->con_priv = radeon_dig_connector;
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
- drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
+ ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
+ if (ret)
+ goto failed;
if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI");
if (!radeon_connector->ddc_bus)
radeon_dig_connector->igp_lane_info = igp_lane_info;
radeon_connector->con_priv = radeon_dig_connector;
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
- drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
+ ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
+ if (ret)
+ goto failed;
if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP");
if (!radeon_connector->ddc_bus)
case DRM_MODE_CONNECTOR_9PinDIN:
if (radeon_tv == 1) {
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
- drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
+ ret = drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
+ if (ret)
+ goto failed;
+ radeon_connector->dac_load_detect = true;
+ drm_connector_attach_property(&radeon_connector->base,
+ rdev->mode_info.load_detect_property,
+ 1);
}
- drm_connector_attach_property(&radeon_connector->base,
- rdev->mode_info.load_detect_property,
- 1);
break;
case DRM_MODE_CONNECTOR_LVDS:
radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
radeon_dig_connector->igp_lane_info = igp_lane_info;
radeon_connector->con_priv = radeon_dig_connector;
drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
- drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
+ ret = drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
+ if (ret)
+ goto failed;
if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS");
if (!radeon_connector->ddc_bus)
struct drm_connector *connector;
struct radeon_connector *radeon_connector;
uint32_t subpixel_order = SubPixelNone;
+ int ret;
/* fixme - tv/cv/din */
if (connector_type == DRM_MODE_CONNECTOR_Unknown)
switch (connector_type) {
case DRM_MODE_CONNECTOR_VGA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
- drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
+ ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
+ if (ret)
+ goto failed;
if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA");
if (!radeon_connector->ddc_bus)
goto failed;
}
+ radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
break;
case DRM_MODE_CONNECTOR_DVIA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
- drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
+ ret = drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
+ if (ret)
+ goto failed;
if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
if (!radeon_connector->ddc_bus)
goto failed;
}
+ radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_DVID:
drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
- drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
+ ret = drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
+ if (ret)
+ goto failed;
if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
if (!radeon_connector->ddc_bus)
goto failed;
+ radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
case DRM_MODE_CONNECTOR_9PinDIN:
if (radeon_tv == 1) {
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
- drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
+ ret = drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
+ if (ret)
+ goto failed;
+ radeon_connector->dac_load_detect = true;
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
break;
case DRM_MODE_CONNECTOR_LVDS:
drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
- drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
+ ret = drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
+ if (ret)
+ goto failed;
if (i2c_bus->valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS");
if (!radeon_connector->ddc_bus)
}
p->chunks[i].length_dw = user_chunk.length_dw;
- cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data;
+ p->chunks[i].user_ptr = (void __user *)(unsigned long)user_chunk.chunk_data;
- size = p->chunks[i].length_dw * sizeof(uint32_t);
- p->chunks[i].kdata = kmalloc(size, GFP_KERNEL);
- if (p->chunks[i].kdata == NULL) {
- return -ENOMEM;
- }
- if (DRM_COPY_FROM_USER(p->chunks[i].kdata, cdata, size)) {
- return -EFAULT;
+ cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data;
+ if (p->chunks[i].chunk_id != RADEON_CHUNK_ID_IB) {
+ size = p->chunks[i].length_dw * sizeof(uint32_t);
+ p->chunks[i].kdata = kmalloc(size, GFP_KERNEL);
+ if (p->chunks[i].kdata == NULL) {
+ return -ENOMEM;
+ }
+ if (DRM_COPY_FROM_USER(p->chunks[i].kdata,
+ p->chunks[i].user_ptr, size)) {
+ return -EFAULT;
+ }
+ } else {
+ p->chunks[i].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ p->chunks[i].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (p->chunks[i].kpage[0] == NULL || p->chunks[i].kpage[1] == NULL) {
+ kfree(p->chunks[i].kpage[0]);
+ kfree(p->chunks[i].kpage[1]);
+ return -ENOMEM;
+ }
+ p->chunks[i].kpage_idx[0] = -1;
+ p->chunks[i].kpage_idx[1] = -1;
+ p->chunks[i].last_copied_page = -1;
+ p->chunks[i].last_page_index = ((p->chunks[i].length_dw * 4) - 1) / PAGE_SIZE;
}
}
if (p->chunks[p->chunk_ib_idx].length_dw > (16 * 1024)) {
kfree(parser->relocs_ptr);
for (i = 0; i < parser->nchunks; i++) {
kfree(parser->chunks[i].kdata);
+ kfree(parser->chunks[i].kpage[0]);
+ kfree(parser->chunks[i].kpage[1]);
}
kfree(parser->chunks);
kfree(parser->chunks_array);
* uncached). */
ib_chunk = &parser.chunks[parser.chunk_ib_idx];
parser.ib->length_dw = ib_chunk->length_dw;
- memcpy((void *)parser.ib->ptr, ib_chunk->kdata, ib_chunk->length_dw*4);
r = radeon_cs_parse(&parser);
+ if (r || parser.parser_error) {
+ DRM_ERROR("Invalid command stream !\n");
+ radeon_cs_parser_fini(&parser, r);
+ mutex_unlock(&rdev->cs_mutex);
+ return r;
+ }
+ r = radeon_cs_finish_pages(&parser);
if (r) {
DRM_ERROR("Invalid command stream !\n");
radeon_cs_parser_fini(&parser, r);
mutex_unlock(&rdev->cs_mutex);
return r;
}
+
+int radeon_cs_finish_pages(struct radeon_cs_parser *p)
+{
+ struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
+ int i;
+ int size = PAGE_SIZE;
+
+ for (i = ibc->last_copied_page + 1; i <= ibc->last_page_index; i++) {
+ if (i == ibc->last_page_index) {
+ size = (ibc->length_dw * 4) % PAGE_SIZE;
+ if (size == 0)
+ size = PAGE_SIZE;
+ }
+
+ if (DRM_COPY_FROM_USER(p->ib->ptr + (i * (PAGE_SIZE/4)),
+ ibc->user_ptr + (i * PAGE_SIZE),
+ size))
+ return -EFAULT;
+ }
+ return 0;
+}
+
+int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx)
+{
+ int new_page;
+ struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
+ int i;
+ int size = PAGE_SIZE;
+
+ for (i = ibc->last_copied_page + 1; i < pg_idx; i++) {
+ if (DRM_COPY_FROM_USER(p->ib->ptr + (i * (PAGE_SIZE/4)),
+ ibc->user_ptr + (i * PAGE_SIZE),
+ PAGE_SIZE)) {
+ p->parser_error = -EFAULT;
+ return 0;
+ }
+ }
+
+ new_page = ibc->kpage_idx[0] < ibc->kpage_idx[1] ? 0 : 1;
+
+ if (pg_idx == ibc->last_page_index) {
+ size = (ibc->length_dw * 4) % PAGE_SIZE;
+ if (size == 0)
+ size = PAGE_SIZE;
+ }
+
+ if (DRM_COPY_FROM_USER(ibc->kpage[new_page],
+ ibc->user_ptr + (pg_idx * PAGE_SIZE),
+ size)) {
+ p->parser_error = -EFAULT;
+ return 0;
+ }
+
+ /* copy to IB here */
+ memcpy((void *)(p->ib->ptr+(pg_idx*(PAGE_SIZE/4))), ibc->kpage[new_page], size);
+
+ ibc->last_copied_page = pg_idx;
+ ibc->kpage_idx[new_page] = pg_idx;
+
+ return new_page;
+}
if (radeon_agpmode == -1) {
rdev->flags &= ~RADEON_IS_AGP;
- if (rdev->family >= CHIP_RV515 ||
- rdev->family == CHIP_RV380 ||
- rdev->family == CHIP_RV410 ||
- rdev->family == CHIP_R423) {
+ if (rdev->family >= CHIP_R600) {
+ DRM_INFO("Forcing AGP to PCIE mode\n");
+ rdev->flags |= RADEON_IS_PCIE;
+ } else if (rdev->family >= CHIP_RV515 ||
+ rdev->family == CHIP_RV380 ||
+ rdev->family == CHIP_RV410 ||
+ rdev->family == CHIP_R423) {
DRM_INFO("Forcing AGP to PCIE mode\n");
rdev->flags |= RADEON_IS_PCIE;
rdev->asic->gart_init = &rv370_pcie_gart_init;
int radeon_driver_irq_postinstall_kms(struct drm_device *dev);
void radeon_driver_irq_uninstall_kms(struct drm_device *dev);
irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS);
-int radeon_master_create_kms(struct drm_device *dev, struct drm_master *master);
-void radeon_master_destroy_kms(struct drm_device *dev,
- struct drm_master *master);
int radeon_dma_ioctl_kms(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int radeon_gem_object_init(struct drm_gem_object *obj);
.get_vblank_counter = radeon_get_vblank_counter_kms,
.enable_vblank = radeon_enable_vblank_kms,
.disable_vblank = radeon_disable_vblank_kms,
- .master_create = radeon_master_create_kms,
- .master_destroy = radeon_master_destroy_kms,
#if defined(CONFIG_DEBUG_FS)
.debugfs_init = radeon_debugfs_init,
.debugfs_cleanup = radeon_debugfs_cleanup,
int radeonfb_create(struct drm_device *dev,
uint32_t fb_width, uint32_t fb_height,
uint32_t surface_width, uint32_t surface_height,
+ uint32_t surface_depth, uint32_t surface_bpp,
struct drm_framebuffer **fb_p)
{
struct radeon_device *rdev = dev->dev_private;
mode_cmd.width = surface_width;
mode_cmd.height = surface_height;
- mode_cmd.bpp = 32;
+ mode_cmd.bpp = surface_bpp;
/* need to align pitch with crtc limits */
mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8);
- mode_cmd.depth = 24;
+ mode_cmd.depth = surface_depth;
size = mode_cmd.pitch * mode_cmd.height;
aligned_size = ALIGN(size, PAGE_SIZE);
return ret;
}
+static char *mode_option;
+int radeon_parse_options(char *options)
+{
+ char *this_opt;
+
+ if (!options || !*options)
+ return 0;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!*this_opt)
+ continue;
+ mode_option = this_opt;
+ }
+ return 0;
+}
+
int radeonfb_probe(struct drm_device *dev)
{
- int ret;
- ret = drm_fb_helper_single_fb_probe(dev, &radeonfb_create);
- return ret;
+ return drm_fb_helper_single_fb_probe(dev, &radeonfb_create);
}
-EXPORT_SYMBOL(radeonfb_probe);
int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
{
}
-/*
- * For multiple master (like multiple X).
- */
-struct drm_radeon_master_private {
- drm_local_map_t *sarea;
- drm_radeon_sarea_t *sarea_priv;
-};
-
-int radeon_master_create_kms(struct drm_device *dev, struct drm_master *master)
-{
- struct drm_radeon_master_private *master_priv;
- unsigned long sareapage;
- int ret;
-
- master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
- if (master_priv == NULL) {
- return -ENOMEM;
- }
- /* prebuild the SAREA */
- sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE);
- ret = drm_addmap(dev, 0, sareapage, _DRM_SHM,
- _DRM_CONTAINS_LOCK,
- &master_priv->sarea);
- if (ret) {
- DRM_ERROR("SAREA setup failed\n");
- return ret;
- }
- master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea);
- master_priv->sarea_priv->pfCurrentPage = 0;
- master->driver_priv = master_priv;
- return 0;
-}
-
-void radeon_master_destroy_kms(struct drm_device *dev,
- struct drm_master *master)
-{
- struct drm_radeon_master_private *master_priv = master->driver_priv;
-
- if (master_priv == NULL) {
- return;
- }
- if (master_priv->sarea) {
- drm_rmmap_locked(dev, master_priv->sarea);
- }
- kfree(master_priv);
- master->driver_priv = NULL;
-}
-
-
/*
* IOCTL.
*/
# define RADEON_CP_PACKET_MAX_DWORDS (1 << 12)
# define RADEON_CP_PACKET0_REG_MASK 0x000007ff
# define R300_CP_PACKET0_REG_MASK 0x00001fff
+# define R600_CP_PACKET0_REG_MASK 0x0000ffff
# define RADEON_CP_PACKET1_REG0_MASK 0x000007ff
# define RADEON_CP_PACKET1_REG1_MASK 0x003ff800
#define RADEON_DEBUGFS_MEM_TYPES 2
-static struct drm_info_list radeon_mem_types_list[RADEON_DEBUGFS_MEM_TYPES];
-static char radeon_mem_types_names[RADEON_DEBUGFS_MEM_TYPES][32];
-
#if defined(CONFIG_DEBUG_FS)
static int radeon_mm_dump_table(struct seq_file *m, void *data)
{
static int radeon_ttm_debugfs_init(struct radeon_device *rdev)
{
+#if defined(CONFIG_DEBUG_FS)
+ static struct drm_info_list radeon_mem_types_list[RADEON_DEBUGFS_MEM_TYPES];
+ static char radeon_mem_types_names[RADEON_DEBUGFS_MEM_TYPES][32];
unsigned i;
-#if defined(CONFIG_DEBUG_FS)
for (i = 0; i < RADEON_DEBUGFS_MEM_TYPES; i++) {
if (i == 0)
sprintf(radeon_mem_types_names[i], "radeon_vram_mm");
#include "drmP.h"
#include "radeon_reg.h"
#include "radeon.h"
-#include "avivod.h"
#include "rs600_reg_safe.h"
*/
void rs600_gpu_init(struct radeon_device *rdev);
int rs600_mc_wait_for_idle(struct radeon_device *rdev);
-void rs600_disable_vga(struct radeon_device *rdev);
/*
"programming pipes. Bad things might happen.\n");
}
- radeon_avivo_vga_render_disable(rdev);
+ rv515_vga_render_disable(rdev);
tmp = RREG32(AVIVO_D1VGA_CONTROL);
WREG32(AVIVO_D1VGA_CONTROL, tmp & ~AVIVO_DVGA_CONTROL_MODE_ENABLE);
/*
* Global GPU functions
*/
-void rs600_disable_vga(struct radeon_device *rdev)
-{
- unsigned tmp;
-
- WREG32(0x330, 0);
- WREG32(0x338, 0);
- tmp = RREG32(0x300);
- tmp &= ~(3 << 16);
- WREG32(0x300, tmp);
- WREG32(0x308, (1 << 8));
- WREG32(0x310, rdev->mc.vram_location);
- WREG32(0x594, 0);
-}
-
int rs600_mc_wait_for_idle(struct radeon_device *rdev)
{
unsigned i;
{
/* FIXME: HDP same place on rs600 ? */
r100_hdp_reset(rdev);
- rs600_disable_vga(rdev);
+ rv515_vga_render_disable(rdev);
/* FIXME: is this correct ? */
r420_pipes_init(rdev);
if (rs600_mc_wait_for_idle(rdev)) {
int rs400_gart_enable(struct radeon_device *rdev);
void rs400_gart_adjust_size(struct radeon_device *rdev);
void rs600_mc_disable_clients(struct radeon_device *rdev);
-void rs600_disable_vga(struct radeon_device *rdev);
/* This files gather functions specifics to :
* rs690,rs740
{
/* FIXME: HDP same place on rs690 ? */
r100_hdp_reset(rdev);
- rs600_disable_vga(rdev);
+ rv515_vga_render_disable(rdev);
/* FIXME: is this correct ? */
r420_pipes_init(rdev);
if (rs690_mc_wait_for_idle(rdev)) {
#include "drmP.h"
#include "rv515d.h"
#include "radeon.h"
-
+#include "atom.h"
#include "rv515_reg_safe.h"
-/* rv515 depends on : */
-void r100_hdp_reset(struct radeon_device *rdev);
-int r100_cp_reset(struct radeon_device *rdev);
-int r100_rb2d_reset(struct radeon_device *rdev);
-int r100_gui_wait_for_idle(struct radeon_device *rdev);
-int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
-void r420_pipes_init(struct radeon_device *rdev);
-void rs600_mc_disable_clients(struct radeon_device *rdev);
-void rs600_disable_vga(struct radeon_device *rdev);
-
-/* This files gather functions specifics to:
- * rv515
- *
- * Some of these functions might be used by newer ASICs.
- */
+
+/* This files gather functions specifics to: rv515 */
int rv515_debugfs_pipes_info_init(struct radeon_device *rdev);
int rv515_debugfs_ga_info_init(struct radeon_device *rdev);
void rv515_gpu_init(struct radeon_device *rdev);
int rv515_mc_wait_for_idle(struct radeon_device *rdev);
-
-/*
- * MC
- */
-int rv515_mc_init(struct radeon_device *rdev)
+void rv515_debugfs(struct radeon_device *rdev)
{
- uint32_t tmp;
- int r;
-
if (r100_debugfs_rbbm_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for RBBM !\n");
}
if (rv515_debugfs_ga_info_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for pipes !\n");
}
-
- rv515_gpu_init(rdev);
- rv370_pcie_gart_disable(rdev);
-
- /* Setup GPU memory space */
- rdev->mc.vram_location = 0xFFFFFFFFUL;
- rdev->mc.gtt_location = 0xFFFFFFFFUL;
- if (rdev->flags & RADEON_IS_AGP) {
- r = radeon_agp_init(rdev);
- if (r) {
- printk(KERN_WARNING "[drm] Disabling AGP\n");
- rdev->flags &= ~RADEON_IS_AGP;
- rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
- } else {
- rdev->mc.gtt_location = rdev->mc.agp_base;
- }
- }
- r = radeon_mc_setup(rdev);
- if (r) {
- return r;
- }
-
- /* Program GPU memory space */
- rs600_mc_disable_clients(rdev);
- if (rv515_mc_wait_for_idle(rdev)) {
- printk(KERN_WARNING "Failed to wait MC idle while "
- "programming pipes. Bad things might happen.\n");
- }
- /* Write VRAM size in case we are limiting it */
- WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
- tmp = REG_SET(MC_FB_START, rdev->mc.vram_location >> 16);
- WREG32(0x134, tmp);
- tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
- tmp = REG_SET(MC_FB_TOP, tmp >> 16);
- tmp |= REG_SET(MC_FB_START, rdev->mc.vram_location >> 16);
- WREG32_MC(MC_FB_LOCATION, tmp);
- WREG32(HDP_FB_LOCATION, rdev->mc.vram_location >> 16);
- WREG32(0x310, rdev->mc.vram_location);
- if (rdev->flags & RADEON_IS_AGP) {
- tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
- tmp = REG_SET(MC_AGP_TOP, tmp >> 16);
- tmp |= REG_SET(MC_AGP_START, rdev->mc.gtt_location >> 16);
- WREG32_MC(MC_AGP_LOCATION, tmp);
- WREG32_MC(MC_AGP_BASE, rdev->mc.agp_base);
- WREG32_MC(MC_AGP_BASE_2, 0);
- } else {
- WREG32_MC(MC_AGP_LOCATION, 0x0FFFFFFF);
- WREG32_MC(MC_AGP_BASE, 0);
- WREG32_MC(MC_AGP_BASE_2, 0);
- }
- return 0;
-}
-
-void rv515_mc_fini(struct radeon_device *rdev)
-{
}
-
-/*
- * Global GPU functions
- */
void rv515_ring_start(struct radeon_device *rdev)
{
int r;
radeon_ring_unlock_commit(rdev);
}
-void rv515_errata(struct radeon_device *rdev)
-{
- rdev->pll_errata = 0;
-}
-
int rv515_mc_wait_for_idle(struct radeon_device *rdev)
{
unsigned i;
return -1;
}
+void rv515_vga_render_disable(struct radeon_device *rdev)
+{
+ WREG32(R_000300_VGA_RENDER_CONTROL,
+ RREG32(R_000300_VGA_RENDER_CONTROL) & C_000300_VGA_VSTATUS_CNTL);
+}
+
void rv515_gpu_init(struct radeon_device *rdev)
{
unsigned pipe_select_current, gb_pipe_select, tmp;
"reseting GPU. Bad things might happen.\n");
}
- rs600_disable_vga(rdev);
+ rv515_vga_render_disable(rdev);
r420_pipes_init(rdev);
gb_pipe_select = RREG32(0x402C);
return 0;
}
-
-/*
- * VRAM info
- */
static void rv515_vram_get_type(struct radeon_device *rdev)
{
uint32_t tmp;
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
}
-
-/*
- * Indirect registers accessor
- */
uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg)
{
uint32_t r;
WREG32(MC_IND_INDEX, 0);
}
-/*
- * Debugfs info
- */
#if defined(CONFIG_DEBUG_FS)
static int rv515_debugfs_pipes_info(struct seq_file *m, void *data)
{
#endif
}
-/*
- * Asic initialization
- */
-int rv515_init(struct radeon_device *rdev)
+void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save)
+{
+ save->d1vga_control = RREG32(R_000330_D1VGA_CONTROL);
+ save->d2vga_control = RREG32(R_000338_D2VGA_CONTROL);
+ save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL);
+ save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL);
+ save->d1crtc_control = RREG32(R_006080_D1CRTC_CONTROL);
+ save->d2crtc_control = RREG32(R_006880_D2CRTC_CONTROL);
+
+ /* Stop all video */
+ WREG32(R_000330_D1VGA_CONTROL, 0);
+ WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
+ WREG32(R_000300_VGA_RENDER_CONTROL, 0);
+ WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1);
+ WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1);
+ WREG32(R_006080_D1CRTC_CONTROL, 0);
+ WREG32(R_006880_D2CRTC_CONTROL, 0);
+ WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0);
+ WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
+}
+
+void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)
+{
+ WREG32(R_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS, rdev->mc.vram_start);
+ WREG32(R_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS, rdev->mc.vram_start);
+ WREG32(R_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS, rdev->mc.vram_start);
+ WREG32(R_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS, rdev->mc.vram_start);
+ WREG32(R_000310_VGA_MEMORY_BASE_ADDRESS, rdev->mc.vram_start);
+ /* Unlock host access */
+ WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control);
+ mdelay(1);
+ /* Restore video state */
+ WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1);
+ WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1);
+ WREG32(R_006080_D1CRTC_CONTROL, save->d1crtc_control);
+ WREG32(R_006880_D2CRTC_CONTROL, save->d2crtc_control);
+ WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0);
+ WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
+ WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control);
+ WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control);
+ WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control);
+}
+
+void rv515_mc_program(struct radeon_device *rdev)
+{
+ struct rv515_mc_save save;
+
+ /* Stops all mc clients */
+ rv515_mc_stop(rdev, &save);
+
+ /* Wait for mc idle */
+ if (rv515_mc_wait_for_idle(rdev))
+ dev_warn(rdev->dev, "Wait MC idle timeout before updating MC.\n");
+ /* Write VRAM size in case we are limiting it */
+ WREG32(R_0000F8_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
+ /* Program MC, should be a 32bits limited address space */
+ WREG32_MC(R_000001_MC_FB_LOCATION,
+ S_000001_MC_FB_START(rdev->mc.vram_start >> 16) |
+ S_000001_MC_FB_TOP(rdev->mc.vram_end >> 16));
+ WREG32(R_000134_HDP_FB_LOCATION,
+ S_000134_HDP_FB_START(rdev->mc.vram_start >> 16));
+ if (rdev->flags & RADEON_IS_AGP) {
+ WREG32_MC(R_000002_MC_AGP_LOCATION,
+ S_000002_MC_AGP_START(rdev->mc.gtt_start >> 16) |
+ S_000002_MC_AGP_TOP(rdev->mc.gtt_end >> 16));
+ WREG32_MC(R_000003_MC_AGP_BASE, lower_32_bits(rdev->mc.agp_base));
+ WREG32_MC(R_000004_MC_AGP_BASE_2,
+ S_000004_AGP_BASE_ADDR_2(upper_32_bits(rdev->mc.agp_base)));
+ } else {
+ WREG32_MC(R_000002_MC_AGP_LOCATION, 0xFFFFFFFF);
+ WREG32_MC(R_000003_MC_AGP_BASE, 0);
+ WREG32_MC(R_000004_MC_AGP_BASE_2, 0);
+ }
+
+ rv515_mc_resume(rdev, &save);
+}
+
+void rv515_clock_startup(struct radeon_device *rdev)
+{
+ if (radeon_dynclks != -1 && radeon_dynclks)
+ radeon_atom_set_clock_gating(rdev, 1);
+ /* We need to force on some of the block */
+ WREG32_PLL(R_00000F_CP_DYN_CNTL,
+ RREG32_PLL(R_00000F_CP_DYN_CNTL) | S_00000F_CP_FORCEON(1));
+ WREG32_PLL(R_000011_E2_DYN_CNTL,
+ RREG32_PLL(R_000011_E2_DYN_CNTL) | S_000011_E2_FORCEON(1));
+ WREG32_PLL(R_000013_IDCT_DYN_CNTL,
+ RREG32_PLL(R_000013_IDCT_DYN_CNTL) | S_000013_IDCT_FORCEON(1));
+}
+
+static int rv515_startup(struct radeon_device *rdev)
+{
+ int r;
+
+ rv515_mc_program(rdev);
+ /* Resume clock */
+ rv515_clock_startup(rdev);
+ /* Initialize GPU configuration (# pipes, ...) */
+ rv515_gpu_init(rdev);
+ /* Initialize GART (initialize after TTM so we can allocate
+ * memory through TTM but finalize after TTM) */
+ if (rdev->flags & RADEON_IS_PCIE) {
+ r = rv370_pcie_gart_enable(rdev);
+ if (r)
+ return r;
+ }
+ /* Enable IRQ */
+ rdev->irq.sw_int = true;
+ r100_irq_set(rdev);
+ /* 1M ring buffer */
+ r = r100_cp_init(rdev, 1024 * 1024);
+ if (r) {
+ dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+ return r;
+ }
+ r = r100_wb_init(rdev);
+ if (r)
+ dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
+ r = r100_ib_init(rdev);
+ if (r) {
+ dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+ return r;
+ }
+ return 0;
+}
+
+int rv515_resume(struct radeon_device *rdev)
+{
+ /* Make sur GART are not working */
+ if (rdev->flags & RADEON_IS_PCIE)
+ rv370_pcie_gart_disable(rdev);
+ /* Resume clock before doing reset */
+ rv515_clock_startup(rdev);
+ /* Reset gpu before posting otherwise ATOM will enter infinite loop */
+ if (radeon_gpu_reset(rdev)) {
+ dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
+ RREG32(R_000E40_RBBM_STATUS),
+ RREG32(R_0007C0_CP_STAT));
+ }
+ /* post */
+ atom_asic_init(rdev->mode_info.atom_context);
+ /* Resume clock after posting */
+ rv515_clock_startup(rdev);
+ return rv515_startup(rdev);
+}
+
+int rv515_suspend(struct radeon_device *rdev)
+{
+ r100_cp_disable(rdev);
+ r100_wb_disable(rdev);
+ r100_irq_disable(rdev);
+ if (rdev->flags & RADEON_IS_PCIE)
+ rv370_pcie_gart_disable(rdev);
+ return 0;
+}
+
+void rv515_set_safe_registers(struct radeon_device *rdev)
{
rdev->config.r300.reg_safe_bm = rv515_reg_safe_bm;
rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rv515_reg_safe_bm);
+}
+
+void rv515_fini(struct radeon_device *rdev)
+{
+ rv515_suspend(rdev);
+ r100_cp_fini(rdev);
+ r100_wb_fini(rdev);
+ r100_ib_fini(rdev);
+ radeon_gem_fini(rdev);
+ rv370_pcie_gart_fini(rdev);
+ radeon_agp_fini(rdev);
+ radeon_irq_kms_fini(rdev);
+ radeon_fence_driver_fini(rdev);
+ radeon_object_fini(rdev);
+ radeon_atombios_fini(rdev);
+ kfree(rdev->bios);
+ rdev->bios = NULL;
+}
+
+int rv515_init(struct radeon_device *rdev)
+{
+ int r;
+
+ rdev->new_init_path = true;
+ /* Initialize scratch registers */
+ radeon_scratch_init(rdev);
+ /* Initialize surface registers */
+ radeon_surface_init(rdev);
+ /* TODO: disable VGA need to use VGA request */
+ /* BIOS*/
+ if (!radeon_get_bios(rdev)) {
+ if (ASIC_IS_AVIVO(rdev))
+ return -EINVAL;
+ }
+ if (rdev->is_atom_bios) {
+ r = radeon_atombios_init(rdev);
+ if (r)
+ return r;
+ } else {
+ dev_err(rdev->dev, "Expecting atombios for RV515 GPU\n");
+ return -EINVAL;
+ }
+ /* Reset gpu before posting otherwise ATOM will enter infinite loop */
+ if (radeon_gpu_reset(rdev)) {
+ dev_warn(rdev->dev,
+ "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
+ RREG32(R_000E40_RBBM_STATUS),
+ RREG32(R_0007C0_CP_STAT));
+ }
+ /* check if cards are posted or not */
+ if (!radeon_card_posted(rdev) && rdev->bios) {
+ DRM_INFO("GPU not posted. posting now...\n");
+ atom_asic_init(rdev->mode_info.atom_context);
+ }
+ /* Initialize clocks */
+ radeon_get_clock_info(rdev->ddev);
+ /* Get vram informations */
+ rv515_vram_info(rdev);
+ /* Initialize memory controller (also test AGP) */
+ r = r420_mc_init(rdev);
+ if (r)
+ return r;
+ rv515_debugfs(rdev);
+ /* Fence driver */
+ r = radeon_fence_driver_init(rdev);
+ if (r)
+ return r;
+ r = radeon_irq_kms_init(rdev);
+ if (r)
+ return r;
+ /* Memory manager */
+ r = radeon_object_init(rdev);
+ if (r)
+ return r;
+ r = rv370_pcie_gart_init(rdev);
+ if (r)
+ return r;
+ rv515_set_safe_registers(rdev);
+ rdev->accel_working = true;
+ r = rv515_startup(rdev);
+ if (r) {
+ /* Somethings want wront with the accel init stop accel */
+ dev_err(rdev->dev, "Disabling GPU acceleration\n");
+ rv515_suspend(rdev);
+ r100_cp_fini(rdev);
+ r100_wb_fini(rdev);
+ r100_ib_fini(rdev);
+ rv370_pcie_gart_fini(rdev);
+ radeon_agp_fini(rdev);
+ radeon_irq_kms_fini(rdev);
+ rdev->accel_working = false;
+ }
return 0;
}
#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1)
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
-#endif
+/* Registers */
+#define R_0000F8_CONFIG_MEMSIZE 0x0000F8
+#define S_0000F8_CONFIG_MEMSIZE(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_0000F8_CONFIG_MEMSIZE(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_0000F8_CONFIG_MEMSIZE 0x00000000
+#define R_000134_HDP_FB_LOCATION 0x000134
+#define S_000134_HDP_FB_START(x) (((x) & 0xFFFF) << 0)
+#define G_000134_HDP_FB_START(x) (((x) >> 0) & 0xFFFF)
+#define C_000134_HDP_FB_START 0xFFFF0000
+#define R_000300_VGA_RENDER_CONTROL 0x000300
+#define S_000300_VGA_BLINK_RATE(x) (((x) & 0x1F) << 0)
+#define G_000300_VGA_BLINK_RATE(x) (((x) >> 0) & 0x1F)
+#define C_000300_VGA_BLINK_RATE 0xFFFFFFE0
+#define S_000300_VGA_BLINK_MODE(x) (((x) & 0x3) << 5)
+#define G_000300_VGA_BLINK_MODE(x) (((x) >> 5) & 0x3)
+#define C_000300_VGA_BLINK_MODE 0xFFFFFF9F
+#define S_000300_VGA_CURSOR_BLINK_INVERT(x) (((x) & 0x1) << 7)
+#define G_000300_VGA_CURSOR_BLINK_INVERT(x) (((x) >> 7) & 0x1)
+#define C_000300_VGA_CURSOR_BLINK_INVERT 0xFFFFFF7F
+#define S_000300_VGA_EXTD_ADDR_COUNT_ENABLE(x) (((x) & 0x1) << 8)
+#define G_000300_VGA_EXTD_ADDR_COUNT_ENABLE(x) (((x) >> 8) & 0x1)
+#define C_000300_VGA_EXTD_ADDR_COUNT_ENABLE 0xFFFFFEFF
+#define S_000300_VGA_VSTATUS_CNTL(x) (((x) & 0x3) << 16)
+#define G_000300_VGA_VSTATUS_CNTL(x) (((x) >> 16) & 0x3)
+#define C_000300_VGA_VSTATUS_CNTL 0xFFFCFFFF
+#define S_000300_VGA_LOCK_8DOT(x) (((x) & 0x1) << 24)
+#define G_000300_VGA_LOCK_8DOT(x) (((x) >> 24) & 0x1)
+#define C_000300_VGA_LOCK_8DOT 0xFEFFFFFF
+#define S_000300_VGAREG_LINECMP_COMPATIBILITY_SEL(x) (((x) & 0x1) << 25)
+#define G_000300_VGAREG_LINECMP_COMPATIBILITY_SEL(x) (((x) >> 25) & 0x1)
+#define C_000300_VGAREG_LINECMP_COMPATIBILITY_SEL 0xFDFFFFFF
+#define R_000310_VGA_MEMORY_BASE_ADDRESS 0x000310
+#define S_000310_VGA_MEMORY_BASE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_000310_VGA_MEMORY_BASE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_000310_VGA_MEMORY_BASE_ADDRESS 0x00000000
+#define R_000328_VGA_HDP_CONTROL 0x000328
+#define S_000328_VGA_MEM_PAGE_SELECT_EN(x) (((x) & 0x1) << 0)
+#define G_000328_VGA_MEM_PAGE_SELECT_EN(x) (((x) >> 0) & 0x1)
+#define C_000328_VGA_MEM_PAGE_SELECT_EN 0xFFFFFFFE
+#define S_000328_VGA_RBBM_LOCK_DISABLE(x) (((x) & 0x1) << 8)
+#define G_000328_VGA_RBBM_LOCK_DISABLE(x) (((x) >> 8) & 0x1)
+#define C_000328_VGA_RBBM_LOCK_DISABLE 0xFFFFFEFF
+#define S_000328_VGA_SOFT_RESET(x) (((x) & 0x1) << 16)
+#define G_000328_VGA_SOFT_RESET(x) (((x) >> 16) & 0x1)
+#define C_000328_VGA_SOFT_RESET 0xFFFEFFFF
+#define S_000328_VGA_TEST_RESET_CONTROL(x) (((x) & 0x1) << 24)
+#define G_000328_VGA_TEST_RESET_CONTROL(x) (((x) >> 24) & 0x1)
+#define C_000328_VGA_TEST_RESET_CONTROL 0xFEFFFFFF
+#define R_000330_D1VGA_CONTROL 0x000330
+#define S_000330_D1VGA_MODE_ENABLE(x) (((x) & 0x1) << 0)
+#define G_000330_D1VGA_MODE_ENABLE(x) (((x) >> 0) & 0x1)
+#define C_000330_D1VGA_MODE_ENABLE 0xFFFFFFFE
+#define S_000330_D1VGA_TIMING_SELECT(x) (((x) & 0x1) << 8)
+#define G_000330_D1VGA_TIMING_SELECT(x) (((x) >> 8) & 0x1)
+#define C_000330_D1VGA_TIMING_SELECT 0xFFFFFEFF
+#define S_000330_D1VGA_SYNC_POLARITY_SELECT(x) (((x) & 0x1) << 9)
+#define G_000330_D1VGA_SYNC_POLARITY_SELECT(x) (((x) >> 9) & 0x1)
+#define C_000330_D1VGA_SYNC_POLARITY_SELECT 0xFFFFFDFF
+#define S_000330_D1VGA_OVERSCAN_TIMING_SELECT(x) (((x) & 0x1) << 10)
+#define G_000330_D1VGA_OVERSCAN_TIMING_SELECT(x) (((x) >> 10) & 0x1)
+#define C_000330_D1VGA_OVERSCAN_TIMING_SELECT 0xFFFFFBFF
+#define S_000330_D1VGA_OVERSCAN_COLOR_EN(x) (((x) & 0x1) << 16)
+#define G_000330_D1VGA_OVERSCAN_COLOR_EN(x) (((x) >> 16) & 0x1)
+#define C_000330_D1VGA_OVERSCAN_COLOR_EN 0xFFFEFFFF
+#define S_000330_D1VGA_ROTATE(x) (((x) & 0x3) << 24)
+#define G_000330_D1VGA_ROTATE(x) (((x) >> 24) & 0x3)
+#define C_000330_D1VGA_ROTATE 0xFCFFFFFF
+#define R_000338_D2VGA_CONTROL 0x000338
+#define S_000338_D2VGA_MODE_ENABLE(x) (((x) & 0x1) << 0)
+#define G_000338_D2VGA_MODE_ENABLE(x) (((x) >> 0) & 0x1)
+#define C_000338_D2VGA_MODE_ENABLE 0xFFFFFFFE
+#define S_000338_D2VGA_TIMING_SELECT(x) (((x) & 0x1) << 8)
+#define G_000338_D2VGA_TIMING_SELECT(x) (((x) >> 8) & 0x1)
+#define C_000338_D2VGA_TIMING_SELECT 0xFFFFFEFF
+#define S_000338_D2VGA_SYNC_POLARITY_SELECT(x) (((x) & 0x1) << 9)
+#define G_000338_D2VGA_SYNC_POLARITY_SELECT(x) (((x) >> 9) & 0x1)
+#define C_000338_D2VGA_SYNC_POLARITY_SELECT 0xFFFFFDFF
+#define S_000338_D2VGA_OVERSCAN_TIMING_SELECT(x) (((x) & 0x1) << 10)
+#define G_000338_D2VGA_OVERSCAN_TIMING_SELECT(x) (((x) >> 10) & 0x1)
+#define C_000338_D2VGA_OVERSCAN_TIMING_SELECT 0xFFFFFBFF
+#define S_000338_D2VGA_OVERSCAN_COLOR_EN(x) (((x) & 0x1) << 16)
+#define G_000338_D2VGA_OVERSCAN_COLOR_EN(x) (((x) >> 16) & 0x1)
+#define C_000338_D2VGA_OVERSCAN_COLOR_EN 0xFFFEFFFF
+#define S_000338_D2VGA_ROTATE(x) (((x) & 0x3) << 24)
+#define G_000338_D2VGA_ROTATE(x) (((x) >> 24) & 0x3)
+#define C_000338_D2VGA_ROTATE 0xFCFFFFFF
+#define R_0007C0_CP_STAT 0x0007C0
+#define S_0007C0_MRU_BUSY(x) (((x) & 0x1) << 0)
+#define G_0007C0_MRU_BUSY(x) (((x) >> 0) & 0x1)
+#define C_0007C0_MRU_BUSY 0xFFFFFFFE
+#define S_0007C0_MWU_BUSY(x) (((x) & 0x1) << 1)
+#define G_0007C0_MWU_BUSY(x) (((x) >> 1) & 0x1)
+#define C_0007C0_MWU_BUSY 0xFFFFFFFD
+#define S_0007C0_RSIU_BUSY(x) (((x) & 0x1) << 2)
+#define G_0007C0_RSIU_BUSY(x) (((x) >> 2) & 0x1)
+#define C_0007C0_RSIU_BUSY 0xFFFFFFFB
+#define S_0007C0_RCIU_BUSY(x) (((x) & 0x1) << 3)
+#define G_0007C0_RCIU_BUSY(x) (((x) >> 3) & 0x1)
+#define C_0007C0_RCIU_BUSY 0xFFFFFFF7
+#define S_0007C0_CSF_PRIMARY_BUSY(x) (((x) & 0x1) << 9)
+#define G_0007C0_CSF_PRIMARY_BUSY(x) (((x) >> 9) & 0x1)
+#define C_0007C0_CSF_PRIMARY_BUSY 0xFFFFFDFF
+#define S_0007C0_CSF_INDIRECT_BUSY(x) (((x) & 0x1) << 10)
+#define G_0007C0_CSF_INDIRECT_BUSY(x) (((x) >> 10) & 0x1)
+#define C_0007C0_CSF_INDIRECT_BUSY 0xFFFFFBFF
+#define S_0007C0_CSQ_PRIMARY_BUSY(x) (((x) & 0x1) << 11)
+#define G_0007C0_CSQ_PRIMARY_BUSY(x) (((x) >> 11) & 0x1)
+#define C_0007C0_CSQ_PRIMARY_BUSY 0xFFFFF7FF
+#define S_0007C0_CSQ_INDIRECT_BUSY(x) (((x) & 0x1) << 12)
+#define G_0007C0_CSQ_INDIRECT_BUSY(x) (((x) >> 12) & 0x1)
+#define C_0007C0_CSQ_INDIRECT_BUSY 0xFFFFEFFF
+#define S_0007C0_CSI_BUSY(x) (((x) & 0x1) << 13)
+#define G_0007C0_CSI_BUSY(x) (((x) >> 13) & 0x1)
+#define C_0007C0_CSI_BUSY 0xFFFFDFFF
+#define S_0007C0_CSF_INDIRECT2_BUSY(x) (((x) & 0x1) << 14)
+#define G_0007C0_CSF_INDIRECT2_BUSY(x) (((x) >> 14) & 0x1)
+#define C_0007C0_CSF_INDIRECT2_BUSY 0xFFFFBFFF
+#define S_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) & 0x1) << 15)
+#define G_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) >> 15) & 0x1)
+#define C_0007C0_CSQ_INDIRECT2_BUSY 0xFFFF7FFF
+#define S_0007C0_GUIDMA_BUSY(x) (((x) & 0x1) << 28)
+#define G_0007C0_GUIDMA_BUSY(x) (((x) >> 28) & 0x1)
+#define C_0007C0_GUIDMA_BUSY 0xEFFFFFFF
+#define S_0007C0_VIDDMA_BUSY(x) (((x) & 0x1) << 29)
+#define G_0007C0_VIDDMA_BUSY(x) (((x) >> 29) & 0x1)
+#define C_0007C0_VIDDMA_BUSY 0xDFFFFFFF
+#define S_0007C0_CMDSTRM_BUSY(x) (((x) & 0x1) << 30)
+#define G_0007C0_CMDSTRM_BUSY(x) (((x) >> 30) & 0x1)
+#define C_0007C0_CMDSTRM_BUSY 0xBFFFFFFF
+#define S_0007C0_CP_BUSY(x) (((x) & 0x1) << 31)
+#define G_0007C0_CP_BUSY(x) (((x) >> 31) & 0x1)
+#define C_0007C0_CP_BUSY 0x7FFFFFFF
+#define R_000E40_RBBM_STATUS 0x000E40
+#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0)
+#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F)
+#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80
+#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8)
+#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1)
+#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF
+#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9)
+#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1)
+#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF
+#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10)
+#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1)
+#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF
+#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11)
+#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1)
+#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF
+#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12)
+#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1)
+#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF
+#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13)
+#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1)
+#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF
+#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14)
+#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1)
+#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF
+#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15)
+#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1)
+#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF
+#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16)
+#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1)
+#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF
+#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17)
+#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1)
+#define C_000E40_E2_BUSY 0xFFFDFFFF
+#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18)
+#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1)
+#define C_000E40_RB2D_BUSY 0xFFFBFFFF
+#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19)
+#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1)
+#define C_000E40_RB3D_BUSY 0xFFF7FFFF
+#define S_000E40_VAP_BUSY(x) (((x) & 0x1) << 20)
+#define G_000E40_VAP_BUSY(x) (((x) >> 20) & 0x1)
+#define C_000E40_VAP_BUSY 0xFFEFFFFF
+#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21)
+#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1)
+#define C_000E40_RE_BUSY 0xFFDFFFFF
+#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22)
+#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1)
+#define C_000E40_TAM_BUSY 0xFFBFFFFF
+#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23)
+#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1)
+#define C_000E40_TDM_BUSY 0xFF7FFFFF
+#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24)
+#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1)
+#define C_000E40_PB_BUSY 0xFEFFFFFF
+#define S_000E40_TIM_BUSY(x) (((x) & 0x1) << 25)
+#define G_000E40_TIM_BUSY(x) (((x) >> 25) & 0x1)
+#define C_000E40_TIM_BUSY 0xFDFFFFFF
+#define S_000E40_GA_BUSY(x) (((x) & 0x1) << 26)
+#define G_000E40_GA_BUSY(x) (((x) >> 26) & 0x1)
+#define C_000E40_GA_BUSY 0xFBFFFFFF
+#define S_000E40_CBA2D_BUSY(x) (((x) & 0x1) << 27)
+#define G_000E40_CBA2D_BUSY(x) (((x) >> 27) & 0x1)
+#define C_000E40_CBA2D_BUSY 0xF7FFFFFF
+#define S_000E40_RBBM_HIBUSY(x) (((x) & 0x1) << 28)
+#define G_000E40_RBBM_HIBUSY(x) (((x) >> 28) & 0x1)
+#define C_000E40_RBBM_HIBUSY 0xEFFFFFFF
+#define S_000E40_SKID_CFBUSY(x) (((x) & 0x1) << 29)
+#define G_000E40_SKID_CFBUSY(x) (((x) >> 29) & 0x1)
+#define C_000E40_SKID_CFBUSY 0xDFFFFFFF
+#define S_000E40_VAP_VF_BUSY(x) (((x) & 0x1) << 30)
+#define G_000E40_VAP_VF_BUSY(x) (((x) >> 30) & 0x1)
+#define C_000E40_VAP_VF_BUSY 0xBFFFFFFF
+#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31)
+#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1)
+#define C_000E40_GUI_ACTIVE 0x7FFFFFFF
+#define R_006080_D1CRTC_CONTROL 0x006080
+#define S_006080_D1CRTC_MASTER_EN(x) (((x) & 0x1) << 0)
+#define G_006080_D1CRTC_MASTER_EN(x) (((x) >> 0) & 0x1)
+#define C_006080_D1CRTC_MASTER_EN 0xFFFFFFFE
+#define S_006080_D1CRTC_SYNC_RESET_SEL(x) (((x) & 0x1) << 4)
+#define G_006080_D1CRTC_SYNC_RESET_SEL(x) (((x) >> 4) & 0x1)
+#define C_006080_D1CRTC_SYNC_RESET_SEL 0xFFFFFFEF
+#define S_006080_D1CRTC_DISABLE_POINT_CNTL(x) (((x) & 0x3) << 8)
+#define G_006080_D1CRTC_DISABLE_POINT_CNTL(x) (((x) >> 8) & 0x3)
+#define C_006080_D1CRTC_DISABLE_POINT_CNTL 0xFFFFFCFF
+#define S_006080_D1CRTC_CURRENT_MASTER_EN_STATE(x) (((x) & 0x1) << 16)
+#define G_006080_D1CRTC_CURRENT_MASTER_EN_STATE(x) (((x) >> 16) & 0x1)
+#define C_006080_D1CRTC_CURRENT_MASTER_EN_STATE 0xFFFEFFFF
+#define S_006080_D1CRTC_DISP_READ_REQUEST_DISABLE(x) (((x) & 0x1) << 24)
+#define G_006080_D1CRTC_DISP_READ_REQUEST_DISABLE(x) (((x) >> 24) & 0x1)
+#define C_006080_D1CRTC_DISP_READ_REQUEST_DISABLE 0xFEFFFFFF
+#define R_0060E8_D1CRTC_UPDATE_LOCK 0x0060E8
+#define S_0060E8_D1CRTC_UPDATE_LOCK(x) (((x) & 0x1) << 0)
+#define G_0060E8_D1CRTC_UPDATE_LOCK(x) (((x) >> 0) & 0x1)
+#define C_0060E8_D1CRTC_UPDATE_LOCK 0xFFFFFFFE
+#define R_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS 0x006110
+#define S_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS 0x00000000
+#define R_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS 0x006118
+#define S_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS 0x00000000
+#define R_006880_D2CRTC_CONTROL 0x006880
+#define S_006880_D2CRTC_MASTER_EN(x) (((x) & 0x1) << 0)
+#define G_006880_D2CRTC_MASTER_EN(x) (((x) >> 0) & 0x1)
+#define C_006880_D2CRTC_MASTER_EN 0xFFFFFFFE
+#define S_006880_D2CRTC_SYNC_RESET_SEL(x) (((x) & 0x1) << 4)
+#define G_006880_D2CRTC_SYNC_RESET_SEL(x) (((x) >> 4) & 0x1)
+#define C_006880_D2CRTC_SYNC_RESET_SEL 0xFFFFFFEF
+#define S_006880_D2CRTC_DISABLE_POINT_CNTL(x) (((x) & 0x3) << 8)
+#define G_006880_D2CRTC_DISABLE_POINT_CNTL(x) (((x) >> 8) & 0x3)
+#define C_006880_D2CRTC_DISABLE_POINT_CNTL 0xFFFFFCFF
+#define S_006880_D2CRTC_CURRENT_MASTER_EN_STATE(x) (((x) & 0x1) << 16)
+#define G_006880_D2CRTC_CURRENT_MASTER_EN_STATE(x) (((x) >> 16) & 0x1)
+#define C_006880_D2CRTC_CURRENT_MASTER_EN_STATE 0xFFFEFFFF
+#define S_006880_D2CRTC_DISP_READ_REQUEST_DISABLE(x) (((x) & 0x1) << 24)
+#define G_006880_D2CRTC_DISP_READ_REQUEST_DISABLE(x) (((x) >> 24) & 0x1)
+#define C_006880_D2CRTC_DISP_READ_REQUEST_DISABLE 0xFEFFFFFF
+#define R_0068E8_D2CRTC_UPDATE_LOCK 0x0068E8
+#define S_0068E8_D2CRTC_UPDATE_LOCK(x) (((x) & 0x1) << 0)
+#define G_0068E8_D2CRTC_UPDATE_LOCK(x) (((x) >> 0) & 0x1)
+#define C_0068E8_D2CRTC_UPDATE_LOCK 0xFFFFFFFE
+#define R_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS 0x006910
+#define S_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS 0x00000000
+#define R_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS 0x006918
+#define S_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS 0x00000000
+
+
+#define R_000001_MC_FB_LOCATION 0x000001
+#define S_000001_MC_FB_START(x) (((x) & 0xFFFF) << 0)
+#define G_000001_MC_FB_START(x) (((x) >> 0) & 0xFFFF)
+#define C_000001_MC_FB_START 0xFFFF0000
+#define S_000001_MC_FB_TOP(x) (((x) & 0xFFFF) << 16)
+#define G_000001_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF)
+#define C_000001_MC_FB_TOP 0x0000FFFF
+#define R_000002_MC_AGP_LOCATION 0x000002
+#define S_000002_MC_AGP_START(x) (((x) & 0xFFFF) << 0)
+#define G_000002_MC_AGP_START(x) (((x) >> 0) & 0xFFFF)
+#define C_000002_MC_AGP_START 0xFFFF0000
+#define S_000002_MC_AGP_TOP(x) (((x) & 0xFFFF) << 16)
+#define G_000002_MC_AGP_TOP(x) (((x) >> 16) & 0xFFFF)
+#define C_000002_MC_AGP_TOP 0x0000FFFF
+#define R_000003_MC_AGP_BASE 0x000003
+#define S_000003_AGP_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0)
+#define G_000003_AGP_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF)
+#define C_000003_AGP_BASE_ADDR 0x00000000
+#define R_000004_MC_AGP_BASE_2 0x000004
+#define S_000004_AGP_BASE_ADDR_2(x) (((x) & 0xF) << 0)
+#define G_000004_AGP_BASE_ADDR_2(x) (((x) >> 0) & 0xF)
+#define C_000004_AGP_BASE_ADDR_2 0xFFFFFFF0
+
+#define R_00000F_CP_DYN_CNTL 0x00000F
+#define S_00000F_CP_FORCEON(x) (((x) & 0x1) << 0)
+#define G_00000F_CP_FORCEON(x) (((x) >> 0) & 0x1)
+#define C_00000F_CP_FORCEON 0xFFFFFFFE
+#define S_00000F_CP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 1)
+#define G_00000F_CP_MAX_DYN_STOP_LAT(x) (((x) >> 1) & 0x1)
+#define C_00000F_CP_MAX_DYN_STOP_LAT 0xFFFFFFFD
+#define S_00000F_CP_CLOCK_STATUS(x) (((x) & 0x1) << 2)
+#define G_00000F_CP_CLOCK_STATUS(x) (((x) >> 2) & 0x1)
+#define C_00000F_CP_CLOCK_STATUS 0xFFFFFFFB
+#define S_00000F_CP_PROG_SHUTOFF(x) (((x) & 0x1) << 3)
+#define G_00000F_CP_PROG_SHUTOFF(x) (((x) >> 3) & 0x1)
+#define C_00000F_CP_PROG_SHUTOFF 0xFFFFFFF7
+#define S_00000F_CP_PROG_DELAY_VALUE(x) (((x) & 0xFF) << 4)
+#define G_00000F_CP_PROG_DELAY_VALUE(x) (((x) >> 4) & 0xFF)
+#define C_00000F_CP_PROG_DELAY_VALUE 0xFFFFF00F
+#define S_00000F_CP_LOWER_POWER_IDLE(x) (((x) & 0xFF) << 12)
+#define G_00000F_CP_LOWER_POWER_IDLE(x) (((x) >> 12) & 0xFF)
+#define C_00000F_CP_LOWER_POWER_IDLE 0xFFF00FFF
+#define S_00000F_CP_LOWER_POWER_IGNORE(x) (((x) & 0x1) << 20)
+#define G_00000F_CP_LOWER_POWER_IGNORE(x) (((x) >> 20) & 0x1)
+#define C_00000F_CP_LOWER_POWER_IGNORE 0xFFEFFFFF
+#define S_00000F_CP_NORMAL_POWER_IGNORE(x) (((x) & 0x1) << 21)
+#define G_00000F_CP_NORMAL_POWER_IGNORE(x) (((x) >> 21) & 0x1)
+#define C_00000F_CP_NORMAL_POWER_IGNORE 0xFFDFFFFF
+#define S_00000F_SPARE(x) (((x) & 0x3) << 22)
+#define G_00000F_SPARE(x) (((x) >> 22) & 0x3)
+#define C_00000F_SPARE 0xFF3FFFFF
+#define S_00000F_CP_NORMAL_POWER_BUSY(x) (((x) & 0xFF) << 24)
+#define G_00000F_CP_NORMAL_POWER_BUSY(x) (((x) >> 24) & 0xFF)
+#define C_00000F_CP_NORMAL_POWER_BUSY 0x00FFFFFF
+#define R_000011_E2_DYN_CNTL 0x000011
+#define S_000011_E2_FORCEON(x) (((x) & 0x1) << 0)
+#define G_000011_E2_FORCEON(x) (((x) >> 0) & 0x1)
+#define C_000011_E2_FORCEON 0xFFFFFFFE
+#define S_000011_E2_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 1)
+#define G_000011_E2_MAX_DYN_STOP_LAT(x) (((x) >> 1) & 0x1)
+#define C_000011_E2_MAX_DYN_STOP_LAT 0xFFFFFFFD
+#define S_000011_E2_CLOCK_STATUS(x) (((x) & 0x1) << 2)
+#define G_000011_E2_CLOCK_STATUS(x) (((x) >> 2) & 0x1)
+#define C_000011_E2_CLOCK_STATUS 0xFFFFFFFB
+#define S_000011_E2_PROG_SHUTOFF(x) (((x) & 0x1) << 3)
+#define G_000011_E2_PROG_SHUTOFF(x) (((x) >> 3) & 0x1)
+#define C_000011_E2_PROG_SHUTOFF 0xFFFFFFF7
+#define S_000011_E2_PROG_DELAY_VALUE(x) (((x) & 0xFF) << 4)
+#define G_000011_E2_PROG_DELAY_VALUE(x) (((x) >> 4) & 0xFF)
+#define C_000011_E2_PROG_DELAY_VALUE 0xFFFFF00F
+#define S_000011_E2_LOWER_POWER_IDLE(x) (((x) & 0xFF) << 12)
+#define G_000011_E2_LOWER_POWER_IDLE(x) (((x) >> 12) & 0xFF)
+#define C_000011_E2_LOWER_POWER_IDLE 0xFFF00FFF
+#define S_000011_E2_LOWER_POWER_IGNORE(x) (((x) & 0x1) << 20)
+#define G_000011_E2_LOWER_POWER_IGNORE(x) (((x) >> 20) & 0x1)
+#define C_000011_E2_LOWER_POWER_IGNORE 0xFFEFFFFF
+#define S_000011_E2_NORMAL_POWER_IGNORE(x) (((x) & 0x1) << 21)
+#define G_000011_E2_NORMAL_POWER_IGNORE(x) (((x) >> 21) & 0x1)
+#define C_000011_E2_NORMAL_POWER_IGNORE 0xFFDFFFFF
+#define S_000011_SPARE(x) (((x) & 0x3) << 22)
+#define G_000011_SPARE(x) (((x) >> 22) & 0x3)
+#define C_000011_SPARE 0xFF3FFFFF
+#define S_000011_E2_NORMAL_POWER_BUSY(x) (((x) & 0xFF) << 24)
+#define G_000011_E2_NORMAL_POWER_BUSY(x) (((x) >> 24) & 0xFF)
+#define C_000011_E2_NORMAL_POWER_BUSY 0x00FFFFFF
+#define R_000013_IDCT_DYN_CNTL 0x000013
+#define S_000013_IDCT_FORCEON(x) (((x) & 0x1) << 0)
+#define G_000013_IDCT_FORCEON(x) (((x) >> 0) & 0x1)
+#define C_000013_IDCT_FORCEON 0xFFFFFFFE
+#define S_000013_IDCT_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 1)
+#define G_000013_IDCT_MAX_DYN_STOP_LAT(x) (((x) >> 1) & 0x1)
+#define C_000013_IDCT_MAX_DYN_STOP_LAT 0xFFFFFFFD
+#define S_000013_IDCT_CLOCK_STATUS(x) (((x) & 0x1) << 2)
+#define G_000013_IDCT_CLOCK_STATUS(x) (((x) >> 2) & 0x1)
+#define C_000013_IDCT_CLOCK_STATUS 0xFFFFFFFB
+#define S_000013_IDCT_PROG_SHUTOFF(x) (((x) & 0x1) << 3)
+#define G_000013_IDCT_PROG_SHUTOFF(x) (((x) >> 3) & 0x1)
+#define C_000013_IDCT_PROG_SHUTOFF 0xFFFFFFF7
+#define S_000013_IDCT_PROG_DELAY_VALUE(x) (((x) & 0xFF) << 4)
+#define G_000013_IDCT_PROG_DELAY_VALUE(x) (((x) >> 4) & 0xFF)
+#define C_000013_IDCT_PROG_DELAY_VALUE 0xFFFFF00F
+#define S_000013_IDCT_LOWER_POWER_IDLE(x) (((x) & 0xFF) << 12)
+#define G_000013_IDCT_LOWER_POWER_IDLE(x) (((x) >> 12) & 0xFF)
+#define C_000013_IDCT_LOWER_POWER_IDLE 0xFFF00FFF
+#define S_000013_IDCT_LOWER_POWER_IGNORE(x) (((x) & 0x1) << 20)
+#define G_000013_IDCT_LOWER_POWER_IGNORE(x) (((x) >> 20) & 0x1)
+#define C_000013_IDCT_LOWER_POWER_IGNORE 0xFFEFFFFF
+#define S_000013_IDCT_NORMAL_POWER_IGNORE(x) (((x) & 0x1) << 21)
+#define G_000013_IDCT_NORMAL_POWER_IGNORE(x) (((x) >> 21) & 0x1)
+#define C_000013_IDCT_NORMAL_POWER_IGNORE 0xFFDFFFFF
+#define S_000013_SPARE(x) (((x) & 0x3) << 22)
+#define G_000013_SPARE(x) (((x) >> 22) & 0x3)
+#define C_000013_SPARE 0xFF3FFFFF
+#define S_000013_IDCT_NORMAL_POWER_BUSY(x) (((x) & 0xFF) << 24)
+#define G_000013_IDCT_NORMAL_POWER_BUSY(x) (((x) >> 24) & 0xFF)
+#define C_000013_IDCT_NORMAL_POWER_BUSY 0x00FFFFFF
+
+#endif
#include "radeon.h"
#include "radeon_drm.h"
#include "rv770d.h"
-#include "avivod.h"
#include "atom.h"
+#include "avivod.h"
#define R700_PFP_UCODE_SIZE 848
#define R700_PM4_UCODE_SIZE 1360
/* we need to own VRAM, so turn off the VGA renderer here
* to stop it overwriting our objects */
- radeon_avivo_vga_render_disable(rdev);
+ rv515_vga_render_disable(rdev);
}
/* Setup GPU memory space */
rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
+
+ if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
+ rdev->mc.mc_vram_size = rdev->mc.aper_size;
+
+ if (rdev->mc.real_vram_size > rdev->mc.aper_size)
+ rdev->mc.real_vram_size = rdev->mc.aper_size;
+
if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev);
if (r)
return ret;
}
-static struct file_operations watchdog_fops = {
+static const struct file_operations watchdog_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.open = watchdog_open,
cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
list_del(&cq->entry);
- __queue_comp_task(cq, per_cpu_ptr(pool->cpu_comp_tasks,
- smp_processor_id()));
+ __queue_comp_task(cq, this_cpu_ptr(pool->cpu_comp_tasks));
}
spin_unlock_irqrestore(&cct->task_lock, flags_cct);
} \
} while (0)
+#ifdef CONFIG_PM
static void input_dev_reset(struct input_dev *dev, bool activate)
{
if (!dev->event)
}
}
-#ifdef CONFIG_PM
static int input_dev_suspend(struct device *dev)
{
struct input_dev *input_dev = to_input_dev(dev);
depends on PCI
select MISDN_IPAC
select ISDN_HDLC
+ select ISDN_I4L
help
Enable support for Traverse Technologies NETJet PCI cards.
endif
config ISDN_HDLC
- tristate
- depends on HISAX_ST5481
+ tristate
select CRC_CCITT
select BITREVERSE
}
static int data_sock_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int len)
+ char __user *optval, unsigned int len)
{
struct sock *sk = sock->sk;
int err = 0, opt = 0;
* uses: reading and writing a character device called /dev/lguest. All the
* work happens in the read(), write() and close() routines:
*/
-static struct file_operations lguest_fops = {
+static const struct file_operations lguest_fops = {
.owner = THIS_MODULE,
.release = close,
.write = write,
return mask;
}
-static struct file_operations dvb_dvr_fops = {
+static const struct file_operations dvb_dvr_fops = {
.owner = THIS_MODULE,
.read = dvb_dvr_read,
.write = dvb_dvr_write,
return POLLIN;
}
-static struct file_operations fdtv_ca_fops = {
+static const struct file_operations fdtv_ca_fops = {
.owner = THIS_MODULE,
.ioctl = dvb_generic_ioctl,
.open = dvb_generic_open,
return mask;
}
-static struct file_operations phantom_file_ops = {
+static const struct file_operations phantom_file_ops = {
.open = phantom_open,
.release = phantom_release,
.unlocked_ioctl = phantom_ioctl,
/* Guaranteed user available resources on each node */
static int max_user_cbrs, max_user_dsr_bytes;
-static struct file_operations gru_fops;
static struct miscdevice gru_miscdev;
gru_proc_exit();
}
-static struct file_operations gru_fops = {
+static const struct file_operations gru_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = gru_file_unlocked_ioctl,
.mmap = gru_file_mmap,
return 0;
}
-static struct file_operations mmc_dbg_ext_csd_fops = {
+static const struct file_operations mmc_dbg_ext_csd_fops = {
.open = mmc_ext_csd_open,
.read = mmc_ext_csd_read,
.release = mmc_ext_csd_release,
static const unsigned int speed_unit[8] =
{ 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 };
+/* FUNCE tuples with these types get passed to SDIO drivers */
+static const unsigned char funce_type_whitelist[] = {
+ 4 /* CISTPL_FUNCE_LAN_NODE_ID used in Broadcom cards */
+};
+
+static int cistpl_funce_whitelisted(unsigned char type)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(funce_type_whitelist); i++) {
+ if (funce_type_whitelist[i] == type)
+ return 1;
+ }
+ return 0;
+}
+
static int cistpl_funce_common(struct mmc_card *card,
const unsigned char *buf, unsigned size)
{
unsigned vsn;
unsigned min_size;
+ /* let SDIO drivers take care of whitelisted FUNCE tuples */
+ if (cistpl_funce_whitelisted(buf[0]))
+ return -EILSEQ;
+
vsn = func->card->cccr.sdio_vsn;
min_size = (vsn == SDIO_SDIO_REV_1_00) ? 28 : 42;
else
ret = cistpl_funce_common(card, buf, size);
- if (ret) {
+ if (ret && ret != -EILSEQ) {
printk(KERN_ERR "%s: bad CISTPL_FUNCE size %u "
"type %u\n", mmc_hostname(card->host), size, buf[0]);
- return ret;
}
- return 0;
+ return ret;
}
typedef int (tpl_parse_t)(struct mmc_card *, struct sdio_func *,
for (i = 0; i < ARRAY_SIZE(cis_tpl_list); i++)
if (cis_tpl_list[i].code == tpl_code)
break;
- if (i >= ARRAY_SIZE(cis_tpl_list)) {
- /* this tuple is unknown to the core */
- this->next = NULL;
- this->code = tpl_code;
- this->size = tpl_link;
- *prev = this;
- prev = &this->next;
- printk(KERN_DEBUG
- "%s: queuing CIS tuple 0x%02x length %u\n",
- mmc_hostname(card->host), tpl_code, tpl_link);
- } else {
+ if (i < ARRAY_SIZE(cis_tpl_list)) {
const struct cis_tpl *tpl = cis_tpl_list + i;
if (tpl_link < tpl->min_size) {
printk(KERN_ERR
- "%s: bad CIS tuple 0x%02x (length = %u, expected >= %u)\n",
+ "%s: bad CIS tuple 0x%02x"
+ " (length = %u, expected >= %u)\n",
mmc_hostname(card->host),
tpl_code, tpl_link, tpl->min_size);
ret = -EINVAL;
ret = tpl->parse(card, func,
this->data, tpl_link);
}
- kfree(this);
+ /*
+ * We don't need the tuple anymore if it was
+ * successfully parsed by the SDIO core or if it is
+ * not going to be parsed by SDIO drivers.
+ */
+ if (!ret || ret != -EILSEQ)
+ kfree(this);
+ } else {
+ /* unknown tuple */
+ ret = -EILSEQ;
+ }
+
+ if (ret == -EILSEQ) {
+ /* this tuple is unknown to the core or whitelisted */
+ this->next = NULL;
+ this->code = tpl_code;
+ this->size = tpl_link;
+ *prev = this;
+ prev = &this->next;
+ printk(KERN_DEBUG
+ "%s: queuing CIS tuple 0x%02x length %u\n",
+ mmc_hostname(card->host), tpl_code, tpl_link);
+ /* keep on analyzing tuples */
+ ret = 0;
}
ptr += tpl_link;
If unsure, say N.
+config MMC_S3C_HW_SDIO_IRQ
+ bool "Hardware support for SDIO IRQ"
+ depends on MMC_S3C
+ help
+ Enable the hardware support for SDIO interrupts instead of using
+ the generic polling code.
+
+choice
+ prompt "Samsung S3C SD/MMC transfer code"
+ depends on MMC_S3C
+
+config MMC_S3C_PIO
+ bool "Use PIO transfers only"
+ help
+ Use PIO to transfer data between memory and the hardware.
+
+ PIO is slower than DMA as it requires CPU instructions to
+ move the data. This has been the traditional default for
+ the S3C MCI driver.
+
+config MMC_S3C_DMA
+ bool "Use DMA transfers only (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ Use DMA to transfer data between memory and the hardare.
+
+ Currently, the DMA support in this driver seems to not be
+ working properly and needs to be debugged before this
+ option is useful.
+
+config MMC_S3C_PIODMA
+ bool "Support for both PIO and DMA (EXPERIMENTAL)"
+ help
+ Compile both the PIO and DMA transfer routines into the
+ driver and let the platform select at run-time which one
+ is best.
+
+ See notes for the DMA option.
+
+endchoice
+
config MMC_SDRICOH_CS
tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)"
depends on EXPERIMENTAL && PCI && PCMCIA
#include <linux/mmc/host.h>
#include <linux/platform_device.h>
#include <linux/cpufreq.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/io.h>
dev_dbg(&host->pdev->dev, args); \
} while (0)
-#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
-
static struct s3c2410_dma_client s3cmci_dma_client = {
.name = "s3c-mci",
};
#endif /* CONFIG_MMC_DEBUG */
+/**
+ * s3cmci_host_usedma - return whether the host is using dma or pio
+ * @host: The host state
+ *
+ * Return true if the host is using DMA to transfer data, else false
+ * to use PIO mode. Will return static data depending on the driver
+ * configuration.
+ */
+static inline bool s3cmci_host_usedma(struct s3cmci_host *host)
+{
+#ifdef CONFIG_MMC_S3C_PIO
+ return false;
+#elif defined(CONFIG_MMC_S3C_DMA)
+ return true;
+#else
+ return host->dodma;
+#endif
+}
+
+/**
+ * s3cmci_host_canpio - return true if host has pio code available
+ *
+ * Return true if the driver has been compiled with the PIO support code
+ * available.
+ */
+static inline bool s3cmci_host_canpio(void)
+{
+#ifdef CONFIG_MMC_S3C_PIO
+ return true;
+#else
+ return false;
+#endif
+}
+
static inline u32 enable_imask(struct s3cmci_host *host, u32 imask)
{
u32 newmask;
static inline void clear_imask(struct s3cmci_host *host)
{
- writel(0, host->base + host->sdiimsk);
+ u32 mask = readl(host->base + host->sdiimsk);
+
+ /* preserve the SDIO IRQ mask state */
+ mask &= S3C2410_SDIIMSK_SDIOIRQ;
+ writel(mask, host->base + host->sdiimsk);
+}
+
+/**
+ * s3cmci_check_sdio_irq - test whether the SDIO IRQ is being signalled
+ * @host: The host to check.
+ *
+ * Test to see if the SDIO interrupt is being signalled in case the
+ * controller has failed to re-detect a card interrupt. Read GPE8 and
+ * see if it is low and if so, signal a SDIO interrupt.
+ *
+ * This is currently called if a request is finished (we assume that the
+ * bus is now idle) and when the SDIO IRQ is enabled in case the IRQ is
+ * already being indicated.
+*/
+static void s3cmci_check_sdio_irq(struct s3cmci_host *host)
+{
+ if (host->sdio_irqen) {
+ if (gpio_get_value(S3C2410_GPE(8)) == 0) {
+ printk(KERN_DEBUG "%s: signalling irq\n", __func__);
+ mmc_signal_sdio_irq(host->mmc);
+ }
+ }
}
static inline int get_data_buffer(struct s3cmci_host *host,
return 63 - fifostat;
}
+/**
+ * s3cmci_enable_irq - enable IRQ, after having disabled it.
+ * @host: The device state.
+ * @more: True if more IRQs are expected from transfer.
+ *
+ * Enable the main IRQ if needed after it has been disabled.
+ *
+ * The IRQ can be one of the following states:
+ * - disabled during IDLE
+ * - disabled whilst processing data
+ * - enabled during transfer
+ * - enabled whilst awaiting SDIO interrupt detection
+ */
+static void s3cmci_enable_irq(struct s3cmci_host *host, bool more)
+{
+ unsigned long flags;
+ bool enable = false;
+
+ local_irq_save(flags);
+
+ host->irq_enabled = more;
+ host->irq_disabled = false;
+
+ enable = more | host->sdio_irqen;
+
+ if (host->irq_state != enable) {
+ host->irq_state = enable;
+
+ if (enable)
+ enable_irq(host->irq);
+ else
+ disable_irq(host->irq);
+ }
+
+ local_irq_restore(flags);
+}
+
+/**
+ *
+ */
+static void s3cmci_disable_irq(struct s3cmci_host *host, bool transfer)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ //printk(KERN_DEBUG "%s: transfer %d\n", __func__, transfer);
+
+ host->irq_disabled = transfer;
+
+ if (transfer && host->irq_state) {
+ host->irq_state = false;
+ disable_irq(host->irq);
+ }
+
+ local_irq_restore(flags);
+}
+
static void do_pio_read(struct s3cmci_host *host)
{
int res;
{
struct s3cmci_host *host = (struct s3cmci_host *) data;
-
- disable_irq(host->irq);
+ s3cmci_disable_irq(host, true);
if (host->pio_active == XFER_WRITE)
do_pio_write(host);
host->mrq->data->error = -EINVAL;
}
+ s3cmci_enable_irq(host, false);
finalize_request(host);
} else
- enable_irq(host->irq);
+ s3cmci_enable_irq(host, true);
}
/*
struct s3cmci_host *host = dev_id;
struct mmc_command *cmd;
u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt, mci_imsk;
- u32 mci_cclear, mci_dclear;
+ u32 mci_cclear = 0, mci_dclear;
unsigned long iflags;
+ mci_dsta = readl(host->base + S3C2410_SDIDSTA);
+ mci_imsk = readl(host->base + host->sdiimsk);
+
+ if (mci_dsta & S3C2410_SDIDSTA_SDIOIRQDETECT) {
+ if (mci_imsk & S3C2410_SDIIMSK_SDIOIRQ) {
+ mci_dclear = S3C2410_SDIDSTA_SDIOIRQDETECT;
+ writel(mci_dclear, host->base + S3C2410_SDIDSTA);
+
+ mmc_signal_sdio_irq(host->mmc);
+ return IRQ_HANDLED;
+ }
+ }
+
spin_lock_irqsave(&host->complete_lock, iflags);
mci_csta = readl(host->base + S3C2410_SDICMDSTAT);
- mci_dsta = readl(host->base + S3C2410_SDIDSTA);
mci_dcnt = readl(host->base + S3C2410_SDIDCNT);
mci_fsta = readl(host->base + S3C2410_SDIFSTA);
- mci_imsk = readl(host->base + host->sdiimsk);
- mci_cclear = 0;
mci_dclear = 0;
if ((host->complete_what == COMPLETION_NONE) ||
goto irq_out;
}
- if (!host->dodma) {
+ if (!s3cmci_host_usedma(host)) {
if ((host->pio_active == XFER_WRITE) &&
(mci_fsta & S3C2410_SDIFSTA_TFDET)) {
dbg(host, dbg_dma, "DMA FINISHED Size:%i DSTA:%08x DCNT:%08x\n",
size, mci_dsta, mci_dcnt);
+ host->dma_complete = 1;
host->complete_what = COMPLETION_FINALIZE;
out:
fail_request:
host->mrq->data->error = -EINVAL;
host->complete_what = COMPLETION_FINALIZE;
- writel(0, host->base + host->sdiimsk);
- goto out;
+ clear_imask(host);
+ goto out;
}
static void finalize_request(struct s3cmci_host *host)
if (cmd->data && (cmd->error == 0) &&
(cmd->data->error == 0)) {
- if (host->dodma && (!host->dma_complete)) {
- dbg(host, dbg_dma, "DMA Missing!\n");
+ if (s3cmci_host_usedma(host) && (!host->dma_complete)) {
+ dbg(host, dbg_dma, "DMA Missing (%d)!\n",
+ host->dma_complete);
return;
}
}
writel(0, host->base + S3C2410_SDICMDARG);
writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON);
writel(0, host->base + S3C2410_SDICMDCON);
- writel(0, host->base + host->sdiimsk);
+ clear_imask(host);
if (cmd->data && cmd->error)
cmd->data->error = cmd->error;
/* If we had an error while transfering data we flush the
* DMA channel and the fifo to clear out any garbage. */
if (mrq->data->error != 0) {
- if (host->dodma)
+ if (s3cmci_host_usedma(host))
s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
if (host->is2440) {
request_done:
host->complete_what = COMPLETION_NONE;
host->mrq = NULL;
+
+ s3cmci_check_sdio_irq(host);
mmc_request_done(host->mmc, mrq);
}
dcon = data->blocks & S3C2410_SDIDCON_BLKNUM_MASK;
- if (host->dodma)
+ if (s3cmci_host_usedma(host))
dcon |= S3C2410_SDIDCON_DMAEN;
if (host->bus_width == MMC_BUS_WIDTH_4)
static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
{
int dma_len, i;
- int rw = (data->flags & MMC_DATA_WRITE) ? 1 : 0;
+ int rw = data->flags & MMC_DATA_WRITE;
BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
- (rw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (dma_len == 0)
return -ENOMEM;
for (i = 0; i < dma_len; i++) {
int res;
- dbg(host, dbg_dma, "enqueue %i:%u@%u\n", i,
- sg_dma_address(&data->sg[i]),
- sg_dma_len(&data->sg[i]));
+ dbg(host, dbg_dma, "enqueue %i: %08x@%u\n", i,
+ sg_dma_address(&data->sg[i]),
+ sg_dma_len(&data->sg[i]));
- res = s3c2410_dma_enqueue(host->dma, (void *) host,
+ res = s3c2410_dma_enqueue(host->dma, host,
sg_dma_address(&data->sg[i]),
sg_dma_len(&data->sg[i]));
return;
}
- if (host->dodma)
+ if (s3cmci_host_usedma(host))
res = s3cmci_prepare_dma(host, cmd->data);
else
res = s3cmci_prepare_pio(host, cmd->data);
s3cmci_send_command(host, cmd);
/* Enable Interrupt */
- enable_irq(host->irq);
+ s3cmci_enable_irq(host, true);
}
static int s3cmci_card_present(struct mmc_host *mmc)
if (pdata->gpio_detect == 0)
return -ENOSYS;
- ret = s3c2410_gpio_getpin(pdata->gpio_detect) ? 0 : 1;
+ ret = gpio_get_value(pdata->gpio_detect) ? 0 : 1;
return ret ^ pdata->detect_invert;
}
switch (ios->power_mode) {
case MMC_POWER_ON:
case MMC_POWER_UP:
- s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
- s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
- s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
- s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
- s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
- s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(5), S3C2410_GPE5_SDCLK);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(6), S3C2410_GPE6_SDCMD);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(7), S3C2410_GPE7_SDDAT0);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(8), S3C2410_GPE8_SDDAT1);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(9), S3C2410_GPE9_SDDAT2);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(10), S3C2410_GPE10_SDDAT3);
if (host->pdata->set_power)
host->pdata->set_power(ios->power_mode, ios->vdd);
case MMC_POWER_OFF:
default:
- s3c2410_gpio_setpin(S3C2410_GPE5, 0);
- s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPIO_OUTPUT);
+ gpio_direction_output(S3C2410_GPE(5), 0);
if (host->is2440)
mci_con |= S3C2440_SDICON_SDRESET;
struct s3c24xx_mci_pdata *pdata = host->pdata;
int ret;
- if (pdata->gpio_wprotect == 0)
+ if (pdata->no_wprotect)
return 0;
ret = s3c2410_gpio_getpin(pdata->gpio_wprotect);
return ret;
}
+static void s3cmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+ struct s3cmci_host *host = mmc_priv(mmc);
+ unsigned long flags;
+ u32 con;
+
+ local_irq_save(flags);
+
+ con = readl(host->base + S3C2410_SDICON);
+ host->sdio_irqen = enable;
+
+ if (enable == host->sdio_irqen)
+ goto same_state;
+
+ if (enable) {
+ con |= S3C2410_SDICON_SDIOIRQ;
+ enable_imask(host, S3C2410_SDIIMSK_SDIOIRQ);
+
+ if (!host->irq_state && !host->irq_disabled) {
+ host->irq_state = true;
+ enable_irq(host->irq);
+ }
+ } else {
+ disable_imask(host, S3C2410_SDIIMSK_SDIOIRQ);
+ con &= ~S3C2410_SDICON_SDIOIRQ;
+
+ if (!host->irq_enabled && host->irq_state) {
+ disable_irq_nosync(host->irq);
+ host->irq_state = false;
+ }
+ }
+
+ writel(con, host->base + S3C2410_SDICON);
+
+ same_state:
+ local_irq_restore(flags);
+
+ s3cmci_check_sdio_irq(host);
+}
+
static struct mmc_host_ops s3cmci_ops = {
.request = s3cmci_request,
.set_ios = s3cmci_set_ios,
.get_ro = s3cmci_get_ro,
.get_cd = s3cmci_card_present,
+ .enable_sdio_irq = s3cmci_enable_sdio_irq,
};
static struct s3c24xx_mci_pdata s3cmci_def_pdata = {
}
#endif
-static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
+
+#ifdef CONFIG_DEBUG_FS
+
+static int s3cmci_state_show(struct seq_file *seq, void *v)
+{
+ struct s3cmci_host *host = seq->private;
+
+ seq_printf(seq, "Register base = 0x%08x\n", (u32)host->base);
+ seq_printf(seq, "Clock rate = %ld\n", host->clk_rate);
+ seq_printf(seq, "Prescale = %d\n", host->prescaler);
+ seq_printf(seq, "is2440 = %d\n", host->is2440);
+ seq_printf(seq, "IRQ = %d\n", host->irq);
+ seq_printf(seq, "IRQ enabled = %d\n", host->irq_enabled);
+ seq_printf(seq, "IRQ disabled = %d\n", host->irq_disabled);
+ seq_printf(seq, "IRQ state = %d\n", host->irq_state);
+ seq_printf(seq, "CD IRQ = %d\n", host->irq_cd);
+ seq_printf(seq, "Do DMA = %d\n", s3cmci_host_usedma(host));
+ seq_printf(seq, "SDIIMSK at %d\n", host->sdiimsk);
+ seq_printf(seq, "SDIDATA at %d\n", host->sdidata);
+
+ return 0;
+}
+
+static int s3cmci_state_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, s3cmci_state_show, inode->i_private);
+}
+
+static const struct file_operations s3cmci_fops_state = {
+ .owner = THIS_MODULE,
+ .open = s3cmci_state_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+#define DBG_REG(_r) { .addr = S3C2410_SDI##_r, .name = #_r }
+
+struct s3cmci_reg {
+ unsigned short addr;
+ unsigned char *name;
+} debug_regs[] = {
+ DBG_REG(CON),
+ DBG_REG(PRE),
+ DBG_REG(CMDARG),
+ DBG_REG(CMDCON),
+ DBG_REG(CMDSTAT),
+ DBG_REG(RSP0),
+ DBG_REG(RSP1),
+ DBG_REG(RSP2),
+ DBG_REG(RSP3),
+ DBG_REG(TIMER),
+ DBG_REG(BSIZE),
+ DBG_REG(DCON),
+ DBG_REG(DCNT),
+ DBG_REG(DSTA),
+ DBG_REG(FSTA),
+ {}
+};
+
+static int s3cmci_regs_show(struct seq_file *seq, void *v)
+{
+ struct s3cmci_host *host = seq->private;
+ struct s3cmci_reg *rptr = debug_regs;
+
+ for (; rptr->name; rptr++)
+ seq_printf(seq, "SDI%s\t=0x%08x\n", rptr->name,
+ readl(host->base + rptr->addr));
+
+ seq_printf(seq, "SDIIMSK\t=0x%08x\n", readl(host->base + host->sdiimsk));
+
+ return 0;
+}
+
+static int s3cmci_regs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, s3cmci_regs_show, inode->i_private);
+}
+
+static const struct file_operations s3cmci_fops_regs = {
+ .owner = THIS_MODULE,
+ .open = s3cmci_regs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void s3cmci_debugfs_attach(struct s3cmci_host *host)
+{
+ struct device *dev = &host->pdev->dev;
+
+ host->debug_root = debugfs_create_dir(dev_name(dev), NULL);
+ if (IS_ERR(host->debug_root)) {
+ dev_err(dev, "failed to create debugfs root\n");
+ return;
+ }
+
+ host->debug_state = debugfs_create_file("state", 0444,
+ host->debug_root, host,
+ &s3cmci_fops_state);
+
+ if (IS_ERR(host->debug_state))
+ dev_err(dev, "failed to create debug state file\n");
+
+ host->debug_regs = debugfs_create_file("regs", 0444,
+ host->debug_root, host,
+ &s3cmci_fops_regs);
+
+ if (IS_ERR(host->debug_regs))
+ dev_err(dev, "failed to create debug regs file\n");
+}
+
+static void s3cmci_debugfs_remove(struct s3cmci_host *host)
+{
+ debugfs_remove(host->debug_regs);
+ debugfs_remove(host->debug_state);
+ debugfs_remove(host->debug_root);
+}
+
+#else
+static inline void s3cmci_debugfs_attach(struct s3cmci_host *host) { }
+static inline void s3cmci_debugfs_remove(struct s3cmci_host *host) { }
+
+#endif /* CONFIG_DEBUG_FS */
+
+static int __devinit s3cmci_probe(struct platform_device *pdev)
{
struct s3cmci_host *host;
struct mmc_host *mmc;
int ret;
+ int is2440;
+ int i;
+
+ is2440 = platform_get_device_id(pdev)->driver_data;
mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);
if (!mmc) {
goto probe_out;
}
+ for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++) {
+ ret = gpio_request(i, dev_name(&pdev->dev));
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get gpio %d\n", i);
+
+ for (i--; i >= S3C2410_GPE(5); i--)
+ gpio_free(i);
+
+ goto probe_free_host;
+ }
+ }
+
host = mmc_priv(mmc);
host->mmc = mmc;
host->pdev = pdev;
host->clk_div = 2;
}
- host->dodma = 0;
host->complete_what = COMPLETION_NONE;
host->pio_active = XFER_NONE;
- host->dma = S3CMCI_DMA;
+#ifdef CONFIG_MMC_S3C_PIODMA
+ host->dodma = host->pdata->dma;
+#endif
host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!host->mem) {
"failed to get io memory region resouce.\n");
ret = -ENOENT;
- goto probe_free_host;
+ goto probe_free_gpio;
}
host->mem = request_mem_region(host->mem->start,
- RESSIZE(host->mem), pdev->name);
+ resource_size(host->mem), pdev->name);
if (!host->mem) {
dev_err(&pdev->dev, "failed to request io memory region.\n");
ret = -ENOENT;
- goto probe_free_host;
+ goto probe_free_gpio;
}
- host->base = ioremap(host->mem->start, RESSIZE(host->mem));
+ host->base = ioremap(host->mem->start, resource_size(host->mem));
if (!host->base) {
dev_err(&pdev->dev, "failed to ioremap() io memory region.\n");
ret = -EINVAL;
* ensure we don't lock the system with un-serviceable requests. */
disable_irq(host->irq);
+ host->irq_state = false;
- host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);
-
- if (host->irq_cd >= 0) {
- if (request_irq(host->irq_cd, s3cmci_irq_cd,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- DRIVER_NAME, host)) {
- dev_err(&pdev->dev, "can't get card detect irq.\n");
- ret = -ENOENT;
+ if (!host->pdata->no_detect) {
+ ret = gpio_request(host->pdata->gpio_detect, "s3cmci detect");
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get detect gpio\n");
goto probe_free_irq;
}
- } else {
- dev_warn(&pdev->dev, "host detect has no irq available\n");
- s3c2410_gpio_cfgpin(host->pdata->gpio_detect,
- S3C2410_GPIO_INPUT);
+
+ host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);
+
+ if (host->irq_cd >= 0) {
+ if (request_irq(host->irq_cd, s3cmci_irq_cd,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING,
+ DRIVER_NAME, host)) {
+ dev_err(&pdev->dev,
+ "can't get card detect irq.\n");
+ ret = -ENOENT;
+ goto probe_free_gpio_cd;
+ }
+ } else {
+ dev_warn(&pdev->dev,
+ "host detect has no irq available\n");
+ gpio_direction_input(host->pdata->gpio_detect);
+ }
+ } else
+ host->irq_cd = -1;
+
+ if (!host->pdata->no_wprotect) {
+ ret = gpio_request(host->pdata->gpio_wprotect, "s3cmci wp");
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get writeprotect\n");
+ goto probe_free_irq_cd;
+ }
+
+ gpio_direction_input(host->pdata->gpio_wprotect);
}
- if (host->pdata->gpio_wprotect)
- s3c2410_gpio_cfgpin(host->pdata->gpio_wprotect,
- S3C2410_GPIO_INPUT);
+ /* depending on the dma state, get a dma channel to use. */
- if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL) < 0) {
- dev_err(&pdev->dev, "unable to get DMA channel.\n");
- ret = -EBUSY;
- goto probe_free_irq_cd;
+ if (s3cmci_host_usedma(host)) {
+ host->dma = s3c2410_dma_request(DMACH_SDI, &s3cmci_dma_client,
+ host);
+ if (host->dma < 0) {
+ dev_err(&pdev->dev, "cannot get DMA channel.\n");
+ if (!s3cmci_host_canpio()) {
+ ret = -EBUSY;
+ goto probe_free_gpio_wp;
+ } else {
+ dev_warn(&pdev->dev, "falling back to PIO.\n");
+ host->dodma = 0;
+ }
+ }
}
host->clk = clk_get(&pdev->dev, "sdi");
dev_err(&pdev->dev, "failed to find clock source.\n");
ret = PTR_ERR(host->clk);
host->clk = NULL;
- goto probe_free_host;
+ goto probe_free_dma;
}
ret = clk_enable(host->clk);
mmc->ops = &s3cmci_ops;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+#ifdef CONFIG_MMC_S3C_HW_SDIO_IRQ
+ mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
+#else
mmc->caps = MMC_CAP_4_BIT_DATA;
+#endif
mmc->f_min = host->clk_rate / (host->clk_div * 256);
mmc->f_max = host->clk_rate / host->clk_div;
goto free_cpufreq;
}
+ s3cmci_debugfs_attach(host);
+
platform_set_drvdata(pdev, mmc);
- dev_info(&pdev->dev, "initialisation done.\n");
+ dev_info(&pdev->dev, "%s - using %s, %s SDIO IRQ\n", mmc_hostname(mmc),
+ s3cmci_host_usedma(host) ? "dma" : "pio",
+ mmc->caps & MMC_CAP_SDIO_IRQ ? "hw" : "sw");
return 0;
clk_free:
clk_put(host->clk);
+ probe_free_dma:
+ if (s3cmci_host_usedma(host))
+ s3c2410_dma_free(host->dma, &s3cmci_dma_client);
+
+ probe_free_gpio_wp:
+ if (!host->pdata->no_wprotect)
+ gpio_free(host->pdata->gpio_wprotect);
+
+ probe_free_gpio_cd:
+ if (!host->pdata->no_detect)
+ gpio_free(host->pdata->gpio_detect);
+
probe_free_irq_cd:
if (host->irq_cd >= 0)
free_irq(host->irq_cd, host);
iounmap(host->base);
probe_free_mem_region:
- release_mem_region(host->mem->start, RESSIZE(host->mem));
+ release_mem_region(host->mem->start, resource_size(host->mem));
+
+ probe_free_gpio:
+ for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
+ gpio_free(i);
probe_free_host:
mmc_free_host(mmc);
+
probe_out:
return ret;
}
if (host->irq_cd >= 0)
free_irq(host->irq_cd, host);
+ s3cmci_debugfs_remove(host);
s3cmci_cpufreq_deregister(host);
mmc_remove_host(mmc);
clk_disable(host->clk);
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
struct s3cmci_host *host = mmc_priv(mmc);
+ struct s3c24xx_mci_pdata *pd = host->pdata;
+ int i;
s3cmci_shutdown(pdev);
clk_put(host->clk);
tasklet_disable(&host->pio_tasklet);
- s3c2410_dma_free(S3CMCI_DMA, &s3cmci_dma_client);
+
+ if (s3cmci_host_usedma(host))
+ s3c2410_dma_free(host->dma, &s3cmci_dma_client);
free_irq(host->irq, host);
+ if (!pd->no_wprotect)
+ gpio_free(pd->gpio_wprotect);
+
+ if (!pd->no_detect)
+ gpio_free(pd->gpio_detect);
+
+ for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
+ gpio_free(i);
+
+
iounmap(host->base);
- release_mem_region(host->mem->start, RESSIZE(host->mem));
+ release_mem_region(host->mem->start, resource_size(host->mem));
mmc_free_host(mmc);
return 0;
}
-static int __devinit s3cmci_2410_probe(struct platform_device *dev)
-{
- return s3cmci_probe(dev, 0);
-}
+static struct platform_device_id s3cmci_driver_ids[] = {
+ {
+ .name = "s3c2410-sdi",
+ .driver_data = 0,
+ }, {
+ .name = "s3c2412-sdi",
+ .driver_data = 1,
+ }, {
+ .name = "s3c2440-sdi",
+ .driver_data = 1,
+ },
+ { }
+};
-static int __devinit s3cmci_2412_probe(struct platform_device *dev)
-{
- return s3cmci_probe(dev, 1);
-}
+MODULE_DEVICE_TABLE(platform, s3cmci_driver_ids);
-static int __devinit s3cmci_2440_probe(struct platform_device *dev)
-{
- return s3cmci_probe(dev, 1);
-}
#ifdef CONFIG_PM
-static int s3cmci_suspend(struct platform_device *dev, pm_message_t state)
+static int s3cmci_suspend(struct device *dev)
{
- struct mmc_host *mmc = platform_get_drvdata(dev);
+ struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev));
+ struct pm_message event = { PM_EVENT_SUSPEND };
- return mmc_suspend_host(mmc, state);
+ return mmc_suspend_host(mmc, event);
}
-static int s3cmci_resume(struct platform_device *dev)
+static int s3cmci_resume(struct device *dev)
{
- struct mmc_host *mmc = platform_get_drvdata(dev);
+ struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev));
return mmc_resume_host(mmc);
}
-#else /* CONFIG_PM */
-#define s3cmci_suspend NULL
-#define s3cmci_resume NULL
-#endif /* CONFIG_PM */
-
-
-static struct platform_driver s3cmci_2410_driver = {
- .driver.name = "s3c2410-sdi",
- .driver.owner = THIS_MODULE,
- .probe = s3cmci_2410_probe,
- .remove = __devexit_p(s3cmci_remove),
- .shutdown = s3cmci_shutdown,
+static struct dev_pm_ops s3cmci_pm = {
.suspend = s3cmci_suspend,
.resume = s3cmci_resume,
};
-static struct platform_driver s3cmci_2412_driver = {
- .driver.name = "s3c2412-sdi",
- .driver.owner = THIS_MODULE,
- .probe = s3cmci_2412_probe,
- .remove = __devexit_p(s3cmci_remove),
- .shutdown = s3cmci_shutdown,
- .suspend = s3cmci_suspend,
- .resume = s3cmci_resume,
-};
+#define s3cmci_pm_ops &s3cmci_pm
+#else /* CONFIG_PM */
+#define s3cmci_pm_ops NULL
+#endif /* CONFIG_PM */
-static struct platform_driver s3cmci_2440_driver = {
- .driver.name = "s3c2440-sdi",
- .driver.owner = THIS_MODULE,
- .probe = s3cmci_2440_probe,
+
+static struct platform_driver s3cmci_driver = {
+ .driver = {
+ .name = "s3c-sdi",
+ .owner = THIS_MODULE,
+ .pm = s3cmci_pm_ops,
+ },
+ .id_table = s3cmci_driver_ids,
+ .probe = s3cmci_probe,
.remove = __devexit_p(s3cmci_remove),
.shutdown = s3cmci_shutdown,
- .suspend = s3cmci_suspend,
- .resume = s3cmci_resume,
};
-
static int __init s3cmci_init(void)
{
- platform_driver_register(&s3cmci_2410_driver);
- platform_driver_register(&s3cmci_2412_driver);
- platform_driver_register(&s3cmci_2440_driver);
- return 0;
+ return platform_driver_register(&s3cmci_driver);
}
static void __exit s3cmci_exit(void)
{
- platform_driver_unregister(&s3cmci_2410_driver);
- platform_driver_unregister(&s3cmci_2412_driver);
- platform_driver_unregister(&s3cmci_2440_driver);
+ platform_driver_unregister(&s3cmci_driver);
}
module_init(s3cmci_init);
MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>, Ben Dooks <ben-linux@fluff.org>");
-MODULE_ALIAS("platform:s3c2410-sdi");
-MODULE_ALIAS("platform:s3c2412-sdi");
-MODULE_ALIAS("platform:s3c2440-sdi");
* published by the Free Software Foundation.
*/
-/* FIXME: DMA Resource management ?! */
-#define S3CMCI_DMA 0
-
enum s3cmci_waitfor {
COMPLETION_NONE,
COMPLETION_FINALIZE,
int dodma;
int dmatogo;
+ bool irq_disabled;
+ bool irq_enabled;
+ bool irq_state;
+ int sdio_irqen;
+
struct mmc_request *mrq;
int cmd_is_stop;
unsigned int ccnt, dcnt;
struct tasklet_struct pio_tasklet;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debug_root;
+ struct dentry *debug_state;
+ struct dentry *debug_regs;
+#endif
+
#ifdef CONFIG_CPU_FREQ
struct notifier_block freq_transition;
#endif
}
__skb_pull(skb, sizeof(*p));
- st = per_cpu_ptr(sge->port_stats[p->iff], smp_processor_id());
+ st = this_cpu_ptr(sge->port_stats[p->iff]);
skb->protocol = eth_type_trans(skb, adapter->port[p->iff].dev);
if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff &&
{
struct adapter *adapter = dev->ml_priv;
struct sge *sge = adapter->sge;
- struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port],
- smp_processor_id());
+ struct sge_port_stats *st = this_cpu_ptr(sge->port_stats[dev->if_port]);
struct cpl_tx_pkt *cpl;
struct sk_buff *orig_skb = skb;
int ret;
#define AUTO_ALL_MODES 0
#define E1000_EEPROM_82544_APM 0x0004
-#define E1000_EEPROM_ICH8_APME 0x0004
#define E1000_EEPROM_APME 0x0400
#ifndef E1000_MASTER_SLAVE
u64 hw_csum_err;
u64 hw_csum_good;
- u64 rx_hdr_split;
u32 alloc_rx_buff_failed;
u32 rx_int_delay;
u32 rx_abs_int_delay;
struct e1000_rx_ring test_rx_ring;
int msg_enable;
- bool have_msi;
/* to not mess up cache alignment, always add to the bottom */
bool tso_force;
{ "rx_long_byte_count", E1000_STAT(stats.gorcl) },
{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
- { "rx_header_split", E1000_STAT(rx_hdr_split) },
{ "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) },
{ "tx_smbus", E1000_STAT(stats.mgptc) },
{ "rx_smbus", E1000_STAT(stats.mgprc) },
SUPPORTED_1000baseT_Full|
SUPPORTED_Autoneg |
SUPPORTED_TP);
- if (hw->phy_type == e1000_phy_ife)
- ecmd->supported &= ~SUPPORTED_1000baseT_Full;
ecmd->advertising = ADVERTISED_TP;
if (hw->autoneg == 1) {
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- /* When SoL/IDER sessions are active, autoneg/speed/duplex
- * cannot be changed */
- if (e1000_check_phy_reset_block(hw)) {
- DPRINTK(DRV, ERR, "Cannot change link characteristics "
- "when SoL/IDER is active.\n");
- return -EINVAL;
- }
-
while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
msleep(1);
else
netdev->features &= ~NETIF_F_TSO;
- if (data && (adapter->hw.mac_type > e1000_82547_rev_2))
- netdev->features |= NETIF_F_TSO6;
- else
- netdev->features &= ~NETIF_F_TSO6;
+ netdev->features &= ~NETIF_F_TSO6;
DPRINTK(PROBE, INFO, "TSO is %s\n", data ? "Enabled" : "Disabled");
adapter->tso_force = true;
regs_buff[24] = (u32)phy_data; /* phy local receiver status */
regs_buff[25] = regs_buff[24]; /* phy remote receiver status */
if (hw->mac_type >= e1000_82540 &&
- hw->mac_type < e1000_82571 &&
hw->media_type == e1000_media_type_copper) {
regs_buff[26] = er32(MANC);
}
ret_val = e1000_write_eeprom(hw, first_word,
last_word - first_word + 1, eeprom_buff);
- /* Update the checksum over the first part of the EEPROM if needed
- * and flush shadow RAM for 82573 conrollers */
- if ((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) ||
- (hw->mac_type == e1000_82573)))
+ /* Update the checksum over the first part of the EEPROM if needed */
+ if ((ret_val == 0) && (first_word <= EEPROM_CHECKSUM_REG))
e1000_update_eeprom_checksum(hw);
kfree(eeprom_buff);
struct ethtool_drvinfo *drvinfo)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- struct e1000_hw *hw = &adapter->hw;
char firmware_version[32];
- u16 eeprom_data;
strncpy(drvinfo->driver, e1000_driver_name, 32);
strncpy(drvinfo->version, e1000_driver_version, 32);
- /* EEPROM image version # is reported as firmware version # for
- * 8257{1|2|3} controllers */
- e1000_read_eeprom(hw, 5, 1, &eeprom_data);
- switch (hw->mac_type) {
- case e1000_82571:
- case e1000_82572:
- case e1000_82573:
- case e1000_80003es2lan:
- case e1000_ich8lan:
- sprintf(firmware_version, "%d.%d-%d",
- (eeprom_data & 0xF000) >> 12,
- (eeprom_data & 0x0FF0) >> 4,
- eeprom_data & 0x000F);
- break;
- default:
- sprintf(firmware_version, "N/A");
- }
-
+ sprintf(firmware_version, "N/A");
strncpy(drvinfo->fw_version, firmware_version, 32);
strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
drvinfo->regdump_len = e1000_get_regs_len(netdev);
/* The status register is Read Only, so a write should fail.
* Some bits that get toggled are ignored.
*/
- switch (hw->mac_type) {
+
/* there are several bits on newer hardware that are r/w */
- case e1000_82571:
- case e1000_82572:
- case e1000_80003es2lan:
- toggle = 0x7FFFF3FF;
- break;
- case e1000_82573:
- case e1000_ich8lan:
- toggle = 0x7FFFF033;
- break;
- default:
- toggle = 0xFFFFF833;
- break;
- }
+ toggle = 0xFFFFF833;
before = er32(STATUS);
value = (er32(STATUS) & toggle);
/* restore previous status */
ew32(STATUS, before);
- if (hw->mac_type != e1000_ich8lan) {
- REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
- REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);
- }
+ REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF);
+ REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF);
+ REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF);
+ REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF);
REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF);
REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000);
- before = (hw->mac_type == e1000_ich8lan ?
- 0x06C3B33E : 0x06DFB3FE);
+ before = 0x06DFB3FE;
REG_SET_AND_CHECK(RCTL, before, 0x003FFFFB);
REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
REG_SET_AND_CHECK(RCTL, before, 0xFFFFFFFF);
REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
- if (hw->mac_type != e1000_ich8lan)
- REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
+ REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF);
REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
- value = (hw->mac_type == e1000_ich8lan ?
- E1000_RAR_ENTRIES_ICH8LAN : E1000_RAR_ENTRIES);
+ value = E1000_RAR_ENTRIES;
for (i = 0; i < value; i++) {
REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
0xFFFFFFFF);
}
- value = (hw->mac_type == e1000_ich8lan ?
- E1000_MC_TBL_SIZE_ICH8LAN : E1000_MC_TBL_SIZE);
+ value = E1000_MC_TBL_SIZE;
for (i = 0; i < value; i++)
REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
/* Test each interrupt */
for (; i < 10; i++) {
- if (hw->mac_type == e1000_ich8lan && i == 8)
- continue;
-
/* Interrupt to test */
mask = 1 << i;
e1000_write_phy_reg(hw, PHY_CTRL, 0x9140);
/* autoneg off */
e1000_write_phy_reg(hw, PHY_CTRL, 0x8140);
- } else if (hw->phy_type == e1000_phy_gg82563)
- e1000_write_phy_reg(hw,
- GG82563_PHY_KMRN_MODE_CTRL,
- 0x1CC);
+ }
ctrl_reg = er32(CTRL);
- if (hw->phy_type == e1000_phy_ife) {
- /* force 100, set loopback */
- e1000_write_phy_reg(hw, PHY_CTRL, 0x6100);
+ /* force 1000, set loopback */
+ e1000_write_phy_reg(hw, PHY_CTRL, 0x4140);
- /* Now set up the MAC to the same speed/duplex as the PHY. */
- ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
- ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
- E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
- E1000_CTRL_SPD_100 |/* Force Speed to 100 */
- E1000_CTRL_FD); /* Force Duplex to FULL */
- } else {
- /* force 1000, set loopback */
- e1000_write_phy_reg(hw, PHY_CTRL, 0x4140);
-
- /* Now set up the MAC to the same speed/duplex as the PHY. */
- ctrl_reg = er32(CTRL);
- ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
- ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
- E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
- E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
- E1000_CTRL_FD); /* Force Duplex to FULL */
- }
+ /* Now set up the MAC to the same speed/duplex as the PHY. */
+ ctrl_reg = er32(CTRL);
+ ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
+ ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */
+ E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */
+ E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
+ E1000_CTRL_FD); /* Force Duplex to FULL */
if (hw->media_type == e1000_media_type_copper &&
hw->phy_type == e1000_phy_m88)
case e1000_82541_rev_2:
case e1000_82547:
case e1000_82547_rev_2:
- case e1000_82571:
- case e1000_82572:
- case e1000_82573:
- case e1000_80003es2lan:
- case e1000_ich8lan:
return e1000_integrated_phy_loopback(adapter);
break;
-
default:
/* Default PHY loopback work is to read the MII
* control register and assert bit 14 (loopback mode).
case e1000_82546_rev_3:
return e1000_set_phy_loopback(adapter);
break;
- case e1000_82571:
- case e1000_82572:
-#define E1000_SERDES_LB_ON 0x410
- e1000_set_phy_loopback(adapter);
- ew32(SCTL, E1000_SERDES_LB_ON);
- msleep(10);
- return 0;
- break;
default:
rctl = er32(RCTL);
rctl |= E1000_RCTL_LBM_TCVR;
ew32(RCTL, rctl);
switch (hw->mac_type) {
- case e1000_82571:
- case e1000_82572:
- if (hw->media_type == e1000_media_type_fiber ||
- hw->media_type == e1000_media_type_internal_serdes) {
-#define E1000_SERDES_LB_OFF 0x400
- ew32(SCTL, E1000_SERDES_LB_OFF);
- msleep(10);
- break;
- }
- /* Fall Through */
case e1000_82545:
case e1000_82546:
case e1000_82545_rev_3:
case e1000_82546_rev_3:
default:
hw->autoneg = true;
- if (hw->phy_type == e1000_phy_gg82563)
- e1000_write_phy_reg(hw,
- GG82563_PHY_KMRN_MODE_CTRL,
- 0x180);
e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
if (phy_reg & MII_CR_LOOPBACK) {
phy_reg &= ~MII_CR_LOOPBACK;
static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
{
- struct e1000_hw *hw = &adapter->hw;
-
- /* PHY loopback cannot be performed if SoL/IDER
- * sessions are active */
- if (e1000_check_phy_reset_block(hw)) {
- DPRINTK(DRV, ERR, "Cannot do PHY loopback test "
- "when SoL/IDER is active.\n");
- *data = 0;
- goto out;
- }
-
*data = e1000_setup_desc_rings(adapter);
if (*data)
goto out;
*data = 0;
if (hw->media_type == e1000_media_type_internal_serdes) {
int i = 0;
- hw->serdes_link_down = true;
+ hw->serdes_has_link = false;
/* On some blade server designs, link establishment
* could take as long as 2-3 minutes */
do {
e1000_check_for_link(hw);
- if (!hw->serdes_link_down)
+ if (hw->serdes_has_link)
return *data;
msleep(20);
} while (i++ < 3750);
case E1000_DEV_ID_82545EM_COPPER:
case E1000_DEV_ID_82546GB_QUAD_COPPER:
case E1000_DEV_ID_82546GB_PCIE:
- case E1000_DEV_ID_82571EB_SERDES_QUAD:
/* these don't support WoL at all */
wol->supported = 0;
break;
case E1000_DEV_ID_82546EB_FIBER:
case E1000_DEV_ID_82546GB_FIBER:
- case E1000_DEV_ID_82571EB_FIBER:
- case E1000_DEV_ID_82571EB_SERDES:
- case E1000_DEV_ID_82571EB_COPPER:
/* Wake events not supported on port B */
if (er32(STATUS) & E1000_STATUS_FUNC_1) {
wol->supported = 0;
/* return success for non excluded adapter ports */
retval = 0;
break;
- case E1000_DEV_ID_82571EB_QUAD_COPPER:
- case E1000_DEV_ID_82571EB_QUAD_FIBER:
- case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE:
- case E1000_DEV_ID_82571PT_QUAD_COPPER:
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
/* quad port adapters only support WoL on port A */
if (!adapter->quad_port_a) {
if (!data)
data = INT_MAX;
- if (hw->mac_type < e1000_82571) {
- if (!adapter->blink_timer.function) {
- init_timer(&adapter->blink_timer);
- adapter->blink_timer.function = e1000_led_blink_callback;
- adapter->blink_timer.data = (unsigned long)adapter;
- }
- e1000_setup_led(hw);
- mod_timer(&adapter->blink_timer, jiffies);
- msleep_interruptible(data * 1000);
- del_timer_sync(&adapter->blink_timer);
- } else if (hw->phy_type == e1000_phy_ife) {
- if (!adapter->blink_timer.function) {
- init_timer(&adapter->blink_timer);
- adapter->blink_timer.function = e1000_led_blink_callback;
- adapter->blink_timer.data = (unsigned long)adapter;
- }
- mod_timer(&adapter->blink_timer, jiffies);
- msleep_interruptible(data * 1000);
- del_timer_sync(&adapter->blink_timer);
- e1000_write_phy_reg(&(adapter->hw), IFE_PHY_SPECIAL_CONTROL_LED, 0);
- } else {
- e1000_blink_led_start(hw);
- msleep_interruptible(data * 1000);
+ if (!adapter->blink_timer.function) {
+ init_timer(&adapter->blink_timer);
+ adapter->blink_timer.function = e1000_led_blink_callback;
+ adapter->blink_timer.data = (unsigned long)adapter;
}
+ e1000_setup_led(hw);
+ mod_timer(&adapter->blink_timer, jiffies);
+ msleep_interruptible(data * 1000);
+ del_timer_sync(&adapter->blink_timer);
e1000_led_off(hw);
clear_bit(E1000_LED_ON, &adapter->led_status);
e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-*******************************************************************************/
+ */
/* e1000_hw.c
* Shared functions for accessing and configuring the MAC
*/
-
#include "e1000_hw.h"
-static s32 e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask);
-static void e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask);
-static s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 *data);
-static s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 data);
-static s32 e1000_get_software_semaphore(struct e1000_hw *hw);
-static void e1000_release_software_semaphore(struct e1000_hw *hw);
-
-static u8 e1000_arc_subsystem_valid(struct e1000_hw *hw);
static s32 e1000_check_downshift(struct e1000_hw *hw);
static s32 e1000_check_polarity(struct e1000_hw *hw,
e1000_rev_polarity *polarity);
static void e1000_clear_hw_cntrs(struct e1000_hw *hw);
static void e1000_clear_vfta(struct e1000_hw *hw);
-static s32 e1000_commit_shadow_ram(struct e1000_hw *hw);
static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw,
bool link_up);
static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw);
static s32 e1000_detect_gig_phy(struct e1000_hw *hw);
-static s32 e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank);
static s32 e1000_get_auto_rd_done(struct e1000_hw *hw);
static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
u16 *max_length);
-static s32 e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);
static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw);
-static s32 e1000_get_software_flag(struct e1000_hw *hw);
-static s32 e1000_ich8_cycle_init(struct e1000_hw *hw);
-static s32 e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout);
static s32 e1000_id_led_init(struct e1000_hw *hw);
-static s32 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
- u32 cnf_base_addr,
- u32 cnf_size);
-static s32 e1000_init_lcd_from_nvm(struct e1000_hw *hw);
static void e1000_init_rx_addrs(struct e1000_hw *hw);
-static void e1000_initialize_hardware_bits(struct e1000_hw *hw);
-static bool e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw);
-static s32 e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
-static s32 e1000_mng_enable_host_if(struct e1000_hw *hw);
-static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length,
- u16 offset, u8 *sum);
-static s32 e1000_mng_write_cmd_header(struct e1000_hw* hw,
- struct e1000_host_mng_command_header
- *hdr);
-static s32 e1000_mng_write_commit(struct e1000_hw *hw);
-static s32 e1000_phy_ife_get_info(struct e1000_hw *hw,
- struct e1000_phy_info *phy_info);
static s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
struct e1000_phy_info *phy_info);
-static s32 e1000_read_eeprom_eerd(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data);
-static s32 e1000_write_eeprom_eewr(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data);
-static s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd);
static s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
struct e1000_phy_info *phy_info);
-static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw);
-static s32 e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8 *data);
-static s32 e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index,
- u8 byte);
-static s32 e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte);
-static s32 e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data);
-static s32 e1000_read_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
- u16 *data);
-static s32 e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
- u16 data);
-static s32 e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data);
-static s32 e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data);
-static void e1000_release_software_flag(struct e1000_hw *hw);
static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
-static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active);
-static s32 e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop);
-static void e1000_set_pci_express_master_disable(struct e1000_hw *hw);
static s32 e1000_wait_autoneg(struct e1000_hw *hw);
static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value);
static s32 e1000_set_phy_type(struct e1000_hw *hw);
static s32 e1000_config_mac_to_phy(struct e1000_hw *hw);
static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
-static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data,
- u16 count);
+static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count);
static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw);
static s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset,
- u16 words, u16 *data);
+ u16 words, u16 *data);
static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data);
static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw);
static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count);
static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
u16 phy_data);
-static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw,u32 reg_addr,
+static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
u16 *phy_data);
static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count);
static s32 e1000_acquire_eeprom(struct e1000_hw *hw);
static s32 e1000_set_vco_speed(struct e1000_hw *hw);
static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw);
static s32 e1000_set_phy_mode(struct e1000_hw *hw);
-static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer);
-static u8 e1000_calculate_mng_checksum(char *buffer, u32 length);
-static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex);
-static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
-static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
-static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
+static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
/* IGP cable length table */
static const
-u16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
- { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,
- 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60,
- 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90,
- 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
- 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120};
-
-static const
-u16 e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
- { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
- 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
- 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
- 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82,
- 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104,
- 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121,
- 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
- 104, 109, 114, 118, 121, 124};
+u16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = {
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,
+ 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90,
+ 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100,
+ 100,
+ 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110,
+ 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120,
+ 120, 120
+};
static DEFINE_SPINLOCK(e1000_eeprom_lock);
-/******************************************************************************
- * Set the phy type member in the hw struct.
- *
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
+/**
+ * e1000_set_phy_type - Set the phy type member in the hw struct.
+ * @hw: Struct containing variables accessed by shared code
+ */
static s32 e1000_set_phy_type(struct e1000_hw *hw)
{
- DEBUGFUNC("e1000_set_phy_type");
-
- if (hw->mac_type == e1000_undefined)
- return -E1000_ERR_PHY_TYPE;
-
- switch (hw->phy_id) {
- case M88E1000_E_PHY_ID:
- case M88E1000_I_PHY_ID:
- case M88E1011_I_PHY_ID:
- case M88E1111_I_PHY_ID:
- hw->phy_type = e1000_phy_m88;
- break;
- case IGP01E1000_I_PHY_ID:
- if (hw->mac_type == e1000_82541 ||
- hw->mac_type == e1000_82541_rev_2 ||
- hw->mac_type == e1000_82547 ||
- hw->mac_type == e1000_82547_rev_2) {
- hw->phy_type = e1000_phy_igp;
- break;
- }
- case IGP03E1000_E_PHY_ID:
- hw->phy_type = e1000_phy_igp_3;
- break;
- case IFE_E_PHY_ID:
- case IFE_PLUS_E_PHY_ID:
- case IFE_C_E_PHY_ID:
- hw->phy_type = e1000_phy_ife;
- break;
- case GG82563_E_PHY_ID:
- if (hw->mac_type == e1000_80003es2lan) {
- hw->phy_type = e1000_phy_gg82563;
- break;
- }
- /* Fall Through */
- default:
- /* Should never have loaded on this device */
- hw->phy_type = e1000_phy_undefined;
- return -E1000_ERR_PHY_TYPE;
- }
-
- return E1000_SUCCESS;
-}
-
-/******************************************************************************
- * IGP phy init script - initializes the GbE PHY
- *
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-static void e1000_phy_init_script(struct e1000_hw *hw)
-{
- u32 ret_val;
- u16 phy_saved_data;
-
- DEBUGFUNC("e1000_phy_init_script");
-
- if (hw->phy_init_script) {
- msleep(20);
-
- /* Save off the current value of register 0x2F5B to be restored at
- * the end of this routine. */
- ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
-
- /* Disabled the PHY transmitter */
- e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
-
- msleep(20);
-
- e1000_write_phy_reg(hw,0x0000,0x0140);
-
- msleep(5);
-
- switch (hw->mac_type) {
- case e1000_82541:
- case e1000_82547:
- e1000_write_phy_reg(hw, 0x1F95, 0x0001);
-
- e1000_write_phy_reg(hw, 0x1F71, 0xBD21);
-
- e1000_write_phy_reg(hw, 0x1F79, 0x0018);
-
- e1000_write_phy_reg(hw, 0x1F30, 0x1600);
-
- e1000_write_phy_reg(hw, 0x1F31, 0x0014);
-
- e1000_write_phy_reg(hw, 0x1F32, 0x161C);
-
- e1000_write_phy_reg(hw, 0x1F94, 0x0003);
-
- e1000_write_phy_reg(hw, 0x1F96, 0x003F);
-
- e1000_write_phy_reg(hw, 0x2010, 0x0008);
- break;
+ DEBUGFUNC("e1000_set_phy_type");
- case e1000_82541_rev_2:
- case e1000_82547_rev_2:
- e1000_write_phy_reg(hw, 0x1F73, 0x0099);
- break;
- default:
- break;
- }
+ if (hw->mac_type == e1000_undefined)
+ return -E1000_ERR_PHY_TYPE;
- e1000_write_phy_reg(hw, 0x0000, 0x3300);
-
- msleep(20);
-
- /* Now enable the transmitter */
- e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
-
- if (hw->mac_type == e1000_82547) {
- u16 fused, fine, coarse;
-
- /* Move to analog registers page */
- e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused);
-
- if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
- e1000_read_phy_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS, &fused);
+ switch (hw->phy_id) {
+ case M88E1000_E_PHY_ID:
+ case M88E1000_I_PHY_ID:
+ case M88E1011_I_PHY_ID:
+ case M88E1111_I_PHY_ID:
+ hw->phy_type = e1000_phy_m88;
+ break;
+ case IGP01E1000_I_PHY_ID:
+ if (hw->mac_type == e1000_82541 ||
+ hw->mac_type == e1000_82541_rev_2 ||
+ hw->mac_type == e1000_82547 ||
+ hw->mac_type == e1000_82547_rev_2) {
+ hw->phy_type = e1000_phy_igp;
+ break;
+ }
+ default:
+ /* Should never have loaded on this device */
+ hw->phy_type = e1000_phy_undefined;
+ return -E1000_ERR_PHY_TYPE;
+ }
- fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
- coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
+ return E1000_SUCCESS;
+}
- if (coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
- coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10;
- fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
- } else if (coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
- fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
+/**
+ * e1000_phy_init_script - IGP phy init script - initializes the GbE PHY
+ * @hw: Struct containing variables accessed by shared code
+ */
+static void e1000_phy_init_script(struct e1000_hw *hw)
+{
+ u32 ret_val;
+ u16 phy_saved_data;
+
+ DEBUGFUNC("e1000_phy_init_script");
+
+ if (hw->phy_init_script) {
+ msleep(20);
+
+ /* Save off the current value of register 0x2F5B to be restored at
+ * the end of this routine. */
+ ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
+
+ /* Disabled the PHY transmitter */
+ e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
+ msleep(20);
+
+ e1000_write_phy_reg(hw, 0x0000, 0x0140);
+ msleep(5);
+
+ switch (hw->mac_type) {
+ case e1000_82541:
+ case e1000_82547:
+ e1000_write_phy_reg(hw, 0x1F95, 0x0001);
+ e1000_write_phy_reg(hw, 0x1F71, 0xBD21);
+ e1000_write_phy_reg(hw, 0x1F79, 0x0018);
+ e1000_write_phy_reg(hw, 0x1F30, 0x1600);
+ e1000_write_phy_reg(hw, 0x1F31, 0x0014);
+ e1000_write_phy_reg(hw, 0x1F32, 0x161C);
+ e1000_write_phy_reg(hw, 0x1F94, 0x0003);
+ e1000_write_phy_reg(hw, 0x1F96, 0x003F);
+ e1000_write_phy_reg(hw, 0x2010, 0x0008);
+ break;
- fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
- (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
- (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);
+ case e1000_82541_rev_2:
+ case e1000_82547_rev_2:
+ e1000_write_phy_reg(hw, 0x1F73, 0x0099);
+ break;
+ default:
+ break;
+ }
- e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_CONTROL, fused);
- e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS,
- IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
- }
- }
- }
+ e1000_write_phy_reg(hw, 0x0000, 0x3300);
+ msleep(20);
+
+ /* Now enable the transmitter */
+ e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+
+ if (hw->mac_type == e1000_82547) {
+ u16 fused, fine, coarse;
+
+ /* Move to analog registers page */
+ e1000_read_phy_reg(hw,
+ IGP01E1000_ANALOG_SPARE_FUSE_STATUS,
+ &fused);
+
+ if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
+ e1000_read_phy_reg(hw,
+ IGP01E1000_ANALOG_FUSE_STATUS,
+ &fused);
+
+ fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
+ coarse =
+ fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
+
+ if (coarse >
+ IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
+ coarse -=
+ IGP01E1000_ANALOG_FUSE_COARSE_10;
+ fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
+ } else if (coarse ==
+ IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
+ fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
+
+ fused =
+ (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
+ (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
+ (coarse &
+ IGP01E1000_ANALOG_FUSE_COARSE_MASK);
+
+ e1000_write_phy_reg(hw,
+ IGP01E1000_ANALOG_FUSE_CONTROL,
+ fused);
+ e1000_write_phy_reg(hw,
+ IGP01E1000_ANALOG_FUSE_BYPASS,
+ IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
+ }
+ }
+ }
}
-/******************************************************************************
- * Set the mac type member in the hw struct.
- *
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
+/**
+ * e1000_set_mac_type - Set the mac type member in the hw struct.
+ * @hw: Struct containing variables accessed by shared code
+ */
s32 e1000_set_mac_type(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_set_mac_type");
case E1000_DEV_ID_82547GI:
hw->mac_type = e1000_82547_rev_2;
break;
- case E1000_DEV_ID_82571EB_COPPER:
- case E1000_DEV_ID_82571EB_FIBER:
- case E1000_DEV_ID_82571EB_SERDES:
- case E1000_DEV_ID_82571EB_SERDES_DUAL:
- case E1000_DEV_ID_82571EB_SERDES_QUAD:
- case E1000_DEV_ID_82571EB_QUAD_COPPER:
- case E1000_DEV_ID_82571PT_QUAD_COPPER:
- case E1000_DEV_ID_82571EB_QUAD_FIBER:
- case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE:
- hw->mac_type = e1000_82571;
- break;
- case E1000_DEV_ID_82572EI_COPPER:
- case E1000_DEV_ID_82572EI_FIBER:
- case E1000_DEV_ID_82572EI_SERDES:
- case E1000_DEV_ID_82572EI:
- hw->mac_type = e1000_82572;
- break;
- case E1000_DEV_ID_82573E:
- case E1000_DEV_ID_82573E_IAMT:
- case E1000_DEV_ID_82573L:
- hw->mac_type = e1000_82573;
- break;
- case E1000_DEV_ID_80003ES2LAN_COPPER_SPT:
- case E1000_DEV_ID_80003ES2LAN_SERDES_SPT:
- case E1000_DEV_ID_80003ES2LAN_COPPER_DPT:
- case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
- hw->mac_type = e1000_80003es2lan;
- break;
- case E1000_DEV_ID_ICH8_IGP_M_AMT:
- case E1000_DEV_ID_ICH8_IGP_AMT:
- case E1000_DEV_ID_ICH8_IGP_C:
- case E1000_DEV_ID_ICH8_IFE:
- case E1000_DEV_ID_ICH8_IFE_GT:
- case E1000_DEV_ID_ICH8_IFE_G:
- case E1000_DEV_ID_ICH8_IGP_M:
- hw->mac_type = e1000_ich8lan;
- break;
default:
/* Should never have loaded on this device */
return -E1000_ERR_MAC_TYPE;
}
switch (hw->mac_type) {
- case e1000_ich8lan:
- hw->swfwhw_semaphore_present = true;
- hw->asf_firmware_present = true;
- break;
- case e1000_80003es2lan:
- hw->swfw_sync_present = true;
- /* fall through */
- case e1000_82571:
- case e1000_82572:
- case e1000_82573:
- hw->eeprom_semaphore_present = true;
- /* fall through */
case e1000_82541:
case e1000_82547:
case e1000_82541_rev_2:
if (hw->mac_type == e1000_82543)
hw->bad_tx_carr_stats_fd = true;
- /* capable of receiving management packets to the host */
- if (hw->mac_type >= e1000_82571)
- hw->has_manc2h = true;
-
- /* In rare occasions, ESB2 systems would end up started without
- * the RX unit being turned on.
- */
- if (hw->mac_type == e1000_80003es2lan)
- hw->rx_needs_kicking = true;
-
if (hw->mac_type > e1000_82544)
hw->has_smbus = true;
return E1000_SUCCESS;
}
-/*****************************************************************************
- * Set media type and TBI compatibility.
- *
- * hw - Struct containing variables accessed by shared code
- * **************************************************************************/
+/**
+ * e1000_set_media_type - Set media type and TBI compatibility.
+ * @hw: Struct containing variables accessed by shared code
+ */
void e1000_set_media_type(struct e1000_hw *hw)
{
- u32 status;
-
- DEBUGFUNC("e1000_set_media_type");
-
- if (hw->mac_type != e1000_82543) {
- /* tbi_compatibility is only valid on 82543 */
- hw->tbi_compatibility_en = false;
- }
-
- switch (hw->device_id) {
- case E1000_DEV_ID_82545GM_SERDES:
- case E1000_DEV_ID_82546GB_SERDES:
- case E1000_DEV_ID_82571EB_SERDES:
- case E1000_DEV_ID_82571EB_SERDES_DUAL:
- case E1000_DEV_ID_82571EB_SERDES_QUAD:
- case E1000_DEV_ID_82572EI_SERDES:
- case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
- hw->media_type = e1000_media_type_internal_serdes;
- break;
- default:
- switch (hw->mac_type) {
- case e1000_82542_rev2_0:
- case e1000_82542_rev2_1:
- hw->media_type = e1000_media_type_fiber;
- break;
- case e1000_ich8lan:
- case e1000_82573:
- /* The STATUS_TBIMODE bit is reserved or reused for the this
- * device.
- */
- hw->media_type = e1000_media_type_copper;
- break;
- default:
- status = er32(STATUS);
- if (status & E1000_STATUS_TBIMODE) {
- hw->media_type = e1000_media_type_fiber;
- /* tbi_compatibility not valid on fiber */
- hw->tbi_compatibility_en = false;
- } else {
- hw->media_type = e1000_media_type_copper;
- }
- break;
- }
- }
+ u32 status;
+
+ DEBUGFUNC("e1000_set_media_type");
+
+ if (hw->mac_type != e1000_82543) {
+ /* tbi_compatibility is only valid on 82543 */
+ hw->tbi_compatibility_en = false;
+ }
+
+ switch (hw->device_id) {
+ case E1000_DEV_ID_82545GM_SERDES:
+ case E1000_DEV_ID_82546GB_SERDES:
+ hw->media_type = e1000_media_type_internal_serdes;
+ break;
+ default:
+ switch (hw->mac_type) {
+ case e1000_82542_rev2_0:
+ case e1000_82542_rev2_1:
+ hw->media_type = e1000_media_type_fiber;
+ break;
+ default:
+ status = er32(STATUS);
+ if (status & E1000_STATUS_TBIMODE) {
+ hw->media_type = e1000_media_type_fiber;
+ /* tbi_compatibility not valid on fiber */
+ hw->tbi_compatibility_en = false;
+ } else {
+ hw->media_type = e1000_media_type_copper;
+ }
+ break;
+ }
+ }
}
-/******************************************************************************
- * Reset the transmit and receive units; mask and clear all interrupts.
+/**
+ * e1000_reset_hw: reset the hardware completely
+ * @hw: Struct containing variables accessed by shared code
*
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
+ * Reset the transmit and receive units; mask and clear all interrupts.
+ */
s32 e1000_reset_hw(struct e1000_hw *hw)
{
- u32 ctrl;
- u32 ctrl_ext;
- u32 icr;
- u32 manc;
- u32 led_ctrl;
- u32 timeout;
- u32 extcnf_ctrl;
- s32 ret_val;
-
- DEBUGFUNC("e1000_reset_hw");
-
- /* For 82542 (rev 2.0), disable MWI before issuing a device reset */
- if (hw->mac_type == e1000_82542_rev2_0) {
- DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
- e1000_pci_clear_mwi(hw);
- }
-
- if (hw->bus_type == e1000_bus_type_pci_express) {
- /* Prevent the PCI-E bus from sticking if there is no TLP connection
- * on the last TLP read/write transaction when MAC is reset.
- */
- if (e1000_disable_pciex_master(hw) != E1000_SUCCESS) {
- DEBUGOUT("PCI-E Master disable polling has failed.\n");
- }
- }
-
- /* Clear interrupt mask to stop board from generating interrupts */
- DEBUGOUT("Masking off all interrupts\n");
- ew32(IMC, 0xffffffff);
-
- /* Disable the Transmit and Receive units. Then delay to allow
- * any pending transactions to complete before we hit the MAC with
- * the global reset.
- */
- ew32(RCTL, 0);
- ew32(TCTL, E1000_TCTL_PSP);
- E1000_WRITE_FLUSH();
-
- /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
- hw->tbi_compatibility_on = false;
-
- /* Delay to allow any outstanding PCI transactions to complete before
- * resetting the device
- */
- msleep(10);
-
- ctrl = er32(CTRL);
-
- /* Must reset the PHY before resetting the MAC */
- if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
- ew32(CTRL, (ctrl | E1000_CTRL_PHY_RST));
- msleep(5);
- }
-
- /* Must acquire the MDIO ownership before MAC reset.
- * Ownership defaults to firmware after a reset. */
- if (hw->mac_type == e1000_82573) {
- timeout = 10;
-
- extcnf_ctrl = er32(EXTCNF_CTRL);
- extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
-
- do {
- ew32(EXTCNF_CTRL, extcnf_ctrl);
- extcnf_ctrl = er32(EXTCNF_CTRL);
-
- if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
- break;
- else
- extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
-
- msleep(2);
- timeout--;
- } while (timeout);
- }
-
- /* Workaround for ICH8 bit corruption issue in FIFO memory */
- if (hw->mac_type == e1000_ich8lan) {
- /* Set Tx and Rx buffer allocation to 8k apiece. */
- ew32(PBA, E1000_PBA_8K);
- /* Set Packet Buffer Size to 16k. */
- ew32(PBS, E1000_PBS_16K);
- }
-
- /* Issue a global reset to the MAC. This will reset the chip's
- * transmit, receive, DMA, and link units. It will not effect
- * the current PCI configuration. The global reset bit is self-
- * clearing, and should clear within a microsecond.
- */
- DEBUGOUT("Issuing a global reset to MAC\n");
-
- switch (hw->mac_type) {
- case e1000_82544:
- case e1000_82540:
- case e1000_82545:
- case e1000_82546:
- case e1000_82541:
- case e1000_82541_rev_2:
- /* These controllers can't ack the 64-bit write when issuing the
- * reset, so use IO-mapping as a workaround to issue the reset */
- E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST));
- break;
- case e1000_82545_rev_3:
- case e1000_82546_rev_3:
- /* Reset is performed on a shadow of the control register */
- ew32(CTRL_DUP, (ctrl | E1000_CTRL_RST));
- break;
- case e1000_ich8lan:
- if (!hw->phy_reset_disable &&
- e1000_check_phy_reset_block(hw) == E1000_SUCCESS) {
- /* e1000_ich8lan PHY HW reset requires MAC CORE reset
- * at the same time to make sure the interface between
- * MAC and the external PHY is reset.
- */
- ctrl |= E1000_CTRL_PHY_RST;
- }
-
- e1000_get_software_flag(hw);
- ew32(CTRL, (ctrl | E1000_CTRL_RST));
- msleep(5);
- break;
- default:
- ew32(CTRL, (ctrl | E1000_CTRL_RST));
- break;
- }
-
- /* After MAC reset, force reload of EEPROM to restore power-on settings to
- * device. Later controllers reload the EEPROM automatically, so just wait
- * for reload to complete.
- */
- switch (hw->mac_type) {
- case e1000_82542_rev2_0:
- case e1000_82542_rev2_1:
- case e1000_82543:
- case e1000_82544:
- /* Wait for reset to complete */
- udelay(10);
- ctrl_ext = er32(CTRL_EXT);
- ctrl_ext |= E1000_CTRL_EXT_EE_RST;
- ew32(CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH();
- /* Wait for EEPROM reload */
- msleep(2);
- break;
- case e1000_82541:
- case e1000_82541_rev_2:
- case e1000_82547:
- case e1000_82547_rev_2:
- /* Wait for EEPROM reload */
- msleep(20);
- break;
- case e1000_82573:
- if (!e1000_is_onboard_nvm_eeprom(hw)) {
- udelay(10);
- ctrl_ext = er32(CTRL_EXT);
- ctrl_ext |= E1000_CTRL_EXT_EE_RST;
- ew32(CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH();
- }
- /* fall through */
- default:
- /* Auto read done will delay 5ms or poll based on mac type */
- ret_val = e1000_get_auto_rd_done(hw);
- if (ret_val)
- return ret_val;
- break;
- }
-
- /* Disable HW ARPs on ASF enabled adapters */
- if (hw->mac_type >= e1000_82540 && hw->mac_type <= e1000_82547_rev_2) {
- manc = er32(MANC);
- manc &= ~(E1000_MANC_ARP_EN);
- ew32(MANC, manc);
- }
-
- if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
- e1000_phy_init_script(hw);
-
- /* Configure activity LED after PHY reset */
- led_ctrl = er32(LEDCTL);
- led_ctrl &= IGP_ACTIVITY_LED_MASK;
- led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
- ew32(LEDCTL, led_ctrl);
- }
-
- /* Clear interrupt mask to stop board from generating interrupts */
- DEBUGOUT("Masking off all interrupts\n");
- ew32(IMC, 0xffffffff);
-
- /* Clear any pending interrupt events. */
- icr = er32(ICR);
-
- /* If MWI was previously enabled, reenable it. */
- if (hw->mac_type == e1000_82542_rev2_0) {
- if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
- e1000_pci_set_mwi(hw);
- }
-
- if (hw->mac_type == e1000_ich8lan) {
- u32 kab = er32(KABGTXD);
- kab |= E1000_KABGTXD_BGSQLBIAS;
- ew32(KABGTXD, kab);
- }
-
- return E1000_SUCCESS;
-}
+ u32 ctrl;
+ u32 ctrl_ext;
+ u32 icr;
+ u32 manc;
+ u32 led_ctrl;
+ s32 ret_val;
-/******************************************************************************
- *
- * Initialize a number of hardware-dependent bits
- *
- * hw: Struct containing variables accessed by shared code
- *
- * This function contains hardware limitation workarounds for PCI-E adapters
- *
- *****************************************************************************/
-static void e1000_initialize_hardware_bits(struct e1000_hw *hw)
-{
- if ((hw->mac_type >= e1000_82571) && (!hw->initialize_hw_bits_disable)) {
- /* Settings common to all PCI-express silicon */
- u32 reg_ctrl, reg_ctrl_ext;
- u32 reg_tarc0, reg_tarc1;
- u32 reg_tctl;
- u32 reg_txdctl, reg_txdctl1;
-
- /* link autonegotiation/sync workarounds */
- reg_tarc0 = er32(TARC0);
- reg_tarc0 &= ~((1 << 30)|(1 << 29)|(1 << 28)|(1 << 27));
-
- /* Enable not-done TX descriptor counting */
- reg_txdctl = er32(TXDCTL);
- reg_txdctl |= E1000_TXDCTL_COUNT_DESC;
- ew32(TXDCTL, reg_txdctl);
- reg_txdctl1 = er32(TXDCTL1);
- reg_txdctl1 |= E1000_TXDCTL_COUNT_DESC;
- ew32(TXDCTL1, reg_txdctl1);
-
- switch (hw->mac_type) {
- case e1000_82571:
- case e1000_82572:
- /* Clear PHY TX compatible mode bits */
- reg_tarc1 = er32(TARC1);
- reg_tarc1 &= ~((1 << 30)|(1 << 29));
-
- /* link autonegotiation/sync workarounds */
- reg_tarc0 |= ((1 << 26)|(1 << 25)|(1 << 24)|(1 << 23));
-
- /* TX ring control fixes */
- reg_tarc1 |= ((1 << 26)|(1 << 25)|(1 << 24));
-
- /* Multiple read bit is reversed polarity */
- reg_tctl = er32(TCTL);
- if (reg_tctl & E1000_TCTL_MULR)
- reg_tarc1 &= ~(1 << 28);
- else
- reg_tarc1 |= (1 << 28);
-
- ew32(TARC1, reg_tarc1);
- break;
- case e1000_82573:
- reg_ctrl_ext = er32(CTRL_EXT);
- reg_ctrl_ext &= ~(1 << 23);
- reg_ctrl_ext |= (1 << 22);
-
- /* TX byte count fix */
- reg_ctrl = er32(CTRL);
- reg_ctrl &= ~(1 << 29);
-
- ew32(CTRL_EXT, reg_ctrl_ext);
- ew32(CTRL, reg_ctrl);
- break;
- case e1000_80003es2lan:
- /* improve small packet performace for fiber/serdes */
- if ((hw->media_type == e1000_media_type_fiber) ||
- (hw->media_type == e1000_media_type_internal_serdes)) {
- reg_tarc0 &= ~(1 << 20);
- }
-
- /* Multiple read bit is reversed polarity */
- reg_tctl = er32(TCTL);
- reg_tarc1 = er32(TARC1);
- if (reg_tctl & E1000_TCTL_MULR)
- reg_tarc1 &= ~(1 << 28);
- else
- reg_tarc1 |= (1 << 28);
-
- ew32(TARC1, reg_tarc1);
- break;
- case e1000_ich8lan:
- /* Reduce concurrent DMA requests to 3 from 4 */
- if ((hw->revision_id < 3) ||
- ((hw->device_id != E1000_DEV_ID_ICH8_IGP_M_AMT) &&
- (hw->device_id != E1000_DEV_ID_ICH8_IGP_M)))
- reg_tarc0 |= ((1 << 29)|(1 << 28));
-
- reg_ctrl_ext = er32(CTRL_EXT);
- reg_ctrl_ext |= (1 << 22);
- ew32(CTRL_EXT, reg_ctrl_ext);
-
- /* workaround TX hang with TSO=on */
- reg_tarc0 |= ((1 << 27)|(1 << 26)|(1 << 24)|(1 << 23));
-
- /* Multiple read bit is reversed polarity */
- reg_tctl = er32(TCTL);
- reg_tarc1 = er32(TARC1);
- if (reg_tctl & E1000_TCTL_MULR)
- reg_tarc1 &= ~(1 << 28);
- else
- reg_tarc1 |= (1 << 28);
-
- /* workaround TX hang with TSO=on */
- reg_tarc1 |= ((1 << 30)|(1 << 26)|(1 << 24));
-
- ew32(TARC1, reg_tarc1);
- break;
- default:
- break;
- }
-
- ew32(TARC0, reg_tarc0);
- }
+ DEBUGFUNC("e1000_reset_hw");
+
+ /* For 82542 (rev 2.0), disable MWI before issuing a device reset */
+ if (hw->mac_type == e1000_82542_rev2_0) {
+ DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
+ e1000_pci_clear_mwi(hw);
+ }
+
+ /* Clear interrupt mask to stop board from generating interrupts */
+ DEBUGOUT("Masking off all interrupts\n");
+ ew32(IMC, 0xffffffff);
+
+ /* Disable the Transmit and Receive units. Then delay to allow
+ * any pending transactions to complete before we hit the MAC with
+ * the global reset.
+ */
+ ew32(RCTL, 0);
+ ew32(TCTL, E1000_TCTL_PSP);
+ E1000_WRITE_FLUSH();
+
+ /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
+ hw->tbi_compatibility_on = false;
+
+ /* Delay to allow any outstanding PCI transactions to complete before
+ * resetting the device
+ */
+ msleep(10);
+
+ ctrl = er32(CTRL);
+
+ /* Must reset the PHY before resetting the MAC */
+ if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
+ ew32(CTRL, (ctrl | E1000_CTRL_PHY_RST));
+ msleep(5);
+ }
+
+ /* Issue a global reset to the MAC. This will reset the chip's
+ * transmit, receive, DMA, and link units. It will not effect
+ * the current PCI configuration. The global reset bit is self-
+ * clearing, and should clear within a microsecond.
+ */
+ DEBUGOUT("Issuing a global reset to MAC\n");
+
+ switch (hw->mac_type) {
+ case e1000_82544:
+ case e1000_82540:
+ case e1000_82545:
+ case e1000_82546:
+ case e1000_82541:
+ case e1000_82541_rev_2:
+ /* These controllers can't ack the 64-bit write when issuing the
+ * reset, so use IO-mapping as a workaround to issue the reset */
+ E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST));
+ break;
+ case e1000_82545_rev_3:
+ case e1000_82546_rev_3:
+ /* Reset is performed on a shadow of the control register */
+ ew32(CTRL_DUP, (ctrl | E1000_CTRL_RST));
+ break;
+ default:
+ ew32(CTRL, (ctrl | E1000_CTRL_RST));
+ break;
+ }
+
+ /* After MAC reset, force reload of EEPROM to restore power-on settings to
+ * device. Later controllers reload the EEPROM automatically, so just wait
+ * for reload to complete.
+ */
+ switch (hw->mac_type) {
+ case e1000_82542_rev2_0:
+ case e1000_82542_rev2_1:
+ case e1000_82543:
+ case e1000_82544:
+ /* Wait for reset to complete */
+ udelay(10);
+ ctrl_ext = er32(CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_EE_RST;
+ ew32(CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH();
+ /* Wait for EEPROM reload */
+ msleep(2);
+ break;
+ case e1000_82541:
+ case e1000_82541_rev_2:
+ case e1000_82547:
+ case e1000_82547_rev_2:
+ /* Wait for EEPROM reload */
+ msleep(20);
+ break;
+ default:
+ /* Auto read done will delay 5ms or poll based on mac type */
+ ret_val = e1000_get_auto_rd_done(hw);
+ if (ret_val)
+ return ret_val;
+ break;
+ }
+
+ /* Disable HW ARPs on ASF enabled adapters */
+ if (hw->mac_type >= e1000_82540) {
+ manc = er32(MANC);
+ manc &= ~(E1000_MANC_ARP_EN);
+ ew32(MANC, manc);
+ }
+
+ if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
+ e1000_phy_init_script(hw);
+
+ /* Configure activity LED after PHY reset */
+ led_ctrl = er32(LEDCTL);
+ led_ctrl &= IGP_ACTIVITY_LED_MASK;
+ led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
+ ew32(LEDCTL, led_ctrl);
+ }
+
+ /* Clear interrupt mask to stop board from generating interrupts */
+ DEBUGOUT("Masking off all interrupts\n");
+ ew32(IMC, 0xffffffff);
+
+ /* Clear any pending interrupt events. */
+ icr = er32(ICR);
+
+ /* If MWI was previously enabled, reenable it. */
+ if (hw->mac_type == e1000_82542_rev2_0) {
+ if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
+ e1000_pci_set_mwi(hw);
+ }
+
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * Performs basic configuration of the adapter.
- *
- * hw - Struct containing variables accessed by shared code
+/**
+ * e1000_init_hw: Performs basic configuration of the adapter.
+ * @hw: Struct containing variables accessed by shared code
*
* Assumes that the controller has previously been reset and is in a
* post-reset uninitialized state. Initializes the receive address registers,
* multicast table, and VLAN filter table. Calls routines to setup link
* configuration and flow control settings. Clears all on-chip counters. Leaves
* the transmit and receive units disabled and uninitialized.
- *****************************************************************************/
+ */
s32 e1000_init_hw(struct e1000_hw *hw)
{
- u32 ctrl;
- u32 i;
- s32 ret_val;
- u32 mta_size;
- u32 reg_data;
- u32 ctrl_ext;
-
- DEBUGFUNC("e1000_init_hw");
-
- /* force full DMA clock frequency for 10/100 on ICH8 A0-B0 */
- if ((hw->mac_type == e1000_ich8lan) &&
- ((hw->revision_id < 3) ||
- ((hw->device_id != E1000_DEV_ID_ICH8_IGP_M_AMT) &&
- (hw->device_id != E1000_DEV_ID_ICH8_IGP_M)))) {
- reg_data = er32(STATUS);
- reg_data &= ~0x80000000;
- ew32(STATUS, reg_data);
- }
-
- /* Initialize Identification LED */
- ret_val = e1000_id_led_init(hw);
- if (ret_val) {
- DEBUGOUT("Error Initializing Identification LED\n");
- return ret_val;
- }
-
- /* Set the media type and TBI compatibility */
- e1000_set_media_type(hw);
-
- /* Must be called after e1000_set_media_type because media_type is used */
- e1000_initialize_hardware_bits(hw);
-
- /* Disabling VLAN filtering. */
- DEBUGOUT("Initializing the IEEE VLAN\n");
- /* VET hardcoded to standard value and VFTA removed in ICH8 LAN */
- if (hw->mac_type != e1000_ich8lan) {
- if (hw->mac_type < e1000_82545_rev_3)
- ew32(VET, 0);
- e1000_clear_vfta(hw);
- }
-
- /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
- if (hw->mac_type == e1000_82542_rev2_0) {
- DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
- e1000_pci_clear_mwi(hw);
- ew32(RCTL, E1000_RCTL_RST);
- E1000_WRITE_FLUSH();
- msleep(5);
- }
-
- /* Setup the receive address. This involves initializing all of the Receive
- * Address Registers (RARs 0 - 15).
- */
- e1000_init_rx_addrs(hw);
-
- /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
- if (hw->mac_type == e1000_82542_rev2_0) {
- ew32(RCTL, 0);
- E1000_WRITE_FLUSH();
- msleep(1);
- if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
- e1000_pci_set_mwi(hw);
- }
-
- /* Zero out the Multicast HASH table */
- DEBUGOUT("Zeroing the MTA\n");
- mta_size = E1000_MC_TBL_SIZE;
- if (hw->mac_type == e1000_ich8lan)
- mta_size = E1000_MC_TBL_SIZE_ICH8LAN;
- for (i = 0; i < mta_size; i++) {
- E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
- /* use write flush to prevent Memory Write Block (MWB) from
- * occuring when accessing our register space */
- E1000_WRITE_FLUSH();
- }
-
- /* Set the PCI priority bit correctly in the CTRL register. This
- * determines if the adapter gives priority to receives, or if it
- * gives equal priority to transmits and receives. Valid only on
- * 82542 and 82543 silicon.
- */
- if (hw->dma_fairness && hw->mac_type <= e1000_82543) {
- ctrl = er32(CTRL);
- ew32(CTRL, ctrl | E1000_CTRL_PRIOR);
- }
-
- switch (hw->mac_type) {
- case e1000_82545_rev_3:
- case e1000_82546_rev_3:
- break;
- default:
- /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */
- if (hw->bus_type == e1000_bus_type_pcix && e1000_pcix_get_mmrbc(hw) > 2048)
- e1000_pcix_set_mmrbc(hw, 2048);
- break;
- }
-
- /* More time needed for PHY to initialize */
- if (hw->mac_type == e1000_ich8lan)
- msleep(15);
-
- /* Call a subroutine to configure the link and setup flow control. */
- ret_val = e1000_setup_link(hw);
-
- /* Set the transmit descriptor write-back policy */
- if (hw->mac_type > e1000_82544) {
- ctrl = er32(TXDCTL);
- ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
- ew32(TXDCTL, ctrl);
- }
-
- if (hw->mac_type == e1000_82573) {
- e1000_enable_tx_pkt_filtering(hw);
- }
-
- switch (hw->mac_type) {
- default:
- break;
- case e1000_80003es2lan:
- /* Enable retransmit on late collisions */
- reg_data = er32(TCTL);
- reg_data |= E1000_TCTL_RTLC;
- ew32(TCTL, reg_data);
-
- /* Configure Gigabit Carry Extend Padding */
- reg_data = er32(TCTL_EXT);
- reg_data &= ~E1000_TCTL_EXT_GCEX_MASK;
- reg_data |= DEFAULT_80003ES2LAN_TCTL_EXT_GCEX;
- ew32(TCTL_EXT, reg_data);
-
- /* Configure Transmit Inter-Packet Gap */
- reg_data = er32(TIPG);
- reg_data &= ~E1000_TIPG_IPGT_MASK;
- reg_data |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000;
- ew32(TIPG, reg_data);
-
- reg_data = E1000_READ_REG_ARRAY(hw, FFLT, 0x0001);
- reg_data &= ~0x00100000;
- E1000_WRITE_REG_ARRAY(hw, FFLT, 0x0001, reg_data);
- /* Fall through */
- case e1000_82571:
- case e1000_82572:
- case e1000_ich8lan:
- ctrl = er32(TXDCTL1);
- ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
- ew32(TXDCTL1, ctrl);
- break;
- }
-
-
- if (hw->mac_type == e1000_82573) {
- u32 gcr = er32(GCR);
- gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
- ew32(GCR, gcr);
- }
-
- /* Clear all of the statistics registers (clear on read). It is
- * important that we do this after we have tried to establish link
- * because the symbol error count will increment wildly if there
- * is no link.
- */
- e1000_clear_hw_cntrs(hw);
-
- /* ICH8 No-snoop bits are opposite polarity.
- * Set to snoop by default after reset. */
- if (hw->mac_type == e1000_ich8lan)
- e1000_set_pci_ex_no_snoop(hw, PCI_EX_82566_SNOOP_ALL);
-
- if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
- hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
- ctrl_ext = er32(CTRL_EXT);
- /* Relaxed ordering must be disabled to avoid a parity
- * error crash in a PCI slot. */
- ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
- ew32(CTRL_EXT, ctrl_ext);
- }
-
- return ret_val;
-}
+ u32 ctrl;
+ u32 i;
+ s32 ret_val;
+ u32 mta_size;
+ u32 ctrl_ext;
-/******************************************************************************
- * Adjust SERDES output amplitude based on EEPROM setting.
- *
- * hw - Struct containing variables accessed by shared code.
- *****************************************************************************/
-static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
-{
- u16 eeprom_data;
- s32 ret_val;
-
- DEBUGFUNC("e1000_adjust_serdes_amplitude");
-
- if (hw->media_type != e1000_media_type_internal_serdes)
- return E1000_SUCCESS;
-
- switch (hw->mac_type) {
- case e1000_82545_rev_3:
- case e1000_82546_rev_3:
- break;
- default:
- return E1000_SUCCESS;
- }
-
- ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1, &eeprom_data);
- if (ret_val) {
- return ret_val;
- }
-
- if (eeprom_data != EEPROM_RESERVED_WORD) {
- /* Adjust SERDES output amplitude only. */
- eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK;
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data);
- if (ret_val)
- return ret_val;
- }
-
- return E1000_SUCCESS;
-}
+ DEBUGFUNC("e1000_init_hw");
-/******************************************************************************
- * Configures flow control and link settings.
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Determines which flow control settings to use. Calls the apropriate media-
- * specific link configuration function. Configures the flow control settings.
- * Assuming the adapter has a valid link partner, a valid link should be
- * established. Assumes the hardware has previously been reset and the
- * transmitter and receiver are not enabled.
- *****************************************************************************/
-s32 e1000_setup_link(struct e1000_hw *hw)
-{
- u32 ctrl_ext;
- s32 ret_val;
- u16 eeprom_data;
-
- DEBUGFUNC("e1000_setup_link");
-
- /* In the case of the phy reset being blocked, we already have a link.
- * We do not have to set it up again. */
- if (e1000_check_phy_reset_block(hw))
- return E1000_SUCCESS;
-
- /* Read and store word 0x0F of the EEPROM. This word contains bits
- * that determine the hardware's default PAUSE (flow control) mode,
- * a bit that determines whether the HW defaults to enabling or
- * disabling auto-negotiation, and the direction of the
- * SW defined pins. If there is no SW over-ride of the flow
- * control setting, then the variable hw->fc will
- * be initialized based on a value in the EEPROM.
- */
- if (hw->fc == E1000_FC_DEFAULT) {
- switch (hw->mac_type) {
- case e1000_ich8lan:
- case e1000_82573:
- hw->fc = E1000_FC_FULL;
- break;
- default:
- ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
- 1, &eeprom_data);
- if (ret_val) {
- DEBUGOUT("EEPROM Read Error\n");
- return -E1000_ERR_EEPROM;
- }
- if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
- hw->fc = E1000_FC_NONE;
- else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
- EEPROM_WORD0F_ASM_DIR)
- hw->fc = E1000_FC_TX_PAUSE;
- else
- hw->fc = E1000_FC_FULL;
- break;
- }
- }
-
- /* We want to save off the original Flow Control configuration just
- * in case we get disconnected and then reconnected into a different
- * hub or switch with different Flow Control capabilities.
- */
- if (hw->mac_type == e1000_82542_rev2_0)
- hw->fc &= (~E1000_FC_TX_PAUSE);
-
- if ((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1))
- hw->fc &= (~E1000_FC_RX_PAUSE);
-
- hw->original_fc = hw->fc;
-
- DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc);
-
- /* Take the 4 bits from EEPROM word 0x0F that determine the initial
- * polarity value for the SW controlled pins, and setup the
- * Extended Device Control reg with that info.
- * This is needed because one of the SW controlled pins is used for
- * signal detection. So this should be done before e1000_setup_pcs_link()
- * or e1000_phy_setup() is called.
- */
- if (hw->mac_type == e1000_82543) {
- ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
- 1, &eeprom_data);
- if (ret_val) {
- DEBUGOUT("EEPROM Read Error\n");
- return -E1000_ERR_EEPROM;
- }
- ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) <<
- SWDPIO__EXT_SHIFT);
- ew32(CTRL_EXT, ctrl_ext);
- }
-
- /* Call the necessary subroutine to configure the link. */
- ret_val = (hw->media_type == e1000_media_type_copper) ?
- e1000_setup_copper_link(hw) :
- e1000_setup_fiber_serdes_link(hw);
-
- /* Initialize the flow control address, type, and PAUSE timer
- * registers to their default values. This is done even if flow
- * control is disabled, because it does not hurt anything to
- * initialize these registers.
- */
- DEBUGOUT("Initializing the Flow Control address, type and timer regs\n");
-
- /* FCAL/H and FCT are hardcoded to standard values in e1000_ich8lan. */
- if (hw->mac_type != e1000_ich8lan) {
- ew32(FCT, FLOW_CONTROL_TYPE);
- ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
- ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
- }
-
- ew32(FCTTV, hw->fc_pause_time);
-
- /* Set the flow control receive threshold registers. Normally,
- * these registers will be set to a default threshold that may be
- * adjusted later by the driver's runtime code. However, if the
- * ability to transmit pause frames in not enabled, then these
- * registers will be set to 0.
- */
- if (!(hw->fc & E1000_FC_TX_PAUSE)) {
- ew32(FCRTL, 0);
- ew32(FCRTH, 0);
- } else {
- /* We need to set up the Receive Threshold high and low water marks
- * as well as (optionally) enabling the transmission of XON frames.
- */
- if (hw->fc_send_xon) {
- ew32(FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
- ew32(FCRTH, hw->fc_high_water);
- } else {
- ew32(FCRTL, hw->fc_low_water);
- ew32(FCRTH, hw->fc_high_water);
- }
- }
- return ret_val;
-}
+ /* Initialize Identification LED */
+ ret_val = e1000_id_led_init(hw);
+ if (ret_val) {
+ DEBUGOUT("Error Initializing Identification LED\n");
+ return ret_val;
+ }
-/******************************************************************************
- * Sets up link for a fiber based or serdes based adapter
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Manipulates Physical Coding Sublayer functions in order to configure
- * link. Assumes the hardware has been previously reset and the transmitter
- * and receiver are not enabled.
- *****************************************************************************/
-static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
-{
- u32 ctrl;
- u32 status;
- u32 txcw = 0;
- u32 i;
- u32 signal = 0;
- s32 ret_val;
-
- DEBUGFUNC("e1000_setup_fiber_serdes_link");
-
- /* On 82571 and 82572 Fiber connections, SerDes loopback mode persists
- * until explicitly turned off or a power cycle is performed. A read to
- * the register does not indicate its status. Therefore, we ensure
- * loopback mode is disabled during initialization.
- */
- if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572)
- ew32(SCTL, E1000_DISABLE_SERDES_LOOPBACK);
-
- /* On adapters with a MAC newer than 82544, SWDP 1 will be
- * set when the optics detect a signal. On older adapters, it will be
- * cleared when there is a signal. This applies to fiber media only.
- * If we're on serdes media, adjust the output amplitude to value
- * set in the EEPROM.
- */
- ctrl = er32(CTRL);
- if (hw->media_type == e1000_media_type_fiber)
- signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
-
- ret_val = e1000_adjust_serdes_amplitude(hw);
- if (ret_val)
- return ret_val;
-
- /* Take the link out of reset */
- ctrl &= ~(E1000_CTRL_LRST);
-
- /* Adjust VCO speed to improve BER performance */
- ret_val = e1000_set_vco_speed(hw);
- if (ret_val)
- return ret_val;
-
- e1000_config_collision_dist(hw);
-
- /* Check for a software override of the flow control settings, and setup
- * the device accordingly. If auto-negotiation is enabled, then software
- * will have to set the "PAUSE" bits to the correct value in the Tranmsit
- * Config Word Register (TXCW) and re-start auto-negotiation. However, if
- * auto-negotiation is disabled, then software will have to manually
- * configure the two flow control enable bits in the CTRL register.
- *
- * The possible values of the "fc" parameter are:
- * 0: Flow control is completely disabled
- * 1: Rx flow control is enabled (we can receive pause frames, but
- * not send pause frames).
- * 2: Tx flow control is enabled (we can send pause frames but we do
- * not support receiving pause frames).
- * 3: Both Rx and TX flow control (symmetric) are enabled.
- */
- switch (hw->fc) {
- case E1000_FC_NONE:
- /* Flow control is completely disabled by a software over-ride. */
- txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
- break;
- case E1000_FC_RX_PAUSE:
- /* RX Flow control is enabled and TX Flow control is disabled by a
- * software over-ride. Since there really isn't a way to advertise
- * that we are capable of RX Pause ONLY, we will advertise that we
- * support both symmetric and asymmetric RX PAUSE. Later, we will
- * disable the adapter's ability to send PAUSE frames.
- */
- txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
- break;
- case E1000_FC_TX_PAUSE:
- /* TX Flow control is enabled, and RX Flow control is disabled, by a
- * software over-ride.
- */
- txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
- break;
- case E1000_FC_FULL:
- /* Flow control (both RX and TX) is enabled by a software over-ride. */
- txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
- break;
- default:
- DEBUGOUT("Flow control param set incorrectly\n");
- return -E1000_ERR_CONFIG;
- break;
- }
-
- /* Since auto-negotiation is enabled, take the link out of reset (the link
- * will be in reset, because we previously reset the chip). This will
- * restart auto-negotiation. If auto-neogtiation is successful then the
- * link-up status bit will be set and the flow control enable bits (RFCE
- * and TFCE) will be set according to their negotiated value.
- */
- DEBUGOUT("Auto-negotiation enabled\n");
-
- ew32(TXCW, txcw);
- ew32(CTRL, ctrl);
- E1000_WRITE_FLUSH();
-
- hw->txcw = txcw;
- msleep(1);
-
- /* If we have a signal (the cable is plugged in) then poll for a "Link-Up"
- * indication in the Device Status Register. Time-out if a link isn't
- * seen in 500 milliseconds seconds (Auto-negotiation should complete in
- * less than 500 milliseconds even if the other end is doing it in SW).
- * For internal serdes, we just assume a signal is present, then poll.
- */
- if (hw->media_type == e1000_media_type_internal_serdes ||
- (er32(CTRL) & E1000_CTRL_SWDPIN1) == signal) {
- DEBUGOUT("Looking for Link\n");
- for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
- msleep(10);
- status = er32(STATUS);
- if (status & E1000_STATUS_LU) break;
- }
- if (i == (LINK_UP_TIMEOUT / 10)) {
- DEBUGOUT("Never got a valid link from auto-neg!!!\n");
- hw->autoneg_failed = 1;
- /* AutoNeg failed to achieve a link, so we'll call
- * e1000_check_for_link. This routine will force the link up if
- * we detect a signal. This will allow us to communicate with
- * non-autonegotiating link partners.
- */
- ret_val = e1000_check_for_link(hw);
- if (ret_val) {
- DEBUGOUT("Error while checking for link\n");
- return ret_val;
- }
- hw->autoneg_failed = 0;
- } else {
- hw->autoneg_failed = 0;
- DEBUGOUT("Valid Link Found\n");
- }
- } else {
- DEBUGOUT("No Signal Detected\n");
- }
- return E1000_SUCCESS;
-}
+ /* Set the media type and TBI compatibility */
+ e1000_set_media_type(hw);
+
+ /* Disabling VLAN filtering. */
+ DEBUGOUT("Initializing the IEEE VLAN\n");
+ if (hw->mac_type < e1000_82545_rev_3)
+ ew32(VET, 0);
+ e1000_clear_vfta(hw);
+
+ /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
+ if (hw->mac_type == e1000_82542_rev2_0) {
+ DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
+ e1000_pci_clear_mwi(hw);
+ ew32(RCTL, E1000_RCTL_RST);
+ E1000_WRITE_FLUSH();
+ msleep(5);
+ }
-/******************************************************************************
-* Make sure we have a valid PHY and change PHY mode before link setup.
-*
-* hw - Struct containing variables accessed by shared code
-******************************************************************************/
-static s32 e1000_copper_link_preconfig(struct e1000_hw *hw)
-{
- u32 ctrl;
- s32 ret_val;
- u16 phy_data;
-
- DEBUGFUNC("e1000_copper_link_preconfig");
-
- ctrl = er32(CTRL);
- /* With 82543, we need to force speed and duplex on the MAC equal to what
- * the PHY speed and duplex configuration is. In addition, we need to
- * perform a hardware reset on the PHY to take it out of reset.
- */
- if (hw->mac_type > e1000_82543) {
- ctrl |= E1000_CTRL_SLU;
- ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
- ew32(CTRL, ctrl);
- } else {
- ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
- ew32(CTRL, ctrl);
- ret_val = e1000_phy_hw_reset(hw);
- if (ret_val)
- return ret_val;
- }
-
- /* Make sure we have a valid PHY */
- ret_val = e1000_detect_gig_phy(hw);
- if (ret_val) {
- DEBUGOUT("Error, did not detect valid phy.\n");
- return ret_val;
- }
- DEBUGOUT1("Phy ID = %x \n", hw->phy_id);
-
- /* Set PHY to class A mode (if necessary) */
- ret_val = e1000_set_phy_mode(hw);
- if (ret_val)
- return ret_val;
-
- if ((hw->mac_type == e1000_82545_rev_3) ||
- (hw->mac_type == e1000_82546_rev_3)) {
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
- phy_data |= 0x00000008;
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
- }
-
- if (hw->mac_type <= e1000_82543 ||
- hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
- hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2)
- hw->phy_reset_disable = false;
-
- return E1000_SUCCESS;
-}
+ /* Setup the receive address. This involves initializing all of the Receive
+ * Address Registers (RARs 0 - 15).
+ */
+ e1000_init_rx_addrs(hw);
+
+ /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
+ if (hw->mac_type == e1000_82542_rev2_0) {
+ ew32(RCTL, 0);
+ E1000_WRITE_FLUSH();
+ msleep(1);
+ if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
+ e1000_pci_set_mwi(hw);
+ }
+ /* Zero out the Multicast HASH table */
+ DEBUGOUT("Zeroing the MTA\n");
+ mta_size = E1000_MC_TBL_SIZE;
+ for (i = 0; i < mta_size; i++) {
+ E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
+ /* use write flush to prevent Memory Write Block (MWB) from
+ * occurring when accessing our register space */
+ E1000_WRITE_FLUSH();
+ }
-/********************************************************************
-* Copper link setup for e1000_phy_igp series.
-*
-* hw - Struct containing variables accessed by shared code
-*********************************************************************/
-static s32 e1000_copper_link_igp_setup(struct e1000_hw *hw)
-{
- u32 led_ctrl;
- s32 ret_val;
- u16 phy_data;
-
- DEBUGFUNC("e1000_copper_link_igp_setup");
-
- if (hw->phy_reset_disable)
- return E1000_SUCCESS;
-
- ret_val = e1000_phy_reset(hw);
- if (ret_val) {
- DEBUGOUT("Error Resetting the PHY\n");
- return ret_val;
- }
-
- /* Wait 15ms for MAC to configure PHY from eeprom settings */
- msleep(15);
- if (hw->mac_type != e1000_ich8lan) {
- /* Configure activity LED after PHY reset */
- led_ctrl = er32(LEDCTL);
- led_ctrl &= IGP_ACTIVITY_LED_MASK;
- led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
- ew32(LEDCTL, led_ctrl);
- }
-
- /* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */
- if (hw->phy_type == e1000_phy_igp) {
- /* disable lplu d3 during driver init */
- ret_val = e1000_set_d3_lplu_state(hw, false);
- if (ret_val) {
- DEBUGOUT("Error Disabling LPLU D3\n");
- return ret_val;
- }
- }
-
- /* disable lplu d0 during driver init */
- ret_val = e1000_set_d0_lplu_state(hw, false);
- if (ret_val) {
- DEBUGOUT("Error Disabling LPLU D0\n");
- return ret_val;
- }
- /* Configure mdi-mdix settings */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
- if (ret_val)
- return ret_val;
-
- if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
- hw->dsp_config_state = e1000_dsp_config_disabled;
- /* Force MDI for earlier revs of the IGP PHY */
- phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | IGP01E1000_PSCR_FORCE_MDI_MDIX);
- hw->mdix = 1;
-
- } else {
- hw->dsp_config_state = e1000_dsp_config_enabled;
- phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
-
- switch (hw->mdix) {
- case 1:
- phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
- break;
- case 2:
- phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
- break;
- case 0:
- default:
- phy_data |= IGP01E1000_PSCR_AUTO_MDIX;
- break;
- }
- }
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
- if (ret_val)
- return ret_val;
-
- /* set auto-master slave resolution settings */
- if (hw->autoneg) {
- e1000_ms_type phy_ms_setting = hw->master_slave;
-
- if (hw->ffe_config_state == e1000_ffe_config_active)
- hw->ffe_config_state = e1000_ffe_config_enabled;
-
- if (hw->dsp_config_state == e1000_dsp_config_activated)
- hw->dsp_config_state = e1000_dsp_config_enabled;
-
- /* when autonegotiation advertisment is only 1000Mbps then we
- * should disable SmartSpeed and enable Auto MasterSlave
- * resolution as hardware default. */
- if (hw->autoneg_advertised == ADVERTISE_1000_FULL) {
- /* Disable SmartSpeed */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- &phy_data);
- if (ret_val)
- return ret_val;
- phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- phy_data);
- if (ret_val)
- return ret_val;
- /* Set auto Master/Slave resolution process */
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
- if (ret_val)
- return ret_val;
- phy_data &= ~CR_1000T_MS_ENABLE;
- ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
- if (ret_val)
- return ret_val;
- }
-
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
- if (ret_val)
- return ret_val;
-
- /* load defaults for future use */
- hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?
- ((phy_data & CR_1000T_MS_VALUE) ?
- e1000_ms_force_master :
- e1000_ms_force_slave) :
- e1000_ms_auto;
-
- switch (phy_ms_setting) {
- case e1000_ms_force_master:
- phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
- break;
- case e1000_ms_force_slave:
- phy_data |= CR_1000T_MS_ENABLE;
- phy_data &= ~(CR_1000T_MS_VALUE);
- break;
- case e1000_ms_auto:
- phy_data &= ~CR_1000T_MS_ENABLE;
- default:
- break;
- }
- ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
- if (ret_val)
- return ret_val;
- }
-
- return E1000_SUCCESS;
-}
+ /* Set the PCI priority bit correctly in the CTRL register. This
+ * determines if the adapter gives priority to receives, or if it
+ * gives equal priority to transmits and receives. Valid only on
+ * 82542 and 82543 silicon.
+ */
+ if (hw->dma_fairness && hw->mac_type <= e1000_82543) {
+ ctrl = er32(CTRL);
+ ew32(CTRL, ctrl | E1000_CTRL_PRIOR);
+ }
-/********************************************************************
-* Copper link setup for e1000_phy_gg82563 series.
-*
-* hw - Struct containing variables accessed by shared code
-*********************************************************************/
-static s32 e1000_copper_link_ggp_setup(struct e1000_hw *hw)
-{
- s32 ret_val;
- u16 phy_data;
- u32 reg_data;
-
- DEBUGFUNC("e1000_copper_link_ggp_setup");
-
- if (!hw->phy_reset_disable) {
-
- /* Enable CRS on TX for half-duplex operation. */
- ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
- /* Use 25MHz for both link down and 1000BASE-T for Tx clock */
- phy_data |= GG82563_MSCR_TX_CLK_1000MBPS_25MHZ;
-
- ret_val = e1000_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
- phy_data);
- if (ret_val)
- return ret_val;
-
- /* Options:
- * MDI/MDI-X = 0 (default)
- * 0 - Auto for all speeds
- * 1 - MDI mode
- * 2 - MDI-X mode
- * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
- */
- ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK;
-
- switch (hw->mdix) {
- case 1:
- phy_data |= GG82563_PSCR_CROSSOVER_MODE_MDI;
- break;
- case 2:
- phy_data |= GG82563_PSCR_CROSSOVER_MODE_MDIX;
- break;
- case 0:
- default:
- phy_data |= GG82563_PSCR_CROSSOVER_MODE_AUTO;
- break;
- }
-
- /* Options:
- * disable_polarity_correction = 0 (default)
- * Automatic Correction for Reversed Cable Polarity
- * 0 - Disabled
- * 1 - Enabled
- */
- phy_data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
- if (hw->disable_polarity_correction == 1)
- phy_data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
- ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data);
-
- if (ret_val)
- return ret_val;
-
- /* SW Reset the PHY so all changes take effect */
- ret_val = e1000_phy_reset(hw);
- if (ret_val) {
- DEBUGOUT("Error Resetting the PHY\n");
- return ret_val;
- }
- } /* phy_reset_disable */
-
- if (hw->mac_type == e1000_80003es2lan) {
- /* Bypass RX and TX FIFO's */
- ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL,
- E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS |
- E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS);
- if (ret_val)
- return ret_val;
-
- ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG;
- ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, phy_data);
-
- if (ret_val)
- return ret_val;
-
- reg_data = er32(CTRL_EXT);
- reg_data &= ~(E1000_CTRL_EXT_LINK_MODE_MASK);
- ew32(CTRL_EXT, reg_data);
-
- ret_val = e1000_read_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- /* Do not init these registers when the HW is in IAMT mode, since the
- * firmware will have already initialized them. We only initialize
- * them if the HW is not in IAMT mode.
- */
- if (!e1000_check_mng_mode(hw)) {
- /* Enable Electrical Idle on the PHY */
- phy_data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
- ret_val = e1000_write_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
- phy_data);
- if (ret_val)
- return ret_val;
-
- ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
- ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
- phy_data);
-
- if (ret_val)
- return ret_val;
- }
-
- /* Workaround: Disable padding in Kumeran interface in the MAC
- * and in the PHY to avoid CRC errors.
- */
- ret_val = e1000_read_phy_reg(hw, GG82563_PHY_INBAND_CTRL,
- &phy_data);
- if (ret_val)
- return ret_val;
- phy_data |= GG82563_ICR_DIS_PADDING;
- ret_val = e1000_write_phy_reg(hw, GG82563_PHY_INBAND_CTRL,
- phy_data);
- if (ret_val)
- return ret_val;
- }
-
- return E1000_SUCCESS;
-}
+ switch (hw->mac_type) {
+ case e1000_82545_rev_3:
+ case e1000_82546_rev_3:
+ break;
+ default:
+ /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */
+ if (hw->bus_type == e1000_bus_type_pcix
+ && e1000_pcix_get_mmrbc(hw) > 2048)
+ e1000_pcix_set_mmrbc(hw, 2048);
+ break;
+ }
-/********************************************************************
-* Copper link setup for e1000_phy_m88 series.
-*
-* hw - Struct containing variables accessed by shared code
-*********************************************************************/
-static s32 e1000_copper_link_mgp_setup(struct e1000_hw *hw)
-{
- s32 ret_val;
- u16 phy_data;
-
- DEBUGFUNC("e1000_copper_link_mgp_setup");
-
- if (hw->phy_reset_disable)
- return E1000_SUCCESS;
-
- /* Enable CRS on TX. This must be set for half-duplex operation. */
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
-
- /* Options:
- * MDI/MDI-X = 0 (default)
- * 0 - Auto for all speeds
- * 1 - MDI mode
- * 2 - MDI-X mode
- * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
- */
- phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
-
- switch (hw->mdix) {
- case 1:
- phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
- break;
- case 2:
- phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
- break;
- case 3:
- phy_data |= M88E1000_PSCR_AUTO_X_1000T;
- break;
- case 0:
- default:
- phy_data |= M88E1000_PSCR_AUTO_X_MODE;
- break;
- }
-
- /* Options:
- * disable_polarity_correction = 0 (default)
- * Automatic Correction for Reversed Cable Polarity
- * 0 - Disabled
- * 1 - Enabled
- */
- phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
- if (hw->disable_polarity_correction == 1)
- phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
- if (ret_val)
- return ret_val;
-
- if (hw->phy_revision < M88E1011_I_REV_4) {
- /* Force TX_CLK in the Extended PHY Specific Control Register
- * to 25MHz clock.
- */
- ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data |= M88E1000_EPSCR_TX_CLK_25;
-
- if ((hw->phy_revision == E1000_REVISION_2) &&
- (hw->phy_id == M88E1111_I_PHY_ID)) {
- /* Vidalia Phy, set the downshift counter to 5x */
- phy_data &= ~(M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK);
- phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X;
- ret_val = e1000_write_phy_reg(hw,
- M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
- if (ret_val)
- return ret_val;
- } else {
- /* Configure Master and Slave downshift values */
- phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
- M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
- phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
- M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
- ret_val = e1000_write_phy_reg(hw,
- M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
- if (ret_val)
- return ret_val;
- }
- }
-
- /* SW Reset the PHY so all changes take effect */
- ret_val = e1000_phy_reset(hw);
- if (ret_val) {
- DEBUGOUT("Error Resetting the PHY\n");
- return ret_val;
- }
-
- return E1000_SUCCESS;
-}
+ /* Call a subroutine to configure the link and setup flow control. */
+ ret_val = e1000_setup_link(hw);
-/********************************************************************
-* Setup auto-negotiation and flow control advertisements,
-* and then perform auto-negotiation.
-*
-* hw - Struct containing variables accessed by shared code
-*********************************************************************/
-static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
-{
- s32 ret_val;
- u16 phy_data;
-
- DEBUGFUNC("e1000_copper_link_autoneg");
-
- /* Perform some bounds checking on the hw->autoneg_advertised
- * parameter. If this variable is zero, then set it to the default.
- */
- hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
-
- /* If autoneg_advertised is zero, we assume it was not defaulted
- * by the calling code so we set to advertise full capability.
- */
- if (hw->autoneg_advertised == 0)
- hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
-
- /* IFE phy only supports 10/100 */
- if (hw->phy_type == e1000_phy_ife)
- hw->autoneg_advertised &= AUTONEG_ADVERTISE_10_100_ALL;
-
- DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
- ret_val = e1000_phy_setup_autoneg(hw);
- if (ret_val) {
- DEBUGOUT("Error Setting up Auto-Negotiation\n");
- return ret_val;
- }
- DEBUGOUT("Restarting Auto-Neg\n");
-
- /* Restart auto-negotiation by setting the Auto Neg Enable bit and
- * the Auto Neg Restart bit in the PHY control register.
- */
- ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
- ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
- if (ret_val)
- return ret_val;
-
- /* Does the user want to wait for Auto-Neg to complete here, or
- * check at a later time (for example, callback routine).
- */
- if (hw->wait_autoneg_complete) {
- ret_val = e1000_wait_autoneg(hw);
- if (ret_val) {
- DEBUGOUT("Error while waiting for autoneg to complete\n");
- return ret_val;
- }
- }
-
- hw->get_link_status = true;
-
- return E1000_SUCCESS;
-}
+ /* Set the transmit descriptor write-back policy */
+ if (hw->mac_type > e1000_82544) {
+ ctrl = er32(TXDCTL);
+ ctrl =
+ (ctrl & ~E1000_TXDCTL_WTHRESH) |
+ E1000_TXDCTL_FULL_TX_DESC_WB;
+ ew32(TXDCTL, ctrl);
+ }
-/******************************************************************************
-* Config the MAC and the PHY after link is up.
-* 1) Set up the MAC to the current PHY speed/duplex
-* if we are on 82543. If we
-* are on newer silicon, we only need to configure
-* collision distance in the Transmit Control Register.
-* 2) Set up flow control on the MAC to that established with
-* the link partner.
-* 3) Config DSP to improve Gigabit link quality for some PHY revisions.
-*
-* hw - Struct containing variables accessed by shared code
-******************************************************************************/
-static s32 e1000_copper_link_postconfig(struct e1000_hw *hw)
-{
- s32 ret_val;
- DEBUGFUNC("e1000_copper_link_postconfig");
-
- if (hw->mac_type >= e1000_82544) {
- e1000_config_collision_dist(hw);
- } else {
- ret_val = e1000_config_mac_to_phy(hw);
- if (ret_val) {
- DEBUGOUT("Error configuring MAC to PHY settings\n");
- return ret_val;
- }
- }
- ret_val = e1000_config_fc_after_link_up(hw);
- if (ret_val) {
- DEBUGOUT("Error Configuring Flow Control\n");
- return ret_val;
- }
-
- /* Config DSP to improve Giga link quality */
- if (hw->phy_type == e1000_phy_igp) {
- ret_val = e1000_config_dsp_after_link_change(hw, true);
- if (ret_val) {
- DEBUGOUT("Error Configuring DSP after link up\n");
- return ret_val;
- }
- }
-
- return E1000_SUCCESS;
-}
+ /* Clear all of the statistics registers (clear on read). It is
+ * important that we do this after we have tried to establish link
+ * because the symbol error count will increment wildly if there
+ * is no link.
+ */
+ e1000_clear_hw_cntrs(hw);
+
+ if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
+ hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
+ ctrl_ext = er32(CTRL_EXT);
+ /* Relaxed ordering must be disabled to avoid a parity
+ * error crash in a PCI slot. */
+ ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
+ ew32(CTRL_EXT, ctrl_ext);
+ }
-/******************************************************************************
-* Detects which PHY is present and setup the speed and duplex
-*
-* hw - Struct containing variables accessed by shared code
-******************************************************************************/
-static s32 e1000_setup_copper_link(struct e1000_hw *hw)
-{
- s32 ret_val;
- u16 i;
- u16 phy_data;
- u16 reg_data = 0;
-
- DEBUGFUNC("e1000_setup_copper_link");
-
- switch (hw->mac_type) {
- case e1000_80003es2lan:
- case e1000_ich8lan:
- /* Set the mac to wait the maximum time between each
- * iteration and increase the max iterations when
- * polling the phy; this fixes erroneous timeouts at 10Mbps. */
- ret_val = e1000_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF);
- if (ret_val)
- return ret_val;
- ret_val = e1000_read_kmrn_reg(hw, GG82563_REG(0x34, 9), ®_data);
- if (ret_val)
- return ret_val;
- reg_data |= 0x3F;
- ret_val = e1000_write_kmrn_reg(hw, GG82563_REG(0x34, 9), reg_data);
- if (ret_val)
- return ret_val;
- default:
- break;
- }
-
- /* Check if it is a valid PHY and set PHY mode if necessary. */
- ret_val = e1000_copper_link_preconfig(hw);
- if (ret_val)
- return ret_val;
-
- switch (hw->mac_type) {
- case e1000_80003es2lan:
- /* Kumeran registers are written-only */
- reg_data = E1000_KUMCTRLSTA_INB_CTRL_LINK_STATUS_TX_TIMEOUT_DEFAULT;
- reg_data |= E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING;
- ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL,
- reg_data);
- if (ret_val)
- return ret_val;
- break;
- default:
- break;
- }
-
- if (hw->phy_type == e1000_phy_igp ||
- hw->phy_type == e1000_phy_igp_3 ||
- hw->phy_type == e1000_phy_igp_2) {
- ret_val = e1000_copper_link_igp_setup(hw);
- if (ret_val)
- return ret_val;
- } else if (hw->phy_type == e1000_phy_m88) {
- ret_val = e1000_copper_link_mgp_setup(hw);
- if (ret_val)
- return ret_val;
- } else if (hw->phy_type == e1000_phy_gg82563) {
- ret_val = e1000_copper_link_ggp_setup(hw);
- if (ret_val)
- return ret_val;
- }
-
- if (hw->autoneg) {
- /* Setup autoneg and flow control advertisement
- * and perform autonegotiation */
- ret_val = e1000_copper_link_autoneg(hw);
- if (ret_val)
- return ret_val;
- } else {
- /* PHY will be set to 10H, 10F, 100H,or 100F
- * depending on value from forced_speed_duplex. */
- DEBUGOUT("Forcing speed and duplex\n");
- ret_val = e1000_phy_force_speed_duplex(hw);
- if (ret_val) {
- DEBUGOUT("Error Forcing Speed and Duplex\n");
- return ret_val;
- }
- }
-
- /* Check link status. Wait up to 100 microseconds for link to become
- * valid.
- */
- for (i = 0; i < 10; i++) {
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
- if (ret_val)
- return ret_val;
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
- if (ret_val)
- return ret_val;
-
- if (phy_data & MII_SR_LINK_STATUS) {
- /* Config the MAC and PHY after link is up */
- ret_val = e1000_copper_link_postconfig(hw);
- if (ret_val)
- return ret_val;
-
- DEBUGOUT("Valid link established!!!\n");
- return E1000_SUCCESS;
- }
- udelay(10);
- }
-
- DEBUGOUT("Unable to establish link!!!\n");
- return E1000_SUCCESS;
+ return ret_val;
}
-/******************************************************************************
-* Configure the MAC-to-PHY interface for 10/100Mbps
-*
-* hw - Struct containing variables accessed by shared code
-******************************************************************************/
-static s32 e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, u16 duplex)
+/**
+ * e1000_adjust_serdes_amplitude - Adjust SERDES output amplitude based on EEPROM setting.
+ * @hw: Struct containing variables accessed by shared code.
+ */
+static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
- u32 tipg;
- u16 reg_data;
-
- DEBUGFUNC("e1000_configure_kmrn_for_10_100");
+ u16 eeprom_data;
+ s32 ret_val;
- reg_data = E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT;
- ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_HD_CTRL,
- reg_data);
- if (ret_val)
- return ret_val;
+ DEBUGFUNC("e1000_adjust_serdes_amplitude");
- /* Configure Transmit Inter-Packet Gap */
- tipg = er32(TIPG);
- tipg &= ~E1000_TIPG_IPGT_MASK;
- tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_10_100;
- ew32(TIPG, tipg);
+ if (hw->media_type != e1000_media_type_internal_serdes)
+ return E1000_SUCCESS;
- ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data);
-
- if (ret_val)
- return ret_val;
+ switch (hw->mac_type) {
+ case e1000_82545_rev_3:
+ case e1000_82546_rev_3:
+ break;
+ default:
+ return E1000_SUCCESS;
+ }
- if (duplex == HALF_DUPLEX)
- reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
- else
- reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+ ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1,
+ &eeprom_data);
+ if (ret_val) {
+ return ret_val;
+ }
- ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
+ if (eeprom_data != EEPROM_RESERVED_WORD) {
+ /* Adjust SERDES output amplitude only. */
+ eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK;
+ ret_val =
+ e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data);
+ if (ret_val)
+ return ret_val;
+ }
- return ret_val;
+ return E1000_SUCCESS;
}
-static s32 e1000_configure_kmrn_for_1000(struct e1000_hw *hw)
+/**
+ * e1000_setup_link - Configures flow control and link settings.
+ * @hw: Struct containing variables accessed by shared code
+ *
+ * Determines which flow control settings to use. Calls the appropriate media-
+ * specific link configuration function. Configures the flow control settings.
+ * Assuming the adapter has a valid link partner, a valid link should be
+ * established. Assumes the hardware has previously been reset and the
+ * transmitter and receiver are not enabled.
+ */
+s32 e1000_setup_link(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
- u16 reg_data;
- u32 tipg;
+ u32 ctrl_ext;
+ s32 ret_val;
+ u16 eeprom_data;
- DEBUGFUNC("e1000_configure_kmrn_for_1000");
+ DEBUGFUNC("e1000_setup_link");
- reg_data = E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT;
- ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_HD_CTRL,
- reg_data);
- if (ret_val)
- return ret_val;
+ /* Read and store word 0x0F of the EEPROM. This word contains bits
+ * that determine the hardware's default PAUSE (flow control) mode,
+ * a bit that determines whether the HW defaults to enabling or
+ * disabling auto-negotiation, and the direction of the
+ * SW defined pins. If there is no SW over-ride of the flow
+ * control setting, then the variable hw->fc will
+ * be initialized based on a value in the EEPROM.
+ */
+ if (hw->fc == E1000_FC_DEFAULT) {
+ ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
+ 1, &eeprom_data);
+ if (ret_val) {
+ DEBUGOUT("EEPROM Read Error\n");
+ return -E1000_ERR_EEPROM;
+ }
+ if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
+ hw->fc = E1000_FC_NONE;
+ else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
+ EEPROM_WORD0F_ASM_DIR)
+ hw->fc = E1000_FC_TX_PAUSE;
+ else
+ hw->fc = E1000_FC_FULL;
+ }
- /* Configure Transmit Inter-Packet Gap */
- tipg = er32(TIPG);
- tipg &= ~E1000_TIPG_IPGT_MASK;
- tipg |= DEFAULT_80003ES2LAN_TIPG_IPGT_1000;
- ew32(TIPG, tipg);
+ /* We want to save off the original Flow Control configuration just
+ * in case we get disconnected and then reconnected into a different
+ * hub or switch with different Flow Control capabilities.
+ */
+ if (hw->mac_type == e1000_82542_rev2_0)
+ hw->fc &= (~E1000_FC_TX_PAUSE);
- ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data);
+ if ((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1))
+ hw->fc &= (~E1000_FC_RX_PAUSE);
- if (ret_val)
- return ret_val;
+ hw->original_fc = hw->fc;
- reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
- ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
+ DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc);
- return ret_val;
-}
+ /* Take the 4 bits from EEPROM word 0x0F that determine the initial
+ * polarity value for the SW controlled pins, and setup the
+ * Extended Device Control reg with that info.
+ * This is needed because one of the SW controlled pins is used for
+ * signal detection. So this should be done before e1000_setup_pcs_link()
+ * or e1000_phy_setup() is called.
+ */
+ if (hw->mac_type == e1000_82543) {
+ ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
+ 1, &eeprom_data);
+ if (ret_val) {
+ DEBUGOUT("EEPROM Read Error\n");
+ return -E1000_ERR_EEPROM;
+ }
+ ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) <<
+ SWDPIO__EXT_SHIFT);
+ ew32(CTRL_EXT, ctrl_ext);
+ }
-/******************************************************************************
-* Configures PHY autoneg and flow control advertisement settings
-*
-* hw - Struct containing variables accessed by shared code
-******************************************************************************/
-s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
-{
- s32 ret_val;
- u16 mii_autoneg_adv_reg;
- u16 mii_1000t_ctrl_reg;
-
- DEBUGFUNC("e1000_phy_setup_autoneg");
-
- /* Read the MII Auto-Neg Advertisement Register (Address 4). */
- ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
- if (ret_val)
- return ret_val;
-
- if (hw->phy_type != e1000_phy_ife) {
- /* Read the MII 1000Base-T Control Register (Address 9). */
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
- if (ret_val)
- return ret_val;
- } else
- mii_1000t_ctrl_reg=0;
-
- /* Need to parse both autoneg_advertised and fc and set up
- * the appropriate PHY registers. First we will parse for
- * autoneg_advertised software override. Since we can advertise
- * a plethora of combinations, we need to check each bit
- * individually.
- */
-
- /* First we clear all the 10/100 mb speed bits in the Auto-Neg
- * Advertisement Register (Address 4) and the 1000 mb speed bits in
- * the 1000Base-T Control Register (Address 9).
- */
- mii_autoneg_adv_reg &= ~REG4_SPEED_MASK;
- mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
-
- DEBUGOUT1("autoneg_advertised %x\n", hw->autoneg_advertised);
-
- /* Do we want to advertise 10 Mb Half Duplex? */
- if (hw->autoneg_advertised & ADVERTISE_10_HALF) {
- DEBUGOUT("Advertise 10mb Half duplex\n");
- mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
- }
-
- /* Do we want to advertise 10 Mb Full Duplex? */
- if (hw->autoneg_advertised & ADVERTISE_10_FULL) {
- DEBUGOUT("Advertise 10mb Full duplex\n");
- mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
- }
-
- /* Do we want to advertise 100 Mb Half Duplex? */
- if (hw->autoneg_advertised & ADVERTISE_100_HALF) {
- DEBUGOUT("Advertise 100mb Half duplex\n");
- mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
- }
-
- /* Do we want to advertise 100 Mb Full Duplex? */
- if (hw->autoneg_advertised & ADVERTISE_100_FULL) {
- DEBUGOUT("Advertise 100mb Full duplex\n");
- mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
- }
-
- /* We do not allow the Phy to advertise 1000 Mb Half Duplex */
- if (hw->autoneg_advertised & ADVERTISE_1000_HALF) {
- DEBUGOUT("Advertise 1000mb Half duplex requested, request denied!\n");
- }
-
- /* Do we want to advertise 1000 Mb Full Duplex? */
- if (hw->autoneg_advertised & ADVERTISE_1000_FULL) {
- DEBUGOUT("Advertise 1000mb Full duplex\n");
- mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
- if (hw->phy_type == e1000_phy_ife) {
- DEBUGOUT("e1000_phy_ife is a 10/100 PHY. Gigabit speed is not supported.\n");
- }
- }
-
- /* Check for a software override of the flow control settings, and
- * setup the PHY advertisement registers accordingly. If
- * auto-negotiation is enabled, then software will have to set the
- * "PAUSE" bits to the correct value in the Auto-Negotiation
- * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-negotiation.
- *
- * The possible values of the "fc" parameter are:
- * 0: Flow control is completely disabled
- * 1: Rx flow control is enabled (we can receive pause frames
- * but not send pause frames).
- * 2: Tx flow control is enabled (we can send pause frames
- * but we do not support receiving pause frames).
- * 3: Both Rx and TX flow control (symmetric) are enabled.
- * other: No software override. The flow control configuration
- * in the EEPROM is used.
- */
- switch (hw->fc) {
- case E1000_FC_NONE: /* 0 */
- /* Flow control (RX & TX) is completely disabled by a
- * software over-ride.
- */
- mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
- break;
- case E1000_FC_RX_PAUSE: /* 1 */
- /* RX Flow control is enabled, and TX Flow control is
- * disabled, by a software over-ride.
- */
- /* Since there really isn't a way to advertise that we are
- * capable of RX Pause ONLY, we will advertise that we
- * support both symmetric and asymmetric RX PAUSE. Later
- * (in e1000_config_fc_after_link_up) we will disable the
- *hw's ability to send PAUSE frames.
- */
- mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
- break;
- case E1000_FC_TX_PAUSE: /* 2 */
- /* TX Flow control is enabled, and RX Flow control is
- * disabled, by a software over-ride.
- */
- mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
- mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
- break;
- case E1000_FC_FULL: /* 3 */
- /* Flow control (both RX and TX) is enabled by a software
- * over-ride.
- */
- mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
- break;
- default:
- DEBUGOUT("Flow control param set incorrectly\n");
- return -E1000_ERR_CONFIG;
- }
-
- ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
- if (ret_val)
- return ret_val;
-
- DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
-
- if (hw->phy_type != e1000_phy_ife) {
- ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
- if (ret_val)
- return ret_val;
- }
-
- return E1000_SUCCESS;
-}
+ /* Call the necessary subroutine to configure the link. */
+ ret_val = (hw->media_type == e1000_media_type_copper) ?
+ e1000_setup_copper_link(hw) : e1000_setup_fiber_serdes_link(hw);
-/******************************************************************************
-* Force PHY speed and duplex settings to hw->forced_speed_duplex
-*
-* hw - Struct containing variables accessed by shared code
-******************************************************************************/
-static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
-{
- u32 ctrl;
- s32 ret_val;
- u16 mii_ctrl_reg;
- u16 mii_status_reg;
- u16 phy_data;
- u16 i;
-
- DEBUGFUNC("e1000_phy_force_speed_duplex");
-
- /* Turn off Flow control if we are forcing speed and duplex. */
- hw->fc = E1000_FC_NONE;
-
- DEBUGOUT1("hw->fc = %d\n", hw->fc);
-
- /* Read the Device Control Register. */
- ctrl = er32(CTRL);
-
- /* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */
- ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
- ctrl &= ~(DEVICE_SPEED_MASK);
-
- /* Clear the Auto Speed Detect Enable bit. */
- ctrl &= ~E1000_CTRL_ASDE;
-
- /* Read the MII Control Register. */
- ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg);
- if (ret_val)
- return ret_val;
-
- /* We need to disable autoneg in order to force link and duplex. */
-
- mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN;
-
- /* Are we forcing Full or Half Duplex? */
- if (hw->forced_speed_duplex == e1000_100_full ||
- hw->forced_speed_duplex == e1000_10_full) {
- /* We want to force full duplex so we SET the full duplex bits in the
- * Device and MII Control Registers.
- */
- ctrl |= E1000_CTRL_FD;
- mii_ctrl_reg |= MII_CR_FULL_DUPLEX;
- DEBUGOUT("Full Duplex\n");
- } else {
- /* We want to force half duplex so we CLEAR the full duplex bits in
- * the Device and MII Control Registers.
- */
- ctrl &= ~E1000_CTRL_FD;
- mii_ctrl_reg &= ~MII_CR_FULL_DUPLEX;
- DEBUGOUT("Half Duplex\n");
- }
-
- /* Are we forcing 100Mbps??? */
- if (hw->forced_speed_duplex == e1000_100_full ||
- hw->forced_speed_duplex == e1000_100_half) {
- /* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */
- ctrl |= E1000_CTRL_SPD_100;
- mii_ctrl_reg |= MII_CR_SPEED_100;
- mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10);
- DEBUGOUT("Forcing 100mb ");
- } else {
- /* Set the 10Mb bit and turn off the 1000Mb and 100Mb bits. */
- ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
- mii_ctrl_reg |= MII_CR_SPEED_10;
- mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
- DEBUGOUT("Forcing 10mb ");
- }
-
- e1000_config_collision_dist(hw);
-
- /* Write the configured values back to the Device Control Reg. */
- ew32(CTRL, ctrl);
-
- if ((hw->phy_type == e1000_phy_m88) ||
- (hw->phy_type == e1000_phy_gg82563)) {
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
- if (ret_val)
- return ret_val;
-
- /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
- * forced whenever speed are duplex are forced.
- */
- phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
- if (ret_val)
- return ret_val;
-
- DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data);
-
- /* Need to reset the PHY or these changes will be ignored */
- mii_ctrl_reg |= MII_CR_RESET;
-
- /* Disable MDI-X support for 10/100 */
- } else if (hw->phy_type == e1000_phy_ife) {
- ret_val = e1000_read_phy_reg(hw, IFE_PHY_MDIX_CONTROL, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data &= ~IFE_PMC_AUTO_MDIX;
- phy_data &= ~IFE_PMC_FORCE_MDIX;
-
- ret_val = e1000_write_phy_reg(hw, IFE_PHY_MDIX_CONTROL, phy_data);
- if (ret_val)
- return ret_val;
-
- } else {
- /* Clear Auto-Crossover to force MDI manually. IGP requires MDI
- * forced whenever speed or duplex are forced.
- */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
- phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
-
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
- if (ret_val)
- return ret_val;
- }
-
- /* Write back the modified PHY MII control register. */
- ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg);
- if (ret_val)
- return ret_val;
-
- udelay(1);
-
- /* The wait_autoneg_complete flag may be a little misleading here.
- * Since we are forcing speed and duplex, Auto-Neg is not enabled.
- * But we do want to delay for a period while forcing only so we
- * don't generate false No Link messages. So we will wait here
- * only if the user has set wait_autoneg_complete to 1, which is
- * the default.
- */
- if (hw->wait_autoneg_complete) {
- /* We will wait for autoneg to complete. */
- DEBUGOUT("Waiting for forced speed/duplex link.\n");
- mii_status_reg = 0;
-
- /* We will wait for autoneg to complete or 4.5 seconds to expire. */
- for (i = PHY_FORCE_TIME; i > 0; i--) {
- /* Read the MII Status Register and wait for Auto-Neg Complete bit
- * to be set.
- */
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
- if (ret_val)
- return ret_val;
-
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
- if (ret_val)
- return ret_val;
-
- if (mii_status_reg & MII_SR_LINK_STATUS) break;
- msleep(100);
- }
- if ((i == 0) &&
- ((hw->phy_type == e1000_phy_m88) ||
- (hw->phy_type == e1000_phy_gg82563))) {
- /* We didn't get link. Reset the DSP and wait again for link. */
- ret_val = e1000_phy_reset_dsp(hw);
- if (ret_val) {
- DEBUGOUT("Error Resetting PHY DSP\n");
- return ret_val;
- }
- }
- /* This loop will early-out if the link condition has been met. */
- for (i = PHY_FORCE_TIME; i > 0; i--) {
- if (mii_status_reg & MII_SR_LINK_STATUS) break;
- msleep(100);
- /* Read the MII Status Register and wait for Auto-Neg Complete bit
- * to be set.
- */
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
- if (ret_val)
- return ret_val;
-
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
- if (ret_val)
- return ret_val;
- }
- }
-
- if (hw->phy_type == e1000_phy_m88) {
- /* Because we reset the PHY above, we need to re-force TX_CLK in the
- * Extended PHY Specific Control Register to 25MHz clock. This value
- * defaults back to a 2.5MHz clock when the PHY is reset.
- */
- ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data |= M88E1000_EPSCR_TX_CLK_25;
- ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
- if (ret_val)
- return ret_val;
-
- /* In addition, because of the s/w reset above, we need to enable CRS on
- * TX. This must be set for both full and half duplex operation.
- */
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
- if (ret_val)
- return ret_val;
-
- if ((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) &&
- (!hw->autoneg) && (hw->forced_speed_duplex == e1000_10_full ||
- hw->forced_speed_duplex == e1000_10_half)) {
- ret_val = e1000_polarity_reversal_workaround(hw);
- if (ret_val)
- return ret_val;
- }
- } else if (hw->phy_type == e1000_phy_gg82563) {
- /* The TX_CLK of the Extended PHY Specific Control Register defaults
- * to 2.5MHz on a reset. We need to re-force it back to 25MHz, if
- * we're not in a forced 10/duplex configuration. */
- ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
- if ((hw->forced_speed_duplex == e1000_10_full) ||
- (hw->forced_speed_duplex == e1000_10_half))
- phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ;
- else
- phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25MHZ;
-
- /* Also due to the reset, we need to enable CRS on Tx. */
- phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
-
- ret_val = e1000_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data);
- if (ret_val)
- return ret_val;
- }
- return E1000_SUCCESS;
+ /* Initialize the flow control address, type, and PAUSE timer
+ * registers to their default values. This is done even if flow
+ * control is disabled, because it does not hurt anything to
+ * initialize these registers.
+ */
+ DEBUGOUT
+ ("Initializing the Flow Control address, type and timer regs\n");
+
+ ew32(FCT, FLOW_CONTROL_TYPE);
+ ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
+ ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
+
+ ew32(FCTTV, hw->fc_pause_time);
+
+ /* Set the flow control receive threshold registers. Normally,
+ * these registers will be set to a default threshold that may be
+ * adjusted later by the driver's runtime code. However, if the
+ * ability to transmit pause frames in not enabled, then these
+ * registers will be set to 0.
+ */
+ if (!(hw->fc & E1000_FC_TX_PAUSE)) {
+ ew32(FCRTL, 0);
+ ew32(FCRTH, 0);
+ } else {
+ /* We need to set up the Receive Threshold high and low water marks
+ * as well as (optionally) enabling the transmission of XON frames.
+ */
+ if (hw->fc_send_xon) {
+ ew32(FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
+ ew32(FCRTH, hw->fc_high_water);
+ } else {
+ ew32(FCRTL, hw->fc_low_water);
+ ew32(FCRTH, hw->fc_high_water);
+ }
+ }
+ return ret_val;
}
-/******************************************************************************
-* Sets the collision distance in the Transmit Control register
-*
-* hw - Struct containing variables accessed by shared code
-*
-* Link should have been established previously. Reads the speed and duplex
-* information from the Device Status register.
-******************************************************************************/
-void e1000_config_collision_dist(struct e1000_hw *hw)
+/**
+ * e1000_setup_fiber_serdes_link - prepare fiber or serdes link
+ * @hw: Struct containing variables accessed by shared code
+ *
+ * Manipulates Physical Coding Sublayer functions in order to configure
+ * link. Assumes the hardware has been previously reset and the transmitter
+ * and receiver are not enabled.
+ */
+static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
{
- u32 tctl, coll_dist;
+ u32 ctrl;
+ u32 status;
+ u32 txcw = 0;
+ u32 i;
+ u32 signal = 0;
+ s32 ret_val;
- DEBUGFUNC("e1000_config_collision_dist");
+ DEBUGFUNC("e1000_setup_fiber_serdes_link");
- if (hw->mac_type < e1000_82543)
- coll_dist = E1000_COLLISION_DISTANCE_82542;
- else
- coll_dist = E1000_COLLISION_DISTANCE;
+ /* On adapters with a MAC newer than 82544, SWDP 1 will be
+ * set when the optics detect a signal. On older adapters, it will be
+ * cleared when there is a signal. This applies to fiber media only.
+ * If we're on serdes media, adjust the output amplitude to value
+ * set in the EEPROM.
+ */
+ ctrl = er32(CTRL);
+ if (hw->media_type == e1000_media_type_fiber)
+ signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
+
+ ret_val = e1000_adjust_serdes_amplitude(hw);
+ if (ret_val)
+ return ret_val;
+
+ /* Take the link out of reset */
+ ctrl &= ~(E1000_CTRL_LRST);
+
+ /* Adjust VCO speed to improve BER performance */
+ ret_val = e1000_set_vco_speed(hw);
+ if (ret_val)
+ return ret_val;
+
+ e1000_config_collision_dist(hw);
+
+ /* Check for a software override of the flow control settings, and setup
+ * the device accordingly. If auto-negotiation is enabled, then software
+ * will have to set the "PAUSE" bits to the correct value in the Tranmsit
+ * Config Word Register (TXCW) and re-start auto-negotiation. However, if
+ * auto-negotiation is disabled, then software will have to manually
+ * configure the two flow control enable bits in the CTRL register.
+ *
+ * The possible values of the "fc" parameter are:
+ * 0: Flow control is completely disabled
+ * 1: Rx flow control is enabled (we can receive pause frames, but
+ * not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames but we do
+ * not support receiving pause frames).
+ * 3: Both Rx and TX flow control (symmetric) are enabled.
+ */
+ switch (hw->fc) {
+ case E1000_FC_NONE:
+ /* Flow control is completely disabled by a software over-ride. */
+ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
+ break;
+ case E1000_FC_RX_PAUSE:
+ /* RX Flow control is enabled and TX Flow control is disabled by a
+ * software over-ride. Since there really isn't a way to advertise
+ * that we are capable of RX Pause ONLY, we will advertise that we
+ * support both symmetric and asymmetric RX PAUSE. Later, we will
+ * disable the adapter's ability to send PAUSE frames.
+ */
+ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+ break;
+ case E1000_FC_TX_PAUSE:
+ /* TX Flow control is enabled, and RX Flow control is disabled, by a
+ * software over-ride.
+ */
+ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
+ break;
+ case E1000_FC_FULL:
+ /* Flow control (both RX and TX) is enabled by a software over-ride. */
+ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
+ break;
+ default:
+ DEBUGOUT("Flow control param set incorrectly\n");
+ return -E1000_ERR_CONFIG;
+ break;
+ }
+
+ /* Since auto-negotiation is enabled, take the link out of reset (the link
+ * will be in reset, because we previously reset the chip). This will
+ * restart auto-negotiation. If auto-negotiation is successful then the
+ * link-up status bit will be set and the flow control enable bits (RFCE
+ * and TFCE) will be set according to their negotiated value.
+ */
+ DEBUGOUT("Auto-negotiation enabled\n");
- tctl = er32(TCTL);
+ ew32(TXCW, txcw);
+ ew32(CTRL, ctrl);
+ E1000_WRITE_FLUSH();
- tctl &= ~E1000_TCTL_COLD;
- tctl |= coll_dist << E1000_COLD_SHIFT;
+ hw->txcw = txcw;
+ msleep(1);
- ew32(TCTL, tctl);
- E1000_WRITE_FLUSH();
+ /* If we have a signal (the cable is plugged in) then poll for a "Link-Up"
+ * indication in the Device Status Register. Time-out if a link isn't
+ * seen in 500 milliseconds seconds (Auto-negotiation should complete in
+ * less than 500 milliseconds even if the other end is doing it in SW).
+ * For internal serdes, we just assume a signal is present, then poll.
+ */
+ if (hw->media_type == e1000_media_type_internal_serdes ||
+ (er32(CTRL) & E1000_CTRL_SWDPIN1) == signal) {
+ DEBUGOUT("Looking for Link\n");
+ for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
+ msleep(10);
+ status = er32(STATUS);
+ if (status & E1000_STATUS_LU)
+ break;
+ }
+ if (i == (LINK_UP_TIMEOUT / 10)) {
+ DEBUGOUT("Never got a valid link from auto-neg!!!\n");
+ hw->autoneg_failed = 1;
+ /* AutoNeg failed to achieve a link, so we'll call
+ * e1000_check_for_link. This routine will force the link up if
+ * we detect a signal. This will allow us to communicate with
+ * non-autonegotiating link partners.
+ */
+ ret_val = e1000_check_for_link(hw);
+ if (ret_val) {
+ DEBUGOUT("Error while checking for link\n");
+ return ret_val;
+ }
+ hw->autoneg_failed = 0;
+ } else {
+ hw->autoneg_failed = 0;
+ DEBUGOUT("Valid Link Found\n");
+ }
+ } else {
+ DEBUGOUT("No Signal Detected\n");
+ }
+ return E1000_SUCCESS;
}
-/******************************************************************************
-* Sets MAC speed and duplex settings to reflect the those in the PHY
-*
-* hw - Struct containing variables accessed by shared code
-* mii_reg - data to write to the MII control register
-*
-* The contents of the PHY register containing the needed information need to
-* be passed in.
-******************************************************************************/
-static s32 e1000_config_mac_to_phy(struct e1000_hw *hw)
-{
- u32 ctrl;
- s32 ret_val;
- u16 phy_data;
-
- DEBUGFUNC("e1000_config_mac_to_phy");
-
- /* 82544 or newer MAC, Auto Speed Detection takes care of
- * MAC speed/duplex configuration.*/
- if (hw->mac_type >= e1000_82544)
- return E1000_SUCCESS;
-
- /* Read the Device Control Register and set the bits to Force Speed
- * and Duplex.
- */
- ctrl = er32(CTRL);
- ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
- ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
-
- /* Set up duplex in the Device Control and Transmit Control
- * registers depending on negotiated values.
- */
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
- if (ret_val)
- return ret_val;
-
- if (phy_data & M88E1000_PSSR_DPLX)
- ctrl |= E1000_CTRL_FD;
- else
- ctrl &= ~E1000_CTRL_FD;
-
- e1000_config_collision_dist(hw);
-
- /* Set up speed in the Device Control register depending on
- * negotiated values.
- */
- if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
- ctrl |= E1000_CTRL_SPD_1000;
- else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
- ctrl |= E1000_CTRL_SPD_100;
-
- /* Write the configured values back to the Device Control Reg. */
- ew32(CTRL, ctrl);
- return E1000_SUCCESS;
-}
-
-/******************************************************************************
- * Forces the MAC's flow control settings.
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Sets the TFCE and RFCE bits in the device control register to reflect
- * the adapter settings. TFCE and RFCE need to be explicitly set by
- * software when a Copper PHY is used because autonegotiation is managed
- * by the PHY rather than the MAC. Software must also configure these
- * bits when link is forced on a fiber connection.
- *****************************************************************************/
-s32 e1000_force_mac_fc(struct e1000_hw *hw)
-{
- u32 ctrl;
-
- DEBUGFUNC("e1000_force_mac_fc");
-
- /* Get the current configuration of the Device Control Register */
- ctrl = er32(CTRL);
-
- /* Because we didn't get link via the internal auto-negotiation
- * mechanism (we either forced link or we got link via PHY
- * auto-neg), we have to manually enable/disable transmit an
- * receive flow control.
- *
- * The "Case" statement below enables/disable flow control
- * according to the "hw->fc" parameter.
- *
- * The possible values of the "fc" parameter are:
- * 0: Flow control is completely disabled
- * 1: Rx flow control is enabled (we can receive pause
- * frames but not send pause frames).
- * 2: Tx flow control is enabled (we can send pause frames
- * frames but we do not receive pause frames).
- * 3: Both Rx and TX flow control (symmetric) is enabled.
- * other: No other values should be possible at this point.
- */
-
- switch (hw->fc) {
- case E1000_FC_NONE:
- ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
- break;
- case E1000_FC_RX_PAUSE:
- ctrl &= (~E1000_CTRL_TFCE);
- ctrl |= E1000_CTRL_RFCE;
- break;
- case E1000_FC_TX_PAUSE:
- ctrl &= (~E1000_CTRL_RFCE);
- ctrl |= E1000_CTRL_TFCE;
- break;
- case E1000_FC_FULL:
- ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
- break;
- default:
- DEBUGOUT("Flow control param set incorrectly\n");
- return -E1000_ERR_CONFIG;
- }
-
- /* Disable TX Flow Control for 82542 (rev 2.0) */
- if (hw->mac_type == e1000_82542_rev2_0)
- ctrl &= (~E1000_CTRL_TFCE);
-
- ew32(CTRL, ctrl);
- return E1000_SUCCESS;
-}
-
-/******************************************************************************
- * Configures flow control settings after link is established
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Should be called immediately after a valid link has been established.
- * Forces MAC flow control settings if link was forced. When in MII/GMII mode
- * and autonegotiation is enabled, the MAC flow control settings will be set
- * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
- * and RFCE bits will be automaticaly set to the negotiated flow control mode.
- *****************************************************************************/
-static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw)
-{
- s32 ret_val;
- u16 mii_status_reg;
- u16 mii_nway_adv_reg;
- u16 mii_nway_lp_ability_reg;
- u16 speed;
- u16 duplex;
-
- DEBUGFUNC("e1000_config_fc_after_link_up");
-
- /* Check for the case where we have fiber media and auto-neg failed
- * so we had to force link. In this case, we need to force the
- * configuration of the MAC to match the "fc" parameter.
- */
- if (((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) ||
- ((hw->media_type == e1000_media_type_internal_serdes) &&
- (hw->autoneg_failed)) ||
- ((hw->media_type == e1000_media_type_copper) && (!hw->autoneg))) {
- ret_val = e1000_force_mac_fc(hw);
- if (ret_val) {
- DEBUGOUT("Error forcing flow control settings\n");
- return ret_val;
- }
- }
-
- /* Check for the case where we have copper media and auto-neg is
- * enabled. In this case, we need to check and see if Auto-Neg
- * has completed, and if so, how the PHY and link partner has
- * flow control configured.
- */
- if ((hw->media_type == e1000_media_type_copper) && hw->autoneg) {
- /* Read the MII Status Register and check to see if AutoNeg
- * has completed. We read this twice because this reg has
- * some "sticky" (latched) bits.
- */
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
- if (ret_val)
- return ret_val;
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
- if (ret_val)
- return ret_val;
-
- if (mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
- /* The AutoNeg process has completed, so we now need to
- * read both the Auto Negotiation Advertisement Register
- * (Address 4) and the Auto_Negotiation Base Page Ability
- * Register (Address 5) to determine how flow control was
- * negotiated.
- */
- ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
- &mii_nway_adv_reg);
- if (ret_val)
- return ret_val;
- ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
- &mii_nway_lp_ability_reg);
- if (ret_val)
- return ret_val;
-
- /* Two bits in the Auto Negotiation Advertisement Register
- * (Address 4) and two bits in the Auto Negotiation Base
- * Page Ability Register (Address 5) determine flow control
- * for both the PHY and the link partner. The following
- * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
- * 1999, describes these PAUSE resolution bits and how flow
- * control is determined based upon these settings.
- * NOTE: DC = Don't Care
- *
- * LOCAL DEVICE | LINK PARTNER
- * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
- *-------|---------|-------|---------|--------------------
- * 0 | 0 | DC | DC | E1000_FC_NONE
- * 0 | 1 | 0 | DC | E1000_FC_NONE
- * 0 | 1 | 1 | 0 | E1000_FC_NONE
- * 0 | 1 | 1 | 1 | E1000_FC_TX_PAUSE
- * 1 | 0 | 0 | DC | E1000_FC_NONE
- * 1 | DC | 1 | DC | E1000_FC_FULL
- * 1 | 1 | 0 | 0 | E1000_FC_NONE
- * 1 | 1 | 0 | 1 | E1000_FC_RX_PAUSE
- *
- */
- /* Are both PAUSE bits set to 1? If so, this implies
- * Symmetric Flow Control is enabled at both ends. The
- * ASM_DIR bits are irrelevant per the spec.
- *
- * For Symmetric Flow Control:
- *
- * LOCAL DEVICE | LINK PARTNER
- * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
- *-------|---------|-------|---------|--------------------
- * 1 | DC | 1 | DC | E1000_FC_FULL
- *
- */
- if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
- (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
- /* Now we need to check if the user selected RX ONLY
- * of pause frames. In this case, we had to advertise
- * FULL flow control because we could not advertise RX
- * ONLY. Hence, we must now check to see if we need to
- * turn OFF the TRANSMISSION of PAUSE frames.
- */
- if (hw->original_fc == E1000_FC_FULL) {
- hw->fc = E1000_FC_FULL;
- DEBUGOUT("Flow Control = FULL.\n");
- } else {
- hw->fc = E1000_FC_RX_PAUSE;
- DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
- }
- }
- /* For receiving PAUSE frames ONLY.
- *
- * LOCAL DEVICE | LINK PARTNER
- * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
- *-------|---------|-------|---------|--------------------
- * 0 | 1 | 1 | 1 | E1000_FC_TX_PAUSE
- *
- */
- else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
- (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
- (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
- (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
- hw->fc = E1000_FC_TX_PAUSE;
- DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
- }
- /* For transmitting PAUSE frames ONLY.
- *
- * LOCAL DEVICE | LINK PARTNER
- * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
- *-------|---------|-------|---------|--------------------
- * 1 | 1 | 0 | 1 | E1000_FC_RX_PAUSE
- *
- */
- else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
- (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
- !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
- (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
- hw->fc = E1000_FC_RX_PAUSE;
- DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
- }
- /* Per the IEEE spec, at this point flow control should be
- * disabled. However, we want to consider that we could
- * be connected to a legacy switch that doesn't advertise
- * desired flow control, but can be forced on the link
- * partner. So if we advertised no flow control, that is
- * what we will resolve to. If we advertised some kind of
- * receive capability (Rx Pause Only or Full Flow Control)
- * and the link partner advertised none, we will configure
- * ourselves to enable Rx Flow Control only. We can do
- * this safely for two reasons: If the link partner really
- * didn't want flow control enabled, and we enable Rx, no
- * harm done since we won't be receiving any PAUSE frames
- * anyway. If the intent on the link partner was to have
- * flow control enabled, then by us enabling RX only, we
- * can at least receive pause frames and process them.
- * This is a good idea because in most cases, since we are
- * predominantly a server NIC, more times than not we will
- * be asked to delay transmission of packets than asking
- * our link partner to pause transmission of frames.
- */
- else if ((hw->original_fc == E1000_FC_NONE ||
- hw->original_fc == E1000_FC_TX_PAUSE) ||
- hw->fc_strict_ieee) {
- hw->fc = E1000_FC_NONE;
- DEBUGOUT("Flow Control = NONE.\n");
- } else {
- hw->fc = E1000_FC_RX_PAUSE;
- DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
- }
-
- /* Now we need to do one last check... If we auto-
- * negotiated to HALF DUPLEX, flow control should not be
- * enabled per IEEE 802.3 spec.
- */
- ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
- if (ret_val) {
- DEBUGOUT("Error getting link speed and duplex\n");
- return ret_val;
- }
-
- if (duplex == HALF_DUPLEX)
- hw->fc = E1000_FC_NONE;
-
- /* Now we call a subroutine to actually force the MAC
- * controller to use the correct flow control settings.
- */
- ret_val = e1000_force_mac_fc(hw);
- if (ret_val) {
- DEBUGOUT("Error forcing flow control settings\n");
- return ret_val;
- }
- } else {
- DEBUGOUT("Copper PHY and Auto Neg has not completed.\n");
- }
- }
- return E1000_SUCCESS;
-}
-
-/******************************************************************************
- * Checks to see if the link status of the hardware has changed.
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Called by any function that needs to check the link status of the adapter.
- *****************************************************************************/
-s32 e1000_check_for_link(struct e1000_hw *hw)
-{
- u32 rxcw = 0;
- u32 ctrl;
- u32 status;
- u32 rctl;
- u32 icr;
- u32 signal = 0;
- s32 ret_val;
- u16 phy_data;
-
- DEBUGFUNC("e1000_check_for_link");
-
- ctrl = er32(CTRL);
- status = er32(STATUS);
-
- /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
- * set when the optics detect a signal. On older adapters, it will be
- * cleared when there is a signal. This applies to fiber media only.
- */
- if ((hw->media_type == e1000_media_type_fiber) ||
- (hw->media_type == e1000_media_type_internal_serdes)) {
- rxcw = er32(RXCW);
-
- if (hw->media_type == e1000_media_type_fiber) {
- signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
- if (status & E1000_STATUS_LU)
- hw->get_link_status = false;
- }
- }
-
- /* If we have a copper PHY then we only want to go out to the PHY
- * registers to see if Auto-Neg has completed and/or if our link
- * status has changed. The get_link_status flag will be set if we
- * receive a Link Status Change interrupt or we have Rx Sequence
- * Errors.
- */
- if ((hw->media_type == e1000_media_type_copper) && hw->get_link_status) {
- /* First we want to see if the MII Status Register reports
- * link. If so, then we want to get the current speed/duplex
- * of the PHY.
- * Read the register twice since the link bit is sticky.
- */
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
- if (ret_val)
- return ret_val;
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
- if (ret_val)
- return ret_val;
-
- if (phy_data & MII_SR_LINK_STATUS) {
- hw->get_link_status = false;
- /* Check if there was DownShift, must be checked immediately after
- * link-up */
- e1000_check_downshift(hw);
-
- /* If we are on 82544 or 82543 silicon and speed/duplex
- * are forced to 10H or 10F, then we will implement the polarity
- * reversal workaround. We disable interrupts first, and upon
- * returning, place the devices interrupt state to its previous
- * value except for the link status change interrupt which will
- * happen due to the execution of this workaround.
- */
-
- if ((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) &&
- (!hw->autoneg) &&
- (hw->forced_speed_duplex == e1000_10_full ||
- hw->forced_speed_duplex == e1000_10_half)) {
- ew32(IMC, 0xffffffff);
- ret_val = e1000_polarity_reversal_workaround(hw);
- icr = er32(ICR);
- ew32(ICS, (icr & ~E1000_ICS_LSC));
- ew32(IMS, IMS_ENABLE_MASK);
- }
-
- } else {
- /* No link detected */
- e1000_config_dsp_after_link_change(hw, false);
- return 0;
- }
-
- /* If we are forcing speed/duplex, then we simply return since
- * we have already determined whether we have link or not.
- */
- if (!hw->autoneg) return -E1000_ERR_CONFIG;
-
- /* optimize the dsp settings for the igp phy */
- e1000_config_dsp_after_link_change(hw, true);
-
- /* We have a M88E1000 PHY and Auto-Neg is enabled. If we
- * have Si on board that is 82544 or newer, Auto
- * Speed Detection takes care of MAC speed/duplex
- * configuration. So we only need to configure Collision
- * Distance in the MAC. Otherwise, we need to force
- * speed/duplex on the MAC to the current PHY speed/duplex
- * settings.
- */
- if (hw->mac_type >= e1000_82544)
- e1000_config_collision_dist(hw);
- else {
- ret_val = e1000_config_mac_to_phy(hw);
- if (ret_val) {
- DEBUGOUT("Error configuring MAC to PHY settings\n");
- return ret_val;
- }
- }
-
- /* Configure Flow Control now that Auto-Neg has completed. First, we
- * need to restore the desired flow control settings because we may
- * have had to re-autoneg with a different link partner.
- */
- ret_val = e1000_config_fc_after_link_up(hw);
- if (ret_val) {
- DEBUGOUT("Error configuring flow control\n");
- return ret_val;
- }
-
- /* At this point we know that we are on copper and we have
- * auto-negotiated link. These are conditions for checking the link
- * partner capability register. We use the link speed to determine if
- * TBI compatibility needs to be turned on or off. If the link is not
- * at gigabit speed, then TBI compatibility is not needed. If we are
- * at gigabit speed, we turn on TBI compatibility.
- */
- if (hw->tbi_compatibility_en) {
- u16 speed, duplex;
- ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
- if (ret_val) {
- DEBUGOUT("Error getting link speed and duplex\n");
- return ret_val;
- }
- if (speed != SPEED_1000) {
- /* If link speed is not set to gigabit speed, we do not need
- * to enable TBI compatibility.
- */
- if (hw->tbi_compatibility_on) {
- /* If we previously were in the mode, turn it off. */
- rctl = er32(RCTL);
- rctl &= ~E1000_RCTL_SBP;
- ew32(RCTL, rctl);
- hw->tbi_compatibility_on = false;
- }
- } else {
- /* If TBI compatibility is was previously off, turn it on. For
- * compatibility with a TBI link partner, we will store bad
- * packets. Some frames have an additional byte on the end and
- * will look like CRC errors to the hardware.
- */
- if (!hw->tbi_compatibility_on) {
- hw->tbi_compatibility_on = true;
- rctl = er32(RCTL);
- rctl |= E1000_RCTL_SBP;
- ew32(RCTL, rctl);
- }
- }
- }
- }
- /* If we don't have link (auto-negotiation failed or link partner cannot
- * auto-negotiate), the cable is plugged in (we have signal), and our
- * link partner is not trying to auto-negotiate with us (we are receiving
- * idles or data), we need to force link up. We also need to give
- * auto-negotiation time to complete, in case the cable was just plugged
- * in. The autoneg_failed flag does this.
- */
- else if ((((hw->media_type == e1000_media_type_fiber) &&
- ((ctrl & E1000_CTRL_SWDPIN1) == signal)) ||
- (hw->media_type == e1000_media_type_internal_serdes)) &&
- (!(status & E1000_STATUS_LU)) &&
- (!(rxcw & E1000_RXCW_C))) {
- if (hw->autoneg_failed == 0) {
- hw->autoneg_failed = 1;
- return 0;
- }
- DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
-
- /* Disable auto-negotiation in the TXCW register */
- ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE));
-
- /* Force link-up and also force full-duplex. */
- ctrl = er32(CTRL);
- ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
- ew32(CTRL, ctrl);
-
- /* Configure Flow Control after forcing link up. */
- ret_val = e1000_config_fc_after_link_up(hw);
- if (ret_val) {
- DEBUGOUT("Error configuring flow control\n");
- return ret_val;
- }
- }
- /* If we are forcing link and we are receiving /C/ ordered sets, re-enable
- * auto-negotiation in the TXCW register and disable forced link in the
- * Device Control register in an attempt to auto-negotiate with our link
- * partner.
- */
- else if (((hw->media_type == e1000_media_type_fiber) ||
- (hw->media_type == e1000_media_type_internal_serdes)) &&
- (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
- DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
- ew32(TXCW, hw->txcw);
- ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
-
- hw->serdes_link_down = false;
- }
- /* If we force link for non-auto-negotiation switch, check link status
- * based on MAC synchronization for internal serdes media type.
- */
- else if ((hw->media_type == e1000_media_type_internal_serdes) &&
- !(E1000_TXCW_ANE & er32(TXCW))) {
- /* SYNCH bit and IV bit are sticky. */
- udelay(10);
- if (E1000_RXCW_SYNCH & er32(RXCW)) {
- if (!(rxcw & E1000_RXCW_IV)) {
- hw->serdes_link_down = false;
- DEBUGOUT("SERDES: Link is up.\n");
- }
- } else {
- hw->serdes_link_down = true;
- DEBUGOUT("SERDES: Link is down.\n");
- }
- }
- if ((hw->media_type == e1000_media_type_internal_serdes) &&
- (E1000_TXCW_ANE & er32(TXCW))) {
- hw->serdes_link_down = !(E1000_STATUS_LU & er32(STATUS));
- }
- return E1000_SUCCESS;
-}
-
-/******************************************************************************
- * Detects the current speed and duplex settings of the hardware.
+/**
+ * e1000_copper_link_preconfig - early configuration for copper
+ * @hw: Struct containing variables accessed by shared code
*
- * hw - Struct containing variables accessed by shared code
- * speed - Speed of the connection
- * duplex - Duplex setting of the connection
- *****************************************************************************/
-s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex)
+ * Make sure we have a valid PHY and change PHY mode before link setup.
+ */
+static s32 e1000_copper_link_preconfig(struct e1000_hw *hw)
{
- u32 status;
- s32 ret_val;
- u16 phy_data;
-
- DEBUGFUNC("e1000_get_speed_and_duplex");
-
- if (hw->mac_type >= e1000_82543) {
- status = er32(STATUS);
- if (status & E1000_STATUS_SPEED_1000) {
- *speed = SPEED_1000;
- DEBUGOUT("1000 Mbs, ");
- } else if (status & E1000_STATUS_SPEED_100) {
- *speed = SPEED_100;
- DEBUGOUT("100 Mbs, ");
- } else {
- *speed = SPEED_10;
- DEBUGOUT("10 Mbs, ");
- }
-
- if (status & E1000_STATUS_FD) {
- *duplex = FULL_DUPLEX;
- DEBUGOUT("Full Duplex\n");
- } else {
- *duplex = HALF_DUPLEX;
- DEBUGOUT(" Half Duplex\n");
- }
- } else {
- DEBUGOUT("1000 Mbs, Full Duplex\n");
- *speed = SPEED_1000;
- *duplex = FULL_DUPLEX;
- }
-
- /* IGP01 PHY may advertise full duplex operation after speed downgrade even
- * if it is operating at half duplex. Here we set the duplex settings to
- * match the duplex in the link partner's capabilities.
- */
- if (hw->phy_type == e1000_phy_igp && hw->speed_downgraded) {
- ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data);
- if (ret_val)
- return ret_val;
-
- if (!(phy_data & NWAY_ER_LP_NWAY_CAPS))
- *duplex = HALF_DUPLEX;
- else {
- ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data);
- if (ret_val)
- return ret_val;
- if ((*speed == SPEED_100 && !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) ||
- (*speed == SPEED_10 && !(phy_data & NWAY_LPAR_10T_FD_CAPS)))
- *duplex = HALF_DUPLEX;
- }
- }
-
- if ((hw->mac_type == e1000_80003es2lan) &&
- (hw->media_type == e1000_media_type_copper)) {
- if (*speed == SPEED_1000)
- ret_val = e1000_configure_kmrn_for_1000(hw);
- else
- ret_val = e1000_configure_kmrn_for_10_100(hw, *duplex);
- if (ret_val)
- return ret_val;
- }
-
- if ((hw->phy_type == e1000_phy_igp_3) && (*speed == SPEED_1000)) {
- ret_val = e1000_kumeran_lock_loss_workaround(hw);
- if (ret_val)
- return ret_val;
- }
-
- return E1000_SUCCESS;
-}
+ u32 ctrl;
+ s32 ret_val;
+ u16 phy_data;
-/******************************************************************************
-* Blocks until autoneg completes or times out (~4.5 seconds)
-*
-* hw - Struct containing variables accessed by shared code
-******************************************************************************/
-static s32 e1000_wait_autoneg(struct e1000_hw *hw)
-{
- s32 ret_val;
- u16 i;
- u16 phy_data;
-
- DEBUGFUNC("e1000_wait_autoneg");
- DEBUGOUT("Waiting for Auto-Neg to complete.\n");
-
- /* We will wait for autoneg to complete or 4.5 seconds to expire. */
- for (i = PHY_AUTO_NEG_TIME; i > 0; i--) {
- /* Read the MII Status Register and wait for Auto-Neg
- * Complete bit to be set.
- */
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
- if (ret_val)
- return ret_val;
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
- if (ret_val)
- return ret_val;
- if (phy_data & MII_SR_AUTONEG_COMPLETE) {
- return E1000_SUCCESS;
- }
- msleep(100);
- }
- return E1000_SUCCESS;
-}
+ DEBUGFUNC("e1000_copper_link_preconfig");
-/******************************************************************************
-* Raises the Management Data Clock
-*
-* hw - Struct containing variables accessed by shared code
-* ctrl - Device control register's current value
-******************************************************************************/
-static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
-{
- /* Raise the clock input to the Management Data Clock (by setting the MDC
- * bit), and then delay 10 microseconds.
- */
- ew32(CTRL, (*ctrl | E1000_CTRL_MDC));
- E1000_WRITE_FLUSH();
- udelay(10);
-}
+ ctrl = er32(CTRL);
+ /* With 82543, we need to force speed and duplex on the MAC equal to what
+ * the PHY speed and duplex configuration is. In addition, we need to
+ * perform a hardware reset on the PHY to take it out of reset.
+ */
+ if (hw->mac_type > e1000_82543) {
+ ctrl |= E1000_CTRL_SLU;
+ ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+ ew32(CTRL, ctrl);
+ } else {
+ ctrl |=
+ (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
+ ew32(CTRL, ctrl);
+ ret_val = e1000_phy_hw_reset(hw);
+ if (ret_val)
+ return ret_val;
+ }
-/******************************************************************************
-* Lowers the Management Data Clock
-*
-* hw - Struct containing variables accessed by shared code
-* ctrl - Device control register's current value
-******************************************************************************/
-static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
-{
- /* Lower the clock input to the Management Data Clock (by clearing the MDC
- * bit), and then delay 10 microseconds.
- */
- ew32(CTRL, (*ctrl & ~E1000_CTRL_MDC));
- E1000_WRITE_FLUSH();
- udelay(10);
-}
+ /* Make sure we have a valid PHY */
+ ret_val = e1000_detect_gig_phy(hw);
+ if (ret_val) {
+ DEBUGOUT("Error, did not detect valid phy.\n");
+ return ret_val;
+ }
+ DEBUGOUT1("Phy ID = %x \n", hw->phy_id);
+
+ /* Set PHY to class A mode (if necessary) */
+ ret_val = e1000_set_phy_mode(hw);
+ if (ret_val)
+ return ret_val;
+
+ if ((hw->mac_type == e1000_82545_rev_3) ||
+ (hw->mac_type == e1000_82546_rev_3)) {
+ ret_val =
+ e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ phy_data |= 0x00000008;
+ ret_val =
+ e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+ }
-/******************************************************************************
-* Shifts data bits out to the PHY
-*
-* hw - Struct containing variables accessed by shared code
-* data - Data to send out to the PHY
-* count - Number of bits to shift out
-*
-* Bits are shifted out in MSB to LSB order.
-******************************************************************************/
-static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count)
-{
- u32 ctrl;
- u32 mask;
-
- /* We need to shift "count" number of bits out to the PHY. So, the value
- * in the "data" parameter will be shifted out to the PHY one bit at a
- * time. In order to do this, "data" must be broken down into bits.
- */
- mask = 0x01;
- mask <<= (count - 1);
-
- ctrl = er32(CTRL);
-
- /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
- ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
-
- while (mask) {
- /* A "1" is shifted out to the PHY by setting the MDIO bit to "1" and
- * then raising and lowering the Management Data Clock. A "0" is
- * shifted out to the PHY by setting the MDIO bit to "0" and then
- * raising and lowering the clock.
- */
- if (data & mask)
- ctrl |= E1000_CTRL_MDIO;
- else
- ctrl &= ~E1000_CTRL_MDIO;
-
- ew32(CTRL, ctrl);
- E1000_WRITE_FLUSH();
-
- udelay(10);
-
- e1000_raise_mdi_clk(hw, &ctrl);
- e1000_lower_mdi_clk(hw, &ctrl);
-
- mask = mask >> 1;
- }
-}
+ if (hw->mac_type <= e1000_82543 ||
+ hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
+ hw->mac_type == e1000_82541_rev_2
+ || hw->mac_type == e1000_82547_rev_2)
+ hw->phy_reset_disable = false;
-/******************************************************************************
-* Shifts data bits in from the PHY
-*
-* hw - Struct containing variables accessed by shared code
-*
-* Bits are shifted in in MSB to LSB order.
-******************************************************************************/
-static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw)
-{
- u32 ctrl;
- u16 data = 0;
- u8 i;
-
- /* In order to read a register from the PHY, we need to shift in a total
- * of 18 bits from the PHY. The first two bit (turnaround) times are used
- * to avoid contention on the MDIO pin when a read operation is performed.
- * These two bits are ignored by us and thrown away. Bits are "shifted in"
- * by raising the input to the Management Data Clock (setting the MDC bit),
- * and then reading the value of the MDIO bit.
- */
- ctrl = er32(CTRL);
-
- /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */
- ctrl &= ~E1000_CTRL_MDIO_DIR;
- ctrl &= ~E1000_CTRL_MDIO;
-
- ew32(CTRL, ctrl);
- E1000_WRITE_FLUSH();
-
- /* Raise and Lower the clock before reading in the data. This accounts for
- * the turnaround bits. The first clock occurred when we clocked out the
- * last bit of the Register Address.
- */
- e1000_raise_mdi_clk(hw, &ctrl);
- e1000_lower_mdi_clk(hw, &ctrl);
-
- for (data = 0, i = 0; i < 16; i++) {
- data = data << 1;
- e1000_raise_mdi_clk(hw, &ctrl);
- ctrl = er32(CTRL);
- /* Check to see if we shifted in a "1". */
- if (ctrl & E1000_CTRL_MDIO)
- data |= 1;
- e1000_lower_mdi_clk(hw, &ctrl);
- }
-
- e1000_raise_mdi_clk(hw, &ctrl);
- e1000_lower_mdi_clk(hw, &ctrl);
-
- return data;
+ return E1000_SUCCESS;
}
-static s32 e1000_swfw_sync_acquire(struct e1000_hw *hw, u16 mask)
+/**
+ * e1000_copper_link_igp_setup - Copper link setup for e1000_phy_igp series.
+ * @hw: Struct containing variables accessed by shared code
+ */
+static s32 e1000_copper_link_igp_setup(struct e1000_hw *hw)
{
- u32 swfw_sync = 0;
- u32 swmask = mask;
- u32 fwmask = mask << 16;
- s32 timeout = 200;
+ u32 led_ctrl;
+ s32 ret_val;
+ u16 phy_data;
- DEBUGFUNC("e1000_swfw_sync_acquire");
+ DEBUGFUNC("e1000_copper_link_igp_setup");
- if (hw->swfwhw_semaphore_present)
- return e1000_get_software_flag(hw);
+ if (hw->phy_reset_disable)
+ return E1000_SUCCESS;
- if (!hw->swfw_sync_present)
- return e1000_get_hw_eeprom_semaphore(hw);
+ ret_val = e1000_phy_reset(hw);
+ if (ret_val) {
+ DEBUGOUT("Error Resetting the PHY\n");
+ return ret_val;
+ }
- while (timeout) {
- if (e1000_get_hw_eeprom_semaphore(hw))
- return -E1000_ERR_SWFW_SYNC;
+ /* Wait 15ms for MAC to configure PHY from eeprom settings */
+ msleep(15);
+ /* Configure activity LED after PHY reset */
+ led_ctrl = er32(LEDCTL);
+ led_ctrl &= IGP_ACTIVITY_LED_MASK;
+ led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
+ ew32(LEDCTL, led_ctrl);
+
+ /* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */
+ if (hw->phy_type == e1000_phy_igp) {
+ /* disable lplu d3 during driver init */
+ ret_val = e1000_set_d3_lplu_state(hw, false);
+ if (ret_val) {
+ DEBUGOUT("Error Disabling LPLU D3\n");
+ return ret_val;
+ }
+ }
- swfw_sync = er32(SW_FW_SYNC);
- if (!(swfw_sync & (fwmask | swmask))) {
- break;
- }
+ /* Configure mdi-mdix settings */
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
+ hw->dsp_config_state = e1000_dsp_config_disabled;
+ /* Force MDI for earlier revs of the IGP PHY */
+ phy_data &=
+ ~(IGP01E1000_PSCR_AUTO_MDIX |
+ IGP01E1000_PSCR_FORCE_MDI_MDIX);
+ hw->mdix = 1;
+
+ } else {
+ hw->dsp_config_state = e1000_dsp_config_enabled;
+ phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
+
+ switch (hw->mdix) {
+ case 1:
+ phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
+ break;
+ case 2:
+ phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
+ break;
+ case 0:
+ default:
+ phy_data |= IGP01E1000_PSCR_AUTO_MDIX;
+ break;
+ }
+ }
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* set auto-master slave resolution settings */
+ if (hw->autoneg) {
+ e1000_ms_type phy_ms_setting = hw->master_slave;
+
+ if (hw->ffe_config_state == e1000_ffe_config_active)
+ hw->ffe_config_state = e1000_ffe_config_enabled;
+
+ if (hw->dsp_config_state == e1000_dsp_config_activated)
+ hw->dsp_config_state = e1000_dsp_config_enabled;
+
+ /* when autonegotiation advertisement is only 1000Mbps then we
+ * should disable SmartSpeed and enable Auto MasterSlave
+ * resolution as hardware default. */
+ if (hw->autoneg_advertised == ADVERTISE_1000_FULL) {
+ /* Disable SmartSpeed */
+ ret_val =
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+ phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val =
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ /* Set auto Master/Slave resolution process */
+ ret_val =
+ e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+ phy_data &= ~CR_1000T_MS_ENABLE;
+ ret_val =
+ e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
+ if (ret_val)
+ return ret_val;
+ }
- /* firmware currently using resource (fwmask) */
- /* or other software thread currently using resource (swmask) */
- e1000_put_hw_eeprom_semaphore(hw);
- mdelay(5);
- timeout--;
- }
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
- if (!timeout) {
- DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
- return -E1000_ERR_SWFW_SYNC;
- }
+ /* load defaults for future use */
+ hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?
+ ((phy_data & CR_1000T_MS_VALUE) ?
+ e1000_ms_force_master :
+ e1000_ms_force_slave) : e1000_ms_auto;
- swfw_sync |= swmask;
- ew32(SW_FW_SYNC, swfw_sync);
+ switch (phy_ms_setting) {
+ case e1000_ms_force_master:
+ phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_force_slave:
+ phy_data |= CR_1000T_MS_ENABLE;
+ phy_data &= ~(CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_auto:
+ phy_data &= ~CR_1000T_MS_ENABLE;
+ default:
+ break;
+ }
+ ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
+ if (ret_val)
+ return ret_val;
+ }
- e1000_put_hw_eeprom_semaphore(hw);
- return E1000_SUCCESS;
+ return E1000_SUCCESS;
}
-static void e1000_swfw_sync_release(struct e1000_hw *hw, u16 mask)
+/**
+ * e1000_copper_link_mgp_setup - Copper link setup for e1000_phy_m88 series.
+ * @hw: Struct containing variables accessed by shared code
+ */
+static s32 e1000_copper_link_mgp_setup(struct e1000_hw *hw)
{
- u32 swfw_sync;
- u32 swmask = mask;
+ s32 ret_val;
+ u16 phy_data;
- DEBUGFUNC("e1000_swfw_sync_release");
+ DEBUGFUNC("e1000_copper_link_mgp_setup");
- if (hw->swfwhw_semaphore_present) {
- e1000_release_software_flag(hw);
- return;
- }
+ if (hw->phy_reset_disable)
+ return E1000_SUCCESS;
- if (!hw->swfw_sync_present) {
- e1000_put_hw_eeprom_semaphore(hw);
- return;
- }
+ /* Enable CRS on TX. This must be set for half-duplex operation. */
+ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
- /* if (e1000_get_hw_eeprom_semaphore(hw))
- * return -E1000_ERR_SWFW_SYNC; */
- while (e1000_get_hw_eeprom_semaphore(hw) != E1000_SUCCESS);
- /* empty */
+ phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
- swfw_sync = er32(SW_FW_SYNC);
- swfw_sync &= ~swmask;
- ew32(SW_FW_SYNC, swfw_sync);
-
- e1000_put_hw_eeprom_semaphore(hw);
-}
-
-/*****************************************************************************
-* Reads the value from a PHY register, if the value is on a specific non zero
-* page, sets the page first.
-* hw - Struct containing variables accessed by shared code
-* reg_addr - address of the PHY register to read
-******************************************************************************/
-s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data)
-{
- u32 ret_val;
- u16 swfw;
-
- DEBUGFUNC("e1000_read_phy_reg");
-
- if ((hw->mac_type == e1000_80003es2lan) &&
- (er32(STATUS) & E1000_STATUS_FUNC_1)) {
- swfw = E1000_SWFW_PHY1_SM;
- } else {
- swfw = E1000_SWFW_PHY0_SM;
- }
- if (e1000_swfw_sync_acquire(hw, swfw))
- return -E1000_ERR_SWFW_SYNC;
-
- if ((hw->phy_type == e1000_phy_igp ||
- hw->phy_type == e1000_phy_igp_3 ||
- hw->phy_type == e1000_phy_igp_2) &&
- (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
- ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
- (u16)reg_addr);
- if (ret_val) {
- e1000_swfw_sync_release(hw, swfw);
- return ret_val;
- }
- } else if (hw->phy_type == e1000_phy_gg82563) {
- if (((reg_addr & MAX_PHY_REG_ADDRESS) > MAX_PHY_MULTI_PAGE_REG) ||
- (hw->mac_type == e1000_80003es2lan)) {
- /* Select Configuration Page */
- if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
- ret_val = e1000_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT,
- (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
- } else {
- /* Use Alternative Page Select register to access
- * registers 30 and 31
- */
- ret_val = e1000_write_phy_reg_ex(hw,
- GG82563_PHY_PAGE_SELECT_ALT,
- (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
- }
-
- if (ret_val) {
- e1000_swfw_sync_release(hw, swfw);
- return ret_val;
- }
- }
- }
-
- ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
- phy_data);
-
- e1000_swfw_sync_release(hw, swfw);
- return ret_val;
-}
+ /* Options:
+ * MDI/MDI-X = 0 (default)
+ * 0 - Auto for all speeds
+ * 1 - MDI mode
+ * 2 - MDI-X mode
+ * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+ */
+ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
-static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
- u16 *phy_data)
-{
- u32 i;
- u32 mdic = 0;
- const u32 phy_addr = 1;
-
- DEBUGFUNC("e1000_read_phy_reg_ex");
-
- if (reg_addr > MAX_PHY_REG_ADDRESS) {
- DEBUGOUT1("PHY Address %d is out of range\n", reg_addr);
- return -E1000_ERR_PARAM;
- }
-
- if (hw->mac_type > e1000_82543) {
- /* Set up Op-code, Phy Address, and register address in the MDI
- * Control register. The MAC will take care of interfacing with the
- * PHY to retrieve the desired data.
- */
- mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
- (phy_addr << E1000_MDIC_PHY_SHIFT) |
- (E1000_MDIC_OP_READ));
-
- ew32(MDIC, mdic);
-
- /* Poll the ready bit to see if the MDI read completed */
- for (i = 0; i < 64; i++) {
- udelay(50);
- mdic = er32(MDIC);
- if (mdic & E1000_MDIC_READY) break;
- }
- if (!(mdic & E1000_MDIC_READY)) {
- DEBUGOUT("MDI Read did not complete\n");
- return -E1000_ERR_PHY;
- }
- if (mdic & E1000_MDIC_ERROR) {
- DEBUGOUT("MDI Error\n");
- return -E1000_ERR_PHY;
- }
- *phy_data = (u16)mdic;
- } else {
- /* We must first send a preamble through the MDIO pin to signal the
- * beginning of an MII instruction. This is done by sending 32
- * consecutive "1" bits.
- */
- e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
-
- /* Now combine the next few fields that are required for a read
- * operation. We use this method instead of calling the
- * e1000_shift_out_mdi_bits routine five different times. The format of
- * a MII read instruction consists of a shift out of 14 bits and is
- * defined as follows:
- * <Preamble><SOF><Op Code><Phy Addr><Reg Addr>
- * followed by a shift in of 18 bits. This first two bits shifted in
- * are TurnAround bits used to avoid contention on the MDIO pin when a
- * READ operation is performed. These two bits are thrown away
- * followed by a shift in of 16 bits which contains the desired data.
- */
- mdic = ((reg_addr) | (phy_addr << 5) |
- (PHY_OP_READ << 10) | (PHY_SOF << 12));
-
- e1000_shift_out_mdi_bits(hw, mdic, 14);
-
- /* Now that we've shifted out the read command to the MII, we need to
- * "shift in" the 16-bit value (18 total bits) of the requested PHY
- * register address.
- */
- *phy_data = e1000_shift_in_mdi_bits(hw);
- }
- return E1000_SUCCESS;
-}
+ switch (hw->mdix) {
+ case 1:
+ phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
+ break;
+ case 2:
+ phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
+ break;
+ case 3:
+ phy_data |= M88E1000_PSCR_AUTO_X_1000T;
+ break;
+ case 0:
+ default:
+ phy_data |= M88E1000_PSCR_AUTO_X_MODE;
+ break;
+ }
-/******************************************************************************
-* Writes a value to a PHY register
-*
-* hw - Struct containing variables accessed by shared code
-* reg_addr - address of the PHY register to write
-* data - data to write to the PHY
-******************************************************************************/
-s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data)
-{
- u32 ret_val;
- u16 swfw;
-
- DEBUGFUNC("e1000_write_phy_reg");
-
- if ((hw->mac_type == e1000_80003es2lan) &&
- (er32(STATUS) & E1000_STATUS_FUNC_1)) {
- swfw = E1000_SWFW_PHY1_SM;
- } else {
- swfw = E1000_SWFW_PHY0_SM;
- }
- if (e1000_swfw_sync_acquire(hw, swfw))
- return -E1000_ERR_SWFW_SYNC;
-
- if ((hw->phy_type == e1000_phy_igp ||
- hw->phy_type == e1000_phy_igp_3 ||
- hw->phy_type == e1000_phy_igp_2) &&
- (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
- ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
- (u16)reg_addr);
- if (ret_val) {
- e1000_swfw_sync_release(hw, swfw);
- return ret_val;
- }
- } else if (hw->phy_type == e1000_phy_gg82563) {
- if (((reg_addr & MAX_PHY_REG_ADDRESS) > MAX_PHY_MULTI_PAGE_REG) ||
- (hw->mac_type == e1000_80003es2lan)) {
- /* Select Configuration Page */
- if ((reg_addr & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
- ret_val = e1000_write_phy_reg_ex(hw, GG82563_PHY_PAGE_SELECT,
- (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
- } else {
- /* Use Alternative Page Select register to access
- * registers 30 and 31
- */
- ret_val = e1000_write_phy_reg_ex(hw,
- GG82563_PHY_PAGE_SELECT_ALT,
- (u16)((u16)reg_addr >> GG82563_PAGE_SHIFT));
- }
-
- if (ret_val) {
- e1000_swfw_sync_release(hw, swfw);
- return ret_val;
- }
- }
- }
-
- ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
- phy_data);
-
- e1000_swfw_sync_release(hw, swfw);
- return ret_val;
-}
+ /* Options:
+ * disable_polarity_correction = 0 (default)
+ * Automatic Correction for Reversed Cable Polarity
+ * 0 - Disabled
+ * 1 - Enabled
+ */
+ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
+ if (hw->disable_polarity_correction == 1)
+ phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+ if (ret_val)
+ return ret_val;
+
+ if (hw->phy_revision < M88E1011_I_REV_4) {
+ /* Force TX_CLK in the Extended PHY Specific Control Register
+ * to 25MHz clock.
+ */
+ ret_val =
+ e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data |= M88E1000_EPSCR_TX_CLK_25;
+
+ if ((hw->phy_revision == E1000_REVISION_2) &&
+ (hw->phy_id == M88E1111_I_PHY_ID)) {
+ /* Vidalia Phy, set the downshift counter to 5x */
+ phy_data &= ~(M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK);
+ phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X;
+ ret_val = e1000_write_phy_reg(hw,
+ M88E1000_EXT_PHY_SPEC_CTRL,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ } else {
+ /* Configure Master and Slave downshift values */
+ phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
+ M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
+ phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
+ M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
+ ret_val = e1000_write_phy_reg(hw,
+ M88E1000_EXT_PHY_SPEC_CTRL,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ }
+ }
-static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
- u16 phy_data)
-{
- u32 i;
- u32 mdic = 0;
- const u32 phy_addr = 1;
-
- DEBUGFUNC("e1000_write_phy_reg_ex");
-
- if (reg_addr > MAX_PHY_REG_ADDRESS) {
- DEBUGOUT1("PHY Address %d is out of range\n", reg_addr);
- return -E1000_ERR_PARAM;
- }
-
- if (hw->mac_type > e1000_82543) {
- /* Set up Op-code, Phy Address, register address, and data intended
- * for the PHY register in the MDI Control register. The MAC will take
- * care of interfacing with the PHY to send the desired data.
- */
- mdic = (((u32)phy_data) |
- (reg_addr << E1000_MDIC_REG_SHIFT) |
- (phy_addr << E1000_MDIC_PHY_SHIFT) |
- (E1000_MDIC_OP_WRITE));
-
- ew32(MDIC, mdic);
-
- /* Poll the ready bit to see if the MDI read completed */
- for (i = 0; i < 641; i++) {
- udelay(5);
- mdic = er32(MDIC);
- if (mdic & E1000_MDIC_READY) break;
- }
- if (!(mdic & E1000_MDIC_READY)) {
- DEBUGOUT("MDI Write did not complete\n");
- return -E1000_ERR_PHY;
- }
- } else {
- /* We'll need to use the SW defined pins to shift the write command
- * out to the PHY. We first send a preamble to the PHY to signal the
- * beginning of the MII instruction. This is done by sending 32
- * consecutive "1" bits.
- */
- e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
-
- /* Now combine the remaining required fields that will indicate a
- * write operation. We use this method instead of calling the
- * e1000_shift_out_mdi_bits routine for each field in the command. The
- * format of a MII write instruction is as follows:
- * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
- */
- mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
- (PHY_OP_WRITE << 12) | (PHY_SOF << 14));
- mdic <<= 16;
- mdic |= (u32)phy_data;
-
- e1000_shift_out_mdi_bits(hw, mdic, 32);
- }
-
- return E1000_SUCCESS;
-}
+ /* SW Reset the PHY so all changes take effect */
+ ret_val = e1000_phy_reset(hw);
+ if (ret_val) {
+ DEBUGOUT("Error Resetting the PHY\n");
+ return ret_val;
+ }
-static s32 e1000_read_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 *data)
-{
- u32 reg_val;
- u16 swfw;
- DEBUGFUNC("e1000_read_kmrn_reg");
-
- if ((hw->mac_type == e1000_80003es2lan) &&
- (er32(STATUS) & E1000_STATUS_FUNC_1)) {
- swfw = E1000_SWFW_PHY1_SM;
- } else {
- swfw = E1000_SWFW_PHY0_SM;
- }
- if (e1000_swfw_sync_acquire(hw, swfw))
- return -E1000_ERR_SWFW_SYNC;
-
- /* Write register address */
- reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
- E1000_KUMCTRLSTA_OFFSET) |
- E1000_KUMCTRLSTA_REN;
- ew32(KUMCTRLSTA, reg_val);
- udelay(2);
-
- /* Read the data returned */
- reg_val = er32(KUMCTRLSTA);
- *data = (u16)reg_val;
-
- e1000_swfw_sync_release(hw, swfw);
- return E1000_SUCCESS;
+ return E1000_SUCCESS;
}
-static s32 e1000_write_kmrn_reg(struct e1000_hw *hw, u32 reg_addr, u16 data)
+/**
+ * e1000_copper_link_autoneg - setup auto-neg
+ * @hw: Struct containing variables accessed by shared code
+ *
+ * Setup auto-negotiation and flow control advertisements,
+ * and then perform auto-negotiation.
+ */
+static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
{
- u32 reg_val;
- u16 swfw;
- DEBUGFUNC("e1000_write_kmrn_reg");
-
- if ((hw->mac_type == e1000_80003es2lan) &&
- (er32(STATUS) & E1000_STATUS_FUNC_1)) {
- swfw = E1000_SWFW_PHY1_SM;
- } else {
- swfw = E1000_SWFW_PHY0_SM;
- }
- if (e1000_swfw_sync_acquire(hw, swfw))
- return -E1000_ERR_SWFW_SYNC;
-
- reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
- E1000_KUMCTRLSTA_OFFSET) | data;
- ew32(KUMCTRLSTA, reg_val);
- udelay(2);
-
- e1000_swfw_sync_release(hw, swfw);
- return E1000_SUCCESS;
-}
+ s32 ret_val;
+ u16 phy_data;
-/******************************************************************************
-* Returns the PHY to the power-on reset state
-*
-* hw - Struct containing variables accessed by shared code
-******************************************************************************/
-s32 e1000_phy_hw_reset(struct e1000_hw *hw)
-{
- u32 ctrl, ctrl_ext;
- u32 led_ctrl;
- s32 ret_val;
- u16 swfw;
-
- DEBUGFUNC("e1000_phy_hw_reset");
-
- /* In the case of the phy reset being blocked, it's not an error, we
- * simply return success without performing the reset. */
- ret_val = e1000_check_phy_reset_block(hw);
- if (ret_val)
- return E1000_SUCCESS;
-
- DEBUGOUT("Resetting Phy...\n");
-
- if (hw->mac_type > e1000_82543) {
- if ((hw->mac_type == e1000_80003es2lan) &&
- (er32(STATUS) & E1000_STATUS_FUNC_1)) {
- swfw = E1000_SWFW_PHY1_SM;
- } else {
- swfw = E1000_SWFW_PHY0_SM;
- }
- if (e1000_swfw_sync_acquire(hw, swfw)) {
- DEBUGOUT("Unable to acquire swfw sync\n");
- return -E1000_ERR_SWFW_SYNC;
- }
- /* Read the device control register and assert the E1000_CTRL_PHY_RST
- * bit. Then, take it out of reset.
- * For pre-e1000_82571 hardware, we delay for 10ms between the assert
- * and deassert. For e1000_82571 hardware and later, we instead delay
- * for 50us between and 10ms after the deassertion.
- */
- ctrl = er32(CTRL);
- ew32(CTRL, ctrl | E1000_CTRL_PHY_RST);
- E1000_WRITE_FLUSH();
-
- if (hw->mac_type < e1000_82571)
- msleep(10);
- else
- udelay(100);
-
- ew32(CTRL, ctrl);
- E1000_WRITE_FLUSH();
-
- if (hw->mac_type >= e1000_82571)
- mdelay(10);
-
- e1000_swfw_sync_release(hw, swfw);
- } else {
- /* Read the Extended Device Control Register, assert the PHY_RESET_DIR
- * bit to put the PHY into reset. Then, take it out of reset.
- */
- ctrl_ext = er32(CTRL_EXT);
- ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
- ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
- ew32(CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH();
- msleep(10);
- ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
- ew32(CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH();
- }
- udelay(150);
-
- if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
- /* Configure activity LED after PHY reset */
- led_ctrl = er32(LEDCTL);
- led_ctrl &= IGP_ACTIVITY_LED_MASK;
- led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
- ew32(LEDCTL, led_ctrl);
- }
-
- /* Wait for FW to finish PHY configuration. */
- ret_val = e1000_get_phy_cfg_done(hw);
- if (ret_val != E1000_SUCCESS)
- return ret_val;
- e1000_release_software_semaphore(hw);
-
- if ((hw->mac_type == e1000_ich8lan) && (hw->phy_type == e1000_phy_igp_3))
- ret_val = e1000_init_lcd_from_nvm(hw);
-
- return ret_val;
-}
+ DEBUGFUNC("e1000_copper_link_autoneg");
-/******************************************************************************
-* Resets the PHY
-*
-* hw - Struct containing variables accessed by shared code
-*
-* Sets bit 15 of the MII Control register
-******************************************************************************/
-s32 e1000_phy_reset(struct e1000_hw *hw)
-{
- s32 ret_val;
- u16 phy_data;
-
- DEBUGFUNC("e1000_phy_reset");
-
- /* In the case of the phy reset being blocked, it's not an error, we
- * simply return success without performing the reset. */
- ret_val = e1000_check_phy_reset_block(hw);
- if (ret_val)
- return E1000_SUCCESS;
-
- switch (hw->phy_type) {
- case e1000_phy_igp:
- case e1000_phy_igp_2:
- case e1000_phy_igp_3:
- case e1000_phy_ife:
- ret_val = e1000_phy_hw_reset(hw);
- if (ret_val)
- return ret_val;
- break;
- default:
- ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data |= MII_CR_RESET;
- ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
- if (ret_val)
- return ret_val;
-
- udelay(1);
- break;
- }
-
- if (hw->phy_type == e1000_phy_igp || hw->phy_type == e1000_phy_igp_2)
- e1000_phy_init_script(hw);
-
- return E1000_SUCCESS;
-}
+ /* Perform some bounds checking on the hw->autoneg_advertised
+ * parameter. If this variable is zero, then set it to the default.
+ */
+ hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
-/******************************************************************************
-* Work-around for 82566 power-down: on D3 entry-
-* 1) disable gigabit link
-* 2) write VR power-down enable
-* 3) read it back
-* if successful continue, else issue LCD reset and repeat
-*
-* hw - struct containing variables accessed by shared code
-******************************************************************************/
-void e1000_phy_powerdown_workaround(struct e1000_hw *hw)
-{
- s32 reg;
- u16 phy_data;
- s32 retry = 0;
+ /* If autoneg_advertised is zero, we assume it was not defaulted
+ * by the calling code so we set to advertise full capability.
+ */
+ if (hw->autoneg_advertised == 0)
+ hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+
+ DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
+ ret_val = e1000_phy_setup_autoneg(hw);
+ if (ret_val) {
+ DEBUGOUT("Error Setting up Auto-Negotiation\n");
+ return ret_val;
+ }
+ DEBUGOUT("Restarting Auto-Neg\n");
- DEBUGFUNC("e1000_phy_powerdown_workaround");
+ /* Restart auto-negotiation by setting the Auto Neg Enable bit and
+ * the Auto Neg Restart bit in the PHY control register.
+ */
+ ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
- if (hw->phy_type != e1000_phy_igp_3)
- return;
+ phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
+ ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
+ if (ret_val)
+ return ret_val;
- do {
- /* Disable link */
- reg = er32(PHY_CTRL);
- ew32(PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
- E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
+ /* Does the user want to wait for Auto-Neg to complete here, or
+ * check at a later time (for example, callback routine).
+ */
+ if (hw->wait_autoneg_complete) {
+ ret_val = e1000_wait_autoneg(hw);
+ if (ret_val) {
+ DEBUGOUT
+ ("Error while waiting for autoneg to complete\n");
+ return ret_val;
+ }
+ }
- /* Write VR power-down enable - bits 9:8 should be 10b */
- e1000_read_phy_reg(hw, IGP3_VR_CTRL, &phy_data);
- phy_data |= (1 << 9);
- phy_data &= ~(1 << 8);
- e1000_write_phy_reg(hw, IGP3_VR_CTRL, phy_data);
+ hw->get_link_status = true;
- /* Read it back and test */
- e1000_read_phy_reg(hw, IGP3_VR_CTRL, &phy_data);
- if (((phy_data & IGP3_VR_CTRL_MODE_MASK) == IGP3_VR_CTRL_MODE_SHUT) || retry)
- break;
+ return E1000_SUCCESS;
+}
- /* Issue PHY reset and repeat at most one more time */
- reg = er32(CTRL);
- ew32(CTRL, reg | E1000_CTRL_PHY_RST);
- retry++;
- } while (retry);
+/**
+ * e1000_copper_link_postconfig - post link setup
+ * @hw: Struct containing variables accessed by shared code
+ *
+ * Config the MAC and the PHY after link is up.
+ * 1) Set up the MAC to the current PHY speed/duplex
+ * if we are on 82543. If we
+ * are on newer silicon, we only need to configure
+ * collision distance in the Transmit Control Register.
+ * 2) Set up flow control on the MAC to that established with
+ * the link partner.
+ * 3) Config DSP to improve Gigabit link quality for some PHY revisions.
+ */
+static s32 e1000_copper_link_postconfig(struct e1000_hw *hw)
+{
+ s32 ret_val;
+ DEBUGFUNC("e1000_copper_link_postconfig");
- return;
+ if (hw->mac_type >= e1000_82544) {
+ e1000_config_collision_dist(hw);
+ } else {
+ ret_val = e1000_config_mac_to_phy(hw);
+ if (ret_val) {
+ DEBUGOUT("Error configuring MAC to PHY settings\n");
+ return ret_val;
+ }
+ }
+ ret_val = e1000_config_fc_after_link_up(hw);
+ if (ret_val) {
+ DEBUGOUT("Error Configuring Flow Control\n");
+ return ret_val;
+ }
-}
+ /* Config DSP to improve Giga link quality */
+ if (hw->phy_type == e1000_phy_igp) {
+ ret_val = e1000_config_dsp_after_link_change(hw, true);
+ if (ret_val) {
+ DEBUGOUT("Error Configuring DSP after link up\n");
+ return ret_val;
+ }
+ }
-/******************************************************************************
-* Work-around for 82566 Kumeran PCS lock loss:
-* On link status change (i.e. PCI reset, speed change) and link is up and
-* speed is gigabit-
-* 0) if workaround is optionally disabled do nothing
-* 1) wait 1ms for Kumeran link to come up
-* 2) check Kumeran Diagnostic register PCS lock loss bit
-* 3) if not set the link is locked (all is good), otherwise...
-* 4) reset the PHY
-* 5) repeat up to 10 times
-* Note: this is only called for IGP3 copper when speed is 1gb.
-*
-* hw - struct containing variables accessed by shared code
-******************************************************************************/
-static s32 e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
-{
- s32 ret_val;
- s32 reg;
- s32 cnt;
- u16 phy_data;
-
- if (hw->kmrn_lock_loss_workaround_disabled)
- return E1000_SUCCESS;
-
- /* Make sure link is up before proceeding. If not just return.
- * Attempting this while link is negotiating fouled up link
- * stability */
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-
- if (phy_data & MII_SR_LINK_STATUS) {
- for (cnt = 0; cnt < 10; cnt++) {
- /* read once to clear */
- ret_val = e1000_read_phy_reg(hw, IGP3_KMRN_DIAG, &phy_data);
- if (ret_val)
- return ret_val;
- /* and again to get new status */
- ret_val = e1000_read_phy_reg(hw, IGP3_KMRN_DIAG, &phy_data);
- if (ret_val)
- return ret_val;
-
- /* check for PCS lock */
- if (!(phy_data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS))
- return E1000_SUCCESS;
-
- /* Issue PHY reset */
- e1000_phy_hw_reset(hw);
- mdelay(5);
- }
- /* Disable GigE link negotiation */
- reg = er32(PHY_CTRL);
- ew32(PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE |
- E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
-
- /* unable to acquire PCS lock */
- return E1000_ERR_PHY;
- }
-
- return E1000_SUCCESS;
+ return E1000_SUCCESS;
}
-/******************************************************************************
-* Probes the expected PHY address for known PHY IDs
-*
-* hw - Struct containing variables accessed by shared code
-******************************************************************************/
-static s32 e1000_detect_gig_phy(struct e1000_hw *hw)
+/**
+ * e1000_setup_copper_link - phy/speed/duplex setting
+ * @hw: Struct containing variables accessed by shared code
+ *
+ * Detects which PHY is present and sets up the speed and duplex
+ */
+static s32 e1000_setup_copper_link(struct e1000_hw *hw)
{
- s32 phy_init_status, ret_val;
- u16 phy_id_high, phy_id_low;
- bool match = false;
-
- DEBUGFUNC("e1000_detect_gig_phy");
-
- if (hw->phy_id != 0)
- return E1000_SUCCESS;
-
- /* The 82571 firmware may still be configuring the PHY. In this
- * case, we cannot access the PHY until the configuration is done. So
- * we explicitly set the PHY values. */
- if (hw->mac_type == e1000_82571 ||
- hw->mac_type == e1000_82572) {
- hw->phy_id = IGP01E1000_I_PHY_ID;
- hw->phy_type = e1000_phy_igp_2;
- return E1000_SUCCESS;
- }
-
- /* ESB-2 PHY reads require e1000_phy_gg82563 to be set because of a work-
- * around that forces PHY page 0 to be set or the reads fail. The rest of
- * the code in this routine uses e1000_read_phy_reg to read the PHY ID.
- * So for ESB-2 we need to have this set so our reads won't fail. If the
- * attached PHY is not a e1000_phy_gg82563, the routines below will figure
- * this out as well. */
- if (hw->mac_type == e1000_80003es2lan)
- hw->phy_type = e1000_phy_gg82563;
-
- /* Read the PHY ID Registers to identify which PHY is onboard. */
- ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
- if (ret_val)
- return ret_val;
-
- hw->phy_id = (u32)(phy_id_high << 16);
- udelay(20);
- ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low);
- if (ret_val)
- return ret_val;
-
- hw->phy_id |= (u32)(phy_id_low & PHY_REVISION_MASK);
- hw->phy_revision = (u32)phy_id_low & ~PHY_REVISION_MASK;
-
- switch (hw->mac_type) {
- case e1000_82543:
- if (hw->phy_id == M88E1000_E_PHY_ID) match = true;
- break;
- case e1000_82544:
- if (hw->phy_id == M88E1000_I_PHY_ID) match = true;
- break;
- case e1000_82540:
- case e1000_82545:
- case e1000_82545_rev_3:
- case e1000_82546:
- case e1000_82546_rev_3:
- if (hw->phy_id == M88E1011_I_PHY_ID) match = true;
- break;
- case e1000_82541:
- case e1000_82541_rev_2:
- case e1000_82547:
- case e1000_82547_rev_2:
- if (hw->phy_id == IGP01E1000_I_PHY_ID) match = true;
- break;
- case e1000_82573:
- if (hw->phy_id == M88E1111_I_PHY_ID) match = true;
- break;
- case e1000_80003es2lan:
- if (hw->phy_id == GG82563_E_PHY_ID) match = true;
- break;
- case e1000_ich8lan:
- if (hw->phy_id == IGP03E1000_E_PHY_ID) match = true;
- if (hw->phy_id == IFE_E_PHY_ID) match = true;
- if (hw->phy_id == IFE_PLUS_E_PHY_ID) match = true;
- if (hw->phy_id == IFE_C_E_PHY_ID) match = true;
- break;
- default:
- DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
- return -E1000_ERR_CONFIG;
- }
- phy_init_status = e1000_set_phy_type(hw);
-
- if ((match) && (phy_init_status == E1000_SUCCESS)) {
- DEBUGOUT1("PHY ID 0x%X detected\n", hw->phy_id);
- return E1000_SUCCESS;
- }
- DEBUGOUT1("Invalid PHY ID 0x%X\n", hw->phy_id);
- return -E1000_ERR_PHY;
-}
+ s32 ret_val;
+ u16 i;
+ u16 phy_data;
+
+ DEBUGFUNC("e1000_setup_copper_link");
+
+ /* Check if it is a valid PHY and set PHY mode if necessary. */
+ ret_val = e1000_copper_link_preconfig(hw);
+ if (ret_val)
+ return ret_val;
+
+ if (hw->phy_type == e1000_phy_igp) {
+ ret_val = e1000_copper_link_igp_setup(hw);
+ if (ret_val)
+ return ret_val;
+ } else if (hw->phy_type == e1000_phy_m88) {
+ ret_val = e1000_copper_link_mgp_setup(hw);
+ if (ret_val)
+ return ret_val;
+ }
-/******************************************************************************
-* Resets the PHY's DSP
-*
-* hw - Struct containing variables accessed by shared code
-******************************************************************************/
-static s32 e1000_phy_reset_dsp(struct e1000_hw *hw)
-{
- s32 ret_val;
- DEBUGFUNC("e1000_phy_reset_dsp");
-
- do {
- if (hw->phy_type != e1000_phy_gg82563) {
- ret_val = e1000_write_phy_reg(hw, 29, 0x001d);
- if (ret_val) break;
- }
- ret_val = e1000_write_phy_reg(hw, 30, 0x00c1);
- if (ret_val) break;
- ret_val = e1000_write_phy_reg(hw, 30, 0x0000);
- if (ret_val) break;
- ret_val = E1000_SUCCESS;
- } while (0);
-
- return ret_val;
-}
+ if (hw->autoneg) {
+ /* Setup autoneg and flow control advertisement
+ * and perform autonegotiation */
+ ret_val = e1000_copper_link_autoneg(hw);
+ if (ret_val)
+ return ret_val;
+ } else {
+ /* PHY will be set to 10H, 10F, 100H,or 100F
+ * depending on value from forced_speed_duplex. */
+ DEBUGOUT("Forcing speed and duplex\n");
+ ret_val = e1000_phy_force_speed_duplex(hw);
+ if (ret_val) {
+ DEBUGOUT("Error Forcing Speed and Duplex\n");
+ return ret_val;
+ }
+ }
-/******************************************************************************
-* Get PHY information from various PHY registers for igp PHY only.
-*
-* hw - Struct containing variables accessed by shared code
-* phy_info - PHY information structure
-******************************************************************************/
-static s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
- struct e1000_phy_info *phy_info)
-{
- s32 ret_val;
- u16 phy_data, min_length, max_length, average;
- e1000_rev_polarity polarity;
-
- DEBUGFUNC("e1000_phy_igp_get_info");
-
- /* The downshift status is checked only once, after link is established,
- * and it stored in the hw->speed_downgraded parameter. */
- phy_info->downshift = (e1000_downshift)hw->speed_downgraded;
-
- /* IGP01E1000 does not need to support it. */
- phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal;
-
- /* IGP01E1000 always correct polarity reversal */
- phy_info->polarity_correction = e1000_polarity_reversal_enabled;
-
- /* Check polarity status */
- ret_val = e1000_check_polarity(hw, &polarity);
- if (ret_val)
- return ret_val;
-
- phy_info->cable_polarity = polarity;
-
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_info->mdix_mode = (e1000_auto_x_mode)((phy_data & IGP01E1000_PSSR_MDIX) >>
- IGP01E1000_PSSR_MDIX_SHIFT);
-
- if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
- IGP01E1000_PSSR_SPEED_1000MBPS) {
- /* Local/Remote Receiver Information are only valid at 1000 Mbps */
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >>
- SR_1000T_LOCAL_RX_STATUS_SHIFT) ?
- e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
- phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >>
- SR_1000T_REMOTE_RX_STATUS_SHIFT) ?
- e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
-
- /* Get cable length */
- ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
- if (ret_val)
- return ret_val;
-
- /* Translate to old method */
- average = (max_length + min_length) / 2;
-
- if (average <= e1000_igp_cable_length_50)
- phy_info->cable_length = e1000_cable_length_50;
- else if (average <= e1000_igp_cable_length_80)
- phy_info->cable_length = e1000_cable_length_50_80;
- else if (average <= e1000_igp_cable_length_110)
- phy_info->cable_length = e1000_cable_length_80_110;
- else if (average <= e1000_igp_cable_length_140)
- phy_info->cable_length = e1000_cable_length_110_140;
- else
- phy_info->cable_length = e1000_cable_length_140;
- }
-
- return E1000_SUCCESS;
-}
+ /* Check link status. Wait up to 100 microseconds for link to become
+ * valid.
+ */
+ for (i = 0; i < 10; i++) {
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ if (phy_data & MII_SR_LINK_STATUS) {
+ /* Config the MAC and PHY after link is up */
+ ret_val = e1000_copper_link_postconfig(hw);
+ if (ret_val)
+ return ret_val;
+
+ DEBUGOUT("Valid link established!!!\n");
+ return E1000_SUCCESS;
+ }
+ udelay(10);
+ }
-/******************************************************************************
-* Get PHY information from various PHY registers for ife PHY only.
-*
-* hw - Struct containing variables accessed by shared code
-* phy_info - PHY information structure
-******************************************************************************/
-static s32 e1000_phy_ife_get_info(struct e1000_hw *hw,
- struct e1000_phy_info *phy_info)
-{
- s32 ret_val;
- u16 phy_data;
- e1000_rev_polarity polarity;
-
- DEBUGFUNC("e1000_phy_ife_get_info");
-
- phy_info->downshift = (e1000_downshift)hw->speed_downgraded;
- phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal;
-
- ret_val = e1000_read_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL, &phy_data);
- if (ret_val)
- return ret_val;
- phy_info->polarity_correction =
- ((phy_data & IFE_PSC_AUTO_POLARITY_DISABLE) >>
- IFE_PSC_AUTO_POLARITY_DISABLE_SHIFT) ?
- e1000_polarity_reversal_disabled : e1000_polarity_reversal_enabled;
-
- if (phy_info->polarity_correction == e1000_polarity_reversal_enabled) {
- ret_val = e1000_check_polarity(hw, &polarity);
- if (ret_val)
- return ret_val;
- } else {
- /* Polarity is forced. */
- polarity = ((phy_data & IFE_PSC_FORCE_POLARITY) >>
- IFE_PSC_FORCE_POLARITY_SHIFT) ?
- e1000_rev_polarity_reversed : e1000_rev_polarity_normal;
- }
- phy_info->cable_polarity = polarity;
-
- ret_val = e1000_read_phy_reg(hw, IFE_PHY_MDIX_CONTROL, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_info->mdix_mode = (e1000_auto_x_mode)
- ((phy_data & (IFE_PMC_AUTO_MDIX | IFE_PMC_FORCE_MDIX)) >>
- IFE_PMC_MDIX_MODE_SHIFT);
-
- return E1000_SUCCESS;
+ DEBUGOUT("Unable to establish link!!!\n");
+ return E1000_SUCCESS;
}
-/******************************************************************************
-* Get PHY information from various PHY registers fot m88 PHY only.
-*
-* hw - Struct containing variables accessed by shared code
-* phy_info - PHY information structure
-******************************************************************************/
-static s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
- struct e1000_phy_info *phy_info)
+/**
+ * e1000_phy_setup_autoneg - phy settings
+ * @hw: Struct containing variables accessed by shared code
+ *
+ * Configures PHY autoneg and flow control advertisement settings
+ */
+s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
{
- s32 ret_val;
- u16 phy_data;
- e1000_rev_polarity polarity;
-
- DEBUGFUNC("e1000_phy_m88_get_info");
-
- /* The downshift status is checked only once, after link is established,
- * and it stored in the hw->speed_downgraded parameter. */
- phy_info->downshift = (e1000_downshift)hw->speed_downgraded;
-
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_info->extended_10bt_distance =
- ((phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >>
- M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT) ?
- e1000_10bt_ext_dist_enable_lower : e1000_10bt_ext_dist_enable_normal;
-
- phy_info->polarity_correction =
- ((phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >>
- M88E1000_PSCR_POLARITY_REVERSAL_SHIFT) ?
- e1000_polarity_reversal_disabled : e1000_polarity_reversal_enabled;
-
- /* Check polarity status */
- ret_val = e1000_check_polarity(hw, &polarity);
- if (ret_val)
- return ret_val;
- phy_info->cable_polarity = polarity;
-
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_info->mdix_mode = (e1000_auto_x_mode)((phy_data & M88E1000_PSSR_MDIX) >>
- M88E1000_PSSR_MDIX_SHIFT);
-
- if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
- /* Cable Length Estimation and Local/Remote Receiver Information
- * are only valid at 1000 Mbps.
- */
- if (hw->phy_type != e1000_phy_gg82563) {
- phy_info->cable_length = (e1000_cable_length)((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
- M88E1000_PSSR_CABLE_LENGTH_SHIFT);
- } else {
- ret_val = e1000_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_info->cable_length = (e1000_cable_length)(phy_data & GG82563_DSPD_CABLE_LENGTH);
- }
-
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >>
- SR_1000T_LOCAL_RX_STATUS_SHIFT) ?
- e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
- phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >>
- SR_1000T_REMOTE_RX_STATUS_SHIFT) ?
- e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
-
- }
-
- return E1000_SUCCESS;
-}
+ s32 ret_val;
+ u16 mii_autoneg_adv_reg;
+ u16 mii_1000t_ctrl_reg;
-/******************************************************************************
-* Get PHY information from various PHY registers
-*
-* hw - Struct containing variables accessed by shared code
-* phy_info - PHY information structure
-******************************************************************************/
-s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info)
-{
- s32 ret_val;
- u16 phy_data;
-
- DEBUGFUNC("e1000_phy_get_info");
-
- phy_info->cable_length = e1000_cable_length_undefined;
- phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_undefined;
- phy_info->cable_polarity = e1000_rev_polarity_undefined;
- phy_info->downshift = e1000_downshift_undefined;
- phy_info->polarity_correction = e1000_polarity_reversal_undefined;
- phy_info->mdix_mode = e1000_auto_x_mode_undefined;
- phy_info->local_rx = e1000_1000t_rx_status_undefined;
- phy_info->remote_rx = e1000_1000t_rx_status_undefined;
-
- if (hw->media_type != e1000_media_type_copper) {
- DEBUGOUT("PHY info is only valid for copper media\n");
- return -E1000_ERR_CONFIG;
- }
-
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
- if (ret_val)
- return ret_val;
-
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
- if (ret_val)
- return ret_val;
-
- if ((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) {
- DEBUGOUT("PHY info is only valid if link is up\n");
- return -E1000_ERR_CONFIG;
- }
-
- if (hw->phy_type == e1000_phy_igp ||
- hw->phy_type == e1000_phy_igp_3 ||
- hw->phy_type == e1000_phy_igp_2)
- return e1000_phy_igp_get_info(hw, phy_info);
- else if (hw->phy_type == e1000_phy_ife)
- return e1000_phy_ife_get_info(hw, phy_info);
- else
- return e1000_phy_m88_get_info(hw, phy_info);
-}
+ DEBUGFUNC("e1000_phy_setup_autoneg");
-s32 e1000_validate_mdi_setting(struct e1000_hw *hw)
-{
- DEBUGFUNC("e1000_validate_mdi_settings");
-
- if (!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) {
- DEBUGOUT("Invalid MDI setting detected\n");
- hw->mdix = 1;
- return -E1000_ERR_CONFIG;
- }
- return E1000_SUCCESS;
-}
+ /* Read the MII Auto-Neg Advertisement Register (Address 4). */
+ ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
+ if (ret_val)
+ return ret_val;
+ /* Read the MII 1000Base-T Control Register (Address 9). */
+ ret_val =
+ e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
+ if (ret_val)
+ return ret_val;
-/******************************************************************************
- * Sets up eeprom variables in the hw struct. Must be called after mac_type
- * is configured. Additionally, if this is ICH8, the flash controller GbE
- * registers must be mapped, or this will crash.
- *
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-s32 e1000_init_eeprom_params(struct e1000_hw *hw)
-{
- struct e1000_eeprom_info *eeprom = &hw->eeprom;
- u32 eecd = er32(EECD);
- s32 ret_val = E1000_SUCCESS;
- u16 eeprom_size;
-
- DEBUGFUNC("e1000_init_eeprom_params");
-
- switch (hw->mac_type) {
- case e1000_82542_rev2_0:
- case e1000_82542_rev2_1:
- case e1000_82543:
- case e1000_82544:
- eeprom->type = e1000_eeprom_microwire;
- eeprom->word_size = 64;
- eeprom->opcode_bits = 3;
- eeprom->address_bits = 6;
- eeprom->delay_usec = 50;
- eeprom->use_eerd = false;
- eeprom->use_eewr = false;
- break;
- case e1000_82540:
- case e1000_82545:
- case e1000_82545_rev_3:
- case e1000_82546:
- case e1000_82546_rev_3:
- eeprom->type = e1000_eeprom_microwire;
- eeprom->opcode_bits = 3;
- eeprom->delay_usec = 50;
- if (eecd & E1000_EECD_SIZE) {
- eeprom->word_size = 256;
- eeprom->address_bits = 8;
- } else {
- eeprom->word_size = 64;
- eeprom->address_bits = 6;
- }
- eeprom->use_eerd = false;
- eeprom->use_eewr = false;
- break;
- case e1000_82541:
- case e1000_82541_rev_2:
- case e1000_82547:
- case e1000_82547_rev_2:
- if (eecd & E1000_EECD_TYPE) {
- eeprom->type = e1000_eeprom_spi;
- eeprom->opcode_bits = 8;
- eeprom->delay_usec = 1;
- if (eecd & E1000_EECD_ADDR_BITS) {
- eeprom->page_size = 32;
- eeprom->address_bits = 16;
- } else {
- eeprom->page_size = 8;
- eeprom->address_bits = 8;
- }
- } else {
- eeprom->type = e1000_eeprom_microwire;
- eeprom->opcode_bits = 3;
- eeprom->delay_usec = 50;
- if (eecd & E1000_EECD_ADDR_BITS) {
- eeprom->word_size = 256;
- eeprom->address_bits = 8;
- } else {
- eeprom->word_size = 64;
- eeprom->address_bits = 6;
- }
- }
- eeprom->use_eerd = false;
- eeprom->use_eewr = false;
- break;
- case e1000_82571:
- case e1000_82572:
- eeprom->type = e1000_eeprom_spi;
- eeprom->opcode_bits = 8;
- eeprom->delay_usec = 1;
- if (eecd & E1000_EECD_ADDR_BITS) {
- eeprom->page_size = 32;
- eeprom->address_bits = 16;
- } else {
- eeprom->page_size = 8;
- eeprom->address_bits = 8;
- }
- eeprom->use_eerd = false;
- eeprom->use_eewr = false;
- break;
- case e1000_82573:
- eeprom->type = e1000_eeprom_spi;
- eeprom->opcode_bits = 8;
- eeprom->delay_usec = 1;
- if (eecd & E1000_EECD_ADDR_BITS) {
- eeprom->page_size = 32;
- eeprom->address_bits = 16;
- } else {
- eeprom->page_size = 8;
- eeprom->address_bits = 8;
- }
- eeprom->use_eerd = true;
- eeprom->use_eewr = true;
- if (!e1000_is_onboard_nvm_eeprom(hw)) {
- eeprom->type = e1000_eeprom_flash;
- eeprom->word_size = 2048;
-
- /* Ensure that the Autonomous FLASH update bit is cleared due to
- * Flash update issue on parts which use a FLASH for NVM. */
- eecd &= ~E1000_EECD_AUPDEN;
- ew32(EECD, eecd);
- }
- break;
- case e1000_80003es2lan:
- eeprom->type = e1000_eeprom_spi;
- eeprom->opcode_bits = 8;
- eeprom->delay_usec = 1;
- if (eecd & E1000_EECD_ADDR_BITS) {
- eeprom->page_size = 32;
- eeprom->address_bits = 16;
- } else {
- eeprom->page_size = 8;
- eeprom->address_bits = 8;
- }
- eeprom->use_eerd = true;
- eeprom->use_eewr = false;
- break;
- case e1000_ich8lan:
- {
- s32 i = 0;
- u32 flash_size = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_GFPREG);
-
- eeprom->type = e1000_eeprom_ich8;
- eeprom->use_eerd = false;
- eeprom->use_eewr = false;
- eeprom->word_size = E1000_SHADOW_RAM_WORDS;
-
- /* Zero the shadow RAM structure. But don't load it from NVM
- * so as to save time for driver init */
- if (hw->eeprom_shadow_ram != NULL) {
- for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
- hw->eeprom_shadow_ram[i].modified = false;
- hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF;
- }
- }
-
- hw->flash_base_addr = (flash_size & ICH_GFPREG_BASE_MASK) *
- ICH_FLASH_SECTOR_SIZE;
-
- hw->flash_bank_size = ((flash_size >> 16) & ICH_GFPREG_BASE_MASK) + 1;
- hw->flash_bank_size -= (flash_size & ICH_GFPREG_BASE_MASK);
-
- hw->flash_bank_size *= ICH_FLASH_SECTOR_SIZE;
-
- hw->flash_bank_size /= 2 * sizeof(u16);
-
- break;
- }
- default:
- break;
- }
-
- if (eeprom->type == e1000_eeprom_spi) {
- /* eeprom_size will be an enum [0..8] that maps to eeprom sizes 128B to
- * 32KB (incremented by powers of 2).
- */
- if (hw->mac_type <= e1000_82547_rev_2) {
- /* Set to default value for initial eeprom read. */
- eeprom->word_size = 64;
- ret_val = e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size);
- if (ret_val)
- return ret_val;
- eeprom_size = (eeprom_size & EEPROM_SIZE_MASK) >> EEPROM_SIZE_SHIFT;
- /* 256B eeprom size was not supported in earlier hardware, so we
- * bump eeprom_size up one to ensure that "1" (which maps to 256B)
- * is never the result used in the shifting logic below. */
- if (eeprom_size)
- eeprom_size++;
- } else {
- eeprom_size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
- E1000_EECD_SIZE_EX_SHIFT);
- }
-
- eeprom->word_size = 1 << (eeprom_size + EEPROM_WORD_SIZE_SHIFT);
- }
- return ret_val;
-}
+ /* Need to parse both autoneg_advertised and fc and set up
+ * the appropriate PHY registers. First we will parse for
+ * autoneg_advertised software override. Since we can advertise
+ * a plethora of combinations, we need to check each bit
+ * individually.
+ */
-/******************************************************************************
- * Raises the EEPROM's clock input.
- *
- * hw - Struct containing variables accessed by shared code
- * eecd - EECD's current value
- *****************************************************************************/
-static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd)
-{
- /* Raise the clock input to the EEPROM (by setting the SK bit), and then
- * wait <delay> microseconds.
- */
- *eecd = *eecd | E1000_EECD_SK;
- ew32(EECD, *eecd);
- E1000_WRITE_FLUSH();
- udelay(hw->eeprom.delay_usec);
-}
+ /* First we clear all the 10/100 mb speed bits in the Auto-Neg
+ * Advertisement Register (Address 4) and the 1000 mb speed bits in
+ * the 1000Base-T Control Register (Address 9).
+ */
+ mii_autoneg_adv_reg &= ~REG4_SPEED_MASK;
+ mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
-/******************************************************************************
- * Lowers the EEPROM's clock input.
- *
- * hw - Struct containing variables accessed by shared code
- * eecd - EECD's current value
- *****************************************************************************/
-static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd)
-{
- /* Lower the clock input to the EEPROM (by clearing the SK bit), and then
- * wait 50 microseconds.
- */
- *eecd = *eecd & ~E1000_EECD_SK;
- ew32(EECD, *eecd);
- E1000_WRITE_FLUSH();
- udelay(hw->eeprom.delay_usec);
-}
+ DEBUGOUT1("autoneg_advertised %x\n", hw->autoneg_advertised);
-/******************************************************************************
- * Shift data bits out to the EEPROM.
- *
- * hw - Struct containing variables accessed by shared code
- * data - data to send to the EEPROM
- * count - number of bits to shift out
- *****************************************************************************/
-static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count)
-{
- struct e1000_eeprom_info *eeprom = &hw->eeprom;
- u32 eecd;
- u32 mask;
-
- /* We need to shift "count" bits out to the EEPROM. So, value in the
- * "data" parameter will be shifted out to the EEPROM one bit at a time.
- * In order to do this, "data" must be broken down into bits.
- */
- mask = 0x01 << (count - 1);
- eecd = er32(EECD);
- if (eeprom->type == e1000_eeprom_microwire) {
- eecd &= ~E1000_EECD_DO;
- } else if (eeprom->type == e1000_eeprom_spi) {
- eecd |= E1000_EECD_DO;
- }
- do {
- /* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1",
- * and then raising and then lowering the clock (the SK bit controls
- * the clock input to the EEPROM). A "0" is shifted out to the EEPROM
- * by setting "DI" to "0" and then raising and then lowering the clock.
- */
- eecd &= ~E1000_EECD_DI;
-
- if (data & mask)
- eecd |= E1000_EECD_DI;
-
- ew32(EECD, eecd);
- E1000_WRITE_FLUSH();
-
- udelay(eeprom->delay_usec);
-
- e1000_raise_ee_clk(hw, &eecd);
- e1000_lower_ee_clk(hw, &eecd);
-
- mask = mask >> 1;
-
- } while (mask);
-
- /* We leave the "DI" bit set to "0" when we leave this routine. */
- eecd &= ~E1000_EECD_DI;
- ew32(EECD, eecd);
-}
+ /* Do we want to advertise 10 Mb Half Duplex? */
+ if (hw->autoneg_advertised & ADVERTISE_10_HALF) {
+ DEBUGOUT("Advertise 10mb Half duplex\n");
+ mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
+ }
-/******************************************************************************
- * Shift data bits in from the EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count)
-{
- u32 eecd;
- u32 i;
- u16 data;
+ /* Do we want to advertise 10 Mb Full Duplex? */
+ if (hw->autoneg_advertised & ADVERTISE_10_FULL) {
+ DEBUGOUT("Advertise 10mb Full duplex\n");
+ mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
+ }
- /* In order to read a register from the EEPROM, we need to shift 'count'
- * bits in from the EEPROM. Bits are "shifted in" by raising the clock
- * input to the EEPROM (setting the SK bit), and then reading the value of
- * the "DO" bit. During this "shifting in" process the "DI" bit should
- * always be clear.
- */
+ /* Do we want to advertise 100 Mb Half Duplex? */
+ if (hw->autoneg_advertised & ADVERTISE_100_HALF) {
+ DEBUGOUT("Advertise 100mb Half duplex\n");
+ mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
+ }
- eecd = er32(EECD);
+ /* Do we want to advertise 100 Mb Full Duplex? */
+ if (hw->autoneg_advertised & ADVERTISE_100_FULL) {
+ DEBUGOUT("Advertise 100mb Full duplex\n");
+ mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
+ }
- eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
- data = 0;
+ /* We do not allow the Phy to advertise 1000 Mb Half Duplex */
+ if (hw->autoneg_advertised & ADVERTISE_1000_HALF) {
+ DEBUGOUT
+ ("Advertise 1000mb Half duplex requested, request denied!\n");
+ }
- for (i = 0; i < count; i++) {
- data = data << 1;
- e1000_raise_ee_clk(hw, &eecd);
+ /* Do we want to advertise 1000 Mb Full Duplex? */
+ if (hw->autoneg_advertised & ADVERTISE_1000_FULL) {
+ DEBUGOUT("Advertise 1000mb Full duplex\n");
+ mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
+ }
- eecd = er32(EECD);
+ /* Check for a software override of the flow control settings, and
+ * setup the PHY advertisement registers accordingly. If
+ * auto-negotiation is enabled, then software will have to set the
+ * "PAUSE" bits to the correct value in the Auto-Negotiation
+ * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-negotiation.
+ *
+ * The possible values of the "fc" parameter are:
+ * 0: Flow control is completely disabled
+ * 1: Rx flow control is enabled (we can receive pause frames
+ * but not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames
+ * but we do not support receiving pause frames).
+ * 3: Both Rx and TX flow control (symmetric) are enabled.
+ * other: No software override. The flow control configuration
+ * in the EEPROM is used.
+ */
+ switch (hw->fc) {
+ case E1000_FC_NONE: /* 0 */
+ /* Flow control (RX & TX) is completely disabled by a
+ * software over-ride.
+ */
+ mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+ break;
+ case E1000_FC_RX_PAUSE: /* 1 */
+ /* RX Flow control is enabled, and TX Flow control is
+ * disabled, by a software over-ride.
+ */
+ /* Since there really isn't a way to advertise that we are
+ * capable of RX Pause ONLY, we will advertise that we
+ * support both symmetric and asymmetric RX PAUSE. Later
+ * (in e1000_config_fc_after_link_up) we will disable the
+ *hw's ability to send PAUSE frames.
+ */
+ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+ break;
+ case E1000_FC_TX_PAUSE: /* 2 */
+ /* TX Flow control is enabled, and RX Flow control is
+ * disabled, by a software over-ride.
+ */
+ mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
+ mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
+ break;
+ case E1000_FC_FULL: /* 3 */
+ /* Flow control (both RX and TX) is enabled by a software
+ * over-ride.
+ */
+ mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+ break;
+ default:
+ DEBUGOUT("Flow control param set incorrectly\n");
+ return -E1000_ERR_CONFIG;
+ }
- eecd &= ~(E1000_EECD_DI);
- if (eecd & E1000_EECD_DO)
- data |= 1;
+ ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
+ if (ret_val)
+ return ret_val;
- e1000_lower_ee_clk(hw, &eecd);
- }
+ DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
- return data;
-}
+ ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
+ if (ret_val)
+ return ret_val;
-/******************************************************************************
- * Prepares EEPROM for access
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
- * function should be called before issuing a command to the EEPROM.
- *****************************************************************************/
-static s32 e1000_acquire_eeprom(struct e1000_hw *hw)
-{
- struct e1000_eeprom_info *eeprom = &hw->eeprom;
- u32 eecd, i=0;
-
- DEBUGFUNC("e1000_acquire_eeprom");
-
- if (e1000_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM))
- return -E1000_ERR_SWFW_SYNC;
- eecd = er32(EECD);
-
- if (hw->mac_type != e1000_82573) {
- /* Request EEPROM Access */
- if (hw->mac_type > e1000_82544) {
- eecd |= E1000_EECD_REQ;
- ew32(EECD, eecd);
- eecd = er32(EECD);
- while ((!(eecd & E1000_EECD_GNT)) &&
- (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
- i++;
- udelay(5);
- eecd = er32(EECD);
- }
- if (!(eecd & E1000_EECD_GNT)) {
- eecd &= ~E1000_EECD_REQ;
- ew32(EECD, eecd);
- DEBUGOUT("Could not acquire EEPROM grant\n");
- e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
- return -E1000_ERR_EEPROM;
- }
- }
- }
-
- /* Setup EEPROM for Read/Write */
-
- if (eeprom->type == e1000_eeprom_microwire) {
- /* Clear SK and DI */
- eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
- ew32(EECD, eecd);
-
- /* Set CS */
- eecd |= E1000_EECD_CS;
- ew32(EECD, eecd);
- } else if (eeprom->type == e1000_eeprom_spi) {
- /* Clear SK and CS */
- eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
- ew32(EECD, eecd);
- udelay(1);
- }
-
- return E1000_SUCCESS;
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * Returns EEPROM to a "standby" state
+/**
+ * e1000_phy_force_speed_duplex - force link settings
+ * @hw: Struct containing variables accessed by shared code
*
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-static void e1000_standby_eeprom(struct e1000_hw *hw)
+ * Force PHY speed and duplex settings to hw->forced_speed_duplex
+ */
+static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
{
- struct e1000_eeprom_info *eeprom = &hw->eeprom;
- u32 eecd;
-
- eecd = er32(EECD);
-
- if (eeprom->type == e1000_eeprom_microwire) {
- eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
- ew32(EECD, eecd);
- E1000_WRITE_FLUSH();
- udelay(eeprom->delay_usec);
-
- /* Clock high */
- eecd |= E1000_EECD_SK;
- ew32(EECD, eecd);
- E1000_WRITE_FLUSH();
- udelay(eeprom->delay_usec);
-
- /* Select EEPROM */
- eecd |= E1000_EECD_CS;
- ew32(EECD, eecd);
- E1000_WRITE_FLUSH();
- udelay(eeprom->delay_usec);
-
- /* Clock low */
- eecd &= ~E1000_EECD_SK;
- ew32(EECD, eecd);
- E1000_WRITE_FLUSH();
- udelay(eeprom->delay_usec);
- } else if (eeprom->type == e1000_eeprom_spi) {
- /* Toggle CS to flush commands */
- eecd |= E1000_EECD_CS;
- ew32(EECD, eecd);
- E1000_WRITE_FLUSH();
- udelay(eeprom->delay_usec);
- eecd &= ~E1000_EECD_CS;
- ew32(EECD, eecd);
- E1000_WRITE_FLUSH();
- udelay(eeprom->delay_usec);
- }
-}
+ u32 ctrl;
+ s32 ret_val;
+ u16 mii_ctrl_reg;
+ u16 mii_status_reg;
+ u16 phy_data;
+ u16 i;
+
+ DEBUGFUNC("e1000_phy_force_speed_duplex");
+
+ /* Turn off Flow control if we are forcing speed and duplex. */
+ hw->fc = E1000_FC_NONE;
+
+ DEBUGOUT1("hw->fc = %d\n", hw->fc);
+
+ /* Read the Device Control Register. */
+ ctrl = er32(CTRL);
+
+ /* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */
+ ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+ ctrl &= ~(DEVICE_SPEED_MASK);
+
+ /* Clear the Auto Speed Detect Enable bit. */
+ ctrl &= ~E1000_CTRL_ASDE;
+
+ /* Read the MII Control Register. */
+ ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg);
+ if (ret_val)
+ return ret_val;
+
+ /* We need to disable autoneg in order to force link and duplex. */
+
+ mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN;
+
+ /* Are we forcing Full or Half Duplex? */
+ if (hw->forced_speed_duplex == e1000_100_full ||
+ hw->forced_speed_duplex == e1000_10_full) {
+ /* We want to force full duplex so we SET the full duplex bits in the
+ * Device and MII Control Registers.
+ */
+ ctrl |= E1000_CTRL_FD;
+ mii_ctrl_reg |= MII_CR_FULL_DUPLEX;
+ DEBUGOUT("Full Duplex\n");
+ } else {
+ /* We want to force half duplex so we CLEAR the full duplex bits in
+ * the Device and MII Control Registers.
+ */
+ ctrl &= ~E1000_CTRL_FD;
+ mii_ctrl_reg &= ~MII_CR_FULL_DUPLEX;
+ DEBUGOUT("Half Duplex\n");
+ }
-/******************************************************************************
- * Terminates a command by inverting the EEPROM's chip select pin
- *
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-static void e1000_release_eeprom(struct e1000_hw *hw)
-{
- u32 eecd;
+ /* Are we forcing 100Mbps??? */
+ if (hw->forced_speed_duplex == e1000_100_full ||
+ hw->forced_speed_duplex == e1000_100_half) {
+ /* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */
+ ctrl |= E1000_CTRL_SPD_100;
+ mii_ctrl_reg |= MII_CR_SPEED_100;
+ mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10);
+ DEBUGOUT("Forcing 100mb ");
+ } else {
+ /* Set the 10Mb bit and turn off the 1000Mb and 100Mb bits. */
+ ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
+ mii_ctrl_reg |= MII_CR_SPEED_10;
+ mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
+ DEBUGOUT("Forcing 10mb ");
+ }
- DEBUGFUNC("e1000_release_eeprom");
+ e1000_config_collision_dist(hw);
+
+ /* Write the configured values back to the Device Control Reg. */
+ ew32(CTRL, ctrl);
+
+ if (hw->phy_type == e1000_phy_m88) {
+ ret_val =
+ e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
+ * forced whenever speed are duplex are forced.
+ */
+ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+ ret_val =
+ e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+ if (ret_val)
+ return ret_val;
+
+ DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data);
+
+ /* Need to reset the PHY or these changes will be ignored */
+ mii_ctrl_reg |= MII_CR_RESET;
+
+ /* Disable MDI-X support for 10/100 */
+ } else {
+ /* Clear Auto-Crossover to force MDI manually. IGP requires MDI
+ * forced whenever speed or duplex are forced.
+ */
+ ret_val =
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
+ phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
+
+ ret_val =
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
+ if (ret_val)
+ return ret_val;
+ }
- eecd = er32(EECD);
+ /* Write back the modified PHY MII control register. */
+ ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg);
+ if (ret_val)
+ return ret_val;
- if (hw->eeprom.type == e1000_eeprom_spi) {
- eecd |= E1000_EECD_CS; /* Pull CS high */
- eecd &= ~E1000_EECD_SK; /* Lower SCK */
+ udelay(1);
- ew32(EECD, eecd);
+ /* The wait_autoneg_complete flag may be a little misleading here.
+ * Since we are forcing speed and duplex, Auto-Neg is not enabled.
+ * But we do want to delay for a period while forcing only so we
+ * don't generate false No Link messages. So we will wait here
+ * only if the user has set wait_autoneg_complete to 1, which is
+ * the default.
+ */
+ if (hw->wait_autoneg_complete) {
+ /* We will wait for autoneg to complete. */
+ DEBUGOUT("Waiting for forced speed/duplex link.\n");
+ mii_status_reg = 0;
+
+ /* We will wait for autoneg to complete or 4.5 seconds to expire. */
+ for (i = PHY_FORCE_TIME; i > 0; i--) {
+ /* Read the MII Status Register and wait for Auto-Neg Complete bit
+ * to be set.
+ */
+ ret_val =
+ e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+ if (ret_val)
+ return ret_val;
+
+ ret_val =
+ e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+ if (ret_val)
+ return ret_val;
+
+ if (mii_status_reg & MII_SR_LINK_STATUS)
+ break;
+ msleep(100);
+ }
+ if ((i == 0) && (hw->phy_type == e1000_phy_m88)) {
+ /* We didn't get link. Reset the DSP and wait again for link. */
+ ret_val = e1000_phy_reset_dsp(hw);
+ if (ret_val) {
+ DEBUGOUT("Error Resetting PHY DSP\n");
+ return ret_val;
+ }
+ }
+ /* This loop will early-out if the link condition has been met. */
+ for (i = PHY_FORCE_TIME; i > 0; i--) {
+ if (mii_status_reg & MII_SR_LINK_STATUS)
+ break;
+ msleep(100);
+ /* Read the MII Status Register and wait for Auto-Neg Complete bit
+ * to be set.
+ */
+ ret_val =
+ e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+ if (ret_val)
+ return ret_val;
+
+ ret_val =
+ e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+ if (ret_val)
+ return ret_val;
+ }
+ }
- udelay(hw->eeprom.delay_usec);
- } else if (hw->eeprom.type == e1000_eeprom_microwire) {
- /* cleanup eeprom */
+ if (hw->phy_type == e1000_phy_m88) {
+ /* Because we reset the PHY above, we need to re-force TX_CLK in the
+ * Extended PHY Specific Control Register to 25MHz clock. This value
+ * defaults back to a 2.5MHz clock when the PHY is reset.
+ */
+ ret_val =
+ e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data |= M88E1000_EPSCR_TX_CLK_25;
+ ret_val =
+ e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* In addition, because of the s/w reset above, we need to enable CRS on
+ * TX. This must be set for both full and half duplex operation.
+ */
+ ret_val =
+ e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+ ret_val =
+ e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+ if (ret_val)
+ return ret_val;
+
+ if ((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543)
+ && (!hw->autoneg)
+ && (hw->forced_speed_duplex == e1000_10_full
+ || hw->forced_speed_duplex == e1000_10_half)) {
+ ret_val = e1000_polarity_reversal_workaround(hw);
+ if (ret_val)
+ return ret_val;
+ }
+ }
+ return E1000_SUCCESS;
+}
- /* CS on Microwire is active-high */
- eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
+/**
+ * e1000_config_collision_dist - set collision distance register
+ * @hw: Struct containing variables accessed by shared code
+ *
+ * Sets the collision distance in the Transmit Control register.
+ * Link should have been established previously. Reads the speed and duplex
+ * information from the Device Status register.
+ */
+void e1000_config_collision_dist(struct e1000_hw *hw)
+{
+ u32 tctl, coll_dist;
- ew32(EECD, eecd);
+ DEBUGFUNC("e1000_config_collision_dist");
- /* Rising edge of clock */
- eecd |= E1000_EECD_SK;
- ew32(EECD, eecd);
- E1000_WRITE_FLUSH();
- udelay(hw->eeprom.delay_usec);
+ if (hw->mac_type < e1000_82543)
+ coll_dist = E1000_COLLISION_DISTANCE_82542;
+ else
+ coll_dist = E1000_COLLISION_DISTANCE;
- /* Falling edge of clock */
- eecd &= ~E1000_EECD_SK;
- ew32(EECD, eecd);
- E1000_WRITE_FLUSH();
- udelay(hw->eeprom.delay_usec);
- }
+ tctl = er32(TCTL);
- /* Stop requesting EEPROM access */
- if (hw->mac_type > e1000_82544) {
- eecd &= ~E1000_EECD_REQ;
- ew32(EECD, eecd);
- }
+ tctl &= ~E1000_TCTL_COLD;
+ tctl |= coll_dist << E1000_COLD_SHIFT;
- e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
+ ew32(TCTL, tctl);
+ E1000_WRITE_FLUSH();
}
-/******************************************************************************
- * Reads a 16 bit word from the EEPROM.
+/**
+ * e1000_config_mac_to_phy - sync phy and mac settings
+ * @hw: Struct containing variables accessed by shared code
+ * @mii_reg: data to write to the MII control register
*
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw)
+ * Sets MAC speed and duplex settings to reflect the those in the PHY
+ * The contents of the PHY register containing the needed information need to
+ * be passed in.
+ */
+static s32 e1000_config_mac_to_phy(struct e1000_hw *hw)
{
- u16 retry_count = 0;
- u8 spi_stat_reg;
-
- DEBUGFUNC("e1000_spi_eeprom_ready");
-
- /* Read "Status Register" repeatedly until the LSB is cleared. The
- * EEPROM will signal that the command has been completed by clearing
- * bit 0 of the internal status register. If it's not cleared within
- * 5 milliseconds, then error out.
- */
- retry_count = 0;
- do {
- e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI,
- hw->eeprom.opcode_bits);
- spi_stat_reg = (u8)e1000_shift_in_ee_bits(hw, 8);
- if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI))
- break;
-
- udelay(5);
- retry_count += 5;
-
- e1000_standby_eeprom(hw);
- } while (retry_count < EEPROM_MAX_RETRY_SPI);
-
- /* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and
- * only 0-5mSec on 5V devices)
- */
- if (retry_count >= EEPROM_MAX_RETRY_SPI) {
- DEBUGOUT("SPI EEPROM Status error\n");
- return -E1000_ERR_EEPROM;
- }
-
- return E1000_SUCCESS;
-}
+ u32 ctrl;
+ s32 ret_val;
+ u16 phy_data;
-/******************************************************************************
- * Reads a 16 bit word from the EEPROM.
- *
- * hw - Struct containing variables accessed by shared code
- * offset - offset of word in the EEPROM to read
- * data - word read from the EEPROM
- * words - number of words to read
- *****************************************************************************/
-s32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
-{
- s32 ret;
- spin_lock(&e1000_eeprom_lock);
- ret = e1000_do_read_eeprom(hw, offset, words, data);
- spin_unlock(&e1000_eeprom_lock);
- return ret;
-}
+ DEBUGFUNC("e1000_config_mac_to_phy");
-static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
-{
- struct e1000_eeprom_info *eeprom = &hw->eeprom;
- u32 i = 0;
-
- DEBUGFUNC("e1000_read_eeprom");
-
- /* If eeprom is not yet detected, do so now */
- if (eeprom->word_size == 0)
- e1000_init_eeprom_params(hw);
-
- /* A check for invalid values: offset too large, too many words, and not
- * enough words.
- */
- if ((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) ||
- (words == 0)) {
- DEBUGOUT2("\"words\" parameter out of bounds. Words = %d, size = %d\n", offset, eeprom->word_size);
- return -E1000_ERR_EEPROM;
- }
-
- /* EEPROM's that don't use EERD to read require us to bit-bang the SPI
- * directly. In this case, we need to acquire the EEPROM so that
- * FW or other port software does not interrupt.
- */
- if (e1000_is_onboard_nvm_eeprom(hw) && !hw->eeprom.use_eerd) {
- /* Prepare the EEPROM for bit-bang reading */
- if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
- return -E1000_ERR_EEPROM;
- }
-
- /* Eerd register EEPROM access requires no eeprom aquire/release */
- if (eeprom->use_eerd)
- return e1000_read_eeprom_eerd(hw, offset, words, data);
-
- /* ICH EEPROM access is done via the ICH flash controller */
- if (eeprom->type == e1000_eeprom_ich8)
- return e1000_read_eeprom_ich8(hw, offset, words, data);
-
- /* Set up the SPI or Microwire EEPROM for bit-bang reading. We have
- * acquired the EEPROM at this point, so any returns should relase it */
- if (eeprom->type == e1000_eeprom_spi) {
- u16 word_in;
- u8 read_opcode = EEPROM_READ_OPCODE_SPI;
-
- if (e1000_spi_eeprom_ready(hw)) {
- e1000_release_eeprom(hw);
- return -E1000_ERR_EEPROM;
- }
-
- e1000_standby_eeprom(hw);
-
- /* Some SPI eeproms use the 8th address bit embedded in the opcode */
- if ((eeprom->address_bits == 8) && (offset >= 128))
- read_opcode |= EEPROM_A8_OPCODE_SPI;
-
- /* Send the READ command (opcode + addr) */
- e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits);
- e1000_shift_out_ee_bits(hw, (u16)(offset*2), eeprom->address_bits);
-
- /* Read the data. The address of the eeprom internally increments with
- * each byte (spi) being read, saving on the overhead of eeprom setup
- * and tear-down. The address counter will roll over if reading beyond
- * the size of the eeprom, thus allowing the entire memory to be read
- * starting from any offset. */
- for (i = 0; i < words; i++) {
- word_in = e1000_shift_in_ee_bits(hw, 16);
- data[i] = (word_in >> 8) | (word_in << 8);
- }
- } else if (eeprom->type == e1000_eeprom_microwire) {
- for (i = 0; i < words; i++) {
- /* Send the READ command (opcode + addr) */
- e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE,
- eeprom->opcode_bits);
- e1000_shift_out_ee_bits(hw, (u16)(offset + i),
- eeprom->address_bits);
-
- /* Read the data. For microwire, each word requires the overhead
- * of eeprom setup and tear-down. */
- data[i] = e1000_shift_in_ee_bits(hw, 16);
- e1000_standby_eeprom(hw);
- }
- }
-
- /* End this read operation */
- e1000_release_eeprom(hw);
-
- return E1000_SUCCESS;
-}
+ /* 82544 or newer MAC, Auto Speed Detection takes care of
+ * MAC speed/duplex configuration.*/
+ if (hw->mac_type >= e1000_82544)
+ return E1000_SUCCESS;
-/******************************************************************************
- * Reads a 16 bit word from the EEPROM using the EERD register.
- *
- * hw - Struct containing variables accessed by shared code
- * offset - offset of word in the EEPROM to read
- * data - word read from the EEPROM
- * words - number of words to read
- *****************************************************************************/
-static s32 e1000_read_eeprom_eerd(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
-{
- u32 i, eerd = 0;
- s32 error = 0;
+ /* Read the Device Control Register and set the bits to Force Speed
+ * and Duplex.
+ */
+ ctrl = er32(CTRL);
+ ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+ ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
- for (i = 0; i < words; i++) {
- eerd = ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) +
- E1000_EEPROM_RW_REG_START;
+ /* Set up duplex in the Device Control and Transmit Control
+ * registers depending on negotiated values.
+ */
+ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+ if (ret_val)
+ return ret_val;
- ew32(EERD, eerd);
- error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ);
+ if (phy_data & M88E1000_PSSR_DPLX)
+ ctrl |= E1000_CTRL_FD;
+ else
+ ctrl &= ~E1000_CTRL_FD;
- if (error) {
- break;
- }
- data[i] = (er32(EERD) >> E1000_EEPROM_RW_REG_DATA);
+ e1000_config_collision_dist(hw);
- }
+ /* Set up speed in the Device Control register depending on
+ * negotiated values.
+ */
+ if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
+ ctrl |= E1000_CTRL_SPD_1000;
+ else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
+ ctrl |= E1000_CTRL_SPD_100;
- return error;
+ /* Write the configured values back to the Device Control Reg. */
+ ew32(CTRL, ctrl);
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * Writes a 16 bit word from the EEPROM using the EEWR register.
+/**
+ * e1000_force_mac_fc - force flow control settings
+ * @hw: Struct containing variables accessed by shared code
*
- * hw - Struct containing variables accessed by shared code
- * offset - offset of word in the EEPROM to read
- * data - word read from the EEPROM
- * words - number of words to read
- *****************************************************************************/
-static s32 e1000_write_eeprom_eewr(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
+ * Forces the MAC's flow control settings.
+ * Sets the TFCE and RFCE bits in the device control register to reflect
+ * the adapter settings. TFCE and RFCE need to be explicitly set by
+ * software when a Copper PHY is used because autonegotiation is managed
+ * by the PHY rather than the MAC. Software must also configure these
+ * bits when link is forced on a fiber connection.
+ */
+s32 e1000_force_mac_fc(struct e1000_hw *hw)
{
- u32 register_value = 0;
- u32 i = 0;
- s32 error = 0;
+ u32 ctrl;
+
+ DEBUGFUNC("e1000_force_mac_fc");
+
+ /* Get the current configuration of the Device Control Register */
+ ctrl = er32(CTRL);
+
+ /* Because we didn't get link via the internal auto-negotiation
+ * mechanism (we either forced link or we got link via PHY
+ * auto-neg), we have to manually enable/disable transmit an
+ * receive flow control.
+ *
+ * The "Case" statement below enables/disable flow control
+ * according to the "hw->fc" parameter.
+ *
+ * The possible values of the "fc" parameter are:
+ * 0: Flow control is completely disabled
+ * 1: Rx flow control is enabled (we can receive pause
+ * frames but not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames
+ * frames but we do not receive pause frames).
+ * 3: Both Rx and TX flow control (symmetric) is enabled.
+ * other: No other values should be possible at this point.
+ */
- if (e1000_swfw_sync_acquire(hw, E1000_SWFW_EEP_SM))
- return -E1000_ERR_SWFW_SYNC;
+ switch (hw->fc) {
+ case E1000_FC_NONE:
+ ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
+ break;
+ case E1000_FC_RX_PAUSE:
+ ctrl &= (~E1000_CTRL_TFCE);
+ ctrl |= E1000_CTRL_RFCE;
+ break;
+ case E1000_FC_TX_PAUSE:
+ ctrl &= (~E1000_CTRL_RFCE);
+ ctrl |= E1000_CTRL_TFCE;
+ break;
+ case E1000_FC_FULL:
+ ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
+ break;
+ default:
+ DEBUGOUT("Flow control param set incorrectly\n");
+ return -E1000_ERR_CONFIG;
+ }
- for (i = 0; i < words; i++) {
- register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) |
- ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) |
- E1000_EEPROM_RW_REG_START;
+ /* Disable TX Flow Control for 82542 (rev 2.0) */
+ if (hw->mac_type == e1000_82542_rev2_0)
+ ctrl &= (~E1000_CTRL_TFCE);
- error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
- if (error) {
- break;
- }
+ ew32(CTRL, ctrl);
+ return E1000_SUCCESS;
+}
- ew32(EEWR, register_value);
+/**
+ * e1000_config_fc_after_link_up - configure flow control after autoneg
+ * @hw: Struct containing variables accessed by shared code
+ *
+ * Configures flow control settings after link is established
+ * Should be called immediately after a valid link has been established.
+ * Forces MAC flow control settings if link was forced. When in MII/GMII mode
+ * and autonegotiation is enabled, the MAC flow control settings will be set
+ * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
+ * and RFCE bits will be automatically set to the negotiated flow control mode.
+ */
+static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw)
+{
+ s32 ret_val;
+ u16 mii_status_reg;
+ u16 mii_nway_adv_reg;
+ u16 mii_nway_lp_ability_reg;
+ u16 speed;
+ u16 duplex;
- error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
+ DEBUGFUNC("e1000_config_fc_after_link_up");
- if (error) {
- break;
- }
- }
+ /* Check for the case where we have fiber media and auto-neg failed
+ * so we had to force link. In this case, we need to force the
+ * configuration of the MAC to match the "fc" parameter.
+ */
+ if (((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed))
+ || ((hw->media_type == e1000_media_type_internal_serdes)
+ && (hw->autoneg_failed))
+ || ((hw->media_type == e1000_media_type_copper)
+ && (!hw->autoneg))) {
+ ret_val = e1000_force_mac_fc(hw);
+ if (ret_val) {
+ DEBUGOUT("Error forcing flow control settings\n");
+ return ret_val;
+ }
+ }
- e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
- return error;
+ /* Check for the case where we have copper media and auto-neg is
+ * enabled. In this case, we need to check and see if Auto-Neg
+ * has completed, and if so, how the PHY and link partner has
+ * flow control configured.
+ */
+ if ((hw->media_type == e1000_media_type_copper) && hw->autoneg) {
+ /* Read the MII Status Register and check to see if AutoNeg
+ * has completed. We read this twice because this reg has
+ * some "sticky" (latched) bits.
+ */
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+ if (ret_val)
+ return ret_val;
+
+ if (mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
+ /* The AutoNeg process has completed, so we now need to
+ * read both the Auto Negotiation Advertisement Register
+ * (Address 4) and the Auto_Negotiation Base Page Ability
+ * Register (Address 5) to determine how flow control was
+ * negotiated.
+ */
+ ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
+ &mii_nway_adv_reg);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
+ &mii_nway_lp_ability_reg);
+ if (ret_val)
+ return ret_val;
+
+ /* Two bits in the Auto Negotiation Advertisement Register
+ * (Address 4) and two bits in the Auto Negotiation Base
+ * Page Ability Register (Address 5) determine flow control
+ * for both the PHY and the link partner. The following
+ * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
+ * 1999, describes these PAUSE resolution bits and how flow
+ * control is determined based upon these settings.
+ * NOTE: DC = Don't Care
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
+ *-------|---------|-------|---------|--------------------
+ * 0 | 0 | DC | DC | E1000_FC_NONE
+ * 0 | 1 | 0 | DC | E1000_FC_NONE
+ * 0 | 1 | 1 | 0 | E1000_FC_NONE
+ * 0 | 1 | 1 | 1 | E1000_FC_TX_PAUSE
+ * 1 | 0 | 0 | DC | E1000_FC_NONE
+ * 1 | DC | 1 | DC | E1000_FC_FULL
+ * 1 | 1 | 0 | 0 | E1000_FC_NONE
+ * 1 | 1 | 0 | 1 | E1000_FC_RX_PAUSE
+ *
+ */
+ /* Are both PAUSE bits set to 1? If so, this implies
+ * Symmetric Flow Control is enabled at both ends. The
+ * ASM_DIR bits are irrelevant per the spec.
+ *
+ * For Symmetric Flow Control:
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+ *-------|---------|-------|---------|--------------------
+ * 1 | DC | 1 | DC | E1000_FC_FULL
+ *
+ */
+ if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
+ /* Now we need to check if the user selected RX ONLY
+ * of pause frames. In this case, we had to advertise
+ * FULL flow control because we could not advertise RX
+ * ONLY. Hence, we must now check to see if we need to
+ * turn OFF the TRANSMISSION of PAUSE frames.
+ */
+ if (hw->original_fc == E1000_FC_FULL) {
+ hw->fc = E1000_FC_FULL;
+ DEBUGOUT("Flow Control = FULL.\n");
+ } else {
+ hw->fc = E1000_FC_RX_PAUSE;
+ DEBUGOUT
+ ("Flow Control = RX PAUSE frames only.\n");
+ }
+ }
+ /* For receiving PAUSE frames ONLY.
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+ *-------|---------|-------|---------|--------------------
+ * 0 | 1 | 1 | 1 | E1000_FC_TX_PAUSE
+ *
+ */
+ else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+ (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR))
+ {
+ hw->fc = E1000_FC_TX_PAUSE;
+ DEBUGOUT
+ ("Flow Control = TX PAUSE frames only.\n");
+ }
+ /* For transmitting PAUSE frames ONLY.
+ *
+ * LOCAL DEVICE | LINK PARTNER
+ * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+ *-------|---------|-------|---------|--------------------
+ * 1 | 1 | 0 | 1 | E1000_FC_RX_PAUSE
+ *
+ */
+ else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+ (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+ !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+ (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR))
+ {
+ hw->fc = E1000_FC_RX_PAUSE;
+ DEBUGOUT
+ ("Flow Control = RX PAUSE frames only.\n");
+ }
+ /* Per the IEEE spec, at this point flow control should be
+ * disabled. However, we want to consider that we could
+ * be connected to a legacy switch that doesn't advertise
+ * desired flow control, but can be forced on the link
+ * partner. So if we advertised no flow control, that is
+ * what we will resolve to. If we advertised some kind of
+ * receive capability (Rx Pause Only or Full Flow Control)
+ * and the link partner advertised none, we will configure
+ * ourselves to enable Rx Flow Control only. We can do
+ * this safely for two reasons: If the link partner really
+ * didn't want flow control enabled, and we enable Rx, no
+ * harm done since we won't be receiving any PAUSE frames
+ * anyway. If the intent on the link partner was to have
+ * flow control enabled, then by us enabling RX only, we
+ * can at least receive pause frames and process them.
+ * This is a good idea because in most cases, since we are
+ * predominantly a server NIC, more times than not we will
+ * be asked to delay transmission of packets than asking
+ * our link partner to pause transmission of frames.
+ */
+ else if ((hw->original_fc == E1000_FC_NONE ||
+ hw->original_fc == E1000_FC_TX_PAUSE) ||
+ hw->fc_strict_ieee) {
+ hw->fc = E1000_FC_NONE;
+ DEBUGOUT("Flow Control = NONE.\n");
+ } else {
+ hw->fc = E1000_FC_RX_PAUSE;
+ DEBUGOUT
+ ("Flow Control = RX PAUSE frames only.\n");
+ }
+
+ /* Now we need to do one last check... If we auto-
+ * negotiated to HALF DUPLEX, flow control should not be
+ * enabled per IEEE 802.3 spec.
+ */
+ ret_val =
+ e1000_get_speed_and_duplex(hw, &speed, &duplex);
+ if (ret_val) {
+ DEBUGOUT
+ ("Error getting link speed and duplex\n");
+ return ret_val;
+ }
+
+ if (duplex == HALF_DUPLEX)
+ hw->fc = E1000_FC_NONE;
+
+ /* Now we call a subroutine to actually force the MAC
+ * controller to use the correct flow control settings.
+ */
+ ret_val = e1000_force_mac_fc(hw);
+ if (ret_val) {
+ DEBUGOUT
+ ("Error forcing flow control settings\n");
+ return ret_val;
+ }
+ } else {
+ DEBUGOUT
+ ("Copper PHY and Auto Neg has not completed.\n");
+ }
+ }
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * Polls the status bit (bit 1) of the EERD to determine when the read is done.
+/**
+ * e1000_check_for_serdes_link_generic - Check for link (Serdes)
+ * @hw: pointer to the HW structure
*
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-static s32 e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
+ * Checks for link up on the hardware. If link is not up and we have
+ * a signal, then we need to force link up.
+ */
+static s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
{
- u32 attempts = 100000;
- u32 i, reg = 0;
- s32 done = E1000_ERR_EEPROM;
-
- for (i = 0; i < attempts; i++) {
- if (eerd == E1000_EEPROM_POLL_READ)
- reg = er32(EERD);
- else
- reg = er32(EEWR);
-
- if (reg & E1000_EEPROM_RW_REG_DONE) {
- done = E1000_SUCCESS;
- break;
- }
- udelay(5);
- }
-
- return done;
-}
+ u32 rxcw;
+ u32 ctrl;
+ u32 status;
+ s32 ret_val = E1000_SUCCESS;
-/***************************************************************************
-* Description: Determines if the onboard NVM is FLASH or EEPROM.
-*
-* hw - Struct containing variables accessed by shared code
-****************************************************************************/
-static bool e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
-{
- u32 eecd = 0;
+ DEBUGFUNC("e1000_check_for_serdes_link_generic");
+
+ ctrl = er32(CTRL);
+ status = er32(STATUS);
+ rxcw = er32(RXCW);
- DEBUGFUNC("e1000_is_onboard_nvm_eeprom");
+ /*
+ * If we don't have link (auto-negotiation failed or link partner
+ * cannot auto-negotiate), and our link partner is not trying to
+ * auto-negotiate with us (we are receiving idles or data),
+ * we need to force link up. We also need to give auto-negotiation
+ * time to complete.
+ */
+ /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
+ if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
+ if (hw->autoneg_failed == 0) {
+ hw->autoneg_failed = 1;
+ goto out;
+ }
+ DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
- if (hw->mac_type == e1000_ich8lan)
- return false;
+ /* Disable auto-negotiation in the TXCW register */
+ ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE));
- if (hw->mac_type == e1000_82573) {
- eecd = er32(EECD);
+ /* Force link-up and also force full-duplex. */
+ ctrl = er32(CTRL);
+ ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
+ ew32(CTRL, ctrl);
+
+ /* Configure Flow Control after forcing link up. */
+ ret_val = e1000_config_fc_after_link_up(hw);
+ if (ret_val) {
+ DEBUGOUT("Error configuring flow control\n");
+ goto out;
+ }
+ } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
+ /*
+ * If we are forcing link and we are receiving /C/ ordered
+ * sets, re-enable auto-negotiation in the TXCW register
+ * and disable forced link in the Device Control register
+ * in an attempt to auto-negotiate with our link partner.
+ */
+ DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
+ ew32(TXCW, hw->txcw);
+ ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
+
+ hw->serdes_has_link = true;
+ } else if (!(E1000_TXCW_ANE & er32(TXCW))) {
+ /*
+ * If we force link for non-auto-negotiation switch, check
+ * link status based on MAC synchronization for internal
+ * serdes media type.
+ */
+ /* SYNCH bit and IV bit are sticky. */
+ udelay(10);
+ rxcw = er32(RXCW);
+ if (rxcw & E1000_RXCW_SYNCH) {
+ if (!(rxcw & E1000_RXCW_IV)) {
+ hw->serdes_has_link = true;
+ DEBUGOUT("SERDES: Link up - forced.\n");
+ }
+ } else {
+ hw->serdes_has_link = false;
+ DEBUGOUT("SERDES: Link down - force failed.\n");
+ }
+ }
- /* Isolate bits 15 & 16 */
- eecd = ((eecd >> 15) & 0x03);
+ if (E1000_TXCW_ANE & er32(TXCW)) {
+ status = er32(STATUS);
+ if (status & E1000_STATUS_LU) {
+ /* SYNCH bit and IV bit are sticky, so reread rxcw. */
+ udelay(10);
+ rxcw = er32(RXCW);
+ if (rxcw & E1000_RXCW_SYNCH) {
+ if (!(rxcw & E1000_RXCW_IV)) {
+ hw->serdes_has_link = true;
+ DEBUGOUT("SERDES: Link up - autoneg "
+ "completed successfully.\n");
+ } else {
+ hw->serdes_has_link = false;
+ DEBUGOUT("SERDES: Link down - invalid"
+ "codewords detected in autoneg.\n");
+ }
+ } else {
+ hw->serdes_has_link = false;
+ DEBUGOUT("SERDES: Link down - no sync.\n");
+ }
+ } else {
+ hw->serdes_has_link = false;
+ DEBUGOUT("SERDES: Link down - autoneg failed\n");
+ }
+ }
- /* If both bits are set, device is Flash type */
- if (eecd == 0x03) {
- return false;
- }
- }
- return true;
+ out:
+ return ret_val;
}
-/******************************************************************************
- * Verifies that the EEPROM has a valid checksum
+/**
+ * e1000_check_for_link
+ * @hw: Struct containing variables accessed by shared code
*
- * hw - Struct containing variables accessed by shared code
- *
- * Reads the first 64 16 bit words of the EEPROM and sums the values read.
- * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
- * valid.
- *****************************************************************************/
-s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw)
+ * Checks to see if the link status of the hardware has changed.
+ * Called by any function that needs to check the link status of the adapter.
+ */
+s32 e1000_check_for_link(struct e1000_hw *hw)
{
- u16 checksum = 0;
- u16 i, eeprom_data;
-
- DEBUGFUNC("e1000_validate_eeprom_checksum");
-
- if ((hw->mac_type == e1000_82573) && !e1000_is_onboard_nvm_eeprom(hw)) {
- /* Check bit 4 of word 10h. If it is 0, firmware is done updating
- * 10h-12h. Checksum may need to be fixed. */
- e1000_read_eeprom(hw, 0x10, 1, &eeprom_data);
- if ((eeprom_data & 0x10) == 0) {
- /* Read 0x23 and check bit 15. This bit is a 1 when the checksum
- * has already been fixed. If the checksum is still wrong and this
- * bit is a 1, we need to return bad checksum. Otherwise, we need
- * to set this bit to a 1 and update the checksum. */
- e1000_read_eeprom(hw, 0x23, 1, &eeprom_data);
- if ((eeprom_data & 0x8000) == 0) {
- eeprom_data |= 0x8000;
- e1000_write_eeprom(hw, 0x23, 1, &eeprom_data);
- e1000_update_eeprom_checksum(hw);
- }
- }
- }
-
- if (hw->mac_type == e1000_ich8lan) {
- /* Drivers must allocate the shadow ram structure for the
- * EEPROM checksum to be updated. Otherwise, this bit as well
- * as the checksum must both be set correctly for this
- * validation to pass.
- */
- e1000_read_eeprom(hw, 0x19, 1, &eeprom_data);
- if ((eeprom_data & 0x40) == 0) {
- eeprom_data |= 0x40;
- e1000_write_eeprom(hw, 0x19, 1, &eeprom_data);
- e1000_update_eeprom_checksum(hw);
- }
- }
-
- for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
- if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
- DEBUGOUT("EEPROM Read Error\n");
- return -E1000_ERR_EEPROM;
- }
- checksum += eeprom_data;
- }
-
- if (checksum == (u16)EEPROM_SUM)
- return E1000_SUCCESS;
- else {
- DEBUGOUT("EEPROM Checksum Invalid\n");
- return -E1000_ERR_EEPROM;
- }
+ u32 rxcw = 0;
+ u32 ctrl;
+ u32 status;
+ u32 rctl;
+ u32 icr;
+ u32 signal = 0;
+ s32 ret_val;
+ u16 phy_data;
+
+ DEBUGFUNC("e1000_check_for_link");
+
+ ctrl = er32(CTRL);
+ status = er32(STATUS);
+
+ /* On adapters with a MAC newer than 82544, SW Definable pin 1 will be
+ * set when the optics detect a signal. On older adapters, it will be
+ * cleared when there is a signal. This applies to fiber media only.
+ */
+ if ((hw->media_type == e1000_media_type_fiber) ||
+ (hw->media_type == e1000_media_type_internal_serdes)) {
+ rxcw = er32(RXCW);
+
+ if (hw->media_type == e1000_media_type_fiber) {
+ signal =
+ (hw->mac_type >
+ e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
+ if (status & E1000_STATUS_LU)
+ hw->get_link_status = false;
+ }
+ }
+
+ /* If we have a copper PHY then we only want to go out to the PHY
+ * registers to see if Auto-Neg has completed and/or if our link
+ * status has changed. The get_link_status flag will be set if we
+ * receive a Link Status Change interrupt or we have Rx Sequence
+ * Errors.
+ */
+ if ((hw->media_type == e1000_media_type_copper) && hw->get_link_status) {
+ /* First we want to see if the MII Status Register reports
+ * link. If so, then we want to get the current speed/duplex
+ * of the PHY.
+ * Read the register twice since the link bit is sticky.
+ */
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ if (phy_data & MII_SR_LINK_STATUS) {
+ hw->get_link_status = false;
+ /* Check if there was DownShift, must be checked immediately after
+ * link-up */
+ e1000_check_downshift(hw);
+
+ /* If we are on 82544 or 82543 silicon and speed/duplex
+ * are forced to 10H or 10F, then we will implement the polarity
+ * reversal workaround. We disable interrupts first, and upon
+ * returning, place the devices interrupt state to its previous
+ * value except for the link status change interrupt which will
+ * happen due to the execution of this workaround.
+ */
+
+ if ((hw->mac_type == e1000_82544
+ || hw->mac_type == e1000_82543) && (!hw->autoneg)
+ && (hw->forced_speed_duplex == e1000_10_full
+ || hw->forced_speed_duplex == e1000_10_half)) {
+ ew32(IMC, 0xffffffff);
+ ret_val =
+ e1000_polarity_reversal_workaround(hw);
+ icr = er32(ICR);
+ ew32(ICS, (icr & ~E1000_ICS_LSC));
+ ew32(IMS, IMS_ENABLE_MASK);
+ }
+
+ } else {
+ /* No link detected */
+ e1000_config_dsp_after_link_change(hw, false);
+ return 0;
+ }
+
+ /* If we are forcing speed/duplex, then we simply return since
+ * we have already determined whether we have link or not.
+ */
+ if (!hw->autoneg)
+ return -E1000_ERR_CONFIG;
+
+ /* optimize the dsp settings for the igp phy */
+ e1000_config_dsp_after_link_change(hw, true);
+
+ /* We have a M88E1000 PHY and Auto-Neg is enabled. If we
+ * have Si on board that is 82544 or newer, Auto
+ * Speed Detection takes care of MAC speed/duplex
+ * configuration. So we only need to configure Collision
+ * Distance in the MAC. Otherwise, we need to force
+ * speed/duplex on the MAC to the current PHY speed/duplex
+ * settings.
+ */
+ if (hw->mac_type >= e1000_82544)
+ e1000_config_collision_dist(hw);
+ else {
+ ret_val = e1000_config_mac_to_phy(hw);
+ if (ret_val) {
+ DEBUGOUT
+ ("Error configuring MAC to PHY settings\n");
+ return ret_val;
+ }
+ }
+
+ /* Configure Flow Control now that Auto-Neg has completed. First, we
+ * need to restore the desired flow control settings because we may
+ * have had to re-autoneg with a different link partner.
+ */
+ ret_val = e1000_config_fc_after_link_up(hw);
+ if (ret_val) {
+ DEBUGOUT("Error configuring flow control\n");
+ return ret_val;
+ }
+
+ /* At this point we know that we are on copper and we have
+ * auto-negotiated link. These are conditions for checking the link
+ * partner capability register. We use the link speed to determine if
+ * TBI compatibility needs to be turned on or off. If the link is not
+ * at gigabit speed, then TBI compatibility is not needed. If we are
+ * at gigabit speed, we turn on TBI compatibility.
+ */
+ if (hw->tbi_compatibility_en) {
+ u16 speed, duplex;
+ ret_val =
+ e1000_get_speed_and_duplex(hw, &speed, &duplex);
+ if (ret_val) {
+ DEBUGOUT
+ ("Error getting link speed and duplex\n");
+ return ret_val;
+ }
+ if (speed != SPEED_1000) {
+ /* If link speed is not set to gigabit speed, we do not need
+ * to enable TBI compatibility.
+ */
+ if (hw->tbi_compatibility_on) {
+ /* If we previously were in the mode, turn it off. */
+ rctl = er32(RCTL);
+ rctl &= ~E1000_RCTL_SBP;
+ ew32(RCTL, rctl);
+ hw->tbi_compatibility_on = false;
+ }
+ } else {
+ /* If TBI compatibility is was previously off, turn it on. For
+ * compatibility with a TBI link partner, we will store bad
+ * packets. Some frames have an additional byte on the end and
+ * will look like CRC errors to to the hardware.
+ */
+ if (!hw->tbi_compatibility_on) {
+ hw->tbi_compatibility_on = true;
+ rctl = er32(RCTL);
+ rctl |= E1000_RCTL_SBP;
+ ew32(RCTL, rctl);
+ }
+ }
+ }
+ }
+
+ if ((hw->media_type == e1000_media_type_fiber) ||
+ (hw->media_type == e1000_media_type_internal_serdes))
+ e1000_check_for_serdes_link_generic(hw);
+
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * Calculates the EEPROM checksum and writes it to the EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- *
- * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
- * Writes the difference to word offset 63 of the EEPROM.
- *****************************************************************************/
-s32 e1000_update_eeprom_checksum(struct e1000_hw *hw)
+/**
+ * e1000_get_speed_and_duplex
+ * @hw: Struct containing variables accessed by shared code
+ * @speed: Speed of the connection
+ * @duplex: Duplex setting of the connection
+
+ * Detects the current speed and duplex settings of the hardware.
+ */
+s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex)
{
- u32 ctrl_ext;
- u16 checksum = 0;
- u16 i, eeprom_data;
-
- DEBUGFUNC("e1000_update_eeprom_checksum");
-
- for (i = 0; i < EEPROM_CHECKSUM_REG; i++) {
- if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
- DEBUGOUT("EEPROM Read Error\n");
- return -E1000_ERR_EEPROM;
- }
- checksum += eeprom_data;
- }
- checksum = (u16)EEPROM_SUM - checksum;
- if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
- DEBUGOUT("EEPROM Write Error\n");
- return -E1000_ERR_EEPROM;
- } else if (hw->eeprom.type == e1000_eeprom_flash) {
- e1000_commit_shadow_ram(hw);
- } else if (hw->eeprom.type == e1000_eeprom_ich8) {
- e1000_commit_shadow_ram(hw);
- /* Reload the EEPROM, or else modifications will not appear
- * until after next adapter reset. */
- ctrl_ext = er32(CTRL_EXT);
- ctrl_ext |= E1000_CTRL_EXT_EE_RST;
- ew32(CTRL_EXT, ctrl_ext);
- msleep(10);
- }
- return E1000_SUCCESS;
+ u32 status;
+ s32 ret_val;
+ u16 phy_data;
+
+ DEBUGFUNC("e1000_get_speed_and_duplex");
+
+ if (hw->mac_type >= e1000_82543) {
+ status = er32(STATUS);
+ if (status & E1000_STATUS_SPEED_1000) {
+ *speed = SPEED_1000;
+ DEBUGOUT("1000 Mbs, ");
+ } else if (status & E1000_STATUS_SPEED_100) {
+ *speed = SPEED_100;
+ DEBUGOUT("100 Mbs, ");
+ } else {
+ *speed = SPEED_10;
+ DEBUGOUT("10 Mbs, ");
+ }
+
+ if (status & E1000_STATUS_FD) {
+ *duplex = FULL_DUPLEX;
+ DEBUGOUT("Full Duplex\n");
+ } else {
+ *duplex = HALF_DUPLEX;
+ DEBUGOUT(" Half Duplex\n");
+ }
+ } else {
+ DEBUGOUT("1000 Mbs, Full Duplex\n");
+ *speed = SPEED_1000;
+ *duplex = FULL_DUPLEX;
+ }
+
+ /* IGP01 PHY may advertise full duplex operation after speed downgrade even
+ * if it is operating at half duplex. Here we set the duplex settings to
+ * match the duplex in the link partner's capabilities.
+ */
+ if (hw->phy_type == e1000_phy_igp && hw->speed_downgraded) {
+ ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ if (!(phy_data & NWAY_ER_LP_NWAY_CAPS))
+ *duplex = HALF_DUPLEX;
+ else {
+ ret_val =
+ e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data);
+ if (ret_val)
+ return ret_val;
+ if ((*speed == SPEED_100
+ && !(phy_data & NWAY_LPAR_100TX_FD_CAPS))
+ || (*speed == SPEED_10
+ && !(phy_data & NWAY_LPAR_10T_FD_CAPS)))
+ *duplex = HALF_DUPLEX;
+ }
+ }
+
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * Parent function for writing words to the different EEPROM types.
- *
- * hw - Struct containing variables accessed by shared code
- * offset - offset within the EEPROM to be written to
- * words - number of words to write
- * data - 16 bit word to be written to the EEPROM
+/**
+ * e1000_wait_autoneg
+ * @hw: Struct containing variables accessed by shared code
*
- * If e1000_update_eeprom_checksum is not called after this function, the
- * EEPROM will most likely contain an invalid checksum.
- *****************************************************************************/
-s32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+ * Blocks until autoneg completes or times out (~4.5 seconds)
+ */
+static s32 e1000_wait_autoneg(struct e1000_hw *hw)
{
- s32 ret;
- spin_lock(&e1000_eeprom_lock);
- ret = e1000_do_write_eeprom(hw, offset, words, data);
- spin_unlock(&e1000_eeprom_lock);
- return ret;
+ s32 ret_val;
+ u16 i;
+ u16 phy_data;
+
+ DEBUGFUNC("e1000_wait_autoneg");
+ DEBUGOUT("Waiting for Auto-Neg to complete.\n");
+
+ /* We will wait for autoneg to complete or 4.5 seconds to expire. */
+ for (i = PHY_AUTO_NEG_TIME; i > 0; i--) {
+ /* Read the MII Status Register and wait for Auto-Neg
+ * Complete bit to be set.
+ */
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+ if (ret_val)
+ return ret_val;
+ if (phy_data & MII_SR_AUTONEG_COMPLETE) {
+ return E1000_SUCCESS;
+ }
+ msleep(100);
+ }
+ return E1000_SUCCESS;
}
+/**
+ * e1000_raise_mdi_clk - Raises the Management Data Clock
+ * @hw: Struct containing variables accessed by shared code
+ * @ctrl: Device control register's current value
+ */
+static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
+{
+ /* Raise the clock input to the Management Data Clock (by setting the MDC
+ * bit), and then delay 10 microseconds.
+ */
+ ew32(CTRL, (*ctrl | E1000_CTRL_MDC));
+ E1000_WRITE_FLUSH();
+ udelay(10);
+}
-static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+/**
+ * e1000_lower_mdi_clk - Lowers the Management Data Clock
+ * @hw: Struct containing variables accessed by shared code
+ * @ctrl: Device control register's current value
+ */
+static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
{
- struct e1000_eeprom_info *eeprom = &hw->eeprom;
- s32 status = 0;
-
- DEBUGFUNC("e1000_write_eeprom");
-
- /* If eeprom is not yet detected, do so now */
- if (eeprom->word_size == 0)
- e1000_init_eeprom_params(hw);
-
- /* A check for invalid values: offset too large, too many words, and not
- * enough words.
- */
- if ((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) ||
- (words == 0)) {
- DEBUGOUT("\"words\" parameter out of bounds\n");
- return -E1000_ERR_EEPROM;
- }
-
- /* 82573 writes only through eewr */
- if (eeprom->use_eewr)
- return e1000_write_eeprom_eewr(hw, offset, words, data);
-
- if (eeprom->type == e1000_eeprom_ich8)
- return e1000_write_eeprom_ich8(hw, offset, words, data);
-
- /* Prepare the EEPROM for writing */
- if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
- return -E1000_ERR_EEPROM;
-
- if (eeprom->type == e1000_eeprom_microwire) {
- status = e1000_write_eeprom_microwire(hw, offset, words, data);
- } else {
- status = e1000_write_eeprom_spi(hw, offset, words, data);
- msleep(10);
- }
-
- /* Done with writing */
- e1000_release_eeprom(hw);
-
- return status;
+ /* Lower the clock input to the Management Data Clock (by clearing the MDC
+ * bit), and then delay 10 microseconds.
+ */
+ ew32(CTRL, (*ctrl & ~E1000_CTRL_MDC));
+ E1000_WRITE_FLUSH();
+ udelay(10);
}
-/******************************************************************************
- * Writes a 16 bit word to a given offset in an SPI EEPROM.
+/**
+ * e1000_shift_out_mdi_bits - Shifts data bits out to the PHY
+ * @hw: Struct containing variables accessed by shared code
+ * @data: Data to send out to the PHY
+ * @count: Number of bits to shift out
*
- * hw - Struct containing variables accessed by shared code
- * offset - offset within the EEPROM to be written to
- * words - number of words to write
- * data - pointer to array of 8 bit words to be written to the EEPROM
- *
- *****************************************************************************/
-static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
+ * Bits are shifted out in MSB to LSB order.
+ */
+static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count)
{
- struct e1000_eeprom_info *eeprom = &hw->eeprom;
- u16 widx = 0;
+ u32 ctrl;
+ u32 mask;
- DEBUGFUNC("e1000_write_eeprom_spi");
+ /* We need to shift "count" number of bits out to the PHY. So, the value
+ * in the "data" parameter will be shifted out to the PHY one bit at a
+ * time. In order to do this, "data" must be broken down into bits.
+ */
+ mask = 0x01;
+ mask <<= (count - 1);
- while (widx < words) {
- u8 write_opcode = EEPROM_WRITE_OPCODE_SPI;
+ ctrl = er32(CTRL);
- if (e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM;
+ /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
+ ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
- e1000_standby_eeprom(hw);
+ while (mask) {
+ /* A "1" is shifted out to the PHY by setting the MDIO bit to "1" and
+ * then raising and lowering the Management Data Clock. A "0" is
+ * shifted out to the PHY by setting the MDIO bit to "0" and then
+ * raising and lowering the clock.
+ */
+ if (data & mask)
+ ctrl |= E1000_CTRL_MDIO;
+ else
+ ctrl &= ~E1000_CTRL_MDIO;
- /* Send the WRITE ENABLE command (8 bit opcode ) */
- e1000_shift_out_ee_bits(hw, EEPROM_WREN_OPCODE_SPI,
- eeprom->opcode_bits);
+ ew32(CTRL, ctrl);
+ E1000_WRITE_FLUSH();
- e1000_standby_eeprom(hw);
+ udelay(10);
- /* Some SPI eeproms use the 8th address bit embedded in the opcode */
- if ((eeprom->address_bits == 8) && (offset >= 128))
- write_opcode |= EEPROM_A8_OPCODE_SPI;
+ e1000_raise_mdi_clk(hw, &ctrl);
+ e1000_lower_mdi_clk(hw, &ctrl);
- /* Send the Write command (8-bit opcode + addr) */
- e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits);
+ mask = mask >> 1;
+ }
+}
- e1000_shift_out_ee_bits(hw, (u16)((offset + widx)*2),
- eeprom->address_bits);
+/**
+ * e1000_shift_in_mdi_bits - Shifts data bits in from the PHY
+ * @hw: Struct containing variables accessed by shared code
+ *
+ * Bits are shifted in in MSB to LSB order.
+ */
+static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw)
+{
+ u32 ctrl;
+ u16 data = 0;
+ u8 i;
- /* Send the data */
+ /* In order to read a register from the PHY, we need to shift in a total
+ * of 18 bits from the PHY. The first two bit (turnaround) times are used
+ * to avoid contention on the MDIO pin when a read operation is performed.
+ * These two bits are ignored by us and thrown away. Bits are "shifted in"
+ * by raising the input to the Management Data Clock (setting the MDC bit),
+ * and then reading the value of the MDIO bit.
+ */
+ ctrl = er32(CTRL);
- /* Loop to allow for up to whole page write (32 bytes) of eeprom */
- while (widx < words) {
- u16 word_out = data[widx];
- word_out = (word_out >> 8) | (word_out << 8);
- e1000_shift_out_ee_bits(hw, word_out, 16);
- widx++;
+ /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */
+ ctrl &= ~E1000_CTRL_MDIO_DIR;
+ ctrl &= ~E1000_CTRL_MDIO;
- /* Some larger eeprom sizes are capable of a 32-byte PAGE WRITE
- * operation, while the smaller eeproms are capable of an 8-byte
- * PAGE WRITE operation. Break the inner loop to pass new address
- */
- if ((((offset + widx)*2) % eeprom->page_size) == 0) {
- e1000_standby_eeprom(hw);
- break;
- }
- }
- }
+ ew32(CTRL, ctrl);
+ E1000_WRITE_FLUSH();
- return E1000_SUCCESS;
-}
+ /* Raise and Lower the clock before reading in the data. This accounts for
+ * the turnaround bits. The first clock occurred when we clocked out the
+ * last bit of the Register Address.
+ */
+ e1000_raise_mdi_clk(hw, &ctrl);
+ e1000_lower_mdi_clk(hw, &ctrl);
+
+ for (data = 0, i = 0; i < 16; i++) {
+ data = data << 1;
+ e1000_raise_mdi_clk(hw, &ctrl);
+ ctrl = er32(CTRL);
+ /* Check to see if we shifted in a "1". */
+ if (ctrl & E1000_CTRL_MDIO)
+ data |= 1;
+ e1000_lower_mdi_clk(hw, &ctrl);
+ }
-/******************************************************************************
- * Writes a 16 bit word to a given offset in a Microwire EEPROM.
- *
- * hw - Struct containing variables accessed by shared code
- * offset - offset within the EEPROM to be written to
- * words - number of words to write
- * data - pointer to array of 16 bit words to be written to the EEPROM
- *
- *****************************************************************************/
-static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
- u16 words, u16 *data)
-{
- struct e1000_eeprom_info *eeprom = &hw->eeprom;
- u32 eecd;
- u16 words_written = 0;
- u16 i = 0;
-
- DEBUGFUNC("e1000_write_eeprom_microwire");
-
- /* Send the write enable command to the EEPROM (3-bit opcode plus
- * 6/8-bit dummy address beginning with 11). It's less work to include
- * the 11 of the dummy address as part of the opcode than it is to shift
- * it over the correct number of bits for the address. This puts the
- * EEPROM into write/erase mode.
- */
- e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE,
- (u16)(eeprom->opcode_bits + 2));
-
- e1000_shift_out_ee_bits(hw, 0, (u16)(eeprom->address_bits - 2));
-
- /* Prepare the EEPROM */
- e1000_standby_eeprom(hw);
-
- while (words_written < words) {
- /* Send the Write command (3-bit opcode + addr) */
- e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE,
- eeprom->opcode_bits);
-
- e1000_shift_out_ee_bits(hw, (u16)(offset + words_written),
- eeprom->address_bits);
-
- /* Send the data */
- e1000_shift_out_ee_bits(hw, data[words_written], 16);
-
- /* Toggle the CS line. This in effect tells the EEPROM to execute
- * the previous command.
- */
- e1000_standby_eeprom(hw);
-
- /* Read DO repeatedly until it is high (equal to '1'). The EEPROM will
- * signal that the command has been completed by raising the DO signal.
- * If DO does not go high in 10 milliseconds, then error out.
- */
- for (i = 0; i < 200; i++) {
- eecd = er32(EECD);
- if (eecd & E1000_EECD_DO) break;
- udelay(50);
- }
- if (i == 200) {
- DEBUGOUT("EEPROM Write did not complete\n");
- return -E1000_ERR_EEPROM;
- }
-
- /* Recover from write */
- e1000_standby_eeprom(hw);
-
- words_written++;
- }
-
- /* Send the write disable command to the EEPROM (3-bit opcode plus
- * 6/8-bit dummy address beginning with 10). It's less work to include
- * the 10 of the dummy address as part of the opcode than it is to shift
- * it over the correct number of bits for the address. This takes the
- * EEPROM out of write/erase mode.
- */
- e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE,
- (u16)(eeprom->opcode_bits + 2));
-
- e1000_shift_out_ee_bits(hw, 0, (u16)(eeprom->address_bits - 2));
-
- return E1000_SUCCESS;
+ e1000_raise_mdi_clk(hw, &ctrl);
+ e1000_lower_mdi_clk(hw, &ctrl);
+
+ return data;
}
-/******************************************************************************
- * Flushes the cached eeprom to NVM. This is done by saving the modified values
- * in the eeprom cache and the non modified values in the currently active bank
- * to the new bank.
+
+/**
+ * e1000_read_phy_reg - read a phy register
+ * @hw: Struct containing variables accessed by shared code
+ * @reg_addr: address of the PHY register to read
*
- * hw - Struct containing variables accessed by shared code
- * offset - offset of word in the EEPROM to read
- * data - word read from the EEPROM
- * words - number of words to read
- *****************************************************************************/
-static s32 e1000_commit_shadow_ram(struct e1000_hw *hw)
+ * Reads the value from a PHY register, if the value is on a specific non zero
+ * page, sets the page first.
+ */
+s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data)
{
- u32 attempts = 100000;
- u32 eecd = 0;
- u32 flop = 0;
- u32 i = 0;
- s32 error = E1000_SUCCESS;
- u32 old_bank_offset = 0;
- u32 new_bank_offset = 0;
- u8 low_byte = 0;
- u8 high_byte = 0;
- bool sector_write_failed = false;
-
- if (hw->mac_type == e1000_82573) {
- /* The flop register will be used to determine if flash type is STM */
- flop = er32(FLOP);
- for (i=0; i < attempts; i++) {
- eecd = er32(EECD);
- if ((eecd & E1000_EECD_FLUPD) == 0) {
- break;
- }
- udelay(5);
- }
-
- if (i == attempts) {
- return -E1000_ERR_EEPROM;
- }
-
- /* If STM opcode located in bits 15:8 of flop, reset firmware */
- if ((flop & 0xFF00) == E1000_STM_OPCODE) {
- ew32(HICR, E1000_HICR_FW_RESET);
- }
-
- /* Perform the flash update */
- ew32(EECD, eecd | E1000_EECD_FLUPD);
-
- for (i=0; i < attempts; i++) {
- eecd = er32(EECD);
- if ((eecd & E1000_EECD_FLUPD) == 0) {
- break;
- }
- udelay(5);
- }
-
- if (i == attempts) {
- return -E1000_ERR_EEPROM;
- }
- }
-
- if (hw->mac_type == e1000_ich8lan && hw->eeprom_shadow_ram != NULL) {
- /* We're writing to the opposite bank so if we're on bank 1,
- * write to bank 0 etc. We also need to erase the segment that
- * is going to be written */
- if (!(er32(EECD) & E1000_EECD_SEC1VAL)) {
- new_bank_offset = hw->flash_bank_size * 2;
- old_bank_offset = 0;
- e1000_erase_ich8_4k_segment(hw, 1);
- } else {
- old_bank_offset = hw->flash_bank_size * 2;
- new_bank_offset = 0;
- e1000_erase_ich8_4k_segment(hw, 0);
- }
-
- sector_write_failed = false;
- /* Loop for every byte in the shadow RAM,
- * which is in units of words. */
- for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
- /* Determine whether to write the value stored
- * in the other NVM bank or a modified value stored
- * in the shadow RAM */
- if (hw->eeprom_shadow_ram[i].modified) {
- low_byte = (u8)hw->eeprom_shadow_ram[i].eeprom_word;
- udelay(100);
- error = e1000_verify_write_ich8_byte(hw,
- (i << 1) + new_bank_offset, low_byte);
-
- if (error != E1000_SUCCESS)
- sector_write_failed = true;
- else {
- high_byte =
- (u8)(hw->eeprom_shadow_ram[i].eeprom_word >> 8);
- udelay(100);
- }
- } else {
- e1000_read_ich8_byte(hw, (i << 1) + old_bank_offset,
- &low_byte);
- udelay(100);
- error = e1000_verify_write_ich8_byte(hw,
- (i << 1) + new_bank_offset, low_byte);
-
- if (error != E1000_SUCCESS)
- sector_write_failed = true;
- else {
- e1000_read_ich8_byte(hw, (i << 1) + old_bank_offset + 1,
- &high_byte);
- udelay(100);
- }
- }
-
- /* If the write of the low byte was successful, go ahead and
- * write the high byte while checking to make sure that if it
- * is the signature byte, then it is handled properly */
- if (!sector_write_failed) {
- /* If the word is 0x13, then make sure the signature bits
- * (15:14) are 11b until the commit has completed.
- * This will allow us to write 10b which indicates the
- * signature is valid. We want to do this after the write
- * has completed so that we don't mark the segment valid
- * while the write is still in progress */
- if (i == E1000_ICH_NVM_SIG_WORD)
- high_byte = E1000_ICH_NVM_SIG_MASK | high_byte;
-
- error = e1000_verify_write_ich8_byte(hw,
- (i << 1) + new_bank_offset + 1, high_byte);
- if (error != E1000_SUCCESS)
- sector_write_failed = true;
-
- } else {
- /* If the write failed then break from the loop and
- * return an error */
- break;
- }
- }
-
- /* Don't bother writing the segment valid bits if sector
- * programming failed. */
- if (!sector_write_failed) {
- /* Finally validate the new segment by setting bit 15:14
- * to 10b in word 0x13 , this can be done without an
- * erase as well since these bits are 11 to start with
- * and we need to change bit 14 to 0b */
- e1000_read_ich8_byte(hw,
- E1000_ICH_NVM_SIG_WORD * 2 + 1 + new_bank_offset,
- &high_byte);
- high_byte &= 0xBF;
- error = e1000_verify_write_ich8_byte(hw,
- E1000_ICH_NVM_SIG_WORD * 2 + 1 + new_bank_offset, high_byte);
- /* And invalidate the previously valid segment by setting
- * its signature word (0x13) high_byte to 0b. This can be
- * done without an erase because flash erase sets all bits
- * to 1's. We can write 1's to 0's without an erase */
- if (error == E1000_SUCCESS) {
- error = e1000_verify_write_ich8_byte(hw,
- E1000_ICH_NVM_SIG_WORD * 2 + 1 + old_bank_offset, 0);
- }
-
- /* Clear the now not used entry in the cache */
- for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
- hw->eeprom_shadow_ram[i].modified = false;
- hw->eeprom_shadow_ram[i].eeprom_word = 0xFFFF;
- }
- }
- }
-
- return error;
+ u32 ret_val;
+
+ DEBUGFUNC("e1000_read_phy_reg");
+
+ if ((hw->phy_type == e1000_phy_igp) &&
+ (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
+ ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
+ (u16) reg_addr);
+ if (ret_val)
+ return ret_val;
+ }
+
+ ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
+ phy_data);
+
+ return ret_val;
}
-/******************************************************************************
- * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
- * second function of dual function devices
- *
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-s32 e1000_read_mac_addr(struct e1000_hw *hw)
+static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
+ u16 *phy_data)
{
- u16 offset;
- u16 eeprom_data, i;
-
- DEBUGFUNC("e1000_read_mac_addr");
-
- for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
- offset = i >> 1;
- if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
- DEBUGOUT("EEPROM Read Error\n");
- return -E1000_ERR_EEPROM;
- }
- hw->perm_mac_addr[i] = (u8)(eeprom_data & 0x00FF);
- hw->perm_mac_addr[i+1] = (u8)(eeprom_data >> 8);
- }
-
- switch (hw->mac_type) {
- default:
- break;
- case e1000_82546:
- case e1000_82546_rev_3:
- case e1000_82571:
- case e1000_80003es2lan:
- if (er32(STATUS) & E1000_STATUS_FUNC_1)
- hw->perm_mac_addr[5] ^= 0x01;
- break;
- }
-
- for (i = 0; i < NODE_ADDRESS_SIZE; i++)
- hw->mac_addr[i] = hw->perm_mac_addr[i];
- return E1000_SUCCESS;
+ u32 i;
+ u32 mdic = 0;
+ const u32 phy_addr = 1;
+
+ DEBUGFUNC("e1000_read_phy_reg_ex");
+
+ if (reg_addr > MAX_PHY_REG_ADDRESS) {
+ DEBUGOUT1("PHY Address %d is out of range\n", reg_addr);
+ return -E1000_ERR_PARAM;
+ }
+
+ if (hw->mac_type > e1000_82543) {
+ /* Set up Op-code, Phy Address, and register address in the MDI
+ * Control register. The MAC will take care of interfacing with the
+ * PHY to retrieve the desired data.
+ */
+ mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
+ (phy_addr << E1000_MDIC_PHY_SHIFT) |
+ (E1000_MDIC_OP_READ));
+
+ ew32(MDIC, mdic);
+
+ /* Poll the ready bit to see if the MDI read completed */
+ for (i = 0; i < 64; i++) {
+ udelay(50);
+ mdic = er32(MDIC);
+ if (mdic & E1000_MDIC_READY)
+ break;
+ }
+ if (!(mdic & E1000_MDIC_READY)) {
+ DEBUGOUT("MDI Read did not complete\n");
+ return -E1000_ERR_PHY;
+ }
+ if (mdic & E1000_MDIC_ERROR) {
+ DEBUGOUT("MDI Error\n");
+ return -E1000_ERR_PHY;
+ }
+ *phy_data = (u16) mdic;
+ } else {
+ /* We must first send a preamble through the MDIO pin to signal the
+ * beginning of an MII instruction. This is done by sending 32
+ * consecutive "1" bits.
+ */
+ e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
+
+ /* Now combine the next few fields that are required for a read
+ * operation. We use this method instead of calling the
+ * e1000_shift_out_mdi_bits routine five different times. The format of
+ * a MII read instruction consists of a shift out of 14 bits and is
+ * defined as follows:
+ * <Preamble><SOF><Op Code><Phy Addr><Reg Addr>
+ * followed by a shift in of 18 bits. This first two bits shifted in
+ * are TurnAround bits used to avoid contention on the MDIO pin when a
+ * READ operation is performed. These two bits are thrown away
+ * followed by a shift in of 16 bits which contains the desired data.
+ */
+ mdic = ((reg_addr) | (phy_addr << 5) |
+ (PHY_OP_READ << 10) | (PHY_SOF << 12));
+
+ e1000_shift_out_mdi_bits(hw, mdic, 14);
+
+ /* Now that we've shifted out the read command to the MII, we need to
+ * "shift in" the 16-bit value (18 total bits) of the requested PHY
+ * register address.
+ */
+ *phy_data = e1000_shift_in_mdi_bits(hw);
+ }
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * Initializes receive address filters.
- *
- * hw - Struct containing variables accessed by shared code
+/**
+ * e1000_write_phy_reg - write a phy register
*
- * Places the MAC address in receive address register 0 and clears the rest
- * of the receive addresss registers. Clears the multicast table. Assumes
- * the receiver is in reset when the routine is called.
- *****************************************************************************/
-static void e1000_init_rx_addrs(struct e1000_hw *hw)
+ * @hw: Struct containing variables accessed by shared code
+ * @reg_addr: address of the PHY register to write
+ * @data: data to write to the PHY
+
+ * Writes a value to a PHY register
+ */
+s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data)
{
- u32 i;
- u32 rar_num;
-
- DEBUGFUNC("e1000_init_rx_addrs");
-
- /* Setup the receive address. */
- DEBUGOUT("Programming MAC Address into RAR[0]\n");
-
- e1000_rar_set(hw, hw->mac_addr, 0);
-
- rar_num = E1000_RAR_ENTRIES;
-
- /* Reserve a spot for the Locally Administered Address to work around
- * an 82571 issue in which a reset on one port will reload the MAC on
- * the other port. */
- if ((hw->mac_type == e1000_82571) && (hw->laa_is_present))
- rar_num -= 1;
- if (hw->mac_type == e1000_ich8lan)
- rar_num = E1000_RAR_ENTRIES_ICH8LAN;
-
- /* Zero out the other 15 receive addresses. */
- DEBUGOUT("Clearing RAR[1-15]\n");
- for (i = 1; i < rar_num; i++) {
- E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
- E1000_WRITE_FLUSH();
- E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
- E1000_WRITE_FLUSH();
- }
+ u32 ret_val;
+
+ DEBUGFUNC("e1000_write_phy_reg");
+
+ if ((hw->phy_type == e1000_phy_igp) &&
+ (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
+ ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
+ (u16) reg_addr);
+ if (ret_val)
+ return ret_val;
+ }
+
+ ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
+ phy_data);
+
+ return ret_val;
}
-/******************************************************************************
- * Hashes an address to determine its location in the multicast table
- *
- * hw - Struct containing variables accessed by shared code
- * mc_addr - the multicast address to hash
- *****************************************************************************/
-u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
+static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
+ u16 phy_data)
{
- u32 hash_value = 0;
-
- /* The portion of the address that is used for the hash table is
- * determined by the mc_filter_type setting.
- */
- switch (hw->mc_filter_type) {
- /* [0] [1] [2] [3] [4] [5]
- * 01 AA 00 12 34 56
- * LSB MSB
- */
- case 0:
- if (hw->mac_type == e1000_ich8lan) {
- /* [47:38] i.e. 0x158 for above example address */
- hash_value = ((mc_addr[4] >> 6) | (((u16)mc_addr[5]) << 2));
- } else {
- /* [47:36] i.e. 0x563 for above example address */
- hash_value = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
- }
- break;
- case 1:
- if (hw->mac_type == e1000_ich8lan) {
- /* [46:37] i.e. 0x2B1 for above example address */
- hash_value = ((mc_addr[4] >> 5) | (((u16)mc_addr[5]) << 3));
- } else {
- /* [46:35] i.e. 0xAC6 for above example address */
- hash_value = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5));
- }
- break;
- case 2:
- if (hw->mac_type == e1000_ich8lan) {
- /*[45:36] i.e. 0x163 for above example address */
- hash_value = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4));
- } else {
- /* [45:34] i.e. 0x5D8 for above example address */
- hash_value = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
- }
- break;
- case 3:
- if (hw->mac_type == e1000_ich8lan) {
- /* [43:34] i.e. 0x18D for above example address */
- hash_value = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6));
- } else {
- /* [43:32] i.e. 0x634 for above example address */
- hash_value = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8));
- }
- break;
- }
-
- hash_value &= 0xFFF;
- if (hw->mac_type == e1000_ich8lan)
- hash_value &= 0x3FF;
-
- return hash_value;
+ u32 i;
+ u32 mdic = 0;
+ const u32 phy_addr = 1;
+
+ DEBUGFUNC("e1000_write_phy_reg_ex");
+
+ if (reg_addr > MAX_PHY_REG_ADDRESS) {
+ DEBUGOUT1("PHY Address %d is out of range\n", reg_addr);
+ return -E1000_ERR_PARAM;
+ }
+
+ if (hw->mac_type > e1000_82543) {
+ /* Set up Op-code, Phy Address, register address, and data intended
+ * for the PHY register in the MDI Control register. The MAC will take
+ * care of interfacing with the PHY to send the desired data.
+ */
+ mdic = (((u32) phy_data) |
+ (reg_addr << E1000_MDIC_REG_SHIFT) |
+ (phy_addr << E1000_MDIC_PHY_SHIFT) |
+ (E1000_MDIC_OP_WRITE));
+
+ ew32(MDIC, mdic);
+
+ /* Poll the ready bit to see if the MDI read completed */
+ for (i = 0; i < 641; i++) {
+ udelay(5);
+ mdic = er32(MDIC);
+ if (mdic & E1000_MDIC_READY)
+ break;
+ }
+ if (!(mdic & E1000_MDIC_READY)) {
+ DEBUGOUT("MDI Write did not complete\n");
+ return -E1000_ERR_PHY;
+ }
+ } else {
+ /* We'll need to use the SW defined pins to shift the write command
+ * out to the PHY. We first send a preamble to the PHY to signal the
+ * beginning of the MII instruction. This is done by sending 32
+ * consecutive "1" bits.
+ */
+ e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
+
+ /* Now combine the remaining required fields that will indicate a
+ * write operation. We use this method instead of calling the
+ * e1000_shift_out_mdi_bits routine for each field in the command. The
+ * format of a MII write instruction is as follows:
+ * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
+ */
+ mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
+ (PHY_OP_WRITE << 12) | (PHY_SOF << 14));
+ mdic <<= 16;
+ mdic |= (u32) phy_data;
+
+ e1000_shift_out_mdi_bits(hw, mdic, 32);
+ }
+
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * Puts an ethernet address into a receive address register.
+/**
+ * e1000_phy_hw_reset - reset the phy, hardware style
+ * @hw: Struct containing variables accessed by shared code
*
- * hw - Struct containing variables accessed by shared code
- * addr - Address to put into receive address register
- * index - Receive address register to write
- *****************************************************************************/
-void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
+ * Returns the PHY to the power-on reset state
+ */
+s32 e1000_phy_hw_reset(struct e1000_hw *hw)
{
- u32 rar_low, rar_high;
-
- /* HW expects these in little endian so we reverse the byte order
- * from network order (big endian) to little endian
- */
- rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) |
- ((u32)addr[2] << 16) | ((u32)addr[3] << 24));
- rar_high = ((u32)addr[4] | ((u32)addr[5] << 8));
-
- /* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx
- * unit hang.
- *
- * Description:
- * If there are any Rx frames queued up or otherwise present in the HW
- * before RSS is enabled, and then we enable RSS, the HW Rx unit will
- * hang. To work around this issue, we have to disable receives and
- * flush out all Rx frames before we enable RSS. To do so, we modify we
- * redirect all Rx traffic to manageability and then reset the HW.
- * This flushes away Rx frames, and (since the redirections to
- * manageability persists across resets) keeps new ones from coming in
- * while we work. Then, we clear the Address Valid AV bit for all MAC
- * addresses and undo the re-direction to manageability.
- * Now, frames are coming in again, but the MAC won't accept them, so
- * far so good. We now proceed to initialize RSS (if necessary) and
- * configure the Rx unit. Last, we re-enable the AV bits and continue
- * on our merry way.
- */
- switch (hw->mac_type) {
- case e1000_82571:
- case e1000_82572:
- case e1000_80003es2lan:
- if (hw->leave_av_bit_off)
- break;
- default:
- /* Indicate to hardware the Address is Valid. */
- rar_high |= E1000_RAH_AV;
- break;
- }
-
- E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
- E1000_WRITE_FLUSH();
- E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
- E1000_WRITE_FLUSH();
+ u32 ctrl, ctrl_ext;
+ u32 led_ctrl;
+ s32 ret_val;
+
+ DEBUGFUNC("e1000_phy_hw_reset");
+
+ DEBUGOUT("Resetting Phy...\n");
+
+ if (hw->mac_type > e1000_82543) {
+ /* Read the device control register and assert the E1000_CTRL_PHY_RST
+ * bit. Then, take it out of reset.
+ * For e1000 hardware, we delay for 10ms between the assert
+ * and deassert.
+ */
+ ctrl = er32(CTRL);
+ ew32(CTRL, ctrl | E1000_CTRL_PHY_RST);
+ E1000_WRITE_FLUSH();
+
+ msleep(10);
+
+ ew32(CTRL, ctrl);
+ E1000_WRITE_FLUSH();
+
+ } else {
+ /* Read the Extended Device Control Register, assert the PHY_RESET_DIR
+ * bit to put the PHY into reset. Then, take it out of reset.
+ */
+ ctrl_ext = er32(CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
+ ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
+ ew32(CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH();
+ msleep(10);
+ ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
+ ew32(CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH();
+ }
+ udelay(150);
+
+ if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
+ /* Configure activity LED after PHY reset */
+ led_ctrl = er32(LEDCTL);
+ led_ctrl &= IGP_ACTIVITY_LED_MASK;
+ led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
+ ew32(LEDCTL, led_ctrl);
+ }
+
+ /* Wait for FW to finish PHY configuration. */
+ ret_val = e1000_get_phy_cfg_done(hw);
+ if (ret_val != E1000_SUCCESS)
+ return ret_val;
+
+ return ret_val;
}
-/******************************************************************************
- * Writes a value to the specified offset in the VLAN filter table.
+/**
+ * e1000_phy_reset - reset the phy to commit settings
+ * @hw: Struct containing variables accessed by shared code
*
- * hw - Struct containing variables accessed by shared code
- * offset - Offset in VLAN filer table to write
- * value - Value to write into VLAN filter table
- *****************************************************************************/
-void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
+ * Resets the PHY
+ * Sets bit 15 of the MII Control register
+ */
+s32 e1000_phy_reset(struct e1000_hw *hw)
{
- u32 temp;
-
- if (hw->mac_type == e1000_ich8lan)
- return;
-
- if ((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) {
- temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1));
- E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
- E1000_WRITE_FLUSH();
- E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp);
- E1000_WRITE_FLUSH();
- } else {
- E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
- E1000_WRITE_FLUSH();
- }
+ s32 ret_val;
+ u16 phy_data;
+
+ DEBUGFUNC("e1000_phy_reset");
+
+ switch (hw->phy_type) {
+ case e1000_phy_igp:
+ ret_val = e1000_phy_hw_reset(hw);
+ if (ret_val)
+ return ret_val;
+ break;
+ default:
+ ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data |= MII_CR_RESET;
+ ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
+ if (ret_val)
+ return ret_val;
+
+ udelay(1);
+ break;
+ }
+
+ if (hw->phy_type == e1000_phy_igp)
+ e1000_phy_init_script(hw);
+
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * Clears the VLAN filer table
+/**
+ * e1000_detect_gig_phy - check the phy type
+ * @hw: Struct containing variables accessed by shared code
*
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-static void e1000_clear_vfta(struct e1000_hw *hw)
+ * Probes the expected PHY address for known PHY IDs
+ */
+static s32 e1000_detect_gig_phy(struct e1000_hw *hw)
{
- u32 offset;
- u32 vfta_value = 0;
- u32 vfta_offset = 0;
- u32 vfta_bit_in_reg = 0;
-
- if (hw->mac_type == e1000_ich8lan)
- return;
-
- if (hw->mac_type == e1000_82573) {
- if (hw->mng_cookie.vlan_id != 0) {
- /* The VFTA is a 4096b bit-field, each identifying a single VLAN
- * ID. The following operations determine which 32b entry
- * (i.e. offset) into the array we want to set the VLAN ID
- * (i.e. bit) of the manageability unit. */
- vfta_offset = (hw->mng_cookie.vlan_id >>
- E1000_VFTA_ENTRY_SHIFT) &
- E1000_VFTA_ENTRY_MASK;
- vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id &
- E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
- }
- }
- for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
- /* If the offset we want to clear is the same offset of the
- * manageability VLAN ID, then clear all bits except that of the
- * manageability unit */
- vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
- E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value);
- E1000_WRITE_FLUSH();
- }
-}
+ s32 phy_init_status, ret_val;
+ u16 phy_id_high, phy_id_low;
+ bool match = false;
-static s32 e1000_id_led_init(struct e1000_hw *hw)
-{
- u32 ledctl;
- const u32 ledctl_mask = 0x000000FF;
- const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON;
- const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
- u16 eeprom_data, i, temp;
- const u16 led_mask = 0x0F;
-
- DEBUGFUNC("e1000_id_led_init");
-
- if (hw->mac_type < e1000_82540) {
- /* Nothing to do */
- return E1000_SUCCESS;
- }
-
- ledctl = er32(LEDCTL);
- hw->ledctl_default = ledctl;
- hw->ledctl_mode1 = hw->ledctl_default;
- hw->ledctl_mode2 = hw->ledctl_default;
-
- if (e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) {
- DEBUGOUT("EEPROM Read Error\n");
- return -E1000_ERR_EEPROM;
- }
-
- if ((hw->mac_type == e1000_82573) &&
- (eeprom_data == ID_LED_RESERVED_82573))
- eeprom_data = ID_LED_DEFAULT_82573;
- else if ((eeprom_data == ID_LED_RESERVED_0000) ||
- (eeprom_data == ID_LED_RESERVED_FFFF)) {
- if (hw->mac_type == e1000_ich8lan)
- eeprom_data = ID_LED_DEFAULT_ICH8LAN;
- else
- eeprom_data = ID_LED_DEFAULT;
- }
-
- for (i = 0; i < 4; i++) {
- temp = (eeprom_data >> (i << 2)) & led_mask;
- switch (temp) {
- case ID_LED_ON1_DEF2:
- case ID_LED_ON1_ON2:
- case ID_LED_ON1_OFF2:
- hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
- hw->ledctl_mode1 |= ledctl_on << (i << 3);
- break;
- case ID_LED_OFF1_DEF2:
- case ID_LED_OFF1_ON2:
- case ID_LED_OFF1_OFF2:
- hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
- hw->ledctl_mode1 |= ledctl_off << (i << 3);
- break;
- default:
- /* Do nothing */
- break;
- }
- switch (temp) {
- case ID_LED_DEF1_ON2:
- case ID_LED_ON1_ON2:
- case ID_LED_OFF1_ON2:
- hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
- hw->ledctl_mode2 |= ledctl_on << (i << 3);
- break;
- case ID_LED_DEF1_OFF2:
- case ID_LED_ON1_OFF2:
- case ID_LED_OFF1_OFF2:
- hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
- hw->ledctl_mode2 |= ledctl_off << (i << 3);
- break;
- default:
- /* Do nothing */
- break;
- }
- }
- return E1000_SUCCESS;
+ DEBUGFUNC("e1000_detect_gig_phy");
+
+ if (hw->phy_id != 0)
+ return E1000_SUCCESS;
+
+ /* Read the PHY ID Registers to identify which PHY is onboard. */
+ ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
+ if (ret_val)
+ return ret_val;
+
+ hw->phy_id = (u32) (phy_id_high << 16);
+ udelay(20);
+ ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low);
+ if (ret_val)
+ return ret_val;
+
+ hw->phy_id |= (u32) (phy_id_low & PHY_REVISION_MASK);
+ hw->phy_revision = (u32) phy_id_low & ~PHY_REVISION_MASK;
+
+ switch (hw->mac_type) {
+ case e1000_82543:
+ if (hw->phy_id == M88E1000_E_PHY_ID)
+ match = true;
+ break;
+ case e1000_82544:
+ if (hw->phy_id == M88E1000_I_PHY_ID)
+ match = true;
+ break;
+ case e1000_82540:
+ case e1000_82545:
+ case e1000_82545_rev_3:
+ case e1000_82546:
+ case e1000_82546_rev_3:
+ if (hw->phy_id == M88E1011_I_PHY_ID)
+ match = true;
+ break;
+ case e1000_82541:
+ case e1000_82541_rev_2:
+ case e1000_82547:
+ case e1000_82547_rev_2:
+ if (hw->phy_id == IGP01E1000_I_PHY_ID)
+ match = true;
+ break;
+ default:
+ DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
+ return -E1000_ERR_CONFIG;
+ }
+ phy_init_status = e1000_set_phy_type(hw);
+
+ if ((match) && (phy_init_status == E1000_SUCCESS)) {
+ DEBUGOUT1("PHY ID 0x%X detected\n", hw->phy_id);
+ return E1000_SUCCESS;
+ }
+ DEBUGOUT1("Invalid PHY ID 0x%X\n", hw->phy_id);
+ return -E1000_ERR_PHY;
}
-/******************************************************************************
- * Prepares SW controlable LED for use and saves the current state of the LED.
+/**
+ * e1000_phy_reset_dsp - reset DSP
+ * @hw: Struct containing variables accessed by shared code
*
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-s32 e1000_setup_led(struct e1000_hw *hw)
+ * Resets the PHY's DSP
+ */
+static s32 e1000_phy_reset_dsp(struct e1000_hw *hw)
{
- u32 ledctl;
- s32 ret_val = E1000_SUCCESS;
-
- DEBUGFUNC("e1000_setup_led");
-
- switch (hw->mac_type) {
- case e1000_82542_rev2_0:
- case e1000_82542_rev2_1:
- case e1000_82543:
- case e1000_82544:
- /* No setup necessary */
- break;
- case e1000_82541:
- case e1000_82547:
- case e1000_82541_rev_2:
- case e1000_82547_rev_2:
- /* Turn off PHY Smart Power Down (if enabled) */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO,
- &hw->phy_spd_default);
- if (ret_val)
- return ret_val;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
- (u16)(hw->phy_spd_default &
- ~IGP01E1000_GMII_SPD));
- if (ret_val)
- return ret_val;
- /* Fall Through */
- default:
- if (hw->media_type == e1000_media_type_fiber) {
- ledctl = er32(LEDCTL);
- /* Save current LEDCTL settings */
- hw->ledctl_default = ledctl;
- /* Turn off LED0 */
- ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
- E1000_LEDCTL_LED0_BLINK |
- E1000_LEDCTL_LED0_MODE_MASK);
- ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
- E1000_LEDCTL_LED0_MODE_SHIFT);
- ew32(LEDCTL, ledctl);
- } else if (hw->media_type == e1000_media_type_copper)
- ew32(LEDCTL, hw->ledctl_mode1);
- break;
- }
-
- return E1000_SUCCESS;
-}
+ s32 ret_val;
+ DEBUGFUNC("e1000_phy_reset_dsp");
+ do {
+ ret_val = e1000_write_phy_reg(hw, 29, 0x001d);
+ if (ret_val)
+ break;
+ ret_val = e1000_write_phy_reg(hw, 30, 0x00c1);
+ if (ret_val)
+ break;
+ ret_val = e1000_write_phy_reg(hw, 30, 0x0000);
+ if (ret_val)
+ break;
+ ret_val = E1000_SUCCESS;
+ } while (0);
-/******************************************************************************
- * Used on 82571 and later Si that has LED blink bits.
- * Callers must use their own timer and should have already called
- * e1000_id_led_init()
- * Call e1000_cleanup led() to stop blinking
- *
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-s32 e1000_blink_led_start(struct e1000_hw *hw)
-{
- s16 i;
- u32 ledctl_blink = 0;
-
- DEBUGFUNC("e1000_id_led_blink_on");
-
- if (hw->mac_type < e1000_82571) {
- /* Nothing to do */
- return E1000_SUCCESS;
- }
- if (hw->media_type == e1000_media_type_fiber) {
- /* always blink LED0 for PCI-E fiber */
- ledctl_blink = E1000_LEDCTL_LED0_BLINK |
- (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
- } else {
- /* set the blink bit for each LED that's "on" (0x0E) in ledctl_mode2 */
- ledctl_blink = hw->ledctl_mode2;
- for (i=0; i < 4; i++)
- if (((hw->ledctl_mode2 >> (i * 8)) & 0xFF) ==
- E1000_LEDCTL_MODE_LED_ON)
- ledctl_blink |= (E1000_LEDCTL_LED0_BLINK << (i * 8));
- }
-
- ew32(LEDCTL, ledctl_blink);
-
- return E1000_SUCCESS;
+ return ret_val;
}
-/******************************************************************************
- * Restores the saved state of the SW controlable LED.
+/**
+ * e1000_phy_igp_get_info - get igp specific registers
+ * @hw: Struct containing variables accessed by shared code
+ * @phy_info: PHY information structure
*
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-s32 e1000_cleanup_led(struct e1000_hw *hw)
+ * Get PHY information from various PHY registers for igp PHY only.
+ */
+static s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
{
- s32 ret_val = E1000_SUCCESS;
-
- DEBUGFUNC("e1000_cleanup_led");
-
- switch (hw->mac_type) {
- case e1000_82542_rev2_0:
- case e1000_82542_rev2_1:
- case e1000_82543:
- case e1000_82544:
- /* No cleanup necessary */
- break;
- case e1000_82541:
- case e1000_82547:
- case e1000_82541_rev_2:
- case e1000_82547_rev_2:
- /* Turn on PHY Smart Power Down (if previously enabled) */
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
- hw->phy_spd_default);
- if (ret_val)
- return ret_val;
- /* Fall Through */
- default:
- if (hw->phy_type == e1000_phy_ife) {
- e1000_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0);
- break;
- }
- /* Restore LEDCTL settings */
- ew32(LEDCTL, hw->ledctl_default);
- break;
- }
-
- return E1000_SUCCESS;
+ s32 ret_val;
+ u16 phy_data, min_length, max_length, average;
+ e1000_rev_polarity polarity;
+
+ DEBUGFUNC("e1000_phy_igp_get_info");
+
+ /* The downshift status is checked only once, after link is established,
+ * and it stored in the hw->speed_downgraded parameter. */
+ phy_info->downshift = (e1000_downshift) hw->speed_downgraded;
+
+ /* IGP01E1000 does not need to support it. */
+ phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal;
+
+ /* IGP01E1000 always correct polarity reversal */
+ phy_info->polarity_correction = e1000_polarity_reversal_enabled;
+
+ /* Check polarity status */
+ ret_val = e1000_check_polarity(hw, &polarity);
+ if (ret_val)
+ return ret_val;
+
+ phy_info->cable_polarity = polarity;
+
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_info->mdix_mode =
+ (e1000_auto_x_mode) ((phy_data & IGP01E1000_PSSR_MDIX) >>
+ IGP01E1000_PSSR_MDIX_SHIFT);
+
+ if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
+ IGP01E1000_PSSR_SPEED_1000MBPS) {
+ /* Local/Remote Receiver Information are only valid at 1000 Mbps */
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >>
+ SR_1000T_LOCAL_RX_STATUS_SHIFT) ?
+ e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
+ phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >>
+ SR_1000T_REMOTE_RX_STATUS_SHIFT) ?
+ e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
+
+ /* Get cable length */
+ ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
+ if (ret_val)
+ return ret_val;
+
+ /* Translate to old method */
+ average = (max_length + min_length) / 2;
+
+ if (average <= e1000_igp_cable_length_50)
+ phy_info->cable_length = e1000_cable_length_50;
+ else if (average <= e1000_igp_cable_length_80)
+ phy_info->cable_length = e1000_cable_length_50_80;
+ else if (average <= e1000_igp_cable_length_110)
+ phy_info->cable_length = e1000_cable_length_80_110;
+ else if (average <= e1000_igp_cable_length_140)
+ phy_info->cable_length = e1000_cable_length_110_140;
+ else
+ phy_info->cable_length = e1000_cable_length_140;
+ }
+
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * Turns on the software controllable LED
+/**
+ * e1000_phy_m88_get_info - get m88 specific registers
+ * @hw: Struct containing variables accessed by shared code
+ * @phy_info: PHY information structure
*
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-s32 e1000_led_on(struct e1000_hw *hw)
+ * Get PHY information from various PHY registers for m88 PHY only.
+ */
+static s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
+ struct e1000_phy_info *phy_info)
{
- u32 ctrl = er32(CTRL);
-
- DEBUGFUNC("e1000_led_on");
-
- switch (hw->mac_type) {
- case e1000_82542_rev2_0:
- case e1000_82542_rev2_1:
- case e1000_82543:
- /* Set SW Defineable Pin 0 to turn on the LED */
- ctrl |= E1000_CTRL_SWDPIN0;
- ctrl |= E1000_CTRL_SWDPIO0;
- break;
- case e1000_82544:
- if (hw->media_type == e1000_media_type_fiber) {
- /* Set SW Defineable Pin 0 to turn on the LED */
- ctrl |= E1000_CTRL_SWDPIN0;
- ctrl |= E1000_CTRL_SWDPIO0;
- } else {
- /* Clear SW Defineable Pin 0 to turn on the LED */
- ctrl &= ~E1000_CTRL_SWDPIN0;
- ctrl |= E1000_CTRL_SWDPIO0;
- }
- break;
- default:
- if (hw->media_type == e1000_media_type_fiber) {
- /* Clear SW Defineable Pin 0 to turn on the LED */
- ctrl &= ~E1000_CTRL_SWDPIN0;
- ctrl |= E1000_CTRL_SWDPIO0;
- } else if (hw->phy_type == e1000_phy_ife) {
- e1000_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
- (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON));
- } else if (hw->media_type == e1000_media_type_copper) {
- ew32(LEDCTL, hw->ledctl_mode2);
- return E1000_SUCCESS;
- }
- break;
- }
-
- ew32(CTRL, ctrl);
-
- return E1000_SUCCESS;
+ s32 ret_val;
+ u16 phy_data;
+ e1000_rev_polarity polarity;
+
+ DEBUGFUNC("e1000_phy_m88_get_info");
+
+ /* The downshift status is checked only once, after link is established,
+ * and it stored in the hw->speed_downgraded parameter. */
+ phy_info->downshift = (e1000_downshift) hw->speed_downgraded;
+
+ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_info->extended_10bt_distance =
+ ((phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >>
+ M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT) ?
+ e1000_10bt_ext_dist_enable_lower :
+ e1000_10bt_ext_dist_enable_normal;
+
+ phy_info->polarity_correction =
+ ((phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >>
+ M88E1000_PSCR_POLARITY_REVERSAL_SHIFT) ?
+ e1000_polarity_reversal_disabled : e1000_polarity_reversal_enabled;
+
+ /* Check polarity status */
+ ret_val = e1000_check_polarity(hw, &polarity);
+ if (ret_val)
+ return ret_val;
+ phy_info->cable_polarity = polarity;
+
+ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_info->mdix_mode =
+ (e1000_auto_x_mode) ((phy_data & M88E1000_PSSR_MDIX) >>
+ M88E1000_PSSR_MDIX_SHIFT);
+
+ if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
+ /* Cable Length Estimation and Local/Remote Receiver Information
+ * are only valid at 1000 Mbps.
+ */
+ phy_info->cable_length =
+ (e1000_cable_length) ((phy_data &
+ M88E1000_PSSR_CABLE_LENGTH) >>
+ M88E1000_PSSR_CABLE_LENGTH_SHIFT);
+
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >>
+ SR_1000T_LOCAL_RX_STATUS_SHIFT) ?
+ e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
+ phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >>
+ SR_1000T_REMOTE_RX_STATUS_SHIFT) ?
+ e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
+
+ }
+
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * Turns off the software controllable LED
+/**
+ * e1000_phy_get_info - request phy info
+ * @hw: Struct containing variables accessed by shared code
+ * @phy_info: PHY information structure
*
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-s32 e1000_led_off(struct e1000_hw *hw)
+ * Get PHY information from various PHY registers
+ */
+s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info)
{
- u32 ctrl = er32(CTRL);
-
- DEBUGFUNC("e1000_led_off");
-
- switch (hw->mac_type) {
- case e1000_82542_rev2_0:
- case e1000_82542_rev2_1:
- case e1000_82543:
- /* Clear SW Defineable Pin 0 to turn off the LED */
- ctrl &= ~E1000_CTRL_SWDPIN0;
- ctrl |= E1000_CTRL_SWDPIO0;
- break;
- case e1000_82544:
- if (hw->media_type == e1000_media_type_fiber) {
- /* Clear SW Defineable Pin 0 to turn off the LED */
- ctrl &= ~E1000_CTRL_SWDPIN0;
- ctrl |= E1000_CTRL_SWDPIO0;
- } else {
- /* Set SW Defineable Pin 0 to turn off the LED */
- ctrl |= E1000_CTRL_SWDPIN0;
- ctrl |= E1000_CTRL_SWDPIO0;
- }
- break;
- default:
- if (hw->media_type == e1000_media_type_fiber) {
- /* Set SW Defineable Pin 0 to turn off the LED */
- ctrl |= E1000_CTRL_SWDPIN0;
- ctrl |= E1000_CTRL_SWDPIO0;
- } else if (hw->phy_type == e1000_phy_ife) {
- e1000_write_phy_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
- (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF));
- } else if (hw->media_type == e1000_media_type_copper) {
- ew32(LEDCTL, hw->ledctl_mode1);
- return E1000_SUCCESS;
- }
- break;
- }
-
- ew32(CTRL, ctrl);
-
- return E1000_SUCCESS;
-}
+ s32 ret_val;
+ u16 phy_data;
-/******************************************************************************
- * Clears all hardware statistics counters.
- *
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-static void e1000_clear_hw_cntrs(struct e1000_hw *hw)
+ DEBUGFUNC("e1000_phy_get_info");
+
+ phy_info->cable_length = e1000_cable_length_undefined;
+ phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_undefined;
+ phy_info->cable_polarity = e1000_rev_polarity_undefined;
+ phy_info->downshift = e1000_downshift_undefined;
+ phy_info->polarity_correction = e1000_polarity_reversal_undefined;
+ phy_info->mdix_mode = e1000_auto_x_mode_undefined;
+ phy_info->local_rx = e1000_1000t_rx_status_undefined;
+ phy_info->remote_rx = e1000_1000t_rx_status_undefined;
+
+ if (hw->media_type != e1000_media_type_copper) {
+ DEBUGOUT("PHY info is only valid for copper media\n");
+ return -E1000_ERR_CONFIG;
+ }
+
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ if ((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) {
+ DEBUGOUT("PHY info is only valid if link is up\n");
+ return -E1000_ERR_CONFIG;
+ }
+
+ if (hw->phy_type == e1000_phy_igp)
+ return e1000_phy_igp_get_info(hw, phy_info);
+ else
+ return e1000_phy_m88_get_info(hw, phy_info);
+}
+
+s32 e1000_validate_mdi_setting(struct e1000_hw *hw)
{
- volatile u32 temp;
-
- temp = er32(CRCERRS);
- temp = er32(SYMERRS);
- temp = er32(MPC);
- temp = er32(SCC);
- temp = er32(ECOL);
- temp = er32(MCC);
- temp = er32(LATECOL);
- temp = er32(COLC);
- temp = er32(DC);
- temp = er32(SEC);
- temp = er32(RLEC);
- temp = er32(XONRXC);
- temp = er32(XONTXC);
- temp = er32(XOFFRXC);
- temp = er32(XOFFTXC);
- temp = er32(FCRUC);
-
- if (hw->mac_type != e1000_ich8lan) {
- temp = er32(PRC64);
- temp = er32(PRC127);
- temp = er32(PRC255);
- temp = er32(PRC511);
- temp = er32(PRC1023);
- temp = er32(PRC1522);
- }
-
- temp = er32(GPRC);
- temp = er32(BPRC);
- temp = er32(MPRC);
- temp = er32(GPTC);
- temp = er32(GORCL);
- temp = er32(GORCH);
- temp = er32(GOTCL);
- temp = er32(GOTCH);
- temp = er32(RNBC);
- temp = er32(RUC);
- temp = er32(RFC);
- temp = er32(ROC);
- temp = er32(RJC);
- temp = er32(TORL);
- temp = er32(TORH);
- temp = er32(TOTL);
- temp = er32(TOTH);
- temp = er32(TPR);
- temp = er32(TPT);
-
- if (hw->mac_type != e1000_ich8lan) {
- temp = er32(PTC64);
- temp = er32(PTC127);
- temp = er32(PTC255);
- temp = er32(PTC511);
- temp = er32(PTC1023);
- temp = er32(PTC1522);
- }
-
- temp = er32(MPTC);
- temp = er32(BPTC);
-
- if (hw->mac_type < e1000_82543) return;
-
- temp = er32(ALGNERRC);
- temp = er32(RXERRC);
- temp = er32(TNCRS);
- temp = er32(CEXTERR);
- temp = er32(TSCTC);
- temp = er32(TSCTFC);
-
- if (hw->mac_type <= e1000_82544) return;
-
- temp = er32(MGTPRC);
- temp = er32(MGTPDC);
- temp = er32(MGTPTC);
-
- if (hw->mac_type <= e1000_82547_rev_2) return;
-
- temp = er32(IAC);
- temp = er32(ICRXOC);
-
- if (hw->mac_type == e1000_ich8lan) return;
-
- temp = er32(ICRXPTC);
- temp = er32(ICRXATC);
- temp = er32(ICTXPTC);
- temp = er32(ICTXATC);
- temp = er32(ICTXQEC);
- temp = er32(ICTXQMTC);
- temp = er32(ICRXDMTC);
+ DEBUGFUNC("e1000_validate_mdi_settings");
+
+ if (!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) {
+ DEBUGOUT("Invalid MDI setting detected\n");
+ hw->mdix = 1;
+ return -E1000_ERR_CONFIG;
+ }
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * Resets Adaptive IFS to its default state.
+/**
+ * e1000_init_eeprom_params - initialize sw eeprom vars
+ * @hw: Struct containing variables accessed by shared code
*
- * hw - Struct containing variables accessed by shared code
- *
- * Call this after e1000_init_hw. You may override the IFS defaults by setting
- * hw->ifs_params_forced to true. However, you must initialize hw->
- * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio
- * before calling this function.
- *****************************************************************************/
-void e1000_reset_adaptive(struct e1000_hw *hw)
+ * Sets up eeprom variables in the hw struct. Must be called after mac_type
+ * is configured.
+ */
+s32 e1000_init_eeprom_params(struct e1000_hw *hw)
{
- DEBUGFUNC("e1000_reset_adaptive");
-
- if (hw->adaptive_ifs) {
- if (!hw->ifs_params_forced) {
- hw->current_ifs_val = 0;
- hw->ifs_min_val = IFS_MIN;
- hw->ifs_max_val = IFS_MAX;
- hw->ifs_step_size = IFS_STEP;
- hw->ifs_ratio = IFS_RATIO;
- }
- hw->in_ifs_mode = false;
- ew32(AIT, 0);
- } else {
- DEBUGOUT("Not in Adaptive IFS mode!\n");
- }
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+ u32 eecd = er32(EECD);
+ s32 ret_val = E1000_SUCCESS;
+ u16 eeprom_size;
+
+ DEBUGFUNC("e1000_init_eeprom_params");
+
+ switch (hw->mac_type) {
+ case e1000_82542_rev2_0:
+ case e1000_82542_rev2_1:
+ case e1000_82543:
+ case e1000_82544:
+ eeprom->type = e1000_eeprom_microwire;
+ eeprom->word_size = 64;
+ eeprom->opcode_bits = 3;
+ eeprom->address_bits = 6;
+ eeprom->delay_usec = 50;
+ break;
+ case e1000_82540:
+ case e1000_82545:
+ case e1000_82545_rev_3:
+ case e1000_82546:
+ case e1000_82546_rev_3:
+ eeprom->type = e1000_eeprom_microwire;
+ eeprom->opcode_bits = 3;
+ eeprom->delay_usec = 50;
+ if (eecd & E1000_EECD_SIZE) {
+ eeprom->word_size = 256;
+ eeprom->address_bits = 8;
+ } else {
+ eeprom->word_size = 64;
+ eeprom->address_bits = 6;
+ }
+ break;
+ case e1000_82541:
+ case e1000_82541_rev_2:
+ case e1000_82547:
+ case e1000_82547_rev_2:
+ if (eecd & E1000_EECD_TYPE) {
+ eeprom->type = e1000_eeprom_spi;
+ eeprom->opcode_bits = 8;
+ eeprom->delay_usec = 1;
+ if (eecd & E1000_EECD_ADDR_BITS) {
+ eeprom->page_size = 32;
+ eeprom->address_bits = 16;
+ } else {
+ eeprom->page_size = 8;
+ eeprom->address_bits = 8;
+ }
+ } else {
+ eeprom->type = e1000_eeprom_microwire;
+ eeprom->opcode_bits = 3;
+ eeprom->delay_usec = 50;
+ if (eecd & E1000_EECD_ADDR_BITS) {
+ eeprom->word_size = 256;
+ eeprom->address_bits = 8;
+ } else {
+ eeprom->word_size = 64;
+ eeprom->address_bits = 6;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (eeprom->type == e1000_eeprom_spi) {
+ /* eeprom_size will be an enum [0..8] that maps to eeprom sizes 128B to
+ * 32KB (incremented by powers of 2).
+ */
+ /* Set to default value for initial eeprom read. */
+ eeprom->word_size = 64;
+ ret_val = e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size);
+ if (ret_val)
+ return ret_val;
+ eeprom_size =
+ (eeprom_size & EEPROM_SIZE_MASK) >> EEPROM_SIZE_SHIFT;
+ /* 256B eeprom size was not supported in earlier hardware, so we
+ * bump eeprom_size up one to ensure that "1" (which maps to 256B)
+ * is never the result used in the shifting logic below. */
+ if (eeprom_size)
+ eeprom_size++;
+
+ eeprom->word_size = 1 << (eeprom_size + EEPROM_WORD_SIZE_SHIFT);
+ }
+ return ret_val;
}
-/******************************************************************************
- * Called during the callback/watchdog routine to update IFS value based on
- * the ratio of transmits to collisions.
- *
- * hw - Struct containing variables accessed by shared code
- * tx_packets - Number of transmits since last callback
- * total_collisions - Number of collisions since last callback
- *****************************************************************************/
-void e1000_update_adaptive(struct e1000_hw *hw)
+/**
+ * e1000_raise_ee_clk - Raises the EEPROM's clock input.
+ * @hw: Struct containing variables accessed by shared code
+ * @eecd: EECD's current value
+ */
+static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd)
{
- DEBUGFUNC("e1000_update_adaptive");
-
- if (hw->adaptive_ifs) {
- if ((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) {
- if (hw->tx_packet_delta > MIN_NUM_XMITS) {
- hw->in_ifs_mode = true;
- if (hw->current_ifs_val < hw->ifs_max_val) {
- if (hw->current_ifs_val == 0)
- hw->current_ifs_val = hw->ifs_min_val;
- else
- hw->current_ifs_val += hw->ifs_step_size;
- ew32(AIT, hw->current_ifs_val);
- }
- }
- } else {
- if (hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
- hw->current_ifs_val = 0;
- hw->in_ifs_mode = false;
- ew32(AIT, 0);
- }
- }
- } else {
- DEBUGOUT("Not in Adaptive IFS mode!\n");
- }
+ /* Raise the clock input to the EEPROM (by setting the SK bit), and then
+ * wait <delay> microseconds.
+ */
+ *eecd = *eecd | E1000_EECD_SK;
+ ew32(EECD, *eecd);
+ E1000_WRITE_FLUSH();
+ udelay(hw->eeprom.delay_usec);
}
-/******************************************************************************
- * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
- *
- * hw - Struct containing variables accessed by shared code
- * frame_len - The length of the frame in question
- * mac_addr - The Ethernet destination address of the frame in question
- *****************************************************************************/
-void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats,
- u32 frame_len, u8 *mac_addr)
+/**
+ * e1000_lower_ee_clk - Lowers the EEPROM's clock input.
+ * @hw: Struct containing variables accessed by shared code
+ * @eecd: EECD's current value
+ */
+static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd)
{
- u64 carry_bit;
-
- /* First adjust the frame length. */
- frame_len--;
- /* We need to adjust the statistics counters, since the hardware
- * counters overcount this packet as a CRC error and undercount
- * the packet as a good packet
- */
- /* This packet should not be counted as a CRC error. */
- stats->crcerrs--;
- /* This packet does count as a Good Packet Received. */
- stats->gprc++;
-
- /* Adjust the Good Octets received counters */
- carry_bit = 0x80000000 & stats->gorcl;
- stats->gorcl += frame_len;
- /* If the high bit of Gorcl (the low 32 bits of the Good Octets
- * Received Count) was one before the addition,
- * AND it is zero after, then we lost the carry out,
- * need to add one to Gorch (Good Octets Received Count High).
- * This could be simplified if all environments supported
- * 64-bit integers.
- */
- if (carry_bit && ((stats->gorcl & 0x80000000) == 0))
- stats->gorch++;
- /* Is this a broadcast or multicast? Check broadcast first,
- * since the test for a multicast frame will test positive on
- * a broadcast frame.
- */
- if ((mac_addr[0] == (u8)0xff) && (mac_addr[1] == (u8)0xff))
- /* Broadcast packet */
- stats->bprc++;
- else if (*mac_addr & 0x01)
- /* Multicast packet */
- stats->mprc++;
-
- if (frame_len == hw->max_frame_size) {
- /* In this case, the hardware has overcounted the number of
- * oversize frames.
- */
- if (stats->roc > 0)
- stats->roc--;
- }
-
- /* Adjust the bin counters when the extra byte put the frame in the
- * wrong bin. Remember that the frame_len was adjusted above.
- */
- if (frame_len == 64) {
- stats->prc64++;
- stats->prc127--;
- } else if (frame_len == 127) {
- stats->prc127++;
- stats->prc255--;
- } else if (frame_len == 255) {
- stats->prc255++;
- stats->prc511--;
- } else if (frame_len == 511) {
- stats->prc511++;
- stats->prc1023--;
- } else if (frame_len == 1023) {
- stats->prc1023++;
- stats->prc1522--;
- } else if (frame_len == 1522) {
- stats->prc1522++;
- }
+ /* Lower the clock input to the EEPROM (by clearing the SK bit), and then
+ * wait 50 microseconds.
+ */
+ *eecd = *eecd & ~E1000_EECD_SK;
+ ew32(EECD, *eecd);
+ E1000_WRITE_FLUSH();
+ udelay(hw->eeprom.delay_usec);
}
-/******************************************************************************
- * Gets the current PCI bus type, speed, and width of the hardware
- *
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-void e1000_get_bus_info(struct e1000_hw *hw)
+/**
+ * e1000_shift_out_ee_bits - Shift data bits out to the EEPROM.
+ * @hw: Struct containing variables accessed by shared code
+ * @data: data to send to the EEPROM
+ * @count: number of bits to shift out
+ */
+static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count)
{
- s32 ret_val;
- u16 pci_ex_link_status;
- u32 status;
-
- switch (hw->mac_type) {
- case e1000_82542_rev2_0:
- case e1000_82542_rev2_1:
- hw->bus_type = e1000_bus_type_pci;
- hw->bus_speed = e1000_bus_speed_unknown;
- hw->bus_width = e1000_bus_width_unknown;
- break;
- case e1000_82571:
- case e1000_82572:
- case e1000_82573:
- case e1000_80003es2lan:
- hw->bus_type = e1000_bus_type_pci_express;
- hw->bus_speed = e1000_bus_speed_2500;
- ret_val = e1000_read_pcie_cap_reg(hw,
- PCI_EX_LINK_STATUS,
- &pci_ex_link_status);
- if (ret_val)
- hw->bus_width = e1000_bus_width_unknown;
- else
- hw->bus_width = (pci_ex_link_status & PCI_EX_LINK_WIDTH_MASK) >>
- PCI_EX_LINK_WIDTH_SHIFT;
- break;
- case e1000_ich8lan:
- hw->bus_type = e1000_bus_type_pci_express;
- hw->bus_speed = e1000_bus_speed_2500;
- hw->bus_width = e1000_bus_width_pciex_1;
- break;
- default:
- status = er32(STATUS);
- hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
- e1000_bus_type_pcix : e1000_bus_type_pci;
-
- if (hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
- hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ?
- e1000_bus_speed_66 : e1000_bus_speed_120;
- } else if (hw->bus_type == e1000_bus_type_pci) {
- hw->bus_speed = (status & E1000_STATUS_PCI66) ?
- e1000_bus_speed_66 : e1000_bus_speed_33;
- } else {
- switch (status & E1000_STATUS_PCIX_SPEED) {
- case E1000_STATUS_PCIX_SPEED_66:
- hw->bus_speed = e1000_bus_speed_66;
- break;
- case E1000_STATUS_PCIX_SPEED_100:
- hw->bus_speed = e1000_bus_speed_100;
- break;
- case E1000_STATUS_PCIX_SPEED_133:
- hw->bus_speed = e1000_bus_speed_133;
- break;
- default:
- hw->bus_speed = e1000_bus_speed_reserved;
- break;
- }
- }
- hw->bus_width = (status & E1000_STATUS_BUS64) ?
- e1000_bus_width_64 : e1000_bus_width_32;
- break;
- }
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+ u32 eecd;
+ u32 mask;
+
+ /* We need to shift "count" bits out to the EEPROM. So, value in the
+ * "data" parameter will be shifted out to the EEPROM one bit at a time.
+ * In order to do this, "data" must be broken down into bits.
+ */
+ mask = 0x01 << (count - 1);
+ eecd = er32(EECD);
+ if (eeprom->type == e1000_eeprom_microwire) {
+ eecd &= ~E1000_EECD_DO;
+ } else if (eeprom->type == e1000_eeprom_spi) {
+ eecd |= E1000_EECD_DO;
+ }
+ do {
+ /* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1",
+ * and then raising and then lowering the clock (the SK bit controls
+ * the clock input to the EEPROM). A "0" is shifted out to the EEPROM
+ * by setting "DI" to "0" and then raising and then lowering the clock.
+ */
+ eecd &= ~E1000_EECD_DI;
+
+ if (data & mask)
+ eecd |= E1000_EECD_DI;
+
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
+
+ udelay(eeprom->delay_usec);
+
+ e1000_raise_ee_clk(hw, &eecd);
+ e1000_lower_ee_clk(hw, &eecd);
+
+ mask = mask >> 1;
+
+ } while (mask);
+
+ /* We leave the "DI" bit set to "0" when we leave this routine. */
+ eecd &= ~E1000_EECD_DI;
+ ew32(EECD, eecd);
}
-/******************************************************************************
- * Writes a value to one of the devices registers using port I/O (as opposed to
- * memory mapped I/O). Only 82544 and newer devices support port I/O.
- *
- * hw - Struct containing variables accessed by shared code
- * offset - offset to write to
- * value - value to write
- *****************************************************************************/
-static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value)
+/**
+ * e1000_shift_in_ee_bits - Shift data bits in from the EEPROM
+ * @hw: Struct containing variables accessed by shared code
+ * @count: number of bits to shift in
+ */
+static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count)
{
- unsigned long io_addr = hw->io_base;
- unsigned long io_data = hw->io_base + 4;
+ u32 eecd;
+ u32 i;
+ u16 data;
+
+ /* In order to read a register from the EEPROM, we need to shift 'count'
+ * bits in from the EEPROM. Bits are "shifted in" by raising the clock
+ * input to the EEPROM (setting the SK bit), and then reading the value of
+ * the "DO" bit. During this "shifting in" process the "DI" bit should
+ * always be clear.
+ */
+
+ eecd = er32(EECD);
+
+ eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
+ data = 0;
- e1000_io_write(hw, io_addr, offset);
- e1000_io_write(hw, io_data, value);
+ for (i = 0; i < count; i++) {
+ data = data << 1;
+ e1000_raise_ee_clk(hw, &eecd);
+
+ eecd = er32(EECD);
+
+ eecd &= ~(E1000_EECD_DI);
+ if (eecd & E1000_EECD_DO)
+ data |= 1;
+
+ e1000_lower_ee_clk(hw, &eecd);
+ }
+
+ return data;
}
-/******************************************************************************
- * Estimates the cable length.
- *
- * hw - Struct containing variables accessed by shared code
- * min_length - The estimated minimum length
- * max_length - The estimated maximum length
- *
- * returns: - E1000_ERR_XXX
- * E1000_SUCCESS
+/**
+ * e1000_acquire_eeprom - Prepares EEPROM for access
+ * @hw: Struct containing variables accessed by shared code
*
- * This function always returns a ranged length (minimum & maximum).
- * So for M88 phy's, this function interprets the one value returned from the
- * register to the minimum and maximum range.
- * For IGP phy's, the function calculates the range by the AGC registers.
- *****************************************************************************/
-static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
- u16 *max_length)
+ * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
+ * function should be called before issuing a command to the EEPROM.
+ */
+static s32 e1000_acquire_eeprom(struct e1000_hw *hw)
{
- s32 ret_val;
- u16 agc_value = 0;
- u16 i, phy_data;
- u16 cable_length;
-
- DEBUGFUNC("e1000_get_cable_length");
-
- *min_length = *max_length = 0;
-
- /* Use old method for Phy older than IGP */
- if (hw->phy_type == e1000_phy_m88) {
-
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
- &phy_data);
- if (ret_val)
- return ret_val;
- cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
- M88E1000_PSSR_CABLE_LENGTH_SHIFT;
-
- /* Convert the enum value to ranged values */
- switch (cable_length) {
- case e1000_cable_length_50:
- *min_length = 0;
- *max_length = e1000_igp_cable_length_50;
- break;
- case e1000_cable_length_50_80:
- *min_length = e1000_igp_cable_length_50;
- *max_length = e1000_igp_cable_length_80;
- break;
- case e1000_cable_length_80_110:
- *min_length = e1000_igp_cable_length_80;
- *max_length = e1000_igp_cable_length_110;
- break;
- case e1000_cable_length_110_140:
- *min_length = e1000_igp_cable_length_110;
- *max_length = e1000_igp_cable_length_140;
- break;
- case e1000_cable_length_140:
- *min_length = e1000_igp_cable_length_140;
- *max_length = e1000_igp_cable_length_170;
- break;
- default:
- return -E1000_ERR_PHY;
- break;
- }
- } else if (hw->phy_type == e1000_phy_gg82563) {
- ret_val = e1000_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE,
- &phy_data);
- if (ret_val)
- return ret_val;
- cable_length = phy_data & GG82563_DSPD_CABLE_LENGTH;
-
- switch (cable_length) {
- case e1000_gg_cable_length_60:
- *min_length = 0;
- *max_length = e1000_igp_cable_length_60;
- break;
- case e1000_gg_cable_length_60_115:
- *min_length = e1000_igp_cable_length_60;
- *max_length = e1000_igp_cable_length_115;
- break;
- case e1000_gg_cable_length_115_150:
- *min_length = e1000_igp_cable_length_115;
- *max_length = e1000_igp_cable_length_150;
- break;
- case e1000_gg_cable_length_150:
- *min_length = e1000_igp_cable_length_150;
- *max_length = e1000_igp_cable_length_180;
- break;
- default:
- return -E1000_ERR_PHY;
- break;
- }
- } else if (hw->phy_type == e1000_phy_igp) { /* For IGP PHY */
- u16 cur_agc_value;
- u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
- u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
- {IGP01E1000_PHY_AGC_A,
- IGP01E1000_PHY_AGC_B,
- IGP01E1000_PHY_AGC_C,
- IGP01E1000_PHY_AGC_D};
- /* Read the AGC registers for all channels */
- for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
-
- ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
- if (ret_val)
- return ret_val;
-
- cur_agc_value = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT;
-
- /* Value bound check. */
- if ((cur_agc_value >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) ||
- (cur_agc_value == 0))
- return -E1000_ERR_PHY;
-
- agc_value += cur_agc_value;
-
- /* Update minimal AGC value. */
- if (min_agc_value > cur_agc_value)
- min_agc_value = cur_agc_value;
- }
-
- /* Remove the minimal AGC result for length < 50m */
- if (agc_value < IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) {
- agc_value -= min_agc_value;
-
- /* Get the average length of the remaining 3 channels */
- agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1);
- } else {
- /* Get the average length of all the 4 channels. */
- agc_value /= IGP01E1000_PHY_CHANNEL_NUM;
- }
-
- /* Set the range of the calculated length. */
- *min_length = ((e1000_igp_cable_length_table[agc_value] -
- IGP01E1000_AGC_RANGE) > 0) ?
- (e1000_igp_cable_length_table[agc_value] -
- IGP01E1000_AGC_RANGE) : 0;
- *max_length = e1000_igp_cable_length_table[agc_value] +
- IGP01E1000_AGC_RANGE;
- } else if (hw->phy_type == e1000_phy_igp_2 ||
- hw->phy_type == e1000_phy_igp_3) {
- u16 cur_agc_index, max_agc_index = 0;
- u16 min_agc_index = IGP02E1000_AGC_LENGTH_TABLE_SIZE - 1;
- u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
- {IGP02E1000_PHY_AGC_A,
- IGP02E1000_PHY_AGC_B,
- IGP02E1000_PHY_AGC_C,
- IGP02E1000_PHY_AGC_D};
- /* Read the AGC registers for all channels */
- for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
- ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
- if (ret_val)
- return ret_val;
-
- /* Getting bits 15:9, which represent the combination of course and
- * fine gain values. The result is a number that can be put into
- * the lookup table to obtain the approximate cable length. */
- cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
- IGP02E1000_AGC_LENGTH_MASK;
-
- /* Array index bound check. */
- if ((cur_agc_index >= IGP02E1000_AGC_LENGTH_TABLE_SIZE) ||
- (cur_agc_index == 0))
- return -E1000_ERR_PHY;
-
- /* Remove min & max AGC values from calculation. */
- if (e1000_igp_2_cable_length_table[min_agc_index] >
- e1000_igp_2_cable_length_table[cur_agc_index])
- min_agc_index = cur_agc_index;
- if (e1000_igp_2_cable_length_table[max_agc_index] <
- e1000_igp_2_cable_length_table[cur_agc_index])
- max_agc_index = cur_agc_index;
-
- agc_value += e1000_igp_2_cable_length_table[cur_agc_index];
- }
-
- agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] +
- e1000_igp_2_cable_length_table[max_agc_index]);
- agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
-
- /* Calculate cable length with the error range of +/- 10 meters. */
- *min_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
- (agc_value - IGP02E1000_AGC_RANGE) : 0;
- *max_length = agc_value + IGP02E1000_AGC_RANGE;
- }
-
- return E1000_SUCCESS;
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+ u32 eecd, i = 0;
+
+ DEBUGFUNC("e1000_acquire_eeprom");
+
+ eecd = er32(EECD);
+
+ /* Request EEPROM Access */
+ if (hw->mac_type > e1000_82544) {
+ eecd |= E1000_EECD_REQ;
+ ew32(EECD, eecd);
+ eecd = er32(EECD);
+ while ((!(eecd & E1000_EECD_GNT)) &&
+ (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
+ i++;
+ udelay(5);
+ eecd = er32(EECD);
+ }
+ if (!(eecd & E1000_EECD_GNT)) {
+ eecd &= ~E1000_EECD_REQ;
+ ew32(EECD, eecd);
+ DEBUGOUT("Could not acquire EEPROM grant\n");
+ return -E1000_ERR_EEPROM;
+ }
+ }
+
+ /* Setup EEPROM for Read/Write */
+
+ if (eeprom->type == e1000_eeprom_microwire) {
+ /* Clear SK and DI */
+ eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
+ ew32(EECD, eecd);
+
+ /* Set CS */
+ eecd |= E1000_EECD_CS;
+ ew32(EECD, eecd);
+ } else if (eeprom->type == e1000_eeprom_spi) {
+ /* Clear SK and CS */
+ eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
+ ew32(EECD, eecd);
+ udelay(1);
+ }
+
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * Check the cable polarity
- *
- * hw - Struct containing variables accessed by shared code
- * polarity - output parameter : 0 - Polarity is not reversed
- * 1 - Polarity is reversed.
- *
- * returns: - E1000_ERR_XXX
- * E1000_SUCCESS
- *
- * For phy's older than IGP, this function simply reads the polarity bit in the
- * Phy Status register. For IGP phy's, this bit is valid only if link speed is
- * 10 Mbps. If the link speed is 100 Mbps there is no polarity so this bit will
- * return 0. If the link speed is 1000 Mbps the polarity status is in the
- * IGP01E1000_PHY_PCS_INIT_REG.
- *****************************************************************************/
-static s32 e1000_check_polarity(struct e1000_hw *hw,
- e1000_rev_polarity *polarity)
+/**
+ * e1000_standby_eeprom - Returns EEPROM to a "standby" state
+ * @hw: Struct containing variables accessed by shared code
+ */
+static void e1000_standby_eeprom(struct e1000_hw *hw)
{
- s32 ret_val;
- u16 phy_data;
-
- DEBUGFUNC("e1000_check_polarity");
-
- if ((hw->phy_type == e1000_phy_m88) ||
- (hw->phy_type == e1000_phy_gg82563)) {
- /* return the Polarity bit in the Status register. */
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
- &phy_data);
- if (ret_val)
- return ret_val;
- *polarity = ((phy_data & M88E1000_PSSR_REV_POLARITY) >>
- M88E1000_PSSR_REV_POLARITY_SHIFT) ?
- e1000_rev_polarity_reversed : e1000_rev_polarity_normal;
-
- } else if (hw->phy_type == e1000_phy_igp ||
- hw->phy_type == e1000_phy_igp_3 ||
- hw->phy_type == e1000_phy_igp_2) {
- /* Read the Status register to check the speed */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- /* If speed is 1000 Mbps, must read the IGP01E1000_PHY_PCS_INIT_REG to
- * find the polarity status */
- if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
- IGP01E1000_PSSR_SPEED_1000MBPS) {
-
- /* Read the GIG initialization PCS register (0x00B4) */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- /* Check the polarity bits */
- *polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ?
- e1000_rev_polarity_reversed : e1000_rev_polarity_normal;
- } else {
- /* For 10 Mbps, read the polarity bit in the status register. (for
- * 100 Mbps this bit is always 0) */
- *polarity = (phy_data & IGP01E1000_PSSR_POLARITY_REVERSED) ?
- e1000_rev_polarity_reversed : e1000_rev_polarity_normal;
- }
- } else if (hw->phy_type == e1000_phy_ife) {
- ret_val = e1000_read_phy_reg(hw, IFE_PHY_EXTENDED_STATUS_CONTROL,
- &phy_data);
- if (ret_val)
- return ret_val;
- *polarity = ((phy_data & IFE_PESC_POLARITY_REVERSED) >>
- IFE_PESC_POLARITY_REVERSED_SHIFT) ?
- e1000_rev_polarity_reversed : e1000_rev_polarity_normal;
- }
- return E1000_SUCCESS;
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+ u32 eecd;
+
+ eecd = er32(EECD);
+
+ if (eeprom->type == e1000_eeprom_microwire) {
+ eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
+ udelay(eeprom->delay_usec);
+
+ /* Clock high */
+ eecd |= E1000_EECD_SK;
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
+ udelay(eeprom->delay_usec);
+
+ /* Select EEPROM */
+ eecd |= E1000_EECD_CS;
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
+ udelay(eeprom->delay_usec);
+
+ /* Clock low */
+ eecd &= ~E1000_EECD_SK;
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
+ udelay(eeprom->delay_usec);
+ } else if (eeprom->type == e1000_eeprom_spi) {
+ /* Toggle CS to flush commands */
+ eecd |= E1000_EECD_CS;
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
+ udelay(eeprom->delay_usec);
+ eecd &= ~E1000_EECD_CS;
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
+ udelay(eeprom->delay_usec);
+ }
}
-/******************************************************************************
- * Check if Downshift occured
+/**
+ * e1000_release_eeprom - drop chip select
+ * @hw: Struct containing variables accessed by shared code
*
- * hw - Struct containing variables accessed by shared code
- * downshift - output parameter : 0 - No Downshift ocured.
- * 1 - Downshift ocured.
- *
- * returns: - E1000_ERR_XXX
- * E1000_SUCCESS
- *
- * For phy's older than IGP, this function reads the Downshift bit in the Phy
- * Specific Status register. For IGP phy's, it reads the Downgrade bit in the
- * Link Health register. In IGP this bit is latched high, so the driver must
- * read it immediately after link is established.
- *****************************************************************************/
-static s32 e1000_check_downshift(struct e1000_hw *hw)
+ * Terminates a command by inverting the EEPROM's chip select pin
+ */
+static void e1000_release_eeprom(struct e1000_hw *hw)
{
- s32 ret_val;
- u16 phy_data;
-
- DEBUGFUNC("e1000_check_downshift");
-
- if (hw->phy_type == e1000_phy_igp ||
- hw->phy_type == e1000_phy_igp_3 ||
- hw->phy_type == e1000_phy_igp_2) {
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0;
- } else if ((hw->phy_type == e1000_phy_m88) ||
- (hw->phy_type == e1000_phy_gg82563)) {
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >>
- M88E1000_PSSR_DOWNSHIFT_SHIFT;
- } else if (hw->phy_type == e1000_phy_ife) {
- /* e1000_phy_ife supports 10/100 speed only */
- hw->speed_downgraded = false;
- }
-
- return E1000_SUCCESS;
+ u32 eecd;
+
+ DEBUGFUNC("e1000_release_eeprom");
+
+ eecd = er32(EECD);
+
+ if (hw->eeprom.type == e1000_eeprom_spi) {
+ eecd |= E1000_EECD_CS; /* Pull CS high */
+ eecd &= ~E1000_EECD_SK; /* Lower SCK */
+
+ ew32(EECD, eecd);
+
+ udelay(hw->eeprom.delay_usec);
+ } else if (hw->eeprom.type == e1000_eeprom_microwire) {
+ /* cleanup eeprom */
+
+ /* CS on Microwire is active-high */
+ eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
+
+ ew32(EECD, eecd);
+
+ /* Rising edge of clock */
+ eecd |= E1000_EECD_SK;
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
+ udelay(hw->eeprom.delay_usec);
+
+ /* Falling edge of clock */
+ eecd &= ~E1000_EECD_SK;
+ ew32(EECD, eecd);
+ E1000_WRITE_FLUSH();
+ udelay(hw->eeprom.delay_usec);
+ }
+
+ /* Stop requesting EEPROM access */
+ if (hw->mac_type > e1000_82544) {
+ eecd &= ~E1000_EECD_REQ;
+ ew32(EECD, eecd);
+ }
}
-/*****************************************************************************
- *
- * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a
- * gigabit link is achieved to improve link quality.
- *
- * hw: Struct containing variables accessed by shared code
- *
- * returns: - E1000_ERR_PHY if fail to read/write the PHY
- * E1000_SUCCESS at any other case.
- *
- ****************************************************************************/
+/**
+ * e1000_spi_eeprom_ready - Reads a 16 bit word from the EEPROM.
+ * @hw: Struct containing variables accessed by shared code
+ */
+static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw)
+{
+ u16 retry_count = 0;
+ u8 spi_stat_reg;
-static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
+ DEBUGFUNC("e1000_spi_eeprom_ready");
+
+ /* Read "Status Register" repeatedly until the LSB is cleared. The
+ * EEPROM will signal that the command has been completed by clearing
+ * bit 0 of the internal status register. If it's not cleared within
+ * 5 milliseconds, then error out.
+ */
+ retry_count = 0;
+ do {
+ e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI,
+ hw->eeprom.opcode_bits);
+ spi_stat_reg = (u8) e1000_shift_in_ee_bits(hw, 8);
+ if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI))
+ break;
+
+ udelay(5);
+ retry_count += 5;
+
+ e1000_standby_eeprom(hw);
+ } while (retry_count < EEPROM_MAX_RETRY_SPI);
+
+ /* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and
+ * only 0-5mSec on 5V devices)
+ */
+ if (retry_count >= EEPROM_MAX_RETRY_SPI) {
+ DEBUGOUT("SPI EEPROM Status error\n");
+ return -E1000_ERR_EEPROM;
+ }
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_read_eeprom - Reads a 16 bit word from the EEPROM.
+ * @hw: Struct containing variables accessed by shared code
+ * @offset: offset of word in the EEPROM to read
+ * @data: word read from the EEPROM
+ * @words: number of words to read
+ */
+s32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
{
- s32 ret_val;
- u16 phy_data, phy_saved_data, speed, duplex, i;
- u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
- {IGP01E1000_PHY_AGC_PARAM_A,
- IGP01E1000_PHY_AGC_PARAM_B,
- IGP01E1000_PHY_AGC_PARAM_C,
- IGP01E1000_PHY_AGC_PARAM_D};
- u16 min_length, max_length;
-
- DEBUGFUNC("e1000_config_dsp_after_link_change");
-
- if (hw->phy_type != e1000_phy_igp)
- return E1000_SUCCESS;
-
- if (link_up) {
- ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
- if (ret_val) {
- DEBUGOUT("Error getting link speed and duplex\n");
- return ret_val;
- }
-
- if (speed == SPEED_1000) {
-
- ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
- if (ret_val)
- return ret_val;
-
- if ((hw->dsp_config_state == e1000_dsp_config_enabled) &&
- min_length >= e1000_igp_cable_length_50) {
-
- for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
- ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i],
- &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
-
- ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i],
- phy_data);
- if (ret_val)
- return ret_val;
- }
- hw->dsp_config_state = e1000_dsp_config_activated;
- }
-
- if ((hw->ffe_config_state == e1000_ffe_config_enabled) &&
- (min_length < e1000_igp_cable_length_50)) {
-
- u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
- u32 idle_errs = 0;
-
- /* clear previous idle error counts */
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- for (i = 0; i < ffe_idle_err_timeout; i++) {
- udelay(1000);
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT);
- if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
- hw->ffe_config_state = e1000_ffe_config_active;
-
- ret_val = e1000_write_phy_reg(hw,
- IGP01E1000_PHY_DSP_FFE,
- IGP01E1000_PHY_DSP_FFE_CM_CP);
- if (ret_val)
- return ret_val;
- break;
- }
-
- if (idle_errs)
- ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_100;
- }
- }
- }
- } else {
- if (hw->dsp_config_state == e1000_dsp_config_activated) {
- /* Save off the current value of register 0x2F5B to be restored at
- * the end of the routines. */
- ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
-
- if (ret_val)
- return ret_val;
-
- /* Disable the PHY transmitter */
- ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
-
- if (ret_val)
- return ret_val;
-
- mdelay(20);
-
- ret_val = e1000_write_phy_reg(hw, 0x0000,
- IGP01E1000_IEEE_FORCE_GIGA);
- if (ret_val)
- return ret_val;
- for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
- ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i], &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
- phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
-
- ret_val = e1000_write_phy_reg(hw,dsp_reg_array[i], phy_data);
- if (ret_val)
- return ret_val;
- }
-
- ret_val = e1000_write_phy_reg(hw, 0x0000,
- IGP01E1000_IEEE_RESTART_AUTONEG);
- if (ret_val)
- return ret_val;
-
- mdelay(20);
-
- /* Now enable the transmitter */
- ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
-
- if (ret_val)
- return ret_val;
-
- hw->dsp_config_state = e1000_dsp_config_enabled;
- }
-
- if (hw->ffe_config_state == e1000_ffe_config_active) {
- /* Save off the current value of register 0x2F5B to be restored at
- * the end of the routines. */
- ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
-
- if (ret_val)
- return ret_val;
-
- /* Disable the PHY transmitter */
- ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
-
- if (ret_val)
- return ret_val;
-
- mdelay(20);
-
- ret_val = e1000_write_phy_reg(hw, 0x0000,
- IGP01E1000_IEEE_FORCE_GIGA);
- if (ret_val)
- return ret_val;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE,
- IGP01E1000_PHY_DSP_FFE_DEFAULT);
- if (ret_val)
- return ret_val;
-
- ret_val = e1000_write_phy_reg(hw, 0x0000,
- IGP01E1000_IEEE_RESTART_AUTONEG);
- if (ret_val)
- return ret_val;
-
- mdelay(20);
-
- /* Now enable the transmitter */
- ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
-
- if (ret_val)
- return ret_val;
-
- hw->ffe_config_state = e1000_ffe_config_enabled;
- }
- }
- return E1000_SUCCESS;
+ s32 ret;
+ spin_lock(&e1000_eeprom_lock);
+ ret = e1000_do_read_eeprom(hw, offset, words, data);
+ spin_unlock(&e1000_eeprom_lock);
+ return ret;
}
-/*****************************************************************************
- * Set PHY to class A mode
- * Assumes the following operations will follow to enable the new class mode.
- * 1. Do a PHY soft reset
- * 2. Restart auto-negotiation or force link.
- *
- * hw - Struct containing variables accessed by shared code
- ****************************************************************************/
-static s32 e1000_set_phy_mode(struct e1000_hw *hw)
+static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
{
- s32 ret_val;
- u16 eeprom_data;
-
- DEBUGFUNC("e1000_set_phy_mode");
-
- if ((hw->mac_type == e1000_82545_rev_3) &&
- (hw->media_type == e1000_media_type_copper)) {
- ret_val = e1000_read_eeprom(hw, EEPROM_PHY_CLASS_WORD, 1, &eeprom_data);
- if (ret_val) {
- return ret_val;
- }
-
- if ((eeprom_data != EEPROM_RESERVED_WORD) &&
- (eeprom_data & EEPROM_PHY_CLASS_A)) {
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x000B);
- if (ret_val)
- return ret_val;
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x8104);
- if (ret_val)
- return ret_val;
-
- hw->phy_reset_disable = false;
- }
- }
-
- return E1000_SUCCESS;
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+ u32 i = 0;
+
+ DEBUGFUNC("e1000_read_eeprom");
+
+ /* If eeprom is not yet detected, do so now */
+ if (eeprom->word_size == 0)
+ e1000_init_eeprom_params(hw);
+
+ /* A check for invalid values: offset too large, too many words, and not
+ * enough words.
+ */
+ if ((offset >= eeprom->word_size)
+ || (words > eeprom->word_size - offset) || (words == 0)) {
+ DEBUGOUT2
+ ("\"words\" parameter out of bounds. Words = %d, size = %d\n",
+ offset, eeprom->word_size);
+ return -E1000_ERR_EEPROM;
+ }
+
+ /* EEPROM's that don't use EERD to read require us to bit-bang the SPI
+ * directly. In this case, we need to acquire the EEPROM so that
+ * FW or other port software does not interrupt.
+ */
+ /* Prepare the EEPROM for bit-bang reading */
+ if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
+ return -E1000_ERR_EEPROM;
+
+ /* Set up the SPI or Microwire EEPROM for bit-bang reading. We have
+ * acquired the EEPROM at this point, so any returns should release it */
+ if (eeprom->type == e1000_eeprom_spi) {
+ u16 word_in;
+ u8 read_opcode = EEPROM_READ_OPCODE_SPI;
+
+ if (e1000_spi_eeprom_ready(hw)) {
+ e1000_release_eeprom(hw);
+ return -E1000_ERR_EEPROM;
+ }
+
+ e1000_standby_eeprom(hw);
+
+ /* Some SPI eeproms use the 8th address bit embedded in the opcode */
+ if ((eeprom->address_bits == 8) && (offset >= 128))
+ read_opcode |= EEPROM_A8_OPCODE_SPI;
+
+ /* Send the READ command (opcode + addr) */
+ e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits);
+ e1000_shift_out_ee_bits(hw, (u16) (offset * 2),
+ eeprom->address_bits);
+
+ /* Read the data. The address of the eeprom internally increments with
+ * each byte (spi) being read, saving on the overhead of eeprom setup
+ * and tear-down. The address counter will roll over if reading beyond
+ * the size of the eeprom, thus allowing the entire memory to be read
+ * starting from any offset. */
+ for (i = 0; i < words; i++) {
+ word_in = e1000_shift_in_ee_bits(hw, 16);
+ data[i] = (word_in >> 8) | (word_in << 8);
+ }
+ } else if (eeprom->type == e1000_eeprom_microwire) {
+ for (i = 0; i < words; i++) {
+ /* Send the READ command (opcode + addr) */
+ e1000_shift_out_ee_bits(hw,
+ EEPROM_READ_OPCODE_MICROWIRE,
+ eeprom->opcode_bits);
+ e1000_shift_out_ee_bits(hw, (u16) (offset + i),
+ eeprom->address_bits);
+
+ /* Read the data. For microwire, each word requires the overhead
+ * of eeprom setup and tear-down. */
+ data[i] = e1000_shift_in_ee_bits(hw, 16);
+ e1000_standby_eeprom(hw);
+ }
+ }
+
+ /* End this read operation */
+ e1000_release_eeprom(hw);
+
+ return E1000_SUCCESS;
}
-/*****************************************************************************
+/**
+ * e1000_validate_eeprom_checksum - Verifies that the EEPROM has a valid checksum
+ * @hw: Struct containing variables accessed by shared code
*
- * This function sets the lplu state according to the active flag. When
- * activating lplu this function also disables smart speed and vise versa.
- * lplu will not be activated unless the device autonegotiation advertisment
- * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes.
- * hw: Struct containing variables accessed by shared code
- * active - true to enable lplu false to disable lplu.
- *
- * returns: - E1000_ERR_PHY if fail to read/write the PHY
- * E1000_SUCCESS at any other case.
- *
- ****************************************************************************/
-
-static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active)
+ * Reads the first 64 16 bit words of the EEPROM and sums the values read.
+ * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
+ * valid.
+ */
+s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw)
{
- u32 phy_ctrl = 0;
- s32 ret_val;
- u16 phy_data;
- DEBUGFUNC("e1000_set_d3_lplu_state");
-
- if (hw->phy_type != e1000_phy_igp && hw->phy_type != e1000_phy_igp_2
- && hw->phy_type != e1000_phy_igp_3)
- return E1000_SUCCESS;
-
- /* During driver activity LPLU should not be used or it will attain link
- * from the lowest speeds starting from 10Mbps. The capability is used for
- * Dx transitions and states */
- if (hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) {
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data);
- if (ret_val)
- return ret_val;
- } else if (hw->mac_type == e1000_ich8lan) {
- /* MAC writes into PHY register based on the state transition
- * and start auto-negotiation. SW driver can overwrite the settings
- * in CSR PHY power control E1000_PHY_CTRL register. */
- phy_ctrl = er32(PHY_CTRL);
- } else {
- ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
- if (ret_val)
- return ret_val;
- }
-
- if (!active) {
- if (hw->mac_type == e1000_82541_rev_2 ||
- hw->mac_type == e1000_82547_rev_2) {
- phy_data &= ~IGP01E1000_GMII_FLEX_SPD;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
- if (ret_val)
- return ret_val;
- } else {
- if (hw->mac_type == e1000_ich8lan) {
- phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;
- ew32(PHY_CTRL, phy_ctrl);
- } else {
- phy_data &= ~IGP02E1000_PM_D3_LPLU;
- ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
- phy_data);
- if (ret_val)
- return ret_val;
- }
- }
-
- /* LPLU and SmartSpeed are mutually exclusive. LPLU is used during
- * Dx states where the power conservation is most important. During
- * driver activity we should enable SmartSpeed, so performance is
- * maintained. */
- if (hw->smart_speed == e1000_smart_speed_on) {
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- phy_data);
- if (ret_val)
- return ret_val;
- } else if (hw->smart_speed == e1000_smart_speed_off) {
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- phy_data);
- if (ret_val)
- return ret_val;
- }
-
- } else if ((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) ||
- (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) ||
- (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) {
-
- if (hw->mac_type == e1000_82541_rev_2 ||
- hw->mac_type == e1000_82547_rev_2) {
- phy_data |= IGP01E1000_GMII_FLEX_SPD;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
- if (ret_val)
- return ret_val;
- } else {
- if (hw->mac_type == e1000_ich8lan) {
- phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
- ew32(PHY_CTRL, phy_ctrl);
- } else {
- phy_data |= IGP02E1000_PM_D3_LPLU;
- ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
- phy_data);
- if (ret_val)
- return ret_val;
- }
- }
-
- /* When LPLU is enabled we should disable SmartSpeed */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data);
- if (ret_val)
- return ret_val;
-
- }
- return E1000_SUCCESS;
+ u16 checksum = 0;
+ u16 i, eeprom_data;
+
+ DEBUGFUNC("e1000_validate_eeprom_checksum");
+
+ for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
+ if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
+ DEBUGOUT("EEPROM Read Error\n");
+ return -E1000_ERR_EEPROM;
+ }
+ checksum += eeprom_data;
+ }
+
+ if (checksum == (u16) EEPROM_SUM)
+ return E1000_SUCCESS;
+ else {
+ DEBUGOUT("EEPROM Checksum Invalid\n");
+ return -E1000_ERR_EEPROM;
+ }
}
-/*****************************************************************************
- *
- * This function sets the lplu d0 state according to the active flag. When
- * activating lplu this function also disables smart speed and vise versa.
- * lplu will not be activated unless the device autonegotiation advertisment
- * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes.
- * hw: Struct containing variables accessed by shared code
- * active - true to enable lplu false to disable lplu.
+/**
+ * e1000_update_eeprom_checksum - Calculates/writes the EEPROM checksum
+ * @hw: Struct containing variables accessed by shared code
*
- * returns: - E1000_ERR_PHY if fail to read/write the PHY
- * E1000_SUCCESS at any other case.
+ * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
+ * Writes the difference to word offset 63 of the EEPROM.
+ */
+s32 e1000_update_eeprom_checksum(struct e1000_hw *hw)
+{
+ u16 checksum = 0;
+ u16 i, eeprom_data;
+
+ DEBUGFUNC("e1000_update_eeprom_checksum");
+
+ for (i = 0; i < EEPROM_CHECKSUM_REG; i++) {
+ if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
+ DEBUGOUT("EEPROM Read Error\n");
+ return -E1000_ERR_EEPROM;
+ }
+ checksum += eeprom_data;
+ }
+ checksum = (u16) EEPROM_SUM - checksum;
+ if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
+ DEBUGOUT("EEPROM Write Error\n");
+ return -E1000_ERR_EEPROM;
+ }
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_write_eeprom - write words to the different EEPROM types.
+ * @hw: Struct containing variables accessed by shared code
+ * @offset: offset within the EEPROM to be written to
+ * @words: number of words to write
+ * @data: 16 bit word to be written to the EEPROM
*
- ****************************************************************************/
+ * If e1000_update_eeprom_checksum is not called after this function, the
+ * EEPROM will most likely contain an invalid checksum.
+ */
+s32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+{
+ s32 ret;
+ spin_lock(&e1000_eeprom_lock);
+ ret = e1000_do_write_eeprom(hw, offset, words, data);
+ spin_unlock(&e1000_eeprom_lock);
+ return ret;
+}
-static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
+static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
{
- u32 phy_ctrl = 0;
- s32 ret_val;
- u16 phy_data;
- DEBUGFUNC("e1000_set_d0_lplu_state");
-
- if (hw->mac_type <= e1000_82547_rev_2)
- return E1000_SUCCESS;
-
- if (hw->mac_type == e1000_ich8lan) {
- phy_ctrl = er32(PHY_CTRL);
- } else {
- ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
- if (ret_val)
- return ret_val;
- }
-
- if (!active) {
- if (hw->mac_type == e1000_ich8lan) {
- phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
- ew32(PHY_CTRL, phy_ctrl);
- } else {
- phy_data &= ~IGP02E1000_PM_D0_LPLU;
- ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
- if (ret_val)
- return ret_val;
- }
-
- /* LPLU and SmartSpeed are mutually exclusive. LPLU is used during
- * Dx states where the power conservation is most important. During
- * driver activity we should enable SmartSpeed, so performance is
- * maintained. */
- if (hw->smart_speed == e1000_smart_speed_on) {
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- phy_data);
- if (ret_val)
- return ret_val;
- } else if (hw->smart_speed == e1000_smart_speed_off) {
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- phy_data);
- if (ret_val)
- return ret_val;
- }
-
-
- } else {
-
- if (hw->mac_type == e1000_ich8lan) {
- phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
- ew32(PHY_CTRL, phy_ctrl);
- } else {
- phy_data |= IGP02E1000_PM_D0_LPLU;
- ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
- if (ret_val)
- return ret_val;
- }
-
- /* When LPLU is enabled we should disable SmartSpeed */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
- if (ret_val)
- return ret_val;
-
- phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data);
- if (ret_val)
- return ret_val;
-
- }
- return E1000_SUCCESS;
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+ s32 status = 0;
+
+ DEBUGFUNC("e1000_write_eeprom");
+
+ /* If eeprom is not yet detected, do so now */
+ if (eeprom->word_size == 0)
+ e1000_init_eeprom_params(hw);
+
+ /* A check for invalid values: offset too large, too many words, and not
+ * enough words.
+ */
+ if ((offset >= eeprom->word_size)
+ || (words > eeprom->word_size - offset) || (words == 0)) {
+ DEBUGOUT("\"words\" parameter out of bounds\n");
+ return -E1000_ERR_EEPROM;
+ }
+
+ /* Prepare the EEPROM for writing */
+ if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
+ return -E1000_ERR_EEPROM;
+
+ if (eeprom->type == e1000_eeprom_microwire) {
+ status = e1000_write_eeprom_microwire(hw, offset, words, data);
+ } else {
+ status = e1000_write_eeprom_spi(hw, offset, words, data);
+ msleep(10);
+ }
+
+ /* Done with writing */
+ e1000_release_eeprom(hw);
+
+ return status;
}
-/******************************************************************************
- * Change VCO speed register to improve Bit Error Rate performance of SERDES.
- *
- * hw - Struct containing variables accessed by shared code
- *****************************************************************************/
-static s32 e1000_set_vco_speed(struct e1000_hw *hw)
+/**
+ * e1000_write_eeprom_spi - Writes a 16 bit word to a given offset in an SPI EEPROM.
+ * @hw: Struct containing variables accessed by shared code
+ * @offset: offset within the EEPROM to be written to
+ * @words: number of words to write
+ * @data: pointer to array of 8 bit words to be written to the EEPROM
+ */
+static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
{
- s32 ret_val;
- u16 default_page = 0;
- u16 phy_data;
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+ u16 widx = 0;
- DEBUGFUNC("e1000_set_vco_speed");
+ DEBUGFUNC("e1000_write_eeprom_spi");
- switch (hw->mac_type) {
- case e1000_82545_rev_3:
- case e1000_82546_rev_3:
- break;
- default:
- return E1000_SUCCESS;
- }
+ while (widx < words) {
+ u8 write_opcode = EEPROM_WRITE_OPCODE_SPI;
- /* Set PHY register 30, page 5, bit 8 to 0 */
+ if (e1000_spi_eeprom_ready(hw))
+ return -E1000_ERR_EEPROM;
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, &default_page);
- if (ret_val)
- return ret_val;
+ e1000_standby_eeprom(hw);
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005);
- if (ret_val)
- return ret_val;
+ /* Send the WRITE ENABLE command (8 bit opcode ) */
+ e1000_shift_out_ee_bits(hw, EEPROM_WREN_OPCODE_SPI,
+ eeprom->opcode_bits);
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
- if (ret_val)
- return ret_val;
+ e1000_standby_eeprom(hw);
- phy_data &= ~M88E1000_PHY_VCO_REG_BIT8;
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
- if (ret_val)
- return ret_val;
+ /* Some SPI eeproms use the 8th address bit embedded in the opcode */
+ if ((eeprom->address_bits == 8) && (offset >= 128))
+ write_opcode |= EEPROM_A8_OPCODE_SPI;
- /* Set PHY register 30, page 4, bit 11 to 1 */
+ /* Send the Write command (8-bit opcode + addr) */
+ e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits);
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004);
- if (ret_val)
- return ret_val;
+ e1000_shift_out_ee_bits(hw, (u16) ((offset + widx) * 2),
+ eeprom->address_bits);
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
- if (ret_val)
- return ret_val;
+ /* Send the data */
- phy_data |= M88E1000_PHY_VCO_REG_BIT11;
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
- if (ret_val)
- return ret_val;
+ /* Loop to allow for up to whole page write (32 bytes) of eeprom */
+ while (widx < words) {
+ u16 word_out = data[widx];
+ word_out = (word_out >> 8) | (word_out << 8);
+ e1000_shift_out_ee_bits(hw, word_out, 16);
+ widx++;
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, default_page);
- if (ret_val)
- return ret_val;
+ /* Some larger eeprom sizes are capable of a 32-byte PAGE WRITE
+ * operation, while the smaller eeproms are capable of an 8-byte
+ * PAGE WRITE operation. Break the inner loop to pass new address
+ */
+ if ((((offset + widx) * 2) % eeprom->page_size) == 0) {
+ e1000_standby_eeprom(hw);
+ break;
+ }
+ }
+ }
- return E1000_SUCCESS;
+ return E1000_SUCCESS;
}
+/**
+ * e1000_write_eeprom_microwire - Writes a 16 bit word to a given offset in a Microwire EEPROM.
+ * @hw: Struct containing variables accessed by shared code
+ * @offset: offset within the EEPROM to be written to
+ * @words: number of words to write
+ * @data: pointer to array of 8 bit words to be written to the EEPROM
+ */
+static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
+ u16 words, u16 *data)
+{
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+ u32 eecd;
+ u16 words_written = 0;
+ u16 i = 0;
+
+ DEBUGFUNC("e1000_write_eeprom_microwire");
+
+ /* Send the write enable command to the EEPROM (3-bit opcode plus
+ * 6/8-bit dummy address beginning with 11). It's less work to include
+ * the 11 of the dummy address as part of the opcode than it is to shift
+ * it over the correct number of bits for the address. This puts the
+ * EEPROM into write/erase mode.
+ */
+ e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE,
+ (u16) (eeprom->opcode_bits + 2));
+
+ e1000_shift_out_ee_bits(hw, 0, (u16) (eeprom->address_bits - 2));
+
+ /* Prepare the EEPROM */
+ e1000_standby_eeprom(hw);
+
+ while (words_written < words) {
+ /* Send the Write command (3-bit opcode + addr) */
+ e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE,
+ eeprom->opcode_bits);
+
+ e1000_shift_out_ee_bits(hw, (u16) (offset + words_written),
+ eeprom->address_bits);
+
+ /* Send the data */
+ e1000_shift_out_ee_bits(hw, data[words_written], 16);
+
+ /* Toggle the CS line. This in effect tells the EEPROM to execute
+ * the previous command.
+ */
+ e1000_standby_eeprom(hw);
+
+ /* Read DO repeatedly until it is high (equal to '1'). The EEPROM will
+ * signal that the command has been completed by raising the DO signal.
+ * If DO does not go high in 10 milliseconds, then error out.
+ */
+ for (i = 0; i < 200; i++) {
+ eecd = er32(EECD);
+ if (eecd & E1000_EECD_DO)
+ break;
+ udelay(50);
+ }
+ if (i == 200) {
+ DEBUGOUT("EEPROM Write did not complete\n");
+ return -E1000_ERR_EEPROM;
+ }
+
+ /* Recover from write */
+ e1000_standby_eeprom(hw);
-/*****************************************************************************
- * This function reads the cookie from ARC ram.
+ words_written++;
+ }
+
+ /* Send the write disable command to the EEPROM (3-bit opcode plus
+ * 6/8-bit dummy address beginning with 10). It's less work to include
+ * the 10 of the dummy address as part of the opcode than it is to shift
+ * it over the correct number of bits for the address. This takes the
+ * EEPROM out of write/erase mode.
+ */
+ e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE,
+ (u16) (eeprom->opcode_bits + 2));
+
+ e1000_shift_out_ee_bits(hw, 0, (u16) (eeprom->address_bits - 2));
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_read_mac_addr - read the adapters MAC from eeprom
+ * @hw: Struct containing variables accessed by shared code
*
- * returns: - E1000_SUCCESS .
- ****************************************************************************/
-static s32 e1000_host_if_read_cookie(struct e1000_hw *hw, u8 *buffer)
+ * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
+ * second function of dual function devices
+ */
+s32 e1000_read_mac_addr(struct e1000_hw *hw)
{
- u8 i;
- u32 offset = E1000_MNG_DHCP_COOKIE_OFFSET;
- u8 length = E1000_MNG_DHCP_COOKIE_LENGTH;
-
- length = (length >> 2);
- offset = (offset >> 2);
-
- for (i = 0; i < length; i++) {
- *((u32 *)buffer + i) =
- E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset + i);
- }
- return E1000_SUCCESS;
-}
+ u16 offset;
+ u16 eeprom_data, i;
+ DEBUGFUNC("e1000_read_mac_addr");
-/*****************************************************************************
- * This function checks whether the HOST IF is enabled for command operaton
- * and also checks whether the previous command is completed.
- * It busy waits in case of previous command is not completed.
+ for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
+ offset = i >> 1;
+ if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
+ DEBUGOUT("EEPROM Read Error\n");
+ return -E1000_ERR_EEPROM;
+ }
+ hw->perm_mac_addr[i] = (u8) (eeprom_data & 0x00FF);
+ hw->perm_mac_addr[i + 1] = (u8) (eeprom_data >> 8);
+ }
+
+ switch (hw->mac_type) {
+ default:
+ break;
+ case e1000_82546:
+ case e1000_82546_rev_3:
+ if (er32(STATUS) & E1000_STATUS_FUNC_1)
+ hw->perm_mac_addr[5] ^= 0x01;
+ break;
+ }
+
+ for (i = 0; i < NODE_ADDRESS_SIZE; i++)
+ hw->mac_addr[i] = hw->perm_mac_addr[i];
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_init_rx_addrs - Initializes receive address filters.
+ * @hw: Struct containing variables accessed by shared code
*
- * returns: - E1000_ERR_HOST_INTERFACE_COMMAND in case if is not ready or
- * timeout
- * - E1000_SUCCESS for success.
- ****************************************************************************/
-static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
+ * Places the MAC address in receive address register 0 and clears the rest
+ * of the receive address registers. Clears the multicast table. Assumes
+ * the receiver is in reset when the routine is called.
+ */
+static void e1000_init_rx_addrs(struct e1000_hw *hw)
{
- u32 hicr;
- u8 i;
-
- /* Check that the host interface is enabled. */
- hicr = er32(HICR);
- if ((hicr & E1000_HICR_EN) == 0) {
- DEBUGOUT("E1000_HOST_EN bit disabled.\n");
- return -E1000_ERR_HOST_INTERFACE_COMMAND;
- }
- /* check the previous command is completed */
- for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
- hicr = er32(HICR);
- if (!(hicr & E1000_HICR_C))
- break;
- mdelay(1);
- }
-
- if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
- DEBUGOUT("Previous command timeout failed .\n");
- return -E1000_ERR_HOST_INTERFACE_COMMAND;
- }
- return E1000_SUCCESS;
+ u32 i;
+ u32 rar_num;
+
+ DEBUGFUNC("e1000_init_rx_addrs");
+
+ /* Setup the receive address. */
+ DEBUGOUT("Programming MAC Address into RAR[0]\n");
+
+ e1000_rar_set(hw, hw->mac_addr, 0);
+
+ rar_num = E1000_RAR_ENTRIES;
+
+ /* Zero out the other 15 receive addresses. */
+ DEBUGOUT("Clearing RAR[1-15]\n");
+ for (i = 1; i < rar_num; i++) {
+ E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
+ E1000_WRITE_FLUSH();
+ E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
+ E1000_WRITE_FLUSH();
+ }
}
-/*****************************************************************************
- * This function writes the buffer content at the offset given on the host if.
- * It also does alignment considerations to do the writes in most efficient way.
- * Also fills up the sum of the buffer in *buffer parameter.
- *
- * returns - E1000_SUCCESS for success.
- ****************************************************************************/
-static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, u16 length,
- u16 offset, u8 *sum)
+/**
+ * e1000_hash_mc_addr - Hashes an address to determine its location in the multicast table
+ * @hw: Struct containing variables accessed by shared code
+ * @mc_addr: the multicast address to hash
+ */
+u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
{
- u8 *tmp;
- u8 *bufptr = buffer;
- u32 data = 0;
- u16 remaining, i, j, prev_bytes;
-
- /* sum = only sum of the data and it is not checksum */
-
- if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
- return -E1000_ERR_PARAM;
- }
-
- tmp = (u8 *)&data;
- prev_bytes = offset & 0x3;
- offset &= 0xFFFC;
- offset >>= 2;
-
- if (prev_bytes) {
- data = E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset);
- for (j = prev_bytes; j < sizeof(u32); j++) {
- *(tmp + j) = *bufptr++;
- *sum += *(tmp + j);
- }
- E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, offset, data);
- length -= j - prev_bytes;
- offset++;
- }
-
- remaining = length & 0x3;
- length -= remaining;
-
- /* Calculate length in DWORDs */
- length >>= 2;
-
- /* The device driver writes the relevant command block into the
- * ram area. */
- for (i = 0; i < length; i++) {
- for (j = 0; j < sizeof(u32); j++) {
- *(tmp + j) = *bufptr++;
- *sum += *(tmp + j);
- }
-
- E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, offset + i, data);
- }
- if (remaining) {
- for (j = 0; j < sizeof(u32); j++) {
- if (j < remaining)
- *(tmp + j) = *bufptr++;
- else
- *(tmp + j) = 0;
-
- *sum += *(tmp + j);
- }
- E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, offset + i, data);
- }
-
- return E1000_SUCCESS;
+ u32 hash_value = 0;
+
+ /* The portion of the address that is used for the hash table is
+ * determined by the mc_filter_type setting.
+ */
+ switch (hw->mc_filter_type) {
+ /* [0] [1] [2] [3] [4] [5]
+ * 01 AA 00 12 34 56
+ * LSB MSB
+ */
+ case 0:
+ /* [47:36] i.e. 0x563 for above example address */
+ hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
+ break;
+ case 1:
+ /* [46:35] i.e. 0xAC6 for above example address */
+ hash_value = ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5));
+ break;
+ case 2:
+ /* [45:34] i.e. 0x5D8 for above example address */
+ hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
+ break;
+ case 3:
+ /* [43:32] i.e. 0x634 for above example address */
+ hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8));
+ break;
+ }
+
+ hash_value &= 0xFFF;
+ return hash_value;
}
+/**
+ * e1000_rar_set - Puts an ethernet address into a receive address register.
+ * @hw: Struct containing variables accessed by shared code
+ * @addr: Address to put into receive address register
+ * @index: Receive address register to write
+ */
+void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
+{
+ u32 rar_low, rar_high;
-/*****************************************************************************
- * This function writes the command header after does the checksum calculation.
- *
- * returns - E1000_SUCCESS for success.
- ****************************************************************************/
-static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
- struct e1000_host_mng_command_header *hdr)
+ /* HW expects these in little endian so we reverse the byte order
+ * from network order (big endian) to little endian
+ */
+ rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) |
+ ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+ rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
+
+ /* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx
+ * unit hang.
+ *
+ * Description:
+ * If there are any Rx frames queued up or otherwise present in the HW
+ * before RSS is enabled, and then we enable RSS, the HW Rx unit will
+ * hang. To work around this issue, we have to disable receives and
+ * flush out all Rx frames before we enable RSS. To do so, we modify we
+ * redirect all Rx traffic to manageability and then reset the HW.
+ * This flushes away Rx frames, and (since the redirections to
+ * manageability persists across resets) keeps new ones from coming in
+ * while we work. Then, we clear the Address Valid AV bit for all MAC
+ * addresses and undo the re-direction to manageability.
+ * Now, frames are coming in again, but the MAC won't accept them, so
+ * far so good. We now proceed to initialize RSS (if necessary) and
+ * configure the Rx unit. Last, we re-enable the AV bits and continue
+ * on our merry way.
+ */
+ switch (hw->mac_type) {
+ default:
+ /* Indicate to hardware the Address is Valid. */
+ rar_high |= E1000_RAH_AV;
+ break;
+ }
+
+ E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
+ E1000_WRITE_FLUSH();
+ E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
+ E1000_WRITE_FLUSH();
+}
+
+/**
+ * e1000_write_vfta - Writes a value to the specified offset in the VLAN filter table.
+ * @hw: Struct containing variables accessed by shared code
+ * @offset: Offset in VLAN filer table to write
+ * @value: Value to write into VLAN filter table
+ */
+void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
{
- u16 i;
- u8 sum;
- u8 *buffer;
+ u32 temp;
+
+ if ((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) {
+ temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1));
+ E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
+ E1000_WRITE_FLUSH();
+ E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp);
+ E1000_WRITE_FLUSH();
+ } else {
+ E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
+ E1000_WRITE_FLUSH();
+ }
+}
- /* Write the whole command header structure which includes sum of
- * the buffer */
+/**
+ * e1000_clear_vfta - Clears the VLAN filer table
+ * @hw: Struct containing variables accessed by shared code
+ */
+static void e1000_clear_vfta(struct e1000_hw *hw)
+{
+ u32 offset;
+ u32 vfta_value = 0;
+ u32 vfta_offset = 0;
+ u32 vfta_bit_in_reg = 0;
+
+ for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
+ /* If the offset we want to clear is the same offset of the
+ * manageability VLAN ID, then clear all bits except that of the
+ * manageability unit */
+ vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
+ E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value);
+ E1000_WRITE_FLUSH();
+ }
+}
- u16 length = sizeof(struct e1000_host_mng_command_header);
+static s32 e1000_id_led_init(struct e1000_hw *hw)
+{
+ u32 ledctl;
+ const u32 ledctl_mask = 0x000000FF;
+ const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON;
+ const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
+ u16 eeprom_data, i, temp;
+ const u16 led_mask = 0x0F;
- sum = hdr->checksum;
- hdr->checksum = 0;
+ DEBUGFUNC("e1000_id_led_init");
- buffer = (u8 *)hdr;
- i = length;
- while (i--)
- sum += buffer[i];
+ if (hw->mac_type < e1000_82540) {
+ /* Nothing to do */
+ return E1000_SUCCESS;
+ }
- hdr->checksum = 0 - sum;
+ ledctl = er32(LEDCTL);
+ hw->ledctl_default = ledctl;
+ hw->ledctl_mode1 = hw->ledctl_default;
+ hw->ledctl_mode2 = hw->ledctl_default;
- length >>= 2;
- /* The device driver writes the relevant command block into the ram area. */
- for (i = 0; i < length; i++) {
- E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((u32 *)hdr + i));
- E1000_WRITE_FLUSH();
- }
+ if (e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) {
+ DEBUGOUT("EEPROM Read Error\n");
+ return -E1000_ERR_EEPROM;
+ }
- return E1000_SUCCESS;
-}
+ if ((eeprom_data == ID_LED_RESERVED_0000) ||
+ (eeprom_data == ID_LED_RESERVED_FFFF)) {
+ eeprom_data = ID_LED_DEFAULT;
+ }
+ for (i = 0; i < 4; i++) {
+ temp = (eeprom_data >> (i << 2)) & led_mask;
+ switch (temp) {
+ case ID_LED_ON1_DEF2:
+ case ID_LED_ON1_ON2:
+ case ID_LED_ON1_OFF2:
+ hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
+ hw->ledctl_mode1 |= ledctl_on << (i << 3);
+ break;
+ case ID_LED_OFF1_DEF2:
+ case ID_LED_OFF1_ON2:
+ case ID_LED_OFF1_OFF2:
+ hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
+ hw->ledctl_mode1 |= ledctl_off << (i << 3);
+ break;
+ default:
+ /* Do nothing */
+ break;
+ }
+ switch (temp) {
+ case ID_LED_DEF1_ON2:
+ case ID_LED_ON1_ON2:
+ case ID_LED_OFF1_ON2:
+ hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
+ hw->ledctl_mode2 |= ledctl_on << (i << 3);
+ break;
+ case ID_LED_DEF1_OFF2:
+ case ID_LED_ON1_OFF2:
+ case ID_LED_OFF1_OFF2:
+ hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
+ hw->ledctl_mode2 |= ledctl_off << (i << 3);
+ break;
+ default:
+ /* Do nothing */
+ break;
+ }
+ }
+ return E1000_SUCCESS;
+}
-/*****************************************************************************
- * This function indicates to ARC that a new command is pending which completes
- * one write operation by the driver.
+/**
+ * e1000_setup_led
+ * @hw: Struct containing variables accessed by shared code
*
- * returns - E1000_SUCCESS for success.
- ****************************************************************************/
-static s32 e1000_mng_write_commit(struct e1000_hw *hw)
+ * Prepares SW controlable LED for use and saves the current state of the LED.
+ */
+s32 e1000_setup_led(struct e1000_hw *hw)
{
- u32 hicr;
+ u32 ledctl;
+ s32 ret_val = E1000_SUCCESS;
- hicr = er32(HICR);
- /* Setting this bit tells the ARC that a new command is pending. */
- ew32(HICR, hicr | E1000_HICR_C);
+ DEBUGFUNC("e1000_setup_led");
- return E1000_SUCCESS;
+ switch (hw->mac_type) {
+ case e1000_82542_rev2_0:
+ case e1000_82542_rev2_1:
+ case e1000_82543:
+ case e1000_82544:
+ /* No setup necessary */
+ break;
+ case e1000_82541:
+ case e1000_82547:
+ case e1000_82541_rev_2:
+ case e1000_82547_rev_2:
+ /* Turn off PHY Smart Power Down (if enabled) */
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO,
+ &hw->phy_spd_default);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
+ (u16) (hw->phy_spd_default &
+ ~IGP01E1000_GMII_SPD));
+ if (ret_val)
+ return ret_val;
+ /* Fall Through */
+ default:
+ if (hw->media_type == e1000_media_type_fiber) {
+ ledctl = er32(LEDCTL);
+ /* Save current LEDCTL settings */
+ hw->ledctl_default = ledctl;
+ /* Turn off LED0 */
+ ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
+ E1000_LEDCTL_LED0_BLINK |
+ E1000_LEDCTL_LED0_MODE_MASK);
+ ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
+ E1000_LEDCTL_LED0_MODE_SHIFT);
+ ew32(LEDCTL, ledctl);
+ } else if (hw->media_type == e1000_media_type_copper)
+ ew32(LEDCTL, hw->ledctl_mode1);
+ break;
+ }
+
+ return E1000_SUCCESS;
}
+/**
+ * e1000_cleanup_led - Restores the saved state of the SW controlable LED.
+ * @hw: Struct containing variables accessed by shared code
+ */
+s32 e1000_cleanup_led(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+
+ DEBUGFUNC("e1000_cleanup_led");
-/*****************************************************************************
- * This function checks the mode of the firmware.
+ switch (hw->mac_type) {
+ case e1000_82542_rev2_0:
+ case e1000_82542_rev2_1:
+ case e1000_82543:
+ case e1000_82544:
+ /* No cleanup necessary */
+ break;
+ case e1000_82541:
+ case e1000_82547:
+ case e1000_82541_rev_2:
+ case e1000_82547_rev_2:
+ /* Turn on PHY Smart Power Down (if previously enabled) */
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
+ hw->phy_spd_default);
+ if (ret_val)
+ return ret_val;
+ /* Fall Through */
+ default:
+ /* Restore LEDCTL settings */
+ ew32(LEDCTL, hw->ledctl_default);
+ break;
+ }
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_led_on - Turns on the software controllable LED
+ * @hw: Struct containing variables accessed by shared code
+ */
+s32 e1000_led_on(struct e1000_hw *hw)
+{
+ u32 ctrl = er32(CTRL);
+
+ DEBUGFUNC("e1000_led_on");
+
+ switch (hw->mac_type) {
+ case e1000_82542_rev2_0:
+ case e1000_82542_rev2_1:
+ case e1000_82543:
+ /* Set SW Defineable Pin 0 to turn on the LED */
+ ctrl |= E1000_CTRL_SWDPIN0;
+ ctrl |= E1000_CTRL_SWDPIO0;
+ break;
+ case e1000_82544:
+ if (hw->media_type == e1000_media_type_fiber) {
+ /* Set SW Defineable Pin 0 to turn on the LED */
+ ctrl |= E1000_CTRL_SWDPIN0;
+ ctrl |= E1000_CTRL_SWDPIO0;
+ } else {
+ /* Clear SW Defineable Pin 0 to turn on the LED */
+ ctrl &= ~E1000_CTRL_SWDPIN0;
+ ctrl |= E1000_CTRL_SWDPIO0;
+ }
+ break;
+ default:
+ if (hw->media_type == e1000_media_type_fiber) {
+ /* Clear SW Defineable Pin 0 to turn on the LED */
+ ctrl &= ~E1000_CTRL_SWDPIN0;
+ ctrl |= E1000_CTRL_SWDPIO0;
+ } else if (hw->media_type == e1000_media_type_copper) {
+ ew32(LEDCTL, hw->ledctl_mode2);
+ return E1000_SUCCESS;
+ }
+ break;
+ }
+
+ ew32(CTRL, ctrl);
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_led_off - Turns off the software controllable LED
+ * @hw: Struct containing variables accessed by shared code
+ */
+s32 e1000_led_off(struct e1000_hw *hw)
+{
+ u32 ctrl = er32(CTRL);
+
+ DEBUGFUNC("e1000_led_off");
+
+ switch (hw->mac_type) {
+ case e1000_82542_rev2_0:
+ case e1000_82542_rev2_1:
+ case e1000_82543:
+ /* Clear SW Defineable Pin 0 to turn off the LED */
+ ctrl &= ~E1000_CTRL_SWDPIN0;
+ ctrl |= E1000_CTRL_SWDPIO0;
+ break;
+ case e1000_82544:
+ if (hw->media_type == e1000_media_type_fiber) {
+ /* Clear SW Defineable Pin 0 to turn off the LED */
+ ctrl &= ~E1000_CTRL_SWDPIN0;
+ ctrl |= E1000_CTRL_SWDPIO0;
+ } else {
+ /* Set SW Defineable Pin 0 to turn off the LED */
+ ctrl |= E1000_CTRL_SWDPIN0;
+ ctrl |= E1000_CTRL_SWDPIO0;
+ }
+ break;
+ default:
+ if (hw->media_type == e1000_media_type_fiber) {
+ /* Set SW Defineable Pin 0 to turn off the LED */
+ ctrl |= E1000_CTRL_SWDPIN0;
+ ctrl |= E1000_CTRL_SWDPIO0;
+ } else if (hw->media_type == e1000_media_type_copper) {
+ ew32(LEDCTL, hw->ledctl_mode1);
+ return E1000_SUCCESS;
+ }
+ break;
+ }
+
+ ew32(CTRL, ctrl);
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_clear_hw_cntrs - Clears all hardware statistics counters.
+ * @hw: Struct containing variables accessed by shared code
+ */
+static void e1000_clear_hw_cntrs(struct e1000_hw *hw)
+{
+ volatile u32 temp;
+
+ temp = er32(CRCERRS);
+ temp = er32(SYMERRS);
+ temp = er32(MPC);
+ temp = er32(SCC);
+ temp = er32(ECOL);
+ temp = er32(MCC);
+ temp = er32(LATECOL);
+ temp = er32(COLC);
+ temp = er32(DC);
+ temp = er32(SEC);
+ temp = er32(RLEC);
+ temp = er32(XONRXC);
+ temp = er32(XONTXC);
+ temp = er32(XOFFRXC);
+ temp = er32(XOFFTXC);
+ temp = er32(FCRUC);
+
+ temp = er32(PRC64);
+ temp = er32(PRC127);
+ temp = er32(PRC255);
+ temp = er32(PRC511);
+ temp = er32(PRC1023);
+ temp = er32(PRC1522);
+
+ temp = er32(GPRC);
+ temp = er32(BPRC);
+ temp = er32(MPRC);
+ temp = er32(GPTC);
+ temp = er32(GORCL);
+ temp = er32(GORCH);
+ temp = er32(GOTCL);
+ temp = er32(GOTCH);
+ temp = er32(RNBC);
+ temp = er32(RUC);
+ temp = er32(RFC);
+ temp = er32(ROC);
+ temp = er32(RJC);
+ temp = er32(TORL);
+ temp = er32(TORH);
+ temp = er32(TOTL);
+ temp = er32(TOTH);
+ temp = er32(TPR);
+ temp = er32(TPT);
+
+ temp = er32(PTC64);
+ temp = er32(PTC127);
+ temp = er32(PTC255);
+ temp = er32(PTC511);
+ temp = er32(PTC1023);
+ temp = er32(PTC1522);
+
+ temp = er32(MPTC);
+ temp = er32(BPTC);
+
+ if (hw->mac_type < e1000_82543)
+ return;
+
+ temp = er32(ALGNERRC);
+ temp = er32(RXERRC);
+ temp = er32(TNCRS);
+ temp = er32(CEXTERR);
+ temp = er32(TSCTC);
+ temp = er32(TSCTFC);
+
+ if (hw->mac_type <= e1000_82544)
+ return;
+
+ temp = er32(MGTPRC);
+ temp = er32(MGTPDC);
+ temp = er32(MGTPTC);
+}
+
+/**
+ * e1000_reset_adaptive - Resets Adaptive IFS to its default state.
+ * @hw: Struct containing variables accessed by shared code
*
- * returns - true when the mode is IAMT or false.
- ****************************************************************************/
-bool e1000_check_mng_mode(struct e1000_hw *hw)
+ * Call this after e1000_init_hw. You may override the IFS defaults by setting
+ * hw->ifs_params_forced to true. However, you must initialize hw->
+ * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio
+ * before calling this function.
+ */
+void e1000_reset_adaptive(struct e1000_hw *hw)
{
- u32 fwsm;
-
- fwsm = er32(FWSM);
-
- if (hw->mac_type == e1000_ich8lan) {
- if ((fwsm & E1000_FWSM_MODE_MASK) ==
- (E1000_MNG_ICH_IAMT_MODE << E1000_FWSM_MODE_SHIFT))
- return true;
- } else if ((fwsm & E1000_FWSM_MODE_MASK) ==
- (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT))
- return true;
+ DEBUGFUNC("e1000_reset_adaptive");
- return false;
+ if (hw->adaptive_ifs) {
+ if (!hw->ifs_params_forced) {
+ hw->current_ifs_val = 0;
+ hw->ifs_min_val = IFS_MIN;
+ hw->ifs_max_val = IFS_MAX;
+ hw->ifs_step_size = IFS_STEP;
+ hw->ifs_ratio = IFS_RATIO;
+ }
+ hw->in_ifs_mode = false;
+ ew32(AIT, 0);
+ } else {
+ DEBUGOUT("Not in Adaptive IFS mode!\n");
+ }
}
-
-/*****************************************************************************
- * This function writes the dhcp info .
- ****************************************************************************/
-s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
+/**
+ * e1000_update_adaptive - update adaptive IFS
+ * @hw: Struct containing variables accessed by shared code
+ * @tx_packets: Number of transmits since last callback
+ * @total_collisions: Number of collisions since last callback
+ *
+ * Called during the callback/watchdog routine to update IFS value based on
+ * the ratio of transmits to collisions.
+ */
+void e1000_update_adaptive(struct e1000_hw *hw)
{
- s32 ret_val;
- struct e1000_host_mng_command_header hdr;
-
- hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
- hdr.command_length = length;
- hdr.reserved1 = 0;
- hdr.reserved2 = 0;
- hdr.checksum = 0;
-
- ret_val = e1000_mng_enable_host_if(hw);
- if (ret_val == E1000_SUCCESS) {
- ret_val = e1000_mng_host_if_write(hw, buffer, length, sizeof(hdr),
- &(hdr.checksum));
- if (ret_val == E1000_SUCCESS) {
- ret_val = e1000_mng_write_cmd_header(hw, &hdr);
- if (ret_val == E1000_SUCCESS)
- ret_val = e1000_mng_write_commit(hw);
- }
- }
- return ret_val;
+ DEBUGFUNC("e1000_update_adaptive");
+
+ if (hw->adaptive_ifs) {
+ if ((hw->collision_delta *hw->ifs_ratio) > hw->tx_packet_delta) {
+ if (hw->tx_packet_delta > MIN_NUM_XMITS) {
+ hw->in_ifs_mode = true;
+ if (hw->current_ifs_val < hw->ifs_max_val) {
+ if (hw->current_ifs_val == 0)
+ hw->current_ifs_val =
+ hw->ifs_min_val;
+ else
+ hw->current_ifs_val +=
+ hw->ifs_step_size;
+ ew32(AIT, hw->current_ifs_val);
+ }
+ }
+ } else {
+ if (hw->in_ifs_mode
+ && (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
+ hw->current_ifs_val = 0;
+ hw->in_ifs_mode = false;
+ ew32(AIT, 0);
+ }
+ }
+ } else {
+ DEBUGOUT("Not in Adaptive IFS mode!\n");
+ }
}
-
-/*****************************************************************************
- * This function calculates the checksum.
+/**
+ * e1000_tbi_adjust_stats
+ * @hw: Struct containing variables accessed by shared code
+ * @frame_len: The length of the frame in question
+ * @mac_addr: The Ethernet destination address of the frame in question
*
- * returns - checksum of buffer contents.
- ****************************************************************************/
-static u8 e1000_calculate_mng_checksum(char *buffer, u32 length)
+ * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
+ */
+void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats,
+ u32 frame_len, u8 *mac_addr)
{
- u8 sum = 0;
- u32 i;
-
- if (!buffer)
- return 0;
+ u64 carry_bit;
- for (i=0; i < length; i++)
- sum += buffer[i];
+ /* First adjust the frame length. */
+ frame_len--;
+ /* We need to adjust the statistics counters, since the hardware
+ * counters overcount this packet as a CRC error and undercount
+ * the packet as a good packet
+ */
+ /* This packet should not be counted as a CRC error. */
+ stats->crcerrs--;
+ /* This packet does count as a Good Packet Received. */
+ stats->gprc++;
+
+ /* Adjust the Good Octets received counters */
+ carry_bit = 0x80000000 & stats->gorcl;
+ stats->gorcl += frame_len;
+ /* If the high bit of Gorcl (the low 32 bits of the Good Octets
+ * Received Count) was one before the addition,
+ * AND it is zero after, then we lost the carry out,
+ * need to add one to Gorch (Good Octets Received Count High).
+ * This could be simplified if all environments supported
+ * 64-bit integers.
+ */
+ if (carry_bit && ((stats->gorcl & 0x80000000) == 0))
+ stats->gorch++;
+ /* Is this a broadcast or multicast? Check broadcast first,
+ * since the test for a multicast frame will test positive on
+ * a broadcast frame.
+ */
+ if ((mac_addr[0] == (u8) 0xff) && (mac_addr[1] == (u8) 0xff))
+ /* Broadcast packet */
+ stats->bprc++;
+ else if (*mac_addr & 0x01)
+ /* Multicast packet */
+ stats->mprc++;
+
+ if (frame_len == hw->max_frame_size) {
+ /* In this case, the hardware has overcounted the number of
+ * oversize frames.
+ */
+ if (stats->roc > 0)
+ stats->roc--;
+ }
- return (u8)(0 - sum);
+ /* Adjust the bin counters when the extra byte put the frame in the
+ * wrong bin. Remember that the frame_len was adjusted above.
+ */
+ if (frame_len == 64) {
+ stats->prc64++;
+ stats->prc127--;
+ } else if (frame_len == 127) {
+ stats->prc127++;
+ stats->prc255--;
+ } else if (frame_len == 255) {
+ stats->prc255++;
+ stats->prc511--;
+ } else if (frame_len == 511) {
+ stats->prc511++;
+ stats->prc1023--;
+ } else if (frame_len == 1023) {
+ stats->prc1023++;
+ stats->prc1522--;
+ } else if (frame_len == 1522) {
+ stats->prc1522++;
+ }
}
-/*****************************************************************************
- * This function checks whether tx pkt filtering needs to be enabled or not.
+/**
+ * e1000_get_bus_info
+ * @hw: Struct containing variables accessed by shared code
*
- * returns - true for packet filtering or false.
- ****************************************************************************/
-bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+ * Gets the current PCI bus type, speed, and width of the hardware
+ */
+void e1000_get_bus_info(struct e1000_hw *hw)
{
- /* called in init as well as watchdog timer functions */
-
- s32 ret_val, checksum;
- bool tx_filter = false;
- struct e1000_host_mng_dhcp_cookie *hdr = &(hw->mng_cookie);
- u8 *buffer = (u8 *) &(hw->mng_cookie);
-
- if (e1000_check_mng_mode(hw)) {
- ret_val = e1000_mng_enable_host_if(hw);
- if (ret_val == E1000_SUCCESS) {
- ret_val = e1000_host_if_read_cookie(hw, buffer);
- if (ret_val == E1000_SUCCESS) {
- checksum = hdr->checksum;
- hdr->checksum = 0;
- if ((hdr->signature == E1000_IAMT_SIGNATURE) &&
- checksum == e1000_calculate_mng_checksum((char *)buffer,
- E1000_MNG_DHCP_COOKIE_LENGTH)) {
- if (hdr->status &
- E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT)
- tx_filter = true;
- } else
- tx_filter = true;
- } else
- tx_filter = true;
- }
- }
-
- hw->tx_pkt_filtering = tx_filter;
- return tx_filter;
+ u32 status;
+
+ switch (hw->mac_type) {
+ case e1000_82542_rev2_0:
+ case e1000_82542_rev2_1:
+ hw->bus_type = e1000_bus_type_pci;
+ hw->bus_speed = e1000_bus_speed_unknown;
+ hw->bus_width = e1000_bus_width_unknown;
+ break;
+ default:
+ status = er32(STATUS);
+ hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
+ e1000_bus_type_pcix : e1000_bus_type_pci;
+
+ if (hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
+ hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ?
+ e1000_bus_speed_66 : e1000_bus_speed_120;
+ } else if (hw->bus_type == e1000_bus_type_pci) {
+ hw->bus_speed = (status & E1000_STATUS_PCI66) ?
+ e1000_bus_speed_66 : e1000_bus_speed_33;
+ } else {
+ switch (status & E1000_STATUS_PCIX_SPEED) {
+ case E1000_STATUS_PCIX_SPEED_66:
+ hw->bus_speed = e1000_bus_speed_66;
+ break;
+ case E1000_STATUS_PCIX_SPEED_100:
+ hw->bus_speed = e1000_bus_speed_100;
+ break;
+ case E1000_STATUS_PCIX_SPEED_133:
+ hw->bus_speed = e1000_bus_speed_133;
+ break;
+ default:
+ hw->bus_speed = e1000_bus_speed_reserved;
+ break;
+ }
+ }
+ hw->bus_width = (status & E1000_STATUS_BUS64) ?
+ e1000_bus_width_64 : e1000_bus_width_32;
+ break;
+ }
}
-/******************************************************************************
- * Verifies the hardware needs to allow ARPs to be processed by the host
- *
- * hw - Struct containing variables accessed by shared code
- *
- * returns: - true/false
+/**
+ * e1000_write_reg_io
+ * @hw: Struct containing variables accessed by shared code
+ * @offset: offset to write to
+ * @value: value to write
*
- *****************************************************************************/
-u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw)
+ * Writes a value to one of the devices registers using port I/O (as opposed to
+ * memory mapped I/O). Only 82544 and newer devices support port I/O.
+ */
+static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value)
{
- u32 manc;
- u32 fwsm, factps;
-
- if (hw->asf_firmware_present) {
- manc = er32(MANC);
-
- if (!(manc & E1000_MANC_RCV_TCO_EN) ||
- !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
- return false;
- if (e1000_arc_subsystem_valid(hw)) {
- fwsm = er32(FWSM);
- factps = er32(FACTPS);
-
- if ((((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT) ==
- e1000_mng_mode_pt) && !(factps & E1000_FACTPS_MNGCG))
- return true;
- } else
- if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
- return true;
- }
- return false;
-}
+ unsigned long io_addr = hw->io_base;
+ unsigned long io_data = hw->io_base + 4;
-static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw)
-{
- s32 ret_val;
- u16 mii_status_reg;
- u16 i;
-
- /* Polarity reversal workaround for forced 10F/10H links. */
-
- /* Disable the transmitter on the PHY */
-
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
- if (ret_val)
- return ret_val;
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
- if (ret_val)
- return ret_val;
-
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
- if (ret_val)
- return ret_val;
-
- /* This loop will early-out if the NO link condition has been met. */
- for (i = PHY_FORCE_TIME; i > 0; i--) {
- /* Read the MII Status Register and wait for Link Status bit
- * to be clear.
- */
-
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
- if (ret_val)
- return ret_val;
-
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
- if (ret_val)
- return ret_val;
-
- if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0) break;
- mdelay(100);
- }
-
- /* Recommended delay time after link has been lost */
- mdelay(1000);
-
- /* Now we will re-enable th transmitter on the PHY */
-
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
- if (ret_val)
- return ret_val;
- mdelay(50);
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
- if (ret_val)
- return ret_val;
- mdelay(50);
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
- if (ret_val)
- return ret_val;
- mdelay(50);
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
- if (ret_val)
- return ret_val;
-
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
- if (ret_val)
- return ret_val;
-
- /* This loop will early-out if the link condition has been met. */
- for (i = PHY_FORCE_TIME; i > 0; i--) {
- /* Read the MII Status Register and wait for Link Status bit
- * to be set.
- */
-
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
- if (ret_val)
- return ret_val;
-
- ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
- if (ret_val)
- return ret_val;
-
- if (mii_status_reg & MII_SR_LINK_STATUS) break;
- mdelay(100);
- }
- return E1000_SUCCESS;
+ e1000_io_write(hw, io_addr, offset);
+ e1000_io_write(hw, io_data, value);
}
-/***************************************************************************
+/**
+ * e1000_get_cable_length - Estimates the cable length.
+ * @hw: Struct containing variables accessed by shared code
+ * @min_length: The estimated minimum length
+ * @max_length: The estimated maximum length
*
- * Disables PCI-Express master access.
- *
- * hw: Struct containing variables accessed by shared code
- *
- * returns: - none.
+ * returns: - E1000_ERR_XXX
+ * E1000_SUCCESS
*
- ***************************************************************************/
-static void e1000_set_pci_express_master_disable(struct e1000_hw *hw)
+ * This function always returns a ranged length (minimum & maximum).
+ * So for M88 phy's, this function interprets the one value returned from the
+ * register to the minimum and maximum range.
+ * For IGP phy's, the function calculates the range by the AGC registers.
+ */
+static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
+ u16 *max_length)
{
- u32 ctrl;
-
- DEBUGFUNC("e1000_set_pci_express_master_disable");
+ s32 ret_val;
+ u16 agc_value = 0;
+ u16 i, phy_data;
+ u16 cable_length;
- if (hw->bus_type != e1000_bus_type_pci_express)
- return;
+ DEBUGFUNC("e1000_get_cable_length");
- ctrl = er32(CTRL);
- ctrl |= E1000_CTRL_GIO_MASTER_DISABLE;
- ew32(CTRL, ctrl);
-}
+ *min_length = *max_length = 0;
-/*******************************************************************************
- *
- * Disables PCI-Express master access and verifies there are no pending requests
- *
- * hw: Struct containing variables accessed by shared code
- *
- * returns: - E1000_ERR_MASTER_REQUESTS_PENDING if master disable bit hasn't
- * caused the master requests to be disabled.
- * E1000_SUCCESS master requests disabled.
- *
- ******************************************************************************/
-s32 e1000_disable_pciex_master(struct e1000_hw *hw)
-{
- s32 timeout = MASTER_DISABLE_TIMEOUT; /* 80ms */
+ /* Use old method for Phy older than IGP */
+ if (hw->phy_type == e1000_phy_m88) {
- DEBUGFUNC("e1000_disable_pciex_master");
+ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+ cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
+ M88E1000_PSSR_CABLE_LENGTH_SHIFT;
- if (hw->bus_type != e1000_bus_type_pci_express)
- return E1000_SUCCESS;
+ /* Convert the enum value to ranged values */
+ switch (cable_length) {
+ case e1000_cable_length_50:
+ *min_length = 0;
+ *max_length = e1000_igp_cable_length_50;
+ break;
+ case e1000_cable_length_50_80:
+ *min_length = e1000_igp_cable_length_50;
+ *max_length = e1000_igp_cable_length_80;
+ break;
+ case e1000_cable_length_80_110:
+ *min_length = e1000_igp_cable_length_80;
+ *max_length = e1000_igp_cable_length_110;
+ break;
+ case e1000_cable_length_110_140:
+ *min_length = e1000_igp_cable_length_110;
+ *max_length = e1000_igp_cable_length_140;
+ break;
+ case e1000_cable_length_140:
+ *min_length = e1000_igp_cable_length_140;
+ *max_length = e1000_igp_cable_length_170;
+ break;
+ default:
+ return -E1000_ERR_PHY;
+ break;
+ }
+ } else if (hw->phy_type == e1000_phy_igp) { /* For IGP PHY */
+ u16 cur_agc_value;
+ u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
+ u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
+ { IGP01E1000_PHY_AGC_A,
+ IGP01E1000_PHY_AGC_B,
+ IGP01E1000_PHY_AGC_C,
+ IGP01E1000_PHY_AGC_D
+ };
+ /* Read the AGC registers for all channels */
+ for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
+
+ ret_val =
+ e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ cur_agc_value = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT;
+
+ /* Value bound check. */
+ if ((cur_agc_value >=
+ IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1)
+ || (cur_agc_value == 0))
+ return -E1000_ERR_PHY;
+
+ agc_value += cur_agc_value;
+
+ /* Update minimal AGC value. */
+ if (min_agc_value > cur_agc_value)
+ min_agc_value = cur_agc_value;
+ }
- e1000_set_pci_express_master_disable(hw);
+ /* Remove the minimal AGC result for length < 50m */
+ if (agc_value <
+ IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) {
+ agc_value -= min_agc_value;
- while (timeout) {
- if (!(er32(STATUS) & E1000_STATUS_GIO_MASTER_ENABLE))
- break;
- else
- udelay(100);
- timeout--;
- }
+ /* Get the average length of the remaining 3 channels */
+ agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1);
+ } else {
+ /* Get the average length of all the 4 channels. */
+ agc_value /= IGP01E1000_PHY_CHANNEL_NUM;
+ }
- if (!timeout) {
- DEBUGOUT("Master requests are pending.\n");
- return -E1000_ERR_MASTER_REQUESTS_PENDING;
- }
+ /* Set the range of the calculated length. */
+ *min_length = ((e1000_igp_cable_length_table[agc_value] -
+ IGP01E1000_AGC_RANGE) > 0) ?
+ (e1000_igp_cable_length_table[agc_value] -
+ IGP01E1000_AGC_RANGE) : 0;
+ *max_length = e1000_igp_cable_length_table[agc_value] +
+ IGP01E1000_AGC_RANGE;
+ }
- return E1000_SUCCESS;
+ return E1000_SUCCESS;
}
-/*******************************************************************************
- *
- * Check for EEPROM Auto Read bit done.
- *
- * hw: Struct containing variables accessed by shared code
+/**
+ * e1000_check_polarity - Check the cable polarity
+ * @hw: Struct containing variables accessed by shared code
+ * @polarity: output parameter : 0 - Polarity is not reversed
+ * 1 - Polarity is reversed.
*
- * returns: - E1000_ERR_RESET if fail to reset MAC
- * E1000_SUCCESS at any other case.
+ * returns: - E1000_ERR_XXX
+ * E1000_SUCCESS
*
- ******************************************************************************/
-static s32 e1000_get_auto_rd_done(struct e1000_hw *hw)
+ * For phy's older than IGP, this function simply reads the polarity bit in the
+ * Phy Status register. For IGP phy's, this bit is valid only if link speed is
+ * 10 Mbps. If the link speed is 100 Mbps there is no polarity so this bit will
+ * return 0. If the link speed is 1000 Mbps the polarity status is in the
+ * IGP01E1000_PHY_PCS_INIT_REG.
+ */
+static s32 e1000_check_polarity(struct e1000_hw *hw,
+ e1000_rev_polarity *polarity)
{
- s32 timeout = AUTO_READ_DONE_TIMEOUT;
-
- DEBUGFUNC("e1000_get_auto_rd_done");
-
- switch (hw->mac_type) {
- default:
- msleep(5);
- break;
- case e1000_82571:
- case e1000_82572:
- case e1000_82573:
- case e1000_80003es2lan:
- case e1000_ich8lan:
- while (timeout) {
- if (er32(EECD) & E1000_EECD_AUTO_RD)
- break;
- else msleep(1);
- timeout--;
- }
-
- if (!timeout) {
- DEBUGOUT("Auto read by HW from EEPROM has not completed.\n");
- return -E1000_ERR_RESET;
- }
- break;
- }
-
- /* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high.
- * Need to wait for PHY configuration completion before accessing NVM
- * and PHY. */
- if (hw->mac_type == e1000_82573)
- msleep(25);
-
- return E1000_SUCCESS;
+ s32 ret_val;
+ u16 phy_data;
+
+ DEBUGFUNC("e1000_check_polarity");
+
+ if (hw->phy_type == e1000_phy_m88) {
+ /* return the Polarity bit in the Status register. */
+ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+ *polarity = ((phy_data & M88E1000_PSSR_REV_POLARITY) >>
+ M88E1000_PSSR_REV_POLARITY_SHIFT) ?
+ e1000_rev_polarity_reversed : e1000_rev_polarity_normal;
+
+ } else if (hw->phy_type == e1000_phy_igp) {
+ /* Read the Status register to check the speed */
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* If speed is 1000 Mbps, must read the IGP01E1000_PHY_PCS_INIT_REG to
+ * find the polarity status */
+ if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
+ IGP01E1000_PSSR_SPEED_1000MBPS) {
+
+ /* Read the GIG initialization PCS register (0x00B4) */
+ ret_val =
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* Check the polarity bits */
+ *polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ?
+ e1000_rev_polarity_reversed :
+ e1000_rev_polarity_normal;
+ } else {
+ /* For 10 Mbps, read the polarity bit in the status register. (for
+ * 100 Mbps this bit is always 0) */
+ *polarity =
+ (phy_data & IGP01E1000_PSSR_POLARITY_REVERSED) ?
+ e1000_rev_polarity_reversed :
+ e1000_rev_polarity_normal;
+ }
+ }
+ return E1000_SUCCESS;
}
-/***************************************************************************
- * Checks if the PHY configuration is done
- *
- * hw: Struct containing variables accessed by shared code
+/**
+ * e1000_check_downshift - Check if Downshift occurred
+ * @hw: Struct containing variables accessed by shared code
+ * @downshift: output parameter : 0 - No Downshift occurred.
+ * 1 - Downshift occurred.
*
- * returns: - E1000_ERR_RESET if fail to reset MAC
- * E1000_SUCCESS at any other case.
+ * returns: - E1000_ERR_XXX
+ * E1000_SUCCESS
*
- ***************************************************************************/
-static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw)
+ * For phy's older than IGP, this function reads the Downshift bit in the Phy
+ * Specific Status register. For IGP phy's, it reads the Downgrade bit in the
+ * Link Health register. In IGP this bit is latched high, so the driver must
+ * read it immediately after link is established.
+ */
+static s32 e1000_check_downshift(struct e1000_hw *hw)
{
- s32 timeout = PHY_CFG_TIMEOUT;
- u32 cfg_mask = E1000_EEPROM_CFG_DONE;
-
- DEBUGFUNC("e1000_get_phy_cfg_done");
-
- switch (hw->mac_type) {
- default:
- mdelay(10);
- break;
- case e1000_80003es2lan:
- /* Separate *_CFG_DONE_* bit for each port */
- if (er32(STATUS) & E1000_STATUS_FUNC_1)
- cfg_mask = E1000_EEPROM_CFG_DONE_PORT_1;
- /* Fall Through */
- case e1000_82571:
- case e1000_82572:
- while (timeout) {
- if (er32(EEMNGCTL) & cfg_mask)
- break;
- else
- msleep(1);
- timeout--;
- }
- if (!timeout) {
- DEBUGOUT("MNG configuration cycle has not completed.\n");
- return -E1000_ERR_RESET;
- }
- break;
- }
-
- return E1000_SUCCESS;
-}
+ s32 ret_val;
+ u16 phy_data;
-/***************************************************************************
- *
- * Using the combination of SMBI and SWESMBI semaphore bits when resetting
- * adapter or Eeprom access.
- *
- * hw: Struct containing variables accessed by shared code
- *
- * returns: - E1000_ERR_EEPROM if fail to access EEPROM.
- * E1000_SUCCESS at any other case.
- *
- ***************************************************************************/
-static s32 e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
-{
- s32 timeout;
- u32 swsm;
-
- DEBUGFUNC("e1000_get_hw_eeprom_semaphore");
-
- if (!hw->eeprom_semaphore_present)
- return E1000_SUCCESS;
-
- if (hw->mac_type == e1000_80003es2lan) {
- /* Get the SW semaphore. */
- if (e1000_get_software_semaphore(hw) != E1000_SUCCESS)
- return -E1000_ERR_EEPROM;
- }
-
- /* Get the FW semaphore. */
- timeout = hw->eeprom.word_size + 1;
- while (timeout) {
- swsm = er32(SWSM);
- swsm |= E1000_SWSM_SWESMBI;
- ew32(SWSM, swsm);
- /* if we managed to set the bit we got the semaphore. */
- swsm = er32(SWSM);
- if (swsm & E1000_SWSM_SWESMBI)
- break;
-
- udelay(50);
- timeout--;
- }
-
- if (!timeout) {
- /* Release semaphores */
- e1000_put_hw_eeprom_semaphore(hw);
- DEBUGOUT("Driver can't access the Eeprom - SWESMBI bit is set.\n");
- return -E1000_ERR_EEPROM;
- }
-
- return E1000_SUCCESS;
-}
+ DEBUGFUNC("e1000_check_downshift");
-/***************************************************************************
- * This function clears HW semaphore bits.
- *
- * hw: Struct containing variables accessed by shared code
- *
- * returns: - None.
- *
- ***************************************************************************/
-static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
-{
- u32 swsm;
+ if (hw->phy_type == e1000_phy_igp) {
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
- DEBUGFUNC("e1000_put_hw_eeprom_semaphore");
+ hw->speed_downgraded =
+ (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0;
+ } else if (hw->phy_type == e1000_phy_m88) {
+ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
- if (!hw->eeprom_semaphore_present)
- return;
+ hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >>
+ M88E1000_PSSR_DOWNSHIFT_SHIFT;
+ }
- swsm = er32(SWSM);
- if (hw->mac_type == e1000_80003es2lan) {
- /* Release both semaphores. */
- swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
- } else
- swsm &= ~(E1000_SWSM_SWESMBI);
- ew32(SWSM, swsm);
+ return E1000_SUCCESS;
}
-/***************************************************************************
- *
- * Obtaining software semaphore bit (SMBI) before resetting PHY.
+/**
+ * e1000_config_dsp_after_link_change
+ * @hw: Struct containing variables accessed by shared code
+ * @link_up: was link up at the time this was called
*
- * hw: Struct containing variables accessed by shared code
- *
- * returns: - E1000_ERR_RESET if fail to obtain semaphore.
+ * returns: - E1000_ERR_PHY if fail to read/write the PHY
* E1000_SUCCESS at any other case.
*
- ***************************************************************************/
-static s32 e1000_get_software_semaphore(struct e1000_hw *hw)
-{
- s32 timeout = hw->eeprom.word_size + 1;
- u32 swsm;
-
- DEBUGFUNC("e1000_get_software_semaphore");
-
- if (hw->mac_type != e1000_80003es2lan) {
- return E1000_SUCCESS;
- }
-
- while (timeout) {
- swsm = er32(SWSM);
- /* If SMBI bit cleared, it is now set and we hold the semaphore */
- if (!(swsm & E1000_SWSM_SMBI))
- break;
- mdelay(1);
- timeout--;
- }
-
- if (!timeout) {
- DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
- return -E1000_ERR_RESET;
- }
-
- return E1000_SUCCESS;
-}
+ * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a
+ * gigabit link is achieved to improve link quality.
+ */
-/***************************************************************************
- *
- * Release semaphore bit (SMBI).
- *
- * hw: Struct containing variables accessed by shared code
- *
- ***************************************************************************/
-static void e1000_release_software_semaphore(struct e1000_hw *hw)
+static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
{
- u32 swsm;
-
- DEBUGFUNC("e1000_release_software_semaphore");
-
- if (hw->mac_type != e1000_80003es2lan) {
- return;
- }
+ s32 ret_val;
+ u16 phy_data, phy_saved_data, speed, duplex, i;
+ u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
+ { IGP01E1000_PHY_AGC_PARAM_A,
+ IGP01E1000_PHY_AGC_PARAM_B,
+ IGP01E1000_PHY_AGC_PARAM_C,
+ IGP01E1000_PHY_AGC_PARAM_D
+ };
+ u16 min_length, max_length;
+
+ DEBUGFUNC("e1000_config_dsp_after_link_change");
+
+ if (hw->phy_type != e1000_phy_igp)
+ return E1000_SUCCESS;
+
+ if (link_up) {
+ ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
+ if (ret_val) {
+ DEBUGOUT("Error getting link speed and duplex\n");
+ return ret_val;
+ }
- swsm = er32(SWSM);
- /* Release the SW semaphores.*/
- swsm &= ~E1000_SWSM_SMBI;
- ew32(SWSM, swsm);
-}
+ if (speed == SPEED_1000) {
+
+ ret_val =
+ e1000_get_cable_length(hw, &min_length,
+ &max_length);
+ if (ret_val)
+ return ret_val;
+
+ if ((hw->dsp_config_state == e1000_dsp_config_enabled)
+ && min_length >= e1000_igp_cable_length_50) {
+
+ for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
+ ret_val =
+ e1000_read_phy_reg(hw,
+ dsp_reg_array[i],
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data &=
+ ~IGP01E1000_PHY_EDAC_MU_INDEX;
+
+ ret_val =
+ e1000_write_phy_reg(hw,
+ dsp_reg_array
+ [i], phy_data);
+ if (ret_val)
+ return ret_val;
+ }
+ hw->dsp_config_state =
+ e1000_dsp_config_activated;
+ }
+
+ if ((hw->ffe_config_state == e1000_ffe_config_enabled)
+ && (min_length < e1000_igp_cable_length_50)) {
+
+ u16 ffe_idle_err_timeout =
+ FFE_IDLE_ERR_COUNT_TIMEOUT_20;
+ u32 idle_errs = 0;
+
+ /* clear previous idle error counts */
+ ret_val =
+ e1000_read_phy_reg(hw, PHY_1000T_STATUS,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ for (i = 0; i < ffe_idle_err_timeout; i++) {
+ udelay(1000);
+ ret_val =
+ e1000_read_phy_reg(hw,
+ PHY_1000T_STATUS,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ idle_errs +=
+ (phy_data &
+ SR_1000T_IDLE_ERROR_CNT);
+ if (idle_errs >
+ SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT)
+ {
+ hw->ffe_config_state =
+ e1000_ffe_config_active;
+
+ ret_val =
+ e1000_write_phy_reg(hw,
+ IGP01E1000_PHY_DSP_FFE,
+ IGP01E1000_PHY_DSP_FFE_CM_CP);
+ if (ret_val)
+ return ret_val;
+ break;
+ }
+
+ if (idle_errs)
+ ffe_idle_err_timeout =
+ FFE_IDLE_ERR_COUNT_TIMEOUT_100;
+ }
+ }
+ }
+ } else {
+ if (hw->dsp_config_state == e1000_dsp_config_activated) {
+ /* Save off the current value of register 0x2F5B to be restored at
+ * the end of the routines. */
+ ret_val =
+ e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
+
+ if (ret_val)
+ return ret_val;
+
+ /* Disable the PHY transmitter */
+ ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
+
+ if (ret_val)
+ return ret_val;
+
+ mdelay(20);
+
+ ret_val = e1000_write_phy_reg(hw, 0x0000,
+ IGP01E1000_IEEE_FORCE_GIGA);
+ if (ret_val)
+ return ret_val;
+ for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
+ ret_val =
+ e1000_read_phy_reg(hw, dsp_reg_array[i],
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
+ phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
+
+ ret_val =
+ e1000_write_phy_reg(hw, dsp_reg_array[i],
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ }
+
+ ret_val = e1000_write_phy_reg(hw, 0x0000,
+ IGP01E1000_IEEE_RESTART_AUTONEG);
+ if (ret_val)
+ return ret_val;
+
+ mdelay(20);
+
+ /* Now enable the transmitter */
+ ret_val =
+ e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
+
+ if (ret_val)
+ return ret_val;
+
+ hw->dsp_config_state = e1000_dsp_config_enabled;
+ }
-/******************************************************************************
- * Checks if PHY reset is blocked due to SOL/IDER session, for example.
- * Returning E1000_BLK_PHY_RESET isn't necessarily an error. But it's up to
- * the caller to figure out how to deal with it.
- *
- * hw - Struct containing variables accessed by shared code
- *
- * returns: - E1000_BLK_PHY_RESET
- * E1000_SUCCESS
- *
- *****************************************************************************/
-s32 e1000_check_phy_reset_block(struct e1000_hw *hw)
-{
- u32 manc = 0;
- u32 fwsm = 0;
-
- if (hw->mac_type == e1000_ich8lan) {
- fwsm = er32(FWSM);
- return (fwsm & E1000_FWSM_RSPCIPHY) ? E1000_SUCCESS
- : E1000_BLK_PHY_RESET;
- }
-
- if (hw->mac_type > e1000_82547_rev_2)
- manc = er32(MANC);
- return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
- E1000_BLK_PHY_RESET : E1000_SUCCESS;
-}
+ if (hw->ffe_config_state == e1000_ffe_config_active) {
+ /* Save off the current value of register 0x2F5B to be restored at
+ * the end of the routines. */
+ ret_val =
+ e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
-static u8 e1000_arc_subsystem_valid(struct e1000_hw *hw)
-{
- u32 fwsm;
-
- /* On 8257x silicon, registers in the range of 0x8800 - 0x8FFC
- * may not be provided a DMA clock when no manageability features are
- * enabled. We do not want to perform any reads/writes to these registers
- * if this is the case. We read FWSM to determine the manageability mode.
- */
- switch (hw->mac_type) {
- case e1000_82571:
- case e1000_82572:
- case e1000_82573:
- case e1000_80003es2lan:
- fwsm = er32(FWSM);
- if ((fwsm & E1000_FWSM_MODE_MASK) != 0)
- return true;
- break;
- case e1000_ich8lan:
- return true;
- default:
- break;
- }
- return false;
-}
+ if (ret_val)
+ return ret_val;
+ /* Disable the PHY transmitter */
+ ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
-/******************************************************************************
- * Configure PCI-Ex no-snoop
- *
- * hw - Struct containing variables accessed by shared code.
- * no_snoop - Bitmap of no-snoop events.
- *
- * returns: E1000_SUCCESS
- *
- *****************************************************************************/
-static s32 e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, u32 no_snoop)
-{
- u32 gcr_reg = 0;
+ if (ret_val)
+ return ret_val;
- DEBUGFUNC("e1000_set_pci_ex_no_snoop");
+ mdelay(20);
- if (hw->bus_type == e1000_bus_type_unknown)
- e1000_get_bus_info(hw);
+ ret_val = e1000_write_phy_reg(hw, 0x0000,
+ IGP01E1000_IEEE_FORCE_GIGA);
+ if (ret_val)
+ return ret_val;
+ ret_val =
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE,
+ IGP01E1000_PHY_DSP_FFE_DEFAULT);
+ if (ret_val)
+ return ret_val;
- if (hw->bus_type != e1000_bus_type_pci_express)
- return E1000_SUCCESS;
+ ret_val = e1000_write_phy_reg(hw, 0x0000,
+ IGP01E1000_IEEE_RESTART_AUTONEG);
+ if (ret_val)
+ return ret_val;
- if (no_snoop) {
- gcr_reg = er32(GCR);
- gcr_reg &= ~(PCI_EX_NO_SNOOP_ALL);
- gcr_reg |= no_snoop;
- ew32(GCR, gcr_reg);
- }
- if (hw->mac_type == e1000_ich8lan) {
- u32 ctrl_ext;
+ mdelay(20);
- ew32(GCR, PCI_EX_82566_SNOOP_ALL);
+ /* Now enable the transmitter */
+ ret_val =
+ e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
- ctrl_ext = er32(CTRL_EXT);
- ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
- ew32(CTRL_EXT, ctrl_ext);
- }
+ if (ret_val)
+ return ret_val;
- return E1000_SUCCESS;
+ hw->ffe_config_state = e1000_ffe_config_enabled;
+ }
+ }
+ return E1000_SUCCESS;
}
-/***************************************************************************
+/**
+ * e1000_set_phy_mode - Set PHY to class A mode
+ * @hw: Struct containing variables accessed by shared code
*
- * Get software semaphore FLAG bit (SWFLAG).
- * SWFLAG is used to synchronize the access to all shared resource between
- * SW, FW and HW.
- *
- * hw: Struct containing variables accessed by shared code
- *
- ***************************************************************************/
-static s32 e1000_get_software_flag(struct e1000_hw *hw)
+ * Assumes the following operations will follow to enable the new class mode.
+ * 1. Do a PHY soft reset
+ * 2. Restart auto-negotiation or force link.
+ */
+static s32 e1000_set_phy_mode(struct e1000_hw *hw)
{
- s32 timeout = PHY_CFG_TIMEOUT;
- u32 extcnf_ctrl;
-
- DEBUGFUNC("e1000_get_software_flag");
-
- if (hw->mac_type == e1000_ich8lan) {
- while (timeout) {
- extcnf_ctrl = er32(EXTCNF_CTRL);
- extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
- ew32(EXTCNF_CTRL, extcnf_ctrl);
-
- extcnf_ctrl = er32(EXTCNF_CTRL);
- if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)
- break;
- mdelay(1);
- timeout--;
- }
-
- if (!timeout) {
- DEBUGOUT("FW or HW locks the resource too long.\n");
- return -E1000_ERR_CONFIG;
- }
- }
-
- return E1000_SUCCESS;
+ s32 ret_val;
+ u16 eeprom_data;
+
+ DEBUGFUNC("e1000_set_phy_mode");
+
+ if ((hw->mac_type == e1000_82545_rev_3) &&
+ (hw->media_type == e1000_media_type_copper)) {
+ ret_val =
+ e1000_read_eeprom(hw, EEPROM_PHY_CLASS_WORD, 1,
+ &eeprom_data);
+ if (ret_val) {
+ return ret_val;
+ }
+
+ if ((eeprom_data != EEPROM_RESERVED_WORD) &&
+ (eeprom_data & EEPROM_PHY_CLASS_A)) {
+ ret_val =
+ e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
+ 0x000B);
+ if (ret_val)
+ return ret_val;
+ ret_val =
+ e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL,
+ 0x8104);
+ if (ret_val)
+ return ret_val;
+
+ hw->phy_reset_disable = false;
+ }
+ }
+
+ return E1000_SUCCESS;
}
-/***************************************************************************
- *
- * Release software semaphore FLAG bit (SWFLAG).
- * SWFLAG is used to synchronize the access to all shared resource between
- * SW, FW and HW.
+/**
+ * e1000_set_d3_lplu_state - set d3 link power state
+ * @hw: Struct containing variables accessed by shared code
+ * @active: true to enable lplu false to disable lplu.
*
- * hw: Struct containing variables accessed by shared code
+ * This function sets the lplu state according to the active flag. When
+ * activating lplu this function also disables smart speed and vise versa.
+ * lplu will not be activated unless the device autonegotiation advertisement
+ * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes.
*
- ***************************************************************************/
-static void e1000_release_software_flag(struct e1000_hw *hw)
+ * returns: - E1000_ERR_PHY if fail to read/write the PHY
+ * E1000_SUCCESS at any other case.
+ */
+static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active)
{
- u32 extcnf_ctrl;
+ s32 ret_val;
+ u16 phy_data;
+ DEBUGFUNC("e1000_set_d3_lplu_state");
+
+ if (hw->phy_type != e1000_phy_igp)
+ return E1000_SUCCESS;
+
+ /* During driver activity LPLU should not be used or it will attain link
+ * from the lowest speeds starting from 10Mbps. The capability is used for
+ * Dx transitions and states */
+ if (hw->mac_type == e1000_82541_rev_2
+ || hw->mac_type == e1000_82547_rev_2) {
+ ret_val =
+ e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data);
+ if (ret_val)
+ return ret_val;
+ }
- DEBUGFUNC("e1000_release_software_flag");
+ if (!active) {
+ if (hw->mac_type == e1000_82541_rev_2 ||
+ hw->mac_type == e1000_82547_rev_2) {
+ phy_data &= ~IGP01E1000_GMII_FLEX_SPD;
+ ret_val =
+ e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ }
- if (hw->mac_type == e1000_ich8lan) {
- extcnf_ctrl= er32(EXTCNF_CTRL);
- extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
- ew32(EXTCNF_CTRL, extcnf_ctrl);
- }
+ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used during
+ * Dx states where the power conservation is most important. During
+ * driver activity we should enable SmartSpeed, so performance is
+ * maintained. */
+ if (hw->smart_speed == e1000_smart_speed_on) {
+ ret_val =
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val =
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ } else if (hw->smart_speed == e1000_smart_speed_off) {
+ ret_val =
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val =
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ }
+ } else if ((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT)
+ || (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL)
+ || (hw->autoneg_advertised ==
+ AUTONEG_ADVERTISE_10_100_ALL)) {
+
+ if (hw->mac_type == e1000_82541_rev_2 ||
+ hw->mac_type == e1000_82547_rev_2) {
+ phy_data |= IGP01E1000_GMII_FLEX_SPD;
+ ret_val =
+ e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ }
- return;
-}
+ /* When LPLU is enabled we should disable SmartSpeed */
+ ret_val =
+ e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
-/******************************************************************************
- * Reads a 16 bit word or words from the EEPROM using the ICH8's flash access
- * register.
- *
- * hw - Struct containing variables accessed by shared code
- * offset - offset of word in the EEPROM to read
- * data - word read from the EEPROM
- * words - number of words to read
- *****************************************************************************/
-static s32 e1000_read_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
-{
- s32 error = E1000_SUCCESS;
- u32 flash_bank = 0;
- u32 act_offset = 0;
- u32 bank_offset = 0;
- u16 word = 0;
- u16 i = 0;
-
- /* We need to know which is the valid flash bank. In the event
- * that we didn't allocate eeprom_shadow_ram, we may not be
- * managing flash_bank. So it cannot be trusted and needs
- * to be updated with each read.
- */
- /* Value of bit 22 corresponds to the flash bank we're on. */
- flash_bank = (er32(EECD) & E1000_EECD_SEC1VAL) ? 1 : 0;
-
- /* Adjust offset appropriately if we're on bank 1 - adjust for word size */
- bank_offset = flash_bank * (hw->flash_bank_size * 2);
-
- error = e1000_get_software_flag(hw);
- if (error != E1000_SUCCESS)
- return error;
-
- for (i = 0; i < words; i++) {
- if (hw->eeprom_shadow_ram != NULL &&
- hw->eeprom_shadow_ram[offset+i].modified) {
- data[i] = hw->eeprom_shadow_ram[offset+i].eeprom_word;
- } else {
- /* The NVM part needs a byte offset, hence * 2 */
- act_offset = bank_offset + ((offset + i) * 2);
- error = e1000_read_ich8_word(hw, act_offset, &word);
- if (error != E1000_SUCCESS)
- break;
- data[i] = word;
- }
- }
-
- e1000_release_software_flag(hw);
-
- return error;
-}
+ phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val =
+ e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if (ret_val)
+ return ret_val;
-/******************************************************************************
- * Writes a 16 bit word or words to the EEPROM using the ICH8's flash access
- * register. Actually, writes are written to the shadow ram cache in the hw
- * structure hw->e1000_shadow_ram. e1000_commit_shadow_ram flushes this to
- * the NVM, which occurs when the NVM checksum is updated.
- *
- * hw - Struct containing variables accessed by shared code
- * offset - offset of word in the EEPROM to write
- * words - number of words to write
- * data - words to write to the EEPROM
- *****************************************************************************/
-static s32 e1000_write_eeprom_ich8(struct e1000_hw *hw, u16 offset, u16 words,
- u16 *data)
-{
- u32 i = 0;
- s32 error = E1000_SUCCESS;
-
- error = e1000_get_software_flag(hw);
- if (error != E1000_SUCCESS)
- return error;
-
- /* A driver can write to the NVM only if it has eeprom_shadow_ram
- * allocated. Subsequent reads to the modified words are read from
- * this cached structure as well. Writes will only go into this
- * cached structure unless it's followed by a call to
- * e1000_update_eeprom_checksum() where it will commit the changes
- * and clear the "modified" field.
- */
- if (hw->eeprom_shadow_ram != NULL) {
- for (i = 0; i < words; i++) {
- if ((offset + i) < E1000_SHADOW_RAM_WORDS) {
- hw->eeprom_shadow_ram[offset+i].modified = true;
- hw->eeprom_shadow_ram[offset+i].eeprom_word = data[i];
- } else {
- error = -E1000_ERR_EEPROM;
- break;
- }
- }
- } else {
- /* Drivers have the option to not allocate eeprom_shadow_ram as long
- * as they don't perform any NVM writes. An attempt in doing so
- * will result in this error.
- */
- error = -E1000_ERR_EEPROM;
- }
-
- e1000_release_software_flag(hw);
-
- return error;
+ }
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * This function does initial flash setup so that a new read/write/erase cycle
- * can be started.
+/**
+ * e1000_set_vco_speed
+ * @hw: Struct containing variables accessed by shared code
*
- * hw - The pointer to the hw structure
- ****************************************************************************/
-static s32 e1000_ich8_cycle_init(struct e1000_hw *hw)
+ * Change VCO speed register to improve Bit Error Rate performance of SERDES.
+ */
+static s32 e1000_set_vco_speed(struct e1000_hw *hw)
{
- union ich8_hws_flash_status hsfsts;
- s32 error = E1000_ERR_EEPROM;
- s32 i = 0;
-
- DEBUGFUNC("e1000_ich8_cycle_init");
-
- hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
-
- /* May be check the Flash Des Valid bit in Hw status */
- if (hsfsts.hsf_status.fldesvalid == 0) {
- DEBUGOUT("Flash descriptor invalid. SW Sequencing must be used.");
- return error;
- }
-
- /* Clear FCERR in Hw status by writing 1 */
- /* Clear DAEL in Hw status by writing a 1 */
- hsfsts.hsf_status.flcerr = 1;
- hsfsts.hsf_status.dael = 1;
-
- E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
-
- /* Either we should have a hardware SPI cycle in progress bit to check
- * against, in order to start a new cycle or FDONE bit should be changed
- * in the hardware so that it is 1 after harware reset, which can then be
- * used as an indication whether a cycle is in progress or has been
- * completed .. we should also have some software semaphore mechanism to
- * guard FDONE or the cycle in progress bit so that two threads access to
- * those bits can be sequentiallized or a way so that 2 threads dont
- * start the cycle at the same time */
-
- if (hsfsts.hsf_status.flcinprog == 0) {
- /* There is no cycle running at present, so we can start a cycle */
- /* Begin by setting Flash Cycle Done. */
- hsfsts.hsf_status.flcdone = 1;
- E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
- error = E1000_SUCCESS;
- } else {
- /* otherwise poll for sometime so the current cycle has a chance
- * to end before giving up. */
- for (i = 0; i < ICH_FLASH_COMMAND_TIMEOUT; i++) {
- hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcinprog == 0) {
- error = E1000_SUCCESS;
- break;
- }
- udelay(1);
- }
- if (error == E1000_SUCCESS) {
- /* Successful in waiting for previous cycle to timeout,
- * now set the Flash Cycle Done. */
- hsfsts.hsf_status.flcdone = 1;
- E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
- } else {
- DEBUGOUT("Flash controller busy, cannot get access");
- }
- }
- return error;
-}
+ s32 ret_val;
+ u16 default_page = 0;
+ u16 phy_data;
-/******************************************************************************
- * This function starts a flash cycle and waits for its completion
- *
- * hw - The pointer to the hw structure
- ****************************************************************************/
-static s32 e1000_ich8_flash_cycle(struct e1000_hw *hw, u32 timeout)
-{
- union ich8_hws_flash_ctrl hsflctl;
- union ich8_hws_flash_status hsfsts;
- s32 error = E1000_ERR_EEPROM;
- u32 i = 0;
-
- /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
- hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
- hsflctl.hsf_ctrl.flcgo = 1;
- E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
-
- /* wait till FDONE bit is set to 1 */
- do {
- hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcdone == 1)
- break;
- udelay(1);
- i++;
- } while (i < timeout);
- if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0) {
- error = E1000_SUCCESS;
- }
- return error;
-}
+ DEBUGFUNC("e1000_set_vco_speed");
-/******************************************************************************
- * Reads a byte or word from the NVM using the ICH8 flash access registers.
- *
- * hw - The pointer to the hw structure
- * index - The index of the byte or word to read.
- * size - Size of data to read, 1=byte 2=word
- * data - Pointer to the word to store the value read.
- *****************************************************************************/
-static s32 e1000_read_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
- u16 *data)
-{
- union ich8_hws_flash_status hsfsts;
- union ich8_hws_flash_ctrl hsflctl;
- u32 flash_linear_address;
- u32 flash_data = 0;
- s32 error = -E1000_ERR_EEPROM;
- s32 count = 0;
-
- DEBUGFUNC("e1000_read_ich8_data");
-
- if (size < 1 || size > 2 || data == NULL ||
- index > ICH_FLASH_LINEAR_ADDR_MASK)
- return error;
-
- flash_linear_address = (ICH_FLASH_LINEAR_ADDR_MASK & index) +
- hw->flash_base_addr;
-
- do {
- udelay(1);
- /* Steps */
- error = e1000_ich8_cycle_init(hw);
- if (error != E1000_SUCCESS)
- break;
-
- hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
- /* 0b/1b corresponds to 1 or 2 byte size, respectively. */
- hsflctl.hsf_ctrl.fldbcount = size - 1;
- hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ;
- E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
-
- /* Write the last 24 bits of index into Flash Linear address field in
- * Flash Address */
- /* TODO: TBD maybe check the index against the size of flash */
-
- E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address);
-
- error = e1000_ich8_flash_cycle(hw, ICH_FLASH_COMMAND_TIMEOUT);
-
- /* Check if FCERR is set to 1, if set to 1, clear it and try the whole
- * sequence a few more times, else read in (shift in) the Flash Data0,
- * the order is least significant byte first msb to lsb */
- if (error == E1000_SUCCESS) {
- flash_data = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0);
- if (size == 1) {
- *data = (u8)(flash_data & 0x000000FF);
- } else if (size == 2) {
- *data = (u16)(flash_data & 0x0000FFFF);
- }
- break;
- } else {
- /* If we've gotten here, then things are probably completely hosed,
- * but if the error condition is detected, it won't hurt to give
- * it another try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
- */
- hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcerr == 1) {
- /* Repeat for some time before giving up. */
- continue;
- } else if (hsfsts.hsf_status.flcdone == 0) {
- DEBUGOUT("Timeout error - flash cycle did not complete.");
- break;
- }
- }
- } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
-
- return error;
-}
+ switch (hw->mac_type) {
+ case e1000_82545_rev_3:
+ case e1000_82546_rev_3:
+ break;
+ default:
+ return E1000_SUCCESS;
+ }
-/******************************************************************************
- * Writes One /two bytes to the NVM using the ICH8 flash access registers.
- *
- * hw - The pointer to the hw structure
- * index - The index of the byte/word to read.
- * size - Size of data to read, 1=byte 2=word
- * data - The byte(s) to write to the NVM.
- *****************************************************************************/
-static s32 e1000_write_ich8_data(struct e1000_hw *hw, u32 index, u32 size,
- u16 data)
-{
- union ich8_hws_flash_status hsfsts;
- union ich8_hws_flash_ctrl hsflctl;
- u32 flash_linear_address;
- u32 flash_data = 0;
- s32 error = -E1000_ERR_EEPROM;
- s32 count = 0;
-
- DEBUGFUNC("e1000_write_ich8_data");
-
- if (size < 1 || size > 2 || data > size * 0xff ||
- index > ICH_FLASH_LINEAR_ADDR_MASK)
- return error;
-
- flash_linear_address = (ICH_FLASH_LINEAR_ADDR_MASK & index) +
- hw->flash_base_addr;
-
- do {
- udelay(1);
- /* Steps */
- error = e1000_ich8_cycle_init(hw);
- if (error != E1000_SUCCESS)
- break;
-
- hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
- /* 0b/1b corresponds to 1 or 2 byte size, respectively. */
- hsflctl.hsf_ctrl.fldbcount = size -1;
- hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
- E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
-
- /* Write the last 24 bits of index into Flash Linear address field in
- * Flash Address */
- E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address);
-
- if (size == 1)
- flash_data = (u32)data & 0x00FF;
- else
- flash_data = (u32)data;
-
- E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data);
-
- /* check if FCERR is set to 1 , if set to 1, clear it and try the whole
- * sequence a few more times else done */
- error = e1000_ich8_flash_cycle(hw, ICH_FLASH_COMMAND_TIMEOUT);
- if (error == E1000_SUCCESS) {
- break;
- } else {
- /* If we're here, then things are most likely completely hosed,
- * but if the error condition is detected, it won't hurt to give
- * it another try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
- */
- hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcerr == 1) {
- /* Repeat for some time before giving up. */
- continue;
- } else if (hsfsts.hsf_status.flcdone == 0) {
- DEBUGOUT("Timeout error - flash cycle did not complete.");
- break;
- }
- }
- } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
-
- return error;
-}
+ /* Set PHY register 30, page 5, bit 8 to 0 */
-/******************************************************************************
- * Reads a single byte from the NVM using the ICH8 flash access registers.
- *
- * hw - pointer to e1000_hw structure
- * index - The index of the byte to read.
- * data - Pointer to a byte to store the value read.
- *****************************************************************************/
-static s32 e1000_read_ich8_byte(struct e1000_hw *hw, u32 index, u8 *data)
-{
- s32 status = E1000_SUCCESS;
- u16 word = 0;
+ ret_val =
+ e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, &default_page);
+ if (ret_val)
+ return ret_val;
- status = e1000_read_ich8_data(hw, index, 1, &word);
- if (status == E1000_SUCCESS) {
- *data = (u8)word;
- }
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005);
+ if (ret_val)
+ return ret_val;
- return status;
-}
+ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
+ if (ret_val)
+ return ret_val;
-/******************************************************************************
- * Writes a single byte to the NVM using the ICH8 flash access registers.
- * Performs verification by reading back the value and then going through
- * a retry algorithm before giving up.
- *
- * hw - pointer to e1000_hw structure
- * index - The index of the byte to write.
- * byte - The byte to write to the NVM.
- *****************************************************************************/
-static s32 e1000_verify_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 byte)
-{
- s32 error = E1000_SUCCESS;
- s32 program_retries = 0;
+ phy_data &= ~M88E1000_PHY_VCO_REG_BIT8;
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* Set PHY register 30, page 4, bit 11 to 1 */
- DEBUGOUT2("Byte := %2.2X Offset := %d\n", byte, index);
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004);
+ if (ret_val)
+ return ret_val;
- error = e1000_write_ich8_byte(hw, index, byte);
+ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
+ if (ret_val)
+ return ret_val;
- if (error != E1000_SUCCESS) {
- for (program_retries = 0; program_retries < 100; program_retries++) {
- DEBUGOUT2("Retrying \t Byte := %2.2X Offset := %d\n", byte, index);
- error = e1000_write_ich8_byte(hw, index, byte);
- udelay(100);
- if (error == E1000_SUCCESS)
- break;
- }
- }
+ phy_data |= M88E1000_PHY_VCO_REG_BIT11;
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
+ if (ret_val)
+ return ret_val;
- if (program_retries == 100)
- error = E1000_ERR_EEPROM;
+ ret_val =
+ e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, default_page);
+ if (ret_val)
+ return ret_val;
- return error;
+ return E1000_SUCCESS;
}
-/******************************************************************************
- * Writes a single byte to the NVM using the ICH8 flash access registers.
+
+/**
+ * e1000_enable_mng_pass_thru - check for bmc pass through
+ * @hw: Struct containing variables accessed by shared code
*
- * hw - pointer to e1000_hw structure
- * index - The index of the byte to read.
- * data - The byte to write to the NVM.
- *****************************************************************************/
-static s32 e1000_write_ich8_byte(struct e1000_hw *hw, u32 index, u8 data)
+ * Verifies the hardware needs to allow ARPs to be processed by the host
+ * returns: - true/false
+ */
+u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw)
{
- s32 status = E1000_SUCCESS;
- u16 word = (u16)data;
+ u32 manc;
- status = e1000_write_ich8_data(hw, index, 1, word);
+ if (hw->asf_firmware_present) {
+ manc = er32(MANC);
- return status;
+ if (!(manc & E1000_MANC_RCV_TCO_EN) ||
+ !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
+ return false;
+ if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
+ return true;
+ }
+ return false;
}
-/******************************************************************************
- * Reads a word from the NVM using the ICH8 flash access registers.
- *
- * hw - pointer to e1000_hw structure
- * index - The starting byte index of the word to read.
- * data - Pointer to a word to store the value read.
- *****************************************************************************/
-static s32 e1000_read_ich8_word(struct e1000_hw *hw, u32 index, u16 *data)
+static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw)
{
- s32 status = E1000_SUCCESS;
- status = e1000_read_ich8_data(hw, index, 2, data);
- return status;
-}
+ s32 ret_val;
+ u16 mii_status_reg;
+ u16 i;
-/******************************************************************************
- * Erases the bank specified. Each bank may be a 4, 8 or 64k block. Banks are 0
- * based.
- *
- * hw - pointer to e1000_hw structure
- * bank - 0 for first bank, 1 for second bank
- *
- * Note that this function may actually erase as much as 8 or 64 KBytes. The
- * amount of NVM used in each bank is a *minimum* of 4 KBytes, but in fact the
- * bank size may be 4, 8 or 64 KBytes
- *****************************************************************************/
-static s32 e1000_erase_ich8_4k_segment(struct e1000_hw *hw, u32 bank)
-{
- union ich8_hws_flash_status hsfsts;
- union ich8_hws_flash_ctrl hsflctl;
- u32 flash_linear_address;
- s32 count = 0;
- s32 error = E1000_ERR_EEPROM;
- s32 iteration;
- s32 sub_sector_size = 0;
- s32 bank_size;
- s32 j = 0;
- s32 error_flag = 0;
-
- hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
-
- /* Determine HW Sector size: Read BERASE bits of Hw flash Status register */
- /* 00: The Hw sector is 256 bytes, hence we need to erase 16
- * consecutive sectors. The start index for the nth Hw sector can be
- * calculated as bank * 4096 + n * 256
- * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector.
- * The start index for the nth Hw sector can be calculated
- * as bank * 4096
- * 10: The HW sector is 8K bytes
- * 11: The Hw sector size is 64K bytes */
- if (hsfsts.hsf_status.berasesz == 0x0) {
- /* Hw sector size 256 */
- sub_sector_size = ICH_FLASH_SEG_SIZE_256;
- bank_size = ICH_FLASH_SECTOR_SIZE;
- iteration = ICH_FLASH_SECTOR_SIZE / ICH_FLASH_SEG_SIZE_256;
- } else if (hsfsts.hsf_status.berasesz == 0x1) {
- bank_size = ICH_FLASH_SEG_SIZE_4K;
- iteration = 1;
- } else if (hsfsts.hsf_status.berasesz == 0x3) {
- bank_size = ICH_FLASH_SEG_SIZE_64K;
- iteration = 1;
- } else {
- return error;
- }
-
- for (j = 0; j < iteration ; j++) {
- do {
- count++;
- /* Steps */
- error = e1000_ich8_cycle_init(hw);
- if (error != E1000_SUCCESS) {
- error_flag = 1;
- break;
- }
-
- /* Write a value 11 (block Erase) in Flash Cycle field in Hw flash
- * Control */
- hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
- hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
- E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
-
- /* Write the last 24 bits of an index within the block into Flash
- * Linear address field in Flash Address. This probably needs to
- * be calculated here based off the on-chip erase sector size and
- * the software bank size (4, 8 or 64 KBytes) */
- flash_linear_address = bank * bank_size + j * sub_sector_size;
- flash_linear_address += hw->flash_base_addr;
- flash_linear_address &= ICH_FLASH_LINEAR_ADDR_MASK;
-
- E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address);
-
- error = e1000_ich8_flash_cycle(hw, ICH_FLASH_ERASE_TIMEOUT);
- /* Check if FCERR is set to 1. If 1, clear it and try the whole
- * sequence a few more times else Done */
- if (error == E1000_SUCCESS) {
- break;
- } else {
- hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
- if (hsfsts.hsf_status.flcerr == 1) {
- /* repeat for some time before giving up */
- continue;
- } else if (hsfsts.hsf_status.flcdone == 0) {
- error_flag = 1;
- break;
- }
- }
- } while ((count < ICH_FLASH_CYCLE_REPEAT_COUNT) && !error_flag);
- if (error_flag == 1)
- break;
- }
- if (error_flag != 1)
- error = E1000_SUCCESS;
- return error;
-}
+ /* Polarity reversal workaround for forced 10F/10H links. */
-static s32 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
- u32 cnf_base_addr,
- u32 cnf_size)
-{
- u32 ret_val = E1000_SUCCESS;
- u16 word_addr, reg_data, reg_addr;
- u16 i;
+ /* Disable the transmitter on the PHY */
- /* cnf_base_addr is in DWORD */
- word_addr = (u16)(cnf_base_addr << 1);
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+ if (ret_val)
+ return ret_val;
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
+ if (ret_val)
+ return ret_val;
- /* cnf_size is returned in size of dwords */
- for (i = 0; i < cnf_size; i++) {
- ret_val = e1000_read_eeprom(hw, (word_addr + i*2), 1, ®_data);
- if (ret_val)
- return ret_val;
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
+ if (ret_val)
+ return ret_val;
- ret_val = e1000_read_eeprom(hw, (word_addr + i*2 + 1), 1, ®_addr);
- if (ret_val)
- return ret_val;
+ /* This loop will early-out if the NO link condition has been met. */
+ for (i = PHY_FORCE_TIME; i > 0; i--) {
+ /* Read the MII Status Register and wait for Link Status bit
+ * to be clear.
+ */
- ret_val = e1000_get_software_flag(hw);
- if (ret_val != E1000_SUCCESS)
- return ret_val;
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+ if (ret_val)
+ return ret_val;
- ret_val = e1000_write_phy_reg_ex(hw, (u32)reg_addr, reg_data);
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+ if (ret_val)
+ return ret_val;
- e1000_release_software_flag(hw);
- }
+ if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0)
+ break;
+ mdelay(100);
+ }
- return ret_val;
+ /* Recommended delay time after link has been lost */
+ mdelay(1000);
+
+ /* Now we will re-enable th transmitter on the PHY */
+
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+ if (ret_val)
+ return ret_val;
+ mdelay(50);
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
+ if (ret_val)
+ return ret_val;
+ mdelay(50);
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
+ if (ret_val)
+ return ret_val;
+ mdelay(50);
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
+ if (ret_val)
+ return ret_val;
+
+ /* This loop will early-out if the link condition has been met. */
+ for (i = PHY_FORCE_TIME; i > 0; i--) {
+ /* Read the MII Status Register and wait for Link Status bit
+ * to be set.
+ */
+
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+ if (ret_val)
+ return ret_val;
+
+ if (mii_status_reg & MII_SR_LINK_STATUS)
+ break;
+ mdelay(100);
+ }
+ return E1000_SUCCESS;
}
-
-/******************************************************************************
- * This function initializes the PHY from the NVM on ICH8 platforms. This
- * is needed due to an issue where the NVM configuration is not properly
- * autoloaded after power transitions. Therefore, after each PHY reset, we
- * will load the configuration data out of the NVM manually.
+/**
+ * e1000_get_auto_rd_done
+ * @hw: Struct containing variables accessed by shared code
*
- * hw: Struct containing variables accessed by shared code
- *****************************************************************************/
-static s32 e1000_init_lcd_from_nvm(struct e1000_hw *hw)
+ * Check for EEPROM Auto Read bit done.
+ * returns: - E1000_ERR_RESET if fail to reset MAC
+ * E1000_SUCCESS at any other case.
+ */
+static s32 e1000_get_auto_rd_done(struct e1000_hw *hw)
{
- u32 reg_data, cnf_base_addr, cnf_size, ret_val, loop;
-
- if (hw->phy_type != e1000_phy_igp_3)
- return E1000_SUCCESS;
-
- /* Check if SW needs configure the PHY */
- reg_data = er32(FEXTNVM);
- if (!(reg_data & FEXTNVM_SW_CONFIG))
- return E1000_SUCCESS;
-
- /* Wait for basic configuration completes before proceeding*/
- loop = 0;
- do {
- reg_data = er32(STATUS) & E1000_STATUS_LAN_INIT_DONE;
- udelay(100);
- loop++;
- } while ((!reg_data) && (loop < 50));
-
- /* Clear the Init Done bit for the next init event */
- reg_data = er32(STATUS);
- reg_data &= ~E1000_STATUS_LAN_INIT_DONE;
- ew32(STATUS, reg_data);
-
- /* Make sure HW does not configure LCD from PHY extended configuration
- before SW configuration */
- reg_data = er32(EXTCNF_CTRL);
- if ((reg_data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) == 0x0000) {
- reg_data = er32(EXTCNF_SIZE);
- cnf_size = reg_data & E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH;
- cnf_size >>= 16;
- if (cnf_size) {
- reg_data = er32(EXTCNF_CTRL);
- cnf_base_addr = reg_data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER;
- /* cnf_base_addr is in DWORD */
- cnf_base_addr >>= 16;
-
- /* Configure LCD from extended configuration region. */
- ret_val = e1000_init_lcd_from_nvm_config_region(hw, cnf_base_addr,
- cnf_size);
- if (ret_val)
- return ret_val;
- }
- }
-
- return E1000_SUCCESS;
+ DEBUGFUNC("e1000_get_auto_rd_done");
+ msleep(5);
+ return E1000_SUCCESS;
}
+/**
+ * e1000_get_phy_cfg_done
+ * @hw: Struct containing variables accessed by shared code
+ *
+ * Checks if the PHY configuration is done
+ * returns: - E1000_ERR_RESET if fail to reset MAC
+ * E1000_SUCCESS at any other case.
+ */
+static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw)
+{
+ DEBUGFUNC("e1000_get_phy_cfg_done");
+ mdelay(10);
+ return E1000_SUCCESS;
+}
#include "e1000_osdep.h"
-
/* Forward declarations of structures used by the shared code */
struct e1000_hw;
struct e1000_hw_stats;
/* Enumerated types specific to the e1000 hardware */
/* Media Access Controlers */
typedef enum {
- e1000_undefined = 0,
- e1000_82542_rev2_0,
- e1000_82542_rev2_1,
- e1000_82543,
- e1000_82544,
- e1000_82540,
- e1000_82545,
- e1000_82545_rev_3,
- e1000_82546,
- e1000_82546_rev_3,
- e1000_82541,
- e1000_82541_rev_2,
- e1000_82547,
- e1000_82547_rev_2,
- e1000_82571,
- e1000_82572,
- e1000_82573,
- e1000_80003es2lan,
- e1000_ich8lan,
- e1000_num_macs
+ e1000_undefined = 0,
+ e1000_82542_rev2_0,
+ e1000_82542_rev2_1,
+ e1000_82543,
+ e1000_82544,
+ e1000_82540,
+ e1000_82545,
+ e1000_82545_rev_3,
+ e1000_82546,
+ e1000_82546_rev_3,
+ e1000_82541,
+ e1000_82541_rev_2,
+ e1000_82547,
+ e1000_82547_rev_2,
+ e1000_num_macs
} e1000_mac_type;
typedef enum {
- e1000_eeprom_uninitialized = 0,
- e1000_eeprom_spi,
- e1000_eeprom_microwire,
- e1000_eeprom_flash,
- e1000_eeprom_ich8,
- e1000_eeprom_none, /* No NVM support */
- e1000_num_eeprom_types
+ e1000_eeprom_uninitialized = 0,
+ e1000_eeprom_spi,
+ e1000_eeprom_microwire,
+ e1000_eeprom_flash,
+ e1000_eeprom_none, /* No NVM support */
+ e1000_num_eeprom_types
} e1000_eeprom_type;
/* Media Types */
typedef enum {
- e1000_media_type_copper = 0,
- e1000_media_type_fiber = 1,
- e1000_media_type_internal_serdes = 2,
- e1000_num_media_types
+ e1000_media_type_copper = 0,
+ e1000_media_type_fiber = 1,
+ e1000_media_type_internal_serdes = 2,
+ e1000_num_media_types
} e1000_media_type;
typedef enum {
- e1000_10_half = 0,
- e1000_10_full = 1,
- e1000_100_half = 2,
- e1000_100_full = 3
+ e1000_10_half = 0,
+ e1000_10_full = 1,
+ e1000_100_half = 2,
+ e1000_100_full = 3
} e1000_speed_duplex_type;
/* Flow Control Settings */
typedef enum {
- E1000_FC_NONE = 0,
- E1000_FC_RX_PAUSE = 1,
- E1000_FC_TX_PAUSE = 2,
- E1000_FC_FULL = 3,
- E1000_FC_DEFAULT = 0xFF
+ E1000_FC_NONE = 0,
+ E1000_FC_RX_PAUSE = 1,
+ E1000_FC_TX_PAUSE = 2,
+ E1000_FC_FULL = 3,
+ E1000_FC_DEFAULT = 0xFF
} e1000_fc_type;
struct e1000_shadow_ram {
- u16 eeprom_word;
- bool modified;
+ u16 eeprom_word;
+ bool modified;
};
/* PCI bus types */
typedef enum {
- e1000_bus_type_unknown = 0,
- e1000_bus_type_pci,
- e1000_bus_type_pcix,
- e1000_bus_type_pci_express,
- e1000_bus_type_reserved
+ e1000_bus_type_unknown = 0,
+ e1000_bus_type_pci,
+ e1000_bus_type_pcix,
+ e1000_bus_type_reserved
} e1000_bus_type;
/* PCI bus speeds */
typedef enum {
- e1000_bus_speed_unknown = 0,
- e1000_bus_speed_33,
- e1000_bus_speed_66,
- e1000_bus_speed_100,
- e1000_bus_speed_120,
- e1000_bus_speed_133,
- e1000_bus_speed_2500,
- e1000_bus_speed_reserved
+ e1000_bus_speed_unknown = 0,
+ e1000_bus_speed_33,
+ e1000_bus_speed_66,
+ e1000_bus_speed_100,
+ e1000_bus_speed_120,
+ e1000_bus_speed_133,
+ e1000_bus_speed_reserved
} e1000_bus_speed;
/* PCI bus widths */
typedef enum {
- e1000_bus_width_unknown = 0,
- /* These PCIe values should literally match the possible return values
- * from config space */
- e1000_bus_width_pciex_1 = 1,
- e1000_bus_width_pciex_2 = 2,
- e1000_bus_width_pciex_4 = 4,
- e1000_bus_width_32,
- e1000_bus_width_64,
- e1000_bus_width_reserved
+ e1000_bus_width_unknown = 0,
+ e1000_bus_width_32,
+ e1000_bus_width_64,
+ e1000_bus_width_reserved
} e1000_bus_width;
/* PHY status info structure and supporting enums */
typedef enum {
- e1000_cable_length_50 = 0,
- e1000_cable_length_50_80,
- e1000_cable_length_80_110,
- e1000_cable_length_110_140,
- e1000_cable_length_140,
- e1000_cable_length_undefined = 0xFF
+ e1000_cable_length_50 = 0,
+ e1000_cable_length_50_80,
+ e1000_cable_length_80_110,
+ e1000_cable_length_110_140,
+ e1000_cable_length_140,
+ e1000_cable_length_undefined = 0xFF
} e1000_cable_length;
typedef enum {
- e1000_gg_cable_length_60 = 0,
- e1000_gg_cable_length_60_115 = 1,
- e1000_gg_cable_length_115_150 = 2,
- e1000_gg_cable_length_150 = 4
+ e1000_gg_cable_length_60 = 0,
+ e1000_gg_cable_length_60_115 = 1,
+ e1000_gg_cable_length_115_150 = 2,
+ e1000_gg_cable_length_150 = 4
} e1000_gg_cable_length;
typedef enum {
- e1000_igp_cable_length_10 = 10,
- e1000_igp_cable_length_20 = 20,
- e1000_igp_cable_length_30 = 30,
- e1000_igp_cable_length_40 = 40,
- e1000_igp_cable_length_50 = 50,
- e1000_igp_cable_length_60 = 60,
- e1000_igp_cable_length_70 = 70,
- e1000_igp_cable_length_80 = 80,
- e1000_igp_cable_length_90 = 90,
- e1000_igp_cable_length_100 = 100,
- e1000_igp_cable_length_110 = 110,
- e1000_igp_cable_length_115 = 115,
- e1000_igp_cable_length_120 = 120,
- e1000_igp_cable_length_130 = 130,
- e1000_igp_cable_length_140 = 140,
- e1000_igp_cable_length_150 = 150,
- e1000_igp_cable_length_160 = 160,
- e1000_igp_cable_length_170 = 170,
- e1000_igp_cable_length_180 = 180
+ e1000_igp_cable_length_10 = 10,
+ e1000_igp_cable_length_20 = 20,
+ e1000_igp_cable_length_30 = 30,
+ e1000_igp_cable_length_40 = 40,
+ e1000_igp_cable_length_50 = 50,
+ e1000_igp_cable_length_60 = 60,
+ e1000_igp_cable_length_70 = 70,
+ e1000_igp_cable_length_80 = 80,
+ e1000_igp_cable_length_90 = 90,
+ e1000_igp_cable_length_100 = 100,
+ e1000_igp_cable_length_110 = 110,
+ e1000_igp_cable_length_115 = 115,
+ e1000_igp_cable_length_120 = 120,
+ e1000_igp_cable_length_130 = 130,
+ e1000_igp_cable_length_140 = 140,
+ e1000_igp_cable_length_150 = 150,
+ e1000_igp_cable_length_160 = 160,
+ e1000_igp_cable_length_170 = 170,
+ e1000_igp_cable_length_180 = 180
} e1000_igp_cable_length;
typedef enum {
- e1000_10bt_ext_dist_enable_normal = 0,
- e1000_10bt_ext_dist_enable_lower,
- e1000_10bt_ext_dist_enable_undefined = 0xFF
+ e1000_10bt_ext_dist_enable_normal = 0,
+ e1000_10bt_ext_dist_enable_lower,
+ e1000_10bt_ext_dist_enable_undefined = 0xFF
} e1000_10bt_ext_dist_enable;
typedef enum {
- e1000_rev_polarity_normal = 0,
- e1000_rev_polarity_reversed,
- e1000_rev_polarity_undefined = 0xFF
+ e1000_rev_polarity_normal = 0,
+ e1000_rev_polarity_reversed,
+ e1000_rev_polarity_undefined = 0xFF
} e1000_rev_polarity;
typedef enum {
- e1000_downshift_normal = 0,
- e1000_downshift_activated,
- e1000_downshift_undefined = 0xFF
+ e1000_downshift_normal = 0,
+ e1000_downshift_activated,
+ e1000_downshift_undefined = 0xFF
} e1000_downshift;
typedef enum {
- e1000_smart_speed_default = 0,
- e1000_smart_speed_on,
- e1000_smart_speed_off
+ e1000_smart_speed_default = 0,
+ e1000_smart_speed_on,
+ e1000_smart_speed_off
} e1000_smart_speed;
typedef enum {
- e1000_polarity_reversal_enabled = 0,
- e1000_polarity_reversal_disabled,
- e1000_polarity_reversal_undefined = 0xFF
+ e1000_polarity_reversal_enabled = 0,
+ e1000_polarity_reversal_disabled,
+ e1000_polarity_reversal_undefined = 0xFF
} e1000_polarity_reversal;
typedef enum {
- e1000_auto_x_mode_manual_mdi = 0,
- e1000_auto_x_mode_manual_mdix,
- e1000_auto_x_mode_auto1,
- e1000_auto_x_mode_auto2,
- e1000_auto_x_mode_undefined = 0xFF
+ e1000_auto_x_mode_manual_mdi = 0,
+ e1000_auto_x_mode_manual_mdix,
+ e1000_auto_x_mode_auto1,
+ e1000_auto_x_mode_auto2,
+ e1000_auto_x_mode_undefined = 0xFF
} e1000_auto_x_mode;
typedef enum {
- e1000_1000t_rx_status_not_ok = 0,
- e1000_1000t_rx_status_ok,
- e1000_1000t_rx_status_undefined = 0xFF
+ e1000_1000t_rx_status_not_ok = 0,
+ e1000_1000t_rx_status_ok,
+ e1000_1000t_rx_status_undefined = 0xFF
} e1000_1000t_rx_status;
typedef enum {
e1000_phy_m88 = 0,
e1000_phy_igp,
- e1000_phy_igp_2,
- e1000_phy_gg82563,
- e1000_phy_igp_3,
- e1000_phy_ife,
e1000_phy_undefined = 0xFF
} e1000_phy_type;
typedef enum {
- e1000_ms_hw_default = 0,
- e1000_ms_force_master,
- e1000_ms_force_slave,
- e1000_ms_auto
+ e1000_ms_hw_default = 0,
+ e1000_ms_force_master,
+ e1000_ms_force_slave,
+ e1000_ms_auto
} e1000_ms_type;
typedef enum {
- e1000_ffe_config_enabled = 0,
- e1000_ffe_config_active,
- e1000_ffe_config_blocked
+ e1000_ffe_config_enabled = 0,
+ e1000_ffe_config_active,
+ e1000_ffe_config_blocked
} e1000_ffe_config;
typedef enum {
- e1000_dsp_config_disabled = 0,
- e1000_dsp_config_enabled,
- e1000_dsp_config_activated,
- e1000_dsp_config_undefined = 0xFF
+ e1000_dsp_config_disabled = 0,
+ e1000_dsp_config_enabled,
+ e1000_dsp_config_activated,
+ e1000_dsp_config_undefined = 0xFF
} e1000_dsp_config;
struct e1000_phy_info {
- e1000_cable_length cable_length;
- e1000_10bt_ext_dist_enable extended_10bt_distance;
- e1000_rev_polarity cable_polarity;
- e1000_downshift downshift;
- e1000_polarity_reversal polarity_correction;
- e1000_auto_x_mode mdix_mode;
- e1000_1000t_rx_status local_rx;
- e1000_1000t_rx_status remote_rx;
+ e1000_cable_length cable_length;
+ e1000_10bt_ext_dist_enable extended_10bt_distance;
+ e1000_rev_polarity cable_polarity;
+ e1000_downshift downshift;
+ e1000_polarity_reversal polarity_correction;
+ e1000_auto_x_mode mdix_mode;
+ e1000_1000t_rx_status local_rx;
+ e1000_1000t_rx_status remote_rx;
};
struct e1000_phy_stats {
- u32 idle_errors;
- u32 receive_errors;
+ u32 idle_errors;
+ u32 receive_errors;
};
struct e1000_eeprom_info {
- e1000_eeprom_type type;
- u16 word_size;
- u16 opcode_bits;
- u16 address_bits;
- u16 delay_usec;
- u16 page_size;
- bool use_eerd;
- bool use_eewr;
+ e1000_eeprom_type type;
+ u16 word_size;
+ u16 opcode_bits;
+ u16 address_bits;
+ u16 delay_usec;
+ u16 page_size;
};
/* Flex ASF Information */
#define E1000_HOST_IF_MAX_SIZE 2048
typedef enum {
- e1000_byte_align = 0,
- e1000_word_align = 1,
- e1000_dword_align = 2
+ e1000_byte_align = 0,
+ e1000_word_align = 1,
+ e1000_dword_align = 2
} e1000_align_type;
-
-
/* Error Codes */
#define E1000_SUCCESS 0
#define E1000_ERR_EEPROM 1
#define E1000_ERR_MASTER_REQUESTS_PENDING 10
#define E1000_ERR_HOST_INTERFACE_COMMAND 11
#define E1000_BLK_PHY_RESET 12
-#define E1000_ERR_SWFW_SYNC 13
#define E1000_BYTE_SWAP_WORD(_value) ((((_value) & 0x00ff) << 8) | \
(((_value) & 0xff00) >> 8))
s32 e1000_phy_setup_autoneg(struct e1000_hw *hw);
void e1000_config_collision_dist(struct e1000_hw *hw);
s32 e1000_check_for_link(struct e1000_hw *hw);
-s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex);
+s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 * speed, u16 * duplex);
s32 e1000_force_mac_fc(struct e1000_hw *hw);
/* PHY */
-s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data);
+s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 * phy_data);
s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 data);
s32 e1000_phy_hw_reset(struct e1000_hw *hw);
s32 e1000_phy_reset(struct e1000_hw *hw);
s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
s32 e1000_validate_mdi_setting(struct e1000_hw *hw);
-void e1000_phy_powerdown_workaround(struct e1000_hw *hw);
-
/* EEPROM Functions */
s32 e1000_init_eeprom_params(struct e1000_hw *hw);
u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw);
#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64
-#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 /* Host Interface data length */
+#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 /* Host Interface data length */
-#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 /* Time in ms to process MNG command */
-#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 /* Cookie offset */
-#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 /* Cookie length */
+#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 /* Time in ms to process MNG command */
+#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 /* Cookie offset */
+#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 /* Cookie length */
#define E1000_MNG_IAMT_MODE 0x3
#define E1000_MNG_ICH_IAMT_MODE 0x2
-#define E1000_IAMT_SIGNATURE 0x544D4149 /* Intel(R) Active Management Technology signature */
+#define E1000_IAMT_SIGNATURE 0x544D4149 /* Intel(R) Active Management Technology signature */
-#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT 0x1 /* DHCP parsing enabled */
-#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT 0x2 /* DHCP parsing enabled */
+#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT 0x1 /* DHCP parsing enabled */
+#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT 0x2 /* DHCP parsing enabled */
#define E1000_VFTA_ENTRY_SHIFT 0x5
#define E1000_VFTA_ENTRY_MASK 0x7F
#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F
struct e1000_host_mng_command_header {
- u8 command_id;
- u8 checksum;
- u16 reserved1;
- u16 reserved2;
- u16 command_length;
+ u8 command_id;
+ u8 checksum;
+ u16 reserved1;
+ u16 reserved2;
+ u16 command_length;
};
struct e1000_host_mng_command_info {
- struct e1000_host_mng_command_header command_header; /* Command Head/Command Result Head has 4 bytes */
- u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; /* Command data can length 0..0x658*/
+ struct e1000_host_mng_command_header command_header; /* Command Head/Command Result Head has 4 bytes */
+ u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; /* Command data can length 0..0x658 */
};
#ifdef __BIG_ENDIAN
-struct e1000_host_mng_dhcp_cookie{
- u32 signature;
- u16 vlan_id;
- u8 reserved0;
- u8 status;
- u32 reserved1;
- u8 checksum;
- u8 reserved3;
- u16 reserved2;
+struct e1000_host_mng_dhcp_cookie {
+ u32 signature;
+ u16 vlan_id;
+ u8 reserved0;
+ u8 status;
+ u32 reserved1;
+ u8 checksum;
+ u8 reserved3;
+ u16 reserved2;
};
#else
-struct e1000_host_mng_dhcp_cookie{
- u32 signature;
- u8 status;
- u8 reserved0;
- u16 vlan_id;
- u32 reserved1;
- u16 reserved2;
- u8 reserved3;
- u8 checksum;
+struct e1000_host_mng_dhcp_cookie {
+ u32 signature;
+ u8 status;
+ u8 reserved0;
+ u16 vlan_id;
+ u32 reserved1;
+ u16 reserved2;
+ u8 reserved3;
+ u8 checksum;
};
#endif
-s32 e1000_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer,
- u16 length);
bool e1000_check_mng_mode(struct e1000_hw *hw);
-bool e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
-s32 e1000_read_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 *data);
+s32 e1000_read_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 * data);
s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw);
s32 e1000_update_eeprom_checksum(struct e1000_hw *hw);
-s32 e1000_write_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 *data);
-s32 e1000_read_mac_addr(struct e1000_hw * hw);
+s32 e1000_write_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 * data);
+s32 e1000_read_mac_addr(struct e1000_hw *hw);
/* Filters (multicast, vlan, receive) */
u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 * mc_addr);
/* Everything else */
void e1000_reset_adaptive(struct e1000_hw *hw);
void e1000_update_adaptive(struct e1000_hw *hw);
-void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, u32 frame_len, u8 * mac_addr);
+void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats,
+ u32 frame_len, u8 * mac_addr);
void e1000_get_bus_info(struct e1000_hw *hw);
void e1000_pci_set_mwi(struct e1000_hw *hw);
void e1000_pci_clear_mwi(struct e1000_hw *hw);
-s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc);
int e1000_pcix_get_mmrbc(struct e1000_hw *hw);
/* Port I/O is only supported on 82544 and newer */
void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value);
-s32 e1000_disable_pciex_master(struct e1000_hw *hw);
-s32 e1000_check_phy_reset_block(struct e1000_hw *hw);
-
#define E1000_READ_REG_IO(a, reg) \
e1000_read_reg_io((a), E1000_##reg)
#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
#define E1000_DEV_ID_82547EI 0x1019
#define E1000_DEV_ID_82547EI_MOBILE 0x101A
-#define E1000_DEV_ID_82571EB_COPPER 0x105E
-#define E1000_DEV_ID_82571EB_FIBER 0x105F
-#define E1000_DEV_ID_82571EB_SERDES 0x1060
-#define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4
-#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5
-#define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5
-#define E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE 0x10BC
-#define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9
-#define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA
-#define E1000_DEV_ID_82572EI_COPPER 0x107D
-#define E1000_DEV_ID_82572EI_FIBER 0x107E
-#define E1000_DEV_ID_82572EI_SERDES 0x107F
-#define E1000_DEV_ID_82572EI 0x10B9
-#define E1000_DEV_ID_82573E 0x108B
-#define E1000_DEV_ID_82573E_IAMT 0x108C
-#define E1000_DEV_ID_82573L 0x109A
#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
-#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096
-#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098
-#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA
-#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB
-
-#define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049
-#define E1000_DEV_ID_ICH8_IGP_AMT 0x104A
-#define E1000_DEV_ID_ICH8_IGP_C 0x104B
-#define E1000_DEV_ID_ICH8_IFE 0x104C
-#define E1000_DEV_ID_ICH8_IFE_GT 0x10C4
-#define E1000_DEV_ID_ICH8_IFE_G 0x10C5
-#define E1000_DEV_ID_ICH8_IGP_M 0x104D
-
#define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6
/* The sizes (in bytes) of a ethernet packet */
#define ENET_HEADER_SIZE 14
-#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */
+#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */
#define ETHERNET_FCS_SIZE 4
#define MINIMUM_ETHERNET_PACKET_SIZE \
(MINIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE)
#define CRC_LENGTH ETHERNET_FCS_SIZE
#define MAX_JUMBO_FRAME_SIZE 0x3F00
-
/* 802.1q VLAN Packet Sizes */
-#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMAed) */
+#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMAed) */
/* Ethertype field values */
-#define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */
-#define ETHERNET_IP_TYPE 0x0800 /* IP packets */
-#define ETHERNET_ARP_TYPE 0x0806 /* Address Resolution Protocol (ARP) */
+#define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */
+#define ETHERNET_IP_TYPE 0x0800 /* IP packets */
+#define ETHERNET_ARP_TYPE 0x0806 /* Address Resolution Protocol (ARP) */
/* Packet Header defines */
#define IP_PROTOCOL_TCP 6
E1000_IMS_RXSEQ | \
E1000_IMS_LSC)
-/* Additional interrupts need to be handled for e1000_ich8lan:
- DSW = The FW changed the status of the DISSW bit in FWSM
- PHYINT = The LAN connected device generates an interrupt
- EPRST = Manageability reset event */
-#define IMS_ICH8LAN_ENABLE_MASK (\
- E1000_IMS_DSW | \
- E1000_IMS_PHYINT | \
- E1000_IMS_EPRST)
-
/* Number of high/low register pairs in the RAR. The RAR (Receive Address
* Registers) holds the directed and multicast addresses that we monitor. We
* reserve one of these spots for our directed address, allowing us room for
*/
#define E1000_RAR_ENTRIES 15
-#define E1000_RAR_ENTRIES_ICH8LAN 6
-
#define MIN_NUMBER_OF_DESCRIPTORS 8
#define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8
/* Receive Descriptor */
struct e1000_rx_desc {
- __le64 buffer_addr; /* Address of the descriptor's data buffer */
- __le16 length; /* Length of data DMAed into data buffer */
- __le16 csum; /* Packet checksum */
- u8 status; /* Descriptor status */
- u8 errors; /* Descriptor Errors */
- __le16 special;
+ __le64 buffer_addr; /* Address of the descriptor's data buffer */
+ __le16 length; /* Length of data DMAed into data buffer */
+ __le16 csum; /* Packet checksum */
+ u8 status; /* Descriptor status */
+ u8 errors; /* Descriptor Errors */
+ __le16 special;
};
/* Receive Descriptor - Extended */
union e1000_rx_desc_extended {
- struct {
- __le64 buffer_addr;
- __le64 reserved;
- } read;
- struct {
- struct {
- __le32 mrq; /* Multiple Rx Queues */
- union {
- __le32 rss; /* RSS Hash */
- struct {
- __le16 ip_id; /* IP id */
- __le16 csum; /* Packet Checksum */
- } csum_ip;
- } hi_dword;
- } lower;
- struct {
- __le32 status_error; /* ext status/error */
- __le16 length;
- __le16 vlan; /* VLAN tag */
- } upper;
- } wb; /* writeback */
+ struct {
+ __le64 buffer_addr;
+ __le64 reserved;
+ } read;
+ struct {
+ struct {
+ __le32 mrq; /* Multiple Rx Queues */
+ union {
+ __le32 rss; /* RSS Hash */
+ struct {
+ __le16 ip_id; /* IP id */
+ __le16 csum; /* Packet Checksum */
+ } csum_ip;
+ } hi_dword;
+ } lower;
+ struct {
+ __le32 status_error; /* ext status/error */
+ __le16 length;
+ __le16 vlan; /* VLAN tag */
+ } upper;
+ } wb; /* writeback */
};
#define MAX_PS_BUFFERS 4
/* Receive Descriptor - Packet Split */
union e1000_rx_desc_packet_split {
- struct {
- /* one buffer for protocol header(s), three data buffers */
- __le64 buffer_addr[MAX_PS_BUFFERS];
- } read;
- struct {
- struct {
- __le32 mrq; /* Multiple Rx Queues */
- union {
- __le32 rss; /* RSS Hash */
- struct {
- __le16 ip_id; /* IP id */
- __le16 csum; /* Packet Checksum */
- } csum_ip;
- } hi_dword;
- } lower;
- struct {
- __le32 status_error; /* ext status/error */
- __le16 length0; /* length of buffer 0 */
- __le16 vlan; /* VLAN tag */
- } middle;
- struct {
- __le16 header_status;
- __le16 length[3]; /* length of buffers 1-3 */
- } upper;
- __le64 reserved;
- } wb; /* writeback */
+ struct {
+ /* one buffer for protocol header(s), three data buffers */
+ __le64 buffer_addr[MAX_PS_BUFFERS];
+ } read;
+ struct {
+ struct {
+ __le32 mrq; /* Multiple Rx Queues */
+ union {
+ __le32 rss; /* RSS Hash */
+ struct {
+ __le16 ip_id; /* IP id */
+ __le16 csum; /* Packet Checksum */
+ } csum_ip;
+ } hi_dword;
+ } lower;
+ struct {
+ __le32 status_error; /* ext status/error */
+ __le16 length0; /* length of buffer 0 */
+ __le16 vlan; /* VLAN tag */
+ } middle;
+ struct {
+ __le16 header_status;
+ __le16 length[3]; /* length of buffers 1-3 */
+ } upper;
+ __le64 reserved;
+ } wb; /* writeback */
};
-/* Receive Decriptor bit definitions */
-#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
-#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */
-#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */
-#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
-#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum caculated */
-#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
-#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */
-#define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */
-#define E1000_RXD_STAT_IPIDV 0x200 /* IP identification valid */
-#define E1000_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */
-#define E1000_RXD_STAT_ACK 0x8000 /* ACK Packet indication */
-#define E1000_RXD_ERR_CE 0x01 /* CRC Error */
-#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */
-#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */
-#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */
-#define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */
-#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */
-#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */
-#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
-#define E1000_RXD_SPC_PRI_MASK 0xE000 /* Priority is in upper 3 bits */
+/* Receive Descriptor bit definitions */
+#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
+#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */
+#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */
+#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
+#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */
+#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
+#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */
+#define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */
+#define E1000_RXD_STAT_IPIDV 0x200 /* IP identification valid */
+#define E1000_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */
+#define E1000_RXD_STAT_ACK 0x8000 /* ACK Packet indication */
+#define E1000_RXD_ERR_CE 0x01 /* CRC Error */
+#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */
+#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */
+#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */
+#define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */
+#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */
+#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */
+#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
+#define E1000_RXD_SPC_PRI_MASK 0xE000 /* Priority is in upper 3 bits */
#define E1000_RXD_SPC_PRI_SHIFT 13
-#define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */
+#define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */
#define E1000_RXD_SPC_CFI_SHIFT 12
#define E1000_RXDEXT_STATERR_CE 0x01000000
E1000_RXD_ERR_CXE | \
E1000_RXD_ERR_RXE)
-
/* Same mask, but for extended and packet split descriptors */
#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \
E1000_RXDEXT_STATERR_CE | \
E1000_RXDEXT_STATERR_CXE | \
E1000_RXDEXT_STATERR_RXE)
-
/* Transmit Descriptor */
struct e1000_tx_desc {
- __le64 buffer_addr; /* Address of the descriptor's data buffer */
- union {
- __le32 data;
- struct {
- __le16 length; /* Data buffer length */
- u8 cso; /* Checksum offset */
- u8 cmd; /* Descriptor control */
- } flags;
- } lower;
- union {
- __le32 data;
- struct {
- u8 status; /* Descriptor status */
- u8 css; /* Checksum start */
- __le16 special;
- } fields;
- } upper;
+ __le64 buffer_addr; /* Address of the descriptor's data buffer */
+ union {
+ __le32 data;
+ struct {
+ __le16 length; /* Data buffer length */
+ u8 cso; /* Checksum offset */
+ u8 cmd; /* Descriptor control */
+ } flags;
+ } lower;
+ union {
+ __le32 data;
+ struct {
+ u8 status; /* Descriptor status */
+ u8 css; /* Checksum start */
+ __le16 special;
+ } fields;
+ } upper;
};
/* Transmit Descriptor bit definitions */
-#define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */
-#define E1000_TXD_DTYP_C 0x00000000 /* Context Descriptor */
-#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */
-#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */
-#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */
-#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
-#define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */
-#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */
-#define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */
-#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */
-#define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */
-#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */
-#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */
-#define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */
-#define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */
-#define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */
-#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */
-#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */
-#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */
-#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */
+#define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */
+#define E1000_TXD_DTYP_C 0x00000000 /* Context Descriptor */
+#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */
+#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */
+#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */
+#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
+#define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */
+#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */
+#define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */
+#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */
+#define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */
+#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */
+#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */
+#define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */
+#define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */
+#define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */
+#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */
+#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */
+#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */
+#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */
/* Offload Context Descriptor */
struct e1000_context_desc {
- union {
- __le32 ip_config;
- struct {
- u8 ipcss; /* IP checksum start */
- u8 ipcso; /* IP checksum offset */
- __le16 ipcse; /* IP checksum end */
- } ip_fields;
- } lower_setup;
- union {
- __le32 tcp_config;
- struct {
- u8 tucss; /* TCP checksum start */
- u8 tucso; /* TCP checksum offset */
- __le16 tucse; /* TCP checksum end */
- } tcp_fields;
- } upper_setup;
- __le32 cmd_and_length; /* */
- union {
- __le32 data;
- struct {
- u8 status; /* Descriptor status */
- u8 hdr_len; /* Header length */
- __le16 mss; /* Maximum segment size */
- } fields;
- } tcp_seg_setup;
+ union {
+ __le32 ip_config;
+ struct {
+ u8 ipcss; /* IP checksum start */
+ u8 ipcso; /* IP checksum offset */
+ __le16 ipcse; /* IP checksum end */
+ } ip_fields;
+ } lower_setup;
+ union {
+ __le32 tcp_config;
+ struct {
+ u8 tucss; /* TCP checksum start */
+ u8 tucso; /* TCP checksum offset */
+ __le16 tucse; /* TCP checksum end */
+ } tcp_fields;
+ } upper_setup;
+ __le32 cmd_and_length; /* */
+ union {
+ __le32 data;
+ struct {
+ u8 status; /* Descriptor status */
+ u8 hdr_len; /* Header length */
+ __le16 mss; /* Maximum segment size */
+ } fields;
+ } tcp_seg_setup;
};
/* Offload data descriptor */
struct e1000_data_desc {
- __le64 buffer_addr; /* Address of the descriptor's buffer address */
- union {
- __le32 data;
- struct {
- __le16 length; /* Data buffer length */
- u8 typ_len_ext; /* */
- u8 cmd; /* */
- } flags;
- } lower;
- union {
- __le32 data;
- struct {
- u8 status; /* Descriptor status */
- u8 popts; /* Packet Options */
- __le16 special; /* */
- } fields;
- } upper;
+ __le64 buffer_addr; /* Address of the descriptor's buffer address */
+ union {
+ __le32 data;
+ struct {
+ __le16 length; /* Data buffer length */
+ u8 typ_len_ext; /* */
+ u8 cmd; /* */
+ } flags;
+ } lower;
+ union {
+ __le32 data;
+ struct {
+ u8 status; /* Descriptor status */
+ u8 popts; /* Packet Options */
+ __le16 special; /* */
+ } fields;
+ } upper;
};
/* Filters */
-#define E1000_NUM_UNICAST 16 /* Unicast filter entries */
-#define E1000_MC_TBL_SIZE 128 /* Multicast Filter Table (4096 bits) */
-#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
-
-#define E1000_NUM_UNICAST_ICH8LAN 7
-#define E1000_MC_TBL_SIZE_ICH8LAN 32
-
+#define E1000_NUM_UNICAST 16 /* Unicast filter entries */
+#define E1000_MC_TBL_SIZE 128 /* Multicast Filter Table (4096 bits) */
+#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */
/* Receive Address Register */
struct e1000_rar {
- volatile __le32 low; /* receive address low */
- volatile __le32 high; /* receive address high */
+ volatile __le32 low; /* receive address low */
+ volatile __le32 high; /* receive address high */
};
/* Number of entries in the Multicast Table Array (MTA). */
#define E1000_NUM_MTA_REGISTERS 128
-#define E1000_NUM_MTA_REGISTERS_ICH8LAN 32
/* IPv4 Address Table Entry */
struct e1000_ipv4_at_entry {
- volatile u32 ipv4_addr; /* IP Address (RW) */
- volatile u32 reserved;
+ volatile u32 ipv4_addr; /* IP Address (RW) */
+ volatile u32 reserved;
};
/* Four wakeup IP addresses are supported */
#define E1000_WAKEUP_IP_ADDRESS_COUNT_MAX 4
#define E1000_IP4AT_SIZE E1000_WAKEUP_IP_ADDRESS_COUNT_MAX
-#define E1000_IP4AT_SIZE_ICH8LAN 3
#define E1000_IP6AT_SIZE 1
/* IPv6 Address Table Entry */
struct e1000_ipv6_at_entry {
- volatile u8 ipv6_addr[16];
+ volatile u8 ipv6_addr[16];
};
/* Flexible Filter Length Table Entry */
struct e1000_fflt_entry {
- volatile u32 length; /* Flexible Filter Length (RW) */
- volatile u32 reserved;
+ volatile u32 length; /* Flexible Filter Length (RW) */
+ volatile u32 reserved;
};
/* Flexible Filter Mask Table Entry */
struct e1000_ffmt_entry {
- volatile u32 mask; /* Flexible Filter Mask (RW) */
- volatile u32 reserved;
+ volatile u32 mask; /* Flexible Filter Mask (RW) */
+ volatile u32 reserved;
};
/* Flexible Filter Value Table Entry */
struct e1000_ffvt_entry {
- volatile u32 value; /* Flexible Filter Value (RW) */
- volatile u32 reserved;
+ volatile u32 value; /* Flexible Filter Value (RW) */
+ volatile u32 reserved;
};
/* Four Flexible Filters are supported */
* R/clr - register is read only and is cleared when read
* A - register array
*/
-#define E1000_CTRL 0x00000 /* Device Control - RW */
-#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */
-#define E1000_STATUS 0x00008 /* Device Status - RO */
-#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */
-#define E1000_EERD 0x00014 /* EEPROM Read - RW */
-#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
-#define E1000_FLA 0x0001C /* Flash Access - RW */
-#define E1000_MDIC 0x00020 /* MDI Control - RW */
-#define E1000_SCTL 0x00024 /* SerDes Control - RW */
-#define E1000_FEXTNVM 0x00028 /* Future Extended NVM register */
-#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
-#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
-#define E1000_FCT 0x00030 /* Flow Control Type - RW */
-#define E1000_VET 0x00038 /* VLAN Ether Type - RW */
-#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */
-#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
-#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
-#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
-#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
-#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
-#define E1000_RCTL 0x00100 /* RX Control - RW */
-#define E1000_RDTR1 0x02820 /* RX Delay Timer (1) - RW */
-#define E1000_RDBAL1 0x02900 /* RX Descriptor Base Address Low (1) - RW */
-#define E1000_RDBAH1 0x02904 /* RX Descriptor Base Address High (1) - RW */
-#define E1000_RDLEN1 0x02908 /* RX Descriptor Length (1) - RW */
-#define E1000_RDH1 0x02910 /* RX Descriptor Head (1) - RW */
-#define E1000_RDT1 0x02918 /* RX Descriptor Tail (1) - RW */
-#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
-#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */
-#define E1000_RXCW 0x00180 /* RX Configuration Word - RO */
-#define E1000_TCTL 0x00400 /* TX Control - RW */
-#define E1000_TCTL_EXT 0x00404 /* Extended TX Control - RW */
-#define E1000_TIPG 0x00410 /* TX Inter-packet gap -RW */
-#define E1000_TBT 0x00448 /* TX Burst Timer - RW */
-#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */
-#define E1000_LEDCTL 0x00E00 /* LED Control - RW */
-#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */
-#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */
-#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */
+#define E1000_CTRL 0x00000 /* Device Control - RW */
+#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */
+#define E1000_STATUS 0x00008 /* Device Status - RO */
+#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */
+#define E1000_EERD 0x00014 /* EEPROM Read - RW */
+#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */
+#define E1000_FLA 0x0001C /* Flash Access - RW */
+#define E1000_MDIC 0x00020 /* MDI Control - RW */
+#define E1000_SCTL 0x00024 /* SerDes Control - RW */
+#define E1000_FEXTNVM 0x00028 /* Future Extended NVM register */
+#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */
+#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */
+#define E1000_FCT 0x00030 /* Flow Control Type - RW */
+#define E1000_VET 0x00038 /* VLAN Ether Type - RW */
+#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */
+#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
+#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
+#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
+#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
+#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
+#define E1000_RCTL 0x00100 /* RX Control - RW */
+#define E1000_RDTR1 0x02820 /* RX Delay Timer (1) - RW */
+#define E1000_RDBAL1 0x02900 /* RX Descriptor Base Address Low (1) - RW */
+#define E1000_RDBAH1 0x02904 /* RX Descriptor Base Address High (1) - RW */
+#define E1000_RDLEN1 0x02908 /* RX Descriptor Length (1) - RW */
+#define E1000_RDH1 0x02910 /* RX Descriptor Head (1) - RW */
+#define E1000_RDT1 0x02918 /* RX Descriptor Tail (1) - RW */
+#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
+#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */
+#define E1000_RXCW 0x00180 /* RX Configuration Word - RO */
+#define E1000_TCTL 0x00400 /* TX Control - RW */
+#define E1000_TCTL_EXT 0x00404 /* Extended TX Control - RW */
+#define E1000_TIPG 0x00410 /* TX Inter-packet gap -RW */
+#define E1000_TBT 0x00448 /* TX Burst Timer - RW */
+#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */
+#define E1000_LEDCTL 0x00E00 /* LED Control - RW */
+#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */
+#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */
+#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */
#define FEXTNVM_SW_CONFIG 0x0001
-#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
-#define E1000_PBS 0x01008 /* Packet Buffer Size */
-#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
+#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
+#define E1000_PBS 0x01008 /* Packet Buffer Size */
+#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
#define E1000_FLASH_UPDATES 1000
-#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */
-#define E1000_FLASHT 0x01028 /* FLASH Timer Register */
-#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */
-#define E1000_FLSWCTL 0x01030 /* FLASH control register */
-#define E1000_FLSWDATA 0x01034 /* FLASH data register */
-#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */
-#define E1000_FLOP 0x0103C /* FLASH Opcode Register */
-#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */
-#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
-#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
-#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */
-#define E1000_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */
-#define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */
-#define E1000_RDLEN 0x02808 /* RX Descriptor Length - RW */
-#define E1000_RDH 0x02810 /* RX Descriptor Head - RW */
-#define E1000_RDT 0x02818 /* RX Descriptor Tail - RW */
-#define E1000_RDTR 0x02820 /* RX Delay Timer - RW */
-#define E1000_RDBAL0 E1000_RDBAL /* RX Desc Base Address Low (0) - RW */
-#define E1000_RDBAH0 E1000_RDBAH /* RX Desc Base Address High (0) - RW */
-#define E1000_RDLEN0 E1000_RDLEN /* RX Desc Length (0) - RW */
-#define E1000_RDH0 E1000_RDH /* RX Desc Head (0) - RW */
-#define E1000_RDT0 E1000_RDT /* RX Desc Tail (0) - RW */
-#define E1000_RDTR0 E1000_RDTR /* RX Delay Timer (0) - RW */
-#define E1000_RXDCTL 0x02828 /* RX Descriptor Control queue 0 - RW */
-#define E1000_RXDCTL1 0x02928 /* RX Descriptor Control queue 1 - RW */
-#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */
-#define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */
-#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */
-#define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */
-#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */
-#define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */
-#define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */
-#define E1000_TDFHS 0x03420 /* TX Data FIFO Head Saved - RW */
-#define E1000_TDFTS 0x03428 /* TX Data FIFO Tail Saved - RW */
-#define E1000_TDFPC 0x03430 /* TX Data FIFO Packet Count - RW */
-#define E1000_TDBAL 0x03800 /* TX Descriptor Base Address Low - RW */
-#define E1000_TDBAH 0x03804 /* TX Descriptor Base Address High - RW */
-#define E1000_TDLEN 0x03808 /* TX Descriptor Length - RW */
-#define E1000_TDH 0x03810 /* TX Descriptor Head - RW */
-#define E1000_TDT 0x03818 /* TX Descripotr Tail - RW */
-#define E1000_TIDV 0x03820 /* TX Interrupt Delay Value - RW */
-#define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */
-#define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */
-#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
-#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */
-#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */
-#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */
-#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */
-#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */
-#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */
-#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */
-#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */
-#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
-#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
-#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
-#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */
-#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */
-#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */
-#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */
-#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */
-#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */
-#define E1000_COLC 0x04028 /* Collision Count - R/clr */
-#define E1000_DC 0x04030 /* Defer Count - R/clr */
-#define E1000_TNCRS 0x04034 /* TX-No CRS - R/clr */
-#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */
-#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */
-#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */
-#define E1000_XONRXC 0x04048 /* XON RX Count - R/clr */
-#define E1000_XONTXC 0x0404C /* XON TX Count - R/clr */
-#define E1000_XOFFRXC 0x04050 /* XOFF RX Count - R/clr */
-#define E1000_XOFFTXC 0x04054 /* XOFF TX Count - R/clr */
-#define E1000_FCRUC 0x04058 /* Flow Control RX Unsupported Count- R/clr */
-#define E1000_PRC64 0x0405C /* Packets RX (64 bytes) - R/clr */
-#define E1000_PRC127 0x04060 /* Packets RX (65-127 bytes) - R/clr */
-#define E1000_PRC255 0x04064 /* Packets RX (128-255 bytes) - R/clr */
-#define E1000_PRC511 0x04068 /* Packets RX (255-511 bytes) - R/clr */
-#define E1000_PRC1023 0x0406C /* Packets RX (512-1023 bytes) - R/clr */
-#define E1000_PRC1522 0x04070 /* Packets RX (1024-1522 bytes) - R/clr */
-#define E1000_GPRC 0x04074 /* Good Packets RX Count - R/clr */
-#define E1000_BPRC 0x04078 /* Broadcast Packets RX Count - R/clr */
-#define E1000_MPRC 0x0407C /* Multicast Packets RX Count - R/clr */
-#define E1000_GPTC 0x04080 /* Good Packets TX Count - R/clr */
-#define E1000_GORCL 0x04088 /* Good Octets RX Count Low - R/clr */
-#define E1000_GORCH 0x0408C /* Good Octets RX Count High - R/clr */
-#define E1000_GOTCL 0x04090 /* Good Octets TX Count Low - R/clr */
-#define E1000_GOTCH 0x04094 /* Good Octets TX Count High - R/clr */
-#define E1000_RNBC 0x040A0 /* RX No Buffers Count - R/clr */
-#define E1000_RUC 0x040A4 /* RX Undersize Count - R/clr */
-#define E1000_RFC 0x040A8 /* RX Fragment Count - R/clr */
-#define E1000_ROC 0x040AC /* RX Oversize Count - R/clr */
-#define E1000_RJC 0x040B0 /* RX Jabber Count - R/clr */
-#define E1000_MGTPRC 0x040B4 /* Management Packets RX Count - R/clr */
-#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */
-#define E1000_MGTPTC 0x040BC /* Management Packets TX Count - R/clr */
-#define E1000_TORL 0x040C0 /* Total Octets RX Low - R/clr */
-#define E1000_TORH 0x040C4 /* Total Octets RX High - R/clr */
-#define E1000_TOTL 0x040C8 /* Total Octets TX Low - R/clr */
-#define E1000_TOTH 0x040CC /* Total Octets TX High - R/clr */
-#define E1000_TPR 0x040D0 /* Total Packets RX - R/clr */
-#define E1000_TPT 0x040D4 /* Total Packets TX - R/clr */
-#define E1000_PTC64 0x040D8 /* Packets TX (64 bytes) - R/clr */
-#define E1000_PTC127 0x040DC /* Packets TX (65-127 bytes) - R/clr */
-#define E1000_PTC255 0x040E0 /* Packets TX (128-255 bytes) - R/clr */
-#define E1000_PTC511 0x040E4 /* Packets TX (256-511 bytes) - R/clr */
-#define E1000_PTC1023 0x040E8 /* Packets TX (512-1023 bytes) - R/clr */
-#define E1000_PTC1522 0x040EC /* Packets TX (1024-1522 Bytes) - R/clr */
-#define E1000_MPTC 0x040F0 /* Multicast Packets TX Count - R/clr */
-#define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */
-#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */
-#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */
-#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
-#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Packet Timer Expire Count */
-#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Absolute Timer Expire Count */
-#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Packet Timer Expire Count */
-#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Absolute Timer Expire Count */
-#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */
-#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Minimum Threshold Count */
-#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
-#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
-#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */
-#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
-#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
-#define E1000_RA 0x05400 /* Receive Address - RW Array */
-#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
-#define E1000_WUC 0x05800 /* Wakeup Control - RW */
-#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */
-#define E1000_WUS 0x05810 /* Wakeup Status - RO */
-#define E1000_MANC 0x05820 /* Management Control - RW */
-#define E1000_IPAV 0x05838 /* IP Address Valid - RW */
-#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */
-#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */
-#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */
-#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */
-#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */
-#define E1000_HOST_IF 0x08800 /* Host Interface */
-#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */
-#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */
-
-#define E1000_KUMCTRLSTA 0x00034 /* MAC-PHY interface - RW */
-#define E1000_MDPHYA 0x0003C /* PHY address - RW */
-#define E1000_MANC2H 0x05860 /* Managment Control To Host - RW */
-#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
-
-#define E1000_GCR 0x05B00 /* PCI-Ex Control */
-#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */
-#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */
-#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */
-#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */
-#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
-#define E1000_SWSM 0x05B50 /* SW Semaphore */
-#define E1000_FWSM 0x05B54 /* FW Semaphore */
-#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
-#define E1000_HICR 0x08F00 /* Host Inteface Control */
+#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */
+#define E1000_FLASHT 0x01028 /* FLASH Timer Register */
+#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */
+#define E1000_FLSWCTL 0x01030 /* FLASH control register */
+#define E1000_FLSWDATA 0x01034 /* FLASH data register */
+#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */
+#define E1000_FLOP 0x0103C /* FLASH Opcode Register */
+#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */
+#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
+#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
+#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */
+#define E1000_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */
+#define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */
+#define E1000_RDLEN 0x02808 /* RX Descriptor Length - RW */
+#define E1000_RDH 0x02810 /* RX Descriptor Head - RW */
+#define E1000_RDT 0x02818 /* RX Descriptor Tail - RW */
+#define E1000_RDTR 0x02820 /* RX Delay Timer - RW */
+#define E1000_RDBAL0 E1000_RDBAL /* RX Desc Base Address Low (0) - RW */
+#define E1000_RDBAH0 E1000_RDBAH /* RX Desc Base Address High (0) - RW */
+#define E1000_RDLEN0 E1000_RDLEN /* RX Desc Length (0) - RW */
+#define E1000_RDH0 E1000_RDH /* RX Desc Head (0) - RW */
+#define E1000_RDT0 E1000_RDT /* RX Desc Tail (0) - RW */
+#define E1000_RDTR0 E1000_RDTR /* RX Delay Timer (0) - RW */
+#define E1000_RXDCTL 0x02828 /* RX Descriptor Control queue 0 - RW */
+#define E1000_RXDCTL1 0x02928 /* RX Descriptor Control queue 1 - RW */
+#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */
+#define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */
+#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */
+#define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */
+#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */
+#define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */
+#define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */
+#define E1000_TDFHS 0x03420 /* TX Data FIFO Head Saved - RW */
+#define E1000_TDFTS 0x03428 /* TX Data FIFO Tail Saved - RW */
+#define E1000_TDFPC 0x03430 /* TX Data FIFO Packet Count - RW */
+#define E1000_TDBAL 0x03800 /* TX Descriptor Base Address Low - RW */
+#define E1000_TDBAH 0x03804 /* TX Descriptor Base Address High - RW */
+#define E1000_TDLEN 0x03808 /* TX Descriptor Length - RW */
+#define E1000_TDH 0x03810 /* TX Descriptor Head - RW */
+#define E1000_TDT 0x03818 /* TX Descripotr Tail - RW */
+#define E1000_TIDV 0x03820 /* TX Interrupt Delay Value - RW */
+#define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */
+#define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */
+#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
+#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */
+#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */
+#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */
+#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */
+#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */
+#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */
+#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */
+#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */
+#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
+#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
+#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
+#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */
+#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */
+#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */
+#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */
+#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */
+#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */
+#define E1000_COLC 0x04028 /* Collision Count - R/clr */
+#define E1000_DC 0x04030 /* Defer Count - R/clr */
+#define E1000_TNCRS 0x04034 /* TX-No CRS - R/clr */
+#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */
+#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */
+#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */
+#define E1000_XONRXC 0x04048 /* XON RX Count - R/clr */
+#define E1000_XONTXC 0x0404C /* XON TX Count - R/clr */
+#define E1000_XOFFRXC 0x04050 /* XOFF RX Count - R/clr */
+#define E1000_XOFFTXC 0x04054 /* XOFF TX Count - R/clr */
+#define E1000_FCRUC 0x04058 /* Flow Control RX Unsupported Count- R/clr */
+#define E1000_PRC64 0x0405C /* Packets RX (64 bytes) - R/clr */
+#define E1000_PRC127 0x04060 /* Packets RX (65-127 bytes) - R/clr */
+#define E1000_PRC255 0x04064 /* Packets RX (128-255 bytes) - R/clr */
+#define E1000_PRC511 0x04068 /* Packets RX (255-511 bytes) - R/clr */
+#define E1000_PRC1023 0x0406C /* Packets RX (512-1023 bytes) - R/clr */
+#define E1000_PRC1522 0x04070 /* Packets RX (1024-1522 bytes) - R/clr */
+#define E1000_GPRC 0x04074 /* Good Packets RX Count - R/clr */
+#define E1000_BPRC 0x04078 /* Broadcast Packets RX Count - R/clr */
+#define E1000_MPRC 0x0407C /* Multicast Packets RX Count - R/clr */
+#define E1000_GPTC 0x04080 /* Good Packets TX Count - R/clr */
+#define E1000_GORCL 0x04088 /* Good Octets RX Count Low - R/clr */
+#define E1000_GORCH 0x0408C /* Good Octets RX Count High - R/clr */
+#define E1000_GOTCL 0x04090 /* Good Octets TX Count Low - R/clr */
+#define E1000_GOTCH 0x04094 /* Good Octets TX Count High - R/clr */
+#define E1000_RNBC 0x040A0 /* RX No Buffers Count - R/clr */
+#define E1000_RUC 0x040A4 /* RX Undersize Count - R/clr */
+#define E1000_RFC 0x040A8 /* RX Fragment Count - R/clr */
+#define E1000_ROC 0x040AC /* RX Oversize Count - R/clr */
+#define E1000_RJC 0x040B0 /* RX Jabber Count - R/clr */
+#define E1000_MGTPRC 0x040B4 /* Management Packets RX Count - R/clr */
+#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */
+#define E1000_MGTPTC 0x040BC /* Management Packets TX Count - R/clr */
+#define E1000_TORL 0x040C0 /* Total Octets RX Low - R/clr */
+#define E1000_TORH 0x040C4 /* Total Octets RX High - R/clr */
+#define E1000_TOTL 0x040C8 /* Total Octets TX Low - R/clr */
+#define E1000_TOTH 0x040CC /* Total Octets TX High - R/clr */
+#define E1000_TPR 0x040D0 /* Total Packets RX - R/clr */
+#define E1000_TPT 0x040D4 /* Total Packets TX - R/clr */
+#define E1000_PTC64 0x040D8 /* Packets TX (64 bytes) - R/clr */
+#define E1000_PTC127 0x040DC /* Packets TX (65-127 bytes) - R/clr */
+#define E1000_PTC255 0x040E0 /* Packets TX (128-255 bytes) - R/clr */
+#define E1000_PTC511 0x040E4 /* Packets TX (256-511 bytes) - R/clr */
+#define E1000_PTC1023 0x040E8 /* Packets TX (512-1023 bytes) - R/clr */
+#define E1000_PTC1522 0x040EC /* Packets TX (1024-1522 Bytes) - R/clr */
+#define E1000_MPTC 0x040F0 /* Multicast Packets TX Count - R/clr */
+#define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */
+#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */
+#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */
+#define E1000_IAC 0x04100 /* Interrupt Assertion Count */
+#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Packet Timer Expire Count */
+#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Absolute Timer Expire Count */
+#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Packet Timer Expire Count */
+#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Absolute Timer Expire Count */
+#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */
+#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Minimum Threshold Count */
+#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
+#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
+#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */
+#define E1000_RFCTL 0x05008 /* Receive Filter Control */
+#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
+#define E1000_RA 0x05400 /* Receive Address - RW Array */
+#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
+#define E1000_WUC 0x05800 /* Wakeup Control - RW */
+#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */
+#define E1000_WUS 0x05810 /* Wakeup Status - RO */
+#define E1000_MANC 0x05820 /* Management Control - RW */
+#define E1000_IPAV 0x05838 /* IP Address Valid - RW */
+#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */
+#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */
+#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */
+#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */
+#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */
+#define E1000_HOST_IF 0x08800 /* Host Interface */
+#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */
+#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */
+
+#define E1000_KUMCTRLSTA 0x00034 /* MAC-PHY interface - RW */
+#define E1000_MDPHYA 0x0003C /* PHY address - RW */
+#define E1000_MANC2H 0x05860 /* Managment Control To Host - RW */
+#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */
+
+#define E1000_GCR 0x05B00 /* PCI-Ex Control */
+#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */
+#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */
+#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */
+#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */
+#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
+#define E1000_SWSM 0x05B50 /* SW Semaphore */
+#define E1000_FWSM 0x05B54 /* FW Semaphore */
+#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
+#define E1000_HICR 0x08F00 /* Host Interface Control */
/* RSS registers */
-#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
-#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
-#define E1000_RETA 0x05C00 /* Redirection Table - RW Array */
-#define E1000_RSSRK 0x05C80 /* RSS Random Key - RW Array */
-#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
-#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
+#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */
+#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */
+#define E1000_RETA 0x05C00 /* Redirection Table - RW Array */
+#define E1000_RSSRK 0x05C80 /* RSS Random Key - RW Array */
+#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */
+#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */
/* Register Set (82542)
*
* Some of the 82542 registers are located at different offsets than they are
#define E1000_82542_RDLEN0 E1000_82542_RDLEN
#define E1000_82542_RDH0 E1000_82542_RDH
#define E1000_82542_RDT0 E1000_82542_RDT
-#define E1000_82542_SRRCTL(_n) (0x280C + ((_n) << 8)) /* Split and Replication
- * RX Control - RW */
+#define E1000_82542_SRRCTL(_n) (0x280C + ((_n) << 8)) /* Split and Replication
+ * RX Control - RW */
#define E1000_82542_DCA_RXCTRL(_n) (0x02814 + ((_n) << 8))
-#define E1000_82542_RDBAH3 0x02B04 /* RX Desc Base High Queue 3 - RW */
-#define E1000_82542_RDBAL3 0x02B00 /* RX Desc Low Queue 3 - RW */
-#define E1000_82542_RDLEN3 0x02B08 /* RX Desc Length Queue 3 - RW */
-#define E1000_82542_RDH3 0x02B10 /* RX Desc Head Queue 3 - RW */
-#define E1000_82542_RDT3 0x02B18 /* RX Desc Tail Queue 3 - RW */
-#define E1000_82542_RDBAL2 0x02A00 /* RX Desc Base Low Queue 2 - RW */
-#define E1000_82542_RDBAH2 0x02A04 /* RX Desc Base High Queue 2 - RW */
-#define E1000_82542_RDLEN2 0x02A08 /* RX Desc Length Queue 2 - RW */
-#define E1000_82542_RDH2 0x02A10 /* RX Desc Head Queue 2 - RW */
-#define E1000_82542_RDT2 0x02A18 /* RX Desc Tail Queue 2 - RW */
+#define E1000_82542_RDBAH3 0x02B04 /* RX Desc Base High Queue 3 - RW */
+#define E1000_82542_RDBAL3 0x02B00 /* RX Desc Low Queue 3 - RW */
+#define E1000_82542_RDLEN3 0x02B08 /* RX Desc Length Queue 3 - RW */
+#define E1000_82542_RDH3 0x02B10 /* RX Desc Head Queue 3 - RW */
+#define E1000_82542_RDT3 0x02B18 /* RX Desc Tail Queue 3 - RW */
+#define E1000_82542_RDBAL2 0x02A00 /* RX Desc Base Low Queue 2 - RW */
+#define E1000_82542_RDBAH2 0x02A04 /* RX Desc Base High Queue 2 - RW */
+#define E1000_82542_RDLEN2 0x02A08 /* RX Desc Length Queue 2 - RW */
+#define E1000_82542_RDH2 0x02A10 /* RX Desc Head Queue 2 - RW */
+#define E1000_82542_RDT2 0x02A18 /* RX Desc Tail Queue 2 - RW */
#define E1000_82542_RDTR1 0x00130
#define E1000_82542_RDBAL1 0x00138
#define E1000_82542_RDBAH1 0x0013C
#define E1000_82542_RSSIR E1000_RSSIR
#define E1000_82542_KUMCTRLSTA E1000_KUMCTRLSTA
#define E1000_82542_SW_FW_SYNC E1000_SW_FW_SYNC
-#define E1000_82542_MANC2H E1000_MANC2H
/* Statistics counters collected by the MAC */
struct e1000_hw_stats {
- u64 crcerrs;
- u64 algnerrc;
- u64 symerrs;
- u64 rxerrc;
- u64 txerrc;
- u64 mpc;
- u64 scc;
- u64 ecol;
- u64 mcc;
- u64 latecol;
- u64 colc;
- u64 dc;
- u64 tncrs;
- u64 sec;
- u64 cexterr;
- u64 rlec;
- u64 xonrxc;
- u64 xontxc;
- u64 xoffrxc;
- u64 xofftxc;
- u64 fcruc;
- u64 prc64;
- u64 prc127;
- u64 prc255;
- u64 prc511;
- u64 prc1023;
- u64 prc1522;
- u64 gprc;
- u64 bprc;
- u64 mprc;
- u64 gptc;
- u64 gorcl;
- u64 gorch;
- u64 gotcl;
- u64 gotch;
- u64 rnbc;
- u64 ruc;
- u64 rfc;
- u64 roc;
- u64 rlerrc;
- u64 rjc;
- u64 mgprc;
- u64 mgpdc;
- u64 mgptc;
- u64 torl;
- u64 torh;
- u64 totl;
- u64 toth;
- u64 tpr;
- u64 tpt;
- u64 ptc64;
- u64 ptc127;
- u64 ptc255;
- u64 ptc511;
- u64 ptc1023;
- u64 ptc1522;
- u64 mptc;
- u64 bptc;
- u64 tsctc;
- u64 tsctfc;
- u64 iac;
- u64 icrxptc;
- u64 icrxatc;
- u64 ictxptc;
- u64 ictxatc;
- u64 ictxqec;
- u64 ictxqmtc;
- u64 icrxdmtc;
- u64 icrxoc;
+ u64 crcerrs;
+ u64 algnerrc;
+ u64 symerrs;
+ u64 rxerrc;
+ u64 txerrc;
+ u64 mpc;
+ u64 scc;
+ u64 ecol;
+ u64 mcc;
+ u64 latecol;
+ u64 colc;
+ u64 dc;
+ u64 tncrs;
+ u64 sec;
+ u64 cexterr;
+ u64 rlec;
+ u64 xonrxc;
+ u64 xontxc;
+ u64 xoffrxc;
+ u64 xofftxc;
+ u64 fcruc;
+ u64 prc64;
+ u64 prc127;
+ u64 prc255;
+ u64 prc511;
+ u64 prc1023;
+ u64 prc1522;
+ u64 gprc;
+ u64 bprc;
+ u64 mprc;
+ u64 gptc;
+ u64 gorcl;
+ u64 gorch;
+ u64 gotcl;
+ u64 gotch;
+ u64 rnbc;
+ u64 ruc;
+ u64 rfc;
+ u64 roc;
+ u64 rlerrc;
+ u64 rjc;
+ u64 mgprc;
+ u64 mgpdc;
+ u64 mgptc;
+ u64 torl;
+ u64 torh;
+ u64 totl;
+ u64 toth;
+ u64 tpr;
+ u64 tpt;
+ u64 ptc64;
+ u64 ptc127;
+ u64 ptc255;
+ u64 ptc511;
+ u64 ptc1023;
+ u64 ptc1522;
+ u64 mptc;
+ u64 bptc;
+ u64 tsctc;
+ u64 tsctfc;
+ u64 iac;
+ u64 icrxptc;
+ u64 icrxatc;
+ u64 ictxptc;
+ u64 ictxatc;
+ u64 ictxqec;
+ u64 ictxqmtc;
+ u64 icrxdmtc;
+ u64 icrxoc;
};
/* Structure containing variables used by the shared code (e1000_hw.c) */
struct e1000_hw {
- u8 __iomem *hw_addr;
- u8 __iomem *flash_address;
- e1000_mac_type mac_type;
- e1000_phy_type phy_type;
- u32 phy_init_script;
- e1000_media_type media_type;
- void *back;
- struct e1000_shadow_ram *eeprom_shadow_ram;
- u32 flash_bank_size;
- u32 flash_base_addr;
- e1000_fc_type fc;
- e1000_bus_speed bus_speed;
- e1000_bus_width bus_width;
- e1000_bus_type bus_type;
+ u8 __iomem *hw_addr;
+ u8 __iomem *flash_address;
+ e1000_mac_type mac_type;
+ e1000_phy_type phy_type;
+ u32 phy_init_script;
+ e1000_media_type media_type;
+ void *back;
+ struct e1000_shadow_ram *eeprom_shadow_ram;
+ u32 flash_bank_size;
+ u32 flash_base_addr;
+ e1000_fc_type fc;
+ e1000_bus_speed bus_speed;
+ e1000_bus_width bus_width;
+ e1000_bus_type bus_type;
struct e1000_eeprom_info eeprom;
- e1000_ms_type master_slave;
- e1000_ms_type original_master_slave;
- e1000_ffe_config ffe_config_state;
- u32 asf_firmware_present;
- u32 eeprom_semaphore_present;
- u32 swfw_sync_present;
- u32 swfwhw_semaphore_present;
- unsigned long io_base;
- u32 phy_id;
- u32 phy_revision;
- u32 phy_addr;
- u32 original_fc;
- u32 txcw;
- u32 autoneg_failed;
- u32 max_frame_size;
- u32 min_frame_size;
- u32 mc_filter_type;
- u32 num_mc_addrs;
- u32 collision_delta;
- u32 tx_packet_delta;
- u32 ledctl_default;
- u32 ledctl_mode1;
- u32 ledctl_mode2;
- bool tx_pkt_filtering;
+ e1000_ms_type master_slave;
+ e1000_ms_type original_master_slave;
+ e1000_ffe_config ffe_config_state;
+ u32 asf_firmware_present;
+ u32 eeprom_semaphore_present;
+ unsigned long io_base;
+ u32 phy_id;
+ u32 phy_revision;
+ u32 phy_addr;
+ u32 original_fc;
+ u32 txcw;
+ u32 autoneg_failed;
+ u32 max_frame_size;
+ u32 min_frame_size;
+ u32 mc_filter_type;
+ u32 num_mc_addrs;
+ u32 collision_delta;
+ u32 tx_packet_delta;
+ u32 ledctl_default;
+ u32 ledctl_mode1;
+ u32 ledctl_mode2;
+ bool tx_pkt_filtering;
struct e1000_host_mng_dhcp_cookie mng_cookie;
- u16 phy_spd_default;
- u16 autoneg_advertised;
- u16 pci_cmd_word;
- u16 fc_high_water;
- u16 fc_low_water;
- u16 fc_pause_time;
- u16 current_ifs_val;
- u16 ifs_min_val;
- u16 ifs_max_val;
- u16 ifs_step_size;
- u16 ifs_ratio;
- u16 device_id;
- u16 vendor_id;
- u16 subsystem_id;
- u16 subsystem_vendor_id;
- u8 revision_id;
- u8 autoneg;
- u8 mdix;
- u8 forced_speed_duplex;
- u8 wait_autoneg_complete;
- u8 dma_fairness;
- u8 mac_addr[NODE_ADDRESS_SIZE];
- u8 perm_mac_addr[NODE_ADDRESS_SIZE];
- bool disable_polarity_correction;
- bool speed_downgraded;
- e1000_smart_speed smart_speed;
- e1000_dsp_config dsp_config_state;
- bool get_link_status;
- bool serdes_link_down;
- bool tbi_compatibility_en;
- bool tbi_compatibility_on;
- bool laa_is_present;
- bool phy_reset_disable;
- bool initialize_hw_bits_disable;
- bool fc_send_xon;
- bool fc_strict_ieee;
- bool report_tx_early;
- bool adaptive_ifs;
- bool ifs_params_forced;
- bool in_ifs_mode;
- bool mng_reg_access_disabled;
- bool leave_av_bit_off;
- bool kmrn_lock_loss_workaround_disabled;
- bool bad_tx_carr_stats_fd;
- bool has_manc2h;
- bool rx_needs_kicking;
- bool has_smbus;
+ u16 phy_spd_default;
+ u16 autoneg_advertised;
+ u16 pci_cmd_word;
+ u16 fc_high_water;
+ u16 fc_low_water;
+ u16 fc_pause_time;
+ u16 current_ifs_val;
+ u16 ifs_min_val;
+ u16 ifs_max_val;
+ u16 ifs_step_size;
+ u16 ifs_ratio;
+ u16 device_id;
+ u16 vendor_id;
+ u16 subsystem_id;
+ u16 subsystem_vendor_id;
+ u8 revision_id;
+ u8 autoneg;
+ u8 mdix;
+ u8 forced_speed_duplex;
+ u8 wait_autoneg_complete;
+ u8 dma_fairness;
+ u8 mac_addr[NODE_ADDRESS_SIZE];
+ u8 perm_mac_addr[NODE_ADDRESS_SIZE];
+ bool disable_polarity_correction;
+ bool speed_downgraded;
+ e1000_smart_speed smart_speed;
+ e1000_dsp_config dsp_config_state;
+ bool get_link_status;
+ bool serdes_has_link;
+ bool tbi_compatibility_en;
+ bool tbi_compatibility_on;
+ bool laa_is_present;
+ bool phy_reset_disable;
+ bool initialize_hw_bits_disable;
+ bool fc_send_xon;
+ bool fc_strict_ieee;
+ bool report_tx_early;
+ bool adaptive_ifs;
+ bool ifs_params_forced;
+ bool in_ifs_mode;
+ bool mng_reg_access_disabled;
+ bool leave_av_bit_off;
+ bool bad_tx_carr_stats_fd;
+ bool has_smbus;
};
-
-#define E1000_EEPROM_SWDPIN0 0x0001 /* SWDPIN 0 EEPROM Value */
-#define E1000_EEPROM_LED_LOGIC 0x0020 /* Led Logic Word */
-#define E1000_EEPROM_RW_REG_DATA 16 /* Offset to data in EEPROM read/write registers */
-#define E1000_EEPROM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */
-#define E1000_EEPROM_RW_REG_START 1 /* First bit for telling part to start operation */
-#define E1000_EEPROM_RW_ADDR_SHIFT 2 /* Shift to the address bits */
-#define E1000_EEPROM_POLL_WRITE 1 /* Flag for polling for write complete */
-#define E1000_EEPROM_POLL_READ 0 /* Flag for polling for read complete */
+#define E1000_EEPROM_SWDPIN0 0x0001 /* SWDPIN 0 EEPROM Value */
+#define E1000_EEPROM_LED_LOGIC 0x0020 /* Led Logic Word */
+#define E1000_EEPROM_RW_REG_DATA 16 /* Offset to data in EEPROM read/write registers */
+#define E1000_EEPROM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */
+#define E1000_EEPROM_RW_REG_START 1 /* First bit for telling part to start operation */
+#define E1000_EEPROM_RW_ADDR_SHIFT 2 /* Shift to the address bits */
+#define E1000_EEPROM_POLL_WRITE 1 /* Flag for polling for write complete */
+#define E1000_EEPROM_POLL_READ 0 /* Flag for polling for read complete */
/* Register Bit Masks */
/* Device Control */
-#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */
-#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */
-#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */
-#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */
-#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */
-#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */
-#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */
-#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */
-#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */
-#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */
-#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */
-#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */
-#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */
-#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */
-#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */
-#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */
-#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */
-#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */
-#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */
-#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */
-#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */
-#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
-#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
-#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */
-#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */
-#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */
-#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */
-#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */
-#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */
-#define E1000_CTRL_RST 0x04000000 /* Global reset */
-#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */
-#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */
-#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */
-#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */
-#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */
-#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to manageability engine */
+#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */
+#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */
+#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */
+#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */
+#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */
+#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */
+#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */
+#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */
+#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */
+#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */
+#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */
+#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */
+#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */
+#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */
+#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */
+#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */
+#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */
+#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */
+#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */
+#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */
+#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */
+#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
+#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
+#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */
+#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */
+#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */
+#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */
+#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */
+#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */
+#define E1000_CTRL_RST 0x04000000 /* Global reset */
+#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */
+#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */
+#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */
+#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */
+#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */
+#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to manageability engine */
/* Device Status */
-#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
-#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
-#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */
+#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
+#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
+#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */
#define E1000_STATUS_FUNC_SHIFT 2
-#define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */
-#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */
-#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */
-#define E1000_STATUS_TBIMODE 0x00000020 /* TBI mode */
+#define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */
+#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */
+#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */
+#define E1000_STATUS_TBIMODE 0x00000020 /* TBI mode */
#define E1000_STATUS_SPEED_MASK 0x000000C0
-#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */
-#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
-#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
-#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion
- by EEPROM/Flash */
-#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */
-#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. Clear on write '0'. */
-#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */
-#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */
-#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */
-#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */
-#define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */
-#define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */
-#define E1000_STATUS_BMC_SKU_0 0x00100000 /* BMC USB redirect disabled */
-#define E1000_STATUS_BMC_SKU_1 0x00200000 /* BMC SRAM disabled */
-#define E1000_STATUS_BMC_SKU_2 0x00400000 /* BMC SDRAM disabled */
-#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */
-#define E1000_STATUS_BMC_LITE 0x01000000 /* BMC external code execution disabled */
-#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */
+#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */
+#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
+#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
+#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion
+ by EEPROM/Flash */
+#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */
+#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. Clear on write '0'. */
+#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */
+#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */
+#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */
+#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */
+#define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */
+#define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */
+#define E1000_STATUS_BMC_SKU_0 0x00100000 /* BMC USB redirect disabled */
+#define E1000_STATUS_BMC_SKU_1 0x00200000 /* BMC SRAM disabled */
+#define E1000_STATUS_BMC_SKU_2 0x00400000 /* BMC SDRAM disabled */
+#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */
+#define E1000_STATUS_BMC_LITE 0x01000000 /* BMC external code execution disabled */
+#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */
#define E1000_STATUS_FUSE_8 0x04000000
#define E1000_STATUS_FUSE_9 0x08000000
-#define E1000_STATUS_SERDES0_DIS 0x10000000 /* SERDES disabled on port 0 */
-#define E1000_STATUS_SERDES1_DIS 0x20000000 /* SERDES disabled on port 1 */
+#define E1000_STATUS_SERDES0_DIS 0x10000000 /* SERDES disabled on port 0 */
+#define E1000_STATUS_SERDES1_DIS 0x20000000 /* SERDES disabled on port 1 */
-/* Constants used to intrepret the masked PCI-X bus speed. */
-#define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */
-#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */
-#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz */
+/* Constants used to interpret the masked PCI-X bus speed. */
+#define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */
+#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */
+#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz */
/* EEPROM/Flash Control */
-#define E1000_EECD_SK 0x00000001 /* EEPROM Clock */
-#define E1000_EECD_CS 0x00000002 /* EEPROM Chip Select */
-#define E1000_EECD_DI 0x00000004 /* EEPROM Data In */
-#define E1000_EECD_DO 0x00000008 /* EEPROM Data Out */
+#define E1000_EECD_SK 0x00000001 /* EEPROM Clock */
+#define E1000_EECD_CS 0x00000002 /* EEPROM Chip Select */
+#define E1000_EECD_DI 0x00000004 /* EEPROM Data In */
+#define E1000_EECD_DO 0x00000008 /* EEPROM Data Out */
#define E1000_EECD_FWE_MASK 0x00000030
-#define E1000_EECD_FWE_DIS 0x00000010 /* Disable FLASH writes */
-#define E1000_EECD_FWE_EN 0x00000020 /* Enable FLASH writes */
+#define E1000_EECD_FWE_DIS 0x00000010 /* Disable FLASH writes */
+#define E1000_EECD_FWE_EN 0x00000020 /* Enable FLASH writes */
#define E1000_EECD_FWE_SHIFT 4
-#define E1000_EECD_REQ 0x00000040 /* EEPROM Access Request */
-#define E1000_EECD_GNT 0x00000080 /* EEPROM Access Grant */
-#define E1000_EECD_PRES 0x00000100 /* EEPROM Present */
-#define E1000_EECD_SIZE 0x00000200 /* EEPROM Size (0=64 word 1=256 word) */
-#define E1000_EECD_ADDR_BITS 0x00000400 /* EEPROM Addressing bits based on type
- * (0-small, 1-large) */
-#define E1000_EECD_TYPE 0x00002000 /* EEPROM Type (1-SPI, 0-Microwire) */
+#define E1000_EECD_REQ 0x00000040 /* EEPROM Access Request */
+#define E1000_EECD_GNT 0x00000080 /* EEPROM Access Grant */
+#define E1000_EECD_PRES 0x00000100 /* EEPROM Present */
+#define E1000_EECD_SIZE 0x00000200 /* EEPROM Size (0=64 word 1=256 word) */
+#define E1000_EECD_ADDR_BITS 0x00000400 /* EEPROM Addressing bits based on type
+ * (0-small, 1-large) */
+#define E1000_EECD_TYPE 0x00002000 /* EEPROM Type (1-SPI, 0-Microwire) */
#ifndef E1000_EEPROM_GRANT_ATTEMPTS
-#define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */
+#define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */
#endif
-#define E1000_EECD_AUTO_RD 0x00000200 /* EEPROM Auto Read done */
-#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* EEprom Size */
+#define E1000_EECD_AUTO_RD 0x00000200 /* EEPROM Auto Read done */
+#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* EEprom Size */
#define E1000_EECD_SIZE_EX_SHIFT 11
-#define E1000_EECD_NVADDS 0x00018000 /* NVM Address Size */
-#define E1000_EECD_SELSHAD 0x00020000 /* Select Shadow RAM */
-#define E1000_EECD_INITSRAM 0x00040000 /* Initialize Shadow RAM */
-#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */
-#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */
-#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */
-#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
+#define E1000_EECD_NVADDS 0x00018000 /* NVM Address Size */
+#define E1000_EECD_SELSHAD 0x00020000 /* Select Shadow RAM */
+#define E1000_EECD_INITSRAM 0x00040000 /* Initialize Shadow RAM */
+#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */
+#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */
+#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */
+#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
#define E1000_EECD_SECVAL_SHIFT 22
#define E1000_STM_OPCODE 0xDB00
#define E1000_HICR_FW_RESET 0xC0
#define E1000_ICH_NVM_SIG_MASK 0xC0
/* EEPROM Read */
-#define E1000_EERD_START 0x00000001 /* Start Read */
-#define E1000_EERD_DONE 0x00000010 /* Read Done */
+#define E1000_EERD_START 0x00000001 /* Start Read */
+#define E1000_EERD_DONE 0x00000010 /* Read Done */
#define E1000_EERD_ADDR_SHIFT 8
-#define E1000_EERD_ADDR_MASK 0x0000FF00 /* Read Address */
+#define E1000_EERD_ADDR_MASK 0x0000FF00 /* Read Address */
#define E1000_EERD_DATA_SHIFT 16
-#define E1000_EERD_DATA_MASK 0xFFFF0000 /* Read Data */
+#define E1000_EERD_DATA_MASK 0xFFFF0000 /* Read Data */
/* SPI EEPROM Status Register */
#define EEPROM_STATUS_RDY_SPI 0x01
#define EEPROM_STATUS_WPEN_SPI 0x80
/* Extended Device Control */
-#define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */
-#define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */
+#define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */
+#define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */
#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN
-#define E1000_CTRL_EXT_GPI2_EN 0x00000004 /* Maps SDP6 to GPI2 */
-#define E1000_CTRL_EXT_GPI3_EN 0x00000008 /* Maps SDP7 to GPI3 */
-#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Defineable Pin 4 */
-#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Defineable Pin 5 */
+#define E1000_CTRL_EXT_GPI2_EN 0x00000004 /* Maps SDP6 to GPI2 */
+#define E1000_CTRL_EXT_GPI3_EN 0x00000008 /* Maps SDP7 to GPI3 */
+#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Defineable Pin 4 */
+#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Defineable Pin 5 */
#define E1000_CTRL_EXT_PHY_INT E1000_CTRL_EXT_SDP5_DATA
-#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Defineable Pin 6 */
-#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */
-#define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */
-#define E1000_CTRL_EXT_SDP5_DIR 0x00000200 /* Direction of SDP5 0=in 1=out */
-#define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */
-#define E1000_CTRL_EXT_SDP7_DIR 0x00000800 /* Direction of SDP7 0=in 1=out */
-#define E1000_CTRL_EXT_ASDCHK 0x00001000 /* Initiate an ASD sequence */
-#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
-#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */
-#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
-#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
+#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Defineable Pin 6 */
+#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */
+#define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */
+#define E1000_CTRL_EXT_SDP5_DIR 0x00000200 /* Direction of SDP5 0=in 1=out */
+#define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */
+#define E1000_CTRL_EXT_SDP7_DIR 0x00000800 /* Direction of SDP7 0=in 1=out */
+#define E1000_CTRL_EXT_ASDCHK 0x00001000 /* Initiate an ASD sequence */
+#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
+#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */
+#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
+#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000
#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000
#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000
#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000
-#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */
-#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */
-#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */
-#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error detection enabled */
-#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity error detection enable */
+#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */
+#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */
+#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */
+#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error detection enabled */
+#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity error detection enable */
#define E1000_CTRL_EXT_GHOST_PAREN 0x40000000
/* MDI Control */
#define E1000_LEDCTL_MODE_LED_OFF 0xF
/* Receive Address */
-#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */
+#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */
/* Interrupt Cause Read */
-#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */
-#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */
-#define E1000_ICR_LSC 0x00000004 /* Link Status Change */
-#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */
-#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */
-#define E1000_ICR_RXO 0x00000040 /* rx overrun */
-#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */
-#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */
-#define E1000_ICR_RXCFG 0x00000400 /* RX /c/ ordered set */
-#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */
-#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */
-#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */
-#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */
+#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */
+#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */
+#define E1000_ICR_LSC 0x00000004 /* Link Status Change */
+#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */
+#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */
+#define E1000_ICR_RXO 0x00000040 /* rx overrun */
+#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */
+#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */
+#define E1000_ICR_RXCFG 0x00000400 /* RX /c/ ordered set */
+#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */
+#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */
+#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */
+#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */
#define E1000_ICR_TXD_LOW 0x00008000
#define E1000_ICR_SRPD 0x00010000
-#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */
-#define E1000_ICR_MNG 0x00040000 /* Manageability event */
-#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */
-#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */
-#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* queue 0 Rx descriptor FIFO parity error */
-#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* queue 0 Tx descriptor FIFO parity error */
-#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity error */
-#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */
-#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO parity error */
-#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO parity error */
-#define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */
-#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW bit in the FWSM */
-#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates an interrupt */
-#define E1000_ICR_EPRST 0x00100000 /* ME handware reset occurs */
+#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */
+#define E1000_ICR_MNG 0x00040000 /* Manageability event */
+#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */
+#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */
+#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* queue 0 Rx descriptor FIFO parity error */
+#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* queue 0 Tx descriptor FIFO parity error */
+#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity error */
+#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */
+#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO parity error */
+#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO parity error */
+#define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */
+#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW bit in the FWSM */
+#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates an interrupt */
+#define E1000_ICR_EPRST 0x00100000 /* ME hardware reset occurs */
/* Interrupt Cause Set */
-#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
-#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */
-#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */
-#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
-#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
-#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */
-#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
-#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */
-#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */
-#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */
-#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */
-#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */
-#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
+#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
+#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */
+#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */
+#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
+#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
+#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */
+#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
+#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */
+#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */
+#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */
+#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */
+#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */
+#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW
#define E1000_ICS_SRPD E1000_ICR_SRPD
-#define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */
-#define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */
-#define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */
-#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */
-#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */
-#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */
-#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */
-#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
-#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
+#define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */
+#define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */
+#define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */
+#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */
+#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */
+#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */
+#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */
+#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
+#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
#define E1000_ICS_DSW E1000_ICR_DSW
#define E1000_ICS_PHYINT E1000_ICR_PHYINT
#define E1000_ICS_EPRST E1000_ICR_EPRST
/* Interrupt Mask Set */
-#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
-#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */
-#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */
-#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
-#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
-#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */
-#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
-#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */
-#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */
-#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */
-#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */
-#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */
-#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
+#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
+#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */
+#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */
+#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
+#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
+#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */
+#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
+#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */
+#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */
+#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */
+#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */
+#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */
+#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW
#define E1000_IMS_SRPD E1000_ICR_SRPD
-#define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */
-#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */
-#define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */
-#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */
-#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */
-#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */
-#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */
-#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
-#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
+#define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */
+#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */
+#define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */
+#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */
+#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */
+#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */
+#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */
+#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
+#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
#define E1000_IMS_DSW E1000_ICR_DSW
#define E1000_IMS_PHYINT E1000_ICR_PHYINT
#define E1000_IMS_EPRST E1000_ICR_EPRST
/* Interrupt Mask Clear */
-#define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */
-#define E1000_IMC_TXQE E1000_ICR_TXQE /* Transmit Queue empty */
-#define E1000_IMC_LSC E1000_ICR_LSC /* Link Status Change */
-#define E1000_IMC_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
-#define E1000_IMC_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
-#define E1000_IMC_RXO E1000_ICR_RXO /* rx overrun */
-#define E1000_IMC_RXT0 E1000_ICR_RXT0 /* rx timer intr */
-#define E1000_IMC_MDAC E1000_ICR_MDAC /* MDIO access complete */
-#define E1000_IMC_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */
-#define E1000_IMC_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */
-#define E1000_IMC_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */
-#define E1000_IMC_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */
-#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
+#define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */
+#define E1000_IMC_TXQE E1000_ICR_TXQE /* Transmit Queue empty */
+#define E1000_IMC_LSC E1000_ICR_LSC /* Link Status Change */
+#define E1000_IMC_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
+#define E1000_IMC_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
+#define E1000_IMC_RXO E1000_ICR_RXO /* rx overrun */
+#define E1000_IMC_RXT0 E1000_ICR_RXT0 /* rx timer intr */
+#define E1000_IMC_MDAC E1000_ICR_MDAC /* MDIO access complete */
+#define E1000_IMC_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */
+#define E1000_IMC_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */
+#define E1000_IMC_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */
+#define E1000_IMC_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */
+#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW
#define E1000_IMC_SRPD E1000_ICR_SRPD
-#define E1000_IMC_ACK E1000_ICR_ACK /* Receive Ack frame */
-#define E1000_IMC_MNG E1000_ICR_MNG /* Manageability event */
-#define E1000_IMC_DOCK E1000_ICR_DOCK /* Dock/Undock */
-#define E1000_IMC_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */
-#define E1000_IMC_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */
-#define E1000_IMC_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */
-#define E1000_IMC_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */
-#define E1000_IMC_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
-#define E1000_IMC_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
+#define E1000_IMC_ACK E1000_ICR_ACK /* Receive Ack frame */
+#define E1000_IMC_MNG E1000_ICR_MNG /* Manageability event */
+#define E1000_IMC_DOCK E1000_ICR_DOCK /* Dock/Undock */
+#define E1000_IMC_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */
+#define E1000_IMC_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */
+#define E1000_IMC_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */
+#define E1000_IMC_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */
+#define E1000_IMC_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */
+#define E1000_IMC_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */
#define E1000_IMC_DSW E1000_ICR_DSW
#define E1000_IMC_PHYINT E1000_ICR_PHYINT
#define E1000_IMC_EPRST E1000_ICR_EPRST
/* Receive Control */
-#define E1000_RCTL_RST 0x00000001 /* Software reset */
-#define E1000_RCTL_EN 0x00000002 /* enable */
-#define E1000_RCTL_SBP 0x00000004 /* store bad packet */
-#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */
-#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */
-#define E1000_RCTL_LPE 0x00000020 /* long packet enable */
-#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */
-#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */
-#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */
-#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
-#define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */
-#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */
-#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */
-#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */
-#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */
-#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */
-#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */
-#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */
-#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */
-#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */
-#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */
-#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */
+#define E1000_RCTL_RST 0x00000001 /* Software reset */
+#define E1000_RCTL_EN 0x00000002 /* enable */
+#define E1000_RCTL_SBP 0x00000004 /* store bad packet */
+#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */
+#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */
+#define E1000_RCTL_LPE 0x00000020 /* long packet enable */
+#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */
+#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */
+#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */
+#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
+#define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */
+#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */
+#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */
+#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */
+#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */
+#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */
+#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */
+#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */
+#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */
+#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */
+#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */
+#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */
/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
-#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */
-#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */
-#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */
-#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */
+#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */
+#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */
+#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */
+#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */
/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
-#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */
-#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */
-#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */
-#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */
-#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */
-#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */
-#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */
-#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */
-#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */
-#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
-#define E1000_RCTL_FLXBUF_MASK 0x78000000 /* Flexible buffer size */
-#define E1000_RCTL_FLXBUF_SHIFT 27 /* Flexible buffer shift */
+#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */
+#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */
+#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */
+#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */
+#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */
+#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */
+#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */
+#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */
+#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */
+#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
+#define E1000_RCTL_FLXBUF_MASK 0x78000000 /* Flexible buffer size */
+#define E1000_RCTL_FLXBUF_SHIFT 27 /* Flexible buffer shift */
/* Use byte values for the following shift parameters
* Usage:
#define E1000_PSRCTL_BSIZE2_MASK 0x003F0000
#define E1000_PSRCTL_BSIZE3_MASK 0x3F000000
-#define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */
-#define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */
-#define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */
-#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */
+#define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */
+#define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */
+#define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */
+#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */
/* SW_W_SYNC definitions */
#define E1000_SWFW_EEP_SM 0x0001
#define E1000_SWFW_MAC_CSR_SM 0x0008
/* Receive Descriptor */
-#define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */
-#define E1000_RDT_FPDB 0x80000000 /* Flush descriptor block */
-#define E1000_RDLEN_LEN 0x0007ff80 /* descriptor length */
-#define E1000_RDH_RDH 0x0000ffff /* receive descriptor head */
-#define E1000_RDT_RDT 0x0000ffff /* receive descriptor tail */
+#define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */
+#define E1000_RDT_FPDB 0x80000000 /* Flush descriptor block */
+#define E1000_RDLEN_LEN 0x0007ff80 /* descriptor length */
+#define E1000_RDH_RDH 0x0000ffff /* receive descriptor head */
+#define E1000_RDT_RDT 0x0000ffff /* receive descriptor tail */
/* Flow Control */
-#define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */
-#define E1000_FCRTH_XFCE 0x80000000 /* External Flow Control Enable */
-#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */
-#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */
+#define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */
+#define E1000_FCRTH_XFCE 0x80000000 /* External Flow Control Enable */
+#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */
+#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */
/* Header split receive */
#define E1000_RFCTL_ISCSI_DIS 0x00000001
#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000
/* Receive Descriptor Control */
-#define E1000_RXDCTL_PTHRESH 0x0000003F /* RXDCTL Prefetch Threshold */
-#define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */
-#define E1000_RXDCTL_WTHRESH 0x003F0000 /* RXDCTL Writeback Threshold */
-#define E1000_RXDCTL_GRAN 0x01000000 /* RXDCTL Granularity */
+#define E1000_RXDCTL_PTHRESH 0x0000003F /* RXDCTL Prefetch Threshold */
+#define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */
+#define E1000_RXDCTL_WTHRESH 0x003F0000 /* RXDCTL Writeback Threshold */
+#define E1000_RXDCTL_GRAN 0x01000000 /* RXDCTL Granularity */
/* Transmit Descriptor Control */
-#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
-#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */
-#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */
-#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */
-#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
-#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
-#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc.
- still to be processed. */
+#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
+#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */
+#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */
+#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */
+#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
+#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
+#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc.
+ still to be processed. */
/* Transmit Configuration Word */
-#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */
-#define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */
-#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */
-#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */
-#define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */
-#define E1000_TXCW_RF 0x00003000 /* TXCW remote fault */
-#define E1000_TXCW_NP 0x00008000 /* TXCW next page */
-#define E1000_TXCW_CW 0x0000ffff /* TxConfigWord mask */
-#define E1000_TXCW_TXC 0x40000000 /* Transmit Config control */
-#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */
+#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */
+#define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */
+#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */
+#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */
+#define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */
+#define E1000_TXCW_RF 0x00003000 /* TXCW remote fault */
+#define E1000_TXCW_NP 0x00008000 /* TXCW next page */
+#define E1000_TXCW_CW 0x0000ffff /* TxConfigWord mask */
+#define E1000_TXCW_TXC 0x40000000 /* Transmit Config control */
+#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */
/* Receive Configuration Word */
-#define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */
-#define E1000_RXCW_NC 0x04000000 /* Receive config no carrier */
-#define E1000_RXCW_IV 0x08000000 /* Receive config invalid */
-#define E1000_RXCW_CC 0x10000000 /* Receive config change */
-#define E1000_RXCW_C 0x20000000 /* Receive config */
-#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */
-#define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */
+#define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */
+#define E1000_RXCW_NC 0x04000000 /* Receive config no carrier */
+#define E1000_RXCW_IV 0x08000000 /* Receive config invalid */
+#define E1000_RXCW_CC 0x10000000 /* Receive config change */
+#define E1000_RXCW_C 0x20000000 /* Receive config */
+#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */
+#define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */
/* Transmit Control */
-#define E1000_TCTL_RST 0x00000001 /* software reset */
-#define E1000_TCTL_EN 0x00000002 /* enable tx */
-#define E1000_TCTL_BCE 0x00000004 /* busy check enable */
-#define E1000_TCTL_PSP 0x00000008 /* pad short packets */
-#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */
-#define E1000_TCTL_COLD 0x003ff000 /* collision distance */
-#define E1000_TCTL_SWXOFF 0x00400000 /* SW Xoff transmission */
-#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */
-#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */
-#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */
-#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */
+#define E1000_TCTL_RST 0x00000001 /* software reset */
+#define E1000_TCTL_EN 0x00000002 /* enable tx */
+#define E1000_TCTL_BCE 0x00000004 /* busy check enable */
+#define E1000_TCTL_PSP 0x00000008 /* pad short packets */
+#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */
+#define E1000_TCTL_COLD 0x003ff000 /* collision distance */
+#define E1000_TCTL_SWXOFF 0x00400000 /* SW Xoff transmission */
+#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */
+#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */
+#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */
+#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */
/* Extended Transmit Control */
-#define E1000_TCTL_EXT_BST_MASK 0x000003FF /* Backoff Slot Time */
-#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */
-
-#define DEFAULT_80003ES2LAN_TCTL_EXT_GCEX 0x00010000
+#define E1000_TCTL_EXT_BST_MASK 0x000003FF /* Backoff Slot Time */
+#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */
/* Receive Checksum Control */
-#define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */
-#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */
-#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */
-#define E1000_RXCSUM_IPV6OFL 0x00000400 /* IPv6 checksum offload */
-#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
-#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
+#define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */
+#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */
+#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */
+#define E1000_RXCSUM_IPV6OFL 0x00000400 /* IPv6 checksum offload */
+#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
+#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
/* Multiple Receive Queue Control */
#define E1000_MRQC_ENABLE_MASK 0x00000003
/* Definitions for power management and wakeup registers */
/* Wake Up Control */
-#define E1000_WUC_APME 0x00000001 /* APM Enable */
-#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */
-#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */
-#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */
-#define E1000_WUC_SPM 0x80000000 /* Enable SPM */
+#define E1000_WUC_APME 0x00000001 /* APM Enable */
+#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */
+#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */
+#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */
+#define E1000_WUC_SPM 0x80000000 /* Enable SPM */
/* Wake Up Filter Control */
-#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
-#define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
-#define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
-#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */
-#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
-#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */
-#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */
-#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */
-#define E1000_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */
-#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */
-#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */
-#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */
-#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */
-#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */
-#define E1000_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */
-#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */
+#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
+#define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
+#define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
+#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */
+#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
+#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */
+#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */
+#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */
+#define E1000_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */
+#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */
+#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */
+#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */
+#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */
+#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */
+#define E1000_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */
+#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */
/* Wake Up Status */
-#define E1000_WUS_LNKC 0x00000001 /* Link Status Changed */
-#define E1000_WUS_MAG 0x00000002 /* Magic Packet Received */
-#define E1000_WUS_EX 0x00000004 /* Directed Exact Received */
-#define E1000_WUS_MC 0x00000008 /* Directed Multicast Received */
-#define E1000_WUS_BC 0x00000010 /* Broadcast Received */
-#define E1000_WUS_ARP 0x00000020 /* ARP Request Packet Received */
-#define E1000_WUS_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Received */
-#define E1000_WUS_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Received */
-#define E1000_WUS_FLX0 0x00010000 /* Flexible Filter 0 Match */
-#define E1000_WUS_FLX1 0x00020000 /* Flexible Filter 1 Match */
-#define E1000_WUS_FLX2 0x00040000 /* Flexible Filter 2 Match */
-#define E1000_WUS_FLX3 0x00080000 /* Flexible Filter 3 Match */
-#define E1000_WUS_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */
+#define E1000_WUS_LNKC 0x00000001 /* Link Status Changed */
+#define E1000_WUS_MAG 0x00000002 /* Magic Packet Received */
+#define E1000_WUS_EX 0x00000004 /* Directed Exact Received */
+#define E1000_WUS_MC 0x00000008 /* Directed Multicast Received */
+#define E1000_WUS_BC 0x00000010 /* Broadcast Received */
+#define E1000_WUS_ARP 0x00000020 /* ARP Request Packet Received */
+#define E1000_WUS_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Received */
+#define E1000_WUS_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Received */
+#define E1000_WUS_FLX0 0x00010000 /* Flexible Filter 0 Match */
+#define E1000_WUS_FLX1 0x00020000 /* Flexible Filter 1 Match */
+#define E1000_WUS_FLX2 0x00040000 /* Flexible Filter 2 Match */
+#define E1000_WUS_FLX3 0x00080000 /* Flexible Filter 3 Match */
+#define E1000_WUS_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */
/* Management Control */
-#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */
-#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */
-#define E1000_MANC_R_ON_FORCE 0x00000004 /* Reset on Force TCO - RO */
-#define E1000_MANC_RMCP_EN 0x00000100 /* Enable RCMP 026Fh Filtering */
-#define E1000_MANC_0298_EN 0x00000200 /* Enable RCMP 0298h Filtering */
-#define E1000_MANC_IPV4_EN 0x00000400 /* Enable IPv4 */
-#define E1000_MANC_IPV6_EN 0x00000800 /* Enable IPv6 */
-#define E1000_MANC_SNAP_EN 0x00001000 /* Accept LLC/SNAP */
-#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */
-#define E1000_MANC_NEIGHBOR_EN 0x00004000 /* Enable Neighbor Discovery
- * Filtering */
-#define E1000_MANC_ARP_RES_EN 0x00008000 /* Enable ARP response Filtering */
-#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */
-#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
-#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
-#define E1000_MANC_RCV_ALL 0x00080000 /* Receive All Enabled */
-#define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */
-#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MAC address
- * filtering */
-#define E1000_MANC_EN_MNG2HOST 0x00200000 /* Enable MNG packets to host
- * memory */
-#define E1000_MANC_EN_IP_ADDR_FILTER 0x00400000 /* Enable IP address
- * filtering */
-#define E1000_MANC_EN_XSUM_FILTER 0x00800000 /* Enable checksum filtering */
-#define E1000_MANC_BR_EN 0x01000000 /* Enable broadcast filtering */
-#define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */
-#define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */
-#define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */
-#define E1000_MANC_SMB_DATA_IN 0x08000000 /* SMBus Data In */
-#define E1000_MANC_SMB_DATA_OUT 0x10000000 /* SMBus Data Out */
-#define E1000_MANC_SMB_CLK_OUT 0x20000000 /* SMBus Clock Out */
-
-#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */
-#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */
+#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */
+#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */
+#define E1000_MANC_R_ON_FORCE 0x00000004 /* Reset on Force TCO - RO */
+#define E1000_MANC_RMCP_EN 0x00000100 /* Enable RCMP 026Fh Filtering */
+#define E1000_MANC_0298_EN 0x00000200 /* Enable RCMP 0298h Filtering */
+#define E1000_MANC_IPV4_EN 0x00000400 /* Enable IPv4 */
+#define E1000_MANC_IPV6_EN 0x00000800 /* Enable IPv6 */
+#define E1000_MANC_SNAP_EN 0x00001000 /* Accept LLC/SNAP */
+#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */
+#define E1000_MANC_NEIGHBOR_EN 0x00004000 /* Enable Neighbor Discovery
+ * Filtering */
+#define E1000_MANC_ARP_RES_EN 0x00008000 /* Enable ARP response Filtering */
+#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */
+#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
+#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
+#define E1000_MANC_RCV_ALL 0x00080000 /* Receive All Enabled */
+#define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */
+#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MAC address
+ * filtering */
+#define E1000_MANC_EN_MNG2HOST 0x00200000 /* Enable MNG packets to host
+ * memory */
+#define E1000_MANC_EN_IP_ADDR_FILTER 0x00400000 /* Enable IP address
+ * filtering */
+#define E1000_MANC_EN_XSUM_FILTER 0x00800000 /* Enable checksum filtering */
+#define E1000_MANC_BR_EN 0x01000000 /* Enable broadcast filtering */
+#define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */
+#define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */
+#define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */
+#define E1000_MANC_SMB_DATA_IN 0x08000000 /* SMBus Data In */
+#define E1000_MANC_SMB_DATA_OUT 0x10000000 /* SMBus Data Out */
+#define E1000_MANC_SMB_CLK_OUT 0x20000000 /* SMBus Clock Out */
+
+#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */
+#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */
/* SW Semaphore Register */
-#define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
-#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
-#define E1000_SWSM_WMNG 0x00000004 /* Wake MNG Clock */
-#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */
+#define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
+#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
+#define E1000_SWSM_WMNG 0x00000004 /* Wake MNG Clock */
+#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */
/* FW Semaphore Register */
-#define E1000_FWSM_MODE_MASK 0x0000000E /* FW mode */
+#define E1000_FWSM_MODE_MASK 0x0000000E /* FW mode */
#define E1000_FWSM_MODE_SHIFT 1
-#define E1000_FWSM_FW_VALID 0x00008000 /* FW established a valid mode */
+#define E1000_FWSM_FW_VALID 0x00008000 /* FW established a valid mode */
-#define E1000_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI reset */
-#define E1000_FWSM_DISSW 0x10000000 /* FW disable SW Write Access */
-#define E1000_FWSM_SKUSEL_MASK 0x60000000 /* LAN SKU select */
+#define E1000_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI reset */
+#define E1000_FWSM_DISSW 0x10000000 /* FW disable SW Write Access */
+#define E1000_FWSM_SKUSEL_MASK 0x60000000 /* LAN SKU select */
#define E1000_FWSM_SKUEL_SHIFT 29
-#define E1000_FWSM_SKUSEL_EMB 0x0 /* Embedded SKU */
-#define E1000_FWSM_SKUSEL_CONS 0x1 /* Consumer SKU */
-#define E1000_FWSM_SKUSEL_PERF_100 0x2 /* Perf & Corp 10/100 SKU */
-#define E1000_FWSM_SKUSEL_PERF_GBE 0x3 /* Perf & Copr GbE SKU */
+#define E1000_FWSM_SKUSEL_EMB 0x0 /* Embedded SKU */
+#define E1000_FWSM_SKUSEL_CONS 0x1 /* Consumer SKU */
+#define E1000_FWSM_SKUSEL_PERF_100 0x2 /* Perf & Corp 10/100 SKU */
+#define E1000_FWSM_SKUSEL_PERF_GBE 0x3 /* Perf & Copr GbE SKU */
/* FFLT Debug Register */
-#define E1000_FFLT_DBG_INVC 0x00100000 /* Invalid /C/ code handling */
+#define E1000_FFLT_DBG_INVC 0x00100000 /* Invalid /C/ code handling */
typedef enum {
- e1000_mng_mode_none = 0,
- e1000_mng_mode_asf,
- e1000_mng_mode_pt,
- e1000_mng_mode_ipmi,
- e1000_mng_mode_host_interface_only
+ e1000_mng_mode_none = 0,
+ e1000_mng_mode_asf,
+ e1000_mng_mode_pt,
+ e1000_mng_mode_ipmi,
+ e1000_mng_mode_host_interface_only
} e1000_mng_mode;
-/* Host Inteface Control Register */
-#define E1000_HICR_EN 0x00000001 /* Enable Bit - RO */
-#define E1000_HICR_C 0x00000002 /* Driver sets this bit when done
- * to put command in RAM */
-#define E1000_HICR_SV 0x00000004 /* Status Validity */
-#define E1000_HICR_FWR 0x00000080 /* FW reset. Set by the Host */
+/* Host Interface Control Register */
+#define E1000_HICR_EN 0x00000001 /* Enable Bit - RO */
+#define E1000_HICR_C 0x00000002 /* Driver sets this bit when done
+ * to put command in RAM */
+#define E1000_HICR_SV 0x00000004 /* Status Validity */
+#define E1000_HICR_FWR 0x00000080 /* FW reset. Set by the Host */
/* Host Interface Command Interface - Address range 0x8800-0x8EFF */
-#define E1000_HI_MAX_DATA_LENGTH 252 /* Host Interface data length */
-#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Number of bytes in range */
-#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Number of dwords in range */
-#define E1000_HI_COMMAND_TIMEOUT 500 /* Time in ms to process HI command */
+#define E1000_HI_MAX_DATA_LENGTH 252 /* Host Interface data length */
+#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Number of bytes in range */
+#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Number of dwords in range */
+#define E1000_HI_COMMAND_TIMEOUT 500 /* Time in ms to process HI command */
struct e1000_host_command_header {
- u8 command_id;
- u8 command_length;
- u8 command_options; /* I/F bits for command, status for return */
- u8 checksum;
+ u8 command_id;
+ u8 command_length;
+ u8 command_options; /* I/F bits for command, status for return */
+ u8 checksum;
};
struct e1000_host_command_info {
- struct e1000_host_command_header command_header; /* Command Head/Command Result Head has 4 bytes */
- u8 command_data[E1000_HI_MAX_DATA_LENGTH]; /* Command data can length 0..252 */
+ struct e1000_host_command_header command_header; /* Command Head/Command Result Head has 4 bytes */
+ u8 command_data[E1000_HI_MAX_DATA_LENGTH]; /* Command data can length 0..252 */
};
/* Host SMB register #0 */
-#define E1000_HSMC0R_CLKIN 0x00000001 /* SMB Clock in */
-#define E1000_HSMC0R_DATAIN 0x00000002 /* SMB Data in */
-#define E1000_HSMC0R_DATAOUT 0x00000004 /* SMB Data out */
-#define E1000_HSMC0R_CLKOUT 0x00000008 /* SMB Clock out */
+#define E1000_HSMC0R_CLKIN 0x00000001 /* SMB Clock in */
+#define E1000_HSMC0R_DATAIN 0x00000002 /* SMB Data in */
+#define E1000_HSMC0R_DATAOUT 0x00000004 /* SMB Data out */
+#define E1000_HSMC0R_CLKOUT 0x00000008 /* SMB Clock out */
/* Host SMB register #1 */
#define E1000_HSMC1R_CLKIN E1000_HSMC0R_CLKIN
#define E1000_HSMC1R_CLKOUT E1000_HSMC0R_CLKOUT
/* FW Status Register */
-#define E1000_FWSTS_FWS_MASK 0x000000FF /* FW Status */
+#define E1000_FWSTS_FWS_MASK 0x000000FF /* FW Status */
/* Wake Up Packet Length */
-#define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */
+#define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */
#define E1000_MDALIGN 4096
#define PCI_EX_LINK_WIDTH_SHIFT 4
/* EEPROM Commands - Microwire */
-#define EEPROM_READ_OPCODE_MICROWIRE 0x6 /* EEPROM read opcode */
-#define EEPROM_WRITE_OPCODE_MICROWIRE 0x5 /* EEPROM write opcode */
-#define EEPROM_ERASE_OPCODE_MICROWIRE 0x7 /* EEPROM erase opcode */
-#define EEPROM_EWEN_OPCODE_MICROWIRE 0x13 /* EEPROM erase/write enable */
-#define EEPROM_EWDS_OPCODE_MICROWIRE 0x10 /* EEPROM erast/write disable */
+#define EEPROM_READ_OPCODE_MICROWIRE 0x6 /* EEPROM read opcode */
+#define EEPROM_WRITE_OPCODE_MICROWIRE 0x5 /* EEPROM write opcode */
+#define EEPROM_ERASE_OPCODE_MICROWIRE 0x7 /* EEPROM erase opcode */
+#define EEPROM_EWEN_OPCODE_MICROWIRE 0x13 /* EEPROM erase/write enable */
+#define EEPROM_EWDS_OPCODE_MICROWIRE 0x10 /* EEPROM erase/write disable */
/* EEPROM Commands - SPI */
-#define EEPROM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */
-#define EEPROM_READ_OPCODE_SPI 0x03 /* EEPROM read opcode */
-#define EEPROM_WRITE_OPCODE_SPI 0x02 /* EEPROM write opcode */
-#define EEPROM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */
-#define EEPROM_WREN_OPCODE_SPI 0x06 /* EEPROM set Write Enable latch */
-#define EEPROM_WRDI_OPCODE_SPI 0x04 /* EEPROM reset Write Enable latch */
-#define EEPROM_RDSR_OPCODE_SPI 0x05 /* EEPROM read Status register */
-#define EEPROM_WRSR_OPCODE_SPI 0x01 /* EEPROM write Status register */
-#define EEPROM_ERASE4K_OPCODE_SPI 0x20 /* EEPROM ERASE 4KB */
-#define EEPROM_ERASE64K_OPCODE_SPI 0xD8 /* EEPROM ERASE 64KB */
-#define EEPROM_ERASE256_OPCODE_SPI 0xDB /* EEPROM ERASE 256B */
+#define EEPROM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */
+#define EEPROM_READ_OPCODE_SPI 0x03 /* EEPROM read opcode */
+#define EEPROM_WRITE_OPCODE_SPI 0x02 /* EEPROM write opcode */
+#define EEPROM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */
+#define EEPROM_WREN_OPCODE_SPI 0x06 /* EEPROM set Write Enable latch */
+#define EEPROM_WRDI_OPCODE_SPI 0x04 /* EEPROM reset Write Enable latch */
+#define EEPROM_RDSR_OPCODE_SPI 0x05 /* EEPROM read Status register */
+#define EEPROM_WRSR_OPCODE_SPI 0x01 /* EEPROM write Status register */
+#define EEPROM_ERASE4K_OPCODE_SPI 0x20 /* EEPROM ERASE 4KB */
+#define EEPROM_ERASE64K_OPCODE_SPI 0xD8 /* EEPROM ERASE 64KB */
+#define EEPROM_ERASE256_OPCODE_SPI 0xDB /* EEPROM ERASE 256B */
/* EEPROM Size definitions */
#define EEPROM_WORD_SIZE_SHIFT 6
#define EEPROM_COMPAT 0x0003
#define EEPROM_ID_LED_SETTINGS 0x0004
#define EEPROM_VERSION 0x0005
-#define EEPROM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */
+#define EEPROM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */
#define EEPROM_PHY_CLASS_WORD 0x0007
#define EEPROM_INIT_CONTROL1_REG 0x000A
#define EEPROM_INIT_CONTROL2_REG 0x000F
#define EEPROM_FLASH_VERSION 0x0032
#define EEPROM_CHECKSUM_REG 0x003F
-#define E1000_EEPROM_CFG_DONE 0x00040000 /* MNG config cycle done */
-#define E1000_EEPROM_CFG_DONE_PORT_1 0x00080000 /* ...for second port */
+#define E1000_EEPROM_CFG_DONE 0x00040000 /* MNG config cycle done */
+#define E1000_EEPROM_CFG_DONE_PORT_1 0x00080000 /* ...for second port */
/* Word definitions for ID LED Settings */
#define ID_LED_RESERVED_0000 0x0000
#define ID_LED_RESERVED_FFFF 0xFFFF
-#define ID_LED_RESERVED_82573 0xF746
-#define ID_LED_DEFAULT_82573 0x1811
#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \
(ID_LED_OFF1_OFF2 << 8) | \
(ID_LED_DEF1_DEF2 << 4) | \
(ID_LED_DEF1_DEF2))
-#define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \
- (ID_LED_DEF1_OFF2 << 8) | \
- (ID_LED_DEF1_ON2 << 4) | \
- (ID_LED_DEF1_DEF2))
#define ID_LED_DEF1_DEF2 0x1
#define ID_LED_DEF1_ON2 0x2
#define ID_LED_DEF1_OFF2 0x3
#define IGP_ACTIVITY_LED_ENABLE 0x0300
#define IGP_LED3_MODE 0x07000000
-
/* Mask bits for SERDES amplitude adjustment in Word 6 of the EEPROM */
#define EEPROM_SERDES_AMPLITUDE_MASK 0x000F
#define DEFAULT_82542_TIPG_IPGR2 10
#define DEFAULT_82543_TIPG_IPGR2 6
-#define DEFAULT_80003ES2LAN_TIPG_IPGR2 7
#define E1000_TIPG_IPGR2_SHIFT 20
-#define DEFAULT_80003ES2LAN_TIPG_IPGT_10_100 0x00000009
-#define DEFAULT_80003ES2LAN_TIPG_IPGT_1000 0x00000008
#define E1000_TXDMAC_DPP 0x00000001
/* Adaptive IFS defines */
#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020
/* PBA constants */
-#define E1000_PBA_8K 0x0008 /* 8KB, default Rx allocation */
-#define E1000_PBA_12K 0x000C /* 12KB, default Rx allocation */
-#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */
+#define E1000_PBA_8K 0x0008 /* 8KB, default Rx allocation */
+#define E1000_PBA_12K 0x000C /* 12KB, default Rx allocation */
+#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */
#define E1000_PBA_20K 0x0014
#define E1000_PBA_22K 0x0016
#define E1000_PBA_24K 0x0018
#define E1000_PBA_34K 0x0022
#define E1000_PBA_38K 0x0026
#define E1000_PBA_40K 0x0028
-#define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */
+#define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */
#define E1000_PBS_16K E1000_PBA_16K
#define FLOW_CONTROL_TYPE 0x8808
/* The historical defaults for the flow control values are given below. */
-#define FC_DEFAULT_HI_THRESH (0x8000) /* 32KB */
-#define FC_DEFAULT_LO_THRESH (0x4000) /* 16KB */
-#define FC_DEFAULT_TX_TIMER (0x100) /* ~130 us */
+#define FC_DEFAULT_HI_THRESH (0x8000) /* 32KB */
+#define FC_DEFAULT_LO_THRESH (0x4000) /* 16KB */
+#define FC_DEFAULT_TX_TIMER (0x100) /* ~130 us */
/* PCIX Config space */
#define PCIX_COMMAND_REGISTER 0xE6
#define PCIX_STATUS_HI_MMRBC_4K 0x3
#define PCIX_STATUS_HI_MMRBC_2K 0x2
-
/* Number of bits required to shift right the "pause" bits from the
* EEPROM (bits 13:12) to the "pause" (bits 8:7) field in the TXCW register.
*/
*/
#define ILOS_SHIFT 3
-
#define RECEIVE_BUFFER_ALIGN_SIZE (256)
/* Number of milliseconds we wait for auto-negotiation to complete */
#define LINK_UP_TIMEOUT 500
-/* Number of 100 microseconds we wait for PCI Express master disable */
-#define MASTER_DISABLE_TIMEOUT 800
/* Number of milliseconds we wait for Eeprom auto read bit done after MAC reset */
#define AUTO_READ_DONE_TIMEOUT 10
/* Number of milliseconds we wait for PHY configuration done after MAC reset */
(((length) > (adapter)->min_frame_size) && \
((length) <= ((adapter)->max_frame_size + VLAN_TAG_SIZE + 1)))))
-
/* Structures, enums, and macros for the PHY */
/* Bit definitions for the Management Data IO (MDIO) and Management Data
/* PHY 1000 MII Register/Bit Definitions */
/* PHY Registers defined by IEEE */
-#define PHY_CTRL 0x00 /* Control Register */
-#define PHY_STATUS 0x01 /* Status Regiser */
-#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */
-#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */
-#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */
-#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */
-#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */
-#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */
-#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */
-#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */
-#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
-#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */
-
-#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
-#define MAX_PHY_MULTI_PAGE_REG 0xF /* Registers equal on all pages */
+#define PHY_CTRL 0x00 /* Control Register */
+#define PHY_STATUS 0x01 /* Status Register */
+#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */
+#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */
+#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */
+#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */
+#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */
+#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */
+#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */
+#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */
+#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
+#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */
+
+#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
+#define MAX_PHY_MULTI_PAGE_REG 0xF /* Registers equal on all pages */
/* M88E1000 Specific Registers */
-#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
-#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */
-#define M88E1000_INT_ENABLE 0x12 /* Interrupt Enable Register */
-#define M88E1000_INT_STATUS 0x13 /* Interrupt Status Register */
-#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */
-#define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */
-
-#define M88E1000_PHY_EXT_CTRL 0x1A /* PHY extend control register */
-#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */
-#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */
-#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */
-#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */
+#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
+#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */
+#define M88E1000_INT_ENABLE 0x12 /* Interrupt Enable Register */
+#define M88E1000_INT_STATUS 0x13 /* Interrupt Status Register */
+#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */
+#define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */
+
+#define M88E1000_PHY_EXT_CTRL 0x1A /* PHY extend control register */
+#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */
+#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */
+#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */
+#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */
#define IGP01E1000_IEEE_REGS_PAGE 0x0000
#define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300
#define IGP01E1000_IEEE_FORCE_GIGA 0x0140
/* IGP01E1000 Specific Registers */
-#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */
-#define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */
-#define IGP01E1000_PHY_PORT_CTRL 0x12 /* PHY Specific Control Register */
-#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health Register */
-#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO Register */
-#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality Register */
+#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */
+#define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */
+#define IGP01E1000_PHY_PORT_CTRL 0x12 /* PHY Specific Control Register */
+#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health Register */
+#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO Register */
+#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality Register */
#define IGP02E1000_PHY_POWER_MGMT 0x19
-#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* PHY Page Select Core Register */
+#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* PHY Page Select Core Register */
/* IGP01E1000 AGC Registers - stores the cable length values*/
#define IGP01E1000_PHY_AGC_A 0x1172
#define IGP01E1000_ANALOG_REGS_PAGE 0x20C0
-/* Bits...
- * 15-5: page
- * 4-0: register offset
- */
-#define GG82563_PAGE_SHIFT 5
-#define GG82563_REG(page, reg) \
- (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS))
-#define GG82563_MIN_ALT_REG 30
-
-/* GG82563 Specific Registers */
-#define GG82563_PHY_SPEC_CTRL \
- GG82563_REG(0, 16) /* PHY Specific Control */
-#define GG82563_PHY_SPEC_STATUS \
- GG82563_REG(0, 17) /* PHY Specific Status */
-#define GG82563_PHY_INT_ENABLE \
- GG82563_REG(0, 18) /* Interrupt Enable */
-#define GG82563_PHY_SPEC_STATUS_2 \
- GG82563_REG(0, 19) /* PHY Specific Status 2 */
-#define GG82563_PHY_RX_ERR_CNTR \
- GG82563_REG(0, 21) /* Receive Error Counter */
-#define GG82563_PHY_PAGE_SELECT \
- GG82563_REG(0, 22) /* Page Select */
-#define GG82563_PHY_SPEC_CTRL_2 \
- GG82563_REG(0, 26) /* PHY Specific Control 2 */
-#define GG82563_PHY_PAGE_SELECT_ALT \
- GG82563_REG(0, 29) /* Alternate Page Select */
-#define GG82563_PHY_TEST_CLK_CTRL \
- GG82563_REG(0, 30) /* Test Clock Control (use reg. 29 to select) */
-
-#define GG82563_PHY_MAC_SPEC_CTRL \
- GG82563_REG(2, 21) /* MAC Specific Control Register */
-#define GG82563_PHY_MAC_SPEC_CTRL_2 \
- GG82563_REG(2, 26) /* MAC Specific Control 2 */
-
-#define GG82563_PHY_DSP_DISTANCE \
- GG82563_REG(5, 26) /* DSP Distance */
-
-/* Page 193 - Port Control Registers */
-#define GG82563_PHY_KMRN_MODE_CTRL \
- GG82563_REG(193, 16) /* Kumeran Mode Control */
-#define GG82563_PHY_PORT_RESET \
- GG82563_REG(193, 17) /* Port Reset */
-#define GG82563_PHY_REVISION_ID \
- GG82563_REG(193, 18) /* Revision ID */
-#define GG82563_PHY_DEVICE_ID \
- GG82563_REG(193, 19) /* Device ID */
-#define GG82563_PHY_PWR_MGMT_CTRL \
- GG82563_REG(193, 20) /* Power Management Control */
-#define GG82563_PHY_RATE_ADAPT_CTRL \
- GG82563_REG(193, 25) /* Rate Adaptation Control */
-
-/* Page 194 - KMRN Registers */
-#define GG82563_PHY_KMRN_FIFO_CTRL_STAT \
- GG82563_REG(194, 16) /* FIFO's Control/Status */
-#define GG82563_PHY_KMRN_CTRL \
- GG82563_REG(194, 17) /* Control */
-#define GG82563_PHY_INBAND_CTRL \
- GG82563_REG(194, 18) /* Inband Control */
-#define GG82563_PHY_KMRN_DIAGNOSTIC \
- GG82563_REG(194, 19) /* Diagnostic */
-#define GG82563_PHY_ACK_TIMEOUTS \
- GG82563_REG(194, 20) /* Acknowledge Timeouts */
-#define GG82563_PHY_ADV_ABILITY \
- GG82563_REG(194, 21) /* Advertised Ability */
-#define GG82563_PHY_LINK_PARTNER_ADV_ABILITY \
- GG82563_REG(194, 23) /* Link Partner Advertised Ability */
-#define GG82563_PHY_ADV_NEXT_PAGE \
- GG82563_REG(194, 24) /* Advertised Next Page */
-#define GG82563_PHY_LINK_PARTNER_ADV_NEXT_PAGE \
- GG82563_REG(194, 25) /* Link Partner Advertised Next page */
-#define GG82563_PHY_KMRN_MISC \
- GG82563_REG(194, 26) /* Misc. */
-
/* PHY Control Register */
-#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
-#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
-#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
-#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
-#define MII_CR_POWER_DOWN 0x0800 /* Power down */
-#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
-#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
-#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
+#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
+#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
+#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN 0x0800 /* Power down */
+#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
/* PHY Status Register */
-#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
-#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
-#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
-#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
-#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
-#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
-#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
-#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */
-#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
-#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
-#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
-#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
-#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
-#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
-#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
+#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
+#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
+#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
+#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */
+#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */
+#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
+#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */
+#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */
+#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */
+#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */
+#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */
+#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */
+#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */
+#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */
+#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */
/* Autoneg Advertisement Register */
-#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */
-#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
-#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
-#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
-#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
-#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */
-#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */
-#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
-#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
-#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */
+#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */
+#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
+#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
+#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
+#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
+#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */
+#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */
+#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
+#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */
+#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */
/* Link Partner Ability Register (Base Page) */
-#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */
-#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP is 10T Half Duplex Capable */
-#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP is 10T Full Duplex Capable */
-#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP is 100TX Half Duplex Capable */
-#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP is 100TX Full Duplex Capable */
-#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */
-#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */
-#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */
-#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP has detected Remote Fault */
-#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP has rx'd link code word */
-#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */
+#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */
+#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP is 10T Half Duplex Capable */
+#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP is 10T Full Duplex Capable */
+#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP is 100TX Half Duplex Capable */
+#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP is 100TX Full Duplex Capable */
+#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */
+#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */
+#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */
+#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP has detected Remote Fault */
+#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP has rx'd link code word */
+#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */
/* Autoneg Expansion Register */
-#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */
-#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */
-#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */
-#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */
-#define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP is 100TX Full Duplex Capable */
+#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */
+#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */
+#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */
+#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */
+#define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP is 100TX Full Duplex Capable */
/* Next Page TX Register */
-#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
-#define NPTX_TOGGLE 0x0800 /* Toggles between exchanges
- * of different NP
- */
-#define NPTX_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg
- * 0 = cannot comply with msg
- */
-#define NPTX_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */
-#define NPTX_NEXT_PAGE 0x8000 /* 1 = addition NP will follow
- * 0 = sending last NP
- */
+#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
+#define NPTX_TOGGLE 0x0800 /* Toggles between exchanges
+ * of different NP
+ */
+#define NPTX_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg
+ * 0 = cannot comply with msg
+ */
+#define NPTX_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */
+#define NPTX_NEXT_PAGE 0x8000 /* 1 = addition NP will follow
+ * 0 = sending last NP
+ */
/* Link Partner Next Page Register */
-#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
-#define LP_RNPR_TOGGLE 0x0800 /* Toggles between exchanges
- * of different NP
- */
-#define LP_RNPR_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg
- * 0 = cannot comply with msg
- */
-#define LP_RNPR_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */
-#define LP_RNPR_ACKNOWLDGE 0x4000 /* 1 = ACK / 0 = NO ACK */
-#define LP_RNPR_NEXT_PAGE 0x8000 /* 1 = addition NP will follow
- * 0 = sending last NP
- */
+#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */
+#define LP_RNPR_TOGGLE 0x0800 /* Toggles between exchanges
+ * of different NP
+ */
+#define LP_RNPR_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg
+ * 0 = cannot comply with msg
+ */
+#define LP_RNPR_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */
+#define LP_RNPR_ACKNOWLDGE 0x4000 /* 1 = ACK / 0 = NO ACK */
+#define LP_RNPR_NEXT_PAGE 0x8000 /* 1 = addition NP will follow
+ * 0 = sending last NP
+ */
/* 1000BASE-T Control Register */
-#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */
-#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
-#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
-#define CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */
- /* 0=DTE device */
-#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */
- /* 0=Configure PHY as Slave */
-#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */
- /* 0=Automatic Master/Slave config */
-#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
-#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
-#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */
-#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */
-#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */
+#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */
+#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
+#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
+#define CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */
+ /* 0=DTE device */
+#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */
+ /* 0=Configure PHY as Slave */
+#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */
+ /* 0=Automatic Master/Slave config */
+#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */
+#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */
+#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */
+#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */
+#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */
/* 1000BASE-T Status Register */
-#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */
-#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */
-#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
-#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
-#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
-#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
-#define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */
-#define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */
+#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */
+#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */
+#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */
+#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */
+#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
+#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */
+#define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */
+#define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */
#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12
#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13
#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5
#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100
/* Extended Status Register */
-#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
-#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
-#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
-#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
+#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */
+#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */
+#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */
+#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */
-#define PHY_TX_POLARITY_MASK 0x0100 /* register 10h bit 8 (polarity bit) */
-#define PHY_TX_NORMAL_POLARITY 0 /* register 10h bit 8 (normal polarity) */
+#define PHY_TX_POLARITY_MASK 0x0100 /* register 10h bit 8 (polarity bit) */
+#define PHY_TX_NORMAL_POLARITY 0 /* register 10h bit 8 (normal polarity) */
-#define AUTO_POLARITY_DISABLE 0x0010 /* register 11h bit 4 */
- /* (0=enable, 1=disable) */
+#define AUTO_POLARITY_DISABLE 0x0010 /* register 11h bit 4 */
+ /* (0=enable, 1=disable) */
/* M88E1000 PHY Specific Control Register */
-#define M88E1000_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */
-#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */
-#define M88E1000_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */
-#define M88E1000_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low,
- * 0=CLK125 toggling
- */
-#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */
- /* Manual MDI configuration */
-#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
-#define M88E1000_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover,
- * 100BASE-TX/10BASE-T:
- * MDI Mode
- */
-#define M88E1000_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled
- * all speeds.
- */
+#define M88E1000_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */
+#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */
+#define M88E1000_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */
+#define M88E1000_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low,
+ * 0=CLK125 toggling
+ */
+#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */
+ /* Manual MDI configuration */
+#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */
+#define M88E1000_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover,
+ * 100BASE-TX/10BASE-T:
+ * MDI Mode
+ */
+#define M88E1000_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled
+ * all speeds.
+ */
#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE 0x0080
- /* 1=Enable Extended 10BASE-T distance
- * (Lower 10BASE-T RX Threshold)
- * 0=Normal 10BASE-T RX Threshold */
+ /* 1=Enable Extended 10BASE-T distance
+ * (Lower 10BASE-T RX Threshold)
+ * 0=Normal 10BASE-T RX Threshold */
#define M88E1000_PSCR_MII_5BIT_ENABLE 0x0100
- /* 1=5-Bit interface in 100BASE-TX
- * 0=MII interface in 100BASE-TX */
-#define M88E1000_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */
-#define M88E1000_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */
-#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
+ /* 1=5-Bit interface in 100BASE-TX
+ * 0=MII interface in 100BASE-TX */
+#define M88E1000_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */
+#define M88E1000_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */
+#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
#define M88E1000_PSCR_POLARITY_REVERSAL_SHIFT 1
#define M88E1000_PSCR_AUTO_X_MODE_SHIFT 5
#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7
/* M88E1000 PHY Specific Status Register */
-#define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */
-#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */
-#define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */
-#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */
-#define M88E1000_PSSR_CABLE_LENGTH 0x0380 /* 0=<50M;1=50-80M;2=80-110M;
- * 3=110-140M;4=>140M */
-#define M88E1000_PSSR_LINK 0x0400 /* 1=Link up, 0=Link down */
-#define M88E1000_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */
-#define M88E1000_PSSR_PAGE_RCVD 0x1000 /* 1=Page received */
-#define M88E1000_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */
-#define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
-#define M88E1000_PSSR_10MBS 0x0000 /* 00=10Mbs */
-#define M88E1000_PSSR_100MBS 0x4000 /* 01=100Mbs */
-#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
+#define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */
+#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */
+#define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */
+#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */
+#define M88E1000_PSSR_CABLE_LENGTH 0x0380 /* 0=<50M;1=50-80M;2=80-110M;
+ * 3=110-140M;4=>140M */
+#define M88E1000_PSSR_LINK 0x0400 /* 1=Link up, 0=Link down */
+#define M88E1000_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */
+#define M88E1000_PSSR_PAGE_RCVD 0x1000 /* 1=Page received */
+#define M88E1000_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */
+#define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */
+#define M88E1000_PSSR_10MBS 0x0000 /* 00=10Mbs */
+#define M88E1000_PSSR_100MBS 0x4000 /* 01=100Mbs */
+#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */
#define M88E1000_PSSR_REV_POLARITY_SHIFT 1
#define M88E1000_PSSR_DOWNSHIFT_SHIFT 5
#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
/* M88E1000 Extended PHY Specific Control Register */
-#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */
-#define M88E1000_EPSCR_DOWN_NO_IDLE 0x8000 /* 1=Lost lock detect enabled.
- * Will assert lost lock and bring
- * link down if idle not seen
- * within 1ms in 1000BASE-T
- */
+#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */
+#define M88E1000_EPSCR_DOWN_NO_IDLE 0x8000 /* 1=Lost lock detect enabled.
+ * Will assert lost lock and bring
+ * link down if idle not seen
+ * within 1ms in 1000BASE-T
+ */
/* Number of times we will attempt to autonegotiate before downshifting if we
* are the master */
#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00
#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100
#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X 0x0200
#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X 0x0300
-#define M88E1000_EPSCR_TX_CLK_2_5 0x0060 /* 2.5 MHz TX_CLK */
-#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */
-#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_2_5 0x0060 /* 2.5 MHz TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */
/* M88EC018 Rev 2 specific DownShift settings */
#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00
#define IGP01E1000_PSCFR_DISABLE_TRANSMIT 0x2000
/* IGP01E1000 Specific Port Status Register - R/O */
-#define IGP01E1000_PSSR_AUTONEG_FAILED 0x0001 /* RO LH SC */
+#define IGP01E1000_PSSR_AUTONEG_FAILED 0x0001 /* RO LH SC */
#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002
#define IGP01E1000_PSSR_CABLE_LENGTH 0x007C
#define IGP01E1000_PSSR_FULL_DUPLEX 0x0200
#define IGP01E1000_PSSR_LINK_UP 0x0400
#define IGP01E1000_PSSR_MDIX 0x0800
-#define IGP01E1000_PSSR_SPEED_MASK 0xC000 /* speed bits mask */
+#define IGP01E1000_PSSR_SPEED_MASK 0xC000 /* speed bits mask */
#define IGP01E1000_PSSR_SPEED_10MBPS 0x4000
#define IGP01E1000_PSSR_SPEED_100MBPS 0x8000
#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000
-#define IGP01E1000_PSSR_CABLE_LENGTH_SHIFT 0x0002 /* shift right 2 */
-#define IGP01E1000_PSSR_MDIX_SHIFT 0x000B /* shift right 11 */
+#define IGP01E1000_PSSR_CABLE_LENGTH_SHIFT 0x0002 /* shift right 2 */
+#define IGP01E1000_PSSR_MDIX_SHIFT 0x000B /* shift right 11 */
/* IGP01E1000 Specific Port Control Register - R/W */
#define IGP01E1000_PSCR_TP_LOOPBACK 0x0010
#define IGP01E1000_PSCR_TEN_CRS_SELECT 0x0400
#define IGP01E1000_PSCR_FLIP_CHIP 0x0800
#define IGP01E1000_PSCR_AUTO_MDIX 0x1000
-#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0-MDI, 1-MDIX */
+#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0-MDI, 1-MDIX */
/* IGP01E1000 Specific Port Link Health Register */
#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000
#define IGP01E1000_PLHR_GIG_SCRAMBLER_ERROR 0x4000
#define IGP01E1000_PLHR_MASTER_FAULT 0x2000
#define IGP01E1000_PLHR_MASTER_RESOLUTION 0x1000
-#define IGP01E1000_PLHR_GIG_REM_RCVR_NOK 0x0800 /* LH */
-#define IGP01E1000_PLHR_IDLE_ERROR_CNT_OFLOW 0x0400 /* LH */
-#define IGP01E1000_PLHR_DATA_ERR_1 0x0200 /* LH */
+#define IGP01E1000_PLHR_GIG_REM_RCVR_NOK 0x0800 /* LH */
+#define IGP01E1000_PLHR_IDLE_ERROR_CNT_OFLOW 0x0400 /* LH */
+#define IGP01E1000_PLHR_DATA_ERR_1 0x0200 /* LH */
#define IGP01E1000_PLHR_DATA_ERR_0 0x0100
#define IGP01E1000_PLHR_AUTONEG_FAULT 0x0040
#define IGP01E1000_PLHR_AUTONEG_ACTIVE 0x0010
#define IGP01E1000_MSE_CHANNEL_B 0x0F00
#define IGP01E1000_MSE_CHANNEL_A 0xF000
-#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */
-#define IGP02E1000_PM_D3_LPLU 0x0004 /* Enable LPLU in non-D0a modes */
-#define IGP02E1000_PM_D0_LPLU 0x0002 /* Enable LPLU in D0a mode */
+#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */
+#define IGP02E1000_PM_D3_LPLU 0x0004 /* Enable LPLU in non-D0a modes */
+#define IGP02E1000_PM_D0_LPLU 0x0002 /* Enable LPLU in D0a mode */
/* IGP01E1000 DSP reset macros */
#define DSP_RESET_ENABLE 0x0
/* IGP01E1000 & IGP02E1000 AGC Registers */
-#define IGP01E1000_AGC_LENGTH_SHIFT 7 /* Coarse - 13:11, Fine - 10:7 */
-#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Coarse - 15:13, Fine - 12:9 */
+#define IGP01E1000_AGC_LENGTH_SHIFT 7 /* Coarse - 13:11, Fine - 10:7 */
+#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Coarse - 15:13, Fine - 12:9 */
/* IGP02E1000 AGC Register Length 9-bit mask */
#define IGP02E1000_AGC_LENGTH_MASK 0x7F
#define IGP01E1000_PHY_POLARITY_MASK 0x0078
/* IGP01E1000 GMII FIFO Register */
-#define IGP01E1000_GMII_FLEX_SPD 0x10 /* Enable flexible speed
- * on Link-Up */
-#define IGP01E1000_GMII_SPD 0x20 /* Enable SPD */
+#define IGP01E1000_GMII_FLEX_SPD 0x10 /* Enable flexible speed
+ * on Link-Up */
+#define IGP01E1000_GMII_SPD 0x20 /* Enable SPD */
/* IGP01E1000 Analog Register */
#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x20D1
#define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080
#define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500
-/* GG82563 PHY Specific Status Register (Page 0, Register 16 */
-#define GG82563_PSCR_DISABLE_JABBER 0x0001 /* 1=Disable Jabber */
-#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Polarity Reversal Disabled */
-#define GG82563_PSCR_POWER_DOWN 0x0004 /* 1=Power Down */
-#define GG82563_PSCR_COPPER_TRANSMITER_DISABLE 0x0008 /* 1=Transmitter Disabled */
-#define GG82563_PSCR_CROSSOVER_MODE_MASK 0x0060
-#define GG82563_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI configuration */
-#define GG82563_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX configuration */
-#define GG82563_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Automatic crossover */
-#define GG82563_PSCR_ENALBE_EXTENDED_DISTANCE 0x0080 /* 1=Enable Extended Distance */
-#define GG82563_PSCR_ENERGY_DETECT_MASK 0x0300
-#define GG82563_PSCR_ENERGY_DETECT_OFF 0x0000 /* 00,01=Off */
-#define GG82563_PSCR_ENERGY_DETECT_RX 0x0200 /* 10=Sense on Rx only (Energy Detect) */
-#define GG82563_PSCR_ENERGY_DETECT_RX_TM 0x0300 /* 11=Sense and Tx NLP */
-#define GG82563_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force Link Good */
-#define GG82563_PSCR_DOWNSHIFT_ENABLE 0x0800 /* 1=Enable Downshift */
-#define GG82563_PSCR_DOWNSHIFT_COUNTER_MASK 0x7000
-#define GG82563_PSCR_DOWNSHIFT_COUNTER_SHIFT 12
-
-/* PHY Specific Status Register (Page 0, Register 17) */
-#define GG82563_PSSR_JABBER 0x0001 /* 1=Jabber */
-#define GG82563_PSSR_POLARITY 0x0002 /* 1=Polarity Reversed */
-#define GG82563_PSSR_LINK 0x0008 /* 1=Link is Up */
-#define GG82563_PSSR_ENERGY_DETECT 0x0010 /* 1=Sleep, 0=Active */
-#define GG82563_PSSR_DOWNSHIFT 0x0020 /* 1=Downshift */
-#define GG82563_PSSR_CROSSOVER_STATUS 0x0040 /* 1=MDIX, 0=MDI */
-#define GG82563_PSSR_RX_PAUSE_ENABLED 0x0100 /* 1=Receive Pause Enabled */
-#define GG82563_PSSR_TX_PAUSE_ENABLED 0x0200 /* 1=Transmit Pause Enabled */
-#define GG82563_PSSR_LINK_UP 0x0400 /* 1=Link Up */
-#define GG82563_PSSR_SPEED_DUPLEX_RESOLVED 0x0800 /* 1=Resolved */
-#define GG82563_PSSR_PAGE_RECEIVED 0x1000 /* 1=Page Received */
-#define GG82563_PSSR_DUPLEX 0x2000 /* 1-Full-Duplex */
-#define GG82563_PSSR_SPEED_MASK 0xC000
-#define GG82563_PSSR_SPEED_10MBPS 0x0000 /* 00=10Mbps */
-#define GG82563_PSSR_SPEED_100MBPS 0x4000 /* 01=100Mbps */
-#define GG82563_PSSR_SPEED_1000MBPS 0x8000 /* 10=1000Mbps */
-
-/* PHY Specific Status Register 2 (Page 0, Register 19) */
-#define GG82563_PSSR2_JABBER 0x0001 /* 1=Jabber */
-#define GG82563_PSSR2_POLARITY_CHANGED 0x0002 /* 1=Polarity Changed */
-#define GG82563_PSSR2_ENERGY_DETECT_CHANGED 0x0010 /* 1=Energy Detect Changed */
-#define GG82563_PSSR2_DOWNSHIFT_INTERRUPT 0x0020 /* 1=Downshift Detected */
-#define GG82563_PSSR2_MDI_CROSSOVER_CHANGE 0x0040 /* 1=Crossover Changed */
-#define GG82563_PSSR2_FALSE_CARRIER 0x0100 /* 1=False Carrier */
-#define GG82563_PSSR2_SYMBOL_ERROR 0x0200 /* 1=Symbol Error */
-#define GG82563_PSSR2_LINK_STATUS_CHANGED 0x0400 /* 1=Link Status Changed */
-#define GG82563_PSSR2_AUTO_NEG_COMPLETED 0x0800 /* 1=Auto-Neg Completed */
-#define GG82563_PSSR2_PAGE_RECEIVED 0x1000 /* 1=Page Received */
-#define GG82563_PSSR2_DUPLEX_CHANGED 0x2000 /* 1=Duplex Changed */
-#define GG82563_PSSR2_SPEED_CHANGED 0x4000 /* 1=Speed Changed */
-#define GG82563_PSSR2_AUTO_NEG_ERROR 0x8000 /* 1=Auto-Neg Error */
-
-/* PHY Specific Control Register 2 (Page 0, Register 26) */
-#define GG82563_PSCR2_10BT_POLARITY_FORCE 0x0002 /* 1=Force Negative Polarity */
-#define GG82563_PSCR2_1000MB_TEST_SELECT_MASK 0x000C
-#define GG82563_PSCR2_1000MB_TEST_SELECT_NORMAL 0x0000 /* 00,01=Normal Operation */
-#define GG82563_PSCR2_1000MB_TEST_SELECT_112NS 0x0008 /* 10=Select 112ns Sequence */
-#define GG82563_PSCR2_1000MB_TEST_SELECT_16NS 0x000C /* 11=Select 16ns Sequence */
-#define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000 /* 1=Reverse Auto-Negotiation */
-#define GG82563_PSCR2_1000BT_DISABLE 0x4000 /* 1=Disable 1000BASE-T */
-#define GG82563_PSCR2_TRANSMITER_TYPE_MASK 0x8000
-#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_B 0x0000 /* 0=Class B */
-#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_A 0x8000 /* 1=Class A */
-
-/* MAC Specific Control Register (Page 2, Register 21) */
-/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */
-#define GG82563_MSCR_TX_CLK_MASK 0x0007
-#define GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ 0x0004
-#define GG82563_MSCR_TX_CLK_100MBPS_25MHZ 0x0005
-#define GG82563_MSCR_TX_CLK_1000MBPS_2_5MHZ 0x0006
-#define GG82563_MSCR_TX_CLK_1000MBPS_25MHZ 0x0007
-
-#define GG82563_MSCR_ASSERT_CRS_ON_TX 0x0010 /* 1=Assert */
-
-/* DSP Distance Register (Page 5, Register 26) */
-#define GG82563_DSPD_CABLE_LENGTH 0x0007 /* 0 = <50M;
- 1 = 50-80M;
- 2 = 80-110M;
- 3 = 110-140M;
- 4 = >140M */
-
-/* Kumeran Mode Control Register (Page 193, Register 16) */
-#define GG82563_KMCR_PHY_LEDS_EN 0x0020 /* 1=PHY LEDs, 0=Kumeran Inband LEDs */
-#define GG82563_KMCR_FORCE_LINK_UP 0x0040 /* 1=Force Link Up */
-#define GG82563_KMCR_SUPPRESS_SGMII_EPD_EXT 0x0080
-#define GG82563_KMCR_MDIO_BUS_SPEED_SELECT_MASK 0x0400
-#define GG82563_KMCR_MDIO_BUS_SPEED_SELECT 0x0400 /* 1=6.25MHz, 0=0.8MHz */
-#define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800
-
-/* Power Management Control Register (Page 193, Register 20) */
-#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001 /* 1=Enalbe SERDES Electrical Idle */
-#define GG82563_PMCR_DISABLE_PORT 0x0002 /* 1=Disable Port */
-#define GG82563_PMCR_DISABLE_SERDES 0x0004 /* 1=Disable SERDES */
-#define GG82563_PMCR_REVERSE_AUTO_NEG 0x0008 /* 1=Enable Reverse Auto-Negotiation */
-#define GG82563_PMCR_DISABLE_1000_NON_D0 0x0010 /* 1=Disable 1000Mbps Auto-Neg in non D0 */
-#define GG82563_PMCR_DISABLE_1000 0x0020 /* 1=Disable 1000Mbps Auto-Neg Always */
-#define GG82563_PMCR_REVERSE_AUTO_NEG_D0A 0x0040 /* 1=Enable D0a Reverse Auto-Negotiation */
-#define GG82563_PMCR_FORCE_POWER_STATE 0x0080 /* 1=Force Power State */
-#define GG82563_PMCR_PROGRAMMED_POWER_STATE_MASK 0x0300
-#define GG82563_PMCR_PROGRAMMED_POWER_STATE_DR 0x0000 /* 00=Dr */
-#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D0U 0x0100 /* 01=D0u */
-#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D0A 0x0200 /* 10=D0a */
-#define GG82563_PMCR_PROGRAMMED_POWER_STATE_D3 0x0300 /* 11=D3 */
-
-/* In-Band Control Register (Page 194, Register 18) */
-#define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding Use */
-
-
/* Bit definitions for valid PHY IDs. */
/* I = Integrated
* E = External
#define M88E1011_I_REV_4 0x04
#define M88E1111_I_PHY_ID 0x01410CC0
#define L1LXT971A_PHY_ID 0x001378E0
-#define GG82563_E_PHY_ID 0x01410CA0
-
/* Bits...
* 15-5: page
(((page) << PHY_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS))
#define IGP3_PHY_PORT_CTRL \
- PHY_REG(769, 17) /* Port General Configuration */
+ PHY_REG(769, 17) /* Port General Configuration */
#define IGP3_PHY_RATE_ADAPT_CTRL \
- PHY_REG(769, 25) /* Rate Adapter Control Register */
+ PHY_REG(769, 25) /* Rate Adapter Control Register */
#define IGP3_KMRN_FIFO_CTRL_STATS \
- PHY_REG(770, 16) /* KMRN FIFO's control/status register */
+ PHY_REG(770, 16) /* KMRN FIFO's control/status register */
#define IGP3_KMRN_POWER_MNG_CTRL \
- PHY_REG(770, 17) /* KMRN Power Management Control Register */
+ PHY_REG(770, 17) /* KMRN Power Management Control Register */
#define IGP3_KMRN_INBAND_CTRL \
- PHY_REG(770, 18) /* KMRN Inband Control Register */
+ PHY_REG(770, 18) /* KMRN Inband Control Register */
#define IGP3_KMRN_DIAG \
- PHY_REG(770, 19) /* KMRN Diagnostic register */
-#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002 /* RX PCS is not synced */
+ PHY_REG(770, 19) /* KMRN Diagnostic register */
+#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002 /* RX PCS is not synced */
#define IGP3_KMRN_ACK_TIMEOUT \
- PHY_REG(770, 20) /* KMRN Acknowledge Timeouts register */
+ PHY_REG(770, 20) /* KMRN Acknowledge Timeouts register */
#define IGP3_VR_CTRL \
- PHY_REG(776, 18) /* Voltage regulator control register */
-#define IGP3_VR_CTRL_MODE_SHUT 0x0200 /* Enter powerdown, shutdown VRs */
-#define IGP3_VR_CTRL_MODE_MASK 0x0300 /* Shutdown VR Mask */
+ PHY_REG(776, 18) /* Voltage regulator control register */
+#define IGP3_VR_CTRL_MODE_SHUT 0x0200 /* Enter powerdown, shutdown VRs */
+#define IGP3_VR_CTRL_MODE_MASK 0x0300 /* Shutdown VR Mask */
#define IGP3_CAPABILITY \
- PHY_REG(776, 19) /* IGP3 Capability Register */
+ PHY_REG(776, 19) /* IGP3 Capability Register */
/* Capabilities for SKU Control */
-#define IGP3_CAP_INITIATE_TEAM 0x0001 /* Able to initiate a team */
-#define IGP3_CAP_WFM 0x0002 /* Support WoL and PXE */
-#define IGP3_CAP_ASF 0x0004 /* Support ASF */
-#define IGP3_CAP_LPLU 0x0008 /* Support Low Power Link Up */
-#define IGP3_CAP_DC_AUTO_SPEED 0x0010 /* Support AC/DC Auto Link Speed */
-#define IGP3_CAP_SPD 0x0020 /* Support Smart Power Down */
-#define IGP3_CAP_MULT_QUEUE 0x0040 /* Support 2 tx & 2 rx queues */
-#define IGP3_CAP_RSS 0x0080 /* Support RSS */
-#define IGP3_CAP_8021PQ 0x0100 /* Support 802.1Q & 802.1p */
-#define IGP3_CAP_AMT_CB 0x0200 /* Support active manageability and circuit breaker */
+#define IGP3_CAP_INITIATE_TEAM 0x0001 /* Able to initiate a team */
+#define IGP3_CAP_WFM 0x0002 /* Support WoL and PXE */
+#define IGP3_CAP_ASF 0x0004 /* Support ASF */
+#define IGP3_CAP_LPLU 0x0008 /* Support Low Power Link Up */
+#define IGP3_CAP_DC_AUTO_SPEED 0x0010 /* Support AC/DC Auto Link Speed */
+#define IGP3_CAP_SPD 0x0020 /* Support Smart Power Down */
+#define IGP3_CAP_MULT_QUEUE 0x0040 /* Support 2 tx & 2 rx queues */
+#define IGP3_CAP_RSS 0x0080 /* Support RSS */
+#define IGP3_CAP_8021PQ 0x0100 /* Support 802.1Q & 802.1p */
+#define IGP3_CAP_AMT_CB 0x0200 /* Support active manageability and circuit breaker */
#define IGP3_PPC_JORDAN_EN 0x0001
#define IGP3_PPC_JORDAN_GIGA_SPEED 0x0002
#define IGP3_KMRN_PMC_K0S_MODE1_EN_GIGA 0x0020
#define IGP3_KMRN_PMC_K0S_MODE1_EN_100 0x0040
-#define IGP3E1000_PHY_MISC_CTRL 0x1B /* Misc. Ctrl register */
-#define IGP3_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Duplex Manual Set */
+#define IGP3E1000_PHY_MISC_CTRL 0x1B /* Misc. Ctrl register */
+#define IGP3_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Duplex Manual Set */
#define IGP3_KMRN_EXT_CTRL PHY_REG(770, 18)
#define IGP3_KMRN_EC_DIS_INBAND 0x0080
#define IGP03E1000_E_PHY_ID 0x02A80390
-#define IFE_E_PHY_ID 0x02A80330 /* 10/100 PHY */
+#define IFE_E_PHY_ID 0x02A80330 /* 10/100 PHY */
#define IFE_PLUS_E_PHY_ID 0x02A80320
#define IFE_C_E_PHY_ID 0x02A80310
-#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 /* 100BaseTx Extended Status, Control and Address */
-#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY special control register */
-#define IFE_PHY_RCV_FALSE_CARRIER 0x13 /* 100BaseTx Receive False Carrier Counter */
-#define IFE_PHY_RCV_DISCONNECT 0x14 /* 100BaseTx Receive Disconnet Counter */
-#define IFE_PHY_RCV_ERROT_FRAME 0x15 /* 100BaseTx Receive Error Frame Counter */
-#define IFE_PHY_RCV_SYMBOL_ERR 0x16 /* Receive Symbol Error Counter */
-#define IFE_PHY_PREM_EOF_ERR 0x17 /* 100BaseTx Receive Premature End Of Frame Error Counter */
-#define IFE_PHY_RCV_EOF_ERR 0x18 /* 10BaseT Receive End Of Frame Error Counter */
-#define IFE_PHY_TX_JABBER_DETECT 0x19 /* 10BaseT Transmit Jabber Detect Counter */
-#define IFE_PHY_EQUALIZER 0x1A /* PHY Equalizer Control and Status */
-#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY special control and LED configuration */
-#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control register */
-#define IFE_PHY_HWI_CONTROL 0x1D /* Hardware Integrity Control (HWI) */
-
-#define IFE_PESC_REDUCED_POWER_DOWN_DISABLE 0x2000 /* Defaut 1 = Disable auto reduced power down */
-#define IFE_PESC_100BTX_POWER_DOWN 0x0400 /* Indicates the power state of 100BASE-TX */
-#define IFE_PESC_10BTX_POWER_DOWN 0x0200 /* Indicates the power state of 10BASE-T */
-#define IFE_PESC_POLARITY_REVERSED 0x0100 /* Indicates 10BASE-T polarity */
-#define IFE_PESC_PHY_ADDR_MASK 0x007C /* Bit 6:2 for sampled PHY address */
-#define IFE_PESC_SPEED 0x0002 /* Auto-negotiation speed result 1=100Mbs, 0=10Mbs */
-#define IFE_PESC_DUPLEX 0x0001 /* Auto-negotiation duplex result 1=Full, 0=Half */
+#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 /* 100BaseTx Extended Status, Control and Address */
+#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY special control register */
+#define IFE_PHY_RCV_FALSE_CARRIER 0x13 /* 100BaseTx Receive False Carrier Counter */
+#define IFE_PHY_RCV_DISCONNECT 0x14 /* 100BaseTx Receive Disconnect Counter */
+#define IFE_PHY_RCV_ERROT_FRAME 0x15 /* 100BaseTx Receive Error Frame Counter */
+#define IFE_PHY_RCV_SYMBOL_ERR 0x16 /* Receive Symbol Error Counter */
+#define IFE_PHY_PREM_EOF_ERR 0x17 /* 100BaseTx Receive Premature End Of Frame Error Counter */
+#define IFE_PHY_RCV_EOF_ERR 0x18 /* 10BaseT Receive End Of Frame Error Counter */
+#define IFE_PHY_TX_JABBER_DETECT 0x19 /* 10BaseT Transmit Jabber Detect Counter */
+#define IFE_PHY_EQUALIZER 0x1A /* PHY Equalizer Control and Status */
+#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY special control and LED configuration */
+#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control register */
+#define IFE_PHY_HWI_CONTROL 0x1D /* Hardware Integrity Control (HWI) */
+
+#define IFE_PESC_REDUCED_POWER_DOWN_DISABLE 0x2000 /* Default 1 = Disable auto reduced power down */
+#define IFE_PESC_100BTX_POWER_DOWN 0x0400 /* Indicates the power state of 100BASE-TX */
+#define IFE_PESC_10BTX_POWER_DOWN 0x0200 /* Indicates the power state of 10BASE-T */
+#define IFE_PESC_POLARITY_REVERSED 0x0100 /* Indicates 10BASE-T polarity */
+#define IFE_PESC_PHY_ADDR_MASK 0x007C /* Bit 6:2 for sampled PHY address */
+#define IFE_PESC_SPEED 0x0002 /* Auto-negotiation speed result 1=100Mbs, 0=10Mbs */
+#define IFE_PESC_DUPLEX 0x0001 /* Auto-negotiation duplex result 1=Full, 0=Half */
#define IFE_PESC_POLARITY_REVERSED_SHIFT 8
-#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100 /* 1 = Dyanmic Power Down disabled */
-#define IFE_PSC_FORCE_POLARITY 0x0020 /* 1=Reversed Polarity, 0=Normal */
-#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 /* 1=Auto Polarity Disabled, 0=Enabled */
-#define IFE_PSC_JABBER_FUNC_DISABLE 0x0001 /* 1=Jabber Disabled, 0=Normal Jabber Operation */
+#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100 /* 1 = Dynamic Power Down disabled */
+#define IFE_PSC_FORCE_POLARITY 0x0020 /* 1=Reversed Polarity, 0=Normal */
+#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 /* 1=Auto Polarity Disabled, 0=Enabled */
+#define IFE_PSC_JABBER_FUNC_DISABLE 0x0001 /* 1=Jabber Disabled, 0=Normal Jabber Operation */
#define IFE_PSC_FORCE_POLARITY_SHIFT 5
#define IFE_PSC_AUTO_POLARITY_DISABLE_SHIFT 4
-#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable MDI/MDI-X feature, default 0=disabled */
-#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDIX-X, 0=force MDI */
-#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */
-#define IFE_PMC_AUTO_MDIX_COMPLETE 0x0010 /* Resolution algorithm is completed */
+#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable MDI/MDI-X feature, default 0=disabled */
+#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDIX-X, 0=force MDI */
+#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */
+#define IFE_PMC_AUTO_MDIX_COMPLETE 0x0010 /* Resolution algorithm is completed */
#define IFE_PMC_MDIX_MODE_SHIFT 6
-#define IFE_PHC_MDIX_RESET_ALL_MASK 0x0000 /* Disable auto MDI-X */
-
-#define IFE_PHC_HWI_ENABLE 0x8000 /* Enable the HWI feature */
-#define IFE_PHC_ABILITY_CHECK 0x4000 /* 1= Test Passed, 0=failed */
-#define IFE_PHC_TEST_EXEC 0x2000 /* PHY launch test pulses on the wire */
-#define IFE_PHC_HIGHZ 0x0200 /* 1 = Open Circuit */
-#define IFE_PHC_LOWZ 0x0400 /* 1 = Short Circuit */
-#define IFE_PHC_LOW_HIGH_Z_MASK 0x0600 /* Mask for indication type of problem on the line */
-#define IFE_PHC_DISTANCE_MASK 0x01FF /* Mask for distance to the cable problem, in 80cm granularity */
-#define IFE_PHC_RESET_ALL_MASK 0x0000 /* Disable HWI */
-#define IFE_PSCL_PROBE_MODE 0x0020 /* LED Probe mode */
-#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */
-#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */
-
-#define ICH_FLASH_COMMAND_TIMEOUT 5000 /* 5000 uSecs - adjusted */
-#define ICH_FLASH_ERASE_TIMEOUT 3000000 /* Up to 3 seconds - worst case */
-#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 /* 10 cycles */
+#define IFE_PHC_MDIX_RESET_ALL_MASK 0x0000 /* Disable auto MDI-X */
+
+#define IFE_PHC_HWI_ENABLE 0x8000 /* Enable the HWI feature */
+#define IFE_PHC_ABILITY_CHECK 0x4000 /* 1= Test Passed, 0=failed */
+#define IFE_PHC_TEST_EXEC 0x2000 /* PHY launch test pulses on the wire */
+#define IFE_PHC_HIGHZ 0x0200 /* 1 = Open Circuit */
+#define IFE_PHC_LOWZ 0x0400 /* 1 = Short Circuit */
+#define IFE_PHC_LOW_HIGH_Z_MASK 0x0600 /* Mask for indication type of problem on the line */
+#define IFE_PHC_DISTANCE_MASK 0x01FF /* Mask for distance to the cable problem, in 80cm granularity */
+#define IFE_PHC_RESET_ALL_MASK 0x0000 /* Disable HWI */
+#define IFE_PSCL_PROBE_MODE 0x0020 /* LED Probe mode */
+#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */
+#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */
+
+#define ICH_FLASH_COMMAND_TIMEOUT 5000 /* 5000 uSecs - adjusted */
+#define ICH_FLASH_ERASE_TIMEOUT 3000000 /* Up to 3 seconds - worst case */
+#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 /* 10 cycles */
#define ICH_FLASH_SEG_SIZE_256 256
#define ICH_FLASH_SEG_SIZE_4K 4096
#define ICH_FLASH_SEG_SIZE_64K 65536
#define ICH_GFPREG_BASE_MASK 0x1FFF
#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF
-/* ICH8 GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
-/* Offset 04h HSFSTS */
-union ich8_hws_flash_status {
- struct ich8_hsfsts {
-#ifdef __BIG_ENDIAN
- u16 reserved2 :6;
- u16 fldesvalid :1;
- u16 flockdn :1;
- u16 flcdone :1;
- u16 flcerr :1;
- u16 dael :1;
- u16 berasesz :2;
- u16 flcinprog :1;
- u16 reserved1 :2;
-#else
- u16 flcdone :1; /* bit 0 Flash Cycle Done */
- u16 flcerr :1; /* bit 1 Flash Cycle Error */
- u16 dael :1; /* bit 2 Direct Access error Log */
- u16 berasesz :2; /* bit 4:3 Block/Sector Erase Size */
- u16 flcinprog :1; /* bit 5 flash SPI cycle in Progress */
- u16 reserved1 :2; /* bit 13:6 Reserved */
- u16 reserved2 :6; /* bit 13:6 Reserved */
- u16 fldesvalid :1; /* bit 14 Flash Descriptor Valid */
- u16 flockdn :1; /* bit 15 Flash Configuration Lock-Down */
-#endif
- } hsf_status;
- u16 regval;
-};
-
-/* ICH8 GbE Flash Hardware Sequencing Flash control Register bit breakdown */
-/* Offset 06h FLCTL */
-union ich8_hws_flash_ctrl {
- struct ich8_hsflctl {
-#ifdef __BIG_ENDIAN
- u16 fldbcount :2;
- u16 flockdn :6;
- u16 flcgo :1;
- u16 flcycle :2;
- u16 reserved :5;
-#else
- u16 flcgo :1; /* 0 Flash Cycle Go */
- u16 flcycle :2; /* 2:1 Flash Cycle */
- u16 reserved :5; /* 7:3 Reserved */
- u16 fldbcount :2; /* 9:8 Flash Data Byte Count */
- u16 flockdn :6; /* 15:10 Reserved */
-#endif
- } hsf_ctrl;
- u16 regval;
-};
-
-/* ICH8 Flash Region Access Permissions */
-union ich8_hws_flash_regacc {
- struct ich8_flracc {
-#ifdef __BIG_ENDIAN
- u32 gmwag :8;
- u32 gmrag :8;
- u32 grwa :8;
- u32 grra :8;
-#else
- u32 grra :8; /* 0:7 GbE region Read Access */
- u32 grwa :8; /* 8:15 GbE region Write Access */
- u32 gmrag :8; /* 23:16 GbE Master Read Access Grant */
- u32 gmwag :8; /* 31:24 GbE Master Write Access Grant */
-#endif
- } hsf_flregacc;
- u16 regval;
-};
-
/* Miscellaneous PHY bit definitions. */
#define PHY_PREAMBLE 0xFFFFFFFF
#define PHY_SOF 0x01
#define MII_CR_SPEED_100 0x2000
#define MII_CR_SPEED_10 0x0000
#define E1000_PHY_ADDRESS 0x01
-#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */
-#define PHY_FORCE_TIME 20 /* 2.0 Seconds */
+#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */
+#define PHY_FORCE_TIME 20 /* 2.0 Seconds */
#define PHY_REVISION_MASK 0xFFFFFFF0
-#define DEVICE_SPEED_MASK 0x00000300 /* Device Ctrl Reg Speed Mask */
+#define DEVICE_SPEED_MASK 0x00000300 /* Device Ctrl Reg Speed Mask */
#define REG4_SPEED_MASK 0x01E0
#define REG9_SPEED_MASK 0x0300
#define ADVERTISE_10_HALF 0x0001
#define ADVERTISE_100_FULL 0x0008
#define ADVERTISE_1000_HALF 0x0010
#define ADVERTISE_1000_FULL 0x0020
-#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* Everything but 1000-Half */
-#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds*/
-#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds*/
+#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* Everything but 1000-Half */
+#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds */
+#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds */
#endif /* _E1000_HW_H_ */
char e1000_driver_name[] = "e1000";
static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-#define DRV_VERSION "7.3.21-k3-NAPI"
+#define DRV_VERSION "7.3.21-k5-NAPI"
const char e1000_driver_version[] = DRV_VERSION;
static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
static int e1000_set_mac(struct net_device *netdev, void *p);
static irqreturn_t e1000_intr(int irq, void *data);
-static irqreturn_t e1000_intr_msi(int irq, void *data);
static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
struct e1000_tx_ring *tx_ring);
static int e1000_clean(struct napi_struct *napi, int budget);
static int e1000_request_irq(struct e1000_adapter *adapter)
{
- struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
irq_handler_t handler = e1000_intr;
int irq_flags = IRQF_SHARED;
int err;
- if (hw->mac_type >= e1000_82571) {
- adapter->have_msi = !pci_enable_msi(adapter->pdev);
- if (adapter->have_msi) {
- handler = e1000_intr_msi;
- irq_flags = 0;
- }
- }
-
err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name,
netdev);
if (err) {
- if (adapter->have_msi)
- pci_disable_msi(adapter->pdev);
DPRINTK(PROBE, ERR,
"Unable to allocate interrupt Error: %d\n", err);
}
struct net_device *netdev = adapter->netdev;
free_irq(adapter->pdev->irq, netdev);
-
- if (adapter->have_msi)
- pci_disable_msi(adapter->pdev);
}
/**
}
}
-/**
- * e1000_release_hw_control - release control of the h/w to f/w
- * @adapter: address of board private structure
- *
- * e1000_release_hw_control resets {CTRL_EXT|FWSM}:DRV_LOAD bit.
- * For ASF and Pass Through versions of f/w this means that the
- * driver is no longer loaded. For AMT version (only with 82573) i
- * of the f/w this means that the network i/f is closed.
- *
- **/
-
-static void e1000_release_hw_control(struct e1000_adapter *adapter)
-{
- u32 ctrl_ext;
- u32 swsm;
- struct e1000_hw *hw = &adapter->hw;
-
- /* Let firmware taken over control of h/w */
- switch (hw->mac_type) {
- case e1000_82573:
- swsm = er32(SWSM);
- ew32(SWSM, swsm & ~E1000_SWSM_DRV_LOAD);
- break;
- case e1000_82571:
- case e1000_82572:
- case e1000_80003es2lan:
- case e1000_ich8lan:
- ctrl_ext = er32(CTRL_EXT);
- ew32(CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
- break;
- default:
- break;
- }
-}
-
-/**
- * e1000_get_hw_control - get control of the h/w from f/w
- * @adapter: address of board private structure
- *
- * e1000_get_hw_control sets {CTRL_EXT|FWSM}:DRV_LOAD bit.
- * For ASF and Pass Through versions of f/w this means that
- * the driver is loaded. For AMT version (only with 82573)
- * of the f/w this means that the network i/f is open.
- *
- **/
-
-static void e1000_get_hw_control(struct e1000_adapter *adapter)
-{
- u32 ctrl_ext;
- u32 swsm;
- struct e1000_hw *hw = &adapter->hw;
-
- /* Let firmware know the driver has taken over */
- switch (hw->mac_type) {
- case e1000_82573:
- swsm = er32(SWSM);
- ew32(SWSM, swsm | E1000_SWSM_DRV_LOAD);
- break;
- case e1000_82571:
- case e1000_82572:
- case e1000_80003es2lan:
- case e1000_ich8lan:
- ctrl_ext = er32(CTRL_EXT);
- ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
- break;
- default:
- break;
- }
-}
-
static void e1000_init_manageability(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
/* disable hardware interception of ARP */
manc &= ~(E1000_MANC_ARP_EN);
- /* enable receiving management packets to the host */
- /* this will probably generate destination unreachable messages
- * from the host OS, but the packets will be handled on SMBUS */
- if (hw->has_manc2h) {
- u32 manc2h = er32(MANC2H);
-
- manc |= E1000_MANC_EN_MNG2HOST;
-#define E1000_MNG2HOST_PORT_623 (1 << 5)
-#define E1000_MNG2HOST_PORT_664 (1 << 6)
- manc2h |= E1000_MNG2HOST_PORT_623;
- manc2h |= E1000_MNG2HOST_PORT_664;
- ew32(MANC2H, manc2h);
- }
-
ew32(MANC, manc);
}
}
/* re-enable hardware interception of ARP */
manc |= E1000_MANC_ARP_EN;
- if (hw->has_manc2h)
- manc &= ~E1000_MANC_EN_MNG2HOST;
-
- /* don't explicitly have to mess with MANC2H since
- * MANC has an enable disable that gates MANC2H */
-
ew32(MANC, manc);
}
}
if (er32(MANC) & E1000_MANC_SMBUS_EN)
goto out;
break;
- case e1000_82571:
- case e1000_82572:
- case e1000_82573:
- case e1000_80003es2lan:
- case e1000_ich8lan:
- if (e1000_check_mng_mode(hw) ||
- e1000_check_phy_reset_block(hw))
- goto out;
- break;
default:
goto out;
}
ew32(RCTL, rctl & ~E1000_RCTL_EN);
/* flush and sleep below */
- /* can be netif_tx_disable when NETIF_F_LLTX is removed */
- netif_stop_queue(netdev);
+ netif_tx_disable(netdev);
/* disable transmits in the hardware */
tctl = er32(TCTL);
legacy_pba_adjust = true;
pba = E1000_PBA_30K;
break;
- case e1000_82571:
- case e1000_82572:
- case e1000_80003es2lan:
- pba = E1000_PBA_38K;
- break;
- case e1000_82573:
- pba = E1000_PBA_20K;
- break;
- case e1000_ich8lan:
- pba = E1000_PBA_8K;
case e1000_undefined:
case e1000_num_macs:
break;
/* if short on rx space, rx wins and must trump tx
* adjustment or use Early Receive if available */
- if (pba < min_rx_space) {
- switch (hw->mac_type) {
- case e1000_82573:
- /* ERT enabled in e1000_configure_rx */
- break;
- default:
- pba = min_rx_space;
- break;
- }
- }
+ if (pba < min_rx_space)
+ pba = min_rx_space;
}
}
/* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */
if (hw->mac_type >= e1000_82544 &&
- hw->mac_type <= e1000_82547_rev_2 &&
hw->autoneg == 1 &&
hw->autoneg_advertised == ADVERTISE_1000_FULL) {
u32 ctrl = er32(CTRL);
e1000_reset_adaptive(hw);
e1000_phy_get_info(hw, &adapter->phy_info);
- if (!adapter->smart_power_down &&
- (hw->mac_type == e1000_82571 ||
- hw->mac_type == e1000_82572)) {
- u16 phy_data = 0;
- /* speed up time to link by disabling smart power down, ignore
- * the return value of this function because there is nothing
- * different we would do if it failed */
- e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
- &phy_data);
- phy_data &= ~IGP02E1000_PM_SPD;
- e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
- phy_data);
- }
-
e1000_release_manageability(adapter);
}
goto err_sw_init;
err = -EIO;
- /* Flash BAR mapping must happen after e1000_sw_init
- * because it depends on mac_type */
- if ((hw->mac_type == e1000_ich8lan) &&
- (pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
- hw->flash_address = pci_ioremap_bar(pdev, 1);
- if (!hw->flash_address)
- goto err_flashmap;
- }
-
- if (e1000_check_phy_reset_block(hw))
- DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
if (hw->mac_type >= e1000_82543) {
netdev->features = NETIF_F_SG |
NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER;
- if (hw->mac_type == e1000_ich8lan)
- netdev->features &= ~NETIF_F_HW_VLAN_FILTER;
}
if ((hw->mac_type >= e1000_82544) &&
(hw->mac_type != e1000_82547))
netdev->features |= NETIF_F_TSO;
- if (hw->mac_type > e1000_82547_rev_2)
- netdev->features |= NETIF_F_TSO6;
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
netdev->vlan_features |= NETIF_F_TSO;
- netdev->vlan_features |= NETIF_F_TSO6;
netdev->vlan_features |= NETIF_F_HW_CSUM;
netdev->vlan_features |= NETIF_F_SG;
EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
eeprom_apme_mask = E1000_EEPROM_82544_APM;
break;
- case e1000_ich8lan:
- e1000_read_eeprom(hw,
- EEPROM_INIT_CONTROL1_REG, 1, &eeprom_data);
- eeprom_apme_mask = E1000_EEPROM_ICH8_APME;
- break;
case e1000_82546:
case e1000_82546_rev_3:
- case e1000_82571:
- case e1000_80003es2lan:
if (er32(STATUS) & E1000_STATUS_FUNC_1){
e1000_read_eeprom(hw,
EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
break;
case E1000_DEV_ID_82546EB_FIBER:
case E1000_DEV_ID_82546GB_FIBER:
- case E1000_DEV_ID_82571EB_FIBER:
/* Wake events only supported on port A for dual fiber
* regardless of eeprom setting */
if (er32(STATUS) & E1000_STATUS_FUNC_1)
adapter->eeprom_wol = 0;
break;
case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
- case E1000_DEV_ID_82571EB_QUAD_COPPER:
- case E1000_DEV_ID_82571EB_QUAD_FIBER:
- case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE:
- case E1000_DEV_ID_82571PT_QUAD_COPPER:
/* if quad port adapter, disable WoL on all but port A */
if (global_quad_port_a != 0)
adapter->eeprom_wol = 0;
/* print bus type/speed/width info */
DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ",
- ((hw->bus_type == e1000_bus_type_pcix) ? "-X" :
- (hw->bus_type == e1000_bus_type_pci_express ? " Express":"")),
- ((hw->bus_speed == e1000_bus_speed_2500) ? "2.5Gb/s" :
- (hw->bus_speed == e1000_bus_speed_133) ? "133MHz" :
+ ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
+ ((hw->bus_speed == e1000_bus_speed_133) ? "133MHz" :
(hw->bus_speed == e1000_bus_speed_120) ? "120MHz" :
(hw->bus_speed == e1000_bus_speed_100) ? "100MHz" :
(hw->bus_speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
- ((hw->bus_width == e1000_bus_width_64) ? "64-bit" :
- (hw->bus_width == e1000_bus_width_pciex_4) ? "Width x4" :
- (hw->bus_width == e1000_bus_width_pciex_1) ? "Width x1" :
- "32-bit"));
+ ((hw->bus_width == e1000_bus_width_64) ? "64-bit" : "32-bit"));
printk("%pM\n", netdev->dev_addr);
- if (hw->bus_type == e1000_bus_type_pci_express) {
- DPRINTK(PROBE, WARNING, "This device (id %04x:%04x) will no "
- "longer be supported by this driver in the future.\n",
- pdev->vendor, pdev->device);
- DPRINTK(PROBE, WARNING, "please use the \"e1000e\" "
- "driver instead.\n");
- }
-
/* reset the hardware with the new settings */
e1000_reset(adapter);
- /* If the controller is 82573 and f/w is AMT, do not set
- * DRV_LOAD until the interface is up. For all other cases,
- * let the f/w know that the h/w is now under the control
- * of the driver. */
- if (hw->mac_type != e1000_82573 ||
- !e1000_check_mng_mode(hw))
- e1000_get_hw_control(adapter);
-
strcpy(netdev->name, "eth%d");
err = register_netdev(netdev);
if (err)
return 0;
err_register:
- e1000_release_hw_control(adapter);
err_eeprom:
- if (!e1000_check_phy_reset_block(hw))
- e1000_phy_hw_reset(hw);
+ e1000_phy_hw_reset(hw);
if (hw->flash_address)
iounmap(hw->flash_address);
-err_flashmap:
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
err_sw_init:
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
+ set_bit(__E1000_DOWN, &adapter->flags);
+ del_timer_sync(&adapter->tx_fifo_stall_timer);
+ del_timer_sync(&adapter->watchdog_timer);
+ del_timer_sync(&adapter->phy_info_timer);
+
cancel_work_sync(&adapter->reset_task);
e1000_release_manageability(adapter);
- /* Release control of h/w to f/w. If f/w is AMT enabled, this
- * would have already happened in close and is redundant. */
- e1000_release_hw_control(adapter);
-
unregister_netdev(netdev);
- if (!e1000_check_phy_reset_block(hw))
- e1000_phy_hw_reset(hw);
+ e1000_phy_hw_reset(hw);
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
e1000_update_mng_vlan(adapter);
}
- /* If AMT is enabled, let the firmware know that the network
- * interface is now open */
- if (hw->mac_type == e1000_82573 &&
- e1000_check_mng_mode(hw))
- e1000_get_hw_control(adapter);
-
/* before we allocate an interrupt, we must be ready to handle it.
* Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
* as soon as we call pci_request_irq, so we have to setup our
return E1000_SUCCESS;
err_req_irq:
- e1000_release_hw_control(adapter);
e1000_power_down_phy(adapter);
e1000_free_all_rx_resources(adapter);
err_setup_rx:
e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
}
- /* If AMT is enabled, let the firmware know that the network
- * interface is now closed */
- if (hw->mac_type == e1000_82573 &&
- e1000_check_mng_mode(hw))
- e1000_release_hw_control(adapter);
-
return 0;
}
{
u64 tdba;
struct e1000_hw *hw = &adapter->hw;
- u32 tdlen, tctl, tipg, tarc;
+ u32 tdlen, tctl, tipg;
u32 ipgr1, ipgr2;
/* Setup the HW Tx Head and Tail descriptor pointers */
}
/* Set the default values for the Tx Inter Packet Gap timer */
- if (hw->mac_type <= e1000_82547_rev_2 &&
- (hw->media_type == e1000_media_type_fiber ||
+ if ((hw->media_type == e1000_media_type_fiber ||
hw->media_type == e1000_media_type_internal_serdes))
tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
else
ipgr1 = DEFAULT_82542_TIPG_IPGR1;
ipgr2 = DEFAULT_82542_TIPG_IPGR2;
break;
- case e1000_80003es2lan:
- ipgr1 = DEFAULT_82543_TIPG_IPGR1;
- ipgr2 = DEFAULT_80003ES2LAN_TIPG_IPGR2;
- break;
default:
ipgr1 = DEFAULT_82543_TIPG_IPGR1;
ipgr2 = DEFAULT_82543_TIPG_IPGR2;
tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
(E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
- if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572) {
- tarc = er32(TARC0);
- /* set the speed mode bit, we'll clear it if we're not at
- * gigabit link later */
- tarc |= (1 << 21);
- ew32(TARC0, tarc);
- } else if (hw->mac_type == e1000_80003es2lan) {
- tarc = er32(TARC0);
- tarc |= 1;
- ew32(TARC0, tarc);
- tarc = er32(TARC1);
- tarc |= 1;
- ew32(TARC1, tarc);
- }
-
e1000_config_collision_dist(hw);
/* Setup Transmit Descriptor Settings for eop descriptor */
static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
struct e1000_rx_ring *rxdr)
{
- struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
int size, desc_len;
}
memset(rxdr->buffer_info, 0, size);
- if (hw->mac_type <= e1000_82547_rev_2)
- desc_len = sizeof(struct e1000_rx_desc);
- else
- desc_len = sizeof(union e1000_rx_desc_packet_split);
+ desc_len = sizeof(struct e1000_rx_desc);
/* Round up to nearest 4K */
{
u64 rdba;
struct e1000_hw *hw = &adapter->hw;
- u32 rdlen, rctl, rxcsum, ctrl_ext;
+ u32 rdlen, rctl, rxcsum;
if (adapter->netdev->mtu > ETH_DATA_LEN) {
rdlen = adapter->rx_ring[0].count *
ew32(ITR, 1000000000 / (adapter->itr * 256));
}
- if (hw->mac_type >= e1000_82571) {
- ctrl_ext = er32(CTRL_EXT);
- /* Reset delay timers after every interrupt */
- ctrl_ext |= E1000_CTRL_EXT_INT_TIMER_CLR;
- /* Auto-Mask interrupts upon ICR access */
- ctrl_ext |= E1000_CTRL_EXT_IAME;
- ew32(IAM, 0xffffffff);
- ew32(CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH();
- }
-
/* Setup the HW Rx Head and Tail Descriptor Pointers and
* the Base and Length of the Rx Descriptor Ring */
switch (adapter->num_rx_queues) {
e1000_rar_set(hw, hw->mac_addr, 0);
- /* With 82571 controllers, LAA may be overwritten (with the default)
- * due to controller reset from the other port. */
- if (hw->mac_type == e1000_82571) {
- /* activate the work around */
- hw->laa_is_present = 1;
-
- /* Hold a copy of the LAA in RAR[14] This is done so that
- * between the time RAR[0] gets clobbered and the time it
- * gets fixed (in e1000_watchdog), the actual LAA is in one
- * of the RARs and no incoming packets directed to this port
- * are dropped. Eventaully the LAA will be in RAR[0] and
- * RAR[14] */
- e1000_rar_set(hw, hw->mac_addr,
- E1000_RAR_ENTRIES - 1);
- }
-
if (hw->mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
u32 rctl;
u32 hash_value;
int i, rar_entries = E1000_RAR_ENTRIES;
- int mta_reg_count = (hw->mac_type == e1000_ich8lan) ?
- E1000_NUM_MTA_REGISTERS_ICH8LAN :
- E1000_NUM_MTA_REGISTERS;
+ int mta_reg_count = E1000_NUM_MTA_REGISTERS;
u32 *mcarray = kcalloc(mta_reg_count, sizeof(u32), GFP_ATOMIC);
if (!mcarray) {
return;
}
- if (hw->mac_type == e1000_ich8lan)
- rar_entries = E1000_RAR_ENTRIES_ICH8LAN;
-
- /* reserve RAR[14] for LAA over-write work-around */
- if (hw->mac_type == e1000_82571)
- rar_entries--;
-
/* Check for Promiscuous and All Multicast modes */
rctl = er32(RCTL);
rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
rctl &= ~E1000_RCTL_VFE;
} else {
- if (netdev->flags & IFF_ALLMULTI) {
+ if (netdev->flags & IFF_ALLMULTI)
rctl |= E1000_RCTL_MPE;
- } else {
+ else
rctl &= ~E1000_RCTL_MPE;
- }
- if (adapter->hw.mac_type != e1000_ich8lan)
- /* Enable VLAN filter if there is a VLAN */
- if (adapter->vlgrp)
- rctl |= E1000_RCTL_VFE;
+ /* Enable VLAN filter if there is a VLAN */
+ if (adapter->vlgrp)
+ rctl |= E1000_RCTL_VFE;
}
if (netdev->uc.count > rar_entries - 1) {
*
* RAR 0 is used for the station MAC adddress
* if there are not 14 addresses, go ahead and clear the filters
- * -- with 82571 controllers only 0-13 entries are filled here
*/
i = 1;
if (use_uc)
adapter->tx_fifo_head = 0;
atomic_set(&adapter->tx_fifo_stall, 0);
netif_wake_queue(netdev);
- } else {
+ } else if (!test_bit(__E1000_DOWN, &adapter->flags)) {
mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1);
}
}
}
+static bool e1000_has_link(struct e1000_adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ bool link_active = false;
+
+ /* get_link_status is set on LSC (link status) interrupt or
+ * rx sequence error interrupt. get_link_status will stay
+ * false until the e1000_check_for_link establishes link
+ * for copper adapters ONLY
+ */
+ switch (hw->media_type) {
+ case e1000_media_type_copper:
+ if (hw->get_link_status) {
+ e1000_check_for_link(hw);
+ link_active = !hw->get_link_status;
+ } else {
+ link_active = true;
+ }
+ break;
+ case e1000_media_type_fiber:
+ e1000_check_for_link(hw);
+ link_active = !!(er32(STATUS) & E1000_STATUS_LU);
+ break;
+ case e1000_media_type_internal_serdes:
+ e1000_check_for_link(hw);
+ link_active = hw->serdes_has_link;
+ break;
+ default:
+ break;
+ }
+
+ return link_active;
+}
+
/**
* e1000_watchdog - Timer Call-back
* @data: pointer to adapter cast into an unsigned long
struct net_device *netdev = adapter->netdev;
struct e1000_tx_ring *txdr = adapter->tx_ring;
u32 link, tctl;
- s32 ret_val;
-
- ret_val = e1000_check_for_link(hw);
- if ((ret_val == E1000_ERR_PHY) &&
- (hw->phy_type == e1000_phy_igp_3) &&
- (er32(CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) {
- /* See e1000_kumeran_lock_loss_workaround() */
- DPRINTK(LINK, INFO,
- "Gigabit has been disabled, downgrading speed\n");
- }
- if (hw->mac_type == e1000_82573) {
- e1000_enable_tx_pkt_filtering(hw);
- if (adapter->mng_vlan_id != hw->mng_cookie.vlan_id)
- e1000_update_mng_vlan(adapter);
- }
-
- if ((hw->media_type == e1000_media_type_internal_serdes) &&
- !(er32(TXCW) & E1000_TXCW_ANE))
- link = !hw->serdes_link_down;
- else
- link = er32(STATUS) & E1000_STATUS_LU;
+ link = e1000_has_link(adapter);
+ if ((netif_carrier_ok(netdev)) && link)
+ goto link_up;
if (link) {
if (!netif_carrier_ok(netdev)) {
u32 ctrl;
bool txb2b = true;
+ /* update snapshot of PHY registers on LSC */
e1000_get_speed_and_duplex(hw,
&adapter->link_speed,
&adapter->link_duplex);
case SPEED_10:
txb2b = false;
netdev->tx_queue_len = 10;
- adapter->tx_timeout_factor = 8;
+ adapter->tx_timeout_factor = 16;
break;
case SPEED_100:
txb2b = false;
break;
}
- if ((hw->mac_type == e1000_82571 ||
- hw->mac_type == e1000_82572) &&
- !txb2b) {
- u32 tarc0;
- tarc0 = er32(TARC0);
- tarc0 &= ~(1 << 21);
- ew32(TARC0, tarc0);
- }
-
- /* disable TSO for pcie and 10/100 speeds, to avoid
- * some hardware issues */
- if (!adapter->tso_force &&
- hw->bus_type == e1000_bus_type_pci_express){
- switch (adapter->link_speed) {
- case SPEED_10:
- case SPEED_100:
- DPRINTK(PROBE,INFO,
- "10/100 speed: disabling TSO\n");
- netdev->features &= ~NETIF_F_TSO;
- netdev->features &= ~NETIF_F_TSO6;
- break;
- case SPEED_1000:
- netdev->features |= NETIF_F_TSO;
- netdev->features |= NETIF_F_TSO6;
- break;
- default:
- /* oops */
- break;
- }
- }
-
- /* enable transmits in the hardware, need to do this
- * after setting TARC0 */
+ /* enable transmits in the hardware */
tctl = er32(TCTL);
tctl |= E1000_TCTL_EN;
ew32(TCTL, tctl);
netif_carrier_on(netdev);
- mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ));
+ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ mod_timer(&adapter->phy_info_timer,
+ round_jiffies(jiffies + 2 * HZ));
adapter->smartspeed = 0;
- } else {
- /* make sure the receive unit is started */
- if (hw->rx_needs_kicking) {
- u32 rctl = er32(RCTL);
- ew32(RCTL, rctl | E1000_RCTL_EN);
- }
}
} else {
if (netif_carrier_ok(netdev)) {
printk(KERN_INFO "e1000: %s NIC Link is Down\n",
netdev->name);
netif_carrier_off(netdev);
- mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ));
-
- /* 80003ES2LAN workaround--
- * For packet buffer work-around on link down event;
- * disable receives in the ISR and
- * reset device here in the watchdog
- */
- if (hw->mac_type == e1000_80003es2lan)
- /* reset device */
- schedule_work(&adapter->reset_task);
+
+ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ mod_timer(&adapter->phy_info_timer,
+ round_jiffies(jiffies + 2 * HZ));
}
e1000_smartspeed(adapter);
}
+link_up:
e1000_update_stats(adapter);
hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
/* Force detection of hung controller every watchdog period */
adapter->detect_tx_hung = true;
- /* With 82571 controllers, LAA may be overwritten due to controller
- * reset from the other port. Set the appropriate LAA in RAR[0] */
- if (hw->mac_type == e1000_82571 && hw->laa_is_present)
- e1000_rar_set(hw, hw->mac_addr, 0);
-
/* Reset the timer */
- mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ));
+ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ mod_timer(&adapter->watchdog_timer,
+ round_jiffies(jiffies + 2 * HZ));
}
enum latency_range {
/**
* e1000_update_itr - update the dynamic ITR value based on statistics
+ * @adapter: pointer to adapter
+ * @itr_setting: current adapter->itr
+ * @packets: the number of packets during this measurement interval
+ * @bytes: the number of bytes during this measurement interval
+ *
* Stores a new ITR value based on packets and byte
* counts during the last interrupt. The advantage of per interrupt
* computation is faster updates and more accurate ITR for the current
* while increasing bulk throughput.
* this functionality is controlled by the InterruptThrottleRate module
* parameter (see e1000_param.c)
- * @adapter: pointer to adapter
- * @itr_setting: current adapter->itr
- * @packets: the number of packets during this measurement interval
- * @bytes: the number of bytes during this measurement interval
**/
static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
u16 itr_setting, int packets, int bytes)
size -= 4;
buffer_info->length = size;
- buffer_info->dma = skb_shinfo(skb)->dma_head + offset;
+ /* set time_stamp *before* dma to help avoid a possible race */
buffer_info->time_stamp = jiffies;
+ buffer_info->dma = skb_shinfo(skb)->dma_head + offset;
buffer_info->next_to_watch = i;
len -= size;
* Avoid terminating buffers within evenly-aligned
* dwords. */
if (unlikely(adapter->pcix_82544 &&
- !((unsigned long)(frag->page+offset+size-1) & 4) &&
- size > 4))
+ !((unsigned long)(page_to_phys(frag->page) + offset
+ + size - 1) & 4) &&
+ size > 4))
size -= 4;
buffer_info->length = size;
- buffer_info->dma = map[f] + offset;
buffer_info->time_stamp = jiffies;
+ buffer_info->dma = map[f] + offset;
buffer_info->next_to_watch = i;
len -= size;
return 0;
}
-#define MINIMUM_DHCP_PACKET_SIZE 282
-static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter,
- struct sk_buff *skb)
-{
- struct e1000_hw *hw = &adapter->hw;
- u16 length, offset;
- if (vlan_tx_tag_present(skb)) {
- if (!((vlan_tx_tag_get(skb) == hw->mng_cookie.vlan_id) &&
- ( hw->mng_cookie.status &
- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
- return 0;
- }
- if (skb->len > MINIMUM_DHCP_PACKET_SIZE) {
- struct ethhdr *eth = (struct ethhdr *)skb->data;
- if ((htons(ETH_P_IP) == eth->h_proto)) {
- const struct iphdr *ip =
- (struct iphdr *)((u8 *)skb->data+14);
- if (IPPROTO_UDP == ip->protocol) {
- struct udphdr *udp =
- (struct udphdr *)((u8 *)ip +
- (ip->ihl << 2));
- if (ntohs(udp->dest) == 67) {
- offset = (u8 *)udp + 8 - skb->data;
- length = skb->len - offset;
-
- return e1000_mng_write_dhcp_info(hw,
- (u8 *)udp + 8,
- length);
- }
- }
- }
- }
- return 0;
-}
-
static int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
return NETDEV_TX_OK;
}
- /* 82571 and newer doesn't need the workaround that limited descriptor
- * length to 4kB */
- if (hw->mac_type >= e1000_82571)
- max_per_txd = 8192;
-
mss = skb_shinfo(skb)->gso_size;
/* The controller does a simple calculation to
* make sure there is enough room in the FIFO before
max_per_txd = min(mss << 2, max_per_txd);
max_txd_pwr = fls(max_per_txd) - 1;
- /* TSO Workaround for 82571/2/3 Controllers -- if skb->data
- * points to just header, pull a few bytes of payload from
- * frags into skb->data */
hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
if (skb->data_len && hdr_len == len) {
switch (hw->mac_type) {
if ((unsigned long)(skb_tail_pointer(skb) - 1) & 4)
break;
/* fall through */
- case e1000_82571:
- case e1000_82572:
- case e1000_82573:
- case e1000_ich8lan:
pull_size = min((unsigned int)4, skb->data_len);
if (!__pskb_pull_tail(skb, pull_size)) {
DPRINTK(DRV, ERR,
if (adapter->pcix_82544)
count += nr_frags;
-
- if (hw->tx_pkt_filtering &&
- (hw->mac_type == e1000_82573))
- e1000_transfer_dhcp_info(adapter, skb);
-
/* need: count + 2 desc gap to keep tail from touching
* head, otherwise try next time */
if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2)))
if (unlikely(hw->mac_type == e1000_82547)) {
if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
netif_stop_queue(netdev);
- mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1);
+ if (!test_bit(__E1000_DOWN, &adapter->flags))
+ mod_timer(&adapter->tx_fifo_stall_timer,
+ jiffies + 1);
return NETDEV_TX_BUSY;
}
}
}
if (likely(tso)) {
- tx_ring->last_tx_tso = 1;
+ if (likely(hw->mac_type != e1000_82544))
+ tx_ring->last_tx_tso = 1;
tx_flags |= E1000_TX_FLAGS_TSO;
} else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
tx_flags |= E1000_TX_FLAGS_CSUM;
- /* Old method was to assume IPv4 packet by default if TSO was enabled.
- * 82571 hardware supports TSO capabilities for IPv6 as well...
- * no longer assume, we must. */
if (likely(skb->protocol == htons(ETH_P_IP)))
tx_flags |= E1000_TX_FLAGS_IPV4;
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
- u16 eeprom_data = 0;
if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
(max_frame > MAX_JUMBO_FRAME_SIZE)) {
/* Adapter-specific max frame size limits. */
switch (hw->mac_type) {
case e1000_undefined ... e1000_82542_rev2_1:
- case e1000_ich8lan:
if (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n");
return -EINVAL;
}
break;
- case e1000_82573:
- /* Jumbo Frames not supported if:
- * - this is not an 82573L device
- * - ASPM is enabled in any way (0x1A bits 3:2) */
- e1000_read_eeprom(hw, EEPROM_INIT_3GIO_3, 1,
- &eeprom_data);
- if ((hw->device_id != E1000_DEV_ID_82573L) ||
- (eeprom_data & EEPROM_WORD1A_ASPM_MASK)) {
- if (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
- DPRINTK(PROBE, ERR,
- "Jumbo Frames not supported.\n");
- return -EINVAL;
- }
- break;
- }
- /* ERT will be enabled later to enable wire speed receives */
-
- /* fall through to get support */
- case e1000_82571:
- case e1000_82572:
- case e1000_80003es2lan:
-#define MAX_STD_JUMBO_FRAME_SIZE 9234
- if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
- DPRINTK(PROBE, ERR, "MTU > 9216 not supported.\n");
- return -EINVAL;
- }
- break;
default:
/* Capable of supporting up to MAX_JUMBO_FRAME_SIZE limit. */
break;
}
+ while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
+ msleep(1);
+ /* e1000_down has a dependency on max_frame_size */
+ hw->max_frame_size = max_frame;
+ if (netif_running(netdev))
+ e1000_down(adapter);
+
/* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
* means we reserve 2 more, this pushes us to allocate from the next
* larger slab size.
(max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
+ printk(KERN_INFO "e1000: %s changing MTU from %d to %d\n",
+ netdev->name, netdev->mtu, new_mtu);
netdev->mtu = new_mtu;
- hw->max_frame_size = max_frame;
if (netif_running(netdev))
- e1000_reinit_locked(adapter);
+ e1000_up(adapter);
+ else
+ e1000_reset(adapter);
+
+ clear_bit(__E1000_RESETTING, &adapter->flags);
return 0;
}
adapter->stats.mprc += er32(MPRC);
adapter->stats.roc += er32(ROC);
- if (hw->mac_type != e1000_ich8lan) {
- adapter->stats.prc64 += er32(PRC64);
- adapter->stats.prc127 += er32(PRC127);
- adapter->stats.prc255 += er32(PRC255);
- adapter->stats.prc511 += er32(PRC511);
- adapter->stats.prc1023 += er32(PRC1023);
- adapter->stats.prc1522 += er32(PRC1522);
- }
+ adapter->stats.prc64 += er32(PRC64);
+ adapter->stats.prc127 += er32(PRC127);
+ adapter->stats.prc255 += er32(PRC255);
+ adapter->stats.prc511 += er32(PRC511);
+ adapter->stats.prc1023 += er32(PRC1023);
+ adapter->stats.prc1522 += er32(PRC1522);
adapter->stats.symerrs += er32(SYMERRS);
adapter->stats.mpc += er32(MPC);
adapter->stats.toth += er32(TOTH);
adapter->stats.tpr += er32(TPR);
- if (hw->mac_type != e1000_ich8lan) {
- adapter->stats.ptc64 += er32(PTC64);
- adapter->stats.ptc127 += er32(PTC127);
- adapter->stats.ptc255 += er32(PTC255);
- adapter->stats.ptc511 += er32(PTC511);
- adapter->stats.ptc1023 += er32(PTC1023);
- adapter->stats.ptc1522 += er32(PTC1522);
- }
+ adapter->stats.ptc64 += er32(PTC64);
+ adapter->stats.ptc127 += er32(PTC127);
+ adapter->stats.ptc255 += er32(PTC255);
+ adapter->stats.ptc511 += er32(PTC511);
+ adapter->stats.ptc1023 += er32(PTC1023);
+ adapter->stats.ptc1522 += er32(PTC1522);
adapter->stats.mptc += er32(MPTC);
adapter->stats.bptc += er32(BPTC);
adapter->stats.tsctc += er32(TSCTC);
adapter->stats.tsctfc += er32(TSCTFC);
}
- if (hw->mac_type > e1000_82547_rev_2) {
- adapter->stats.iac += er32(IAC);
- adapter->stats.icrxoc += er32(ICRXOC);
-
- if (hw->mac_type != e1000_ich8lan) {
- adapter->stats.icrxptc += er32(ICRXPTC);
- adapter->stats.icrxatc += er32(ICRXATC);
- adapter->stats.ictxptc += er32(ICTXPTC);
- adapter->stats.ictxatc += er32(ICTXATC);
- adapter->stats.ictxqec += er32(ICTXQEC);
- adapter->stats.ictxqmtc += er32(ICTXQMTC);
- adapter->stats.icrxdmtc += er32(ICRXDMTC);
- }
- }
/* Fill out the OS statistics structure */
adapter->net_stats.multicast = adapter->stats.mprc;
spin_unlock_irqrestore(&adapter->stats_lock, flags);
}
-/**
- * e1000_intr_msi - Interrupt Handler
- * @irq: interrupt number
- * @data: pointer to a network interface device structure
- **/
-
-static irqreturn_t e1000_intr_msi(int irq, void *data)
-{
- struct net_device *netdev = data;
- struct e1000_adapter *adapter = netdev_priv(netdev);
- struct e1000_hw *hw = &adapter->hw;
- u32 icr = er32(ICR);
-
- /* in NAPI mode read ICR disables interrupts using IAM */
-
- if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
- hw->get_link_status = 1;
- /* 80003ES2LAN workaround-- For packet buffer work-around on
- * link down event; disable receives here in the ISR and reset
- * adapter in watchdog */
- if (netif_carrier_ok(netdev) &&
- (hw->mac_type == e1000_80003es2lan)) {
- /* disable receives */
- u32 rctl = er32(RCTL);
- ew32(RCTL, rctl & ~E1000_RCTL_EN);
- }
- /* guard against interrupt when we're going down */
- if (!test_bit(__E1000_DOWN, &adapter->flags))
- mod_timer(&adapter->watchdog_timer, jiffies + 1);
- }
-
- if (likely(napi_schedule_prep(&adapter->napi))) {
- adapter->total_tx_bytes = 0;
- adapter->total_tx_packets = 0;
- adapter->total_rx_bytes = 0;
- adapter->total_rx_packets = 0;
- __napi_schedule(&adapter->napi);
- } else
- e1000_irq_enable(adapter);
-
- return IRQ_HANDLED;
-}
-
/**
* e1000_intr - Interrupt Handler
* @irq: interrupt number
struct net_device *netdev = data;
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- u32 rctl, icr = er32(ICR);
+ u32 icr = er32(ICR);
if (unlikely((!icr) || test_bit(__E1000_DOWN, &adapter->flags)))
return IRQ_NONE; /* Not our interrupt */
- /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
- * not set, then the adapter didn't send an interrupt */
- if (unlikely(hw->mac_type >= e1000_82571 &&
- !(icr & E1000_ICR_INT_ASSERTED)))
- return IRQ_NONE;
-
- /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No
- * need for the IMC write */
-
if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
hw->get_link_status = 1;
- /* 80003ES2LAN workaround--
- * For packet buffer work-around on link down event;
- * disable receives here in the ISR and
- * reset adapter in watchdog
- */
- if (netif_carrier_ok(netdev) &&
- (hw->mac_type == e1000_80003es2lan)) {
- /* disable receives */
- rctl = er32(RCTL);
- ew32(RCTL, rctl & ~E1000_RCTL_EN);
- }
/* guard against interrupt when we're going down */
if (!test_bit(__E1000_DOWN, &adapter->flags))
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
- if (unlikely(hw->mac_type < e1000_82571)) {
- /* disable interrupts, without the synchronize_irq bit */
- ew32(IMC, ~0);
- E1000_WRITE_FLUSH();
- }
+ /* disable interrupts, without the synchronize_irq bit */
+ ew32(IMC, ~0);
+ E1000_WRITE_FLUSH();
+
if (likely(napi_schedule_prep(&adapter->napi))) {
adapter->total_tx_bytes = 0;
adapter->total_tx_packets = 0;
static int e1000_clean(struct napi_struct *napi, int budget)
{
struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi);
- struct net_device *poll_dev = adapter->netdev;
- int tx_cleaned = 0, work_done = 0;
-
- adapter = netdev_priv(poll_dev);
+ int tx_clean_complete = 0, work_done = 0;
- tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[0]);
+ tx_clean_complete = e1000_clean_tx_irq(adapter, &adapter->tx_ring[0]);
- adapter->clean_rx(adapter, &adapter->rx_ring[0],
- &work_done, budget);
+ adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget);
- if (!tx_cleaned)
+ if (!tx_clean_complete)
work_done = budget;
/* If budget not fully consumed, exit the polling mode */
* sees the new next_to_clean.
*/
smp_mb();
- if (netif_queue_stopped(netdev)) {
+
+ if (netif_queue_stopped(netdev) &&
+ !(test_bit(__E1000_DOWN, &adapter->flags))) {
netif_wake_queue(netdev);
++adapter->restart_queue;
}
/* Detect a transmit hang in hardware, this serializes the
* check with the clearing of time_stamp and movement of i */
adapter->detect_tx_hung = false;
- if (tx_ring->buffer_info[i].time_stamp &&
- time_after(jiffies, tx_ring->buffer_info[i].time_stamp +
+ if (tx_ring->buffer_info[eop].time_stamp &&
+ time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
(adapter->tx_timeout_factor * HZ))
&& !(er32(STATUS) & E1000_STATUS_TXOFF)) {
readl(hw->hw_addr + tx_ring->tdt),
tx_ring->next_to_use,
tx_ring->next_to_clean,
- tx_ring->buffer_info[i].time_stamp,
+ tx_ring->buffer_info[eop].time_stamp,
eop,
jiffies,
eop_desc->upper.fields.status);
return;
}
/* TCP/UDP Checksum has not been calculated */
- if (hw->mac_type <= e1000_82547_rev_2) {
- if (!(status & E1000_RXD_STAT_TCPCS))
- return;
- } else {
- if (!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)))
- return;
- }
+ if (!(status & E1000_RXD_STAT_TCPCS))
+ return;
+
/* It must be a TCP or UDP packet with a valid checksum */
if (likely(status & E1000_RXD_STAT_TCPCS)) {
/* TCP checksum is good */
skb->ip_summed = CHECKSUM_UNNECESSARY;
- } else if (hw->mac_type > e1000_82547_rev_2) {
- /* IP fragment with UDP payload */
- /* Hardware complements the payload checksum, so we undo it
- * and then put the value in host order for further stack use.
- */
- __sum16 sum = (__force __sum16)htons(csum);
- skb->csum = csum_unfold(~sum);
- skb->ip_summed = CHECKSUM_COMPLETE;
}
adapter->hw_csum_good++;
}
pcix_set_mmrbc(adapter->pdev, mmrbc);
}
-s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
-{
- struct e1000_adapter *adapter = hw->back;
- u16 cap_offset;
-
- cap_offset = pci_find_capability(adapter->pdev, PCI_CAP_ID_EXP);
- if (!cap_offset)
- return -E1000_ERR_CONFIG;
-
- pci_read_config_word(adapter->pdev, cap_offset + reg, value);
-
- return E1000_SUCCESS;
-}
-
void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
{
outl(value, port);
ctrl |= E1000_CTRL_VME;
ew32(CTRL, ctrl);
- if (adapter->hw.mac_type != e1000_ich8lan) {
- /* enable VLAN receive filtering */
- rctl = er32(RCTL);
- rctl &= ~E1000_RCTL_CFIEN;
- if (!(netdev->flags & IFF_PROMISC))
- rctl |= E1000_RCTL_VFE;
- ew32(RCTL, rctl);
- e1000_update_mng_vlan(adapter);
- }
+ /* enable VLAN receive filtering */
+ rctl = er32(RCTL);
+ rctl &= ~E1000_RCTL_CFIEN;
+ if (!(netdev->flags & IFF_PROMISC))
+ rctl |= E1000_RCTL_VFE;
+ ew32(RCTL, rctl);
+ e1000_update_mng_vlan(adapter);
} else {
/* disable VLAN tag insert/strip */
ctrl = er32(CTRL);
ctrl &= ~E1000_CTRL_VME;
ew32(CTRL, ctrl);
- if (adapter->hw.mac_type != e1000_ich8lan) {
- /* disable VLAN receive filtering */
- rctl = er32(RCTL);
- rctl &= ~E1000_RCTL_VFE;
- ew32(RCTL, rctl);
+ /* disable VLAN receive filtering */
+ rctl = er32(RCTL);
+ rctl &= ~E1000_RCTL_VFE;
+ ew32(RCTL, rctl);
- if (adapter->mng_vlan_id !=
- (u16)E1000_MNG_VLAN_NONE) {
- e1000_vlan_rx_kill_vid(netdev,
- adapter->mng_vlan_id);
- adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
- }
+ if (adapter->mng_vlan_id != (u16)E1000_MNG_VLAN_NONE) {
+ e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
+ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
}
}
if (!test_bit(__E1000_DOWN, &adapter->flags))
e1000_irq_enable(adapter);
- if ((hw->mng_cookie.status &
- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
- (vid == adapter->mng_vlan_id)) {
- /* release control to f/w */
- e1000_release_hw_control(adapter);
- return;
- }
-
/* remove VID from filter table */
index = (vid >> 5) & 0x7F;
vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
}
if (hw->media_type == e1000_media_type_fiber ||
- hw->media_type == e1000_media_type_internal_serdes) {
+ hw->media_type == e1000_media_type_internal_serdes) {
/* keep the laser running in D3 */
ctrl_ext = er32(CTRL_EXT);
ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
ew32(CTRL_EXT, ctrl_ext);
}
- /* Allow time for pending master requests to run */
- e1000_disable_pciex_master(hw);
-
ew32(WUC, E1000_WUC_PME_EN);
ew32(WUFC, wufc);
} else {
if (adapter->en_mng_pt)
*enable_wake = true;
- if (hw->phy_type == e1000_phy_igp_3)
- e1000_phy_powerdown_workaround(hw);
-
if (netif_running(netdev))
e1000_free_irq(adapter);
- /* Release control of h/w to f/w. If f/w is AMT enabled, this
- * would have already happened in close and is redundant. */
- e1000_release_hw_control(adapter);
-
pci_disable_device(pdev);
return 0;
netif_device_attach(netdev);
- /* If the controller is 82573 and f/w is AMT, do not set
- * DRV_LOAD until the interface is up. For all other cases,
- * let the f/w know that the h/w is now under the control
- * of the driver. */
- if (hw->mac_type != e1000_82573 ||
- !e1000_check_mng_mode(hw))
- e1000_get_hw_control(adapter);
-
return 0;
}
#endif
/**
* e1000_io_error_detected - called when PCI error is detected
* @pdev: Pointer to PCI device
- * @state: The current pci conneection state
+ * @state: The current pci connection state
*
* This function is called after a PCI bus error affecting
* this device has been detected.
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
- struct e1000_hw *hw = &adapter->hw;
e1000_init_manageability(adapter);
}
netif_device_attach(netdev);
-
- /* If the controller is 82573 and f/w is AMT, do not set
- * DRV_LOAD until the interface is up. For all other cases,
- * let the f/w know that the h/w is now under the control
- * of the driver. */
- if (hw->mac_type != e1000_82573 ||
- !e1000_check_mng_mode(hw))
- e1000_get_hw_control(adapter);
-
}
/* e1000_main.c */
adapter->smart_power_down = opt.def;
}
}
- { /* Kumeran Lock Loss Workaround */
- opt = (struct e1000_option) {
- .type = enable_option,
- .name = "Kumeran Lock Loss Workaround",
- .err = "defaulting to Enabled",
- .def = OPTION_ENABLED
- };
-
- if (num_KumeranLockLoss > bd) {
- unsigned int kmrn_lock_loss = KumeranLockLoss[bd];
- e1000_validate_option(&kmrn_lock_loss, &opt, adapter);
- adapter->hw.kmrn_lock_loss_workaround_disabled = !kmrn_lock_loss;
- } else {
- adapter->hw.kmrn_lock_loss_workaround_disabled = !opt.def;
- }
- }
switch (adapter->hw.media_type) {
case e1000_media_type_fiber:
.p = dplx_list }}
};
- if (e1000_check_phy_reset_block(&adapter->hw)) {
- DPRINTK(PROBE, INFO,
- "Link active due to SoL/IDER Session. "
- "Speed/Duplex/AutoNeg parameter ignored.\n");
- return;
- }
if (num_Duplex > bd) {
dplx = Duplex[bd];
e1000_validate_option(&dplx, &opt, adapter);
/* it's OK to use per_cpu_ptr() because BHs are off */
pcpu_lstats = dev->ml_priv;
- lb_stats = per_cpu_ptr(pcpu_lstats, smp_processor_id());
+ lb_stats = this_cpu_ptr(pcpu_lstats);
len = skb->len;
if (likely(netif_rx(skb) == NET_RX_SUCCESS)) {
* session or the special tunnel type.
*/
static int pppol2tp_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct pppol2tp_session *session = sk->sk_user_data;
struct net_device *rcv = NULL;
struct veth_priv *priv, *rcv_priv;
struct veth_net_stats *stats, *rcv_stats;
- int length, cpu;
+ int length;
skb_orphan(skb);
rcv = priv->peer;
rcv_priv = netdev_priv(rcv);
- cpu = smp_processor_id();
- stats = per_cpu_ptr(priv->stats, cpu);
- rcv_stats = per_cpu_ptr(rcv_priv->stats, cpu);
+ stats = this_cpu_ptr(priv->stats);
+ rcv_stats = this_cpu_ptr(rcv_priv->stats);
if (!(rcv->flags & IFF_UP))
goto tx_drop;
.setup_deferred_work = iwl5000_setup_deferred_work,
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
.load_ucode = iwl5000_load_ucode,
+ .dump_nic_event_log = iwl_dump_nic_event_log,
+ .dump_nic_error_log = iwl_dump_nic_error_log,
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
.send_tx_power = iwl5000_send_tx_power,
.txq_free_tfd = iwl3945_hw_txq_free_tfd,
.txq_init = iwl3945_hw_tx_queue_init,
.load_ucode = iwl3945_load_bsm,
+ .dump_nic_event_log = iwl3945_dump_nic_event_log,
+ .dump_nic_error_log = iwl3945_dump_nic_error_log,
.apm_ops = {
.init = iwl3945_apm_init,
.reset = iwl3945_apm_reset,
struct iwl_host_cmd *cmd);
extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,int left);
+extern void iwl3945_dump_nic_event_log(struct iwl_priv *priv);
+extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv);
/*
* Currently used by iwl-3945-rs... look at restructuring so that it doesn't
.alive_notify = iwl4965_alive_notify,
.init_alive_start = iwl4965_init_alive_start,
.load_ucode = iwl4965_load_bsm,
+ .dump_nic_event_log = iwl_dump_nic_event_log,
+ .dump_nic_error_log = iwl_dump_nic_error_log,
.apm_ops = {
.init = iwl4965_apm_init,
.reset = iwl4965_apm_reset,
.rx_handler_setup = iwl5000_rx_handler_setup,
.setup_deferred_work = iwl5000_setup_deferred_work,
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
+ .dump_nic_event_log = iwl_dump_nic_event_log,
+ .dump_nic_error_log = iwl_dump_nic_error_log,
.load_ucode = iwl5000_load_ucode,
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
.rx_handler_setup = iwl5000_rx_handler_setup,
.setup_deferred_work = iwl5000_setup_deferred_work,
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
+ .dump_nic_event_log = iwl_dump_nic_event_log,
+ .dump_nic_error_log = iwl_dump_nic_error_log,
.load_ucode = iwl5000_load_ucode,
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
.setup_deferred_work = iwl5000_setup_deferred_work,
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
.load_ucode = iwl5000_load_ucode,
+ .dump_nic_event_log = iwl_dump_nic_event_log,
+ .dump_nic_error_log = iwl_dump_nic_error_log,
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
.send_tx_power = iwl5000_send_tx_power,
return ret;
}
+#ifdef CONFIG_IWLWIFI_DEBUG
+static const char *desc_lookup_text[] = {
+ "OK",
+ "FAIL",
+ "BAD_PARAM",
+ "BAD_CHECKSUM",
+ "NMI_INTERRUPT_WDG",
+ "SYSASSERT",
+ "FATAL_ERROR",
+ "BAD_COMMAND",
+ "HW_ERROR_TUNE_LOCK",
+ "HW_ERROR_TEMPERATURE",
+ "ILLEGAL_CHAN_FREQ",
+ "VCC_NOT_STABLE",
+ "FH_ERROR",
+ "NMI_INTERRUPT_HOST",
+ "NMI_INTERRUPT_ACTION_PT",
+ "NMI_INTERRUPT_UNKNOWN",
+ "UCODE_VERSION_MISMATCH",
+ "HW_ERROR_ABS_LOCK",
+ "HW_ERROR_CAL_LOCK_FAIL",
+ "NMI_INTERRUPT_INST_ACTION_PT",
+ "NMI_INTERRUPT_DATA_ACTION_PT",
+ "NMI_TRM_HW_ER",
+ "NMI_INTERRUPT_TRM",
+ "NMI_INTERRUPT_BREAK_POINT"
+ "DEBUG_0",
+ "DEBUG_1",
+ "DEBUG_2",
+ "DEBUG_3",
+ "UNKNOWN"
+};
+
+static const char *desc_lookup(int i)
+{
+ int max = ARRAY_SIZE(desc_lookup_text) - 1;
+
+ if (i < 0 || i > max)
+ i = max;
+
+ return desc_lookup_text[i];
+}
+
+#define ERROR_START_OFFSET (1 * sizeof(u32))
+#define ERROR_ELEM_SIZE (7 * sizeof(u32))
+
+void iwl_dump_nic_error_log(struct iwl_priv *priv)
+{
+ u32 data2, line;
+ u32 desc, time, count, base, data1;
+ u32 blink1, blink2, ilink1, ilink2;
+
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
+
+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
+ return;
+ }
+
+ count = iwl_read_targ_mem(priv, base);
+
+ if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+ IWL_ERR(priv, "Start IWL Error Log Dump:\n");
+ IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
+ priv->status, count);
+ }
+
+ desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
+ blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
+ blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
+ ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
+ ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
+ data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
+ data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
+ line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
+ time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
+
+ IWL_ERR(priv, "Desc Time "
+ "data1 data2 line\n");
+ IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
+ desc_lookup(desc), desc, time, data1, data2, line);
+ IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n");
+ IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
+ ilink1, ilink2);
+
+}
+
+#define EVENT_START_OFFSET (4 * sizeof(u32))
+
+/**
+ * iwl_print_event_log - Dump error event log to syslog
+ *
+ */
+static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
+ u32 num_events, u32 mode)
+{
+ u32 i;
+ u32 base; /* SRAM byte address of event log header */
+ u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
+ u32 ptr; /* SRAM byte address of log data */
+ u32 ev, time, data; /* event log data */
+
+ if (num_events == 0)
+ return;
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+
+ if (mode == 0)
+ event_size = 2 * sizeof(u32);
+ else
+ event_size = 3 * sizeof(u32);
+
+ ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
+
+ /* "time" is actually "data" for mode 0 (no timestamp).
+ * place event id # at far right for easier visual parsing. */
+ for (i = 0; i < num_events; i++) {
+ ev = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ time = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ if (mode == 0) {
+ /* data, ev */
+ IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
+ } else {
+ data = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
+ time, data, ev);
+ }
+ }
+}
+
+void iwl_dump_nic_event_log(struct iwl_priv *priv)
+{
+ u32 base; /* SRAM byte address of event log header */
+ u32 capacity; /* event log capacity in # entries */
+ u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
+ u32 num_wraps; /* # times uCode wrapped to top of log */
+ u32 next_entry; /* index of next entry to be written by uCode */
+ u32 size; /* # entries that we'll print */
+
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+
+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
+ return;
+ }
+
+ /* event log header */
+ capacity = iwl_read_targ_mem(priv, base);
+ mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
+ num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
+ next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
+
+ size = num_wraps ? capacity : next_entry;
+
+ /* bail out if nothing in log */
+ if (size == 0) {
+ IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
+ return;
+ }
+
+ IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
+ size, num_wraps);
+
+ /* if uCode has wrapped back to top of log, start at the oldest entry,
+ * i.e the next one that uCode would fill. */
+ if (num_wraps)
+ iwl_print_event_log(priv, next_entry,
+ capacity - next_entry, mode);
+ /* (then/else) start at top of log */
+ iwl_print_event_log(priv, 0, next_entry, mode);
+
+}
+#endif
+
/**
* iwl_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
}
-
-static const char *desc_lookup_text[] = {
- "OK",
- "FAIL",
- "BAD_PARAM",
- "BAD_CHECKSUM",
- "NMI_INTERRUPT_WDG",
- "SYSASSERT",
- "FATAL_ERROR",
- "BAD_COMMAND",
- "HW_ERROR_TUNE_LOCK",
- "HW_ERROR_TEMPERATURE",
- "ILLEGAL_CHAN_FREQ",
- "VCC_NOT_STABLE",
- "FH_ERROR",
- "NMI_INTERRUPT_HOST",
- "NMI_INTERRUPT_ACTION_PT",
- "NMI_INTERRUPT_UNKNOWN",
- "UCODE_VERSION_MISMATCH",
- "HW_ERROR_ABS_LOCK",
- "HW_ERROR_CAL_LOCK_FAIL",
- "NMI_INTERRUPT_INST_ACTION_PT",
- "NMI_INTERRUPT_DATA_ACTION_PT",
- "NMI_TRM_HW_ER",
- "NMI_INTERRUPT_TRM",
- "NMI_INTERRUPT_BREAK_POINT"
- "DEBUG_0",
- "DEBUG_1",
- "DEBUG_2",
- "DEBUG_3",
- "UNKNOWN"
-};
-
-static const char *desc_lookup(int i)
-{
- int max = ARRAY_SIZE(desc_lookup_text) - 1;
-
- if (i < 0 || i > max)
- i = max;
-
- return desc_lookup_text[i];
-}
-
-#define ERROR_START_OFFSET (1 * sizeof(u32))
-#define ERROR_ELEM_SIZE (7 * sizeof(u32))
-
-static void iwl_dump_nic_error_log(struct iwl_priv *priv)
-{
- u32 data2, line;
- u32 desc, time, count, base, data1;
- u32 blink1, blink2, ilink1, ilink2;
-
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
-
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
- return;
- }
-
- count = iwl_read_targ_mem(priv, base);
-
- if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
- IWL_ERR(priv, "Start IWL Error Log Dump:\n");
- IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
- priv->status, count);
- }
-
- desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
- blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
- blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
- ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
- ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
- data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
- data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
- line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
- time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
-
- IWL_ERR(priv, "Desc Time "
- "data1 data2 line\n");
- IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
- desc_lookup(desc), desc, time, data1, data2, line);
- IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n");
- IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
- ilink1, ilink2);
-
-}
-
-#define EVENT_START_OFFSET (4 * sizeof(u32))
-
-/**
- * iwl_print_event_log - Dump error event log to syslog
- *
- */
-static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
- u32 num_events, u32 mode)
-{
- u32 i;
- u32 base; /* SRAM byte address of event log header */
- u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
- u32 ptr; /* SRAM byte address of log data */
- u32 ev, time, data; /* event log data */
-
- if (num_events == 0)
- return;
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
- if (mode == 0)
- event_size = 2 * sizeof(u32);
- else
- event_size = 3 * sizeof(u32);
-
- ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
- /* "time" is actually "data" for mode 0 (no timestamp).
- * place event id # at far right for easier visual parsing. */
- for (i = 0; i < num_events; i++) {
- ev = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- time = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- if (mode == 0) {
- /* data, ev */
- IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
- } else {
- data = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
- time, data, ev);
- }
- }
-}
-
-void iwl_dump_nic_event_log(struct iwl_priv *priv)
-{
- u32 base; /* SRAM byte address of event log header */
- u32 capacity; /* event log capacity in # entries */
- u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
- u32 num_wraps; /* # times uCode wrapped to top of log */
- u32 next_entry; /* index of next entry to be written by uCode */
- u32 size; /* # entries that we'll print */
-
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
- return;
- }
-
- /* event log header */
- capacity = iwl_read_targ_mem(priv, base);
- mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
- num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
- next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
- size = num_wraps ? capacity : next_entry;
-
- /* bail out if nothing in log */
- if (size == 0) {
- IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
- return;
- }
-
- IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
- size, num_wraps);
-
- /* if uCode has wrapped back to top of log, start at the oldest entry,
- * i.e the next one that uCode would fill. */
- if (num_wraps)
- iwl_print_event_log(priv, next_entry,
- capacity - next_entry, mode);
- /* (then/else) start at top of log */
- iwl_print_event_log(priv, 0, next_entry, mode);
-
-}
#endif
/**
* iwl_irq_handle_error - called for HW or SW error interrupt from card
#ifdef CONFIG_IWLWIFI_DEBUG
if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) {
- iwl_dump_nic_error_log(priv);
- iwl_dump_nic_event_log(priv);
+ priv->cfg->ops->lib->dump_nic_error_log(priv);
+ priv->cfg->ops->lib->dump_nic_event_log(priv);
iwl_print_rx_config_cmd(priv);
}
#endif
int (*is_valid_rtc_data_addr)(u32 addr);
/* 1st ucode load */
int (*load_ucode)(struct iwl_priv *priv);
+ void (*dump_nic_event_log)(struct iwl_priv *priv);
+ void (*dump_nic_error_log)(struct iwl_priv *priv);
/* power management */
struct iwl_apm_ops apm_ops;
/*****************************************************
* Error Handling Debugging
******************************************************/
+#ifdef CONFIG_IWLWIFI_DEBUG
void iwl_dump_nic_event_log(struct iwl_priv *priv);
+void iwl_dump_nic_error_log(struct iwl_priv *priv);
+#else
+static inline void iwl_dump_nic_event_log(struct iwl_priv *priv)
+{
+}
+
+static inline void iwl_dump_nic_error_log(struct iwl_priv *priv)
+{
+}
+#endif
+
void iwl_clear_isr_stats(struct iwl_priv *priv);
/*****************************************************
pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
buf_size - pos, 0);
- pos += strlen(buf);
+ pos += strlen(buf + pos);
if (buf_size - pos > 0)
buf[pos++] = '\n';
}
if (sscanf(buf, "%d", &event_log_flag) != 1)
return -EFAULT;
if (event_log_flag == 1)
- iwl_dump_nic_event_log(priv);
+ priv->cfg->ops->lib->dump_nic_event_log(priv);
return count;
}
"0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
buf + pos, bufsz - pos, 0);
- pos += strlen(buf);
+ pos += strlen(buf + pos);
if (bufsz - pos > 0)
buf[pos++] = '\n';
}
"0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
buf + pos, bufsz - pos, 0);
- pos += strlen(buf);
+ pos += strlen(buf + pos);
if (bufsz - pos > 0)
buf[pos++] = '\n';
}
pci_free_consistent(dev, priv->hw_params.tfd_size *
txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+ /* deallocate arrays */
+ kfree(txq->cmd);
+ kfree(txq->meta);
+ txq->cmd = NULL;
+ txq->meta = NULL;
+
/* 0-fill queue descriptor structure */
memset(txq, 0, sizeof(*txq));
}
tasklet_kill(&priv->irq_tasklet);
}
+#ifdef CONFIG_IWLWIFI_DEBUG
static const char *desc_lookup(int i)
{
switch (i) {
#define ERROR_START_OFFSET (1 * sizeof(u32))
#define ERROR_ELEM_SIZE (7 * sizeof(u32))
-static void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
+void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
{
u32 i;
u32 desc, time, count, base, data1;
}
}
-static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
+void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
{
u32 base; /* SRAM byte address of event log header */
u32 capacity; /* event log capacity in # entries */
iwl3945_print_event_log(priv, 0, next_entry, mode);
}
+#else
+void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
+{
+}
+
+void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
+{
+}
+
+#endif
static void iwl3945_irq_tasklet(struct iwl_priv *priv)
{
static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
-static ssize_t dump_event_log(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- char *p = (char *)buf;
-
- if (p[0] == '1')
- iwl3945_dump_nic_event_log(priv);
-
- return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
-
/*****************************************************************************
*
* driver setup and tear down
&dev_attr_antenna.attr,
&dev_attr_channels.attr,
&dev_attr_dump_errors.attr,
- &dev_attr_dump_events.attr,
&dev_attr_flags.attr,
&dev_attr_filter_flags.attr,
#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
tristate "Au1x00 pcmcia support"
depends on SOC_AU1X00 && PCMCIA
+config PCMCIA_BCM63XX
+ tristate "bcm63xx pcmcia support"
+ depends on BCM63XX && PCMCIA
+
config PCMCIA_SA1100
tristate "SA1100 support"
depends on ARM && ARCH_SA1100 && PCMCIA
obj-$(CONFIG_M32R_PCC) += m32r_pcc.o
obj-$(CONFIG_M32R_CFC) += m32r_cfc.o
obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o
+obj-$(CONFIG_PCMCIA_BCM63XX) += bcm63xx_pcmcia.o
obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o
obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o
obj-$(CONFIG_OMAP_CF) += omap_cf.o
struct at91_cf_socket *cf = platform_get_drvdata(pdev);
struct at91_cf_data *board = cf->board;
- pcmcia_socket_dev_suspend(&pdev->dev, mesg);
+ pcmcia_socket_dev_suspend(&pdev->dev);
if (device_may_wakeup(&pdev->dev)) {
enable_irq_wake(board->det_pin);
if (board->irq_pin)
static int au1x00_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int au1x00_drv_pcmcia_resume(struct platform_device *dev)
--- /dev/null
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/timer.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/gpio.h>
+
+#include <bcm63xx_regs.h>
+#include <bcm63xx_io.h>
+#include "bcm63xx_pcmcia.h"
+
+#define PFX "bcm63xx_pcmcia: "
+
+#ifdef CONFIG_CARDBUS
+/* if cardbus is used, platform device needs reference to actual pci
+ * device */
+static struct pci_dev *bcm63xx_cb_dev;
+#endif
+
+/*
+ * read/write helper for pcmcia regs
+ */
+static inline u32 pcmcia_readl(struct bcm63xx_pcmcia_socket *skt, u32 off)
+{
+ return bcm_readl(skt->base + off);
+}
+
+static inline void pcmcia_writel(struct bcm63xx_pcmcia_socket *skt,
+ u32 val, u32 off)
+{
+ bcm_writel(val, skt->base + off);
+}
+
+/*
+ * This callback should (re-)initialise the socket, turn on status
+ * interrupts and PCMCIA bus, and wait for power to stabilise so that
+ * the card status signals report correctly.
+ *
+ * Hardware cannot do that.
+ */
+static int bcm63xx_pcmcia_sock_init(struct pcmcia_socket *sock)
+{
+ return 0;
+}
+
+/*
+ * This callback should remove power on the socket, disable IRQs from
+ * the card, turn off status interrupts, and disable the PCMCIA bus.
+ *
+ * Hardware cannot do that.
+ */
+static int bcm63xx_pcmcia_suspend(struct pcmcia_socket *sock)
+{
+ return 0;
+}
+
+/*
+ * Implements the set_socket() operation for the in-kernel PCMCIA
+ * service (formerly SS_SetSocket in Card Services). We more or
+ * less punt all of this work and let the kernel handle the details
+ * of power configuration, reset, &c. We also record the value of
+ * `state' in order to regurgitate it to the PCMCIA core later.
+ */
+static int bcm63xx_pcmcia_set_socket(struct pcmcia_socket *sock,
+ socket_state_t *state)
+{
+ struct bcm63xx_pcmcia_socket *skt;
+ unsigned long flags;
+ u32 val;
+
+ skt = sock->driver_data;
+
+ spin_lock_irqsave(&skt->lock, flags);
+
+ /* note: hardware cannot control socket power, so we will
+ * always report SS_POWERON */
+
+ /* apply socket reset */
+ val = pcmcia_readl(skt, PCMCIA_C1_REG);
+ if (state->flags & SS_RESET)
+ val |= PCMCIA_C1_RESET_MASK;
+ else
+ val &= ~PCMCIA_C1_RESET_MASK;
+
+ /* reverse reset logic for cardbus card */
+ if (skt->card_detected && (skt->card_type & CARD_CARDBUS))
+ val ^= PCMCIA_C1_RESET_MASK;
+
+ pcmcia_writel(skt, val, PCMCIA_C1_REG);
+
+ /* keep requested state for event reporting */
+ skt->requested_state = *state;
+
+ spin_unlock_irqrestore(&skt->lock, flags);
+
+ return 0;
+}
+
+/*
+ * identity cardtype from VS[12] input, CD[12] input while only VS2 is
+ * floating, and CD[12] input while only VS1 is floating
+ */
+enum {
+ IN_VS1 = (1 << 0),
+ IN_VS2 = (1 << 1),
+ IN_CD1_VS2H = (1 << 2),
+ IN_CD2_VS2H = (1 << 3),
+ IN_CD1_VS1H = (1 << 4),
+ IN_CD2_VS1H = (1 << 5),
+};
+
+static const u8 vscd_to_cardtype[] = {
+
+ /* VS1 float, VS2 float */
+ [IN_VS1 | IN_VS2] = (CARD_PCCARD | CARD_5V),
+
+ /* VS1 grounded, VS2 float */
+ [IN_VS2] = (CARD_PCCARD | CARD_5V | CARD_3V),
+
+ /* VS1 grounded, VS2 grounded */
+ [0] = (CARD_PCCARD | CARD_5V | CARD_3V | CARD_XV),
+
+ /* VS1 tied to CD1, VS2 float */
+ [IN_VS1 | IN_VS2 | IN_CD1_VS1H] = (CARD_CARDBUS | CARD_3V),
+
+ /* VS1 grounded, VS2 tied to CD2 */
+ [IN_VS2 | IN_CD2_VS2H] = (CARD_CARDBUS | CARD_3V | CARD_XV),
+
+ /* VS1 tied to CD2, VS2 grounded */
+ [IN_VS1 | IN_CD2_VS1H] = (CARD_CARDBUS | CARD_3V | CARD_XV | CARD_YV),
+
+ /* VS1 float, VS2 grounded */
+ [IN_VS1] = (CARD_PCCARD | CARD_XV),
+
+ /* VS1 float, VS2 tied to CD2 */
+ [IN_VS1 | IN_VS2 | IN_CD2_VS2H] = (CARD_CARDBUS | CARD_3V),
+
+ /* VS1 float, VS2 tied to CD1 */
+ [IN_VS1 | IN_VS2 | IN_CD1_VS2H] = (CARD_CARDBUS | CARD_XV | CARD_YV),
+
+ /* VS1 tied to CD2, VS2 float */
+ [IN_VS1 | IN_VS2 | IN_CD2_VS1H] = (CARD_CARDBUS | CARD_YV),
+
+ /* VS2 grounded, VS1 is tied to CD1, CD2 is grounded */
+ [IN_VS1 | IN_CD1_VS1H] = 0, /* ignore cardbay */
+};
+
+/*
+ * poll hardware to check card insertion status
+ */
+static unsigned int __get_socket_status(struct bcm63xx_pcmcia_socket *skt)
+{
+ unsigned int stat;
+ u32 val;
+
+ stat = 0;
+
+ /* check CD for card presence */
+ val = pcmcia_readl(skt, PCMCIA_C1_REG);
+
+ if (!(val & PCMCIA_C1_CD1_MASK) && !(val & PCMCIA_C1_CD2_MASK))
+ stat |= SS_DETECT;
+
+ /* if new insertion, detect cardtype */
+ if ((stat & SS_DETECT) && !skt->card_detected) {
+ unsigned int stat = 0;
+
+ /* float VS1, float VS2 */
+ val |= PCMCIA_C1_VS1OE_MASK;
+ val |= PCMCIA_C1_VS2OE_MASK;
+ pcmcia_writel(skt, val, PCMCIA_C1_REG);
+
+ /* wait for output to stabilize and read VS[12] */
+ udelay(10);
+ val = pcmcia_readl(skt, PCMCIA_C1_REG);
+ stat |= (val & PCMCIA_C1_VS1_MASK) ? IN_VS1 : 0;
+ stat |= (val & PCMCIA_C1_VS2_MASK) ? IN_VS2 : 0;
+
+ /* drive VS1 low, float VS2 */
+ val &= ~PCMCIA_C1_VS1OE_MASK;
+ val |= PCMCIA_C1_VS2OE_MASK;
+ pcmcia_writel(skt, val, PCMCIA_C1_REG);
+
+ /* wait for output to stabilize and read CD[12] */
+ udelay(10);
+ val = pcmcia_readl(skt, PCMCIA_C1_REG);
+ stat |= (val & PCMCIA_C1_CD1_MASK) ? IN_CD1_VS2H : 0;
+ stat |= (val & PCMCIA_C1_CD2_MASK) ? IN_CD2_VS2H : 0;
+
+ /* float VS1, drive VS2 low */
+ val |= PCMCIA_C1_VS1OE_MASK;
+ val &= ~PCMCIA_C1_VS2OE_MASK;
+ pcmcia_writel(skt, val, PCMCIA_C1_REG);
+
+ /* wait for output to stabilize and read CD[12] */
+ udelay(10);
+ val = pcmcia_readl(skt, PCMCIA_C1_REG);
+ stat |= (val & PCMCIA_C1_CD1_MASK) ? IN_CD1_VS1H : 0;
+ stat |= (val & PCMCIA_C1_CD2_MASK) ? IN_CD2_VS1H : 0;
+
+ /* guess cardtype from all this */
+ skt->card_type = vscd_to_cardtype[stat];
+ if (!skt->card_type)
+ dev_err(&skt->socket.dev, "unsupported card type\n");
+
+ /* drive both VS pin to 0 again */
+ val &= ~(PCMCIA_C1_VS1OE_MASK | PCMCIA_C1_VS2OE_MASK);
+
+ /* enable correct logic */
+ val &= ~(PCMCIA_C1_EN_PCMCIA_MASK | PCMCIA_C1_EN_CARDBUS_MASK);
+ if (skt->card_type & CARD_PCCARD)
+ val |= PCMCIA_C1_EN_PCMCIA_MASK;
+ else
+ val |= PCMCIA_C1_EN_CARDBUS_MASK;
+
+ pcmcia_writel(skt, val, PCMCIA_C1_REG);
+ }
+ skt->card_detected = (stat & SS_DETECT) ? 1 : 0;
+
+ /* report card type/voltage */
+ if (skt->card_type & CARD_CARDBUS)
+ stat |= SS_CARDBUS;
+ if (skt->card_type & CARD_3V)
+ stat |= SS_3VCARD;
+ if (skt->card_type & CARD_XV)
+ stat |= SS_XVCARD;
+ stat |= SS_POWERON;
+
+ if (gpio_get_value(skt->pd->ready_gpio))
+ stat |= SS_READY;
+
+ return stat;
+}
+
+/*
+ * core request to get current socket status
+ */
+static int bcm63xx_pcmcia_get_status(struct pcmcia_socket *sock,
+ unsigned int *status)
+{
+ struct bcm63xx_pcmcia_socket *skt;
+
+ skt = sock->driver_data;
+
+ spin_lock_bh(&skt->lock);
+ *status = __get_socket_status(skt);
+ spin_unlock_bh(&skt->lock);
+
+ return 0;
+}
+
+/*
+ * socket polling timer callback
+ */
+static void bcm63xx_pcmcia_poll(unsigned long data)
+{
+ struct bcm63xx_pcmcia_socket *skt;
+ unsigned int stat, events;
+
+ skt = (struct bcm63xx_pcmcia_socket *)data;
+
+ spin_lock_bh(&skt->lock);
+
+ stat = __get_socket_status(skt);
+
+ /* keep only changed bits, and mask with required one from the
+ * core */
+ events = (stat ^ skt->old_status) & skt->requested_state.csc_mask;
+ skt->old_status = stat;
+ spin_unlock_bh(&skt->lock);
+
+ if (events)
+ pcmcia_parse_events(&skt->socket, events);
+
+ mod_timer(&skt->timer,
+ jiffies + msecs_to_jiffies(BCM63XX_PCMCIA_POLL_RATE));
+}
+
+static int bcm63xx_pcmcia_set_io_map(struct pcmcia_socket *sock,
+ struct pccard_io_map *map)
+{
+ /* this doesn't seem to be called by pcmcia layer if static
+ * mapping is used */
+ return 0;
+}
+
+static int bcm63xx_pcmcia_set_mem_map(struct pcmcia_socket *sock,
+ struct pccard_mem_map *map)
+{
+ struct bcm63xx_pcmcia_socket *skt;
+ struct resource *res;
+
+ skt = sock->driver_data;
+ if (map->flags & MAP_ATTRIB)
+ res = skt->attr_res;
+ else
+ res = skt->common_res;
+
+ map->static_start = res->start + map->card_start;
+ return 0;
+}
+
+static struct pccard_operations bcm63xx_pcmcia_operations = {
+ .init = bcm63xx_pcmcia_sock_init,
+ .suspend = bcm63xx_pcmcia_suspend,
+ .get_status = bcm63xx_pcmcia_get_status,
+ .set_socket = bcm63xx_pcmcia_set_socket,
+ .set_io_map = bcm63xx_pcmcia_set_io_map,
+ .set_mem_map = bcm63xx_pcmcia_set_mem_map,
+};
+
+/*
+ * register pcmcia socket to core
+ */
+static int __devinit bcm63xx_drv_pcmcia_probe(struct platform_device *pdev)
+{
+ struct bcm63xx_pcmcia_socket *skt;
+ struct pcmcia_socket *sock;
+ struct resource *res, *irq_res;
+ unsigned int regmem_size = 0, iomem_size = 0;
+ u32 val;
+ int ret;
+
+ skt = kzalloc(sizeof(*skt), GFP_KERNEL);
+ if (!skt)
+ return -ENOMEM;
+ spin_lock_init(&skt->lock);
+ sock = &skt->socket;
+ sock->driver_data = skt;
+
+ /* make sure we have all resources we need */
+ skt->common_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ skt->attr_res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ skt->pd = pdev->dev.platform_data;
+ if (!skt->common_res || !skt->attr_res || !irq_res || !skt->pd) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* remap pcmcia registers */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ regmem_size = resource_size(res);
+ if (!request_mem_region(res->start, regmem_size, "bcm63xx_pcmcia")) {
+ ret = -EINVAL;
+ goto err;
+ }
+ skt->reg_res = res;
+
+ skt->base = ioremap(res->start, regmem_size);
+ if (!skt->base) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* remap io registers */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+ iomem_size = resource_size(res);
+ skt->io_base = ioremap(res->start, iomem_size);
+ if (!skt->io_base) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* resources are static */
+ sock->resource_ops = &pccard_static_ops;
+ sock->ops = &bcm63xx_pcmcia_operations;
+ sock->owner = THIS_MODULE;
+ sock->dev.parent = &pdev->dev;
+ sock->features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD;
+ sock->io_offset = (unsigned long)skt->io_base;
+ sock->pci_irq = irq_res->start;
+
+#ifdef CONFIG_CARDBUS
+ sock->cb_dev = bcm63xx_cb_dev;
+ if (bcm63xx_cb_dev)
+ sock->features |= SS_CAP_CARDBUS;
+#endif
+
+ /* assume common & attribute memory have the same size */
+ sock->map_size = resource_size(skt->common_res);
+
+ /* initialize polling timer */
+ setup_timer(&skt->timer, bcm63xx_pcmcia_poll, (unsigned long)skt);
+
+ /* initialize pcmcia control register, drive VS[12] to 0,
+ * leave CB IDSEL to the old value since it is set by the PCI
+ * layer */
+ val = pcmcia_readl(skt, PCMCIA_C1_REG);
+ val &= PCMCIA_C1_CBIDSEL_MASK;
+ val |= PCMCIA_C1_EN_PCMCIA_GPIO_MASK;
+ pcmcia_writel(skt, val, PCMCIA_C1_REG);
+
+ /*
+ * Hardware has only one set of timings registers, not one for
+ * each memory access type, so we configure them for the
+ * slowest one: attribute memory.
+ */
+ val = PCMCIA_C2_DATA16_MASK;
+ val |= 10 << PCMCIA_C2_RWCOUNT_SHIFT;
+ val |= 6 << PCMCIA_C2_INACTIVE_SHIFT;
+ val |= 3 << PCMCIA_C2_SETUP_SHIFT;
+ val |= 3 << PCMCIA_C2_HOLD_SHIFT;
+ pcmcia_writel(skt, val, PCMCIA_C2_REG);
+
+ ret = pcmcia_register_socket(sock);
+ if (ret)
+ goto err;
+
+ /* start polling socket */
+ mod_timer(&skt->timer,
+ jiffies + msecs_to_jiffies(BCM63XX_PCMCIA_POLL_RATE));
+
+ platform_set_drvdata(pdev, skt);
+ return 0;
+
+err:
+ if (skt->io_base)
+ iounmap(skt->io_base);
+ if (skt->base)
+ iounmap(skt->base);
+ if (skt->reg_res)
+ release_mem_region(skt->reg_res->start, regmem_size);
+ kfree(skt);
+ return ret;
+}
+
+static int __devexit bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
+{
+ struct bcm63xx_pcmcia_socket *skt;
+ struct resource *res;
+
+ skt = platform_get_drvdata(pdev);
+ del_timer_sync(&skt->timer);
+ iounmap(skt->base);
+ iounmap(skt->io_base);
+ res = skt->reg_res;
+ release_mem_region(res->start, resource_size(res));
+ kfree(skt);
+ return 0;
+}
+
+struct platform_driver bcm63xx_pcmcia_driver = {
+ .probe = bcm63xx_drv_pcmcia_probe,
+ .remove = __devexit_p(bcm63xx_drv_pcmcia_remove),
+ .driver = {
+ .name = "bcm63xx_pcmcia",
+ .owner = THIS_MODULE,
+ },
+};
+
+#ifdef CONFIG_CARDBUS
+static int __devinit bcm63xx_cb_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ /* keep pci device */
+ bcm63xx_cb_dev = dev;
+ return platform_driver_register(&bcm63xx_pcmcia_driver);
+}
+
+static void __devexit bcm63xx_cb_exit(struct pci_dev *dev)
+{
+ platform_driver_unregister(&bcm63xx_pcmcia_driver);
+ bcm63xx_cb_dev = NULL;
+}
+
+static struct pci_device_id bcm63xx_cb_table[] = {
+ {
+ .vendor = PCI_VENDOR_ID_BROADCOM,
+ .device = BCM6348_CPU_ID,
+ .subvendor = PCI_VENDOR_ID_BROADCOM,
+ .subdevice = PCI_ANY_ID,
+ .class = PCI_CLASS_BRIDGE_CARDBUS << 8,
+ .class_mask = ~0,
+ },
+
+ {
+ .vendor = PCI_VENDOR_ID_BROADCOM,
+ .device = BCM6358_CPU_ID,
+ .subvendor = PCI_VENDOR_ID_BROADCOM,
+ .subdevice = PCI_ANY_ID,
+ .class = PCI_CLASS_BRIDGE_CARDBUS << 8,
+ .class_mask = ~0,
+ },
+
+ { },
+};
+
+MODULE_DEVICE_TABLE(pci, bcm63xx_cb_table);
+
+static struct pci_driver bcm63xx_cardbus_driver = {
+ .name = "bcm63xx_cardbus",
+ .id_table = bcm63xx_cb_table,
+ .probe = bcm63xx_cb_probe,
+ .remove = __devexit_p(bcm63xx_cb_exit),
+};
+#endif
+
+/*
+ * if cardbus support is enabled, register our platform device after
+ * our fake cardbus bridge has been registered
+ */
+static int __init bcm63xx_pcmcia_init(void)
+{
+#ifdef CONFIG_CARDBUS
+ return pci_register_driver(&bcm63xx_cardbus_driver);
+#else
+ return platform_driver_register(&bcm63xx_pcmcia_driver);
+#endif
+}
+
+static void __exit bcm63xx_pcmcia_exit(void)
+{
+#ifdef CONFIG_CARDBUS
+ return pci_unregister_driver(&bcm63xx_cardbus_driver);
+#else
+ platform_driver_unregister(&bcm63xx_pcmcia_driver);
+#endif
+}
+
+module_init(bcm63xx_pcmcia_init);
+module_exit(bcm63xx_pcmcia_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>");
+MODULE_DESCRIPTION("Linux PCMCIA Card Services: bcm63xx Socket Controller");
--- /dev/null
+#ifndef BCM63XX_PCMCIA_H_
+#define BCM63XX_PCMCIA_H_
+
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <pcmcia/ss.h>
+#include <bcm63xx_dev_pcmcia.h>
+
+/* socket polling rate in ms */
+#define BCM63XX_PCMCIA_POLL_RATE 500
+
+enum {
+ CARD_CARDBUS = (1 << 0),
+ CARD_PCCARD = (1 << 1),
+ CARD_5V = (1 << 2),
+ CARD_3V = (1 << 3),
+ CARD_XV = (1 << 4),
+ CARD_YV = (1 << 5),
+};
+
+struct bcm63xx_pcmcia_socket {
+ struct pcmcia_socket socket;
+
+ /* platform specific data */
+ struct bcm63xx_pcmcia_platform_data *pd;
+
+ /* all regs access are protected by this spinlock */
+ spinlock_t lock;
+
+ /* pcmcia registers resource */
+ struct resource *reg_res;
+
+ /* base remapped address of registers */
+ void __iomem *base;
+
+ /* whether a card is detected at the moment */
+ int card_detected;
+
+ /* type of detected card (mask of above enum) */
+ u8 card_type;
+
+ /* keep last socket status to implement event reporting */
+ unsigned int old_status;
+
+ /* backup of requested socket state */
+ socket_state_t requested_state;
+
+ /* timer used for socket status polling */
+ struct timer_list timer;
+
+ /* attribute/common memory resources */
+ struct resource *attr_res;
+ struct resource *common_res;
+ struct resource *io_res;
+
+ /* base address of io memory */
+ void __iomem *io_base;
+};
+
+#endif /* BCM63XX_PCMCIA_H_ */
static int bfin_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
{
- return pcmcia_socket_dev_suspend(&pdev->dev, mesg);
+ return pcmcia_socket_dev_suspend(&pdev->dev);
}
static int bfin_cf_resume(struct platform_device *pdev)
static int socket_resume(struct pcmcia_socket *skt);
static int socket_suspend(struct pcmcia_socket *skt);
-int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state)
+int pcmcia_socket_dev_suspend(struct device *dev)
{
struct pcmcia_socket *socket;
#ifdef CONFIG_PM
static int i82092aa_socket_suspend (struct pci_dev *dev, pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int i82092aa_socket_resume (struct pci_dev *dev)
static int i82365_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int i82365_drv_pcmcia_resume(struct platform_device *dev)
static int cfc_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int cfc_drv_pcmcia_resume(struct platform_device *dev)
static int pcc_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int pcc_drv_pcmcia_resume(struct platform_device *dev)
#ifdef CONFIG_PM
static int m8xx_suspend(struct platform_device *pdev, pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&pdev->dev, state);
+ return pcmcia_socket_dev_suspend(&pdev->dev);
}
static int m8xx_resume(struct platform_device *pdev)
static int omap_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
{
- return pcmcia_socket_dev_suspend(&pdev->dev, mesg);
+ return pcmcia_socket_dev_suspend(&pdev->dev);
}
static int omap_cf_resume(struct platform_device *pdev)
#ifdef CONFIG_PM
static int pd6729_socket_suspend(struct pci_dev *dev, pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int pd6729_socket_resume(struct pci_dev *dev)
static int pxa2xx_drv_pcmcia_suspend(struct device *dev)
{
- return pcmcia_socket_dev_suspend(dev, PMSG_SUSPEND);
+ return pcmcia_socket_dev_suspend(dev);
}
static int pxa2xx_drv_pcmcia_resume(struct device *dev)
static int sa11x0_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int sa11x0_drv_pcmcia_resume(struct platform_device *dev)
static int pcmcia_suspend(struct sa1111_dev *dev, pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int pcmcia_resume(struct sa1111_dev *dev)
static int tcic_drv_pcmcia_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int tcic_drv_pcmcia_resume(struct platform_device *dev)
static int vrc4171_card_suspend(struct platform_device *dev,
pm_message_t state)
{
- return pcmcia_socket_dev_suspend(&dev->dev, state);
+ return pcmcia_socket_dev_suspend(&dev->dev);
}
static int vrc4171_card_resume(struct platform_device *dev)
}
#ifdef CONFIG_PM
-static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state)
+static int yenta_dev_suspend_noirq(struct device *dev)
{
- struct yenta_socket *socket = pci_get_drvdata(dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct yenta_socket *socket = pci_get_drvdata(pdev);
int ret;
- ret = pcmcia_socket_dev_suspend(&dev->dev, state);
+ ret = pcmcia_socket_dev_suspend(dev);
- if (socket) {
- if (socket->type && socket->type->save_state)
- socket->type->save_state(socket);
+ if (!socket)
+ return ret;
- /* FIXME: pci_save_state needs to have a better interface */
- pci_save_state(dev);
- pci_read_config_dword(dev, 16*4, &socket->saved_state[0]);
- pci_read_config_dword(dev, 17*4, &socket->saved_state[1]);
- pci_disable_device(dev);
+ if (socket->type && socket->type->save_state)
+ socket->type->save_state(socket);
- /*
- * Some laptops (IBM T22) do not like us putting the Cardbus
- * bridge into D3. At a guess, some other laptop will
- * probably require this, so leave it commented out for now.
- */
- /* pci_set_power_state(dev, 3); */
- }
+ pci_save_state(pdev);
+ pci_read_config_dword(pdev, 16*4, &socket->saved_state[0]);
+ pci_read_config_dword(pdev, 17*4, &socket->saved_state[1]);
+ pci_disable_device(pdev);
+
+ /*
+ * Some laptops (IBM T22) do not like us putting the Cardbus
+ * bridge into D3. At a guess, some other laptop will
+ * probably require this, so leave it commented out for now.
+ */
+ /* pci_set_power_state(dev, 3); */
return ret;
}
-
-static int yenta_dev_resume (struct pci_dev *dev)
+static int yenta_dev_resume_noirq(struct device *dev)
{
- struct yenta_socket *socket = pci_get_drvdata(dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct yenta_socket *socket = pci_get_drvdata(pdev);
+ int ret;
- if (socket) {
- int rc;
+ if (!socket)
+ return 0;
- pci_set_power_state(dev, 0);
- /* FIXME: pci_restore_state needs to have a better interface */
- pci_restore_state(dev);
- pci_write_config_dword(dev, 16*4, socket->saved_state[0]);
- pci_write_config_dword(dev, 17*4, socket->saved_state[1]);
+ pci_write_config_dword(pdev, 16*4, socket->saved_state[0]);
+ pci_write_config_dword(pdev, 17*4, socket->saved_state[1]);
- rc = pci_enable_device(dev);
- if (rc)
- return rc;
+ ret = pci_enable_device(pdev);
+ if (ret)
+ return ret;
- pci_set_master(dev);
+ pci_set_master(pdev);
- if (socket->type && socket->type->restore_state)
- socket->type->restore_state(socket);
- }
+ if (socket->type && socket->type->restore_state)
+ socket->type->restore_state(socket);
- return pcmcia_socket_dev_resume(&dev->dev);
+ return pcmcia_socket_dev_resume(dev);
}
+
+static struct dev_pm_ops yenta_pm_ops = {
+ .suspend_noirq = yenta_dev_suspend_noirq,
+ .resume_noirq = yenta_dev_resume_noirq,
+ .freeze_noirq = yenta_dev_suspend_noirq,
+ .thaw_noirq = yenta_dev_resume_noirq,
+ .poweroff_noirq = yenta_dev_suspend_noirq,
+ .restore_noirq = yenta_dev_resume_noirq,
+};
+
+#define YENTA_PM_OPS (¥ta_pm_ops)
+#else
+#define YENTA_PM_OPS NULL
#endif
#define CB_ID(vend,dev,type) \
.id_table = yenta_table,
.probe = yenta_probe,
.remove = __devexit_p(yenta_close),
-#ifdef CONFIG_PM
- .suspend = yenta_dev_suspend,
- .resume = yenta_dev_resume,
-#endif
+ .driver.pm = YENTA_PM_OPS,
};
sony_backlight_update_status(sony_backlight_device) < 0)
printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n");
+ /* re-read rfkill state */
+ sony_nc_rfkill_update();
+
return 0;
}
struct rfkill *rfk;
enum rfkill_type type;
const char *name;
+ int result;
+ bool hwblock;
switch (nc_type) {
case SONY_WIFI:
if (!rfk)
return -ENOMEM;
+ sony_call_snc_handle(0x124, 0x200, &result);
+ hwblock = !(result & 0x1);
+ rfkill_set_hw_state(rfk, hwblock);
+
err = rfkill_register(rfk);
if (err) {
rfkill_destroy(rfk);
filp->f_path.dentry->d_inode->i_private);
}
-static struct file_operations debugfs_fops = {
+static const struct file_operations debugfs_fops = {
.owner = THIS_MODULE,
.open = qstat_seq_open,
.read = seq_read,
return single_open(filp, qdio_perf_proc_show, NULL);
}
-static struct file_operations qdio_perf_proc_fops = {
+static const struct file_operations qdio_perf_proc_fops = {
.owner = THIS_MODULE,
.open = qdio_perf_seq_open,
.read = seq_read,
}
}
-static struct file_operations sg_fops = {
+static const struct file_operations sg_fops = {
.owner = THIS_MODULE,
.read = sg_read,
.write = sg_write,
static int sg_proc_single_open_adio(struct inode *inode, struct file *file);
static ssize_t sg_proc_write_adio(struct file *filp, const char __user *buffer,
size_t count, loff_t *off);
-static struct file_operations adio_fops = {
- /* .owner, .read and .llseek added in sg_proc_init() */
+static const struct file_operations adio_fops = {
+ .owner = THIS_MODULE,
.open = sg_proc_single_open_adio,
+ .read = seq_read,
+ .llseek = seq_lseek,
.write = sg_proc_write_adio,
.release = single_release,
};
static int sg_proc_single_open_dressz(struct inode *inode, struct file *file);
static ssize_t sg_proc_write_dressz(struct file *filp,
const char __user *buffer, size_t count, loff_t *off);
-static struct file_operations dressz_fops = {
+static const struct file_operations dressz_fops = {
+ .owner = THIS_MODULE,
.open = sg_proc_single_open_dressz,
+ .read = seq_read,
+ .llseek = seq_lseek,
.write = sg_proc_write_dressz,
.release = single_release,
};
static int sg_proc_seq_show_version(struct seq_file *s, void *v);
static int sg_proc_single_open_version(struct inode *inode, struct file *file);
-static struct file_operations version_fops = {
+static const struct file_operations version_fops = {
+ .owner = THIS_MODULE,
.open = sg_proc_single_open_version,
+ .read = seq_read,
+ .llseek = seq_lseek,
.release = single_release,
};
static int sg_proc_seq_show_devhdr(struct seq_file *s, void *v);
static int sg_proc_single_open_devhdr(struct inode *inode, struct file *file);
-static struct file_operations devhdr_fops = {
+static const struct file_operations devhdr_fops = {
+ .owner = THIS_MODULE,
.open = sg_proc_single_open_devhdr,
+ .read = seq_read,
+ .llseek = seq_lseek,
.release = single_release,
};
static void * dev_seq_start(struct seq_file *s, loff_t *pos);
static void * dev_seq_next(struct seq_file *s, void *v, loff_t *pos);
static void dev_seq_stop(struct seq_file *s, void *v);
-static struct file_operations dev_fops = {
+static const struct file_operations dev_fops = {
+ .owner = THIS_MODULE,
.open = sg_proc_open_dev,
+ .read = seq_read,
+ .llseek = seq_lseek,
.release = seq_release,
};
static const struct seq_operations dev_seq_ops = {
static int sg_proc_seq_show_devstrs(struct seq_file *s, void *v);
static int sg_proc_open_devstrs(struct inode *inode, struct file *file);
-static struct file_operations devstrs_fops = {
+static const struct file_operations devstrs_fops = {
+ .owner = THIS_MODULE,
.open = sg_proc_open_devstrs,
+ .read = seq_read,
+ .llseek = seq_lseek,
.release = seq_release,
};
static const struct seq_operations devstrs_seq_ops = {
static int sg_proc_seq_show_debug(struct seq_file *s, void *v);
static int sg_proc_open_debug(struct inode *inode, struct file *file);
-static struct file_operations debug_fops = {
+static const struct file_operations debug_fops = {
+ .owner = THIS_MODULE,
.open = sg_proc_open_debug,
+ .read = seq_read,
+ .llseek = seq_lseek,
.release = seq_release,
};
static const struct seq_operations debug_seq_ops = {
struct sg_proc_leaf {
const char * name;
- struct file_operations * fops;
+ const struct file_operations * fops;
};
static struct sg_proc_leaf sg_proc_leaf_arr[] = {
for (k = 0; k < num_leaves; ++k) {
leaf = &sg_proc_leaf_arr[k];
mask = leaf->fops->write ? S_IRUGO | S_IWUSR : S_IRUGO;
- leaf->fops->owner = THIS_MODULE;
- leaf->fops->read = seq_read;
- leaf->fops->llseek = seq_lseek;
proc_create(leaf->name, mask, sg_proc_sgp, leaf->fops);
}
return 0;
return (serial8250_reg.minor - 64) + port->line;
}
+static unsigned int skip_txen_test; /* force skip of txen test at init time */
+
/*
* Debugging.
*/
is variable. So, let's just don't test if we receive
TX irq. This way, we'll never enable UART_BUG_TXEN.
*/
- if (up->port.flags & UPF_NO_TXEN_TEST)
+ if (skip_txen_test || up->port.flags & UPF_NO_TXEN_TEST)
goto dont_test_tx_en;
/*
module_param(nr_uarts, uint, 0644);
MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")");
+module_param(skip_txen_test, uint, 0644);
+MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time");
+
#ifdef CONFIG_SERIAL_8250_RSA
module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
config SERIAL_UARTLITE
tristate "Xilinx uartlite serial port support"
- depends on PPC32 || MICROBLAZE
+ depends on PPC32 || MICROBLAZE || MFD_TIMBERDALE
select SERIAL_CORE
help
Say Y here if you want to use the Xilinx uartlite serial controller.
---help---
Add support for UART controller on timberdale.
+config SERIAL_BCM63XX
+ tristate "bcm63xx serial port support"
+ select SERIAL_CORE
+ depends on BCM63XX
+ help
+ If you have a bcm63xx CPU, you can enable its onboard
+ serial port by enabling this options.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bcm963xx_uart.
+
+config SERIAL_BCM63XX_CONSOLE
+ bool "Console on bcm63xx serial port"
+ depends on SERIAL_BCM63XX=y
+ select SERIAL_CORE_CONSOLE
+ help
+ If you have enabled the serial port on the bcm63xx CPU
+ you can make it the console by answering Y to this option.
+
endmenu
obj-$(CONFIG_SERIAL_PXA) += pxa.o
obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
+obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
obj-$(CONFIG_SERIAL_BFIN) += bfin_5xx.o
obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o
obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
--- /dev/null
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Derived from many drivers using generic_serial interface.
+ *
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ *
+ * Serial driver for BCM63xx integrated UART.
+ *
+ * Hardware flow control was _not_ tested since I only have RX/TX on
+ * my board.
+ */
+
+#if defined(CONFIG_SERIAL_BCM63XX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/clk.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/sysrq.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <bcm63xx_clk.h>
+#include <bcm63xx_irq.h>
+#include <bcm63xx_regs.h>
+#include <bcm63xx_io.h>
+
+#define BCM63XX_NR_UARTS 1
+
+static struct uart_port ports[BCM63XX_NR_UARTS];
+
+/*
+ * rx interrupt mask / stat
+ *
+ * mask:
+ * - rx fifo full
+ * - rx fifo above threshold
+ * - rx fifo not empty for too long
+ */
+#define UART_RX_INT_MASK (UART_IR_MASK(UART_IR_RXOVER) | \
+ UART_IR_MASK(UART_IR_RXTHRESH) | \
+ UART_IR_MASK(UART_IR_RXTIMEOUT))
+
+#define UART_RX_INT_STAT (UART_IR_STAT(UART_IR_RXOVER) | \
+ UART_IR_STAT(UART_IR_RXTHRESH) | \
+ UART_IR_STAT(UART_IR_RXTIMEOUT))
+
+/*
+ * tx interrupt mask / stat
+ *
+ * mask:
+ * - tx fifo empty
+ * - tx fifo below threshold
+ */
+#define UART_TX_INT_MASK (UART_IR_MASK(UART_IR_TXEMPTY) | \
+ UART_IR_MASK(UART_IR_TXTRESH))
+
+#define UART_TX_INT_STAT (UART_IR_STAT(UART_IR_TXEMPTY) | \
+ UART_IR_STAT(UART_IR_TXTRESH))
+
+/*
+ * external input interrupt
+ *
+ * mask: any edge on CTS, DCD
+ */
+#define UART_EXTINP_INT_MASK (UART_EXTINP_IRMASK(UART_EXTINP_IR_CTS) | \
+ UART_EXTINP_IRMASK(UART_EXTINP_IR_DCD))
+
+/*
+ * handy uart register accessor
+ */
+static inline unsigned int bcm_uart_readl(struct uart_port *port,
+ unsigned int offset)
+{
+ return bcm_readl(port->membase + offset);
+}
+
+static inline void bcm_uart_writel(struct uart_port *port,
+ unsigned int value, unsigned int offset)
+{
+ bcm_writel(value, port->membase + offset);
+}
+
+/*
+ * serial core request to check if uart tx fifo is empty
+ */
+static unsigned int bcm_uart_tx_empty(struct uart_port *port)
+{
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_IR_REG);
+ return (val & UART_IR_STAT(UART_IR_TXEMPTY)) ? 1 : 0;
+}
+
+/*
+ * serial core request to set RTS and DTR pin state and loopback mode
+ */
+static void bcm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_MCTL_REG);
+ val &= ~(UART_MCTL_DTR_MASK | UART_MCTL_RTS_MASK);
+ /* invert of written value is reflected on the pin */
+ if (!(mctrl & TIOCM_DTR))
+ val |= UART_MCTL_DTR_MASK;
+ if (!(mctrl & TIOCM_RTS))
+ val |= UART_MCTL_RTS_MASK;
+ bcm_uart_writel(port, val, UART_MCTL_REG);
+
+ val = bcm_uart_readl(port, UART_CTL_REG);
+ if (mctrl & TIOCM_LOOP)
+ val |= UART_CTL_LOOPBACK_MASK;
+ else
+ val &= ~UART_CTL_LOOPBACK_MASK;
+ bcm_uart_writel(port, val, UART_CTL_REG);
+}
+
+/*
+ * serial core request to return RI, CTS, DCD and DSR pin state
+ */
+static unsigned int bcm_uart_get_mctrl(struct uart_port *port)
+{
+ unsigned int val, mctrl;
+
+ mctrl = 0;
+ val = bcm_uart_readl(port, UART_EXTINP_REG);
+ if (val & UART_EXTINP_RI_MASK)
+ mctrl |= TIOCM_RI;
+ if (val & UART_EXTINP_CTS_MASK)
+ mctrl |= TIOCM_CTS;
+ if (val & UART_EXTINP_DCD_MASK)
+ mctrl |= TIOCM_CD;
+ if (val & UART_EXTINP_DSR_MASK)
+ mctrl |= TIOCM_DSR;
+ return mctrl;
+}
+
+/*
+ * serial core request to disable tx ASAP (used for flow control)
+ */
+static void bcm_uart_stop_tx(struct uart_port *port)
+{
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_CTL_REG);
+ val &= ~(UART_CTL_TXEN_MASK);
+ bcm_uart_writel(port, val, UART_CTL_REG);
+
+ val = bcm_uart_readl(port, UART_IR_REG);
+ val &= ~UART_TX_INT_MASK;
+ bcm_uart_writel(port, val, UART_IR_REG);
+}
+
+/*
+ * serial core request to (re)enable tx
+ */
+static void bcm_uart_start_tx(struct uart_port *port)
+{
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_IR_REG);
+ val |= UART_TX_INT_MASK;
+ bcm_uart_writel(port, val, UART_IR_REG);
+
+ val = bcm_uart_readl(port, UART_CTL_REG);
+ val |= UART_CTL_TXEN_MASK;
+ bcm_uart_writel(port, val, UART_CTL_REG);
+}
+
+/*
+ * serial core request to stop rx, called before port shutdown
+ */
+static void bcm_uart_stop_rx(struct uart_port *port)
+{
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_IR_REG);
+ val &= ~UART_RX_INT_MASK;
+ bcm_uart_writel(port, val, UART_IR_REG);
+}
+
+/*
+ * serial core request to enable modem status interrupt reporting
+ */
+static void bcm_uart_enable_ms(struct uart_port *port)
+{
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_IR_REG);
+ val |= UART_IR_MASK(UART_IR_EXTIP);
+ bcm_uart_writel(port, val, UART_IR_REG);
+}
+
+/*
+ * serial core request to start/stop emitting break char
+ */
+static void bcm_uart_break_ctl(struct uart_port *port, int ctl)
+{
+ unsigned long flags;
+ unsigned int val;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ val = bcm_uart_readl(port, UART_CTL_REG);
+ if (ctl)
+ val |= UART_CTL_XMITBRK_MASK;
+ else
+ val &= ~UART_CTL_XMITBRK_MASK;
+ bcm_uart_writel(port, val, UART_CTL_REG);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/*
+ * return port type in string format
+ */
+static const char *bcm_uart_type(struct uart_port *port)
+{
+ return (port->type == PORT_BCM63XX) ? "bcm63xx_uart" : NULL;
+}
+
+/*
+ * read all chars in rx fifo and send them to core
+ */
+static void bcm_uart_do_rx(struct uart_port *port)
+{
+ struct tty_struct *tty;
+ unsigned int max_count;
+
+ /* limit number of char read in interrupt, should not be
+ * higher than fifo size anyway since we're much faster than
+ * serial port */
+ max_count = 32;
+ tty = port->info->port.tty;
+ do {
+ unsigned int iestat, c, cstat;
+ char flag;
+
+ /* get overrun/fifo empty information from ier
+ * register */
+ iestat = bcm_uart_readl(port, UART_IR_REG);
+ if (!(iestat & UART_IR_STAT(UART_IR_RXNOTEMPTY)))
+ break;
+
+ cstat = c = bcm_uart_readl(port, UART_FIFO_REG);
+ port->icount.rx++;
+ flag = TTY_NORMAL;
+ c &= 0xff;
+
+ if (unlikely((cstat & UART_FIFO_ANYERR_MASK))) {
+ /* do stats first */
+ if (cstat & UART_FIFO_BRKDET_MASK) {
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ continue;
+ }
+
+ if (cstat & UART_FIFO_PARERR_MASK)
+ port->icount.parity++;
+ if (cstat & UART_FIFO_FRAMEERR_MASK)
+ port->icount.frame++;
+
+ /* update flag wrt read_status_mask */
+ cstat &= port->read_status_mask;
+ if (cstat & UART_FIFO_BRKDET_MASK)
+ flag = TTY_BREAK;
+ if (cstat & UART_FIFO_FRAMEERR_MASK)
+ flag = TTY_FRAME;
+ if (cstat & UART_FIFO_PARERR_MASK)
+ flag = TTY_PARITY;
+ }
+
+ if (uart_handle_sysrq_char(port, c))
+ continue;
+
+ if (unlikely(iestat & UART_IR_STAT(UART_IR_RXOVER))) {
+ port->icount.overrun++;
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ }
+
+ if ((cstat & port->ignore_status_mask) == 0)
+ tty_insert_flip_char(tty, c, flag);
+
+ } while (--max_count);
+
+ tty_flip_buffer_push(tty);
+}
+
+/*
+ * fill tx fifo with chars to send, stop when fifo is about to be full
+ * or when all chars have been sent.
+ */
+static void bcm_uart_do_tx(struct uart_port *port)
+{
+ struct circ_buf *xmit;
+ unsigned int val, max_count;
+
+ if (port->x_char) {
+ bcm_uart_writel(port, port->x_char, UART_FIFO_REG);
+ port->icount.tx++;
+ port->x_char = 0;
+ return;
+ }
+
+ if (uart_tx_stopped(port)) {
+ bcm_uart_stop_tx(port);
+ return;
+ }
+
+ xmit = &port->info->xmit;
+ if (uart_circ_empty(xmit))
+ goto txq_empty;
+
+ val = bcm_uart_readl(port, UART_MCTL_REG);
+ val = (val & UART_MCTL_TXFIFOFILL_MASK) >> UART_MCTL_TXFIFOFILL_SHIFT;
+ max_count = port->fifosize - val;
+
+ while (max_count--) {
+ unsigned int c;
+
+ c = xmit->buf[xmit->tail];
+ bcm_uart_writel(port, c, UART_FIFO_REG);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ if (uart_circ_empty(xmit))
+ break;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit))
+ goto txq_empty;
+ return;
+
+txq_empty:
+ /* nothing to send, disable transmit interrupt */
+ val = bcm_uart_readl(port, UART_IR_REG);
+ val &= ~UART_TX_INT_MASK;
+ bcm_uart_writel(port, val, UART_IR_REG);
+ return;
+}
+
+/*
+ * process uart interrupt
+ */
+static irqreturn_t bcm_uart_interrupt(int irq, void *dev_id)
+{
+ struct uart_port *port;
+ unsigned int irqstat;
+
+ port = dev_id;
+ spin_lock(&port->lock);
+
+ irqstat = bcm_uart_readl(port, UART_IR_REG);
+ if (irqstat & UART_RX_INT_STAT)
+ bcm_uart_do_rx(port);
+
+ if (irqstat & UART_TX_INT_STAT)
+ bcm_uart_do_tx(port);
+
+ if (irqstat & UART_IR_MASK(UART_IR_EXTIP)) {
+ unsigned int estat;
+
+ estat = bcm_uart_readl(port, UART_EXTINP_REG);
+ if (estat & UART_EXTINP_IRSTAT(UART_EXTINP_IR_CTS))
+ uart_handle_cts_change(port,
+ estat & UART_EXTINP_CTS_MASK);
+ if (estat & UART_EXTINP_IRSTAT(UART_EXTINP_IR_DCD))
+ uart_handle_dcd_change(port,
+ estat & UART_EXTINP_DCD_MASK);
+ }
+
+ spin_unlock(&port->lock);
+ return IRQ_HANDLED;
+}
+
+/*
+ * enable rx & tx operation on uart
+ */
+static void bcm_uart_enable(struct uart_port *port)
+{
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_CTL_REG);
+ val |= (UART_CTL_BRGEN_MASK | UART_CTL_TXEN_MASK | UART_CTL_RXEN_MASK);
+ bcm_uart_writel(port, val, UART_CTL_REG);
+}
+
+/*
+ * disable rx & tx operation on uart
+ */
+static void bcm_uart_disable(struct uart_port *port)
+{
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_CTL_REG);
+ val &= ~(UART_CTL_BRGEN_MASK | UART_CTL_TXEN_MASK |
+ UART_CTL_RXEN_MASK);
+ bcm_uart_writel(port, val, UART_CTL_REG);
+}
+
+/*
+ * clear all unread data in rx fifo and unsent data in tx fifo
+ */
+static void bcm_uart_flush(struct uart_port *port)
+{
+ unsigned int val;
+
+ /* empty rx and tx fifo */
+ val = bcm_uart_readl(port, UART_CTL_REG);
+ val |= UART_CTL_RSTRXFIFO_MASK | UART_CTL_RSTTXFIFO_MASK;
+ bcm_uart_writel(port, val, UART_CTL_REG);
+
+ /* read any pending char to make sure all irq status are
+ * cleared */
+ (void)bcm_uart_readl(port, UART_FIFO_REG);
+}
+
+/*
+ * serial core request to initialize uart and start rx operation
+ */
+static int bcm_uart_startup(struct uart_port *port)
+{
+ unsigned int val;
+ int ret;
+
+ /* mask all irq and flush port */
+ bcm_uart_disable(port);
+ bcm_uart_writel(port, 0, UART_IR_REG);
+ bcm_uart_flush(port);
+
+ /* clear any pending external input interrupt */
+ (void)bcm_uart_readl(port, UART_EXTINP_REG);
+
+ /* set rx/tx fifo thresh to fifo half size */
+ val = bcm_uart_readl(port, UART_MCTL_REG);
+ val &= ~(UART_MCTL_RXFIFOTHRESH_MASK | UART_MCTL_TXFIFOTHRESH_MASK);
+ val |= (port->fifosize / 2) << UART_MCTL_RXFIFOTHRESH_SHIFT;
+ val |= (port->fifosize / 2) << UART_MCTL_TXFIFOTHRESH_SHIFT;
+ bcm_uart_writel(port, val, UART_MCTL_REG);
+
+ /* set rx fifo timeout to 1 char time */
+ val = bcm_uart_readl(port, UART_CTL_REG);
+ val &= ~UART_CTL_RXTMOUTCNT_MASK;
+ val |= 1 << UART_CTL_RXTMOUTCNT_SHIFT;
+ bcm_uart_writel(port, val, UART_CTL_REG);
+
+ /* report any edge on dcd and cts */
+ val = UART_EXTINP_INT_MASK;
+ val |= UART_EXTINP_DCD_NOSENSE_MASK;
+ val |= UART_EXTINP_CTS_NOSENSE_MASK;
+ bcm_uart_writel(port, val, UART_EXTINP_REG);
+
+ /* register irq and enable rx interrupts */
+ ret = request_irq(port->irq, bcm_uart_interrupt, 0,
+ bcm_uart_type(port), port);
+ if (ret)
+ return ret;
+ bcm_uart_writel(port, UART_RX_INT_MASK, UART_IR_REG);
+ bcm_uart_enable(port);
+ return 0;
+}
+
+/*
+ * serial core request to flush & disable uart
+ */
+static void bcm_uart_shutdown(struct uart_port *port)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ bcm_uart_writel(port, 0, UART_IR_REG);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ bcm_uart_disable(port);
+ bcm_uart_flush(port);
+ free_irq(port->irq, port);
+}
+
+/*
+ * serial core request to change current uart setting
+ */
+static void bcm_uart_set_termios(struct uart_port *port,
+ struct ktermios *new,
+ struct ktermios *old)
+{
+ unsigned int ctl, baud, quot, ier;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* disable uart while changing speed */
+ bcm_uart_disable(port);
+ bcm_uart_flush(port);
+
+ /* update Control register */
+ ctl = bcm_uart_readl(port, UART_CTL_REG);
+ ctl &= ~UART_CTL_BITSPERSYM_MASK;
+
+ switch (new->c_cflag & CSIZE) {
+ case CS5:
+ ctl |= (0 << UART_CTL_BITSPERSYM_SHIFT);
+ break;
+ case CS6:
+ ctl |= (1 << UART_CTL_BITSPERSYM_SHIFT);
+ break;
+ case CS7:
+ ctl |= (2 << UART_CTL_BITSPERSYM_SHIFT);
+ break;
+ default:
+ ctl |= (3 << UART_CTL_BITSPERSYM_SHIFT);
+ break;
+ }
+
+ ctl &= ~UART_CTL_STOPBITS_MASK;
+ if (new->c_cflag & CSTOPB)
+ ctl |= UART_CTL_STOPBITS_2;
+ else
+ ctl |= UART_CTL_STOPBITS_1;
+
+ ctl &= ~(UART_CTL_RXPAREN_MASK | UART_CTL_TXPAREN_MASK);
+ if (new->c_cflag & PARENB)
+ ctl |= (UART_CTL_RXPAREN_MASK | UART_CTL_TXPAREN_MASK);
+ ctl &= ~(UART_CTL_RXPAREVEN_MASK | UART_CTL_TXPAREVEN_MASK);
+ if (new->c_cflag & PARODD)
+ ctl |= (UART_CTL_RXPAREVEN_MASK | UART_CTL_TXPAREVEN_MASK);
+ bcm_uart_writel(port, ctl, UART_CTL_REG);
+
+ /* update Baudword register */
+ baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
+ quot = uart_get_divisor(port, baud) - 1;
+ bcm_uart_writel(port, quot, UART_BAUD_REG);
+
+ /* update Interrupt register */
+ ier = bcm_uart_readl(port, UART_IR_REG);
+
+ ier &= ~UART_IR_MASK(UART_IR_EXTIP);
+ if (UART_ENABLE_MS(port, new->c_cflag))
+ ier |= UART_IR_MASK(UART_IR_EXTIP);
+
+ bcm_uart_writel(port, ier, UART_IR_REG);
+
+ /* update read/ignore mask */
+ port->read_status_mask = UART_FIFO_VALID_MASK;
+ if (new->c_iflag & INPCK) {
+ port->read_status_mask |= UART_FIFO_FRAMEERR_MASK;
+ port->read_status_mask |= UART_FIFO_PARERR_MASK;
+ }
+ if (new->c_iflag & (BRKINT))
+ port->read_status_mask |= UART_FIFO_BRKDET_MASK;
+
+ port->ignore_status_mask = 0;
+ if (new->c_iflag & IGNPAR)
+ port->ignore_status_mask |= UART_FIFO_PARERR_MASK;
+ if (new->c_iflag & IGNBRK)
+ port->ignore_status_mask |= UART_FIFO_BRKDET_MASK;
+ if (!(new->c_cflag & CREAD))
+ port->ignore_status_mask |= UART_FIFO_VALID_MASK;
+
+ uart_update_timeout(port, new->c_cflag, baud);
+ bcm_uart_enable(port);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/*
+ * serial core request to claim uart iomem
+ */
+static int bcm_uart_request_port(struct uart_port *port)
+{
+ unsigned int size;
+
+ size = RSET_UART_SIZE;
+ if (!request_mem_region(port->mapbase, size, "bcm63xx")) {
+ dev_err(port->dev, "Memory region busy\n");
+ return -EBUSY;
+ }
+
+ port->membase = ioremap(port->mapbase, size);
+ if (!port->membase) {
+ dev_err(port->dev, "Unable to map registers\n");
+ release_mem_region(port->mapbase, size);
+ return -EBUSY;
+ }
+ return 0;
+}
+
+/*
+ * serial core request to release uart iomem
+ */
+static void bcm_uart_release_port(struct uart_port *port)
+{
+ release_mem_region(port->mapbase, RSET_UART_SIZE);
+ iounmap(port->membase);
+}
+
+/*
+ * serial core request to do any port required autoconfiguration
+ */
+static void bcm_uart_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE) {
+ if (bcm_uart_request_port(port))
+ return;
+ port->type = PORT_BCM63XX;
+ }
+}
+
+/*
+ * serial core request to check that port information in serinfo are
+ * suitable
+ */
+static int bcm_uart_verify_port(struct uart_port *port,
+ struct serial_struct *serinfo)
+{
+ if (port->type != PORT_BCM63XX)
+ return -EINVAL;
+ if (port->irq != serinfo->irq)
+ return -EINVAL;
+ if (port->iotype != serinfo->io_type)
+ return -EINVAL;
+ if (port->mapbase != (unsigned long)serinfo->iomem_base)
+ return -EINVAL;
+ return 0;
+}
+
+/* serial core callbacks */
+static struct uart_ops bcm_uart_ops = {
+ .tx_empty = bcm_uart_tx_empty,
+ .get_mctrl = bcm_uart_get_mctrl,
+ .set_mctrl = bcm_uart_set_mctrl,
+ .start_tx = bcm_uart_start_tx,
+ .stop_tx = bcm_uart_stop_tx,
+ .stop_rx = bcm_uart_stop_rx,
+ .enable_ms = bcm_uart_enable_ms,
+ .break_ctl = bcm_uart_break_ctl,
+ .startup = bcm_uart_startup,
+ .shutdown = bcm_uart_shutdown,
+ .set_termios = bcm_uart_set_termios,
+ .type = bcm_uart_type,
+ .release_port = bcm_uart_release_port,
+ .request_port = bcm_uart_request_port,
+ .config_port = bcm_uart_config_port,
+ .verify_port = bcm_uart_verify_port,
+};
+
+
+
+#ifdef CONFIG_SERIAL_BCM63XX_CONSOLE
+static inline void wait_for_xmitr(struct uart_port *port)
+{
+ unsigned int tmout;
+
+ /* Wait up to 10ms for the character(s) to be sent. */
+ tmout = 10000;
+ while (--tmout) {
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_IR_REG);
+ if (val & UART_IR_STAT(UART_IR_TXEMPTY))
+ break;
+ udelay(1);
+ }
+
+ /* Wait up to 1s for flow control if necessary */
+ if (port->flags & UPF_CONS_FLOW) {
+ tmout = 1000000;
+ while (--tmout) {
+ unsigned int val;
+
+ val = bcm_uart_readl(port, UART_EXTINP_REG);
+ if (val & UART_EXTINP_CTS_MASK)
+ break;
+ udelay(1);
+ }
+ }
+}
+
+/*
+ * output given char
+ */
+static void bcm_console_putchar(struct uart_port *port, int ch)
+{
+ wait_for_xmitr(port);
+ bcm_uart_writel(port, ch, UART_FIFO_REG);
+}
+
+/*
+ * console core request to output given string
+ */
+static void bcm_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct uart_port *port;
+ unsigned long flags;
+ int locked;
+
+ port = &ports[co->index];
+
+ local_irq_save(flags);
+ if (port->sysrq) {
+ /* bcm_uart_interrupt() already took the lock */
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&port->lock);
+ } else {
+ spin_lock(&port->lock);
+ locked = 1;
+ }
+
+ /* call helper to deal with \r\n */
+ uart_console_write(port, s, count, bcm_console_putchar);
+
+ /* and wait for char to be transmitted */
+ wait_for_xmitr(port);
+
+ if (locked)
+ spin_unlock(&port->lock);
+ local_irq_restore(flags);
+}
+
+/*
+ * console core request to setup given console, find matching uart
+ * port and setup it.
+ */
+static int bcm_console_setup(struct console *co, char *options)
+{
+ struct uart_port *port;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (co->index < 0 || co->index >= BCM63XX_NR_UARTS)
+ return -EINVAL;
+ port = &ports[co->index];
+ if (!port->membase)
+ return -ENODEV;
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver bcm_uart_driver;
+
+static struct console bcm63xx_console = {
+ .name = "ttyS",
+ .write = bcm_console_write,
+ .device = uart_console_device,
+ .setup = bcm_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &bcm_uart_driver,
+};
+
+static int __init bcm63xx_console_init(void)
+{
+ register_console(&bcm63xx_console);
+ return 0;
+}
+
+console_initcall(bcm63xx_console_init);
+
+#define BCM63XX_CONSOLE (&bcm63xx_console)
+#else
+#define BCM63XX_CONSOLE NULL
+#endif /* CONFIG_SERIAL_BCM63XX_CONSOLE */
+
+static struct uart_driver bcm_uart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = "bcm63xx_uart",
+ .dev_name = "ttyS",
+ .major = TTY_MAJOR,
+ .minor = 64,
+ .nr = 1,
+ .cons = BCM63XX_CONSOLE,
+};
+
+/*
+ * platform driver probe/remove callback
+ */
+static int __devinit bcm_uart_probe(struct platform_device *pdev)
+{
+ struct resource *res_mem, *res_irq;
+ struct uart_port *port;
+ struct clk *clk;
+ int ret;
+
+ if (pdev->id < 0 || pdev->id >= BCM63XX_NR_UARTS)
+ return -EINVAL;
+
+ if (ports[pdev->id].membase)
+ return -EBUSY;
+
+ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res_mem)
+ return -ENODEV;
+
+ res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res_irq)
+ return -ENODEV;
+
+ clk = clk_get(&pdev->dev, "periph");
+ if (IS_ERR(clk))
+ return -ENODEV;
+
+ port = &ports[pdev->id];
+ memset(port, 0, sizeof(*port));
+ port->iotype = UPIO_MEM;
+ port->mapbase = res_mem->start;
+ port->irq = res_irq->start;
+ port->ops = &bcm_uart_ops;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->dev = &pdev->dev;
+ port->fifosize = 16;
+ port->uartclk = clk_get_rate(clk) / 2;
+ clk_put(clk);
+
+ ret = uart_add_one_port(&bcm_uart_driver, port);
+ if (ret) {
+ kfree(port);
+ return ret;
+ }
+ platform_set_drvdata(pdev, port);
+ return 0;
+}
+
+static int __devexit bcm_uart_remove(struct platform_device *pdev)
+{
+ struct uart_port *port;
+
+ port = platform_get_drvdata(pdev);
+ uart_remove_one_port(&bcm_uart_driver, port);
+ platform_set_drvdata(pdev, NULL);
+ /* mark port as free */
+ ports[pdev->id].membase = 0;
+ return 0;
+}
+
+/*
+ * platform driver stuff
+ */
+static struct platform_driver bcm_uart_platform_driver = {
+ .probe = bcm_uart_probe,
+ .remove = __devexit_p(bcm_uart_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "bcm63xx_uart",
+ },
+};
+
+static int __init bcm_uart_init(void)
+{
+ int ret;
+
+ ret = uart_register_driver(&bcm_uart_driver);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&bcm_uart_platform_driver);
+ if (ret)
+ uart_unregister_driver(&bcm_uart_driver);
+
+ return ret;
+}
+
+static void __exit bcm_uart_exit(void)
+{
+ platform_driver_unregister(&bcm_uart_platform_driver);
+ uart_unregister_driver(&bcm_uart_driver);
+}
+
+module_init(bcm_uart_init);
+module_exit(bcm_uart_exit);
+
+MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>");
+MODULE_DESCRIPTION("Broadcom 63<xx integrated uart driver");
+MODULE_LICENSE("GPL");
if (port < 4) {
temp = readl(stop_proc[port].global_control_reg);
temp =
- (temp & ~start_proc[port].processor_id) | stop_proc[port].processor_id;
+ (temp & ~start_proc[port].processor_id) | stop_proc[port].processor_id;
writel(temp, stop_proc[port].global_control_reg);
/* write flush */
if (port < 4) {
temp = readl(start_proc[port].global_control_reg);
temp =
- (temp & ~stop_proc[port].processor_id) | start_proc[port].processor_id;
+ (temp & ~stop_proc[port].processor_id) | start_proc[port].processor_id;
writel(temp, start_proc[port].global_control_reg);
/* write flush */
dev_err(&icom_port->adapter->pci_dev->dev,"Port not opertional\n");
}
- if (new_page != NULL)
- pci_free_consistent(dev, 4096, new_page, temp_pci);
+ if (new_page != NULL)
+ pci_free_consistent(dev, 4096, new_page, temp_pci);
}
static int startup(struct icom_port *icom_port)
const struct pci_device_id *ent)
{
int index;
- unsigned int command_reg;
- int retval;
- struct icom_adapter *icom_adapter;
- struct icom_port *icom_port;
+ unsigned int command_reg;
+ int retval;
+ struct icom_adapter *icom_adapter;
+ struct icom_port *icom_port;
- retval = pci_enable_device(dev);
- if (retval) {
+ retval = pci_enable_device(dev);
+ if (retval) {
dev_err(&dev->dev, "Device enable FAILED\n");
- return retval;
+ return retval;
}
if ( (retval = pci_request_regions(dev, "icom"))) {
return retval;
}
- pci_set_master(dev);
+ pci_set_master(dev);
- if ( (retval = pci_read_config_dword(dev, PCI_COMMAND, &command_reg))) {
+ if ( (retval = pci_read_config_dword(dev, PCI_COMMAND, &command_reg))) {
dev_err(&dev->dev, "PCI Config read FAILED\n");
- return retval;
- }
+ return retval;
+ }
pci_write_config_dword(dev, PCI_COMMAND,
command_reg | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
| PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
- if (ent->driver_data == ADAPTER_V1) {
+ if (ent->driver_data == ADAPTER_V1) {
pci_write_config_dword(dev, 0x44, 0x8300830A);
- } else {
+ } else {
pci_write_config_dword(dev, 0x44, 0x42004200);
pci_write_config_dword(dev, 0x48, 0x42004200);
- }
+ }
retval = icom_alloc_adapter(&icom_adapter);
goto probe_exit0;
}
- icom_adapter->base_addr_pci = pci_resource_start(dev, 0);
- icom_adapter->pci_dev = dev;
- icom_adapter->version = ent->driver_data;
- icom_adapter->subsystem_id = ent->subdevice;
+ icom_adapter->base_addr_pci = pci_resource_start(dev, 0);
+ icom_adapter->pci_dev = dev;
+ icom_adapter->version = ent->driver_data;
+ icom_adapter->subsystem_id = ent->subdevice;
retval = icom_init_ports(icom_adapter);
goto probe_exit1;
}
- icom_adapter->base_addr = pci_ioremap_bar(dev, 0);
+ icom_adapter->base_addr = pci_ioremap_bar(dev, 0);
if (!icom_adapter->base_addr)
goto probe_exit1;
retval = icom_load_ports(icom_adapter);
- for (index = 0; index < icom_adapter->numb_ports; index++) {
+ for (index = 0; index < icom_adapter->numb_ports; index++) {
icom_port = &icom_adapter->port_info[index];
if (icom_port->status == ICOM_PORT_ACTIVE) {
icom_port->status = ICOM_PORT_OFF;
dev_err(&dev->dev, "Device add failed\n");
} else
- dev_info(&dev->dev, "Device added\n");
+ dev_info(&dev->dev, "Device added\n");
}
}
pci_release_regions(dev);
pci_disable_device(dev);
- return retval;
-
-
+ return retval;
}
static void __devexit icom_remove(struct pci_dev *dev)
sio_out(up, TXX9_SIBGR, 0xff | TXX9_SIBGR_BCLK_T6);
}
+static struct uart_txx9_port *to_uart_txx9_port(struct uart_port *port)
+{
+ return container_of(port, struct uart_txx9_port, port);
+}
+
static void serial_txx9_stop_tx(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
}
static void serial_txx9_start_tx(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
sio_set(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
}
static void serial_txx9_stop_rx(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
up->port.read_status_mask &= ~TXX9_SIDISR_RDIS;
}
static void serial_txx9_initialize(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned int tmout = 10000;
sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST);
static unsigned int serial_txx9_tx_empty(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned long flags;
unsigned int ret;
static unsigned int serial_txx9_get_mctrl(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned int ret;
/* no modem control lines */
static void serial_txx9_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
if (mctrl & TIOCM_RTS)
sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC);
static void serial_txx9_break_ctl(struct uart_port *port, int break_state)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned long flags;
spin_lock_irqsave(&up->port.lock, flags);
{
unsigned int ier;
unsigned char c;
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
/*
* First save the IER then disable the interrupts
static void serial_txx9_put_poll_char(struct uart_port *port, unsigned char c)
{
unsigned int ier;
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
/*
* First save the IER then disable the interrupts
static int serial_txx9_startup(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned long flags;
int retval;
static void serial_txx9_shutdown(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned long flags;
/*
serial_txx9_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
unsigned int cval, fcr = 0;
unsigned long flags;
unsigned int baud, quot;
static void serial_txx9_release_port(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
serial_txx9_release_resource(up);
}
static int serial_txx9_request_port(struct uart_port *port)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
return serial_txx9_request_resource(up);
}
static void serial_txx9_config_port(struct uart_port *port, int uflags)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
int ret;
/*
static void serial_txx9_console_putchar(struct uart_port *port, int ch)
{
- struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ struct uart_txx9_port *up = to_uart_txx9_port(port);
wait_for_xmitr(up);
sio_out(up, TXX9_SITFIFO, ch);
obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
-obj-$(CONFIG_SPI_IMX) += mxc_spi.o
+obj-$(CONFIG_SPI_IMX) += spi_imx.o
obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o
#define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */
#define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */
-struct mxc_spi_config {
+struct spi_imx_config {
unsigned int speed_hz;
unsigned int bpw;
unsigned int mode;
int cs;
};
-struct mxc_spi_data {
+struct spi_imx_data {
struct spi_bitbang bitbang;
struct completion xfer_done;
int *chipselect;
unsigned int count;
- void (*tx)(struct mxc_spi_data *);
- void (*rx)(struct mxc_spi_data *);
+ void (*tx)(struct spi_imx_data *);
+ void (*rx)(struct spi_imx_data *);
void *rx_buf;
const void *tx_buf;
unsigned int txfifo; /* number of words pushed in tx FIFO */
/* SoC specific functions */
- void (*intctrl)(struct mxc_spi_data *, int);
- int (*config)(struct mxc_spi_data *, struct mxc_spi_config *);
- void (*trigger)(struct mxc_spi_data *);
- int (*rx_available)(struct mxc_spi_data *);
+ void (*intctrl)(struct spi_imx_data *, int);
+ int (*config)(struct spi_imx_data *, struct spi_imx_config *);
+ void (*trigger)(struct spi_imx_data *);
+ int (*rx_available)(struct spi_imx_data *);
};
#define MXC_SPI_BUF_RX(type) \
-static void mxc_spi_buf_rx_##type(struct mxc_spi_data *mxc_spi) \
+static void spi_imx_buf_rx_##type(struct spi_imx_data *spi_imx) \
{ \
- unsigned int val = readl(mxc_spi->base + MXC_CSPIRXDATA); \
+ unsigned int val = readl(spi_imx->base + MXC_CSPIRXDATA); \
\
- if (mxc_spi->rx_buf) { \
- *(type *)mxc_spi->rx_buf = val; \
- mxc_spi->rx_buf += sizeof(type); \
+ if (spi_imx->rx_buf) { \
+ *(type *)spi_imx->rx_buf = val; \
+ spi_imx->rx_buf += sizeof(type); \
} \
}
#define MXC_SPI_BUF_TX(type) \
-static void mxc_spi_buf_tx_##type(struct mxc_spi_data *mxc_spi) \
+static void spi_imx_buf_tx_##type(struct spi_imx_data *spi_imx) \
{ \
type val = 0; \
\
- if (mxc_spi->tx_buf) { \
- val = *(type *)mxc_spi->tx_buf; \
- mxc_spi->tx_buf += sizeof(type); \
+ if (spi_imx->tx_buf) { \
+ val = *(type *)spi_imx->tx_buf; \
+ spi_imx->tx_buf += sizeof(type); \
} \
\
- mxc_spi->count -= sizeof(type); \
+ spi_imx->count -= sizeof(type); \
\
- writel(val, mxc_spi->base + MXC_CSPITXDATA); \
+ writel(val, spi_imx->base + MXC_CSPITXDATA); \
}
MXC_SPI_BUF_RX(u8)
256, 384, 512, 768, 1024};
/* MX21, MX27 */
-static unsigned int mxc_spi_clkdiv_1(unsigned int fin,
+static unsigned int spi_imx_clkdiv_1(unsigned int fin,
unsigned int fspi)
{
int i, max;
}
/* MX1, MX31, MX35 */
-static unsigned int mxc_spi_clkdiv_2(unsigned int fin,
+static unsigned int spi_imx_clkdiv_2(unsigned int fin,
unsigned int fspi)
{
int i, div = 4;
* the i.MX35 has a slightly different register layout for bits
* we do not use here.
*/
-static void mx31_intctrl(struct mxc_spi_data *mxc_spi, int enable)
+static void mx31_intctrl(struct spi_imx_data *spi_imx, int enable)
{
unsigned int val = 0;
if (enable & MXC_INT_RR)
val |= MX31_INTREG_RREN;
- writel(val, mxc_spi->base + MXC_CSPIINT);
+ writel(val, spi_imx->base + MXC_CSPIINT);
}
-static void mx31_trigger(struct mxc_spi_data *mxc_spi)
+static void mx31_trigger(struct spi_imx_data *spi_imx)
{
unsigned int reg;
- reg = readl(mxc_spi->base + MXC_CSPICTRL);
+ reg = readl(spi_imx->base + MXC_CSPICTRL);
reg |= MX31_CSPICTRL_XCH;
- writel(reg, mxc_spi->base + MXC_CSPICTRL);
+ writel(reg, spi_imx->base + MXC_CSPICTRL);
}
-static int mx31_config(struct mxc_spi_data *mxc_spi,
- struct mxc_spi_config *config)
+static int mx31_config(struct spi_imx_data *spi_imx,
+ struct spi_imx_config *config)
{
unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
- reg |= mxc_spi_clkdiv_2(mxc_spi->spi_clk, config->speed_hz) <<
+ reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
MX31_CSPICTRL_DR_SHIFT;
if (cpu_is_mx31())
reg |= (config->cs + 32) << MX35_CSPICTRL_CS_SHIFT;
}
- writel(reg, mxc_spi->base + MXC_CSPICTRL);
+ writel(reg, spi_imx->base + MXC_CSPICTRL);
return 0;
}
-static int mx31_rx_available(struct mxc_spi_data *mxc_spi)
+static int mx31_rx_available(struct spi_imx_data *spi_imx)
{
- return readl(mxc_spi->base + MX31_CSPISTATUS) & MX31_STATUS_RR;
+ return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR;
}
#define MX27_INTREG_RR (1 << 4)
#define MX27_CSPICTRL_DR_SHIFT 14
#define MX27_CSPICTRL_CS_SHIFT 19
-static void mx27_intctrl(struct mxc_spi_data *mxc_spi, int enable)
+static void mx27_intctrl(struct spi_imx_data *spi_imx, int enable)
{
unsigned int val = 0;
if (enable & MXC_INT_RR)
val |= MX27_INTREG_RREN;
- writel(val, mxc_spi->base + MXC_CSPIINT);
+ writel(val, spi_imx->base + MXC_CSPIINT);
}
-static void mx27_trigger(struct mxc_spi_data *mxc_spi)
+static void mx27_trigger(struct spi_imx_data *spi_imx)
{
unsigned int reg;
- reg = readl(mxc_spi->base + MXC_CSPICTRL);
+ reg = readl(spi_imx->base + MXC_CSPICTRL);
reg |= MX27_CSPICTRL_XCH;
- writel(reg, mxc_spi->base + MXC_CSPICTRL);
+ writel(reg, spi_imx->base + MXC_CSPICTRL);
}
-static int mx27_config(struct mxc_spi_data *mxc_spi,
- struct mxc_spi_config *config)
+static int mx27_config(struct spi_imx_data *spi_imx,
+ struct spi_imx_config *config)
{
unsigned int reg = MX27_CSPICTRL_ENABLE | MX27_CSPICTRL_MASTER;
- reg |= mxc_spi_clkdiv_1(mxc_spi->spi_clk, config->speed_hz) <<
+ reg |= spi_imx_clkdiv_1(spi_imx->spi_clk, config->speed_hz) <<
MX27_CSPICTRL_DR_SHIFT;
reg |= config->bpw - 1;
if (config->cs < 0)
reg |= (config->cs + 32) << MX27_CSPICTRL_CS_SHIFT;
- writel(reg, mxc_spi->base + MXC_CSPICTRL);
+ writel(reg, spi_imx->base + MXC_CSPICTRL);
return 0;
}
-static int mx27_rx_available(struct mxc_spi_data *mxc_spi)
+static int mx27_rx_available(struct spi_imx_data *spi_imx)
{
- return readl(mxc_spi->base + MXC_CSPIINT) & MX27_INTREG_RR;
+ return readl(spi_imx->base + MXC_CSPIINT) & MX27_INTREG_RR;
}
#define MX1_INTREG_RR (1 << 3)
#define MX1_CSPICTRL_MASTER (1 << 10)
#define MX1_CSPICTRL_DR_SHIFT 13
-static void mx1_intctrl(struct mxc_spi_data *mxc_spi, int enable)
+static void mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
{
unsigned int val = 0;
if (enable & MXC_INT_RR)
val |= MX1_INTREG_RREN;
- writel(val, mxc_spi->base + MXC_CSPIINT);
+ writel(val, spi_imx->base + MXC_CSPIINT);
}
-static void mx1_trigger(struct mxc_spi_data *mxc_spi)
+static void mx1_trigger(struct spi_imx_data *spi_imx)
{
unsigned int reg;
- reg = readl(mxc_spi->base + MXC_CSPICTRL);
+ reg = readl(spi_imx->base + MXC_CSPICTRL);
reg |= MX1_CSPICTRL_XCH;
- writel(reg, mxc_spi->base + MXC_CSPICTRL);
+ writel(reg, spi_imx->base + MXC_CSPICTRL);
}
-static int mx1_config(struct mxc_spi_data *mxc_spi,
- struct mxc_spi_config *config)
+static int mx1_config(struct spi_imx_data *spi_imx,
+ struct spi_imx_config *config)
{
unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER;
- reg |= mxc_spi_clkdiv_2(mxc_spi->spi_clk, config->speed_hz) <<
+ reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, config->speed_hz) <<
MX1_CSPICTRL_DR_SHIFT;
reg |= config->bpw - 1;
if (config->mode & SPI_CPOL)
reg |= MX1_CSPICTRL_POL;
- writel(reg, mxc_spi->base + MXC_CSPICTRL);
+ writel(reg, spi_imx->base + MXC_CSPICTRL);
return 0;
}
-static int mx1_rx_available(struct mxc_spi_data *mxc_spi)
+static int mx1_rx_available(struct spi_imx_data *spi_imx)
{
- return readl(mxc_spi->base + MXC_CSPIINT) & MX1_INTREG_RR;
+ return readl(spi_imx->base + MXC_CSPIINT) & MX1_INTREG_RR;
}
-static void mxc_spi_chipselect(struct spi_device *spi, int is_active)
+static void spi_imx_chipselect(struct spi_device *spi, int is_active)
{
- struct mxc_spi_data *mxc_spi = spi_master_get_devdata(spi->master);
- unsigned int cs = 0;
- int gpio = mxc_spi->chipselect[spi->chip_select];
- struct mxc_spi_config config;
+ struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+ int gpio = spi_imx->chipselect[spi->chip_select];
+ int active = is_active != BITBANG_CS_INACTIVE;
+ int dev_is_lowactive = !(spi->mode & SPI_CS_HIGH);
- if (spi->mode & SPI_CS_HIGH)
- cs = 1;
-
- if (is_active == BITBANG_CS_INACTIVE) {
- if (gpio >= 0)
- gpio_set_value(gpio, !cs);
+ if (gpio < 0)
return;
- }
-
- config.bpw = spi->bits_per_word;
- config.speed_hz = spi->max_speed_hz;
- config.mode = spi->mode;
- config.cs = mxc_spi->chipselect[spi->chip_select];
-
- mxc_spi->config(mxc_spi, &config);
-
- /* Initialize the functions for transfer */
- if (config.bpw <= 8) {
- mxc_spi->rx = mxc_spi_buf_rx_u8;
- mxc_spi->tx = mxc_spi_buf_tx_u8;
- } else if (config.bpw <= 16) {
- mxc_spi->rx = mxc_spi_buf_rx_u16;
- mxc_spi->tx = mxc_spi_buf_tx_u16;
- } else if (config.bpw <= 32) {
- mxc_spi->rx = mxc_spi_buf_rx_u32;
- mxc_spi->tx = mxc_spi_buf_tx_u32;
- } else
- BUG();
- if (gpio >= 0)
- gpio_set_value(gpio, cs);
-
- return;
+ gpio_set_value(gpio, dev_is_lowactive ^ active);
}
-static void mxc_spi_push(struct mxc_spi_data *mxc_spi)
+static void spi_imx_push(struct spi_imx_data *spi_imx)
{
- while (mxc_spi->txfifo < 8) {
- if (!mxc_spi->count)
+ while (spi_imx->txfifo < 8) {
+ if (!spi_imx->count)
break;
- mxc_spi->tx(mxc_spi);
- mxc_spi->txfifo++;
+ spi_imx->tx(spi_imx);
+ spi_imx->txfifo++;
}
- mxc_spi->trigger(mxc_spi);
+ spi_imx->trigger(spi_imx);
}
-static irqreturn_t mxc_spi_isr(int irq, void *dev_id)
+static irqreturn_t spi_imx_isr(int irq, void *dev_id)
{
- struct mxc_spi_data *mxc_spi = dev_id;
+ struct spi_imx_data *spi_imx = dev_id;
- while (mxc_spi->rx_available(mxc_spi)) {
- mxc_spi->rx(mxc_spi);
- mxc_spi->txfifo--;
+ while (spi_imx->rx_available(spi_imx)) {
+ spi_imx->rx(spi_imx);
+ spi_imx->txfifo--;
}
- if (mxc_spi->count) {
- mxc_spi_push(mxc_spi);
+ if (spi_imx->count) {
+ spi_imx_push(spi_imx);
return IRQ_HANDLED;
}
- if (mxc_spi->txfifo) {
+ if (spi_imx->txfifo) {
/* No data left to push, but still waiting for rx data,
* enable receive data available interrupt.
*/
- mxc_spi->intctrl(mxc_spi, MXC_INT_RR);
+ spi_imx->intctrl(spi_imx, MXC_INT_RR);
return IRQ_HANDLED;
}
- mxc_spi->intctrl(mxc_spi, 0);
- complete(&mxc_spi->xfer_done);
+ spi_imx->intctrl(spi_imx, 0);
+ complete(&spi_imx->xfer_done);
return IRQ_HANDLED;
}
-static int mxc_spi_setupxfer(struct spi_device *spi,
+static int spi_imx_setupxfer(struct spi_device *spi,
struct spi_transfer *t)
{
- struct mxc_spi_data *mxc_spi = spi_master_get_devdata(spi->master);
- struct mxc_spi_config config;
+ struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+ struct spi_imx_config config;
config.bpw = t ? t->bits_per_word : spi->bits_per_word;
config.speed_hz = t ? t->speed_hz : spi->max_speed_hz;
config.mode = spi->mode;
+ config.cs = spi_imx->chipselect[spi->chip_select];
+
+ if (!config.speed_hz)
+ config.speed_hz = spi->max_speed_hz;
+ if (!config.bpw)
+ config.bpw = spi->bits_per_word;
+ if (!config.speed_hz)
+ config.speed_hz = spi->max_speed_hz;
+
+ /* Initialize the functions for transfer */
+ if (config.bpw <= 8) {
+ spi_imx->rx = spi_imx_buf_rx_u8;
+ spi_imx->tx = spi_imx_buf_tx_u8;
+ } else if (config.bpw <= 16) {
+ spi_imx->rx = spi_imx_buf_rx_u16;
+ spi_imx->tx = spi_imx_buf_tx_u16;
+ } else if (config.bpw <= 32) {
+ spi_imx->rx = spi_imx_buf_rx_u32;
+ spi_imx->tx = spi_imx_buf_tx_u32;
+ } else
+ BUG();
- mxc_spi->config(mxc_spi, &config);
+ spi_imx->config(spi_imx, &config);
return 0;
}
-static int mxc_spi_transfer(struct spi_device *spi,
+static int spi_imx_transfer(struct spi_device *spi,
struct spi_transfer *transfer)
{
- struct mxc_spi_data *mxc_spi = spi_master_get_devdata(spi->master);
+ struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
- mxc_spi->tx_buf = transfer->tx_buf;
- mxc_spi->rx_buf = transfer->rx_buf;
- mxc_spi->count = transfer->len;
- mxc_spi->txfifo = 0;
+ spi_imx->tx_buf = transfer->tx_buf;
+ spi_imx->rx_buf = transfer->rx_buf;
+ spi_imx->count = transfer->len;
+ spi_imx->txfifo = 0;
- init_completion(&mxc_spi->xfer_done);
+ init_completion(&spi_imx->xfer_done);
- mxc_spi_push(mxc_spi);
+ spi_imx_push(spi_imx);
- mxc_spi->intctrl(mxc_spi, MXC_INT_TE);
+ spi_imx->intctrl(spi_imx, MXC_INT_TE);
- wait_for_completion(&mxc_spi->xfer_done);
+ wait_for_completion(&spi_imx->xfer_done);
return transfer->len;
}
-static int mxc_spi_setup(struct spi_device *spi)
+static int spi_imx_setup(struct spi_device *spi)
{
- if (!spi->bits_per_word)
- spi->bits_per_word = 8;
+ struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
+ int gpio = spi_imx->chipselect[spi->chip_select];
pr_debug("%s: mode %d, %u bpw, %d hz\n", __func__,
spi->mode, spi->bits_per_word, spi->max_speed_hz);
- mxc_spi_chipselect(spi, BITBANG_CS_INACTIVE);
+ if (gpio >= 0)
+ gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
+
+ spi_imx_chipselect(spi, BITBANG_CS_INACTIVE);
return 0;
}
-static void mxc_spi_cleanup(struct spi_device *spi)
+static void spi_imx_cleanup(struct spi_device *spi)
{
}
-static int __init mxc_spi_probe(struct platform_device *pdev)
+static int __init spi_imx_probe(struct platform_device *pdev)
{
struct spi_imx_master *mxc_platform_info;
struct spi_master *master;
- struct mxc_spi_data *mxc_spi;
+ struct spi_imx_data *spi_imx;
struct resource *res;
int i, ret;
return -EINVAL;
}
- master = spi_alloc_master(&pdev->dev, sizeof(struct mxc_spi_data));
+ master = spi_alloc_master(&pdev->dev, sizeof(struct spi_imx_data));
if (!master)
return -ENOMEM;
master->bus_num = pdev->id;
master->num_chipselect = mxc_platform_info->num_chipselect;
- mxc_spi = spi_master_get_devdata(master);
- mxc_spi->bitbang.master = spi_master_get(master);
- mxc_spi->chipselect = mxc_platform_info->chipselect;
+ spi_imx = spi_master_get_devdata(master);
+ spi_imx->bitbang.master = spi_master_get(master);
+ spi_imx->chipselect = mxc_platform_info->chipselect;
for (i = 0; i < master->num_chipselect; i++) {
- if (mxc_spi->chipselect[i] < 0)
+ if (spi_imx->chipselect[i] < 0)
continue;
- ret = gpio_request(mxc_spi->chipselect[i], DRIVER_NAME);
+ ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);
if (ret) {
i--;
while (i > 0)
- if (mxc_spi->chipselect[i] >= 0)
- gpio_free(mxc_spi->chipselect[i--]);
+ if (spi_imx->chipselect[i] >= 0)
+ gpio_free(spi_imx->chipselect[i--]);
dev_err(&pdev->dev, "can't get cs gpios");
goto out_master_put;
}
- gpio_direction_output(mxc_spi->chipselect[i], 1);
}
- mxc_spi->bitbang.chipselect = mxc_spi_chipselect;
- mxc_spi->bitbang.setup_transfer = mxc_spi_setupxfer;
- mxc_spi->bitbang.txrx_bufs = mxc_spi_transfer;
- mxc_spi->bitbang.master->setup = mxc_spi_setup;
- mxc_spi->bitbang.master->cleanup = mxc_spi_cleanup;
+ spi_imx->bitbang.chipselect = spi_imx_chipselect;
+ spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
+ spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
+ spi_imx->bitbang.master->setup = spi_imx_setup;
+ spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
+ spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
- init_completion(&mxc_spi->xfer_done);
+ init_completion(&spi_imx->xfer_done);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
goto out_gpio_free;
}
- mxc_spi->base = ioremap(res->start, resource_size(res));
- if (!mxc_spi->base) {
+ spi_imx->base = ioremap(res->start, resource_size(res));
+ if (!spi_imx->base) {
ret = -EINVAL;
goto out_release_mem;
}
- mxc_spi->irq = platform_get_irq(pdev, 0);
- if (!mxc_spi->irq) {
+ spi_imx->irq = platform_get_irq(pdev, 0);
+ if (!spi_imx->irq) {
ret = -EINVAL;
goto out_iounmap;
}
- ret = request_irq(mxc_spi->irq, mxc_spi_isr, 0, DRIVER_NAME, mxc_spi);
+ ret = request_irq(spi_imx->irq, spi_imx_isr, 0, DRIVER_NAME, spi_imx);
if (ret) {
- dev_err(&pdev->dev, "can't get irq%d: %d\n", mxc_spi->irq, ret);
+ dev_err(&pdev->dev, "can't get irq%d: %d\n", spi_imx->irq, ret);
goto out_iounmap;
}
if (cpu_is_mx31() || cpu_is_mx35()) {
- mxc_spi->intctrl = mx31_intctrl;
- mxc_spi->config = mx31_config;
- mxc_spi->trigger = mx31_trigger;
- mxc_spi->rx_available = mx31_rx_available;
+ spi_imx->intctrl = mx31_intctrl;
+ spi_imx->config = mx31_config;
+ spi_imx->trigger = mx31_trigger;
+ spi_imx->rx_available = mx31_rx_available;
} else if (cpu_is_mx27() || cpu_is_mx21()) {
- mxc_spi->intctrl = mx27_intctrl;
- mxc_spi->config = mx27_config;
- mxc_spi->trigger = mx27_trigger;
- mxc_spi->rx_available = mx27_rx_available;
+ spi_imx->intctrl = mx27_intctrl;
+ spi_imx->config = mx27_config;
+ spi_imx->trigger = mx27_trigger;
+ spi_imx->rx_available = mx27_rx_available;
} else if (cpu_is_mx1()) {
- mxc_spi->intctrl = mx1_intctrl;
- mxc_spi->config = mx1_config;
- mxc_spi->trigger = mx1_trigger;
- mxc_spi->rx_available = mx1_rx_available;
+ spi_imx->intctrl = mx1_intctrl;
+ spi_imx->config = mx1_config;
+ spi_imx->trigger = mx1_trigger;
+ spi_imx->rx_available = mx1_rx_available;
} else
BUG();
- mxc_spi->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(mxc_spi->clk)) {
+ spi_imx->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(spi_imx->clk)) {
dev_err(&pdev->dev, "unable to get clock\n");
- ret = PTR_ERR(mxc_spi->clk);
+ ret = PTR_ERR(spi_imx->clk);
goto out_free_irq;
}
- clk_enable(mxc_spi->clk);
- mxc_spi->spi_clk = clk_get_rate(mxc_spi->clk);
+ clk_enable(spi_imx->clk);
+ spi_imx->spi_clk = clk_get_rate(spi_imx->clk);
if (!cpu_is_mx31() || !cpu_is_mx35())
- writel(1, mxc_spi->base + MXC_RESET);
+ writel(1, spi_imx->base + MXC_RESET);
- mxc_spi->intctrl(mxc_spi, 0);
+ spi_imx->intctrl(spi_imx, 0);
- ret = spi_bitbang_start(&mxc_spi->bitbang);
+ ret = spi_bitbang_start(&spi_imx->bitbang);
if (ret) {
dev_err(&pdev->dev, "bitbang start failed with %d\n", ret);
goto out_clk_put;
return ret;
out_clk_put:
- clk_disable(mxc_spi->clk);
- clk_put(mxc_spi->clk);
+ clk_disable(spi_imx->clk);
+ clk_put(spi_imx->clk);
out_free_irq:
- free_irq(mxc_spi->irq, mxc_spi);
+ free_irq(spi_imx->irq, spi_imx);
out_iounmap:
- iounmap(mxc_spi->base);
+ iounmap(spi_imx->base);
out_release_mem:
release_mem_region(res->start, resource_size(res));
out_gpio_free:
for (i = 0; i < master->num_chipselect; i++)
- if (mxc_spi->chipselect[i] >= 0)
- gpio_free(mxc_spi->chipselect[i]);
+ if (spi_imx->chipselect[i] >= 0)
+ gpio_free(spi_imx->chipselect[i]);
out_master_put:
spi_master_put(master);
kfree(master);
return ret;
}
-static int __exit mxc_spi_remove(struct platform_device *pdev)
+static int __exit spi_imx_remove(struct platform_device *pdev)
{
struct spi_master *master = platform_get_drvdata(pdev);
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- struct mxc_spi_data *mxc_spi = spi_master_get_devdata(master);
+ struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
int i;
- spi_bitbang_stop(&mxc_spi->bitbang);
+ spi_bitbang_stop(&spi_imx->bitbang);
- writel(0, mxc_spi->base + MXC_CSPICTRL);
- clk_disable(mxc_spi->clk);
- clk_put(mxc_spi->clk);
- free_irq(mxc_spi->irq, mxc_spi);
- iounmap(mxc_spi->base);
+ writel(0, spi_imx->base + MXC_CSPICTRL);
+ clk_disable(spi_imx->clk);
+ clk_put(spi_imx->clk);
+ free_irq(spi_imx->irq, spi_imx);
+ iounmap(spi_imx->base);
for (i = 0; i < master->num_chipselect; i++)
- if (mxc_spi->chipselect[i] >= 0)
- gpio_free(mxc_spi->chipselect[i]);
+ if (spi_imx->chipselect[i] >= 0)
+ gpio_free(spi_imx->chipselect[i]);
spi_master_put(master);
return 0;
}
-static struct platform_driver mxc_spi_driver = {
+static struct platform_driver spi_imx_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
- .probe = mxc_spi_probe,
- .remove = __exit_p(mxc_spi_remove),
+ .probe = spi_imx_probe,
+ .remove = __exit_p(spi_imx_remove),
};
-static int __init mxc_spi_init(void)
+static int __init spi_imx_init(void)
{
- return platform_driver_register(&mxc_spi_driver);
+ return platform_driver_register(&spi_imx_driver);
}
-static void __exit mxc_spi_exit(void)
+static void __exit spi_imx_exit(void)
{
- platform_driver_unregister(&mxc_spi_driver);
+ platform_driver_unregister(&spi_imx_driver);
}
-module_init(mxc_spi_init);
-module_exit(mxc_spi_exit);
+module_init(spi_imx_init);
+module_exit(spi_imx_exit);
MODULE_DESCRIPTION("SPI Master Controller driver");
MODULE_AUTHOR("Sascha Hauer, Pengutronix");
return status;
}
-static struct file_operations spidev_fops = {
+static const struct file_operations spidev_fops = {
.owner = THIS_MODULE,
/* REVISIT switch to aio primitives, so that userspace
* gets more complete API coverage. It'll simplify things
return retval;
}
-static struct file_operations fops = {
+static const struct file_operations fops = {
.owner = THIS_MODULE,
.read = usbtmc_read,
.write = usbtmc_write,
}
/* used after endpoint configuration */
-static struct file_operations printer_io_operations = {
+static const struct file_operations printer_io_operations = {
.owner = THIS_MODULE,
.open = printer_open,
.read = printer_read,
return single_open(file, pzl_print, inode->i_private);
}
-static struct file_operations di_fops = {
+static const struct file_operations di_fops = {
.open = di_open,
.read = seq_read,
.llseek = seq_lseek,
.owner = THIS_MODULE,
};
-static struct file_operations asl_fops = {
+static const struct file_operations asl_fops = {
.open = asl_open,
.read = seq_read,
.llseek = seq_lseek,
.owner = THIS_MODULE,
};
-static struct file_operations pzl_fops = {
+static const struct file_operations pzl_fops = {
.open = pzl_open,
.read = seq_read,
.llseek = seq_lseek,
return read_count;
}
-static struct
-file_operations usb_rio_fops = {
+static const struct file_operations usb_rio_fops = {
.owner = THIS_MODULE,
.read = read_rio,
.write = write_rio,
return ret < 0 ? ret : len;
}
-static struct file_operations command_fops = {
+static const struct file_operations command_fops = {
.open = command_open,
.write = command_write,
.read = NULL,
return single_open(file, reservations_print, inode->i_private);
}
-static struct file_operations reservations_fops = {
+static const struct file_operations reservations_fops = {
.open = reservations_open,
.read = seq_read,
.llseek = seq_lseek,
return single_open(file, drp_avail_print, inode->i_private);
}
-static struct file_operations drp_avail_fops = {
+static const struct file_operations drp_avail_fops = {
.open = drp_avail_open,
.read = seq_read,
.llseek = seq_lseek,
global = 1;
}
- if (!global && !strstr(options, "fb:")) {
+ if (!global && !strchr(options, ':')) {
fb_mode_option = options;
global = 1;
}
+++ /dev/null
-/* AFS local cache management interface
- *
- * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/fscache.h>
#include <linux/key.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
+#include <linux/fscache.h>
#include "afs.h"
#include "afs_vl.h"
-#include "cache.h"
#define AFS_CELL_MAX_ADDRS 15
#include "btrfs_inode.h"
#include "xattr.h"
-#ifdef CONFIG_FS_POSIX_ACL
+#ifdef CONFIG_BTRFS_POSIX_ACL
static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
{
.set = btrfs_xattr_acl_access_set,
};
-#else /* CONFIG_FS_POSIX_ACL */
+#else /* CONFIG_BTRFS_POSIX_ACL */
int btrfs_acl_chmod(struct inode *inode)
{
return 0;
}
-#endif /* CONFIG_FS_POSIX_ACL */
+#endif /* CONFIG_BTRFS_POSIX_ACL */
*/
u64 last_unlink_trans;
+ /*
+ * These two counters are for delalloc metadata reservations. We keep
+ * track of how many extents we've accounted for vs how many extents we
+ * have.
+ */
+ int delalloc_reserved_extents;
+ int delalloc_extents;
+
/*
* ordered_data_close is set by truncate when a file that used
* to have good data has been truncated to zero. When it is set
current allocations */
u64 bytes_readonly; /* total bytes that are read only */
u64 bytes_super; /* total bytes reserved for the super blocks */
-
- /* delalloc accounting */
- u64 bytes_delalloc; /* number of bytes reserved for allocation,
- this space is not necessarily reserved yet
- by the allocator */
+ u64 bytes_root; /* the number of bytes needed to commit a
+ transaction */
u64 bytes_may_use; /* number of bytes that may be used for
- delalloc */
+ delalloc/allocations */
+ u64 bytes_delalloc; /* number of bytes currently reserved for
+ delayed allocation */
int full; /* indicates that we cannot allocate any more
chunks for this space */
int force_alloc; /* set if we need to force a chunk alloc for
this space */
+ int force_delalloc; /* make people start doing filemap_flush until
+ we're under a threshold */
struct list_head list;
spinlock_t lock;
struct rw_semaphore groups_sem;
atomic_t caching_threads;
+
+ int allocating_chunk;
+ wait_queue_head_t wait;
};
/*
void btrfs_set_inode_space_info(struct btrfs_root *root, struct inode *ionde);
void btrfs_clear_space_info_full(struct btrfs_fs_info *info);
-int btrfs_check_metadata_free_space(struct btrfs_root *root);
+int btrfs_reserve_metadata_space(struct btrfs_root *root, int num_items);
+int btrfs_unreserve_metadata_space(struct btrfs_root *root, int num_items);
+int btrfs_unreserve_metadata_for_delalloc(struct btrfs_root *root,
+ struct inode *inode, int num_items);
+int btrfs_reserve_metadata_for_delalloc(struct btrfs_root *root,
+ struct inode *inode, int num_items);
int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode,
u64 bytes);
void btrfs_free_reserved_data_space(struct btrfs_root *root,
int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
int skip_pinned);
int btrfs_check_file(struct btrfs_root *root, struct inode *inode);
-extern struct file_operations btrfs_file_operations;
+extern const struct file_operations btrfs_file_operations;
int btrfs_drop_extents(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct inode *inode,
u64 start, u64 end, u64 locked_end,
int btrfs_sync_fs(struct super_block *sb, int wait);
/* acl.c */
-#ifdef CONFIG_FS_POSIX_ACL
+#ifdef CONFIG_BTRFS_POSIX_ACL
int btrfs_check_acl(struct inode *inode, int mask);
#else
#define btrfs_check_acl NULL
int btrfs_write_tree_block(struct extent_buffer *buf)
{
- return btrfs_fdatawrite_range(buf->first_page->mapping, buf->start,
- buf->start + buf->len - 1, WB_SYNC_ALL);
+ return filemap_fdatawrite_range(buf->first_page->mapping, buf->start,
+ buf->start + buf->len - 1);
}
int btrfs_wait_tree_block_writeback(struct extent_buffer *buf)
{
- return btrfs_wait_on_page_writeback_range(buf->first_page->mapping,
- buf->start, buf->start + buf->len - 1);
+ return filemap_fdatawait_range(buf->first_page->mapping,
+ buf->start, buf->start + buf->len - 1);
}
struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
fs_info->sb = sb;
fs_info->max_extent = (u64)-1;
fs_info->max_inline = 8192 * 1024;
- fs_info->metadata_ratio = 8;
+ fs_info->metadata_ratio = 0;
fs_info->thread_pool_size = min_t(unsigned long,
num_online_cpus() + 2, 8);
struct extent_buffer **must_clean);
static int find_next_key(struct btrfs_path *path, int level,
struct btrfs_key *key);
+static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
+ int dump_block_groups);
static noinline int
block_group_cache_done(struct btrfs_block_group_cache *cache)
alloc_target);
}
+static u64 calculate_bytes_needed(struct btrfs_root *root, int num_items)
+{
+ u64 num_bytes;
+ int level;
+
+ level = BTRFS_MAX_LEVEL - 2;
+ /*
+ * NOTE: these calculations are absolutely the worst possible case.
+ * This assumes that _every_ item we insert will require a new leaf, and
+ * that the tree has grown to its maximum level size.
+ */
+
+ /*
+ * for every item we insert we could insert both an extent item and a
+ * extent ref item. Then for ever item we insert, we will need to cow
+ * both the original leaf, plus the leaf to the left and right of it.
+ *
+ * Unless we are talking about the extent root, then we just want the
+ * number of items * 2, since we just need the extent item plus its ref.
+ */
+ if (root == root->fs_info->extent_root)
+ num_bytes = num_items * 2;
+ else
+ num_bytes = (num_items + (2 * num_items)) * 3;
+
+ /*
+ * num_bytes is total number of leaves we could need times the leaf
+ * size, and then for every leaf we could end up cow'ing 2 nodes per
+ * level, down to the leaf level.
+ */
+ num_bytes = (num_bytes * root->leafsize) +
+ (num_bytes * (level * 2)) * root->nodesize;
+
+ return num_bytes;
+}
+
/*
- * for now this just makes sure we have at least 5% of our metadata space free
- * for use.
+ * Unreserve metadata space for delalloc. If we have less reserved credits than
+ * we have extents, this function does nothing.
*/
-int btrfs_check_metadata_free_space(struct btrfs_root *root)
+int btrfs_unreserve_metadata_for_delalloc(struct btrfs_root *root,
+ struct inode *inode, int num_items)
{
struct btrfs_fs_info *info = root->fs_info;
struct btrfs_space_info *meta_sinfo;
- u64 alloc_target, thresh;
- int committed = 0, ret;
+ u64 num_bytes;
+ u64 alloc_target;
+ bool bug = false;
/* get the space info for where the metadata will live */
alloc_target = btrfs_get_alloc_profile(root, 0);
meta_sinfo = __find_space_info(info, alloc_target);
- if (!meta_sinfo)
- goto alloc;
-again:
+ num_bytes = calculate_bytes_needed(root->fs_info->extent_root,
+ num_items);
+
spin_lock(&meta_sinfo->lock);
- if (!meta_sinfo->full)
- thresh = meta_sinfo->total_bytes * 80;
- else
- thresh = meta_sinfo->total_bytes * 95;
+ if (BTRFS_I(inode)->delalloc_reserved_extents <=
+ BTRFS_I(inode)->delalloc_extents) {
+ spin_unlock(&meta_sinfo->lock);
+ return 0;
+ }
+
+ BTRFS_I(inode)->delalloc_reserved_extents--;
+ BUG_ON(BTRFS_I(inode)->delalloc_reserved_extents < 0);
+
+ if (meta_sinfo->bytes_delalloc < num_bytes) {
+ bug = true;
+ meta_sinfo->bytes_delalloc = 0;
+ } else {
+ meta_sinfo->bytes_delalloc -= num_bytes;
+ }
+ spin_unlock(&meta_sinfo->lock);
+ BUG_ON(bug);
+
+ return 0;
+}
+
+static void check_force_delalloc(struct btrfs_space_info *meta_sinfo)
+{
+ u64 thresh;
+
+ thresh = meta_sinfo->bytes_used + meta_sinfo->bytes_reserved +
+ meta_sinfo->bytes_pinned + meta_sinfo->bytes_readonly +
+ meta_sinfo->bytes_super + meta_sinfo->bytes_root +
+ meta_sinfo->bytes_may_use;
+
+ thresh = meta_sinfo->total_bytes - thresh;
+ thresh *= 80;
do_div(thresh, 100);
+ if (thresh <= meta_sinfo->bytes_delalloc)
+ meta_sinfo->force_delalloc = 1;
+ else
+ meta_sinfo->force_delalloc = 0;
+}
- if (meta_sinfo->bytes_used + meta_sinfo->bytes_reserved +
- meta_sinfo->bytes_pinned + meta_sinfo->bytes_readonly +
- meta_sinfo->bytes_super > thresh) {
- struct btrfs_trans_handle *trans;
- if (!meta_sinfo->full) {
- meta_sinfo->force_alloc = 1;
+static int maybe_allocate_chunk(struct btrfs_root *root,
+ struct btrfs_space_info *info)
+{
+ struct btrfs_super_block *disk_super = &root->fs_info->super_copy;
+ struct btrfs_trans_handle *trans;
+ bool wait = false;
+ int ret = 0;
+ u64 min_metadata;
+ u64 free_space;
+
+ free_space = btrfs_super_total_bytes(disk_super);
+ /*
+ * we allow the metadata to grow to a max of either 5gb or 5% of the
+ * space in the volume.
+ */
+ min_metadata = min((u64)5 * 1024 * 1024 * 1024,
+ div64_u64(free_space * 5, 100));
+ if (info->total_bytes >= min_metadata) {
+ spin_unlock(&info->lock);
+ return 0;
+ }
+
+ if (info->full) {
+ spin_unlock(&info->lock);
+ return 0;
+ }
+
+ if (!info->allocating_chunk) {
+ info->force_alloc = 1;
+ info->allocating_chunk = 1;
+ init_waitqueue_head(&info->wait);
+ } else {
+ wait = true;
+ }
+
+ spin_unlock(&info->lock);
+
+ if (wait) {
+ wait_event(info->wait,
+ !info->allocating_chunk);
+ return 1;
+ }
+
+ trans = btrfs_start_transaction(root, 1);
+ if (!trans) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = do_chunk_alloc(trans, root->fs_info->extent_root,
+ 4096 + 2 * 1024 * 1024,
+ info->flags, 0);
+ btrfs_end_transaction(trans, root);
+ if (ret)
+ goto out;
+out:
+ spin_lock(&info->lock);
+ info->allocating_chunk = 0;
+ spin_unlock(&info->lock);
+ wake_up(&info->wait);
+
+ if (ret)
+ return 0;
+ return 1;
+}
+
+/*
+ * Reserve metadata space for delalloc.
+ */
+int btrfs_reserve_metadata_for_delalloc(struct btrfs_root *root,
+ struct inode *inode, int num_items)
+{
+ struct btrfs_fs_info *info = root->fs_info;
+ struct btrfs_space_info *meta_sinfo;
+ u64 num_bytes;
+ u64 used;
+ u64 alloc_target;
+ int flushed = 0;
+ int force_delalloc;
+
+ /* get the space info for where the metadata will live */
+ alloc_target = btrfs_get_alloc_profile(root, 0);
+ meta_sinfo = __find_space_info(info, alloc_target);
+
+ num_bytes = calculate_bytes_needed(root->fs_info->extent_root,
+ num_items);
+again:
+ spin_lock(&meta_sinfo->lock);
+
+ force_delalloc = meta_sinfo->force_delalloc;
+
+ if (unlikely(!meta_sinfo->bytes_root))
+ meta_sinfo->bytes_root = calculate_bytes_needed(root, 6);
+
+ if (!flushed)
+ meta_sinfo->bytes_delalloc += num_bytes;
+
+ used = meta_sinfo->bytes_used + meta_sinfo->bytes_reserved +
+ meta_sinfo->bytes_pinned + meta_sinfo->bytes_readonly +
+ meta_sinfo->bytes_super + meta_sinfo->bytes_root +
+ meta_sinfo->bytes_may_use + meta_sinfo->bytes_delalloc;
+
+ if (used > meta_sinfo->total_bytes) {
+ flushed++;
+
+ if (flushed == 1) {
+ if (maybe_allocate_chunk(root, meta_sinfo))
+ goto again;
+ flushed++;
+ } else {
spin_unlock(&meta_sinfo->lock);
-alloc:
- trans = btrfs_start_transaction(root, 1);
- if (!trans)
- return -ENOMEM;
+ }
- ret = do_chunk_alloc(trans, root->fs_info->extent_root,
- 2 * 1024 * 1024, alloc_target, 0);
- btrfs_end_transaction(trans, root);
- if (!meta_sinfo) {
- meta_sinfo = __find_space_info(info,
- alloc_target);
- }
+ if (flushed == 2) {
+ filemap_flush(inode->i_mapping);
+ goto again;
+ } else if (flushed == 3) {
+ btrfs_start_delalloc_inodes(root);
+ btrfs_wait_ordered_extents(root, 0);
goto again;
}
+ spin_lock(&meta_sinfo->lock);
+ meta_sinfo->bytes_delalloc -= num_bytes;
spin_unlock(&meta_sinfo->lock);
+ printk(KERN_ERR "enospc, has %d, reserved %d\n",
+ BTRFS_I(inode)->delalloc_extents,
+ BTRFS_I(inode)->delalloc_reserved_extents);
+ dump_space_info(meta_sinfo, 0, 0);
+ return -ENOSPC;
+ }
- if (!committed) {
- committed = 1;
- trans = btrfs_join_transaction(root, 1);
- if (!trans)
- return -ENOMEM;
- ret = btrfs_commit_transaction(trans, root);
- if (ret)
- return ret;
+ BTRFS_I(inode)->delalloc_reserved_extents++;
+ check_force_delalloc(meta_sinfo);
+ spin_unlock(&meta_sinfo->lock);
+
+ if (!flushed && force_delalloc)
+ filemap_flush(inode->i_mapping);
+
+ return 0;
+}
+
+/*
+ * unreserve num_items number of items worth of metadata space. This needs to
+ * be paired with btrfs_reserve_metadata_space.
+ *
+ * NOTE: if you have the option, run this _AFTER_ you do a
+ * btrfs_end_transaction, since btrfs_end_transaction will run delayed ref
+ * oprations which will result in more used metadata, so we want to make sure we
+ * can do that without issue.
+ */
+int btrfs_unreserve_metadata_space(struct btrfs_root *root, int num_items)
+{
+ struct btrfs_fs_info *info = root->fs_info;
+ struct btrfs_space_info *meta_sinfo;
+ u64 num_bytes;
+ u64 alloc_target;
+ bool bug = false;
+
+ /* get the space info for where the metadata will live */
+ alloc_target = btrfs_get_alloc_profile(root, 0);
+ meta_sinfo = __find_space_info(info, alloc_target);
+
+ num_bytes = calculate_bytes_needed(root, num_items);
+
+ spin_lock(&meta_sinfo->lock);
+ if (meta_sinfo->bytes_may_use < num_bytes) {
+ bug = true;
+ meta_sinfo->bytes_may_use = 0;
+ } else {
+ meta_sinfo->bytes_may_use -= num_bytes;
+ }
+ spin_unlock(&meta_sinfo->lock);
+
+ BUG_ON(bug);
+
+ return 0;
+}
+
+/*
+ * Reserve some metadata space for use. We'll calculate the worste case number
+ * of bytes that would be needed to modify num_items number of items. If we
+ * have space, fantastic, if not, you get -ENOSPC. Please call
+ * btrfs_unreserve_metadata_space when you are done for the _SAME_ number of
+ * items you reserved, since whatever metadata you needed should have already
+ * been allocated.
+ *
+ * This will commit the transaction to make more space if we don't have enough
+ * metadata space. THe only time we don't do this is if we're reserving space
+ * inside of a transaction, then we will just return -ENOSPC and it is the
+ * callers responsibility to handle it properly.
+ */
+int btrfs_reserve_metadata_space(struct btrfs_root *root, int num_items)
+{
+ struct btrfs_fs_info *info = root->fs_info;
+ struct btrfs_space_info *meta_sinfo;
+ u64 num_bytes;
+ u64 used;
+ u64 alloc_target;
+ int retries = 0;
+
+ /* get the space info for where the metadata will live */
+ alloc_target = btrfs_get_alloc_profile(root, 0);
+ meta_sinfo = __find_space_info(info, alloc_target);
+
+ num_bytes = calculate_bytes_needed(root, num_items);
+again:
+ spin_lock(&meta_sinfo->lock);
+
+ if (unlikely(!meta_sinfo->bytes_root))
+ meta_sinfo->bytes_root = calculate_bytes_needed(root, 6);
+
+ if (!retries)
+ meta_sinfo->bytes_may_use += num_bytes;
+
+ used = meta_sinfo->bytes_used + meta_sinfo->bytes_reserved +
+ meta_sinfo->bytes_pinned + meta_sinfo->bytes_readonly +
+ meta_sinfo->bytes_super + meta_sinfo->bytes_root +
+ meta_sinfo->bytes_may_use + meta_sinfo->bytes_delalloc;
+
+ if (used > meta_sinfo->total_bytes) {
+ retries++;
+ if (retries == 1) {
+ if (maybe_allocate_chunk(root, meta_sinfo))
+ goto again;
+ retries++;
+ } else {
+ spin_unlock(&meta_sinfo->lock);
+ }
+
+ if (retries == 2) {
+ btrfs_start_delalloc_inodes(root);
+ btrfs_wait_ordered_extents(root, 0);
goto again;
}
+ spin_lock(&meta_sinfo->lock);
+ meta_sinfo->bytes_may_use -= num_bytes;
+ spin_unlock(&meta_sinfo->lock);
+
+ dump_space_info(meta_sinfo, 0, 0);
return -ENOSPC;
}
+
+ check_force_delalloc(meta_sinfo);
spin_unlock(&meta_sinfo->lock);
return 0;
spin_unlock(&data_sinfo->lock);
/* commit the current transaction and try again */
- if (!committed) {
+ if (!committed && !root->fs_info->open_ioctl_trans) {
committed = 1;
trans = btrfs_join_transaction(root, 1);
if (!trans)
BTRFS_I(inode)->reserved_bytes += bytes;
spin_unlock(&data_sinfo->lock);
- return btrfs_check_metadata_free_space(root);
+ return 0;
}
/*
BUG_ON(!space_info);
spin_lock(&space_info->lock);
- if (space_info->force_alloc) {
+ if (space_info->force_alloc)
force = 1;
- space_info->force_alloc = 0;
- }
if (space_info->full) {
spin_unlock(&space_info->lock);
goto out;
}
thresh = space_info->total_bytes - space_info->bytes_readonly;
- thresh = div_factor(thresh, 6);
+ thresh = div_factor(thresh, 8);
if (!force &&
(space_info->bytes_used + space_info->bytes_pinned +
space_info->bytes_reserved + alloc_bytes) < thresh) {
* we keep a reasonable number of metadata chunks allocated in the
* FS as well.
*/
- if (flags & BTRFS_BLOCK_GROUP_DATA) {
+ if (flags & BTRFS_BLOCK_GROUP_DATA && fs_info->metadata_ratio) {
fs_info->data_chunk_allocations++;
if (!(fs_info->data_chunk_allocations %
fs_info->metadata_ratio))
}
ret = btrfs_alloc_chunk(trans, extent_root, flags);
+ spin_lock(&space_info->lock);
if (ret)
space_info->full = 1;
+ space_info->force_alloc = 0;
+ spin_unlock(&space_info->lock);
out:
mutex_unlock(&extent_root->fs_info->chunk_mutex);
return ret;
return ret;
}
-static void dump_space_info(struct btrfs_space_info *info, u64 bytes)
+static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
+ int dump_block_groups)
{
struct btrfs_block_group_cache *cache;
+ spin_lock(&info->lock);
printk(KERN_INFO "space_info has %llu free, is %sfull\n",
(unsigned long long)(info->total_bytes - info->bytes_used -
- info->bytes_pinned - info->bytes_reserved),
+ info->bytes_pinned - info->bytes_reserved -
+ info->bytes_super),
(info->full) ? "" : "not ");
printk(KERN_INFO "space_info total=%llu, pinned=%llu, delalloc=%llu,"
- " may_use=%llu, used=%llu\n",
+ " may_use=%llu, used=%llu, root=%llu, super=%llu, reserved=%llu"
+ "\n",
(unsigned long long)info->total_bytes,
(unsigned long long)info->bytes_pinned,
(unsigned long long)info->bytes_delalloc,
(unsigned long long)info->bytes_may_use,
- (unsigned long long)info->bytes_used);
+ (unsigned long long)info->bytes_used,
+ (unsigned long long)info->bytes_root,
+ (unsigned long long)info->bytes_super,
+ (unsigned long long)info->bytes_reserved);
+ spin_unlock(&info->lock);
+
+ if (!dump_block_groups)
+ return;
down_read(&info->groups_sem);
list_for_each_entry(cache, &info->block_groups, list) {
printk(KERN_ERR "btrfs allocation failed flags %llu, "
"wanted %llu\n", (unsigned long long)data,
(unsigned long long)num_bytes);
- dump_space_info(sinfo, num_bytes);
+ dump_space_info(sinfo, num_bytes, 1);
}
return ret;
return NULL;
}
+static void merge_cb(struct extent_io_tree *tree, struct extent_state *new,
+ struct extent_state *other)
+{
+ if (tree->ops && tree->ops->merge_extent_hook)
+ tree->ops->merge_extent_hook(tree->mapping->host, new,
+ other);
+}
+
/*
* utility function to look for merge candidates inside a given range.
* Any extents with matching state are merged together into a single
other = rb_entry(other_node, struct extent_state, rb_node);
if (other->end == state->start - 1 &&
other->state == state->state) {
+ merge_cb(tree, state, other);
state->start = other->start;
other->tree = NULL;
rb_erase(&other->rb_node, &tree->state);
other = rb_entry(other_node, struct extent_state, rb_node);
if (other->start == state->end + 1 &&
other->state == state->state) {
+ merge_cb(tree, state, other);
other->start = state->start;
state->tree = NULL;
rb_erase(&state->rb_node, &tree->state);
free_extent_state(state);
+ state = NULL;
}
}
+
return 0;
}
-static void set_state_cb(struct extent_io_tree *tree,
+static int set_state_cb(struct extent_io_tree *tree,
struct extent_state *state,
unsigned long bits)
{
if (tree->ops && tree->ops->set_bit_hook) {
- tree->ops->set_bit_hook(tree->mapping->host, state->start,
- state->end, state->state, bits);
+ return tree->ops->set_bit_hook(tree->mapping->host,
+ state->start, state->end,
+ state->state, bits);
}
+
+ return 0;
}
static void clear_state_cb(struct extent_io_tree *tree,
struct extent_state *state,
unsigned long bits)
{
- if (tree->ops && tree->ops->clear_bit_hook) {
- tree->ops->clear_bit_hook(tree->mapping->host, state->start,
- state->end, state->state, bits);
- }
+ if (tree->ops && tree->ops->clear_bit_hook)
+ tree->ops->clear_bit_hook(tree->mapping->host, state, bits);
}
/*
int bits)
{
struct rb_node *node;
+ int ret;
if (end < start) {
printk(KERN_ERR "btrfs end < start %llu %llu\n",
(unsigned long long)start);
WARN_ON(1);
}
- if (bits & EXTENT_DIRTY)
- tree->dirty_bytes += end - start + 1;
state->start = start;
state->end = end;
- set_state_cb(tree, state, bits);
+ ret = set_state_cb(tree, state, bits);
+ if (ret)
+ return ret;
+
+ if (bits & EXTENT_DIRTY)
+ tree->dirty_bytes += end - start + 1;
state->state |= bits;
node = tree_insert(&tree->state, end, &state->rb_node);
if (node) {
return 0;
}
+static int split_cb(struct extent_io_tree *tree, struct extent_state *orig,
+ u64 split)
+{
+ if (tree->ops && tree->ops->split_extent_hook)
+ return tree->ops->split_extent_hook(tree->mapping->host,
+ orig, split);
+ return 0;
+}
+
/*
* split a given extent state struct in two, inserting the preallocated
* struct 'prealloc' as the newly created second half. 'split' indicates an
struct extent_state *prealloc, u64 split)
{
struct rb_node *node;
+
+ split_cb(tree, orig, split);
+
prealloc->start = orig->start;
prealloc->end = split - 1;
prealloc->state = orig->state;
if (err)
goto out;
if (state->end <= end) {
- set |= clear_state_bit(tree, state, bits,
- wake, delete);
+ set |= clear_state_bit(tree, state, bits, wake,
+ delete);
if (last_end == (u64)-1)
goto out;
start = last_end + 1;
prealloc = alloc_extent_state(GFP_ATOMIC);
err = split_state(tree, state, prealloc, end + 1);
BUG_ON(err == -EEXIST);
-
if (wake)
wake_up(&state->wq);
- set |= clear_state_bit(tree, prealloc, bits,
- wake, delete);
+ set |= clear_state_bit(tree, prealloc, bits, wake, delete);
+
prealloc = NULL;
goto out;
}
return 0;
}
-static void set_state_bits(struct extent_io_tree *tree,
+static int set_state_bits(struct extent_io_tree *tree,
struct extent_state *state,
int bits)
{
+ int ret;
+
+ ret = set_state_cb(tree, state, bits);
+ if (ret)
+ return ret;
+
if ((bits & EXTENT_DIRTY) && !(state->state & EXTENT_DIRTY)) {
u64 range = state->end - state->start + 1;
tree->dirty_bytes += range;
}
- set_state_cb(tree, state, bits);
state->state |= bits;
+
+ return 0;
}
static void cache_state(struct extent_state *state,
goto out;
}
- set_state_bits(tree, state, bits);
+ err = set_state_bits(tree, state, bits);
+ if (err)
+ goto out;
+
cache_state(state, cached_state);
merge_state(tree, state);
if (last_end == (u64)-1)
if (err)
goto out;
if (state->end <= end) {
- set_state_bits(tree, state, bits);
+ err = set_state_bits(tree, state, bits);
+ if (err)
+ goto out;
cache_state(state, cached_state);
merge_state(tree, state);
if (last_end == (u64)-1)
this_end = last_start - 1;
err = insert_state(tree, prealloc, start, this_end,
bits);
- cache_state(prealloc, cached_state);
- prealloc = NULL;
BUG_ON(err == -EEXIST);
- if (err)
+ if (err) {
+ prealloc = NULL;
goto out;
+ }
+ cache_state(prealloc, cached_state);
+ prealloc = NULL;
start = this_end + 1;
goto search_again;
}
err = split_state(tree, state, prealloc, end + 1);
BUG_ON(err == -EEXIST);
- set_state_bits(tree, prealloc, bits);
+ err = set_state_bits(tree, prealloc, bits);
+ if (err) {
+ prealloc = NULL;
+ goto out;
+ }
cache_state(prealloc, cached_state);
merge_state(tree, prealloc);
prealloc = NULL;
struct extent_state *state, int uptodate);
int (*set_bit_hook)(struct inode *inode, u64 start, u64 end,
unsigned long old, unsigned long bits);
- int (*clear_bit_hook)(struct inode *inode, u64 start, u64 end,
- unsigned long old, unsigned long bits);
+ int (*clear_bit_hook)(struct inode *inode, struct extent_state *state,
+ unsigned long bits);
+ int (*merge_extent_hook)(struct inode *inode,
+ struct extent_state *new,
+ struct extent_state *other);
+ int (*split_extent_hook)(struct inode *inode,
+ struct extent_state *orig, u64 split);
int (*write_cache_pages_lock_hook)(struct page *page);
};
u64 start;
u64 end; /* inclusive */
struct rb_node rb_node;
+
+ /* ADD NEW ELEMENTS AFTER THIS */
struct extent_io_tree *tree;
wait_queue_head_t wq;
atomic_t refs;
unsigned long state;
+ u64 split_start;
+ u64 split_end;
/* for use by the FS */
u64 private;
root->sectorsize - 1) & ~((u64)root->sectorsize - 1);
end_of_last_block = start_pos + num_bytes - 1;
- btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block);
+ err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block);
+ if (err)
+ return err;
+
for (i = 0; i < num_pages; i++) {
struct page *p = pages[i];
SetPageUptodate(p);
start_pos = pos;
vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
+
+ /* do the reserve before the mutex lock in case we have to do some
+ * flushing. We wouldn't deadlock, but this is more polite.
+ */
+ err = btrfs_reserve_metadata_for_delalloc(root, inode, 1);
+ if (err)
+ goto out_nolock;
+
+ mutex_lock(&inode->i_mutex);
+
current->backing_dev_info = inode->i_mapping->backing_dev_info;
err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
if (err)
- goto out_nolock;
+ goto out;
+
if (count == 0)
- goto out_nolock;
+ goto out;
err = file_remove_suid(file);
if (err)
- goto out_nolock;
+ goto out;
+
file_update_time(file);
pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL);
- mutex_lock(&inode->i_mutex);
+ /* generic_write_checks can change our pos */
+ start_pos = pos;
+
BTRFS_I(inode)->sequence++;
first_index = pos >> PAGE_CACHE_SHIFT;
last_index = (pos + count) >> PAGE_CACHE_SHIFT;
}
if (will_write) {
- btrfs_fdatawrite_range(inode->i_mapping, pos,
- pos + write_bytes - 1,
- WB_SYNC_ALL);
+ filemap_fdatawrite_range(inode->i_mapping, pos,
+ pos + write_bytes - 1);
} else {
balance_dirty_pages_ratelimited_nr(inode->i_mapping,
num_pages);
mutex_unlock(&inode->i_mutex);
if (ret)
err = ret;
+ btrfs_unreserve_metadata_for_delalloc(root, inode, 1);
out_nolock:
kfree(pages);
return 0;
}
-struct file_operations btrfs_file_operations = {
+const struct file_operations btrfs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.aio_read = generic_file_aio_read,
static const struct inode_operations btrfs_file_inode_operations;
static const struct address_space_operations btrfs_aops;
static const struct address_space_operations btrfs_symlink_aops;
-static struct file_operations btrfs_dir_file_operations;
+static const struct file_operations btrfs_dir_file_operations;
static struct extent_io_ops btrfs_extent_io_ops;
static struct kmem_cache *btrfs_inode_cachep;
return ret;
}
+static int btrfs_split_extent_hook(struct inode *inode,
+ struct extent_state *orig, u64 split)
+{
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ u64 size;
+
+ if (!(orig->state & EXTENT_DELALLOC))
+ return 0;
+
+ size = orig->end - orig->start + 1;
+ if (size > root->fs_info->max_extent) {
+ u64 num_extents;
+ u64 new_size;
+
+ new_size = orig->end - split + 1;
+ num_extents = div64_u64(size + root->fs_info->max_extent - 1,
+ root->fs_info->max_extent);
+
+ /*
+ * if we break a large extent up then leave delalloc_extents be,
+ * since we've already accounted for the large extent.
+ */
+ if (div64_u64(new_size + root->fs_info->max_extent - 1,
+ root->fs_info->max_extent) < num_extents)
+ return 0;
+ }
+
+ BTRFS_I(inode)->delalloc_extents++;
+
+ return 0;
+}
+
+/*
+ * extent_io.c merge_extent_hook, used to track merged delayed allocation
+ * extents so we can keep track of new extents that are just merged onto old
+ * extents, such as when we are doing sequential writes, so we can properly
+ * account for the metadata space we'll need.
+ */
+static int btrfs_merge_extent_hook(struct inode *inode,
+ struct extent_state *new,
+ struct extent_state *other)
+{
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ u64 new_size, old_size;
+ u64 num_extents;
+
+ /* not delalloc, ignore it */
+ if (!(other->state & EXTENT_DELALLOC))
+ return 0;
+
+ old_size = other->end - other->start + 1;
+ if (new->start < other->start)
+ new_size = other->end - new->start + 1;
+ else
+ new_size = new->end - other->start + 1;
+
+ /* we're not bigger than the max, unreserve the space and go */
+ if (new_size <= root->fs_info->max_extent) {
+ BTRFS_I(inode)->delalloc_extents--;
+ return 0;
+ }
+
+ /*
+ * If we grew by another max_extent, just return, we want to keep that
+ * reserved amount.
+ */
+ num_extents = div64_u64(old_size + root->fs_info->max_extent - 1,
+ root->fs_info->max_extent);
+ if (div64_u64(new_size + root->fs_info->max_extent - 1,
+ root->fs_info->max_extent) > num_extents)
+ return 0;
+
+ BTRFS_I(inode)->delalloc_extents--;
+
+ return 0;
+}
+
/*
* extent_io.c set_bit_hook, used to track delayed allocation
* bytes in this file, and to maintain the list of inodes that
static int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end,
unsigned long old, unsigned long bits)
{
+
/*
* set_bit and clear bit hooks normally require _irqsave/restore
* but in this case, we are only testeing for the DELALLOC
*/
if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) {
struct btrfs_root *root = BTRFS_I(inode)->root;
+
+ BTRFS_I(inode)->delalloc_extents++;
btrfs_delalloc_reserve_space(root, inode, end - start + 1);
spin_lock(&root->fs_info->delalloc_lock);
BTRFS_I(inode)->delalloc_bytes += end - start + 1;
/*
* extent_io.c clear_bit_hook, see set_bit_hook for why
*/
-static int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end,
- unsigned long old, unsigned long bits)
+static int btrfs_clear_bit_hook(struct inode *inode,
+ struct extent_state *state, unsigned long bits)
{
/*
* set_bit and clear bit hooks normally require _irqsave/restore
* but in this case, we are only testeing for the DELALLOC
* bit, which is only set or cleared with irqs on
*/
- if ((old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) {
+ if ((state->state & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) {
struct btrfs_root *root = BTRFS_I(inode)->root;
+ BTRFS_I(inode)->delalloc_extents--;
+ btrfs_unreserve_metadata_for_delalloc(root, inode, 1);
+
spin_lock(&root->fs_info->delalloc_lock);
- if (end - start + 1 > root->fs_info->delalloc_bytes) {
+ if (state->end - state->start + 1 >
+ root->fs_info->delalloc_bytes) {
printk(KERN_INFO "btrfs warning: delalloc account "
"%llu %llu\n",
- (unsigned long long)end - start + 1,
+ (unsigned long long)
+ state->end - state->start + 1,
(unsigned long long)
root->fs_info->delalloc_bytes);
btrfs_delalloc_free_space(root, inode, (u64)-1);
BTRFS_I(inode)->delalloc_bytes = 0;
} else {
btrfs_delalloc_free_space(root, inode,
- end - start + 1);
- root->fs_info->delalloc_bytes -= end - start + 1;
- BTRFS_I(inode)->delalloc_bytes -= end - start + 1;
+ state->end -
+ state->start + 1);
+ root->fs_info->delalloc_bytes -= state->end -
+ state->start + 1;
+ BTRFS_I(inode)->delalloc_bytes -= state->end -
+ state->start + 1;
}
if (BTRFS_I(inode)->delalloc_bytes == 0 &&
!list_empty(&BTRFS_I(inode)->delalloc_inodes)) {
goto again;
}
- btrfs_set_extent_delalloc(inode, page_start, page_end);
+ ret = btrfs_set_extent_delalloc(inode, page_start, page_end);
+ if (ret) {
+ unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
+ goto out_unlock;
+ }
+
ret = 0;
if (offset != PAGE_CACHE_SIZE) {
kaddr = kmap(page);
u64 last_byte;
u64 cur_offset;
u64 hole_size;
- int err;
+ int err = 0;
if (size <= hole_start)
return 0;
- err = btrfs_check_metadata_free_space(root);
- if (err)
- return err;
-
btrfs_truncate_page(inode->i_mapping, inode->i_size);
while (1) {
cur_offset, &hint_byte, 1);
if (err)
break;
+
+ err = btrfs_reserve_metadata_space(root, 1);
+ if (err)
+ break;
+
err = btrfs_insert_file_extent(trans, root,
inode->i_ino, cur_offset, 0,
0, hole_size, 0, hole_size,
0, 0, 0);
btrfs_drop_extent_cache(inode, hole_start,
last_byte - 1, 0);
+ btrfs_unreserve_metadata_space(root, 1);
}
free_extent_map(em);
cur_offset = last_byte;
if (!new_valid_dev(rdev))
return -EINVAL;
- err = btrfs_check_metadata_free_space(root);
+ /*
+ * 2 for inode item and ref
+ * 2 for dir items
+ * 1 for xattr if selinux is on
+ */
+ err = btrfs_reserve_metadata_space(root, 5);
if (err)
- goto fail;
+ return err;
trans = btrfs_start_transaction(root, 1);
+ if (!trans)
+ goto fail;
btrfs_set_trans_block_group(trans, dir);
err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
nr = trans->blocks_used;
btrfs_end_transaction_throttle(trans, root);
fail:
+ btrfs_unreserve_metadata_space(root, 5);
if (drop_inode) {
inode_dec_link_count(inode);
iput(inode);
u64 objectid;
u64 index = 0;
- err = btrfs_check_metadata_free_space(root);
+ /*
+ * 2 for inode item and ref
+ * 2 for dir items
+ * 1 for xattr if selinux is on
+ */
+ err = btrfs_reserve_metadata_space(root, 5);
if (err)
- goto fail;
+ return err;
+
trans = btrfs_start_transaction(root, 1);
+ if (!trans)
+ goto fail;
btrfs_set_trans_block_group(trans, dir);
err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
nr = trans->blocks_used;
btrfs_end_transaction_throttle(trans, root);
fail:
+ btrfs_unreserve_metadata_space(root, 5);
if (drop_inode) {
inode_dec_link_count(inode);
iput(inode);
if (inode->i_nlink == 0)
return -ENOENT;
- btrfs_inc_nlink(inode);
- err = btrfs_check_metadata_free_space(root);
+ /*
+ * 1 item for inode ref
+ * 2 items for dir items
+ */
+ err = btrfs_reserve_metadata_space(root, 3);
if (err)
- goto fail;
+ return err;
+
+ btrfs_inc_nlink(inode);
+
err = btrfs_set_inode_index(dir, &index);
if (err)
goto fail;
nr = trans->blocks_used;
btrfs_end_transaction_throttle(trans, root);
fail:
+ btrfs_unreserve_metadata_space(root, 3);
if (drop_inode) {
inode_dec_link_count(inode);
iput(inode);
u64 index = 0;
unsigned long nr = 1;
- err = btrfs_check_metadata_free_space(root);
+ /*
+ * 2 items for inode and ref
+ * 2 items for dir items
+ * 1 for xattr if selinux is on
+ */
+ err = btrfs_reserve_metadata_space(root, 5);
if (err)
- goto out_unlock;
+ return err;
trans = btrfs_start_transaction(root, 1);
- btrfs_set_trans_block_group(trans, dir);
-
- if (IS_ERR(trans)) {
- err = PTR_ERR(trans);
+ if (!trans) {
+ err = -ENOMEM;
goto out_unlock;
}
+ btrfs_set_trans_block_group(trans, dir);
err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
if (err) {
btrfs_end_transaction_throttle(trans, root);
out_unlock:
+ btrfs_unreserve_metadata_space(root, 5);
if (drop_on_err)
iput(inode);
btrfs_btree_balance_dirty(root, nr);
goto out;
}
+ ret = btrfs_reserve_metadata_for_delalloc(root, inode, 1);
+ if (ret) {
+ btrfs_free_reserved_data_space(root, inode, PAGE_CACHE_SIZE);
+ ret = VM_FAULT_SIGBUS;
+ goto out;
+ }
+
ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */
again:
lock_page(page);
goto again;
}
- btrfs_set_extent_delalloc(inode, page_start, page_end);
+ /*
+ * XXX - page_mkwrite gets called every time the page is dirtied, even
+ * if it was already dirty, so for space accounting reasons we need to
+ * clear any delalloc bits for the range we are fixing to save. There
+ * is probably a better way to do this, but for now keep consistent with
+ * prepare_pages in the normal write path.
+ */
+ clear_extent_bits(&BTRFS_I(inode)->io_tree, page_start, page_end,
+ EXTENT_DIRTY | EXTENT_DELALLOC, GFP_NOFS);
+
+ ret = btrfs_set_extent_delalloc(inode, page_start, page_end);
+ if (ret) {
+ unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
+ ret = VM_FAULT_SIGBUS;
+ btrfs_free_reserved_data_space(root, inode, PAGE_CACHE_SIZE);
+ goto out_unlock;
+ }
ret = 0;
/* page is wholly or partially inside EOF */
unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
out_unlock:
+ btrfs_unreserve_metadata_for_delalloc(root, inode, 1);
if (!ret)
return VM_FAULT_LOCKED;
unlock_page(page);
return NULL;
ei->last_trans = 0;
ei->logged_trans = 0;
+ ei->delalloc_extents = 0;
+ ei->delalloc_reserved_extents = 0;
btrfs_ordered_inode_tree_init(&ei->ordered_tree);
INIT_LIST_HEAD(&ei->i_orphan);
INIT_LIST_HEAD(&ei->ordered_operations);
new_inode->i_size > BTRFS_EMPTY_DIR_SIZE)
return -ENOTEMPTY;
- ret = btrfs_check_metadata_free_space(root);
+ /*
+ * 2 items for dir items
+ * 1 item for orphan entry
+ * 1 item for ref
+ */
+ ret = btrfs_reserve_metadata_space(root, 4);
if (ret)
return ret;
if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)
up_read(&root->fs_info->subvol_sem);
+
+ btrfs_unreserve_metadata_space(root, 4);
return ret;
}
if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(root))
return -ENAMETOOLONG;
- err = btrfs_check_metadata_free_space(root);
+ /*
+ * 2 items for inode item and ref
+ * 2 items for dir items
+ * 1 item for xattr if selinux is on
+ */
+ err = btrfs_reserve_metadata_space(root, 5);
if (err)
- goto out_fail;
+ return err;
trans = btrfs_start_transaction(root, 1);
+ if (!trans)
+ goto out_fail;
btrfs_set_trans_block_group(trans, dir);
err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
nr = trans->blocks_used;
btrfs_end_transaction_throttle(trans, root);
out_fail:
+ btrfs_unreserve_metadata_space(root, 5);
if (drop_inode) {
inode_dec_link_count(inode);
iput(inode);
while (num_bytes > 0) {
alloc_size = min(num_bytes, root->fs_info->max_extent);
+
+ ret = btrfs_reserve_metadata_space(root, 1);
+ if (ret)
+ goto out;
+
ret = btrfs_reserve_extent(trans, root, alloc_size,
root->sectorsize, 0, alloc_hint,
(u64)-1, &ins, 1);
num_bytes -= ins.offset;
cur_offset += ins.offset;
alloc_hint = ins.objectid + ins.offset;
+ btrfs_unreserve_metadata_space(root, 1);
}
out:
if (cur_offset > start) {
.permission = btrfs_permission,
};
-static struct file_operations btrfs_dir_file_operations = {
+static const struct file_operations btrfs_dir_file_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = btrfs_real_readdir,
.readpage_io_failed_hook = btrfs_io_failed_hook,
.set_bit_hook = btrfs_set_bit_hook,
.clear_bit_hook = btrfs_clear_bit_hook,
+ .merge_extent_hook = btrfs_merge_extent_hook,
+ .split_extent_hook = btrfs_split_extent_hook,
};
/*
u64 index = 0;
unsigned long nr = 1;
- ret = btrfs_check_metadata_free_space(root);
+ /*
+ * 1 - inode item
+ * 2 - refs
+ * 1 - root item
+ * 2 - dir items
+ */
+ ret = btrfs_reserve_metadata_space(root, 6);
if (ret)
return ret;
err = btrfs_commit_transaction(trans, root);
if (err && !ret)
ret = err;
+
+ btrfs_unreserve_metadata_space(root, 6);
+ btrfs_btree_balance_dirty(root, nr);
return ret;
}
if (!root->ref_cows)
return -EINVAL;
- ret = btrfs_check_metadata_free_space(root);
+ /*
+ * 1 - inode item
+ * 2 - refs
+ * 1 - root item
+ * 2 - dir items
+ */
+ ret = btrfs_reserve_metadata_space(root, 6);
if (ret)
goto fail_unlock;
pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS);
if (!pending_snapshot) {
ret = -ENOMEM;
+ btrfs_unreserve_metadata_space(root, 6);
goto fail_unlock;
}
pending_snapshot->name = kmalloc(namelen + 1, GFP_NOFS);
if (!pending_snapshot->name) {
ret = -ENOMEM;
kfree(pending_snapshot);
+ btrfs_unreserve_metadata_space(root, 6);
goto fail_unlock;
}
memcpy(pending_snapshot->name, name, namelen);
struct inode *inode = fdentry(file)->d_inode;
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_trans_handle *trans;
- int ret = 0;
+ int ret;
+ ret = -EPERM;
if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
+ goto out;
- if (file->private_data) {
- ret = -EINPROGRESS;
+ ret = -EINPROGRESS;
+ if (file->private_data)
goto out;
- }
ret = mnt_want_write(file->f_path.mnt);
if (ret)
root->fs_info->open_ioctl_trans++;
mutex_unlock(&root->fs_info->trans_mutex);
+ ret = -ENOMEM;
trans = btrfs_start_ioctl_transaction(root, 0);
- if (trans)
- file->private_data = trans;
- else
- ret = -ENOMEM;
- /*printk(KERN_INFO "btrfs_ioctl_trans_start on %p\n", file);*/
+ if (!trans)
+ goto out_drop;
+
+ file->private_data = trans;
+ return 0;
+
+out_drop:
+ mutex_lock(&root->fs_info->trans_mutex);
+ root->fs_info->open_ioctl_trans--;
+ mutex_unlock(&root->fs_info->trans_mutex);
+ mnt_drop_write(file->f_path.mnt);
out:
return ret;
}
struct inode *inode = fdentry(file)->d_inode;
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_trans_handle *trans;
- int ret = 0;
trans = file->private_data;
- if (!trans) {
- ret = -EINVAL;
- goto out;
- }
- btrfs_end_transaction(trans, root);
+ if (!trans)
+ return -EINVAL;
file->private_data = NULL;
+ btrfs_end_transaction(trans, root);
+
mutex_lock(&root->fs_info->trans_mutex);
root->fs_info->open_ioctl_trans--;
mutex_unlock(&root->fs_info->trans_mutex);
mnt_drop_write(file->f_path.mnt);
-
-out:
- return ret;
+ return 0;
}
long btrfs_ioctl(struct file *file, unsigned int
* start IO on any dirty ones so the wait doesn't stall waiting
* for pdflush to find them
*/
- btrfs_fdatawrite_range(inode->i_mapping, start, end, WB_SYNC_ALL);
+ filemap_fdatawrite_range(inode->i_mapping, start, end);
if (wait) {
wait_event(entry->wait, test_bit(BTRFS_ORDERED_COMPLETE,
&entry->flags));
/* start IO across the range first to instantiate any delalloc
* extents
*/
- btrfs_fdatawrite_range(inode->i_mapping, start, orig_end, WB_SYNC_ALL);
+ filemap_fdatawrite_range(inode->i_mapping, start, orig_end);
/* The compression code will leave pages locked but return from
* writepage without setting the page writeback. Starting again
* with WB_SYNC_ALL will end up waiting for the IO to actually start.
*/
- btrfs_fdatawrite_range(inode->i_mapping, start, orig_end, WB_SYNC_ALL);
+ filemap_fdatawrite_range(inode->i_mapping, start, orig_end);
- btrfs_wait_on_page_writeback_range(inode->i_mapping,
- start >> PAGE_CACHE_SHIFT,
- orig_end >> PAGE_CACHE_SHIFT);
+ filemap_fdatawait_range(inode->i_mapping, start, orig_end);
end = orig_end;
found = 0;
}
-/**
- * taken from mm/filemap.c because it isn't exported
- *
- * __filemap_fdatawrite_range - start writeback on mapping dirty pages in range
- * @mapping: address space structure to write
- * @start: offset in bytes where the range starts
- * @end: offset in bytes where the range ends (inclusive)
- * @sync_mode: enable synchronous operation
- *
- * Start writeback against all of a mapping's dirty pages that lie
- * within the byte offsets <start, end> inclusive.
- *
- * If sync_mode is WB_SYNC_ALL then this is a "data integrity" operation, as
- * opposed to a regular memory cleansing writeback. The difference between
- * these two operations is that if a dirty page/buffer is encountered, it must
- * be waited upon, and not just skipped over.
- */
-int btrfs_fdatawrite_range(struct address_space *mapping, loff_t start,
- loff_t end, int sync_mode)
-{
- struct writeback_control wbc = {
- .sync_mode = sync_mode,
- .nr_to_write = mapping->nrpages * 2,
- .range_start = start,
- .range_end = end,
- };
- return btrfs_writepages(mapping, &wbc);
-}
-
-/**
- * taken from mm/filemap.c because it isn't exported
- *
- * wait_on_page_writeback_range - wait for writeback to complete
- * @mapping: target address_space
- * @start: beginning page index
- * @end: ending page index
- *
- * Wait for writeback to complete against pages indexed by start->end
- * inclusive
- */
-int btrfs_wait_on_page_writeback_range(struct address_space *mapping,
- pgoff_t start, pgoff_t end)
-{
- struct pagevec pvec;
- int nr_pages;
- int ret = 0;
- pgoff_t index;
-
- if (end < start)
- return 0;
-
- pagevec_init(&pvec, 0);
- index = start;
- while ((index <= end) &&
- (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
- PAGECACHE_TAG_WRITEBACK,
- min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1)) != 0) {
- unsigned i;
-
- for (i = 0; i < nr_pages; i++) {
- struct page *page = pvec.pages[i];
-
- /* until radix tree lookup accepts end_index */
- if (page->index > end)
- continue;
-
- wait_on_page_writeback(page);
- if (PageError(page))
- ret = -EIO;
- }
- pagevec_release(&pvec);
- cond_resched();
- }
-
- /* Check for outstanding write errors */
- if (test_and_clear_bit(AS_ENOSPC, &mapping->flags))
- ret = -ENOSPC;
- if (test_and_clear_bit(AS_EIO, &mapping->flags))
- ret = -EIO;
-
- return ret;
-}
-
/*
* add a given inode to the list of inodes that must be fully on
* disk before a transaction commit finishes.
int btrfs_ordered_update_i_size(struct inode *inode,
struct btrfs_ordered_extent *ordered);
int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, u32 *sum);
-int btrfs_wait_on_page_writeback_range(struct address_space *mapping,
- pgoff_t start, pgoff_t end);
-int btrfs_fdatawrite_range(struct address_space *mapping, loff_t start,
- loff_t end, int sync_mode);
int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only);
int btrfs_run_ordered_operations(struct btrfs_root *root, int wait);
int btrfs_add_ordered_operation(struct btrfs_trans_handle *trans,
sb->s_export_op = &btrfs_export_ops;
sb->s_xattr = btrfs_xattr_handlers;
sb->s_time_gran = 1;
+#ifdef CONFIG_BTRFS_POSIX_ACL
sb->s_flags |= MS_POSIXACL;
+#endif
tree_root = open_ctree(sb, fs_devices, (char *)data);
h->alloc_exclude_start = 0;
h->delayed_ref_updates = 0;
+ if (!current->journal_info)
+ current->journal_info = h;
+
root->fs_info->running_transaction->use_count++;
record_root_in_trans(h, root);
mutex_unlock(&root->fs_info->trans_mutex);
wake_up(&cur_trans->writer_wait);
put_transaction(cur_trans);
mutex_unlock(&info->trans_mutex);
+
+ if (current->journal_info == trans)
+ current->journal_info = NULL;
memset(trans, 0, sizeof(*trans));
kmem_cache_free(btrfs_trans_handle_cachep, trans);
memcpy(&pending->root_key, &key, sizeof(key));
fail:
kfree(new_root_item);
+ btrfs_unreserve_metadata_space(root, 6);
return ret;
}
mutex_unlock(&root->fs_info->trans_mutex);
+ if (current->journal_info == trans)
+ current->journal_info = NULL;
+
kmem_cache_free(btrfs_trans_handle_cachep, trans);
return ret;
}
goto error;
device->name = kstrdup(orig_dev->name, GFP_NOFS);
- if (!device->name)
+ if (!device->name) {
+ kfree(device);
goto error;
+ }
device->devid = orig_dev->devid;
device->work.func = pending_bios_fn;
* attributes are handled directly.
*/
struct xattr_handler *btrfs_xattr_handlers[] = {
-#ifdef CONFIG_FS_POSIX_ACL
+#ifdef CONFIG_BTRFS_POSIX_ACL
&btrfs_xattr_acl_access_handler,
&btrfs_xattr_acl_default_handler,
#endif
/* data type for block group number */
typedef unsigned int ext4_group_t;
+/*
+ * Flags used in mballoc's allocation_context flags field.
+ *
+ * Also used to show what's going on for debugging purposes when the
+ * flag field is exported via the traceport interface
+ */
/* prefer goal again. length */
#define EXT4_MB_HINT_MERGE 0x0001
int pages_written;
int retval;
};
+#define DIO_AIO_UNWRITTEN 0x1
+typedef struct ext4_io_end {
+ struct list_head list; /* per-file finished AIO list */
+ struct inode *inode; /* file being written to */
+ unsigned int flag; /* unwritten or not */
+ int error; /* I/O error code */
+ ext4_lblk_t offset; /* offset in the file */
+ size_t size; /* size of the extent */
+ struct work_struct work; /* data work queue */
+} ext4_io_end_t;
/*
* Special inodes numbers
/* Call ext4_da_update_reserve_space() after successfully
allocating the blocks */
#define EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE 0x0008
-
+ /* caller is from the direct IO path, request to creation of an
+ unitialized extents if not allocated, split the uninitialized
+ extent if blocks has been preallocated already*/
+#define EXT4_GET_BLOCKS_DIO 0x0010
+#define EXT4_GET_BLOCKS_CONVERT 0x0020
+#define EXT4_GET_BLOCKS_DIO_CREATE_EXT (EXT4_GET_BLOCKS_DIO|\
+ EXT4_GET_BLOCKS_CREATE_UNINIT_EXT)
+ /* Convert extent to initialized after direct IO complete */
+#define EXT4_GET_BLOCKS_DIO_CONVERT_EXT (EXT4_GET_BLOCKS_CONVERT|\
+ EXT4_GET_BLOCKS_DIO_CREATE_EXT)
/*
* ioctl commands
static inline __le32 ext4_encode_extra_time(struct timespec *time)
{
return cpu_to_le32((sizeof(time->tv_sec) > 4 ?
- time->tv_sec >> 32 : 0) |
- ((time->tv_nsec << 2) & EXT4_NSEC_MASK));
+ (time->tv_sec >> 32) & EXT4_EPOCH_MASK : 0) |
+ ((time->tv_nsec << EXT4_EPOCH_BITS) & EXT4_NSEC_MASK));
}
static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
if (sizeof(time->tv_sec) > 4)
time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK)
<< 32;
- time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> 2;
+ time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
}
#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
__u16 i_extra_isize;
spinlock_t i_block_reservation_lock;
+
+ /* completed async DIOs that might need unwritten extents handling */
+ struct list_head i_aio_dio_complete_list;
+ /* current io_end structure for async DIO write*/
+ ext4_io_end_t *cur_aio_dio;
};
/*
unsigned int s_mb_stats;
unsigned int s_mb_order2_reqs;
unsigned int s_mb_group_prealloc;
+ unsigned int s_max_writeback_mb_bump;
/* where last allocation was done - for stream allocation */
unsigned long s_mb_last_group;
unsigned long s_mb_last_start;
- /* history to debug policy */
- struct ext4_mb_history *s_mb_history;
- int s_mb_history_cur;
- int s_mb_history_max;
- int s_mb_history_num;
- spinlock_t s_mb_history_lock;
- int s_mb_history_filter;
-
/* stats for buddy allocator */
spinlock_t s_mb_pa_lock;
atomic_t s_bal_reqs; /* number of reqs with len > 1 */
unsigned int s_log_groups_per_flex;
struct flex_groups *s_flex_groups;
+
+ /* workqueue for dio unwritten */
+ struct workqueue_struct *dio_unwritten_wq;
};
static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
struct address_space *mapping, loff_t from);
extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
extern qsize_t ext4_get_reserved_space(struct inode *inode);
-
+extern int flush_aio_dio_completed_IO(struct inode *inode);
/* ioctl.c */
extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long);
extern void ext4_ext_release(struct super_block *);
extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset,
loff_t len);
+extern int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
+ loff_t len);
extern int ext4_get_blocks(handle_t *handle, struct inode *inode,
sector_t block, unsigned int max_blocks,
struct buffer_head *bh, int flags);
(le16_to_cpu(ext->ee_len) - EXT_INIT_MAX_LEN));
}
+static inline void ext4_ext_mark_initialized(struct ext4_extent *ext)
+{
+ ext->ee_len = cpu_to_le16(ext4_ext_get_actual_len(ext));
+}
+
extern int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks);
extern ext4_fsblk_t ext_pblock(struct ext4_extent *ex);
extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *);
struct ext4_ext_path *path,
struct ext4_extent *);
extern unsigned int ext4_ext_check_overlap(struct inode *, struct ext4_extent *, struct ext4_ext_path *);
-extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *);
+extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *, int);
extern int ext4_ext_walk_space(struct inode *, ext4_lblk_t, ext4_lblk_t,
ext_prepare_callback, void *);
extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks);
int __ext4_journal_stop(const char *where, handle_t *handle);
-#define EXT4_NOJOURNAL_HANDLE ((handle_t *) 0x1)
+#define EXT4_NOJOURNAL_MAX_REF_COUNT ((unsigned long) 4096)
+/* Note: Do not use this for NULL handles. This is only to determine if
+ * a properly allocated handle is using a journal or not. */
static inline int ext4_handle_valid(handle_t *handle)
{
- if (handle == EXT4_NOJOURNAL_HANDLE)
+ if ((unsigned long)handle < EXT4_NOJOURNAL_MAX_REF_COUNT)
return 0;
return 1;
}
* insert new index [@logical;@ptr] into the block at @curp;
* check where to insert: before @curp or after @curp
*/
-static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
+int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
struct ext4_ext_path *curp,
int logical, ext4_fsblk_t ptr)
{
*/
int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
struct ext4_ext_path *path,
- struct ext4_extent *newext)
+ struct ext4_extent *newext, int flag)
{
struct ext4_extent_header *eh;
struct ext4_extent *ex, *fex;
BUG_ON(path[depth].p_hdr == NULL);
/* try to insert block into found extent and return */
- if (ex && ext4_can_extents_be_merged(inode, ex, newext)) {
+ if (ex && (flag != EXT4_GET_BLOCKS_DIO_CREATE_EXT)
+ && ext4_can_extents_be_merged(inode, ex, newext)) {
ext_debug("append [%d]%d block to %d:[%d]%d (from %llu)\n",
ext4_ext_is_uninitialized(newext),
ext4_ext_get_actual_len(newext),
merge:
/* try to merge extents to the right */
- ext4_ext_try_to_merge(inode, path, nearex);
+ if (flag != EXT4_GET_BLOCKS_DIO_CREATE_EXT)
+ ext4_ext_try_to_merge(inode, path, nearex);
/* try to merge extents to the left */
*/
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
+#if defined(AGGRESSIVE_TEST) || defined(CHECK_BINSEARCH) || defined(EXTENTS_STATS)
printk(KERN_INFO "EXT4-fs: file extents enabled");
#ifdef AGGRESSIVE_TEST
printk(", aggressive tests");
printk(", stats");
#endif
printk("\n");
+#endif
#ifdef EXTENTS_STATS
spin_lock_init(&EXT4_SB(sb)->s_ext_stats_lock);
EXT4_SB(sb)->s_ext_min = 1 << 30;
}
#define EXT4_EXT_ZERO_LEN 7
-
/*
* This function is called by ext4_ext_get_blocks() if someone tries to write
* to an uninitialized extent. It may result in splitting the uninitialized
ex3->ee_block = cpu_to_le32(iblock);
ext4_ext_store_pblock(ex3, newblock);
ex3->ee_len = cpu_to_le16(allocated);
- err = ext4_ext_insert_extent(handle, inode, path, ex3);
+ err = ext4_ext_insert_extent(handle, inode, path,
+ ex3, 0);
if (err == -ENOSPC) {
err = ext4_ext_zeroout(inode, &orig_ex);
if (err)
ext4_ext_store_pblock(ex3, newblock + max_blocks);
ex3->ee_len = cpu_to_le16(allocated - max_blocks);
ext4_ext_mark_uninitialized(ex3);
- err = ext4_ext_insert_extent(handle, inode, path, ex3);
+ err = ext4_ext_insert_extent(handle, inode, path, ex3, 0);
if (err == -ENOSPC) {
err = ext4_ext_zeroout(inode, &orig_ex);
if (err)
err = ext4_ext_dirty(handle, inode, path + depth);
goto out;
insert:
- err = ext4_ext_insert_extent(handle, inode, path, &newex);
+ err = ext4_ext_insert_extent(handle, inode, path, &newex, 0);
if (err == -ENOSPC) {
err = ext4_ext_zeroout(inode, &orig_ex);
if (err)
return err;
}
+/*
+ * This function is called by ext4_ext_get_blocks() from
+ * ext4_get_blocks_dio_write() when DIO to write
+ * to an uninitialized extent.
+ *
+ * Writing to an uninitized extent may result in splitting the uninitialized
+ * extent into multiple /intialized unintialized extents (up to three)
+ * There are three possibilities:
+ * a> There is no split required: Entire extent should be uninitialized
+ * b> Splits in two extents: Write is happening at either end of the extent
+ * c> Splits in three extents: Somone is writing in middle of the extent
+ *
+ * One of more index blocks maybe needed if the extent tree grow after
+ * the unintialized extent split. To prevent ENOSPC occur at the IO
+ * complete, we need to split the uninitialized extent before DIO submit
+ * the IO. The uninitilized extent called at this time will be split
+ * into three uninitialized extent(at most). After IO complete, the part
+ * being filled will be convert to initialized by the end_io callback function
+ * via ext4_convert_unwritten_extents().
+ */
+static int ext4_split_unwritten_extents(handle_t *handle,
+ struct inode *inode,
+ struct ext4_ext_path *path,
+ ext4_lblk_t iblock,
+ unsigned int max_blocks,
+ int flags)
+{
+ struct ext4_extent *ex, newex, orig_ex;
+ struct ext4_extent *ex1 = NULL;
+ struct ext4_extent *ex2 = NULL;
+ struct ext4_extent *ex3 = NULL;
+ struct ext4_extent_header *eh;
+ ext4_lblk_t ee_block;
+ unsigned int allocated, ee_len, depth;
+ ext4_fsblk_t newblock;
+ int err = 0;
+ int ret = 0;
+
+ ext_debug("ext4_split_unwritten_extents: inode %lu,"
+ "iblock %llu, max_blocks %u\n", inode->i_ino,
+ (unsigned long long)iblock, max_blocks);
+ depth = ext_depth(inode);
+ eh = path[depth].p_hdr;
+ ex = path[depth].p_ext;
+ ee_block = le32_to_cpu(ex->ee_block);
+ ee_len = ext4_ext_get_actual_len(ex);
+ allocated = ee_len - (iblock - ee_block);
+ newblock = iblock - ee_block + ext_pblock(ex);
+ ex2 = ex;
+ orig_ex.ee_block = ex->ee_block;
+ orig_ex.ee_len = cpu_to_le16(ee_len);
+ ext4_ext_store_pblock(&orig_ex, ext_pblock(ex));
+
+ /*
+ * if the entire unintialized extent length less than
+ * the size of extent to write, there is no need to split
+ * uninitialized extent
+ */
+ if (allocated <= max_blocks)
+ return ret;
+
+ err = ext4_ext_get_access(handle, inode, path + depth);
+ if (err)
+ goto out;
+ /* ex1: ee_block to iblock - 1 : uninitialized */
+ if (iblock > ee_block) {
+ ex1 = ex;
+ ex1->ee_len = cpu_to_le16(iblock - ee_block);
+ ext4_ext_mark_uninitialized(ex1);
+ ex2 = &newex;
+ }
+ /*
+ * for sanity, update the length of the ex2 extent before
+ * we insert ex3, if ex1 is NULL. This is to avoid temporary
+ * overlap of blocks.
+ */
+ if (!ex1 && allocated > max_blocks)
+ ex2->ee_len = cpu_to_le16(max_blocks);
+ /* ex3: to ee_block + ee_len : uninitialised */
+ if (allocated > max_blocks) {
+ unsigned int newdepth;
+ ex3 = &newex;
+ ex3->ee_block = cpu_to_le32(iblock + max_blocks);
+ ext4_ext_store_pblock(ex3, newblock + max_blocks);
+ ex3->ee_len = cpu_to_le16(allocated - max_blocks);
+ ext4_ext_mark_uninitialized(ex3);
+ err = ext4_ext_insert_extent(handle, inode, path, ex3, flags);
+ if (err == -ENOSPC) {
+ err = ext4_ext_zeroout(inode, &orig_ex);
+ if (err)
+ goto fix_extent_len;
+ /* update the extent length and mark as initialized */
+ ex->ee_block = orig_ex.ee_block;
+ ex->ee_len = orig_ex.ee_len;
+ ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
+ ext4_ext_dirty(handle, inode, path + depth);
+ /* zeroed the full extent */
+ /* blocks available from iblock */
+ return allocated;
+
+ } else if (err)
+ goto fix_extent_len;
+ /*
+ * The depth, and hence eh & ex might change
+ * as part of the insert above.
+ */
+ newdepth = ext_depth(inode);
+ /*
+ * update the extent length after successful insert of the
+ * split extent
+ */
+ orig_ex.ee_len = cpu_to_le16(ee_len -
+ ext4_ext_get_actual_len(ex3));
+ depth = newdepth;
+ ext4_ext_drop_refs(path);
+ path = ext4_ext_find_extent(inode, iblock, path);
+ if (IS_ERR(path)) {
+ err = PTR_ERR(path);
+ goto out;
+ }
+ eh = path[depth].p_hdr;
+ ex = path[depth].p_ext;
+ if (ex2 != &newex)
+ ex2 = ex;
+
+ err = ext4_ext_get_access(handle, inode, path + depth);
+ if (err)
+ goto out;
+
+ allocated = max_blocks;
+ }
+ /*
+ * If there was a change of depth as part of the
+ * insertion of ex3 above, we need to update the length
+ * of the ex1 extent again here
+ */
+ if (ex1 && ex1 != ex) {
+ ex1 = ex;
+ ex1->ee_len = cpu_to_le16(iblock - ee_block);
+ ext4_ext_mark_uninitialized(ex1);
+ ex2 = &newex;
+ }
+ /*
+ * ex2: iblock to iblock + maxblocks-1 : to be direct IO written,
+ * uninitialised still.
+ */
+ ex2->ee_block = cpu_to_le32(iblock);
+ ext4_ext_store_pblock(ex2, newblock);
+ ex2->ee_len = cpu_to_le16(allocated);
+ ext4_ext_mark_uninitialized(ex2);
+ if (ex2 != ex)
+ goto insert;
+ /* Mark modified extent as dirty */
+ err = ext4_ext_dirty(handle, inode, path + depth);
+ ext_debug("out here\n");
+ goto out;
+insert:
+ err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
+ if (err == -ENOSPC) {
+ err = ext4_ext_zeroout(inode, &orig_ex);
+ if (err)
+ goto fix_extent_len;
+ /* update the extent length and mark as initialized */
+ ex->ee_block = orig_ex.ee_block;
+ ex->ee_len = orig_ex.ee_len;
+ ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
+ ext4_ext_dirty(handle, inode, path + depth);
+ /* zero out the first half */
+ return allocated;
+ } else if (err)
+ goto fix_extent_len;
+out:
+ ext4_ext_show_leaf(inode, path);
+ return err ? err : allocated;
+
+fix_extent_len:
+ ex->ee_block = orig_ex.ee_block;
+ ex->ee_len = orig_ex.ee_len;
+ ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
+ ext4_ext_mark_uninitialized(ex);
+ ext4_ext_dirty(handle, inode, path + depth);
+ return err;
+}
+static int ext4_convert_unwritten_extents_dio(handle_t *handle,
+ struct inode *inode,
+ struct ext4_ext_path *path)
+{
+ struct ext4_extent *ex;
+ struct ext4_extent_header *eh;
+ int depth;
+ int err = 0;
+ int ret = 0;
+
+ depth = ext_depth(inode);
+ eh = path[depth].p_hdr;
+ ex = path[depth].p_ext;
+
+ err = ext4_ext_get_access(handle, inode, path + depth);
+ if (err)
+ goto out;
+ /* first mark the extent as initialized */
+ ext4_ext_mark_initialized(ex);
+
+ /*
+ * We have to see if it can be merged with the extent
+ * on the left.
+ */
+ if (ex > EXT_FIRST_EXTENT(eh)) {
+ /*
+ * To merge left, pass "ex - 1" to try_to_merge(),
+ * since it merges towards right _only_.
+ */
+ ret = ext4_ext_try_to_merge(inode, path, ex - 1);
+ if (ret) {
+ err = ext4_ext_correct_indexes(handle, inode, path);
+ if (err)
+ goto out;
+ depth = ext_depth(inode);
+ ex--;
+ }
+ }
+ /*
+ * Try to Merge towards right.
+ */
+ ret = ext4_ext_try_to_merge(inode, path, ex);
+ if (ret) {
+ err = ext4_ext_correct_indexes(handle, inode, path);
+ if (err)
+ goto out;
+ depth = ext_depth(inode);
+ }
+ /* Mark modified extent as dirty */
+ err = ext4_ext_dirty(handle, inode, path + depth);
+out:
+ ext4_ext_show_leaf(inode, path);
+ return err;
+}
+
+static int
+ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
+ ext4_lblk_t iblock, unsigned int max_blocks,
+ struct ext4_ext_path *path, int flags,
+ unsigned int allocated, struct buffer_head *bh_result,
+ ext4_fsblk_t newblock)
+{
+ int ret = 0;
+ int err = 0;
+ ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio;
+
+ ext_debug("ext4_ext_handle_uninitialized_extents: inode %lu, logical"
+ "block %llu, max_blocks %u, flags %d, allocated %u",
+ inode->i_ino, (unsigned long long)iblock, max_blocks,
+ flags, allocated);
+ ext4_ext_show_leaf(inode, path);
+
+ /* DIO get_block() before submit the IO, split the extent */
+ if (flags == EXT4_GET_BLOCKS_DIO_CREATE_EXT) {
+ ret = ext4_split_unwritten_extents(handle,
+ inode, path, iblock,
+ max_blocks, flags);
+ /* flag the io_end struct that we need convert when IO done */
+ if (io)
+ io->flag = DIO_AIO_UNWRITTEN;
+ goto out;
+ }
+ /* DIO end_io complete, convert the filled extent to written */
+ if (flags == EXT4_GET_BLOCKS_DIO_CONVERT_EXT) {
+ ret = ext4_convert_unwritten_extents_dio(handle, inode,
+ path);
+ goto out2;
+ }
+ /* buffered IO case */
+ /*
+ * repeat fallocate creation request
+ * we already have an unwritten extent
+ */
+ if (flags & EXT4_GET_BLOCKS_UNINIT_EXT)
+ goto map_out;
+
+ /* buffered READ or buffered write_begin() lookup */
+ if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
+ /*
+ * We have blocks reserved already. We
+ * return allocated blocks so that delalloc
+ * won't do block reservation for us. But
+ * the buffer head will be unmapped so that
+ * a read from the block returns 0s.
+ */
+ set_buffer_unwritten(bh_result);
+ goto out1;
+ }
+
+ /* buffered write, writepage time, convert*/
+ ret = ext4_ext_convert_to_initialized(handle, inode,
+ path, iblock,
+ max_blocks);
+out:
+ if (ret <= 0) {
+ err = ret;
+ goto out2;
+ } else
+ allocated = ret;
+ set_buffer_new(bh_result);
+map_out:
+ set_buffer_mapped(bh_result);
+out1:
+ if (allocated > max_blocks)
+ allocated = max_blocks;
+ ext4_ext_show_leaf(inode, path);
+ bh_result->b_bdev = inode->i_sb->s_bdev;
+ bh_result->b_blocknr = newblock;
+out2:
+ if (path) {
+ ext4_ext_drop_refs(path);
+ kfree(path);
+ }
+ return err ? err : allocated;
+}
/*
* Block allocation/map/preallocation routine for extents based files
*
int err = 0, depth, ret, cache_type;
unsigned int allocated = 0;
struct ext4_allocation_request ar;
+ ext4_io_end_t *io = EXT4_I(inode)->cur_aio_dio;
__clear_bit(BH_New, &bh_result->b_state);
ext_debug("blocks %u/%u requested for inode %lu\n",
EXT4_EXT_CACHE_EXTENT);
goto out;
}
- if (flags & EXT4_GET_BLOCKS_UNINIT_EXT)
- goto out;
- if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
- if (allocated > max_blocks)
- allocated = max_blocks;
- /*
- * We have blocks reserved already. We
- * return allocated blocks so that delalloc
- * won't do block reservation for us. But
- * the buffer head will be unmapped so that
- * a read from the block returns 0s.
- */
- set_buffer_unwritten(bh_result);
- bh_result->b_bdev = inode->i_sb->s_bdev;
- bh_result->b_blocknr = newblock;
- goto out2;
- }
-
- ret = ext4_ext_convert_to_initialized(handle, inode,
- path, iblock,
- max_blocks);
- if (ret <= 0) {
- err = ret;
- goto out2;
- } else
- allocated = ret;
- goto outnew;
+ ret = ext4_ext_handle_uninitialized_extents(handle,
+ inode, iblock, max_blocks, path,
+ flags, allocated, bh_result, newblock);
+ return ret;
}
}
/* try to insert new extent into found leaf and return */
ext4_ext_store_pblock(&newex, newblock);
newex.ee_len = cpu_to_le16(ar.len);
- if (flags & EXT4_GET_BLOCKS_UNINIT_EXT) /* Mark uninitialized */
+ /* Mark uninitialized */
+ if (flags & EXT4_GET_BLOCKS_UNINIT_EXT){
ext4_ext_mark_uninitialized(&newex);
- err = ext4_ext_insert_extent(handle, inode, path, &newex);
+ /*
+ * io_end structure was created for every async
+ * direct IO write to the middle of the file.
+ * To avoid unecessary convertion for every aio dio rewrite
+ * to the mid of file, here we flag the IO that is really
+ * need the convertion.
+ *
+ */
+ if (io && flags == EXT4_GET_BLOCKS_DIO_CREATE_EXT)
+ io->flag = DIO_AIO_UNWRITTEN;
+ }
+ err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
if (err) {
/* free data blocks we just allocated */
/* not a good idea to call discard here directly,
/* previous routine could use block we allocated */
newblock = ext_pblock(&newex);
allocated = ext4_ext_get_actual_len(&newex);
-outnew:
set_buffer_new(bh_result);
/* Cache only when it is _not_ an uninitialized extent */
return ret > 0 ? ret2 : ret;
}
+/*
+ * This function convert a range of blocks to written extents
+ * The caller of this function will pass the start offset and the size.
+ * all unwritten extents within this range will be converted to
+ * written extents.
+ *
+ * This function is called from the direct IO end io call back
+ * function, to convert the fallocated extents after IO is completed.
+ */
+int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
+ loff_t len)
+{
+ handle_t *handle;
+ ext4_lblk_t block;
+ unsigned int max_blocks;
+ int ret = 0;
+ int ret2 = 0;
+ struct buffer_head map_bh;
+ unsigned int credits, blkbits = inode->i_blkbits;
+
+ block = offset >> blkbits;
+ /*
+ * We can't just convert len to max_blocks because
+ * If blocksize = 4096 offset = 3072 and len = 2048
+ */
+ max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits)
+ - block;
+ /*
+ * credits to insert 1 extent into extent tree
+ */
+ credits = ext4_chunk_trans_blocks(inode, max_blocks);
+ while (ret >= 0 && ret < max_blocks) {
+ block = block + ret;
+ max_blocks = max_blocks - ret;
+ handle = ext4_journal_start(inode, credits);
+ if (IS_ERR(handle)) {
+ ret = PTR_ERR(handle);
+ break;
+ }
+ map_bh.b_state = 0;
+ ret = ext4_get_blocks(handle, inode, block,
+ max_blocks, &map_bh,
+ EXT4_GET_BLOCKS_DIO_CONVERT_EXT);
+ if (ret <= 0) {
+ WARN_ON(ret <= 0);
+ printk(KERN_ERR "%s: ext4_ext_get_blocks "
+ "returned error inode#%lu, block=%u, "
+ "max_blocks=%u", __func__,
+ inode->i_ino, block, max_blocks);
+ }
+ ext4_mark_inode_dirty(handle, inode);
+ ret2 = ext4_journal_stop(handle);
+ if (ret <= 0 || ret2 )
+ break;
+ }
+ return ret > 0 ? ret2 : ret;
+}
/*
* Callback function called for each extent to gather FIEMAP information.
*/
*
* What we do is just kick off a commit and wait on it. This will snapshot the
* inode to disk.
+ *
+ * i_mutex lock is held when entering and exiting this function
*/
int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync)
trace_ext4_sync_file(file, dentry, datasync);
+ ret = flush_aio_dio_completed_IO(inode);
+ if (ret < 0)
+ goto out;
/*
* data=writeback:
* The caller's filemap_fdatawrite()/wait will sync the data.
#include <linux/namei.h>
#include <linux/uio.h>
#include <linux/bio.h>
+#include <linux/workqueue.h>
#include "ext4_jbd2.h"
#include "xattr.h"
return 0;
}
+/*
+ * Return the number of dirty pages in the given inode starting at
+ * page frame idx.
+ */
+static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx,
+ unsigned int max_pages)
+{
+ struct address_space *mapping = inode->i_mapping;
+ pgoff_t index;
+ struct pagevec pvec;
+ pgoff_t num = 0;
+ int i, nr_pages, done = 0;
+
+ if (max_pages == 0)
+ return 0;
+ pagevec_init(&pvec, 0);
+ while (!done) {
+ index = idx;
+ nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
+ PAGECACHE_TAG_DIRTY,
+ (pgoff_t)PAGEVEC_SIZE);
+ if (nr_pages == 0)
+ break;
+ for (i = 0; i < nr_pages; i++) {
+ struct page *page = pvec.pages[i];
+ struct buffer_head *bh, *head;
+
+ lock_page(page);
+ if (unlikely(page->mapping != mapping) ||
+ !PageDirty(page) ||
+ PageWriteback(page) ||
+ page->index != idx) {
+ done = 1;
+ unlock_page(page);
+ break;
+ }
+ head = page_buffers(page);
+ bh = head;
+ do {
+ if (!buffer_delay(bh) &&
+ !buffer_unwritten(bh)) {
+ done = 1;
+ break;
+ }
+ } while ((bh = bh->b_this_page) != head);
+ unlock_page(page);
+ if (done)
+ break;
+ idx++;
+ num++;
+ if (num >= max_pages)
+ break;
+ }
+ pagevec_release(&pvec);
+ }
+ return num;
+}
+
/*
* The ext4_get_blocks() function tries to look up the requested blocks,
* and returns if the blocks are already mapped.
clear_buffer_mapped(bh);
clear_buffer_unwritten(bh);
+ ext_debug("ext4_get_blocks(): inode %lu, flag %d, max_blocks %u,"
+ "logical block %lu\n", inode->i_ino, flags, max_blocks,
+ (unsigned long)block);
/*
* Try to see if we can get the block without requesting a new
* file system block.
if (ext4_claim_free_blocks(sbi, total)) {
spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+ vfs_dq_release_reservation_block(inode, total);
if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
yield();
goto repeat;
}
- vfs_dq_release_reservation_block(inode, total);
return -ENOSPC;
}
EXT4_I(inode)->i_reserved_data_blocks += nrblocks;
static void ext4_print_free_blocks(struct inode *inode)
{
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
- printk(KERN_EMERG "Total free blocks count %lld\n",
- ext4_count_free_blocks(inode->i_sb));
- printk(KERN_EMERG "Free/Dirty block details\n");
- printk(KERN_EMERG "free_blocks=%lld\n",
- (long long)percpu_counter_sum(&sbi->s_freeblocks_counter));
- printk(KERN_EMERG "dirty_blocks=%lld\n",
- (long long)percpu_counter_sum(&sbi->s_dirtyblocks_counter));
- printk(KERN_EMERG "Block reservation details\n");
- printk(KERN_EMERG "i_reserved_data_blocks=%u\n",
- EXT4_I(inode)->i_reserved_data_blocks);
- printk(KERN_EMERG "i_reserved_meta_blocks=%u\n",
- EXT4_I(inode)->i_reserved_meta_blocks);
+ printk(KERN_CRIT "Total free blocks count %lld\n",
+ ext4_count_free_blocks(inode->i_sb));
+ printk(KERN_CRIT "Free/Dirty block details\n");
+ printk(KERN_CRIT "free_blocks=%lld\n",
+ (long long) percpu_counter_sum(&sbi->s_freeblocks_counter));
+ printk(KERN_CRIT "dirty_blocks=%lld\n",
+ (long long) percpu_counter_sum(&sbi->s_dirtyblocks_counter));
+ printk(KERN_CRIT "Block reservation details\n");
+ printk(KERN_CRIT "i_reserved_data_blocks=%u\n",
+ EXT4_I(inode)->i_reserved_data_blocks);
+ printk(KERN_CRIT "i_reserved_meta_blocks=%u\n",
+ EXT4_I(inode)->i_reserved_meta_blocks);
return;
}
* writepage and writepages will again try to write
* the same.
*/
- printk(KERN_EMERG "%s block allocation failed for inode %lu "
- "at logical offset %llu with max blocks "
- "%zd with error %d\n",
- __func__, mpd->inode->i_ino,
- (unsigned long long)next,
- mpd->b_size >> mpd->inode->i_blkbits, err);
- printk(KERN_EMERG "This should not happen.!! "
- "Data will be lost\n");
+ ext4_msg(mpd->inode->i_sb, KERN_CRIT,
+ "delayed block allocation failed for inode %lu at "
+ "logical offset %llu with max blocks %zd with "
+ "error %d\n", mpd->inode->i_ino,
+ (unsigned long long) next,
+ mpd->b_size >> mpd->inode->i_blkbits, err);
+ printk(KERN_CRIT "This should not happen!! "
+ "Data will be lost\n");
if (err == -ENOSPC) {
ext4_print_free_blocks(mpd->inode);
}
int no_nrwrite_index_update;
int pages_written = 0;
long pages_skipped;
+ unsigned int max_pages;
int range_cyclic, cycled = 1, io_done = 0;
- int needed_blocks, ret = 0, nr_to_writebump = 0;
+ int needed_blocks, ret = 0;
+ long desired_nr_to_write, nr_to_writebump = 0;
loff_t range_start = wbc->range_start;
struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
if (unlikely(sbi->s_mount_flags & EXT4_MF_FS_ABORTED))
return -EROFS;
- /*
- * Make sure nr_to_write is >= sbi->s_mb_stream_request
- * This make sure small files blocks are allocated in
- * single attempt. This ensure that small files
- * get less fragmented.
- */
- if (wbc->nr_to_write < sbi->s_mb_stream_request) {
- nr_to_writebump = sbi->s_mb_stream_request - wbc->nr_to_write;
- wbc->nr_to_write = sbi->s_mb_stream_request;
- }
if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
range_whole = 1;
} else
index = wbc->range_start >> PAGE_CACHE_SHIFT;
+ /*
+ * This works around two forms of stupidity. The first is in
+ * the writeback code, which caps the maximum number of pages
+ * written to be 1024 pages. This is wrong on multiple
+ * levels; different architectues have a different page size,
+ * which changes the maximum amount of data which gets
+ * written. Secondly, 4 megabytes is way too small. XFS
+ * forces this value to be 16 megabytes by multiplying
+ * nr_to_write parameter by four, and then relies on its
+ * allocator to allocate larger extents to make them
+ * contiguous. Unfortunately this brings us to the second
+ * stupidity, which is that ext4's mballoc code only allocates
+ * at most 2048 blocks. So we force contiguous writes up to
+ * the number of dirty blocks in the inode, or
+ * sbi->max_writeback_mb_bump whichever is smaller.
+ */
+ max_pages = sbi->s_max_writeback_mb_bump << (20 - PAGE_CACHE_SHIFT);
+ if (!range_cyclic && range_whole)
+ desired_nr_to_write = wbc->nr_to_write * 8;
+ else
+ desired_nr_to_write = ext4_num_dirty_pages(inode, index,
+ max_pages);
+ if (desired_nr_to_write > max_pages)
+ desired_nr_to_write = max_pages;
+
+ if (wbc->nr_to_write < desired_nr_to_write) {
+ nr_to_writebump = desired_nr_to_write - wbc->nr_to_write;
+ wbc->nr_to_write = desired_nr_to_write;
+ }
+
mpd.wbc = wbc;
mpd.inode = mapping->host;
handle = ext4_journal_start(inode, needed_blocks);
if (IS_ERR(handle)) {
ret = PTR_ERR(handle);
- printk(KERN_CRIT "%s: jbd2_start: "
+ ext4_msg(inode->i_sb, KERN_CRIT, "%s: jbd2_start: "
"%ld pages, ino %lu; err %d\n", __func__,
wbc->nr_to_write, inode->i_ino, ret);
- dump_stack();
goto out_writepages;
}
goto retry;
}
if (pages_skipped != wbc->pages_skipped)
- printk(KERN_EMERG "This should not happen leaving %s "
- "with nr_to_write = %ld ret = %d\n",
- __func__, wbc->nr_to_write, ret);
+ ext4_msg(inode->i_sb, KERN_CRIT,
+ "This should not happen leaving %s "
+ "with nr_to_write = %ld ret = %d\n",
+ __func__, wbc->nr_to_write, ret);
/* Update index */
index += pages_written;
out_writepages:
if (!no_nrwrite_index_update)
wbc->no_nrwrite_index_update = 0;
- wbc->nr_to_write -= nr_to_writebump;
+ if (wbc->nr_to_write > nr_to_writebump)
+ wbc->nr_to_write -= nr_to_writebump;
wbc->range_start = range_start;
trace_ext4_da_writepages_result(inode, wbc, ret, pages_written);
return ret;
}
/*
+ * O_DIRECT for ext3 (or indirect map) based files
+ *
* If the O_DIRECT write will extend the file then add this inode to the
* orphan list. So recovery will truncate it back to the original size
* if the machine crashes during the write.
* crashes then stale disk data _may_ be exposed inside the file. But current
* VFS code falls back into buffered path in that case so we are safe.
*/
-static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
+static ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
const struct iovec *iov, loff_t offset,
unsigned long nr_segs)
{
return ret;
}
+/* Maximum number of blocks we map for direct IO at once. */
+
+static int ext4_get_block_dio_write(struct inode *inode, sector_t iblock,
+ struct buffer_head *bh_result, int create)
+{
+ handle_t *handle = NULL;
+ int ret = 0;
+ unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
+ int dio_credits;
+
+ ext4_debug("ext4_get_block_dio_write: inode %lu, create flag %d\n",
+ inode->i_ino, create);
+ /*
+ * DIO VFS code passes create = 0 flag for write to
+ * the middle of file. It does this to avoid block
+ * allocation for holes, to prevent expose stale data
+ * out when there is parallel buffered read (which does
+ * not hold the i_mutex lock) while direct IO write has
+ * not completed. DIO request on holes finally falls back
+ * to buffered IO for this reason.
+ *
+ * For ext4 extent based file, since we support fallocate,
+ * new allocated extent as uninitialized, for holes, we
+ * could fallocate blocks for holes, thus parallel
+ * buffered IO read will zero out the page when read on
+ * a hole while parallel DIO write to the hole has not completed.
+ *
+ * when we come here, we know it's a direct IO write to
+ * to the middle of file (<i_size)
+ * so it's safe to override the create flag from VFS.
+ */
+ create = EXT4_GET_BLOCKS_DIO_CREATE_EXT;
+
+ if (max_blocks > DIO_MAX_BLOCKS)
+ max_blocks = DIO_MAX_BLOCKS;
+ dio_credits = ext4_chunk_trans_blocks(inode, max_blocks);
+ handle = ext4_journal_start(inode, dio_credits);
+ if (IS_ERR(handle)) {
+ ret = PTR_ERR(handle);
+ goto out;
+ }
+ ret = ext4_get_blocks(handle, inode, iblock, max_blocks, bh_result,
+ create);
+ if (ret > 0) {
+ bh_result->b_size = (ret << inode->i_blkbits);
+ ret = 0;
+ }
+ ext4_journal_stop(handle);
+out:
+ return ret;
+}
+
+static void ext4_free_io_end(ext4_io_end_t *io)
+{
+ BUG_ON(!io);
+ iput(io->inode);
+ kfree(io);
+}
+static void dump_aio_dio_list(struct inode * inode)
+{
+#ifdef EXT4_DEBUG
+ struct list_head *cur, *before, *after;
+ ext4_io_end_t *io, *io0, *io1;
+
+ if (list_empty(&EXT4_I(inode)->i_aio_dio_complete_list)){
+ ext4_debug("inode %lu aio dio list is empty\n", inode->i_ino);
+ return;
+ }
+
+ ext4_debug("Dump inode %lu aio_dio_completed_IO list \n", inode->i_ino);
+ list_for_each_entry(io, &EXT4_I(inode)->i_aio_dio_complete_list, list){
+ cur = &io->list;
+ before = cur->prev;
+ io0 = container_of(before, ext4_io_end_t, list);
+ after = cur->next;
+ io1 = container_of(after, ext4_io_end_t, list);
+
+ ext4_debug("io 0x%p from inode %lu,prev 0x%p,next 0x%p\n",
+ io, inode->i_ino, io0, io1);
+ }
+#endif
+}
+
+/*
+ * check a range of space and convert unwritten extents to written.
+ */
+static int ext4_end_aio_dio_nolock(ext4_io_end_t *io)
+{
+ struct inode *inode = io->inode;
+ loff_t offset = io->offset;
+ size_t size = io->size;
+ int ret = 0;
+
+ ext4_debug("end_aio_dio_onlock: io 0x%p from inode %lu,list->next 0x%p,"
+ "list->prev 0x%p\n",
+ io, inode->i_ino, io->list.next, io->list.prev);
+
+ if (list_empty(&io->list))
+ return ret;
+
+ if (io->flag != DIO_AIO_UNWRITTEN)
+ return ret;
+
+ if (offset + size <= i_size_read(inode))
+ ret = ext4_convert_unwritten_extents(inode, offset, size);
+
+ if (ret < 0) {
+ printk(KERN_EMERG "%s: failed to convert unwritten"
+ "extents to written extents, error is %d"
+ " io is still on inode %lu aio dio list\n",
+ __func__, ret, inode->i_ino);
+ return ret;
+ }
+
+ /* clear the DIO AIO unwritten flag */
+ io->flag = 0;
+ return ret;
+}
+/*
+ * work on completed aio dio IO, to convert unwritten extents to extents
+ */
+static void ext4_end_aio_dio_work(struct work_struct *work)
+{
+ ext4_io_end_t *io = container_of(work, ext4_io_end_t, work);
+ struct inode *inode = io->inode;
+ int ret = 0;
+
+ mutex_lock(&inode->i_mutex);
+ ret = ext4_end_aio_dio_nolock(io);
+ if (ret >= 0) {
+ if (!list_empty(&io->list))
+ list_del_init(&io->list);
+ ext4_free_io_end(io);
+ }
+ mutex_unlock(&inode->i_mutex);
+}
+/*
+ * This function is called from ext4_sync_file().
+ *
+ * When AIO DIO IO is completed, the work to convert unwritten
+ * extents to written is queued on workqueue but may not get immediately
+ * scheduled. When fsync is called, we need to ensure the
+ * conversion is complete before fsync returns.
+ * The inode keeps track of a list of completed AIO from DIO path
+ * that might needs to do the conversion. This function walks through
+ * the list and convert the related unwritten extents to written.
+ */
+int flush_aio_dio_completed_IO(struct inode *inode)
+{
+ ext4_io_end_t *io;
+ int ret = 0;
+ int ret2 = 0;
+
+ if (list_empty(&EXT4_I(inode)->i_aio_dio_complete_list))
+ return ret;
+
+ dump_aio_dio_list(inode);
+ while (!list_empty(&EXT4_I(inode)->i_aio_dio_complete_list)){
+ io = list_entry(EXT4_I(inode)->i_aio_dio_complete_list.next,
+ ext4_io_end_t, list);
+ /*
+ * Calling ext4_end_aio_dio_nolock() to convert completed
+ * IO to written.
+ *
+ * When ext4_sync_file() is called, run_queue() may already
+ * about to flush the work corresponding to this io structure.
+ * It will be upset if it founds the io structure related
+ * to the work-to-be schedule is freed.
+ *
+ * Thus we need to keep the io structure still valid here after
+ * convertion finished. The io structure has a flag to
+ * avoid double converting from both fsync and background work
+ * queue work.
+ */
+ ret = ext4_end_aio_dio_nolock(io);
+ if (ret < 0)
+ ret2 = ret;
+ else
+ list_del_init(&io->list);
+ }
+ return (ret2 < 0) ? ret2 : 0;
+}
+
+static ext4_io_end_t *ext4_init_io_end (struct inode *inode)
+{
+ ext4_io_end_t *io = NULL;
+
+ io = kmalloc(sizeof(*io), GFP_NOFS);
+
+ if (io) {
+ igrab(inode);
+ io->inode = inode;
+ io->flag = 0;
+ io->offset = 0;
+ io->size = 0;
+ io->error = 0;
+ INIT_WORK(&io->work, ext4_end_aio_dio_work);
+ INIT_LIST_HEAD(&io->list);
+ }
+
+ return io;
+}
+
+static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
+ ssize_t size, void *private)
+{
+ ext4_io_end_t *io_end = iocb->private;
+ struct workqueue_struct *wq;
+
+ ext_debug("ext4_end_io_dio(): io_end 0x%p"
+ "for inode %lu, iocb 0x%p, offset %llu, size %llu\n",
+ iocb->private, io_end->inode->i_ino, iocb, offset,
+ size);
+ /* if not async direct IO or dio with 0 bytes write, just return */
+ if (!io_end || !size)
+ return;
+
+ /* if not aio dio with unwritten extents, just free io and return */
+ if (io_end->flag != DIO_AIO_UNWRITTEN){
+ ext4_free_io_end(io_end);
+ iocb->private = NULL;
+ return;
+ }
+
+ io_end->offset = offset;
+ io_end->size = size;
+ wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq;
+
+ /* queue the work to convert unwritten extents to written */
+ queue_work(wq, &io_end->work);
+
+ /* Add the io_end to per-inode completed aio dio list*/
+ list_add_tail(&io_end->list,
+ &EXT4_I(io_end->inode)->i_aio_dio_complete_list);
+ iocb->private = NULL;
+}
+/*
+ * For ext4 extent files, ext4 will do direct-io write to holes,
+ * preallocated extents, and those write extend the file, no need to
+ * fall back to buffered IO.
+ *
+ * For holes, we fallocate those blocks, mark them as unintialized
+ * If those blocks were preallocated, we mark sure they are splited, but
+ * still keep the range to write as unintialized.
+ *
+ * The unwrritten extents will be converted to written when DIO is completed.
+ * For async direct IO, since the IO may still pending when return, we
+ * set up an end_io call back function, which will do the convertion
+ * when async direct IO completed.
+ *
+ * If the O_DIRECT write will extend the file then add this inode to the
+ * orphan list. So recovery will truncate it back to the original size
+ * if the machine crashes during the write.
+ *
+ */
+static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
+ const struct iovec *iov, loff_t offset,
+ unsigned long nr_segs)
+{
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file->f_mapping->host;
+ ssize_t ret;
+ size_t count = iov_length(iov, nr_segs);
+
+ loff_t final_size = offset + count;
+ if (rw == WRITE && final_size <= inode->i_size) {
+ /*
+ * We could direct write to holes and fallocate.
+ *
+ * Allocated blocks to fill the hole are marked as uninitialized
+ * to prevent paralel buffered read to expose the stale data
+ * before DIO complete the data IO.
+ *
+ * As to previously fallocated extents, ext4 get_block
+ * will just simply mark the buffer mapped but still
+ * keep the extents uninitialized.
+ *
+ * for non AIO case, we will convert those unwritten extents
+ * to written after return back from blockdev_direct_IO.
+ *
+ * for async DIO, the conversion needs to be defered when
+ * the IO is completed. The ext4 end_io callback function
+ * will be called to take care of the conversion work.
+ * Here for async case, we allocate an io_end structure to
+ * hook to the iocb.
+ */
+ iocb->private = NULL;
+ EXT4_I(inode)->cur_aio_dio = NULL;
+ if (!is_sync_kiocb(iocb)) {
+ iocb->private = ext4_init_io_end(inode);
+ if (!iocb->private)
+ return -ENOMEM;
+ /*
+ * we save the io structure for current async
+ * direct IO, so that later ext4_get_blocks()
+ * could flag the io structure whether there
+ * is a unwritten extents needs to be converted
+ * when IO is completed.
+ */
+ EXT4_I(inode)->cur_aio_dio = iocb->private;
+ }
+
+ ret = blockdev_direct_IO(rw, iocb, inode,
+ inode->i_sb->s_bdev, iov,
+ offset, nr_segs,
+ ext4_get_block_dio_write,
+ ext4_end_io_dio);
+ if (iocb->private)
+ EXT4_I(inode)->cur_aio_dio = NULL;
+ /*
+ * The io_end structure takes a reference to the inode,
+ * that structure needs to be destroyed and the
+ * reference to the inode need to be dropped, when IO is
+ * complete, even with 0 byte write, or failed.
+ *
+ * In the successful AIO DIO case, the io_end structure will be
+ * desctroyed and the reference to the inode will be dropped
+ * after the end_io call back function is called.
+ *
+ * In the case there is 0 byte write, or error case, since
+ * VFS direct IO won't invoke the end_io call back function,
+ * we need to free the end_io structure here.
+ */
+ if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) {
+ ext4_free_io_end(iocb->private);
+ iocb->private = NULL;
+ } else if (ret > 0)
+ /*
+ * for non AIO case, since the IO is already
+ * completed, we could do the convertion right here
+ */
+ ret = ext4_convert_unwritten_extents(inode,
+ offset, ret);
+ return ret;
+ }
+
+ /* for write the the end of file case, we fall back to old way */
+ return ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs);
+}
+
+static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
+ const struct iovec *iov, loff_t offset,
+ unsigned long nr_segs)
+{
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file->f_mapping->host;
+
+ if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)
+ return ext4_ext_direct_IO(rw, iocb, iov, offset, nr_segs);
+
+ return ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs);
+}
+
/*
* Pages can be marked dirty completely asynchronously from ext4's journalling
* activity. By filemap_sync_pte(), try_to_unmap_one(), etc. We cannot do
*/
static int ext4_do_update_inode(handle_t *handle,
struct inode *inode,
- struct ext4_iloc *iloc,
- int do_sync)
+ struct ext4_iloc *iloc)
{
struct ext4_inode *raw_inode = ext4_raw_inode(iloc);
struct ext4_inode_info *ei = EXT4_I(inode);
raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize);
}
- /*
- * If we're not using a journal and we were called from
- * ext4_write_inode() to sync the inode (making do_sync true),
- * we can just use sync_dirty_buffer() directly to do our dirty
- * work. Testing s_journal here is a bit redundant but it's
- * worth it to avoid potential future trouble.
- */
- if (EXT4_SB(inode->i_sb)->s_journal == NULL && do_sync) {
- BUFFER_TRACE(bh, "call sync_dirty_buffer");
- sync_dirty_buffer(bh);
- } else {
- BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
- rc = ext4_handle_dirty_metadata(handle, inode, bh);
- if (!err)
- err = rc;
- }
+ BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+ rc = ext4_handle_dirty_metadata(handle, inode, bh);
+ if (!err)
+ err = rc;
ei->i_state &= ~EXT4_STATE_NEW;
out_brelse:
err = ext4_get_inode_loc(inode, &iloc);
if (err)
return err;
- err = ext4_do_update_inode(EXT4_NOJOURNAL_HANDLE,
- inode, &iloc, wait);
+ if (wait)
+ sync_dirty_buffer(iloc.bh);
+ if (buffer_req(iloc.bh) && !buffer_uptodate(iloc.bh)) {
+ ext4_error(inode->i_sb, __func__,
+ "IO error syncing inode, "
+ "inode=%lu, block=%llu",
+ inode->i_ino,
+ (unsigned long long)iloc.bh->b_blocknr);
+ err = -EIO;
+ }
}
return err;
}
get_bh(iloc->bh);
/* ext4_do_update_inode() does jbd2_journal_dirty_metadata */
- err = ext4_do_update_inode(handle, inode, iloc, 0);
+ err = ext4_do_update_inode(handle, inode, iloc);
put_bh(iloc->bh);
return err;
}
handle_t *current_handle = ext4_journal_current_handle();
handle_t *handle;
- if (!ext4_handle_valid(current_handle)) {
- ext4_mark_inode_dirty(current_handle, inode);
- return;
- }
-
handle = ext4_journal_start(inode, 2);
if (IS_ERR(handle))
goto out;
- if (current_handle &&
- current_handle->h_transaction != handle->h_transaction) {
- /* This task has a transaction open against a different fs */
- printk(KERN_EMERG "%s: transactions do not match!\n",
- __func__);
- } else {
- jbd_debug(5, "marking dirty. outer handle=%p\n",
- current_handle);
- ext4_mark_inode_dirty(handle, inode);
- }
+
+ jbd_debug(5, "marking dirty. outer handle=%p\n", current_handle);
+ ext4_mark_inode_dirty(handle, inode);
+
ext4_journal_stop(handle);
out:
return;
return err;
}
-#ifdef EXT4_MB_HISTORY
-struct ext4_mb_proc_session {
- struct ext4_mb_history *history;
- struct super_block *sb;
- int start;
- int max;
-};
-
-static void *ext4_mb_history_skip_empty(struct ext4_mb_proc_session *s,
- struct ext4_mb_history *hs,
- int first)
-{
- if (hs == s->history + s->max)
- hs = s->history;
- if (!first && hs == s->history + s->start)
- return NULL;
- while (hs->orig.fe_len == 0) {
- hs++;
- if (hs == s->history + s->max)
- hs = s->history;
- if (hs == s->history + s->start)
- return NULL;
- }
- return hs;
-}
-
-static void *ext4_mb_seq_history_start(struct seq_file *seq, loff_t *pos)
-{
- struct ext4_mb_proc_session *s = seq->private;
- struct ext4_mb_history *hs;
- int l = *pos;
-
- if (l == 0)
- return SEQ_START_TOKEN;
- hs = ext4_mb_history_skip_empty(s, s->history + s->start, 1);
- if (!hs)
- return NULL;
- while (--l && (hs = ext4_mb_history_skip_empty(s, ++hs, 0)) != NULL);
- return hs;
-}
-
-static void *ext4_mb_seq_history_next(struct seq_file *seq, void *v,
- loff_t *pos)
-{
- struct ext4_mb_proc_session *s = seq->private;
- struct ext4_mb_history *hs = v;
-
- ++*pos;
- if (v == SEQ_START_TOKEN)
- return ext4_mb_history_skip_empty(s, s->history + s->start, 1);
- else
- return ext4_mb_history_skip_empty(s, ++hs, 0);
-}
-
-static int ext4_mb_seq_history_show(struct seq_file *seq, void *v)
-{
- char buf[25], buf2[25], buf3[25], *fmt;
- struct ext4_mb_history *hs = v;
-
- if (v == SEQ_START_TOKEN) {
- seq_printf(seq, "%-5s %-8s %-23s %-23s %-23s %-5s "
- "%-5s %-2s %-6s %-5s %-5s %-6s\n",
- "pid", "inode", "original", "goal", "result", "found",
- "grps", "cr", "flags", "merge", "tail", "broken");
- return 0;
- }
-
- if (hs->op == EXT4_MB_HISTORY_ALLOC) {
- fmt = "%-5u %-8u %-23s %-23s %-23s %-5u %-5u %-2u "
- "0x%04x %-5s %-5u %-6u\n";
- sprintf(buf2, "%u/%d/%u@%u", hs->result.fe_group,
- hs->result.fe_start, hs->result.fe_len,
- hs->result.fe_logical);
- sprintf(buf, "%u/%d/%u@%u", hs->orig.fe_group,
- hs->orig.fe_start, hs->orig.fe_len,
- hs->orig.fe_logical);
- sprintf(buf3, "%u/%d/%u@%u", hs->goal.fe_group,
- hs->goal.fe_start, hs->goal.fe_len,
- hs->goal.fe_logical);
- seq_printf(seq, fmt, hs->pid, hs->ino, buf, buf3, buf2,
- hs->found, hs->groups, hs->cr, hs->flags,
- hs->merged ? "M" : "", hs->tail,
- hs->buddy ? 1 << hs->buddy : 0);
- } else if (hs->op == EXT4_MB_HISTORY_PREALLOC) {
- fmt = "%-5u %-8u %-23s %-23s %-23s\n";
- sprintf(buf2, "%u/%d/%u@%u", hs->result.fe_group,
- hs->result.fe_start, hs->result.fe_len,
- hs->result.fe_logical);
- sprintf(buf, "%u/%d/%u@%u", hs->orig.fe_group,
- hs->orig.fe_start, hs->orig.fe_len,
- hs->orig.fe_logical);
- seq_printf(seq, fmt, hs->pid, hs->ino, buf, "", buf2);
- } else if (hs->op == EXT4_MB_HISTORY_DISCARD) {
- sprintf(buf2, "%u/%d/%u", hs->result.fe_group,
- hs->result.fe_start, hs->result.fe_len);
- seq_printf(seq, "%-5u %-8u %-23s discard\n",
- hs->pid, hs->ino, buf2);
- } else if (hs->op == EXT4_MB_HISTORY_FREE) {
- sprintf(buf2, "%u/%d/%u", hs->result.fe_group,
- hs->result.fe_start, hs->result.fe_len);
- seq_printf(seq, "%-5u %-8u %-23s free\n",
- hs->pid, hs->ino, buf2);
- }
- return 0;
-}
-
-static void ext4_mb_seq_history_stop(struct seq_file *seq, void *v)
-{
-}
-
-static const struct seq_operations ext4_mb_seq_history_ops = {
- .start = ext4_mb_seq_history_start,
- .next = ext4_mb_seq_history_next,
- .stop = ext4_mb_seq_history_stop,
- .show = ext4_mb_seq_history_show,
-};
-
-static int ext4_mb_seq_history_open(struct inode *inode, struct file *file)
-{
- struct super_block *sb = PDE(inode)->data;
- struct ext4_sb_info *sbi = EXT4_SB(sb);
- struct ext4_mb_proc_session *s;
- int rc;
- int size;
-
- if (unlikely(sbi->s_mb_history == NULL))
- return -ENOMEM;
- s = kmalloc(sizeof(*s), GFP_KERNEL);
- if (s == NULL)
- return -ENOMEM;
- s->sb = sb;
- size = sizeof(struct ext4_mb_history) * sbi->s_mb_history_max;
- s->history = kmalloc(size, GFP_KERNEL);
- if (s->history == NULL) {
- kfree(s);
- return -ENOMEM;
- }
-
- spin_lock(&sbi->s_mb_history_lock);
- memcpy(s->history, sbi->s_mb_history, size);
- s->max = sbi->s_mb_history_max;
- s->start = sbi->s_mb_history_cur % s->max;
- spin_unlock(&sbi->s_mb_history_lock);
-
- rc = seq_open(file, &ext4_mb_seq_history_ops);
- if (rc == 0) {
- struct seq_file *m = (struct seq_file *)file->private_data;
- m->private = s;
- } else {
- kfree(s->history);
- kfree(s);
- }
- return rc;
-
-}
-
-static int ext4_mb_seq_history_release(struct inode *inode, struct file *file)
-{
- struct seq_file *seq = (struct seq_file *)file->private_data;
- struct ext4_mb_proc_session *s = seq->private;
- kfree(s->history);
- kfree(s);
- return seq_release(inode, file);
-}
-
-static ssize_t ext4_mb_seq_history_write(struct file *file,
- const char __user *buffer,
- size_t count, loff_t *ppos)
-{
- struct seq_file *seq = (struct seq_file *)file->private_data;
- struct ext4_mb_proc_session *s = seq->private;
- struct super_block *sb = s->sb;
- char str[32];
- int value;
-
- if (count >= sizeof(str)) {
- printk(KERN_ERR "EXT4-fs: %s string too long, max %u bytes\n",
- "mb_history", (int)sizeof(str));
- return -EOVERFLOW;
- }
-
- if (copy_from_user(str, buffer, count))
- return -EFAULT;
-
- value = simple_strtol(str, NULL, 0);
- if (value < 0)
- return -ERANGE;
- EXT4_SB(sb)->s_mb_history_filter = value;
-
- return count;
-}
-
-static const struct file_operations ext4_mb_seq_history_fops = {
- .owner = THIS_MODULE,
- .open = ext4_mb_seq_history_open,
- .read = seq_read,
- .write = ext4_mb_seq_history_write,
- .llseek = seq_lseek,
- .release = ext4_mb_seq_history_release,
-};
-
static void *ext4_mb_seq_groups_start(struct seq_file *seq, loff_t *pos)
{
struct super_block *sb = seq->private;
.release = seq_release,
};
-static void ext4_mb_history_release(struct super_block *sb)
-{
- struct ext4_sb_info *sbi = EXT4_SB(sb);
-
- if (sbi->s_proc != NULL) {
- remove_proc_entry("mb_groups", sbi->s_proc);
- if (sbi->s_mb_history_max)
- remove_proc_entry("mb_history", sbi->s_proc);
- }
- kfree(sbi->s_mb_history);
-}
-
-static void ext4_mb_history_init(struct super_block *sb)
-{
- struct ext4_sb_info *sbi = EXT4_SB(sb);
- int i;
-
- if (sbi->s_proc != NULL) {
- if (sbi->s_mb_history_max)
- proc_create_data("mb_history", S_IRUGO, sbi->s_proc,
- &ext4_mb_seq_history_fops, sb);
- proc_create_data("mb_groups", S_IRUGO, sbi->s_proc,
- &ext4_mb_seq_groups_fops, sb);
- }
-
- sbi->s_mb_history_cur = 0;
- spin_lock_init(&sbi->s_mb_history_lock);
- i = sbi->s_mb_history_max * sizeof(struct ext4_mb_history);
- sbi->s_mb_history = i ? kzalloc(i, GFP_KERNEL) : NULL;
- /* if we can't allocate history, then we simple won't use it */
-}
-
-static noinline_for_stack void
-ext4_mb_store_history(struct ext4_allocation_context *ac)
-{
- struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
- struct ext4_mb_history h;
-
- if (sbi->s_mb_history == NULL)
- return;
-
- if (!(ac->ac_op & sbi->s_mb_history_filter))
- return;
-
- h.op = ac->ac_op;
- h.pid = current->pid;
- h.ino = ac->ac_inode ? ac->ac_inode->i_ino : 0;
- h.orig = ac->ac_o_ex;
- h.result = ac->ac_b_ex;
- h.flags = ac->ac_flags;
- h.found = ac->ac_found;
- h.groups = ac->ac_groups_scanned;
- h.cr = ac->ac_criteria;
- h.tail = ac->ac_tail;
- h.buddy = ac->ac_buddy;
- h.merged = 0;
- if (ac->ac_op == EXT4_MB_HISTORY_ALLOC) {
- if (ac->ac_g_ex.fe_start == ac->ac_b_ex.fe_start &&
- ac->ac_g_ex.fe_group == ac->ac_b_ex.fe_group)
- h.merged = 1;
- h.goal = ac->ac_g_ex;
- h.result = ac->ac_f_ex;
- }
-
- spin_lock(&sbi->s_mb_history_lock);
- memcpy(sbi->s_mb_history + sbi->s_mb_history_cur, &h, sizeof(h));
- if (++sbi->s_mb_history_cur >= sbi->s_mb_history_max)
- sbi->s_mb_history_cur = 0;
- spin_unlock(&sbi->s_mb_history_lock);
-}
-
-#else
-#define ext4_mb_history_release(sb)
-#define ext4_mb_history_init(sb)
-#endif
-
/* Create and initialize ext4_group_info data for the given group. */
int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
sbi->s_mb_stats = MB_DEFAULT_STATS;
sbi->s_mb_stream_request = MB_DEFAULT_STREAM_THRESHOLD;
sbi->s_mb_order2_reqs = MB_DEFAULT_ORDER2_REQS;
- sbi->s_mb_history_filter = EXT4_MB_HISTORY_DEFAULT;
sbi->s_mb_group_prealloc = MB_DEFAULT_GROUP_PREALLOC;
sbi->s_locality_groups = alloc_percpu(struct ext4_locality_group);
spin_lock_init(&lg->lg_prealloc_lock);
}
- ext4_mb_history_init(sb);
+ if (sbi->s_proc)
+ proc_create_data("mb_groups", S_IRUGO, sbi->s_proc,
+ &ext4_mb_seq_groups_fops, sb);
if (sbi->s_journal)
sbi->s_journal->j_commit_callback = release_blocks_on_commit;
-
- printk(KERN_INFO "EXT4-fs: mballoc enabled\n");
return 0;
}
}
free_percpu(sbi->s_locality_groups);
- ext4_mb_history_release(sb);
+ if (sbi->s_proc)
+ remove_proc_entry("mb_groups", sbi->s_proc);
return 0;
}
atomic_inc(&sbi->s_bal_breaks);
}
- ext4_mb_store_history(ac);
+ if (ac->ac_op == EXT4_MB_HISTORY_ALLOC)
+ trace_ext4_mballoc_alloc(ac);
+ else
+ trace_ext4_mballoc_prealloc(ac);
}
/*
if (ac) {
ac->ac_sb = sb;
ac->ac_inode = pa->pa_inode;
- ac->ac_op = EXT4_MB_HISTORY_DISCARD;
}
while (bit < end) {
ac->ac_b_ex.fe_start = bit;
ac->ac_b_ex.fe_len = next - bit;
ac->ac_b_ex.fe_logical = 0;
- ext4_mb_store_history(ac);
+ trace_ext4_mballoc_discard(ac);
}
trace_ext4_mb_release_inode_pa(ac, pa, grp_blk_start + bit,
ext4_group_t group;
ext4_grpblk_t bit;
- if (ac)
- ac->ac_op = EXT4_MB_HISTORY_DISCARD;
-
trace_ext4_mb_release_group_pa(ac, pa);
BUG_ON(pa->pa_deleted == 0);
ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
ac->ac_b_ex.fe_start = bit;
ac->ac_b_ex.fe_len = pa->pa_len;
ac->ac_b_ex.fe_logical = 0;
- ext4_mb_store_history(ac);
+ trace_ext4_mballoc_discard(ac);
}
return 0;
size = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len;
isize = (i_size_read(ac->ac_inode) + ac->ac_sb->s_blocksize - 1)
>> bsbits;
- size = max(size, isize);
if ((size == isize) &&
!ext4_fs_is_busy(sbi) &&
}
/* don't use group allocation for large files */
+ size = max(size, isize);
if (size >= sbi->s_mb_stream_request) {
ac->ac_flags |= EXT4_MB_STREAM_ALLOC;
return;
* per cpu locality group is to reduce the contention between block
* request from multiple CPUs.
*/
- ac->ac_lg = per_cpu_ptr(sbi->s_locality_groups, raw_smp_processor_id());
+ ac->ac_lg = __this_cpu_ptr(sbi->s_locality_groups);
/* we're going to use group allocation */
ac->ac_flags |= EXT4_MB_HINT_GROUP_ALLOC;
ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
if (ac) {
- ac->ac_op = EXT4_MB_HISTORY_FREE;
ac->ac_inode = inode;
ac->ac_sb = sb;
}
ac->ac_b_ex.fe_group = block_group;
ac->ac_b_ex.fe_start = bit;
ac->ac_b_ex.fe_len = count;
- ext4_mb_store_history(ac);
+ trace_ext4_mballoc_free(ac);
}
err = ext4_mb_load_buddy(sb, block_group, &e4b);
#define mb_debug(n, fmt, a...)
#endif
-/*
- * with EXT4_MB_HISTORY mballoc stores last N allocations in memory
- * and you can monitor it in /proc/fs/ext4/<dev>/mb_history
- */
-#define EXT4_MB_HISTORY
#define EXT4_MB_HISTORY_ALLOC 1 /* allocation */
#define EXT4_MB_HISTORY_PREALLOC 2 /* preallocated blocks used */
-#define EXT4_MB_HISTORY_DISCARD 4 /* preallocation discarded */
-#define EXT4_MB_HISTORY_FREE 8 /* free */
-
-#define EXT4_MB_HISTORY_DEFAULT (EXT4_MB_HISTORY_ALLOC | \
- EXT4_MB_HISTORY_PREALLOC)
/*
* How long mballoc can look for a best extent (in found extents)
* with 'ext4_mb_stats' allocator will collect stats that will be
* shown at umount. The collecting costs though!
*/
-#define MB_DEFAULT_STATS 1
+#define MB_DEFAULT_STATS 0
/*
* files smaller than MB_DEFAULT_STREAM_THRESHOLD are served
#define AC_STATUS_FOUND 2
#define AC_STATUS_BREAK 3
-struct ext4_mb_history {
- struct ext4_free_extent orig; /* orig allocation */
- struct ext4_free_extent goal; /* goal allocation */
- struct ext4_free_extent result; /* result allocation */
- unsigned pid;
- unsigned ino;
- __u16 found; /* how many extents have been found */
- __u16 groups; /* how many groups have been scanned */
- __u16 tail; /* what tail broke some buddy */
- __u16 buddy; /* buddy the tail ^^^ broke */
- __u16 flags;
- __u8 cr:3; /* which phase the result extent was found at */
- __u8 op:4;
- __u8 merged:1;
-};
-
struct ext4_buddy {
struct page *bd_buddy_page;
void *bd_buddy;
#define EXT4_MB_BITMAP(e4b) ((e4b)->bd_bitmap)
#define EXT4_MB_BUDDY(e4b) ((e4b)->bd_buddy)
-#ifndef EXT4_MB_HISTORY
-static inline void ext4_mb_store_history(struct ext4_allocation_context *ac)
-{
- return;
-}
-#endif
-
#define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1)
static inline ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb,
goto err_out;
}
}
- retval = ext4_ext_insert_extent(handle, inode, path, &newext);
+ retval = ext4_ext_insert_extent(handle, inode, path, &newext, 0);
err_out:
if (path) {
ext4_ext_drop_refs(path);
goto out;
if (ext4_ext_insert_extent(handle, orig_inode,
- orig_path, new_ext))
+ orig_path, new_ext, 0))
goto out;
}
goto out;
if (ext4_ext_insert_extent(handle, orig_inode,
- orig_path, end_ext))
+ orig_path, end_ext, 0))
goto out;
}
out:
return -EINVAL;
}
- /* orig and donor should be different file */
- if (orig_inode->i_ino == donor_inode->i_ino) {
- ext4_debug("ext4 move extent: The argument files should not "
- "be same file [ino:orig %lu, donor %lu]\n",
- orig_inode->i_ino, donor_inode->i_ino);
- return -EINVAL;
- }
-
/* Ext4 move extent supports only extent based file */
if (!(EXT4_I(orig_inode)->i_flags & EXT4_EXTENTS_FL)) {
ext4_debug("ext4 move extent: orig file is not extents "
int block_len_in_page;
int uninit;
+ /* orig and donor should be different file */
+ if (orig_inode->i_ino == donor_inode->i_ino) {
+ ext4_debug("ext4 move extent: The argument files should not "
+ "be same file [ino:orig %lu, donor %lu]\n",
+ orig_inode->i_ino, donor_inode->i_ino);
+ return -EINVAL;
+ }
+
/* protect orig and donor against a truncate */
ret1 = mext_inode_double_lock(orig_inode, donor_inode);
if (ret1 < 0)
struct ext4_iloc iloc;
int err = 0;
- if (!ext4_handle_valid(handle))
+ /* ext4_handle_valid() assumes a valid handle_t pointer */
+ if (handle && !ext4_handle_valid(handle))
return 0;
mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock);
#define CREATE_TRACE_POINTS
#include <trace/events/ext4.h>
-static int default_mb_history_length = 1000;
-
-module_param_named(default_mb_history_length, default_mb_history_length,
- int, 0644);
-MODULE_PARM_DESC(default_mb_history_length,
- "Default number of entries saved for mb_history");
-
struct proc_dir_entry *ext4_proc_root;
static struct kset *ext4_kset;
bg->bg_itable_unused_hi = cpu_to_le16(count >> 16);
}
+
+/* Just increment the non-pointer handle value */
+static handle_t *ext4_get_nojournal(void)
+{
+ handle_t *handle = current->journal_info;
+ unsigned long ref_cnt = (unsigned long)handle;
+
+ BUG_ON(ref_cnt >= EXT4_NOJOURNAL_MAX_REF_COUNT);
+
+ ref_cnt++;
+ handle = (handle_t *)ref_cnt;
+
+ current->journal_info = handle;
+ return handle;
+}
+
+
+/* Decrement the non-pointer handle value */
+static void ext4_put_nojournal(handle_t *handle)
+{
+ unsigned long ref_cnt = (unsigned long)handle;
+
+ BUG_ON(ref_cnt == 0);
+
+ ref_cnt--;
+ handle = (handle_t *)ref_cnt;
+
+ current->journal_info = handle;
+}
+
/*
* Wrappers for jbd2_journal_start/end.
*
}
return jbd2_journal_start(journal, nblocks);
}
- /*
- * We're not journaling, return the appropriate indication.
- */
- current->journal_info = EXT4_NOJOURNAL_HANDLE;
- return current->journal_info;
+ return ext4_get_nojournal();
}
/*
int rc;
if (!ext4_handle_valid(handle)) {
- /*
- * Do this here since we don't call jbd2_journal_stop() in
- * no-journal mode.
- */
- current->journal_info = NULL;
+ ext4_put_nojournal(handle);
return 0;
}
sb = handle->h_transaction->t_journal->j_private;
struct ext4_super_block *es = sbi->s_es;
int i, err;
+ flush_workqueue(sbi->dio_unwritten_wq);
+ destroy_workqueue(sbi->dio_unwritten_wq);
+
lock_super(sb);
lock_kernel();
if (sb->s_dirt)
ei->i_allocated_meta_blocks = 0;
ei->i_delalloc_reserved_flag = 0;
spin_lock_init(&(ei->i_block_reservation_lock));
+ INIT_LIST_HEAD(&ei->i_aio_dio_complete_list);
+ ei->cur_aio_dio = NULL;
return &ei->vfs_inode;
}
Opt_journal_update, Opt_journal_dev,
Opt_journal_checksum, Opt_journal_async_commit,
Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
- Opt_data_err_abort, Opt_data_err_ignore, Opt_mb_history_length,
+ Opt_data_err_abort, Opt_data_err_ignore,
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize,
{Opt_data_writeback, "data=writeback"},
{Opt_data_err_abort, "data_err=abort"},
{Opt_data_err_ignore, "data_err=ignore"},
- {Opt_mb_history_length, "mb_history_length=%u"},
{Opt_offusrjquota, "usrjquota="},
{Opt_usrjquota, "usrjquota=%s"},
{Opt_offgrpjquota, "grpjquota="},
case Opt_data_err_ignore:
clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
break;
- case Opt_mb_history_length:
- if (match_int(&args[0], &option))
- return 0;
- if (option < 0)
- return 0;
- sbi->s_mb_history_max = option;
- break;
#ifdef CONFIG_QUOTA
case Opt_usrjquota:
qtype = USRQUOTA;
EXT4_INODES_PER_GROUP(sb),
sbi->s_mount_opt);
- if (EXT4_SB(sb)->s_journal) {
- ext4_msg(sb, KERN_INFO, "%s journal on %s",
- EXT4_SB(sb)->s_journal->j_inode ? "internal" :
- "external", EXT4_SB(sb)->s_journal->j_devname);
- } else {
- ext4_msg(sb, KERN_INFO, "no journal");
- }
return res;
}
EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs);
EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request);
EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
+EXT4_RW_ATTR_SBI_UI(max_writeback_mb_bump, s_max_writeback_mb_bump);
static struct attribute *ext4_attrs[] = {
ATTR_LIST(delayed_allocation_blocks),
ATTR_LIST(mb_order2_req),
ATTR_LIST(mb_stream_req),
ATTR_LIST(mb_group_prealloc),
+ ATTR_LIST(max_writeback_mb_bump),
NULL,
};
sbi->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE * HZ;
sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME;
sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME;
- sbi->s_mb_history_max = default_mb_history_length;
set_opt(sbi->s_mount_opt, BARRIER);
}
sbi->s_stripe = ext4_get_stripe_size(sbi);
+ sbi->s_max_writeback_mb_bump = 128;
/*
* set up enough so that it can read an inode
clear_opt(sbi->s_mount_opt, NOBH);
}
}
+ EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten");
+ if (!EXT4_SB(sb)->dio_unwritten_wq) {
+ printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n");
+ goto failed_mount_wq;
+ }
+
/*
* The jbd2_journal_load will have done any necessary log recovery,
* so we can safely mount the rest of the filesystem now.
"available");
}
- if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
+ if (test_opt(sb, DELALLOC) &&
+ (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)) {
ext4_msg(sb, KERN_WARNING, "Ignoring delalloc option - "
"requested data journaling mode");
clear_opt(sbi->s_mount_opt, DELALLOC);
- } else if (test_opt(sb, DELALLOC))
- ext4_msg(sb, KERN_INFO, "delayed allocation enabled");
+ }
err = ext4_setup_system_zone(sb);
if (err) {
failed_mount4:
ext4_msg(sb, KERN_ERR, "mount failed");
+ destroy_workqueue(EXT4_SB(sb)->dio_unwritten_wq);
+failed_mount_wq:
ext4_release_system_zone(sb);
if (sbi->s_journal) {
jbd2_journal_destroy(sbi->s_journal);
return -EINVAL;
}
- if (journal->j_flags & JBD2_BARRIER)
- ext4_msg(sb, KERN_INFO, "barriers enabled");
- else
+ if (!(journal->j_flags & JBD2_BARRIER))
ext4_msg(sb, KERN_INFO, "barriers disabled");
if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) {
{
int ret = 0;
tid_t target;
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
trace_ext4_sync_fs(sb, wait);
- if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
+ flush_workqueue(sbi->dio_unwritten_wq);
+ if (jbd2_journal_start_commit(sbi->s_journal, &target)) {
if (wait)
- jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target);
+ jbd2_log_wait_commit(sbi->s_journal, target);
}
return ret;
}
/* fat/misc.c */
extern void fat_fs_error(struct super_block *s, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3))) __cold;
-extern void fat_clusters_flush(struct super_block *sb);
+extern int fat_clusters_flush(struct super_block *sb);
extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts,
__le16 __time, __le16 __date, u8 time_cs);
static int fat_sync_fs(struct super_block *sb, int wait)
{
- lock_super(sb);
- fat_clusters_flush(sb);
- sb->s_dirt = 0;
- unlock_super(sb);
+ int err = 0;
- return 0;
+ if (sb->s_dirt) {
+ lock_super(sb);
+ sb->s_dirt = 0;
+ err = fat_clusters_flush(sb);
+ unlock_super(sb);
+ }
+
+ return err;
}
static void fat_put_super(struct super_block *sb)
seq_puts(m, ",shortname=mixed");
break;
case VFAT_SFN_DISPLAY_LOWER | VFAT_SFN_CREATE_WIN95:
- /* seq_puts(m, ",shortname=lower"); */
+ seq_puts(m, ",shortname=lower");
break;
default:
seq_puts(m, ",shortname=unknown");
opts->codepage = fat_default_codepage;
opts->iocharset = fat_default_iocharset;
if (is_vfat) {
- opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95;
+ opts->shortname = VFAT_SFN_DISPLAY_WINNT|VFAT_SFN_CREATE_WIN95;
opts->rodir = 0;
} else {
opts->shortname = 0;
/* Flushes the number of free clusters on FAT32 */
/* XXX: Need to write one per FSINFO block. Currently only writes 1 */
-void fat_clusters_flush(struct super_block *sb)
+int fat_clusters_flush(struct super_block *sb)
{
struct msdos_sb_info *sbi = MSDOS_SB(sb);
struct buffer_head *bh;
struct fat_boot_fsinfo *fsinfo;
if (sbi->fat_bits != 32)
- return;
+ return 0;
bh = sb_bread(sb, sbi->fsinfo_sector);
if (bh == NULL) {
printk(KERN_ERR "FAT: bread failed in fat_clusters_flush\n");
- return;
+ return -EIO;
}
fsinfo = (struct fat_boot_fsinfo *)bh->b_data;
mark_buffer_dirty(bh);
}
brelse(bh);
+
+ return 0;
}
/*
int charlen;
if (utf8) {
- int name_len = strlen(name);
-
- *outlen = utf8s_to_utf16s(name, PATH_MAX, (wchar_t *) outname);
-
- /*
- * We stripped '.'s before and set len appropriately,
- * but utf8s_to_utf16s doesn't care about len
- */
- *outlen -= (name_len - len);
-
- if (*outlen > 255)
+ *outlen = utf8s_to_utf16s(name, len, (wchar_t *)outname);
+ if (*outlen < 0)
+ return *outlen;
+ else if (*outlen > 255)
return -ENAMETOOLONG;
op = &outname[*outlen * sizeof(wchar_t)];
int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
{
+ struct transaction_chp_stats_s *stats;
transaction_t *transaction;
journal_t *journal;
int ret = 0;
/* OK, that was the last buffer for the transaction: we can now
safely remove this transaction from the log */
+ stats = &transaction->t_chp_stats;
+ if (stats->cs_chp_time)
+ stats->cs_chp_time = jbd2_time_diff(stats->cs_chp_time,
+ jiffies);
+ trace_jbd2_checkpoint_stats(journal->j_fs_dev->bd_dev,
+ transaction->t_tid, stats);
__jbd2_journal_drop_transaction(journal, transaction);
kfree(transaction);
if (commit_transaction->t_synchronous_commit)
write_op = WRITE_SYNC_PLUG;
trace_jbd2_commit_locking(journal, commit_transaction);
- stats.u.run.rs_wait = commit_transaction->t_max_wait;
- stats.u.run.rs_locked = jiffies;
- stats.u.run.rs_running = jbd2_time_diff(commit_transaction->t_start,
- stats.u.run.rs_locked);
+ stats.run.rs_wait = commit_transaction->t_max_wait;
+ stats.run.rs_locked = jiffies;
+ stats.run.rs_running = jbd2_time_diff(commit_transaction->t_start,
+ stats.run.rs_locked);
spin_lock(&commit_transaction->t_handle_lock);
while (commit_transaction->t_updates) {
jbd2_journal_switch_revoke_table(journal);
trace_jbd2_commit_flushing(journal, commit_transaction);
- stats.u.run.rs_flushing = jiffies;
- stats.u.run.rs_locked = jbd2_time_diff(stats.u.run.rs_locked,
- stats.u.run.rs_flushing);
+ stats.run.rs_flushing = jiffies;
+ stats.run.rs_locked = jbd2_time_diff(stats.run.rs_locked,
+ stats.run.rs_flushing);
commit_transaction->t_state = T_FLUSH;
journal->j_committing_transaction = commit_transaction;
spin_unlock(&journal->j_state_lock);
trace_jbd2_commit_logging(journal, commit_transaction);
- stats.u.run.rs_logging = jiffies;
- stats.u.run.rs_flushing = jbd2_time_diff(stats.u.run.rs_flushing,
- stats.u.run.rs_logging);
- stats.u.run.rs_blocks = commit_transaction->t_outstanding_credits;
- stats.u.run.rs_blocks_logged = 0;
+ stats.run.rs_logging = jiffies;
+ stats.run.rs_flushing = jbd2_time_diff(stats.run.rs_flushing,
+ stats.run.rs_logging);
+ stats.run.rs_blocks = commit_transaction->t_outstanding_credits;
+ stats.run.rs_blocks_logged = 0;
J_ASSERT(commit_transaction->t_nr_buffers <=
commit_transaction->t_outstanding_credits);
submit_bh(write_op, bh);
}
cond_resched();
- stats.u.run.rs_blocks_logged += bufs;
+ stats.run.rs_blocks_logged += bufs;
/* Force a new descriptor to be generated next
time round the loop. */
J_ASSERT(commit_transaction->t_state == T_COMMIT);
commit_transaction->t_start = jiffies;
- stats.u.run.rs_logging = jbd2_time_diff(stats.u.run.rs_logging,
- commit_transaction->t_start);
+ stats.run.rs_logging = jbd2_time_diff(stats.run.rs_logging,
+ commit_transaction->t_start);
/*
- * File the transaction for history
+ * File the transaction statistics
*/
- stats.ts_type = JBD2_STATS_RUN;
stats.ts_tid = commit_transaction->t_tid;
- stats.u.run.rs_handle_count = commit_transaction->t_handle_count;
- spin_lock(&journal->j_history_lock);
- memcpy(journal->j_history + journal->j_history_cur, &stats,
- sizeof(stats));
- if (++journal->j_history_cur == journal->j_history_max)
- journal->j_history_cur = 0;
+ stats.run.rs_handle_count = commit_transaction->t_handle_count;
+ trace_jbd2_run_stats(journal->j_fs_dev->bd_dev,
+ commit_transaction->t_tid, &stats.run);
/*
* Calculate overall stats
*/
+ spin_lock(&journal->j_history_lock);
journal->j_stats.ts_tid++;
- journal->j_stats.u.run.rs_wait += stats.u.run.rs_wait;
- journal->j_stats.u.run.rs_running += stats.u.run.rs_running;
- journal->j_stats.u.run.rs_locked += stats.u.run.rs_locked;
- journal->j_stats.u.run.rs_flushing += stats.u.run.rs_flushing;
- journal->j_stats.u.run.rs_logging += stats.u.run.rs_logging;
- journal->j_stats.u.run.rs_handle_count += stats.u.run.rs_handle_count;
- journal->j_stats.u.run.rs_blocks += stats.u.run.rs_blocks;
- journal->j_stats.u.run.rs_blocks_logged += stats.u.run.rs_blocks_logged;
+ journal->j_stats.run.rs_wait += stats.run.rs_wait;
+ journal->j_stats.run.rs_running += stats.run.rs_running;
+ journal->j_stats.run.rs_locked += stats.run.rs_locked;
+ journal->j_stats.run.rs_flushing += stats.run.rs_flushing;
+ journal->j_stats.run.rs_logging += stats.run.rs_logging;
+ journal->j_stats.run.rs_handle_count += stats.run.rs_handle_count;
+ journal->j_stats.run.rs_blocks += stats.run.rs_blocks;
+ journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged;
spin_unlock(&journal->j_history_lock);
commit_transaction->t_state = T_FINISHED;
journal->j_task = current;
wake_up(&journal->j_wait_done_commit);
- printk(KERN_INFO "kjournald2 starting: pid %d, dev %s, "
- "commit interval %ld seconds\n", current->pid,
- journal->j_devname, journal->j_commit_interval / HZ);
-
/*
* And now, wait forever for commit wakeup events.
*/
{
struct task_struct *t;
- t = kthread_run(kjournald2, journal, "kjournald2");
+ t = kthread_run(kjournald2, journal, "jbd2/%s",
+ journal->j_devname);
if (IS_ERR(t))
return PTR_ERR(t);
int max;
};
-static void *jbd2_history_skip_empty(struct jbd2_stats_proc_session *s,
- struct transaction_stats_s *ts,
- int first)
-{
- if (ts == s->stats + s->max)
- ts = s->stats;
- if (!first && ts == s->stats + s->start)
- return NULL;
- while (ts->ts_type == 0) {
- ts++;
- if (ts == s->stats + s->max)
- ts = s->stats;
- if (ts == s->stats + s->start)
- return NULL;
- }
- return ts;
-
-}
-
-static void *jbd2_seq_history_start(struct seq_file *seq, loff_t *pos)
-{
- struct jbd2_stats_proc_session *s = seq->private;
- struct transaction_stats_s *ts;
- int l = *pos;
-
- if (l == 0)
- return SEQ_START_TOKEN;
- ts = jbd2_history_skip_empty(s, s->stats + s->start, 1);
- if (!ts)
- return NULL;
- l--;
- while (l) {
- ts = jbd2_history_skip_empty(s, ++ts, 0);
- if (!ts)
- break;
- l--;
- }
- return ts;
-}
-
-static void *jbd2_seq_history_next(struct seq_file *seq, void *v, loff_t *pos)
-{
- struct jbd2_stats_proc_session *s = seq->private;
- struct transaction_stats_s *ts = v;
-
- ++*pos;
- if (v == SEQ_START_TOKEN)
- return jbd2_history_skip_empty(s, s->stats + s->start, 1);
- else
- return jbd2_history_skip_empty(s, ++ts, 0);
-}
-
-static int jbd2_seq_history_show(struct seq_file *seq, void *v)
-{
- struct transaction_stats_s *ts = v;
- if (v == SEQ_START_TOKEN) {
- seq_printf(seq, "%-4s %-5s %-5s %-5s %-5s %-5s %-5s %-6s %-5s "
- "%-5s %-5s %-5s %-5s %-5s\n", "R/C", "tid",
- "wait", "run", "lock", "flush", "log", "hndls",
- "block", "inlog", "ctime", "write", "drop",
- "close");
- return 0;
- }
- if (ts->ts_type == JBD2_STATS_RUN)
- seq_printf(seq, "%-4s %-5lu %-5u %-5u %-5u %-5u %-5u "
- "%-6lu %-5lu %-5lu\n", "R", ts->ts_tid,
- jiffies_to_msecs(ts->u.run.rs_wait),
- jiffies_to_msecs(ts->u.run.rs_running),
- jiffies_to_msecs(ts->u.run.rs_locked),
- jiffies_to_msecs(ts->u.run.rs_flushing),
- jiffies_to_msecs(ts->u.run.rs_logging),
- ts->u.run.rs_handle_count,
- ts->u.run.rs_blocks,
- ts->u.run.rs_blocks_logged);
- else if (ts->ts_type == JBD2_STATS_CHECKPOINT)
- seq_printf(seq, "%-4s %-5lu %48s %-5u %-5lu %-5lu %-5lu\n",
- "C", ts->ts_tid, " ",
- jiffies_to_msecs(ts->u.chp.cs_chp_time),
- ts->u.chp.cs_written, ts->u.chp.cs_dropped,
- ts->u.chp.cs_forced_to_close);
- else
- J_ASSERT(0);
- return 0;
-}
-
-static void jbd2_seq_history_stop(struct seq_file *seq, void *v)
-{
-}
-
-static const struct seq_operations jbd2_seq_history_ops = {
- .start = jbd2_seq_history_start,
- .next = jbd2_seq_history_next,
- .stop = jbd2_seq_history_stop,
- .show = jbd2_seq_history_show,
-};
-
-static int jbd2_seq_history_open(struct inode *inode, struct file *file)
-{
- journal_t *journal = PDE(inode)->data;
- struct jbd2_stats_proc_session *s;
- int rc, size;
-
- s = kmalloc(sizeof(*s), GFP_KERNEL);
- if (s == NULL)
- return -ENOMEM;
- size = sizeof(struct transaction_stats_s) * journal->j_history_max;
- s->stats = kmalloc(size, GFP_KERNEL);
- if (s->stats == NULL) {
- kfree(s);
- return -ENOMEM;
- }
- spin_lock(&journal->j_history_lock);
- memcpy(s->stats, journal->j_history, size);
- s->max = journal->j_history_max;
- s->start = journal->j_history_cur % s->max;
- spin_unlock(&journal->j_history_lock);
-
- rc = seq_open(file, &jbd2_seq_history_ops);
- if (rc == 0) {
- struct seq_file *m = file->private_data;
- m->private = s;
- } else {
- kfree(s->stats);
- kfree(s);
- }
- return rc;
-
-}
-
-static int jbd2_seq_history_release(struct inode *inode, struct file *file)
-{
- struct seq_file *seq = file->private_data;
- struct jbd2_stats_proc_session *s = seq->private;
-
- kfree(s->stats);
- kfree(s);
- return seq_release(inode, file);
-}
-
-static struct file_operations jbd2_seq_history_fops = {
- .owner = THIS_MODULE,
- .open = jbd2_seq_history_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = jbd2_seq_history_release,
-};
-
static void *jbd2_seq_info_start(struct seq_file *seq, loff_t *pos)
{
return *pos ? NULL : SEQ_START_TOKEN;
if (v != SEQ_START_TOKEN)
return 0;
- seq_printf(seq, "%lu transaction, each upto %u blocks\n",
+ seq_printf(seq, "%lu transaction, each up to %u blocks\n",
s->stats->ts_tid,
s->journal->j_max_transaction_buffers);
if (s->stats->ts_tid == 0)
return 0;
seq_printf(seq, "average: \n %ums waiting for transaction\n",
- jiffies_to_msecs(s->stats->u.run.rs_wait / s->stats->ts_tid));
+ jiffies_to_msecs(s->stats->run.rs_wait / s->stats->ts_tid));
seq_printf(seq, " %ums running transaction\n",
- jiffies_to_msecs(s->stats->u.run.rs_running / s->stats->ts_tid));
+ jiffies_to_msecs(s->stats->run.rs_running / s->stats->ts_tid));
seq_printf(seq, " %ums transaction was being locked\n",
- jiffies_to_msecs(s->stats->u.run.rs_locked / s->stats->ts_tid));
+ jiffies_to_msecs(s->stats->run.rs_locked / s->stats->ts_tid));
seq_printf(seq, " %ums flushing data (in ordered mode)\n",
- jiffies_to_msecs(s->stats->u.run.rs_flushing / s->stats->ts_tid));
+ jiffies_to_msecs(s->stats->run.rs_flushing / s->stats->ts_tid));
seq_printf(seq, " %ums logging transaction\n",
- jiffies_to_msecs(s->stats->u.run.rs_logging / s->stats->ts_tid));
+ jiffies_to_msecs(s->stats->run.rs_logging / s->stats->ts_tid));
seq_printf(seq, " %lluus average transaction commit time\n",
div_u64(s->journal->j_average_commit_time, 1000));
seq_printf(seq, " %lu handles per transaction\n",
- s->stats->u.run.rs_handle_count / s->stats->ts_tid);
+ s->stats->run.rs_handle_count / s->stats->ts_tid);
seq_printf(seq, " %lu blocks per transaction\n",
- s->stats->u.run.rs_blocks / s->stats->ts_tid);
+ s->stats->run.rs_blocks / s->stats->ts_tid);
seq_printf(seq, " %lu logged blocks per transaction\n",
- s->stats->u.run.rs_blocks_logged / s->stats->ts_tid);
+ s->stats->run.rs_blocks_logged / s->stats->ts_tid);
return 0;
}
return seq_release(inode, file);
}
-static struct file_operations jbd2_seq_info_fops = {
+static const struct file_operations jbd2_seq_info_fops = {
.owner = THIS_MODULE,
.open = jbd2_seq_info_open,
.read = seq_read,
{
journal->j_proc_entry = proc_mkdir(journal->j_devname, proc_jbd2_stats);
if (journal->j_proc_entry) {
- proc_create_data("history", S_IRUGO, journal->j_proc_entry,
- &jbd2_seq_history_fops, journal);
proc_create_data("info", S_IRUGO, journal->j_proc_entry,
&jbd2_seq_info_fops, journal);
}
static void jbd2_stats_proc_exit(journal_t *journal)
{
remove_proc_entry("info", journal->j_proc_entry);
- remove_proc_entry("history", journal->j_proc_entry);
remove_proc_entry(journal->j_devname, proc_jbd2_stats);
}
-static void journal_init_stats(journal_t *journal)
-{
- int size;
-
- if (!proc_jbd2_stats)
- return;
-
- journal->j_history_max = 100;
- size = sizeof(struct transaction_stats_s) * journal->j_history_max;
- journal->j_history = kzalloc(size, GFP_KERNEL);
- if (!journal->j_history) {
- journal->j_history_max = 0;
- return;
- }
- spin_lock_init(&journal->j_history_lock);
-}
-
/*
* Management for journal control blocks: functions to create and
* destroy journal_t structures, and to initialise and read existing
goto fail;
}
- journal_init_stats(journal);
+ spin_lock_init(&journal->j_history_lock);
return journal;
fail:
while ((p = strchr(p, '/')))
*p = '!';
p = journal->j_devname + strlen(journal->j_devname);
- sprintf(p, ":%lu", journal->j_inode->i_ino);
+ sprintf(p, "-%lu", journal->j_inode->i_ino);
jbd_debug(1,
"journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n",
journal, inode->i_sb->s_id, inode->i_ino,
static inline void nfs_inc_server_stats(const struct nfs_server *server,
enum nfs_stat_eventcounters stat)
{
- struct nfs_iostats *iostats;
- int cpu;
-
- cpu = get_cpu();
- iostats = per_cpu_ptr(server->io_stats, cpu);
- iostats->events[stat]++;
- put_cpu();
+ this_cpu_inc(server->io_stats->events[stat]);
}
static inline void nfs_inc_stats(const struct inode *inode,
enum nfs_stat_bytecounters stat,
unsigned long addend)
{
- struct nfs_iostats *iostats;
- int cpu;
-
- cpu = get_cpu();
- iostats = per_cpu_ptr(server->io_stats, cpu);
- iostats->bytes[stat] += addend;
- put_cpu();
+ this_cpu_add(server->io_stats->bytes[stat], addend);
}
static inline void nfs_add_stats(const struct inode *inode,
enum nfs_stat_fscachecounters stat,
unsigned long addend)
{
- struct nfs_iostats *iostats;
- int cpu;
-
- cpu = get_cpu();
- iostats = per_cpu_ptr(NFS_SERVER(inode)->io_stats, cpu);
- iostats->fscache[stat] += addend;
- put_cpu();
+ this_cpu_add(NFS_SERVER(inode)->io_stats->fscache[stat], addend);
}
#endif
extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
-static struct file_operations pool_stats_operations = {
+static const struct file_operations pool_stats_operations = {
.open = nfsd_pool_stats_open,
.read = seq_read,
.llseek = seq_lseek,
void nilfs_btnode_cache_init_once(struct address_space *btnc)
{
+ memset(btnc, 0, sizeof(*btnc));
INIT_RADIX_TREE(&btnc->page_tree, GFP_ATOMIC);
spin_lock_init(&btnc->tree_lock);
INIT_LIST_HEAD(&btnc->private_list);
return 0;
}
-struct file_operations nilfs_dir_operations = {
+const struct file_operations nilfs_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
.readdir = nilfs_readdir,
* We have mostly NULL's here: the current defaults are ok for
* the nilfs filesystem.
*/
-struct file_operations nilfs_file_operations = {
+const struct file_operations nilfs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
ii->i_dir_acl = S_ISREG(inode->i_mode) ?
0 : le32_to_cpu(raw_inode->i_dir_acl);
#endif
+ ii->i_dir_start_lookup = 0;
ii->i_cno = 0;
inode->i_generation = le32_to_cpu(raw_inode->i_generation);
};
static const struct inode_operations def_mdt_iops;
-static struct file_operations def_mdt_fops;
+static const struct file_operations def_mdt_fops;
/*
* NILFS2 uses pseudo inodes for meta data files such as DAT, cpfile, sufile,
/*
* Inodes and files operations
*/
-extern struct file_operations nilfs_dir_operations;
+extern const struct file_operations nilfs_dir_operations;
extern const struct inode_operations nilfs_file_inode_operations;
-extern struct file_operations nilfs_file_operations;
+extern const struct file_operations nilfs_file_operations;
extern const struct address_space_operations nilfs_aops;
extern const struct inode_operations nilfs_dir_inode_operations;
extern const struct inode_operations nilfs_special_inode_operations;
while (*s && len > 0) {
if (*s & 0x80) {
size = utf8_to_utf32(s, len, &u);
- if (size < 0) {
- /* Ignore character and move on */
- size = 1;
- } else if (u >= PLANE_SIZE) {
+ if (size < 0)
+ return -EINVAL;
+
+ if (u >= PLANE_SIZE) {
u -= PLANE_SIZE;
*op++ = (wchar_t) (SURROGATE_PAIR |
((u >> 10) & SURROGATE_BITS));
}
#endif /* CONFIG_DEBUG_FS */
-static struct file_operations o2hb_debug_fops = {
+static const struct file_operations o2hb_debug_fops = {
.open = o2hb_debug_open,
.release = o2hb_debug_release,
.read = o2hb_debug_read,
return seq_release_private(inode, file);
}
-static struct file_operations nst_seq_fops = {
+static const struct file_operations nst_seq_fops = {
.open = nst_fop_open,
.read = seq_read,
.llseek = seq_lseek,
return seq_release_private(inode, file);
}
-static struct file_operations sc_seq_fops = {
+static const struct file_operations sc_seq_fops = {
.open = sc_fop_open,
.read = seq_read,
.llseek = seq_lseek,
return -ENOMEM;
}
-static struct file_operations debug_purgelist_fops = {
+static const struct file_operations debug_purgelist_fops = {
.open = debug_purgelist_open,
.release = debug_buffer_release,
.read = debug_buffer_read,
return -ENOMEM;
}
-static struct file_operations debug_mle_fops = {
+static const struct file_operations debug_mle_fops = {
.open = debug_mle_open,
.release = debug_buffer_release,
.read = debug_buffer_read,
return seq_release_private(inode, file);
}
-static struct file_operations debug_lockres_fops = {
+static const struct file_operations debug_lockres_fops = {
.open = debug_lockres_open,
.release = debug_lockres_release,
.read = seq_read,
return -ENOMEM;
}
-static struct file_operations debug_state_fops = {
+static const struct file_operations debug_state_fops = {
.open = debug_state_open,
.release = debug_buffer_release,
.read = debug_buffer_read,
}
#endif /* CONFIG_DEBUG_FS */
-static struct file_operations ocfs2_osb_debug_fops = {
+static const struct file_operations ocfs2_osb_debug_fops = {
.open = ocfs2_osb_debug_open,
.release = ocfs2_debug_release,
.read = ocfs2_debug_read,
.rmdir = omfs_rmdir,
};
-struct file_operations omfs_dir_operations = {
+const struct file_operations omfs_dir_operations = {
.read = generic_read_dir,
.readdir = omfs_readdir,
.llseek = generic_file_llseek,
return generic_block_bmap(mapping, block, omfs_get_block);
}
-struct file_operations omfs_file_operations = {
+const struct file_operations omfs_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
extern int omfs_clear_range(struct super_block *sb, u64 block, int count);
/* dir.c */
-extern struct file_operations omfs_dir_operations;
+extern const struct file_operations omfs_dir_operations;
extern const struct inode_operations omfs_dir_inops;
extern int omfs_make_empty(struct inode *inode, struct super_block *sb);
extern int omfs_is_bad(struct omfs_sb_info *sbi, struct omfs_header *header,
u64 fsblock);
/* file.c */
-extern struct file_operations omfs_file_operations;
+extern const struct file_operations omfs_file_operations;
extern const struct inode_operations omfs_file_inops;
extern const struct address_space_operations omfs_aops;
extern void omfs_make_empty_table(struct buffer_head *bh, int offset);
{
xfs_icsb_cnts_t *icsbp;
long long lcounter; /* long counter for 64 bit fields */
- int cpu, ret = 0;
+ int ret = 0;
might_sleep();
again:
- cpu = get_cpu();
- icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu);
+ preempt_disable();
+ icsbp = this_cpu_ptr(mp->m_sb_cnts);
/*
* if the counter is disabled, go to slow path
break;
}
xfs_icsb_unlock_cntr(icsbp);
- put_cpu();
+ preempt_enable();
return 0;
slow_path:
- put_cpu();
+ preempt_enable();
/*
* serialise with a mutex so we don't burn lots of cpu on
balance_counter:
xfs_icsb_unlock_cntr(icsbp);
- put_cpu();
+ preempt_enable();
/*
* We may have multiple threads here if multiple per-cpu
#ifndef _ASM_GENERIC_GPIO_H
#define _ASM_GENERIC_GPIO_H
+#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
#define __raw_get_cpu_var(var) \
(*SHIFT_PERCPU_PTR(&per_cpu_var(var), __my_cpu_offset))
+#define this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, my_cpu_offset)
+#define __this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, __my_cpu_offset)
+
#ifdef CONFIG_HAVE_SETUP_PER_CPU_AREA
extern void setup_per_cpu_areas(void);
#define per_cpu(var, cpu) (*((void)(cpu), &per_cpu_var(var)))
#define __get_cpu_var(var) per_cpu_var(var)
#define __raw_get_cpu_var(var) per_cpu_var(var)
+#define this_cpu_ptr(ptr) per_cpu_ptr(ptr, 0)
+#define __this_cpu_ptr(ptr) this_cpu_ptr(ptr)
#endif /* SMP */
* @get_modes: get mode list for this connector
* @set_property: property for this connector may need update
* @destroy: make object go away
+ * @force: notify the driver the connector is forced on
*
* Each CRTC may have one or more connectors attached to it. The functions
* below allow the core DRM code to control connectors, enumerate available modes,
int (*set_property)(struct drm_connector *connector, struct drm_property *property,
uint64_t val);
void (*destroy)(struct drm_connector *connector);
+ void (*force)(struct drm_connector *connector);
};
struct drm_encoder_funcs {
void *helper_private;
};
+enum drm_connector_force {
+ DRM_FORCE_UNSPECIFIED,
+ DRM_FORCE_OFF,
+ DRM_FORCE_ON, /* force on analog part normally */
+ DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */
+};
+
/**
* drm_connector - central DRM connector control structure
* @crtc: CRTC this connector is currently connected to, NULL if none
void *helper_private;
+ /* forced on connector */
+ enum drm_connector_force force;
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
uint32_t force_encoder_id;
struct drm_encoder *encoder; /* currently active encoder */
+ void *fb_helper_private;
};
/**
extern bool drm_detect_hdmi_monitor(struct edid *edid);
extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
int hdisplay, int vdisplay, int vrefresh,
- bool reduced, bool interlaced);
+ bool reduced, bool interlaced, bool margins);
extern struct drm_display_mode *drm_gtf_mode(struct drm_device *dev,
int hdisplay, int vdisplay, int vrefresh,
bool interlaced, int margins);
#include <linux/fb.h>
+#include "drm_fb_helper.h"
struct drm_crtc_helper_funcs {
/*
* Control power levels on the CRTC. If the mode passed in is
encoder->helper_private = (void *)funcs;
}
-static inline void drm_connector_helper_add(struct drm_connector *connector,
+static inline int drm_connector_helper_add(struct drm_connector *connector,
const struct drm_connector_helper_funcs *funcs)
{
connector->helper_private = (void *)funcs;
+ return drm_fb_helper_add_connector(connector);
}
extern int drm_helper_resume_force_mode(struct drm_device *dev);
struct drm_mode_set mode_set;
};
+
struct drm_fb_helper_funcs {
void (*gamma_set)(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno);
};
+/* mode specified on the command line */
+struct drm_fb_helper_cmdline_mode {
+ bool specified;
+ bool refresh_specified;
+ bool bpp_specified;
+ int xres, yres;
+ int bpp;
+ int refresh;
+ bool rb;
+ bool interlace;
+ bool cvt;
+ bool margins;
+};
+
+struct drm_fb_helper_connector {
+ struct drm_fb_helper_cmdline_mode cmdline_mode;
+};
+
struct drm_fb_helper {
struct drm_framebuffer *fb;
struct drm_device *dev;
uint32_t fb_height,
uint32_t surface_width,
uint32_t surface_height,
+ uint32_t surface_depth,
+ uint32_t surface_bpp,
struct drm_framebuffer **fb_ptr));
int drm_fb_helper_init_crtc_count(struct drm_fb_helper *helper, int crtc_count,
int max_conn);
uint32_t fb_width, uint32_t fb_height);
void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch);
+int drm_fb_helper_add_connector(struct drm_connector *connector);
+int drm_fb_helper_parse_command_line(struct drm_device *dev);
+
#endif
int (*getsockopt)(struct atm_vcc *vcc,int level,int optname,
void __user *optval,int optlen);
int (*setsockopt)(struct atm_vcc *vcc,int level,int optname,
- void __user *optval,int optlen);
+ void __user *optval,unsigned int optlen);
int (*send)(struct atm_vcc *vcc,struct sk_buff *skb);
int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags);
void (*phy_put)(struct atm_dev *dev,unsigned char value,
extern int cgroupstats_build(struct cgroupstats *stats,
struct dentry *dentry);
-extern struct file_operations proc_cgroup_operations;
+extern const struct file_operations proc_cgroup_operations;
/* Define the enumeration of all cgroup subsystems */
#define SUBSYS(_x) _x ## _subsys_id,
__simple_attr_check_format(__fmt, 0ull); \
return simple_attr_open(inode, file, __get, __set, __fmt); \
} \
-static struct file_operations __fops = { \
+static const struct file_operations __fops = { \
.owner = THIS_MODULE, \
.open = __fops ## _open, \
.release = simple_attr_release, \
__u16 flags;
__u16 __reserved;
__u32 datalen;
- __u32 rs_delay;
+ __u32 __reserved2;
/* data follows */
};
*/
struct transaction_chp_stats_s {
unsigned long cs_chp_time;
- unsigned long cs_forced_to_close;
- unsigned long cs_written;
- unsigned long cs_dropped;
+ __u32 cs_forced_to_close;
+ __u32 cs_written;
+ __u32 cs_dropped;
};
/* The transaction_t type is the guts of the journaling mechanism. It
unsigned long rs_flushing;
unsigned long rs_logging;
- unsigned long rs_handle_count;
- unsigned long rs_blocks;
- unsigned long rs_blocks_logged;
+ __u32 rs_handle_count;
+ __u32 rs_blocks;
+ __u32 rs_blocks_logged;
};
struct transaction_stats_s {
- int ts_type;
unsigned long ts_tid;
- union {
- struct transaction_run_stats_s run;
- struct transaction_chp_stats_s chp;
- } u;
+ struct transaction_run_stats_s run;
};
-#define JBD2_STATS_RUN 1
-#define JBD2_STATS_CHECKPOINT 2
-
static inline unsigned long
jbd2_time_diff(unsigned long start, unsigned long end)
{
/*
* Journal statistics
*/
- struct transaction_stats_s *j_history;
- int j_history_max;
- int j_history_cur;
- /*
- * Protect the transactions statistics history
- */
spinlock_t j_history_lock;
struct proc_dir_entry *j_proc_entry;
struct transaction_stats_s j_stats;
#endif
#ifdef CONFIG_IP_MROUTE
-extern int ip_mroute_setsockopt(struct sock *, int, char __user *, int);
+extern int ip_mroute_setsockopt(struct sock *, int, char __user *, unsigned int);
extern int ip_mroute_getsockopt(struct sock *, int, char __user *, int __user *);
extern int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg);
extern int ip_mr_init(void);
#else
static inline
int ip_mroute_setsockopt(struct sock *sock,
- int optname, char __user *optval, int optlen)
+ int optname, char __user *optval, unsigned int optlen)
{
return -ENOPROTOOPT;
}
struct sock;
#ifdef CONFIG_IPV6_MROUTE
-extern int ip6_mroute_setsockopt(struct sock *, int, char __user *, int);
+extern int ip6_mroute_setsockopt(struct sock *, int, char __user *, unsigned int);
extern int ip6_mroute_getsockopt(struct sock *, int, char __user *, int __user *);
extern int ip6_mr_input(struct sk_buff *skb);
extern int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg);
#else
static inline
int ip6_mroute_setsockopt(struct sock *sock,
- int optname, char __user *optval, int optlen)
+ int optname, char __user *optval, unsigned int optlen)
{
return -ENOPROTOOPT;
}
int (*listen) (struct socket *sock, int len);
int (*shutdown) (struct socket *sock, int flags);
int (*setsockopt)(struct socket *sock, int level,
- int optname, char __user *optval, int optlen);
+ int optname, char __user *optval, unsigned int optlen);
int (*getsockopt)(struct socket *sock, int level,
int optname, char __user *optval, int __user *optlen);
int (*compat_setsockopt)(struct socket *sock, int level,
- int optname, char __user *optval, int optlen);
+ int optname, char __user *optval, unsigned int optlen);
int (*compat_getsockopt)(struct socket *sock, int level,
int optname, char __user *optval, int __user *optlen);
int (*sendmsg) (struct kiocb *iocb, struct socket *sock,
extern int kernel_getsockopt(struct socket *sock, int level, int optname,
char *optval, int *optlen);
extern int kernel_setsockopt(struct socket *sock, int level, int optname,
- char *optval, int optlen);
+ char *optval, unsigned int optlen);
extern int kernel_sendpage(struct socket *sock, struct page *page, int offset,
size_t size, int flags);
extern int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg);
SOCKCALL_WRAP(name, listen, (struct socket *sock, int len), (sock, len)) \
SOCKCALL_WRAP(name, shutdown, (struct socket *sock, int flags), (sock, flags)) \
SOCKCALL_WRAP(name, setsockopt, (struct socket *sock, int level, int optname, \
- char __user *optval, int optlen), (sock, level, optname, optval, optlen)) \
+ char __user *optval, unsigned int optlen), (sock, level, optname, optval, optlen)) \
SOCKCALL_WRAP(name, getsockopt, (struct socket *sock, int level, int optname, \
char __user *optval, int __user *optlen), (sock, level, optname, optval, optlen)) \
SOCKCALL_WRAP(name, sendmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t len), \
/* Call setsockopt() */
int nf_setsockopt(struct sock *sk, u_int8_t pf, int optval, char __user *opt,
- int len);
+ unsigned int len);
int nf_getsockopt(struct sock *sk, u_int8_t pf, int optval, char __user *opt,
int *len);
int compat_nf_setsockopt(struct sock *sk, u_int8_t pf, int optval,
- char __user *opt, int len);
+ char __user *opt, unsigned int len);
int compat_nf_getsockopt(struct sock *sk, u_int8_t pf, int optval,
char __user *opt, int *len);
#ifdef CONFIG_SMP
-#ifndef CONFIG_HAVE_LEGACY_PER_CPU_AREA
-
/* minimum unit size, also is the maximum supported allocation size */
#define PCPU_MIN_UNIT_SIZE PFN_ALIGN(64 << 10)
#define per_cpu_ptr(ptr, cpu) SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu)))
extern void *__alloc_reserved_percpu(size_t size, size_t align);
-
-#else /* CONFIG_HAVE_LEGACY_PER_CPU_AREA */
-
-struct percpu_data {
- void *ptrs[1];
-};
-
-/* pointer disguising messes up the kmemleak objects tracking */
-#ifndef CONFIG_DEBUG_KMEMLEAK
-#define __percpu_disguise(pdata) (struct percpu_data *)~(unsigned long)(pdata)
-#else
-#define __percpu_disguise(pdata) (struct percpu_data *)(pdata)
-#endif
-
-#define per_cpu_ptr(ptr, cpu) \
-({ \
- struct percpu_data *__p = __percpu_disguise(ptr); \
- (__typeof__(ptr))__p->ptrs[(cpu)]; \
-})
-
-#endif /* CONFIG_HAVE_LEGACY_PER_CPU_AREA */
-
extern void *__alloc_percpu(size_t size, size_t align);
extern void free_percpu(void *__pdata);
# define percpu_xor(var, val) __percpu_generic_to_op(var, (val), ^=)
#endif
+/*
+ * Branching function to split up a function into a set of functions that
+ * are called for different scalar sizes of the objects handled.
+ */
+
+extern void __bad_size_call_parameter(void);
+
+#define __size_call_return(stem, variable) \
+({ typeof(variable) ret__; \
+ switch(sizeof(variable)) { \
+ case 1: ret__ = stem##1(variable);break; \
+ case 2: ret__ = stem##2(variable);break; \
+ case 4: ret__ = stem##4(variable);break; \
+ case 8: ret__ = stem##8(variable);break; \
+ default: \
+ __bad_size_call_parameter();break; \
+ } \
+ ret__; \
+})
+
+#define __size_call(stem, variable, ...) \
+do { \
+ switch(sizeof(variable)) { \
+ case 1: stem##1(variable, __VA_ARGS__);break; \
+ case 2: stem##2(variable, __VA_ARGS__);break; \
+ case 4: stem##4(variable, __VA_ARGS__);break; \
+ case 8: stem##8(variable, __VA_ARGS__);break; \
+ default: \
+ __bad_size_call_parameter();break; \
+ } \
+} while (0)
+
+/*
+ * Optimized manipulation for memory allocated through the per cpu
+ * allocator or for addresses of per cpu variables (can be determined
+ * using per_cpu_var(xx).
+ *
+ * These operation guarantee exclusivity of access for other operations
+ * on the *same* processor. The assumption is that per cpu data is only
+ * accessed by a single processor instance (the current one).
+ *
+ * The first group is used for accesses that must be done in a
+ * preemption safe way since we know that the context is not preempt
+ * safe. Interrupts may occur. If the interrupt modifies the variable
+ * too then RMW actions will not be reliable.
+ *
+ * The arch code can provide optimized functions in two ways:
+ *
+ * 1. Override the function completely. F.e. define this_cpu_add().
+ * The arch must then ensure that the various scalar format passed
+ * are handled correctly.
+ *
+ * 2. Provide functions for certain scalar sizes. F.e. provide
+ * this_cpu_add_2() to provide per cpu atomic operations for 2 byte
+ * sized RMW actions. If arch code does not provide operations for
+ * a scalar size then the fallback in the generic code will be
+ * used.
+ */
+
+#define _this_cpu_generic_read(pcp) \
+({ typeof(pcp) ret__; \
+ preempt_disable(); \
+ ret__ = *this_cpu_ptr(&(pcp)); \
+ preempt_enable(); \
+ ret__; \
+})
+
+#ifndef this_cpu_read
+# ifndef this_cpu_read_1
+# define this_cpu_read_1(pcp) _this_cpu_generic_read(pcp)
+# endif
+# ifndef this_cpu_read_2
+# define this_cpu_read_2(pcp) _this_cpu_generic_read(pcp)
+# endif
+# ifndef this_cpu_read_4
+# define this_cpu_read_4(pcp) _this_cpu_generic_read(pcp)
+# endif
+# ifndef this_cpu_read_8
+# define this_cpu_read_8(pcp) _this_cpu_generic_read(pcp)
+# endif
+# define this_cpu_read(pcp) __size_call_return(this_cpu_read_, (pcp))
+#endif
+
+#define _this_cpu_generic_to_op(pcp, val, op) \
+do { \
+ preempt_disable(); \
+ *__this_cpu_ptr(&pcp) op val; \
+ preempt_enable(); \
+} while (0)
+
+#ifndef this_cpu_write
+# ifndef this_cpu_write_1
+# define this_cpu_write_1(pcp, val) _this_cpu_generic_to_op((pcp), (val), =)
+# endif
+# ifndef this_cpu_write_2
+# define this_cpu_write_2(pcp, val) _this_cpu_generic_to_op((pcp), (val), =)
+# endif
+# ifndef this_cpu_write_4
+# define this_cpu_write_4(pcp, val) _this_cpu_generic_to_op((pcp), (val), =)
+# endif
+# ifndef this_cpu_write_8
+# define this_cpu_write_8(pcp, val) _this_cpu_generic_to_op((pcp), (val), =)
+# endif
+# define this_cpu_write(pcp, val) __size_call(this_cpu_write_, (pcp), (val))
+#endif
+
+#ifndef this_cpu_add
+# ifndef this_cpu_add_1
+# define this_cpu_add_1(pcp, val) _this_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# ifndef this_cpu_add_2
+# define this_cpu_add_2(pcp, val) _this_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# ifndef this_cpu_add_4
+# define this_cpu_add_4(pcp, val) _this_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# ifndef this_cpu_add_8
+# define this_cpu_add_8(pcp, val) _this_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# define this_cpu_add(pcp, val) __size_call(this_cpu_add_, (pcp), (val))
+#endif
+
+#ifndef this_cpu_sub
+# define this_cpu_sub(pcp, val) this_cpu_add((pcp), -(val))
+#endif
+
+#ifndef this_cpu_inc
+# define this_cpu_inc(pcp) this_cpu_add((pcp), 1)
+#endif
+
+#ifndef this_cpu_dec
+# define this_cpu_dec(pcp) this_cpu_sub((pcp), 1)
+#endif
+
+#ifndef this_cpu_and
+# ifndef this_cpu_and_1
+# define this_cpu_and_1(pcp, val) _this_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# ifndef this_cpu_and_2
+# define this_cpu_and_2(pcp, val) _this_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# ifndef this_cpu_and_4
+# define this_cpu_and_4(pcp, val) _this_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# ifndef this_cpu_and_8
+# define this_cpu_and_8(pcp, val) _this_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# define this_cpu_and(pcp, val) __size_call(this_cpu_and_, (pcp), (val))
+#endif
+
+#ifndef this_cpu_or
+# ifndef this_cpu_or_1
+# define this_cpu_or_1(pcp, val) _this_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# ifndef this_cpu_or_2
+# define this_cpu_or_2(pcp, val) _this_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# ifndef this_cpu_or_4
+# define this_cpu_or_4(pcp, val) _this_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# ifndef this_cpu_or_8
+# define this_cpu_or_8(pcp, val) _this_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# define this_cpu_or(pcp, val) __size_call(this_cpu_or_, (pcp), (val))
+#endif
+
+#ifndef this_cpu_xor
+# ifndef this_cpu_xor_1
+# define this_cpu_xor_1(pcp, val) _this_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# ifndef this_cpu_xor_2
+# define this_cpu_xor_2(pcp, val) _this_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# ifndef this_cpu_xor_4
+# define this_cpu_xor_4(pcp, val) _this_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# ifndef this_cpu_xor_8
+# define this_cpu_xor_8(pcp, val) _this_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# define this_cpu_xor(pcp, val) __size_call(this_cpu_or_, (pcp), (val))
+#endif
+
+/*
+ * Generic percpu operations that do not require preemption handling.
+ * Either we do not care about races or the caller has the
+ * responsibility of handling preemptions issues. Arch code can still
+ * override these instructions since the arch per cpu code may be more
+ * efficient and may actually get race freeness for free (that is the
+ * case for x86 for example).
+ *
+ * If there is no other protection through preempt disable and/or
+ * disabling interupts then one of these RMW operations can show unexpected
+ * behavior because the execution thread was rescheduled on another processor
+ * or an interrupt occurred and the same percpu variable was modified from
+ * the interrupt context.
+ */
+#ifndef __this_cpu_read
+# ifndef __this_cpu_read_1
+# define __this_cpu_read_1(pcp) (*__this_cpu_ptr(&(pcp)))
+# endif
+# ifndef __this_cpu_read_2
+# define __this_cpu_read_2(pcp) (*__this_cpu_ptr(&(pcp)))
+# endif
+# ifndef __this_cpu_read_4
+# define __this_cpu_read_4(pcp) (*__this_cpu_ptr(&(pcp)))
+# endif
+# ifndef __this_cpu_read_8
+# define __this_cpu_read_8(pcp) (*__this_cpu_ptr(&(pcp)))
+# endif
+# define __this_cpu_read(pcp) __size_call_return(__this_cpu_read_, (pcp))
+#endif
+
+#define __this_cpu_generic_to_op(pcp, val, op) \
+do { \
+ *__this_cpu_ptr(&(pcp)) op val; \
+} while (0)
+
+#ifndef __this_cpu_write
+# ifndef __this_cpu_write_1
+# define __this_cpu_write_1(pcp, val) __this_cpu_generic_to_op((pcp), (val), =)
+# endif
+# ifndef __this_cpu_write_2
+# define __this_cpu_write_2(pcp, val) __this_cpu_generic_to_op((pcp), (val), =)
+# endif
+# ifndef __this_cpu_write_4
+# define __this_cpu_write_4(pcp, val) __this_cpu_generic_to_op((pcp), (val), =)
+# endif
+# ifndef __this_cpu_write_8
+# define __this_cpu_write_8(pcp, val) __this_cpu_generic_to_op((pcp), (val), =)
+# endif
+# define __this_cpu_write(pcp, val) __size_call(__this_cpu_write_, (pcp), (val))
+#endif
+
+#ifndef __this_cpu_add
+# ifndef __this_cpu_add_1
+# define __this_cpu_add_1(pcp, val) __this_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# ifndef __this_cpu_add_2
+# define __this_cpu_add_2(pcp, val) __this_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# ifndef __this_cpu_add_4
+# define __this_cpu_add_4(pcp, val) __this_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# ifndef __this_cpu_add_8
+# define __this_cpu_add_8(pcp, val) __this_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# define __this_cpu_add(pcp, val) __size_call(__this_cpu_add_, (pcp), (val))
+#endif
+
+#ifndef __this_cpu_sub
+# define __this_cpu_sub(pcp, val) __this_cpu_add((pcp), -(val))
+#endif
+
+#ifndef __this_cpu_inc
+# define __this_cpu_inc(pcp) __this_cpu_add((pcp), 1)
+#endif
+
+#ifndef __this_cpu_dec
+# define __this_cpu_dec(pcp) __this_cpu_sub((pcp), 1)
+#endif
+
+#ifndef __this_cpu_and
+# ifndef __this_cpu_and_1
+# define __this_cpu_and_1(pcp, val) __this_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# ifndef __this_cpu_and_2
+# define __this_cpu_and_2(pcp, val) __this_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# ifndef __this_cpu_and_4
+# define __this_cpu_and_4(pcp, val) __this_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# ifndef __this_cpu_and_8
+# define __this_cpu_and_8(pcp, val) __this_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# define __this_cpu_and(pcp, val) __size_call(__this_cpu_and_, (pcp), (val))
+#endif
+
+#ifndef __this_cpu_or
+# ifndef __this_cpu_or_1
+# define __this_cpu_or_1(pcp, val) __this_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# ifndef __this_cpu_or_2
+# define __this_cpu_or_2(pcp, val) __this_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# ifndef __this_cpu_or_4
+# define __this_cpu_or_4(pcp, val) __this_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# ifndef __this_cpu_or_8
+# define __this_cpu_or_8(pcp, val) __this_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# define __this_cpu_or(pcp, val) __size_call(__this_cpu_or_, (pcp), (val))
+#endif
+
+#ifndef __this_cpu_xor
+# ifndef __this_cpu_xor_1
+# define __this_cpu_xor_1(pcp, val) __this_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# ifndef __this_cpu_xor_2
+# define __this_cpu_xor_2(pcp, val) __this_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# ifndef __this_cpu_xor_4
+# define __this_cpu_xor_4(pcp, val) __this_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# ifndef __this_cpu_xor_8
+# define __this_cpu_xor_8(pcp, val) __this_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# define __this_cpu_xor(pcp, val) __size_call(__this_cpu_xor_, (pcp), (val))
+#endif
+
+/*
+ * IRQ safe versions of the per cpu RMW operations. Note that these operations
+ * are *not* safe against modification of the same variable from another
+ * processors (which one gets when using regular atomic operations)
+ . They are guaranteed to be atomic vs. local interrupts and
+ * preemption only.
+ */
+#define irqsafe_cpu_generic_to_op(pcp, val, op) \
+do { \
+ unsigned long flags; \
+ local_irq_save(flags); \
+ *__this_cpu_ptr(&(pcp)) op val; \
+ local_irq_restore(flags); \
+} while (0)
+
+#ifndef irqsafe_cpu_add
+# ifndef irqsafe_cpu_add_1
+# define irqsafe_cpu_add_1(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# ifndef irqsafe_cpu_add_2
+# define irqsafe_cpu_add_2(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# ifndef irqsafe_cpu_add_4
+# define irqsafe_cpu_add_4(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# ifndef irqsafe_cpu_add_8
+# define irqsafe_cpu_add_8(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), +=)
+# endif
+# define irqsafe_cpu_add(pcp, val) __size_call(irqsafe_cpu_add_, (pcp), (val))
+#endif
+
+#ifndef irqsafe_cpu_sub
+# define irqsafe_cpu_sub(pcp, val) irqsafe_cpu_add((pcp), -(val))
+#endif
+
+#ifndef irqsafe_cpu_inc
+# define irqsafe_cpu_inc(pcp) irqsafe_cpu_add((pcp), 1)
+#endif
+
+#ifndef irqsafe_cpu_dec
+# define irqsafe_cpu_dec(pcp) irqsafe_cpu_sub((pcp), 1)
+#endif
+
+#ifndef irqsafe_cpu_and
+# ifndef irqsafe_cpu_and_1
+# define irqsafe_cpu_and_1(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# ifndef irqsafe_cpu_and_2
+# define irqsafe_cpu_and_2(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# ifndef irqsafe_cpu_and_4
+# define irqsafe_cpu_and_4(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# ifndef irqsafe_cpu_and_8
+# define irqsafe_cpu_and_8(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), &=)
+# endif
+# define irqsafe_cpu_and(pcp, val) __size_call(irqsafe_cpu_and_, (val))
+#endif
+
+#ifndef irqsafe_cpu_or
+# ifndef irqsafe_cpu_or_1
+# define irqsafe_cpu_or_1(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# ifndef irqsafe_cpu_or_2
+# define irqsafe_cpu_or_2(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# ifndef irqsafe_cpu_or_4
+# define irqsafe_cpu_or_4(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# ifndef irqsafe_cpu_or_8
+# define irqsafe_cpu_or_8(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), |=)
+# endif
+# define irqsafe_cpu_or(pcp, val) __size_call(irqsafe_cpu_or_, (val))
+#endif
+
+#ifndef irqsafe_cpu_xor
+# ifndef irqsafe_cpu_xor_1
+# define irqsafe_cpu_xor_1(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# ifndef irqsafe_cpu_xor_2
+# define irqsafe_cpu_xor_2(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# ifndef irqsafe_cpu_xor_4
+# define irqsafe_cpu_xor_4(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# ifndef irqsafe_cpu_xor_8
+# define irqsafe_cpu_xor_8(pcp, val) irqsafe_cpu_generic_to_op((pcp), (val), ^=)
+# endif
+# define irqsafe_cpu_xor(pcp, val) __size_call(irqsafe_cpu_xor_, (val))
+#endif
+
#endif /* __LINUX_PERCPU_H */
int __must_check res_counter_charge_locked(struct res_counter *counter,
unsigned long val);
int __must_check res_counter_charge(struct res_counter *counter,
- unsigned long val, struct res_counter **limit_fail_at,
- struct res_counter **soft_limit_at);
+ unsigned long val, struct res_counter **limit_fail_at);
/*
* uncharge - tell that some portion of the resource is released
*/
void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val);
-void res_counter_uncharge(struct res_counter *counter, unsigned long val,
- bool *was_soft_limit_excess);
+void res_counter_uncharge(struct res_counter *counter, unsigned long val);
static inline bool res_counter_limit_check_locked(struct res_counter *cnt)
{
/* Qualcomm MSM SoCs */
#define PORT_MSM 88
+/* BCM63xx family SoCs */
+#define PORT_BCM63XX 89
+
#ifdef __KERNEL__
#include <linux/compiler.h>
static inline void __count_vm_event(enum vm_event_item item)
{
- __get_cpu_var(vm_event_states).event[item]++;
+ __this_cpu_inc(per_cpu_var(vm_event_states).event[item]);
}
static inline void count_vm_event(enum vm_event_item item)
{
- get_cpu_var(vm_event_states).event[item]++;
- put_cpu();
+ this_cpu_inc(per_cpu_var(vm_event_states).event[item]);
}
static inline void __count_vm_events(enum vm_event_item item, long delta)
{
- __get_cpu_var(vm_event_states).event[item] += delta;
+ __this_cpu_add(per_cpu_var(vm_event_states).event[item], delta);
}
static inline void count_vm_events(enum vm_event_item item, long delta)
{
- get_cpu_var(vm_event_states).event[item] += delta;
- put_cpu();
+ this_cpu_add(per_cpu_var(vm_event_states).event[item], delta);
}
extern void all_vm_events(unsigned long *);
extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsigned char *, int);
-extern int compat_mc_setsockopt(struct sock *, int, int, char __user *, int,
- int (*)(struct sock *, int, int, char __user *, int));
+extern int compat_mc_setsockopt(struct sock *, int, int, char __user *, unsigned int,
+ int (*)(struct sock *, int, int, char __user *, unsigned int));
extern int compat_mc_getsockopt(struct sock *, int, int, char __user *,
int __user *, int (*)(struct sock *, int, int, char __user *,
int __user *));
u16 net_header_len;
u16 sockaddr_len;
int (*setsockopt)(struct sock *sk, int level, int optname,
- char __user *optval, int optlen);
+ char __user *optval, unsigned int optlen);
int (*getsockopt)(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
#ifdef CONFIG_COMPAT
int (*compat_setsockopt)(struct sock *sk,
int level, int optname,
- char __user *optval, int optlen);
+ char __user *optval, unsigned int optlen);
int (*compat_getsockopt)(struct sock *sk,
int level, int optname,
char __user *optval, int __user *optlen);
extern int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
extern int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen);
+ char __user *optval, unsigned int optlen);
#endif /* _INET_CONNECTION_SOCK_H */
extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
extern int ip_cmsg_send(struct net *net,
struct msghdr *msg, struct ipcm_cookie *ipc);
-extern int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen);
+extern int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen);
extern int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen);
extern int compat_ip_setsockopt(struct sock *sk, int level,
- int optname, char __user *optval, int optlen);
+ int optname, char __user *optval, unsigned int optlen);
extern int compat_ip_getsockopt(struct sock *sk, int level,
int optname, char __user *optval, int __user *optlen);
extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *));
unsigned int prl_count; /* # of entries in PRL */
};
-/* ISATAP: default interval between RS in secondy */
-#define IPTUNNEL_RS_DEFAULT_DELAY (900)
-
struct ip_tunnel_prl_entry
{
struct ip_tunnel_prl_entry *next;
__be32 addr;
u16 flags;
- unsigned long rs_delay;
- struct timer_list rs_timer;
- struct ip_tunnel *tunnel;
- spinlock_t lock;
};
#define IPTUNNEL_XMIT() do { \
extern int ipv6_setsockopt(struct sock *sk, int level,
int optname,
char __user *optval,
- int optlen);
+ unsigned int optlen);
extern int ipv6_getsockopt(struct sock *sk, int level,
int optname,
char __user *optval,
int level,
int optname,
char __user *optval,
- int optlen);
+ unsigned int optlen);
extern int compat_ipv6_getsockopt(struct sock *sk,
int level,
int optname,
unsigned long unres_discards; /* number of unresolved drops */
};
-#define NEIGH_CACHE_STAT_INC(tbl, field) \
- do { \
- preempt_disable(); \
- (per_cpu_ptr((tbl)->stats, smp_processor_id())->field)++; \
- preempt_enable(); \
- } while (0)
+#define NEIGH_CACHE_STAT_INC(tbl, field) this_cpu_inc((tbl)->stats->field)
struct neighbour
{
extern unsigned int nf_conntrack_max;
#define NF_CT_STAT_INC(net, count) \
- (per_cpu_ptr((net)->ct.stat, raw_smp_processor_id())->count++)
+ __this_cpu_inc((net)->ct.stat->count)
#define NF_CT_STAT_INC_ATOMIC(net, count) \
do { \
local_bh_disable(); \
- per_cpu_ptr((net)->ct.stat, raw_smp_processor_id())->count++; \
+ __this_cpu_inc((net)->ct.stat->count); \
local_bh_enable(); \
} while (0)
int level,
int optname,
char __user *optval,
- int optlen);
+ unsigned int optlen);
int (*getsockopt) (struct sock *sk,
int level,
int optname,
int level,
int optname,
char __user *optval,
- int optlen);
+ unsigned int optlen);
int (*compat_getsockopt) (struct sock *sk,
int level,
int optname,
#define SNMP_STAT_BHPTR(name) (name[0])
#define SNMP_STAT_USRPTR(name) (name[1])
-#define SNMP_INC_STATS_BH(mib, field) \
- (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field]++)
-#define SNMP_INC_STATS_USER(mib, field) \
- do { \
- per_cpu_ptr(mib[1], get_cpu())->mibs[field]++; \
- put_cpu(); \
- } while (0)
-#define SNMP_INC_STATS(mib, field) \
- do { \
- per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]++; \
- put_cpu(); \
- } while (0)
-#define SNMP_DEC_STATS(mib, field) \
- do { \
- per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]--; \
- put_cpu(); \
- } while (0)
-#define SNMP_ADD_STATS(mib, field, addend) \
- do { \
- per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field] += addend; \
- put_cpu(); \
- } while (0)
-#define SNMP_ADD_STATS_BH(mib, field, addend) \
- (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend)
-#define SNMP_ADD_STATS_USER(mib, field, addend) \
- do { \
- per_cpu_ptr(mib[1], get_cpu())->mibs[field] += addend; \
- put_cpu(); \
- } while (0)
+#define SNMP_INC_STATS_BH(mib, field) \
+ __this_cpu_inc(mib[0]->mibs[field])
+#define SNMP_INC_STATS_USER(mib, field) \
+ this_cpu_inc(mib[1]->mibs[field])
+#define SNMP_INC_STATS(mib, field) \
+ this_cpu_inc(mib[!in_softirq()]->mibs[field])
+#define SNMP_DEC_STATS(mib, field) \
+ this_cpu_dec(mib[!in_softirq()]->mibs[field])
+#define SNMP_ADD_STATS_BH(mib, field, addend) \
+ __this_cpu_add(mib[0]->mibs[field], addend)
+#define SNMP_ADD_STATS_USER(mib, field, addend) \
+ this_cpu_add(mib[1]->mibs[field], addend)
#define SNMP_UPD_PO_STATS(mib, basefield, addend) \
do { \
- __typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], get_cpu());\
+ __typeof__(mib[0]) ptr; \
+ preempt_disable(); \
+ ptr = this_cpu_ptr((mib)[!in_softirq()]); \
ptr->mibs[basefield##PKTS]++; \
ptr->mibs[basefield##OCTETS] += addend;\
- put_cpu(); \
+ preempt_enable(); \
} while (0)
#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend) \
do { \
- __typeof__(mib[0]) ptr = per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id());\
+ __typeof__(mib[0]) ptr = \
+ __this_cpu_ptr((mib)[!in_softirq()]); \
ptr->mibs[basefield##PKTS]++; \
ptr->mibs[basefield##OCTETS] += addend;\
} while (0)
void (*shutdown)(struct sock *sk, int how);
int (*setsockopt)(struct sock *sk, int level,
int optname, char __user *optval,
- int optlen);
+ unsigned int optlen);
int (*getsockopt)(struct sock *sk, int level,
int optname, char __user *optval,
int __user *option);
int (*compat_setsockopt)(struct sock *sk,
int level,
int optname, char __user *optval,
- int optlen);
+ unsigned int optlen);
int (*compat_getsockopt)(struct sock *sk,
int level,
int optname, char __user *optval,
extern int sock_setsockopt(struct socket *sock, int level,
int op, char __user *optval,
- int optlen);
+ unsigned int optlen);
extern int sock_getsockopt(struct socket *sock, int level,
int op, char __user *optval,
extern int sock_no_getsockopt(struct socket *, int , int,
char __user *, int __user *);
extern int sock_no_setsockopt(struct socket *, int, int,
- char __user *, int);
+ char __user *, unsigned int);
extern int sock_no_sendmsg(struct kiocb *, struct socket *,
struct msghdr *, size_t);
extern int sock_no_recvmsg(struct kiocb *, struct socket *,
extern int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, int flags);
extern int sock_common_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen);
+ char __user *optval, unsigned int optlen);
extern int compat_sock_common_getsockopt(struct socket *sock, int level,
int optname, char __user *optval, int __user *optlen);
extern int compat_sock_common_setsockopt(struct socket *sock, int level,
- int optname, char __user *optval, int optlen);
+ int optname, char __user *optval, unsigned int optlen);
extern void sk_common_release(struct sock *sk);
int __user *optlen);
extern int tcp_setsockopt(struct sock *sk, int level,
int optname, char __user *optval,
- int optlen);
+ unsigned int optlen);
extern int compat_tcp_getsockopt(struct sock *sk,
int level, int optname,
char __user *optval, int __user *optlen);
extern int compat_tcp_setsockopt(struct sock *sk,
int level, int optname,
- char __user *optval, int optlen);
+ char __user *optval, unsigned int optlen);
extern void tcp_set_keepalive(struct sock *sk, int val);
extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk,
struct msghdr *msg,
extern int udp_lib_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
extern int udp_lib_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen,
+ char __user *optval, unsigned int optlen,
int (*push_pending_frames)(struct sock *));
extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
void __user *arg);
extern int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
unsigned long arg);
+extern struct iw_statistics *get_wireless_stats(struct net_device *dev);
#else
static inline int wext_proc_init(struct net *net)
{
extern struct pccard_resource_ops pccard_nonstatic_ops;
/* socket drivers are expected to use these callbacks in their .drv struct */
-extern int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state);
+extern int pcmcia_socket_dev_suspend(struct device *dev);
extern int pcmcia_socket_dev_resume(struct device *dev);
/* socket drivers use this callback in their IRQ handler */
struct ext4_allocation_request;
struct ext4_prealloc_space;
struct ext4_inode_info;
+struct mpage_da_data;
#define EXT4_I(inode) (container_of(inode, struct ext4_inode_info, vfs_inode))
__field( char, for_kupdate )
__field( char, for_reclaim )
__field( char, range_cyclic )
+ __field( pgoff_t, writeback_index )
),
TP_fast_assign(
__entry->for_kupdate = wbc->for_kupdate;
__entry->for_reclaim = wbc->for_reclaim;
__entry->range_cyclic = wbc->range_cyclic;
+ __entry->writeback_index = inode->i_mapping->writeback_index;
),
- TP_printk("dev %s ino %lu nr_to_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d range_cyclic %d",
+ TP_printk("dev %s ino %lu nr_to_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d range_cyclic %d writeback_index %lu",
jbd2_dev_to_name(__entry->dev),
(unsigned long) __entry->ino, __entry->nr_to_write,
__entry->pages_skipped, __entry->range_start,
__entry->range_end, __entry->nonblocking,
__entry->for_kupdate, __entry->for_reclaim,
- __entry->range_cyclic)
+ __entry->range_cyclic,
+ (unsigned long) __entry->writeback_index)
);
TRACE_EVENT(ext4_da_write_pages,
__field( char, encountered_congestion )
__field( char, more_io )
__field( char, no_nrwrite_index_update )
+ __field( pgoff_t, writeback_index )
),
TP_fast_assign(
__entry->encountered_congestion = wbc->encountered_congestion;
__entry->more_io = wbc->more_io;
__entry->no_nrwrite_index_update = wbc->no_nrwrite_index_update;
+ __entry->writeback_index = inode->i_mapping->writeback_index;
),
- TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld congestion %d more_io %d no_nrwrite_index_update %d",
+ TP_printk("dev %s ino %lu ret %d pages_written %d pages_skipped %ld congestion %d more_io %d no_nrwrite_index_update %d writeback_index %lu",
jbd2_dev_to_name(__entry->dev),
(unsigned long) __entry->ino, __entry->ret,
__entry->pages_written, __entry->pages_skipped,
__entry->encountered_congestion, __entry->more_io,
- __entry->no_nrwrite_index_update)
+ __entry->no_nrwrite_index_update,
+ (unsigned long) __entry->writeback_index)
);
TRACE_EVENT(ext4_da_write_begin,
__entry->data_blocks, __entry->meta_blocks)
);
+TRACE_EVENT(ext4_mballoc_alloc,
+ TP_PROTO(struct ext4_allocation_context *ac),
+
+ TP_ARGS(ac),
+
+ TP_STRUCT__entry(
+ __field( dev_t, dev )
+ __field( ino_t, ino )
+ __field( __u16, found )
+ __field( __u16, groups )
+ __field( __u16, buddy )
+ __field( __u16, flags )
+ __field( __u16, tail )
+ __field( __u8, cr )
+ __field( __u32, orig_logical )
+ __field( int, orig_start )
+ __field( __u32, orig_group )
+ __field( int, orig_len )
+ __field( __u32, goal_logical )
+ __field( int, goal_start )
+ __field( __u32, goal_group )
+ __field( int, goal_len )
+ __field( __u32, result_logical )
+ __field( int, result_start )
+ __field( __u32, result_group )
+ __field( int, result_len )
+ ),
+
+ TP_fast_assign(
+ __entry->dev = ac->ac_inode->i_sb->s_dev;
+ __entry->ino = ac->ac_inode->i_ino;
+ __entry->found = ac->ac_found;
+ __entry->flags = ac->ac_flags;
+ __entry->groups = ac->ac_groups_scanned;
+ __entry->buddy = ac->ac_buddy;
+ __entry->tail = ac->ac_tail;
+ __entry->cr = ac->ac_criteria;
+ __entry->orig_logical = ac->ac_o_ex.fe_logical;
+ __entry->orig_start = ac->ac_o_ex.fe_start;
+ __entry->orig_group = ac->ac_o_ex.fe_group;
+ __entry->orig_len = ac->ac_o_ex.fe_len;
+ __entry->goal_logical = ac->ac_g_ex.fe_logical;
+ __entry->goal_start = ac->ac_g_ex.fe_start;
+ __entry->goal_group = ac->ac_g_ex.fe_group;
+ __entry->goal_len = ac->ac_g_ex.fe_len;
+ __entry->result_logical = ac->ac_f_ex.fe_logical;
+ __entry->result_start = ac->ac_f_ex.fe_start;
+ __entry->result_group = ac->ac_f_ex.fe_group;
+ __entry->result_len = ac->ac_f_ex.fe_len;
+ ),
+
+ TP_printk("dev %s inode %lu orig %u/%d/%u@%u goal %u/%d/%u@%u "
+ "result %u/%d/%u@%u blks %u grps %u cr %u flags 0x%04x "
+ "tail %u broken %u",
+ jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+ __entry->orig_group, __entry->orig_start,
+ __entry->orig_len, __entry->orig_logical,
+ __entry->goal_group, __entry->goal_start,
+ __entry->goal_len, __entry->goal_logical,
+ __entry->result_group, __entry->result_start,
+ __entry->result_len, __entry->result_logical,
+ __entry->found, __entry->groups, __entry->cr,
+ __entry->flags, __entry->tail,
+ __entry->buddy ? 1 << __entry->buddy : 0)
+);
+
+TRACE_EVENT(ext4_mballoc_prealloc,
+ TP_PROTO(struct ext4_allocation_context *ac),
+
+ TP_ARGS(ac),
+
+ TP_STRUCT__entry(
+ __field( dev_t, dev )
+ __field( ino_t, ino )
+ __field( __u32, orig_logical )
+ __field( int, orig_start )
+ __field( __u32, orig_group )
+ __field( int, orig_len )
+ __field( __u32, result_logical )
+ __field( int, result_start )
+ __field( __u32, result_group )
+ __field( int, result_len )
+ ),
+
+ TP_fast_assign(
+ __entry->dev = ac->ac_inode->i_sb->s_dev;
+ __entry->ino = ac->ac_inode->i_ino;
+ __entry->orig_logical = ac->ac_o_ex.fe_logical;
+ __entry->orig_start = ac->ac_o_ex.fe_start;
+ __entry->orig_group = ac->ac_o_ex.fe_group;
+ __entry->orig_len = ac->ac_o_ex.fe_len;
+ __entry->result_logical = ac->ac_b_ex.fe_logical;
+ __entry->result_start = ac->ac_b_ex.fe_start;
+ __entry->result_group = ac->ac_b_ex.fe_group;
+ __entry->result_len = ac->ac_b_ex.fe_len;
+ ),
+
+ TP_printk("dev %s inode %lu orig %u/%d/%u@%u result %u/%d/%u@%u",
+ jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+ __entry->orig_group, __entry->orig_start,
+ __entry->orig_len, __entry->orig_logical,
+ __entry->result_group, __entry->result_start,
+ __entry->result_len, __entry->result_logical)
+);
+
+TRACE_EVENT(ext4_mballoc_discard,
+ TP_PROTO(struct ext4_allocation_context *ac),
+
+ TP_ARGS(ac),
+
+ TP_STRUCT__entry(
+ __field( dev_t, dev )
+ __field( ino_t, ino )
+ __field( __u32, result_logical )
+ __field( int, result_start )
+ __field( __u32, result_group )
+ __field( int, result_len )
+ ),
+
+ TP_fast_assign(
+ __entry->dev = ac->ac_inode->i_sb->s_dev;
+ __entry->ino = ac->ac_inode->i_ino;
+ __entry->result_logical = ac->ac_b_ex.fe_logical;
+ __entry->result_start = ac->ac_b_ex.fe_start;
+ __entry->result_group = ac->ac_b_ex.fe_group;
+ __entry->result_len = ac->ac_b_ex.fe_len;
+ ),
+
+ TP_printk("dev %s inode %lu extent %u/%d/%u@%u ",
+ jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+ __entry->result_group, __entry->result_start,
+ __entry->result_len, __entry->result_logical)
+);
+
+TRACE_EVENT(ext4_mballoc_free,
+ TP_PROTO(struct ext4_allocation_context *ac),
+
+ TP_ARGS(ac),
+
+ TP_STRUCT__entry(
+ __field( dev_t, dev )
+ __field( ino_t, ino )
+ __field( __u32, result_logical )
+ __field( int, result_start )
+ __field( __u32, result_group )
+ __field( int, result_len )
+ ),
+
+ TP_fast_assign(
+ __entry->dev = ac->ac_inode->i_sb->s_dev;
+ __entry->ino = ac->ac_inode->i_ino;
+ __entry->result_logical = ac->ac_b_ex.fe_logical;
+ __entry->result_start = ac->ac_b_ex.fe_start;
+ __entry->result_group = ac->ac_b_ex.fe_group;
+ __entry->result_len = ac->ac_b_ex.fe_len;
+ ),
+
+ TP_printk("dev %s inode %lu extent %u/%d/%u@%u ",
+ jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino,
+ __entry->result_group, __entry->result_start,
+ __entry->result_len, __entry->result_logical)
+);
+
#endif /* _TRACE_EXT4_H */
/* This part must be outside protection */
#include <linux/jbd2.h>
#include <linux/tracepoint.h>
+struct transaction_chp_stats_s;
+struct transaction_run_stats_s;
+
TRACE_EVENT(jbd2_checkpoint,
TP_PROTO(journal_t *journal, int result),
jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino)
);
+TRACE_EVENT(jbd2_run_stats,
+ TP_PROTO(dev_t dev, unsigned long tid,
+ struct transaction_run_stats_s *stats),
+
+ TP_ARGS(dev, tid, stats),
+
+ TP_STRUCT__entry(
+ __field( dev_t, dev )
+ __field( unsigned long, tid )
+ __field( unsigned long, wait )
+ __field( unsigned long, running )
+ __field( unsigned long, locked )
+ __field( unsigned long, flushing )
+ __field( unsigned long, logging )
+ __field( __u32, handle_count )
+ __field( __u32, blocks )
+ __field( __u32, blocks_logged )
+ ),
+
+ TP_fast_assign(
+ __entry->dev = dev;
+ __entry->tid = tid;
+ __entry->wait = stats->rs_wait;
+ __entry->running = stats->rs_running;
+ __entry->locked = stats->rs_locked;
+ __entry->flushing = stats->rs_flushing;
+ __entry->logging = stats->rs_logging;
+ __entry->handle_count = stats->rs_handle_count;
+ __entry->blocks = stats->rs_blocks;
+ __entry->blocks_logged = stats->rs_blocks_logged;
+ ),
+
+ TP_printk("dev %s tid %lu wait %u running %u locked %u flushing %u "
+ "logging %u handle_count %u blocks %u blocks_logged %u",
+ jbd2_dev_to_name(__entry->dev), __entry->tid,
+ jiffies_to_msecs(__entry->wait),
+ jiffies_to_msecs(__entry->running),
+ jiffies_to_msecs(__entry->locked),
+ jiffies_to_msecs(__entry->flushing),
+ jiffies_to_msecs(__entry->logging),
+ __entry->handle_count, __entry->blocks,
+ __entry->blocks_logged)
+);
+
+TRACE_EVENT(jbd2_checkpoint_stats,
+ TP_PROTO(dev_t dev, unsigned long tid,
+ struct transaction_chp_stats_s *stats),
+
+ TP_ARGS(dev, tid, stats),
+
+ TP_STRUCT__entry(
+ __field( dev_t, dev )
+ __field( unsigned long, tid )
+ __field( unsigned long, chp_time )
+ __field( __u32, forced_to_close )
+ __field( __u32, written )
+ __field( __u32, dropped )
+ ),
+
+ TP_fast_assign(
+ __entry->dev = dev;
+ __entry->tid = tid;
+ __entry->chp_time = stats->cs_chp_time;
+ __entry->forced_to_close= stats->cs_forced_to_close;
+ __entry->written = stats->cs_written;
+ __entry->dropped = stats->cs_dropped;
+ ),
+
+ TP_printk("dev %s tid %lu chp_time %u forced_to_close %u "
+ "written %u dropped %u",
+ jbd2_dev_to_name(__entry->dev), __entry->tid,
+ jiffies_to_msecs(__entry->chp_time),
+ __entry->forced_to_close, __entry->written, __entry->dropped)
+);
+
#endif /* _TRACE_JBD2_H */
/* This part must be outside protection */
static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry);
static int cgroup_populate_dir(struct cgroup *cgrp);
static const struct inode_operations cgroup_dir_inode_operations;
-static struct file_operations proc_cgroupstats_operations;
+static const struct file_operations proc_cgroupstats_operations;
static struct backing_dev_info cgroup_backing_dev_info = {
.name = "cgroup",
return single_release(inode, file);
}
-static struct file_operations cgroup_seqfile_operations = {
+static const struct file_operations cgroup_seqfile_operations = {
.read = seq_read,
.write = cgroup_file_write,
.llseek = seq_lseek,
return simple_rename(old_dir, old_dentry, new_dir, new_dentry);
}
-static struct file_operations cgroup_file_operations = {
+static const struct file_operations cgroup_file_operations = {
.read = cgroup_file_read,
.write = cgroup_file_write,
.llseek = generic_file_llseek,
return single_open(file, proc_cgroup_show, pid);
}
-struct file_operations proc_cgroup_operations = {
+const struct file_operations proc_cgroup_operations = {
.open = cgroup_open,
.read = seq_read,
.llseek = seq_lseek,
return single_open(file, proc_cgroupstats_show, NULL);
}
-static struct file_operations proc_cgroupstats_operations = {
+static const struct file_operations proc_cgroupstats_operations = {
.open = cgroupstats_open,
.read = seq_read,
.llseek = seq_lseek,
void __css_put(struct cgroup_subsys_state *css)
{
struct cgroup *cgrp = css->cgroup;
+ int val;
rcu_read_lock();
- if (atomic_dec_return(&css->refcnt) == 1) {
+ val = atomic_dec_return(&css->refcnt);
+ if (val == 1) {
if (notify_on_release(cgrp)) {
set_bit(CGRP_RELEASABLE, &cgrp->flags);
check_for_release(cgrp);
cgroup_wakeup_rmdir_waiter(cgrp);
}
rcu_read_unlock();
+ WARN_ON_ONCE(val < 1);
}
/*
return seq_open(filp, &kprobes_seq_ops);
}
-static struct file_operations debugfs_kprobes_operations = {
+static const struct file_operations debugfs_kprobes_operations = {
.open = kprobes_open,
.read = seq_read,
.llseek = seq_lseek,
return count;
}
-static struct file_operations fops_kp = {
+static const struct file_operations fops_kp = {
.read = read_enabled_file_bool,
.write = write_enabled_file_bool,
};
#ifdef CONFIG_SMP
-#ifndef CONFIG_HAVE_LEGACY_PER_CPU_AREA
-
static void *percpu_modalloc(unsigned long size, unsigned long align,
const char *name)
{
free_percpu(freeme);
}
-#else /* ... CONFIG_HAVE_LEGACY_PER_CPU_AREA */
-
-/* Number of blocks used and allocated. */
-static unsigned int pcpu_num_used, pcpu_num_allocated;
-/* Size of each block. -ve means used. */
-static int *pcpu_size;
-
-static int split_block(unsigned int i, unsigned short size)
-{
- /* Reallocation required? */
- if (pcpu_num_used + 1 > pcpu_num_allocated) {
- int *new;
-
- new = krealloc(pcpu_size, sizeof(new[0])*pcpu_num_allocated*2,
- GFP_KERNEL);
- if (!new)
- return 0;
-
- pcpu_num_allocated *= 2;
- pcpu_size = new;
- }
-
- /* Insert a new subblock */
- memmove(&pcpu_size[i+1], &pcpu_size[i],
- sizeof(pcpu_size[0]) * (pcpu_num_used - i));
- pcpu_num_used++;
-
- pcpu_size[i+1] -= size;
- pcpu_size[i] = size;
- return 1;
-}
-
-static inline unsigned int block_size(int val)
-{
- if (val < 0)
- return -val;
- return val;
-}
-
-static void *percpu_modalloc(unsigned long size, unsigned long align,
- const char *name)
-{
- unsigned long extra;
- unsigned int i;
- void *ptr;
- int cpu;
-
- if (align > PAGE_SIZE) {
- printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n",
- name, align, PAGE_SIZE);
- align = PAGE_SIZE;
- }
-
- ptr = __per_cpu_start;
- for (i = 0; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) {
- /* Extra for alignment requirement. */
- extra = ALIGN((unsigned long)ptr, align) - (unsigned long)ptr;
- BUG_ON(i == 0 && extra != 0);
-
- if (pcpu_size[i] < 0 || pcpu_size[i] < extra + size)
- continue;
-
- /* Transfer extra to previous block. */
- if (pcpu_size[i-1] < 0)
- pcpu_size[i-1] -= extra;
- else
- pcpu_size[i-1] += extra;
- pcpu_size[i] -= extra;
- ptr += extra;
-
- /* Split block if warranted */
- if (pcpu_size[i] - size > sizeof(unsigned long))
- if (!split_block(i, size))
- return NULL;
-
- /* add the per-cpu scanning areas */
- for_each_possible_cpu(cpu)
- kmemleak_alloc(ptr + per_cpu_offset(cpu), size, 0,
- GFP_KERNEL);
-
- /* Mark allocated */
- pcpu_size[i] = -pcpu_size[i];
- return ptr;
- }
-
- printk(KERN_WARNING "Could not allocate %lu bytes percpu data\n",
- size);
- return NULL;
-}
-
-static void percpu_modfree(void *freeme)
-{
- unsigned int i;
- void *ptr = __per_cpu_start + block_size(pcpu_size[0]);
- int cpu;
-
- /* First entry is core kernel percpu data. */
- for (i = 1; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) {
- if (ptr == freeme) {
- pcpu_size[i] = -pcpu_size[i];
- goto free;
- }
- }
- BUG();
-
- free:
- /* remove the per-cpu scanning areas */
- for_each_possible_cpu(cpu)
- kmemleak_free(freeme + per_cpu_offset(cpu));
-
- /* Merge with previous? */
- if (pcpu_size[i-1] >= 0) {
- pcpu_size[i-1] += pcpu_size[i];
- pcpu_num_used--;
- memmove(&pcpu_size[i], &pcpu_size[i+1],
- (pcpu_num_used - i) * sizeof(pcpu_size[0]));
- i--;
- }
- /* Merge with next? */
- if (i+1 < pcpu_num_used && pcpu_size[i+1] >= 0) {
- pcpu_size[i] += pcpu_size[i+1];
- pcpu_num_used--;
- memmove(&pcpu_size[i+1], &pcpu_size[i+2],
- (pcpu_num_used - (i+1)) * sizeof(pcpu_size[0]));
- }
-}
-
-static int percpu_modinit(void)
-{
- pcpu_num_used = 2;
- pcpu_num_allocated = 2;
- pcpu_size = kmalloc(sizeof(pcpu_size[0]) * pcpu_num_allocated,
- GFP_KERNEL);
- /* Static in-kernel percpu data (used). */
- pcpu_size[0] = -(__per_cpu_end-__per_cpu_start);
- /* Free room. */
- pcpu_size[1] = PERCPU_ENOUGH_ROOM + pcpu_size[0];
- if (pcpu_size[1] < 0) {
- printk(KERN_ERR "No per-cpu room for modules.\n");
- pcpu_num_used = 1;
- }
-
- return 0;
-}
-__initcall(percpu_modinit);
-
-#endif /* CONFIG_HAVE_LEGACY_PER_CPU_AREA */
-
static unsigned int find_pcpusec(Elf_Ehdr *hdr,
Elf_Shdr *sechdrs,
const char *secstrings)
Elf_Shdr *sechdrs,
unsigned int symindex,
unsigned int strindex,
- const Elf_Hdr *hdr,
+ const Elf_Ehdr *hdr,
const char *secstrings,
unsigned long *pstroffs,
unsigned long *strmap)
{
+ return 0;
}
+
static inline void add_kallsyms(struct module *mod,
Elf_Shdr *sechdrs,
unsigned int shnum,
struct module *mod;
long err = 0;
void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
-#ifdef CONFIG_KALLSYMS
unsigned long symoffs, stroffs, *strmap;
-#endif
+
mm_segment_t old_fs;
DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
/* Should not happen, but... */
pipe_count = RCU_TORTURE_PIPE_LEN;
}
- ++__get_cpu_var(rcu_torture_count)[pipe_count];
+ __this_cpu_inc(per_cpu_var(rcu_torture_count)[pipe_count]);
completed = cur_ops->completed() - completed;
if (completed > RCU_TORTURE_PIPE_LEN) {
/* Should not happen, but... */
completed = RCU_TORTURE_PIPE_LEN;
}
- ++__get_cpu_var(rcu_torture_batch)[completed];
+ __this_cpu_inc(per_cpu_var(rcu_torture_batch)[completed]);
preempt_enable();
cur_ops->readunlock(idx);
}
/* Should not happen, but... */
pipe_count = RCU_TORTURE_PIPE_LEN;
}
- ++__get_cpu_var(rcu_torture_count)[pipe_count];
+ __this_cpu_inc(per_cpu_var(rcu_torture_count)[pipe_count]);
completed = cur_ops->completed() - completed;
if (completed > RCU_TORTURE_PIPE_LEN) {
/* Should not happen, but... */
completed = RCU_TORTURE_PIPE_LEN;
}
- ++__get_cpu_var(rcu_torture_batch)[completed];
+ __this_cpu_inc(per_cpu_var(rcu_torture_batch)[completed]);
preempt_enable();
cur_ops->readunlock(idx);
schedule();
return single_open(file, show_rcudata, NULL);
}
-static struct file_operations rcudata_fops = {
+static const struct file_operations rcudata_fops = {
.owner = THIS_MODULE,
.open = rcudata_open,
.read = seq_read,
return single_open(file, show_rcudata_csv, NULL);
}
-static struct file_operations rcudata_csv_fops = {
+static const struct file_operations rcudata_csv_fops = {
.owner = THIS_MODULE,
.open = rcudata_csv_open,
.read = seq_read,
return single_open(file, show_rcuhier, NULL);
}
-static struct file_operations rcuhier_fops = {
+static const struct file_operations rcuhier_fops = {
.owner = THIS_MODULE,
.open = rcuhier_open,
.read = seq_read,
return single_open(file, show_rcugp, NULL);
}
-static struct file_operations rcugp_fops = {
+static const struct file_operations rcugp_fops = {
.owner = THIS_MODULE,
.open = rcugp_open,
.read = seq_read,
return single_open(file, show_rcu_pending, NULL);
}
-static struct file_operations rcu_pending_fops = {
+static const struct file_operations rcu_pending_fops = {
.owner = THIS_MODULE,
.open = rcu_pending_open,
.read = seq_read,
}
int res_counter_charge(struct res_counter *counter, unsigned long val,
- struct res_counter **limit_fail_at,
- struct res_counter **soft_limit_fail_at)
+ struct res_counter **limit_fail_at)
{
int ret;
unsigned long flags;
struct res_counter *c, *u;
*limit_fail_at = NULL;
- if (soft_limit_fail_at)
- *soft_limit_fail_at = NULL;
local_irq_save(flags);
for (c = counter; c != NULL; c = c->parent) {
spin_lock(&c->lock);
ret = res_counter_charge_locked(c, val);
- /*
- * With soft limits, we return the highest ancestor
- * that exceeds its soft limit
- */
- if (soft_limit_fail_at &&
- !res_counter_soft_limit_check_locked(c))
- *soft_limit_fail_at = c;
spin_unlock(&c->lock);
if (ret < 0) {
*limit_fail_at = c;
counter->usage -= val;
}
-void res_counter_uncharge(struct res_counter *counter, unsigned long val,
- bool *was_soft_limit_excess)
+void res_counter_uncharge(struct res_counter *counter, unsigned long val)
{
unsigned long flags;
struct res_counter *c;
local_irq_save(flags);
for (c = counter; c != NULL; c = c->parent) {
spin_lock(&c->lock);
- if (was_soft_limit_excess)
- *was_soft_limit_excess =
- !res_counter_soft_limit_check_locked(c);
res_counter_uncharge_locked(c, val);
spin_unlock(&c->lock);
}
return single_open(filp, sched_feat_show, NULL);
}
-static struct file_operations sched_feat_fops = {
+static const struct file_operations sched_feat_fops = {
.open = sched_feat_open,
.write = sched_feat_write,
.read = seq_read,
clock = wrap_max(clock, min_clock);
clock = wrap_min(clock, max_clock);
- if (cmpxchg(&scd->clock, old_clock, clock) != old_clock)
+ if (cmpxchg64(&scd->clock, old_clock, clock) != old_clock)
goto again;
return clock;
val = remote_clock;
}
- if (cmpxchg(ptr, old_val, val) != old_val)
+ if (cmpxchg64(ptr, old_val, val) != old_val)
goto again;
return val;
return single_open(filp, timer_list_show, NULL);
}
-static struct file_operations timer_list_fops = {
+static const struct file_operations timer_list_fops = {
.open = timer_list_open,
.read = seq_read,
.llseek = seq_lseek,
return single_open(filp, tstats_show, NULL);
}
-static struct file_operations tstats_fops = {
+static const struct file_operations tstats_fops = {
.open = tstats_open,
.read = seq_read,
.write = tstats_write,
* advance both strings to next white space
*/
if (*fmt == '*') {
- while (!isspace(*fmt) && *fmt)
+ while (!isspace(*fmt) && *fmt != '%' && *fmt)
fmt++;
while (!isspace(*str) && *str)
str++;
obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
obj-$(CONFIG_FS_XIP) += filemap_xip.o
obj-$(CONFIG_MIGRATION) += migrate.o
-ifndef CONFIG_HAVE_LEGACY_PER_CPU_AREA
obj-$(CONFIG_SMP) += percpu.o
-else
-obj-$(CONFIG_SMP) += allocpercpu.o
-endif
obj-$(CONFIG_QUICKLIST) += quicklist.o
obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o
obj-$(CONFIG_MEMORY_FAILURE) += memory-failure.o
+++ /dev/null
-/*
- * linux/mm/allocpercpu.c
- *
- * Separated from slab.c August 11, 2006 Christoph Lameter
- */
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/bootmem.h>
-#include <asm/sections.h>
-
-#ifndef cache_line_size
-#define cache_line_size() L1_CACHE_BYTES
-#endif
-
-/**
- * percpu_depopulate - depopulate per-cpu data for given cpu
- * @__pdata: per-cpu data to depopulate
- * @cpu: depopulate per-cpu data for this cpu
- *
- * Depopulating per-cpu data for a cpu going offline would be a typical
- * use case. You need to register a cpu hotplug handler for that purpose.
- */
-static void percpu_depopulate(void *__pdata, int cpu)
-{
- struct percpu_data *pdata = __percpu_disguise(__pdata);
-
- kfree(pdata->ptrs[cpu]);
- pdata->ptrs[cpu] = NULL;
-}
-
-/**
- * percpu_depopulate_mask - depopulate per-cpu data for some cpu's
- * @__pdata: per-cpu data to depopulate
- * @mask: depopulate per-cpu data for cpu's selected through mask bits
- */
-static void __percpu_depopulate_mask(void *__pdata, const cpumask_t *mask)
-{
- int cpu;
- for_each_cpu_mask_nr(cpu, *mask)
- percpu_depopulate(__pdata, cpu);
-}
-
-#define percpu_depopulate_mask(__pdata, mask) \
- __percpu_depopulate_mask((__pdata), &(mask))
-
-/**
- * percpu_populate - populate per-cpu data for given cpu
- * @__pdata: per-cpu data to populate further
- * @size: size of per-cpu object
- * @gfp: may sleep or not etc.
- * @cpu: populate per-data for this cpu
- *
- * Populating per-cpu data for a cpu coming online would be a typical
- * use case. You need to register a cpu hotplug handler for that purpose.
- * Per-cpu object is populated with zeroed buffer.
- */
-static void *percpu_populate(void *__pdata, size_t size, gfp_t gfp, int cpu)
-{
- struct percpu_data *pdata = __percpu_disguise(__pdata);
- int node = cpu_to_node(cpu);
-
- /*
- * We should make sure each CPU gets private memory.
- */
- size = roundup(size, cache_line_size());
-
- BUG_ON(pdata->ptrs[cpu]);
- if (node_online(node))
- pdata->ptrs[cpu] = kmalloc_node(size, gfp|__GFP_ZERO, node);
- else
- pdata->ptrs[cpu] = kzalloc(size, gfp);
- return pdata->ptrs[cpu];
-}
-
-/**
- * percpu_populate_mask - populate per-cpu data for more cpu's
- * @__pdata: per-cpu data to populate further
- * @size: size of per-cpu object
- * @gfp: may sleep or not etc.
- * @mask: populate per-cpu data for cpu's selected through mask bits
- *
- * Per-cpu objects are populated with zeroed buffers.
- */
-static int __percpu_populate_mask(void *__pdata, size_t size, gfp_t gfp,
- cpumask_t *mask)
-{
- cpumask_t populated;
- int cpu;
-
- cpus_clear(populated);
- for_each_cpu_mask_nr(cpu, *mask)
- if (unlikely(!percpu_populate(__pdata, size, gfp, cpu))) {
- __percpu_depopulate_mask(__pdata, &populated);
- return -ENOMEM;
- } else
- cpu_set(cpu, populated);
- return 0;
-}
-
-#define percpu_populate_mask(__pdata, size, gfp, mask) \
- __percpu_populate_mask((__pdata), (size), (gfp), &(mask))
-
-/**
- * alloc_percpu - initial setup of per-cpu data
- * @size: size of per-cpu object
- * @align: alignment
- *
- * Allocate dynamic percpu area. Percpu objects are populated with
- * zeroed buffers.
- */
-void *__alloc_percpu(size_t size, size_t align)
-{
- /*
- * We allocate whole cache lines to avoid false sharing
- */
- size_t sz = roundup(nr_cpu_ids * sizeof(void *), cache_line_size());
- void *pdata = kzalloc(sz, GFP_KERNEL);
- void *__pdata = __percpu_disguise(pdata);
-
- /*
- * Can't easily make larger alignment work with kmalloc. WARN
- * on it. Larger alignment should only be used for module
- * percpu sections on SMP for which this path isn't used.
- */
- WARN_ON_ONCE(align > SMP_CACHE_BYTES);
-
- if (unlikely(!pdata))
- return NULL;
- if (likely(!__percpu_populate_mask(__pdata, size, GFP_KERNEL,
- &cpu_possible_map)))
- return __pdata;
- kfree(pdata);
- return NULL;
-}
-EXPORT_SYMBOL_GPL(__alloc_percpu);
-
-/**
- * free_percpu - final cleanup of per-cpu data
- * @__pdata: object to clean up
- *
- * We simply clean up any per-cpu object left. No need for the client to
- * track and specify through a bis mask which per-cpu objects are to free.
- */
-void free_percpu(void *__pdata)
-{
- if (unlikely(!__pdata))
- return;
- __percpu_depopulate_mask(__pdata, cpu_possible_mask);
- kfree(__percpu_disguise(__pdata));
-}
-EXPORT_SYMBOL_GPL(free_percpu);
-
-/*
- * Generic percpu area setup.
- */
-#ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA
-unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
-
-EXPORT_SYMBOL(__per_cpu_offset);
-
-void __init setup_per_cpu_areas(void)
-{
- unsigned long size, i;
- char *ptr;
- unsigned long nr_possible_cpus = num_possible_cpus();
-
- /* Copy section for each CPU (we discard the original) */
- size = ALIGN(PERCPU_ENOUGH_ROOM, PAGE_SIZE);
- ptr = alloc_bootmem_pages(size * nr_possible_cpus);
-
- for_each_possible_cpu(i) {
- __per_cpu_offset[i] = ptr - __per_cpu_start;
- memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
- ptr += size;
- }
-}
-#endif /* CONFIG_HAVE_SETUP_PER_CPU_AREA */
static void
__mem_cgroup_insert_exceeded(struct mem_cgroup *mem,
struct mem_cgroup_per_zone *mz,
- struct mem_cgroup_tree_per_zone *mctz)
+ struct mem_cgroup_tree_per_zone *mctz,
+ unsigned long long new_usage_in_excess)
{
struct rb_node **p = &mctz->rb_root.rb_node;
struct rb_node *parent = NULL;
if (mz->on_tree)
return;
- mz->usage_in_excess = res_counter_soft_limit_excess(&mem->res);
+ mz->usage_in_excess = new_usage_in_excess;
+ if (!mz->usage_in_excess)
+ return;
while (*p) {
parent = *p;
mz_node = rb_entry(parent, struct mem_cgroup_per_zone,
mz->on_tree = false;
}
-static void
-mem_cgroup_insert_exceeded(struct mem_cgroup *mem,
- struct mem_cgroup_per_zone *mz,
- struct mem_cgroup_tree_per_zone *mctz)
-{
- spin_lock(&mctz->lock);
- __mem_cgroup_insert_exceeded(mem, mz, mctz);
- spin_unlock(&mctz->lock);
-}
-
static void
mem_cgroup_remove_exceeded(struct mem_cgroup *mem,
struct mem_cgroup_per_zone *mz,
static void mem_cgroup_update_tree(struct mem_cgroup *mem, struct page *page)
{
- unsigned long long prev_usage_in_excess, new_usage_in_excess;
- bool updated_tree = false;
+ unsigned long long excess;
struct mem_cgroup_per_zone *mz;
struct mem_cgroup_tree_per_zone *mctz;
-
- mz = mem_cgroup_zoneinfo(mem, page_to_nid(page), page_zonenum(page));
+ int nid = page_to_nid(page);
+ int zid = page_zonenum(page);
mctz = soft_limit_tree_from_page(page);
/*
- * We do updates in lazy mode, mem's are removed
- * lazily from the per-zone, per-node rb tree
+ * Necessary to update all ancestors when hierarchy is used.
+ * because their event counter is not touched.
*/
- prev_usage_in_excess = mz->usage_in_excess;
-
- new_usage_in_excess = res_counter_soft_limit_excess(&mem->res);
- if (prev_usage_in_excess) {
- mem_cgroup_remove_exceeded(mem, mz, mctz);
- updated_tree = true;
- }
- if (!new_usage_in_excess)
- goto done;
- mem_cgroup_insert_exceeded(mem, mz, mctz);
-
-done:
- if (updated_tree) {
- spin_lock(&mctz->lock);
- mz->usage_in_excess = new_usage_in_excess;
- spin_unlock(&mctz->lock);
+ for (; mem; mem = parent_mem_cgroup(mem)) {
+ mz = mem_cgroup_zoneinfo(mem, nid, zid);
+ excess = res_counter_soft_limit_excess(&mem->res);
+ /*
+ * We have to update the tree if mz is on RB-tree or
+ * mem is over its softlimit.
+ */
+ if (excess || mz->on_tree) {
+ spin_lock(&mctz->lock);
+ /* if on-tree, remove it */
+ if (mz->on_tree)
+ __mem_cgroup_remove_exceeded(mem, mz, mctz);
+ /*
+ * Insert again. mz->usage_in_excess will be updated.
+ * If excess is 0, no tree ops.
+ */
+ __mem_cgroup_insert_exceeded(mem, mz, mctz, excess);
+ spin_unlock(&mctz->lock);
+ }
}
}
__mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_zone *mctz)
{
struct rb_node *rightmost = NULL;
- struct mem_cgroup_per_zone *mz = NULL;
+ struct mem_cgroup_per_zone *mz;
retry:
+ mz = NULL;
rightmost = rb_last(&mctz->rb_root);
if (!rightmost)
goto done; /* Nothing to reclaim from */
gfp_t gfp_mask, struct mem_cgroup **memcg,
bool oom, struct page *page)
{
- struct mem_cgroup *mem, *mem_over_limit, *mem_over_soft_limit;
+ struct mem_cgroup *mem, *mem_over_limit;
int nr_retries = MEM_CGROUP_RECLAIM_RETRIES;
- struct res_counter *fail_res, *soft_fail_res = NULL;
+ struct res_counter *fail_res;
if (unlikely(test_thread_flag(TIF_MEMDIE))) {
/* Don't account this! */
if (mem_cgroup_is_root(mem))
goto done;
- ret = res_counter_charge(&mem->res, PAGE_SIZE, &fail_res,
- &soft_fail_res);
+ ret = res_counter_charge(&mem->res, PAGE_SIZE, &fail_res);
if (likely(!ret)) {
if (!do_swap_account)
break;
ret = res_counter_charge(&mem->memsw, PAGE_SIZE,
- &fail_res, NULL);
+ &fail_res);
if (likely(!ret))
break;
/* mem+swap counter fails */
- res_counter_uncharge(&mem->res, PAGE_SIZE, NULL);
+ res_counter_uncharge(&mem->res, PAGE_SIZE);
flags |= MEM_CGROUP_RECLAIM_NOSWAP;
mem_over_limit = mem_cgroup_from_res_counter(fail_res,
memsw);
}
}
/*
- * Insert just the ancestor, we should trickle down to the correct
- * cgroup for reclaim, since the other nodes will be below their
- * soft limit
+ * Insert ancestor (and ancestor's ancestors), to softlimit RB-tree.
+ * if they exceeds softlimit.
*/
- if (soft_fail_res) {
- mem_over_soft_limit =
- mem_cgroup_from_res_counter(soft_fail_res, res);
- if (mem_cgroup_soft_limit_check(mem_over_soft_limit))
- mem_cgroup_update_tree(mem_over_soft_limit, page);
- }
+ if (mem_cgroup_soft_limit_check(mem))
+ mem_cgroup_update_tree(mem, page);
done:
return 0;
nomem:
if (unlikely(PageCgroupUsed(pc))) {
unlock_page_cgroup(pc);
if (!mem_cgroup_is_root(mem)) {
- res_counter_uncharge(&mem->res, PAGE_SIZE, NULL);
+ res_counter_uncharge(&mem->res, PAGE_SIZE);
if (do_swap_account)
- res_counter_uncharge(&mem->memsw, PAGE_SIZE,
- NULL);
+ res_counter_uncharge(&mem->memsw, PAGE_SIZE);
}
css_put(&mem->css);
return;
goto out;
if (!mem_cgroup_is_root(from))
- res_counter_uncharge(&from->res, PAGE_SIZE, NULL);
+ res_counter_uncharge(&from->res, PAGE_SIZE);
mem_cgroup_charge_statistics(from, pc, false);
page = pc->page;
}
if (do_swap_account && !mem_cgroup_is_root(from))
- res_counter_uncharge(&from->memsw, PAGE_SIZE, NULL);
+ res_counter_uncharge(&from->memsw, PAGE_SIZE);
css_put(&from->css);
css_get(&to->css);
css_put(&parent->css);
/* uncharge if move fails */
if (!mem_cgroup_is_root(parent)) {
- res_counter_uncharge(&parent->res, PAGE_SIZE, NULL);
+ res_counter_uncharge(&parent->res, PAGE_SIZE);
if (do_swap_account)
- res_counter_uncharge(&parent->memsw, PAGE_SIZE, NULL);
+ res_counter_uncharge(&parent->memsw, PAGE_SIZE);
}
return ret;
}
* calling css_tryget
*/
if (!mem_cgroup_is_root(memcg))
- res_counter_uncharge(&memcg->memsw, PAGE_SIZE,
- NULL);
+ res_counter_uncharge(&memcg->memsw, PAGE_SIZE);
mem_cgroup_swap_statistics(memcg, false);
mem_cgroup_put(memcg);
}
if (!mem)
return;
if (!mem_cgroup_is_root(mem)) {
- res_counter_uncharge(&mem->res, PAGE_SIZE, NULL);
+ res_counter_uncharge(&mem->res, PAGE_SIZE);
if (do_swap_account)
- res_counter_uncharge(&mem->memsw, PAGE_SIZE, NULL);
+ res_counter_uncharge(&mem->memsw, PAGE_SIZE);
}
css_put(&mem->css);
}
struct page_cgroup *pc;
struct mem_cgroup *mem = NULL;
struct mem_cgroup_per_zone *mz;
- bool soft_limit_excess = false;
if (mem_cgroup_disabled())
return NULL;
}
if (!mem_cgroup_is_root(mem)) {
- res_counter_uncharge(&mem->res, PAGE_SIZE, &soft_limit_excess);
+ res_counter_uncharge(&mem->res, PAGE_SIZE);
if (do_swap_account &&
(ctype != MEM_CGROUP_CHARGE_TYPE_SWAPOUT))
- res_counter_uncharge(&mem->memsw, PAGE_SIZE, NULL);
+ res_counter_uncharge(&mem->memsw, PAGE_SIZE);
}
if (ctype == MEM_CGROUP_CHARGE_TYPE_SWAPOUT)
mem_cgroup_swap_statistics(mem, true);
mz = page_cgroup_zoneinfo(pc);
unlock_page_cgroup(pc);
- if (soft_limit_excess && mem_cgroup_soft_limit_check(mem))
+ if (mem_cgroup_soft_limit_check(mem))
mem_cgroup_update_tree(mem, page);
/* at swapout, this memcg will be accessed to record to swap */
if (ctype != MEM_CGROUP_CHARGE_TYPE_SWAPOUT)
* This memcg can be obsolete one. We avoid calling css_tryget
*/
if (!mem_cgroup_is_root(memcg))
- res_counter_uncharge(&memcg->memsw, PAGE_SIZE, NULL);
+ res_counter_uncharge(&memcg->memsw, PAGE_SIZE);
mem_cgroup_swap_statistics(memcg, false);
mem_cgroup_put(memcg);
}
unsigned long reclaimed;
int loop = 0;
struct mem_cgroup_tree_per_zone *mctz;
+ unsigned long long excess;
if (order > 0)
return 0;
break;
} while (1);
}
- mz->usage_in_excess =
- res_counter_soft_limit_excess(&mz->mem->res);
__mem_cgroup_remove_exceeded(mz->mem, mz, mctz);
+ excess = res_counter_soft_limit_excess(&mz->mem->res);
/*
* One school of thought says that we should not add
* back the node to the tree if reclaim returns 0.
* memory to reclaim from. Consider this as a longer
* term TODO.
*/
- if (mz->usage_in_excess)
- __mem_cgroup_insert_exceeded(mz->mem, mz, mctz);
+ /* If excess == 0, no tree ops */
+ __mem_cgroup_insert_exceeded(mz->mem, mz, mctz, excess);
spin_unlock(&mctz->lock);
css_put(&mz->mem->css);
loop++;
*
* To use this allocator, arch code should do the followings.
*
- * - drop CONFIG_HAVE_LEGACY_PER_CPU_AREA
- *
* - define __addr_to_pcpu_ptr() and __pcpu_ptr_to_addr() to translate
* regular address to percpu pointer and back if they need to be
* different from the default
}
/*
- * At what user virtual address is page expected in vma? checking that the
- * page matches the vma: currently only used on anon pages, by unuse_vma;
+ * At what user virtual address is page expected in vma?
+ * checking that the page matches the vma.
*/
unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
{
struct vlan_dev_info *vlan = vlan_dev_info(dev);
return nla_total_size(2) + /* IFLA_VLAN_ID */
+ sizeof(struct ifla_vlan_flags) + /* IFLA_VLAN_FLAGS */
vlan_qos_map_size(vlan->nr_ingress_mappings) +
vlan_qos_map_size(vlan->nr_egress_mappings);
}
}
int vcc_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct atm_vcc *vcc;
unsigned long value;
int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int vcc_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen);
+ char __user *optval, unsigned int optlen);
int vcc_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen);
}
static int pvc_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
int error;
static int svc_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct atm_vcc *vcc = ATM_SD(sock);
*/
static int ax25_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
ax25_cb *ax25;
case SO_BINDTODEVICE:
if (optlen > IFNAMSIZ)
- optlen=IFNAMSIZ;
- if (copy_from_user(devname, optval, optlen)) {
- res = -EFAULT;
- break;
- }
+ optlen = IFNAMSIZ;
- dev = dev_get_by_name(&init_net, devname);
- if (dev == NULL) {
- res = -ENODEV;
+ if (copy_from_user(devname, optval, optlen)) {
+ res = -EFAULT;
break;
}
(sock->state != SS_UNCONNECTED ||
sk->sk_state == TCP_LISTEN)) {
res = -EADDRNOTAVAIL;
- dev_put(dev);
+ break;
+ }
+
+ dev = dev_get_by_name(&init_net, devname);
+ if (!dev) {
+ res = -ENODEV;
break;
}
ax25->ax25_dev = ax25_dev_ax25dev(dev);
ax25_fillin_cb(ax25, ax25->ax25_dev);
+ dev_put(dev);
break;
default:
sock_init_data(NULL, sk);
- sk->sk_destruct = ax25_free_sock;
sk->sk_type = osk->sk_type;
sk->sk_priority = osk->sk_priority;
sk->sk_protocol = osk->sk_protocol;
}
sk->sk_protinfo = ax25;
+ sk->sk_destruct = ax25_free_sock;
ax25->sk = sk;
return sk;
goto done;
}
-static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int len)
+static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int len)
{
struct hci_ufilter uf = { .opcode = 0 };
struct sock *sk = sock->sk;
return bt_sock_recvmsg(iocb, sock, msg, len, flags);
}
-static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, int optlen)
+static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct l2cap_options opts;
return err;
}
-static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
+static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct bt_security sec;
return copied ? : err;
}
-static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, int optlen)
+static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
int err = 0;
return err;
}
-static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
+static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct bt_security sec;
return err;
}
-static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
+static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
int err = 0;
br_fdb_delete_by_port(br, p, 1);
err1:
kobject_put(&p->kobj);
+ p = NULL; /* kobject_put frees */
err0:
dev_set_promiscuity(dev, -1);
put_back:
}
static int raw_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct raw_sock *ro = raw_sk(sk);
};
static int do_set_attach_filter(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval;
struct sock_fprog __user *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog));
}
static int do_set_sock_timeout(struct socket *sock, int level,
- int optname, char __user *optval, int optlen)
+ int optname, char __user *optval, unsigned int optlen)
{
struct compat_timeval __user *up = (struct compat_timeval __user *) optval;
struct timeval ktime;
}
static int compat_sock_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
if (optname == SO_ATTACH_FILTER)
return do_set_attach_filter(sock, level, optname,
}
asmlinkage long compat_sys_setsockopt(int fd, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
int err;
struct socket *sock;
int compat_mc_setsockopt(struct sock *sock, int level, int optname,
- char __user *optval, int optlen,
- int (*setsockopt)(struct sock *,int,int,char __user *,int))
+ char __user *optval, unsigned int optlen,
+ int (*setsockopt)(struct sock *,int,int,char __user *,unsigned int))
{
char __user *koptval = optval;
int koptlen = optlen;
int ret = NET_RX_DROP;
__be16 type;
+ if (!skb->tstamp.tv64)
+ net_timestamp(skb);
+
if (skb->vlan_tci && vlan_hwaccel_do_receive(skb))
return NET_RX_SUCCESS;
if (netpoll_receive_skb(skb))
return NET_RX_DROP;
- if (!skb->tstamp.tv64)
- net_timestamp(skb);
-
if (!skb->iif)
skb->iif = skb->dev->ifindex;
#include <net/sock.h>
#include <linux/rtnetlink.h>
#include <linux/wireless.h>
-#include <net/iw_handler.h>
+#include <net/wext.h>
#include "net-sysfs.h"
char *))
{
struct net_device *dev = to_net_dev(d);
- const struct iw_statistics *iw = NULL;
+ const struct iw_statistics *iw;
ssize_t ret = -EINVAL;
read_lock(&dev_base_lock);
if (dev_isalive(dev)) {
- if (dev->wireless_handlers &&
- dev->wireless_handlers->get_wireless_stats)
- iw = dev->wireless_handlers->get_wireless_stats(dev);
- if (iw != NULL)
+ iw = get_wireless_stats(dev);
+ if (iw)
ret = (*format)(iw, buf);
}
read_unlock(&dev_base_lock);
*groups++ = &netstat_group;
#ifdef CONFIG_WIRELESS_EXT_SYSFS
- if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)
+ if (net->wireless_handlers || net->ieee80211_ptr)
*groups++ = &wireless_group;
#endif
#endif /* CONFIG_SYSFS */
*/
int sock_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
int val;
void sock_wfree(struct sk_buff *skb)
{
struct sock *sk = skb->sk;
- int res;
+ unsigned int len = skb->truesize;
- /* In case it might be waiting for more memory. */
- res = atomic_sub_return(skb->truesize, &sk->sk_wmem_alloc);
- if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE))
+ if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE)) {
+ /*
+ * Keep a reference on sk_wmem_alloc, this will be released
+ * after sk_write_space() call
+ */
+ atomic_sub(len - 1, &sk->sk_wmem_alloc);
sk->sk_write_space(sk);
+ len = 1;
+ }
/*
- * if sk_wmem_alloc reached 0, we are last user and should
- * free this sock, as sk_free() call could not do it.
+ * if sk_wmem_alloc reaches 0, we must finish what sk_free()
+ * could not do because of in-flight packets
*/
- if (res == 0)
+ if (atomic_sub_and_test(len, &sk->sk_wmem_alloc))
__sk_free(sk);
}
EXPORT_SYMBOL(sock_wfree);
EXPORT_SYMBOL(sock_no_shutdown);
int sock_no_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
return -EOPNOTSUPP;
}
* Set socket options on an inet socket.
*/
int sock_common_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
#ifdef CONFIG_COMPAT
int compat_sock_common_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
nlmsg_end(dcbnl_skb, nlh);
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret)
- goto err;
+ return -EINVAL;
return 0;
nlmsg_failure:
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret)
- goto err;
+ goto err_out;
return 0;
nlmsg_failure:
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret)
- goto err;
+ goto err_out;
return 0;
nlmsg_failure:
-err:
kfree_skb(dcbnl_skb);
err_out:
return -EINVAL;
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret)
- goto err;
+ goto err_out;
return 0;
nlmsg_failure:
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret) {
ret = -EINVAL;
- goto err;
+ goto err_out;
}
return 0;
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret)
- goto err;
+ goto err_out;
return 0;
ret = rtnl_unicast(dcbnl_skb, &init_net, pid);
if (ret)
- goto err;
+ goto err_out;
return 0;
extern int dccp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
extern int dccp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen);
+ char __user *optval, unsigned int optlen);
#ifdef CONFIG_COMPAT
extern int compat_dccp_getsockopt(struct sock *sk,
int level, int optname,
char __user *optval, int __user *optlen);
extern int compat_dccp_setsockopt(struct sock *sk,
int level, int optname,
- char __user *optval, int optlen);
+ char __user *optval, unsigned int optlen);
#endif
extern int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg);
extern int dccp_sendmsg(struct kiocb *iocb, struct sock *sk,
EXPORT_SYMBOL_GPL(dccp_ioctl);
static int dccp_setsockopt_service(struct sock *sk, const __be32 service,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct dccp_sock *dp = dccp_sk(sk);
struct dccp_service_list *sl = NULL;
}
static int dccp_setsockopt_ccid(struct sock *sk, int type,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
u8 *val;
int rc = 0;
}
static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct dccp_sock *dp = dccp_sk(sk);
int val, err = 0;
}
int dccp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
if (level != SOL_DCCP)
return inet_csk(sk)->icsk_af_ops->setsockopt(sk, level,
#ifdef CONFIG_COMPAT
int compat_dccp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
if (level != SOL_DCCP)
return inet_csk_compat_setsockopt(sk, level, optname,
static struct hlist_head dn_wild_sk;
static atomic_t decnet_memory_allocated;
-static int __dn_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen, int flags);
+static int __dn_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen, int flags);
static int __dn_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen, int flags);
static struct hlist_head *dn_find_list(struct sock *sk)
return err;
}
-static int dn_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
+static int dn_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
int err;
return err;
}
-static int __dn_setsockopt(struct socket *sock, int level,int optname, char __user *optval, int optlen, int flags)
+static int __dn_setsockopt(struct socket *sock, int level,int optname, char __user *optval, unsigned int optlen, int flags)
{
struct sock *sk = sock->sk;
struct dn_scp *scp = DN_SK(sk);
}
static int dgram_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct dgram_sock *ro = dgram_sk(sk);
int val;
}
static int raw_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
return -EOPNOTSUPP;
}
EXPORT_SYMBOL_GPL(inet_csk_compat_getsockopt);
int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
const struct inet_connection_sock *icsk = inet_csk(sk);
*/
static int do_ip_setsockopt(struct sock *sk, int level,
- int optname, char __user *optval, int optlen)
+ int optname, char __user *optval, unsigned int optlen)
{
struct inet_sock *inet = inet_sk(sk);
int val = 0, err;
}
int ip_setsockopt(struct sock *sk, int level,
- int optname, char __user *optval, int optlen)
+ int optname, char __user *optval, unsigned int optlen)
{
int err;
#ifdef CONFIG_COMPAT
int compat_ip_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
int err;
* MOSPF/PIM router set up we can clean this up.
*/
-int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int optlen)
+int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
{
int ret;
struct vifctl vif;
}
static int do_raw_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
if (optname == ICMP_FILTER) {
if (inet_sk(sk)->num != IPPROTO_ICMP)
}
static int raw_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
if (level != SOL_RAW)
return ip_setsockopt(sk, level, optname, optval, optlen);
#ifdef CONFIG_COMPAT
static int compat_raw_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
if (level != SOL_RAW)
return compat_ip_setsockopt(sk, level, optname, optval, optlen);
* Socket option code for TCP.
*/
static int do_tcp_setsockopt(struct sock *sk, int level,
- int optname, char __user *optval, int optlen)
+ int optname, char __user *optval, unsigned int optlen)
{
struct tcp_sock *tp = tcp_sk(sk);
struct inet_connection_sock *icsk = inet_csk(sk);
}
int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
- int optlen)
+ unsigned int optlen)
{
struct inet_connection_sock *icsk = inet_csk(sk);
#ifdef CONFIG_COMPAT
int compat_tcp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
if (level != SOL_TCP)
return inet_csk_compat_setsockopt(sk, level, optname,
* Socket option code for UDP
*/
int udp_lib_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen,
+ char __user *optval, unsigned int optlen,
int (*push_pending_frames)(struct sock *))
{
struct udp_sock *up = udp_sk(sk);
EXPORT_SYMBOL(udp_lib_setsockopt);
int udp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
if (level == SOL_UDP || level == SOL_UDPLITE)
return udp_lib_setsockopt(sk, level, optname, optval, optlen,
#ifdef CONFIG_COMPAT
int compat_udp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
if (level == SOL_UDP || level == SOL_UDPLITE)
return udp_lib_setsockopt(sk, level, optname, optval, optlen,
extern int udp_v4_get_port(struct sock *sk, unsigned short snum);
extern int udp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen);
+ char __user *optval, unsigned int optlen);
extern int udp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
#ifdef CONFIG_COMPAT
extern int compat_udp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen);
+ char __user *optval, unsigned int optlen);
extern int compat_udp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
#endif
* MOSPF/PIM router set up we can clean this up.
*/
-int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int optlen)
+int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
{
int ret;
struct mif6ctl vif;
}
static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct ipv6_pinfo *np = inet6_sk(sk);
struct net *net = sock_net(sk);
}
int ipv6_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
int err;
#ifdef CONFIG_COMPAT
int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
int err;
&icmp6h, NULL,
send_sllao ? ND_OPT_SOURCE_LL_ADDR : 0);
}
-EXPORT_SYMBOL(ndisc_send_rs);
static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct raw6_sock *rp = raw6_sk(sk);
int val;
}
static int rawv6_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
switch(level) {
case SOL_RAW:
#ifdef CONFIG_COMPAT
static int compat_rawv6_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
switch (level) {
case SOL_RAW:
* Roger Venning <r.venning@telstra.com>: 6to4 support
* Nate Thompson <nate@thebog.net>: 6to4 support
* Fred Templin <fred.l.templin@boeing.com>: isatap support
- * Sascha Hlusiak <mail@saschahlusiak.de>: stateless autoconf for isatap
*/
#include <linux/module.h>
return NULL;
}
-static void ipip6_tunnel_rs_timer(unsigned long data)
-{
- struct ip_tunnel_prl_entry *p = (struct ip_tunnel_prl_entry *) data;
- struct inet6_dev *ifp;
- struct inet6_ifaddr *addr;
-
- spin_lock(&p->lock);
- ifp = __in6_dev_get(p->tunnel->dev);
-
- read_lock_bh(&ifp->lock);
- for (addr = ifp->addr_list; addr; addr = addr->if_next) {
- struct in6_addr rtr;
-
- if (!(ipv6_addr_type(&addr->addr) & IPV6_ADDR_LINKLOCAL))
- continue;
-
- /* Send RS to guessed linklocal address of router
- *
- * Better: send to ff02::2 encapsuled in unicast directly
- * to router-v4 instead of guessing the v6 address.
- *
- * Cisco/Windows seem to not set the u/l bit correctly,
- * so we won't guess right.
- */
- ipv6_addr_set(&rtr, htonl(0xFE800000), 0, 0, 0);
- if (!__ipv6_isatap_ifid(rtr.s6_addr + 8,
- p->addr)) {
- ndisc_send_rs(p->tunnel->dev, &addr->addr, &rtr);
- }
- }
- read_unlock_bh(&ifp->lock);
-
- mod_timer(&p->rs_timer, jiffies + HZ * p->rs_delay);
- spin_unlock(&p->lock);
-
- return;
-}
-
static struct ip_tunnel_prl_entry *
__ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr)
{
c = 0;
for (prl = t->prl; prl; prl = prl->next) {
- if (c > cmax)
+ if (c >= cmax)
break;
if (kprl.addr != htonl(INADDR_ANY) && prl->addr != kprl.addr)
continue;
kp[c].addr = prl->addr;
kp[c].flags = prl->flags;
- kp[c].rs_delay = prl->rs_delay;
c++;
if (kprl.addr != htonl(INADDR_ANY))
break;
}
p->next = t->prl;
- p->tunnel = t;
t->prl = p;
t->prl_count++;
-
- spin_lock_init(&p->lock);
- setup_timer(&p->rs_timer, ipip6_tunnel_rs_timer, (unsigned long) p);
update:
p->addr = a->addr;
p->flags = a->flags;
- p->rs_delay = a->rs_delay;
- if (p->rs_delay == 0)
- p->rs_delay = IPTUNNEL_RS_DEFAULT_DELAY;
- spin_lock(&p->lock);
- del_timer(&p->rs_timer);
- if (p->flags & PRL_DEFAULT)
- mod_timer(&p->rs_timer, jiffies + 1);
- spin_unlock(&p->lock);
out:
write_unlock(&ipip6_lock);
return err;
if ((*p)->addr == a->addr) {
x = *p;
*p = x->next;
- spin_lock(&x->lock);
- del_timer(&x->rs_timer);
- spin_unlock(&x->lock);
kfree(x);
t->prl_count--;
goto out;
while (t->prl) {
x = t->prl;
t->prl = t->prl->next;
- spin_lock(&x->lock);
- del_timer(&x->rs_timer);
- spin_unlock(&x->lock);
kfree(x);
t->prl_count--;
}
* Socket option code for UDP
*/
int udpv6_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
if (level == SOL_UDP || level == SOL_UDPLITE)
return udp_lib_setsockopt(sk, level, optname, optval, optlen,
#ifdef CONFIG_COMPAT
int compat_udpv6_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
if (level == SOL_UDP || level == SOL_UDPLITE)
return udp_lib_setsockopt(sk, level, optname, optval, optlen,
extern int udpv6_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
extern int udpv6_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen);
+ char __user *optval, unsigned int optlen);
#ifdef CONFIG_COMPAT
extern int compat_udpv6_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen);
+ char __user *optval, unsigned int optlen);
extern int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
#endif
* socket object. */
static int ipx_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
int opt;
*
*/
static int irda_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct irda_sock *self = irda_sk(sk);
/* getsockopt and setsockopt */
static int iucv_sock_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct iucv_sock *iucv = iucv_sk(sk);
* Set various connection specific parameters.
*/
static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct llc_sock *llc = llc_sk(sk);
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
- printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
- sdata->dev->name, reason_code);
+ printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
+ sdata->dev->name, mgmt->sa, reason_code);
ieee80211_set_disassoc(sdata, false);
return RX_MGMT_CFG80211_DISASSOC;
/* direct probe may be part of the association flow */
if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) {
- printk(KERN_DEBUG "%s direct probe responded\n",
+ printk(KERN_DEBUG "%s: direct probe responded\n",
sdata->dev->name);
wk->tries = 0;
wk->state = IEEE80211_MGD_STATE_AUTH;
struct ieee80211_mgd_work *wk;
const u8 *bssid = NULL;
- printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
- sdata->dev->name, req->reason_code);
-
mutex_lock(&ifmgd->mtx);
if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) {
mutex_unlock(&ifmgd->mtx);
+ printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
+ sdata->dev->name, bssid, req->reason_code);
+
ieee80211_send_deauth_disassoc(sdata, bssid,
IEEE80211_STYPE_DEAUTH, req->reason_code,
cookie);
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n",
- sdata->dev->name, req->reason_code);
-
mutex_lock(&ifmgd->mtx);
/*
return -ENOLINK;
}
+ printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n",
+ sdata->dev->name, req->bss->bssid, req->reason_code);
+
ieee80211_set_disassoc(sdata, false);
mutex_unlock(&ifmgd->mtx);
}
int nf_setsockopt(struct sock *sk, u_int8_t pf, int val, char __user *opt,
- int len)
+ unsigned int len)
{
return nf_sockopt(sk, pf, val, opt, &len, 0);
}
}
int compat_nf_setsockopt(struct sock *sk, u_int8_t pf,
- int val, char __user *opt, int len)
+ int val, char __user *opt, unsigned int len)
{
return compat_nf_sockopt(sk, pf, val, opt, &len, 0);
}
}
static int netlink_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct netlink_sock *nlk = nlk_sk(sk);
}
rep = __nlmsg_put(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
- NLMSG_ERROR, sizeof(struct nlmsgerr), 0);
+ NLMSG_ERROR, payload, 0);
errmsg = nlmsg_data(rep);
errmsg->error = err;
memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(*nlh));
*/
static int nr_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct nr_sock *nr = nr_sk(sk);
}
static int
-packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
+packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct packet_sock *po = pkt_sk(sk);
}
static int pep_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct pep_sock *pn = pep_sk(sk);
int val = 0, err = 0;
return -EADDRINUSE;
found:
- mutex_unlock(&port_mutex);
pn->sobject = pn_object(pn_addr(pn->sobject), sport);
return 0;
}
}
static int rds_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct rds_sock *rs = rds_sk_to_rs(sock->sk);
int ret;
*/
static int rose_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct rose_sock *rose = rose_sk(sk);
* set RxRPC socket options
*/
static int rxrpc_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
unsigned min_sec_level;
* instead a error will be indicated to the user.
*/
static int sctp_setsockopt_disable_fragments(struct sock *sk,
- char __user *optval, int optlen)
+ char __user *optval,
+ unsigned int optlen)
{
int val;
}
static int sctp_setsockopt_events(struct sock *sk, char __user *optval,
- int optlen)
+ unsigned int optlen)
{
if (optlen > sizeof(struct sctp_event_subscribe))
return -EINVAL;
* association is closed.
*/
static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
- int optlen)
+ unsigned int optlen)
{
struct sctp_sock *sp = sctp_sk(sk);
}
static int sctp_setsockopt_peer_addr_params(struct sock *sk,
- char __user *optval, int optlen)
+ char __user *optval,
+ unsigned int optlen)
{
struct sctp_paddrparams params;
struct sctp_transport *trans = NULL;
*/
static int sctp_setsockopt_delayed_ack(struct sock *sk,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sctp_sack_info params;
struct sctp_transport *trans = NULL;
* by the change). With TCP-style sockets, this option is inherited by
* sockets derived from a listener socket.
*/
-static int sctp_setsockopt_initmsg(struct sock *sk, char __user *optval, int optlen)
+static int sctp_setsockopt_initmsg(struct sock *sk, char __user *optval, unsigned int optlen)
{
struct sctp_initmsg sinit;
struct sctp_sock *sp = sctp_sk(sk);
* to this call if the caller is using the UDP model.
*/
static int sctp_setsockopt_default_send_param(struct sock *sk,
- char __user *optval, int optlen)
+ char __user *optval,
+ unsigned int optlen)
{
struct sctp_sndrcvinfo info;
struct sctp_association *asoc;
* association peer's addresses.
*/
static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval,
- int optlen)
+ unsigned int optlen)
{
struct sctp_prim prim;
struct sctp_transport *trans;
* integer boolean flag.
*/
static int sctp_setsockopt_nodelay(struct sock *sk, char __user *optval,
- int optlen)
+ unsigned int optlen)
{
int val;
* be changed.
*
*/
-static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, int optlen) {
+static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, unsigned int optlen)
+{
struct sctp_rtoinfo rtoinfo;
struct sctp_association *asoc;
* See [SCTP] for more information.
*
*/
-static int sctp_setsockopt_associnfo(struct sock *sk, char __user *optval, int optlen)
+static int sctp_setsockopt_associnfo(struct sock *sk, char __user *optval, unsigned int optlen)
{
struct sctp_assocparams assocparams;
* addresses and a user will receive both PF_INET6 and PF_INET type
* addresses on the socket.
*/
-static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, int optlen)
+static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsigned int optlen)
{
int val;
struct sctp_sock *sp = sctp_sk(sk);
* changed (effecting future associations only).
* assoc_value: This parameter specifies the maximum size in bytes.
*/
-static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optlen)
+static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
{
struct sctp_assoc_value params;
struct sctp_association *asoc;
* set primary request:
*/
static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optval,
- int optlen)
+ unsigned int optlen)
{
struct sctp_sock *sp;
struct sctp_endpoint *ep;
}
static int sctp_setsockopt_adaptation_layer(struct sock *sk, char __user *optval,
- int optlen)
+ unsigned int optlen)
{
struct sctp_setadaptation adaptation;
* saved with outbound messages.
*/
static int sctp_setsockopt_context(struct sock *sk, char __user *optval,
- int optlen)
+ unsigned int optlen)
{
struct sctp_assoc_value params;
struct sctp_sock *sp;
*/
static int sctp_setsockopt_fragment_interleave(struct sock *sk,
char __user *optval,
- int optlen)
+ unsigned int optlen)
{
int val;
*/
static int sctp_setsockopt_partial_delivery_point(struct sock *sk,
char __user *optval,
- int optlen)
+ unsigned int optlen)
{
u32 val;
*/
static int sctp_setsockopt_maxburst(struct sock *sk,
char __user *optval,
- int optlen)
+ unsigned int optlen)
{
struct sctp_assoc_value params;
struct sctp_sock *sp;
* will only effect future associations on the socket.
*/
static int sctp_setsockopt_auth_chunk(struct sock *sk,
- char __user *optval,
- int optlen)
+ char __user *optval,
+ unsigned int optlen)
{
struct sctp_authchunk val;
* endpoint requires the peer to use.
*/
static int sctp_setsockopt_hmac_ident(struct sock *sk,
- char __user *optval,
- int optlen)
+ char __user *optval,
+ unsigned int optlen)
{
struct sctp_hmacalgo *hmacs;
u32 idents;
*/
static int sctp_setsockopt_auth_key(struct sock *sk,
char __user *optval,
- int optlen)
+ unsigned int optlen)
{
struct sctp_authkey *authkey;
struct sctp_association *asoc;
* the association shared key.
*/
static int sctp_setsockopt_active_key(struct sock *sk,
- char __user *optval,
- int optlen)
+ char __user *optval,
+ unsigned int optlen)
{
struct sctp_authkeyid val;
struct sctp_association *asoc;
* This set option will delete a shared secret key from use.
*/
static int sctp_setsockopt_del_key(struct sock *sk,
- char __user *optval,
- int optlen)
+ char __user *optval,
+ unsigned int optlen)
{
struct sctp_authkeyid val;
struct sctp_association *asoc;
* optlen - the size of the buffer.
*/
SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
int retval = 0;
unsigned long a[6];
unsigned long a0, a1;
int err;
+ unsigned int len;
if (call < 1 || call > SYS_ACCEPT4)
return -EINVAL;
+ len = nargs[call];
+ if (len > sizeof(a))
+ return -EINVAL;
+
/* copy_from_user should be SMP safe. */
- if (copy_from_user(a, args, nargs[call]))
+ if (copy_from_user(a, args, len))
return -EFAULT;
audit_socketcall(nargs[call] / sizeof(unsigned long), a);
}
int kernel_setsockopt(struct socket *sock, int level, int optname,
- char *optval, int optlen)
+ char *optval, unsigned int optlen)
{
mm_segment_t oldfs = get_fs();
int err;
*/
static int setsockopt(struct socket *sock,
- int lvl, int opt, char __user *ov, int ol)
+ int lvl, int opt, char __user *ov, unsigned int ol)
{
struct sock *sk = sock->sk;
struct tipc_port *tport = tipc_sk_port(sk);
wdev->conn->params.ssid = wdev->ssid;
wdev->conn->params.ssid_len = connect->ssid_len;
- /* don't care about result -- but fill bssid & channel */
- if (!wdev->conn->params.bssid || !wdev->conn->params.channel)
- bss = cfg80211_get_conn_bss(wdev);
+ /* see if we have the bss already */
+ bss = cfg80211_get_conn_bss(wdev);
wdev->sme_state = CFG80211_SME_CONNECTING;
wdev->connect_keys = connkeys;
if (wdev->wext.keys) {
wdev->wext.keys->def = wdev->wext.default_key;
wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
- wdev->wext.connect.privacy = true;
+ if (wdev->wext.default_key != -1)
+ wdev->wext.connect.privacy = true;
}
if (!wdev->wext.connect.ssid_len)
data->flags = 1;
data->length = wdev->wext.connect.ssid_len;
memcpy(ssid, wdev->wext.connect.ssid, data->length);
- } else
- data->flags = 0;
+ }
wdev_unlock(wdev);
return 0;
wdev_lock(wdev);
if (wdev->current_bss)
memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN);
- else if (wdev->wext.connect.bssid)
- memcpy(ap_addr->sa_data, wdev->wext.connect.bssid, ETH_ALEN);
else
memset(ap_addr->sa_data, 0, ETH_ALEN);
wdev_unlock(wdev);
/*
* Get statistics out of the driver
*/
-static struct iw_statistics *get_wireless_stats(struct net_device *dev)
+struct iw_statistics *get_wireless_stats(struct net_device *dev)
{
/* New location */
if ((dev->wireless_handlers != NULL) &&
essid_compat = 1;
else if (IW_IS_SET(cmd) && (iwp->length != 0)) {
char essid[IW_ESSID_MAX_SIZE + 1];
+ unsigned int len;
+ len = iwp->length * descr->token_size;
- err = copy_from_user(essid, iwp->pointer,
- iwp->length *
- descr->token_size);
+ if (len > IW_ESSID_MAX_SIZE)
+ return -EFAULT;
+
+ err = copy_from_user(essid, iwp->pointer, len);
if (err)
return -EFAULT;
*/
static int x25_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
int opt;
struct sock *sk = sock->sk;
return -EPERM;
}
-static struct file_operations mark_ops = {
+static const struct file_operations mark_ops = {
.open = my_open,
};
return ima_show_htable_value(buf, count, ppos, &ima_htable.violations);
}
-static struct file_operations ima_htable_violations_ops = {
+static const struct file_operations ima_htable_violations_ops = {
.read = ima_show_htable_violations
};
}
-static struct file_operations ima_measurements_count_ops = {
+static const struct file_operations ima_measurements_count_ops = {
.read = ima_show_measurements_count
};
return seq_open(file, &ima_measurments_seqops);
}
-static struct file_operations ima_measurements_ops = {
+static const struct file_operations ima_measurements_ops = {
.open = ima_measurements_open,
.read = seq_read,
.llseek = seq_lseek,
return seq_open(file, &ima_ascii_measurements_seqops);
}
-static struct file_operations ima_ascii_measurements_ops = {
+static const struct file_operations ima_ascii_measurements_ops = {
.open = ima_ascii_measurements_open,
.read = seq_read,
.llseek = seq_lseek,
return 0;
}
-static struct file_operations ima_measure_policy_ops = {
+static const struct file_operations ima_measure_policy_ops = {
.open = ima_open_policy,
.write = ima_write_policy,
.release = ima_release_policy
DEFINE_SIMPLE_ATTRIBUTE(vcpu_stat_fops, vcpu_stat_get, NULL, "%llu\n");
-static struct file_operations *stat_fops[] = {
+static const struct file_operations *stat_fops[] = {
[KVM_STAT_VCPU] = &vcpu_stat_fops,
[KVM_STAT_VM] = &vm_stat_fops,
};