summaryrefslogtreecommitdiff
path: root/drivers/net/fddi/defxx.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-11 14:27:06 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-11 14:27:06 -0800
commit70e71ca0af244f48a5dcf56dc435243792e3a495 (patch)
treef7d9c4c4d9a857a00043e9bf6aa2d6f533a34778 /drivers/net/fddi/defxx.c
parentbae41e45b7400496b9bf0c70c6004419d9987819 (diff)
parent00c83b01d58068dfeb2e1351cca6fccf2a83fa8f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: 1) New offloading infrastructure and example 'rocker' driver for offloading of switching and routing to hardware. This work was done by a large group of dedicated individuals, not limited to: Scott Feldman, Jiri Pirko, Thomas Graf, John Fastabend, Jamal Hadi Salim, Andy Gospodarek, Florian Fainelli, Roopa Prabhu 2) Start making the networking operate on IOV iterators instead of modifying iov objects in-situ during transfers. Thanks to Al Viro and Herbert Xu. 3) A set of new netlink interfaces for the TIPC stack, from Richard Alpe. 4) Remove unnecessary looping during ipv6 routing lookups, from Martin KaFai Lau. 5) Add PAUSE frame generation support to gianfar driver, from Matei Pavaluca. 6) Allow for larger reordering levels in TCP, which are easily achievable in the real world right now, from Eric Dumazet. 7) Add a variable of napi_schedule that doesn't need to disable cpu interrupts, from Eric Dumazet. 8) Use a doubly linked list to optimize neigh_parms_release(), from Nicolas Dichtel. 9) Various enhancements to the kernel BPF verifier, and allow eBPF programs to actually be attached to sockets. From Alexei Starovoitov. 10) Support TSO/LSO in sunvnet driver, from David L Stevens. 11) Allow controlling ECN usage via routing metrics, from Florian Westphal. 12) Remote checksum offload, from Tom Herbert. 13) Add split-header receive, BQL, and xmit_more support to amd-xgbe driver, from Thomas Lendacky. 14) Add MPLS support to openvswitch, from Simon Horman. 15) Support wildcard tunnel endpoints in ipv6 tunnels, from Steffen Klassert. 16) Do gro flushes on a per-device basis using a timer, from Eric Dumazet. This tries to resolve the conflicting goals between the desired handling of bulk vs. RPC-like traffic. 17) Allow userspace to ask for the CPU upon what a packet was received/steered, via SO_INCOMING_CPU. From Eric Dumazet. 18) Limit GSO packets to half the current congestion window, from Eric Dumazet. 19) Add a generic helper so that all drivers set their RSS keys in a consistent way, from Eric Dumazet. 20) Add xmit_more support to enic driver, from Govindarajulu Varadarajan. 21) Add VLAN packet scheduler action, from Jiri Pirko. 22) Support configurable RSS hash functions via ethtool, from Eyal Perry. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1820 commits) Fix race condition between vxlan_sock_add and vxlan_sock_release net/macb: fix compilation warning for print_hex_dump() called with skb->mac_header net/mlx4: Add support for A0 steering net/mlx4: Refactor QUERY_PORT net/mlx4_core: Add explicit error message when rule doesn't meet configuration net/mlx4: Add A0 hybrid steering net/mlx4: Add mlx4_bitmap zone allocator net/mlx4: Add a check if there are too many reserved QPs net/mlx4: Change QP allocation scheme net/mlx4_core: Use tasklet for user-space CQ completion events net/mlx4_core: Mask out host side virtualization features for guests net/mlx4_en: Set csum level for encapsulated packets be2net: Export tunnel offloads only when a VxLAN tunnel is created gianfar: Fix dma check map error when DMA_API_DEBUG is enabled cxgb4/csiostor: Don't use MASTER_MUST for fw_hello call net: fec: only enable mdio interrupt before phy device link up net: fec: clear all interrupt events to support i.MX6SX net: fec: reset fep link status in suspend function net: sock: fix access via invalid file descriptor net: introduce helper macro for_each_cmsghdr ...
Diffstat (limited to 'drivers/net/fddi/defxx.c')
-rw-r--r--drivers/net/fddi/defxx.c187
1 files changed, 126 insertions, 61 deletions
diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c
index caed6eee289c..7f975a2c8990 100644
--- a/drivers/net/fddi/defxx.c
+++ b/drivers/net/fddi/defxx.c
@@ -414,7 +414,7 @@ static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data)
* ================
*
* Overview:
- * Retrieves the address range used to access control and status
+ * Retrieves the address ranges used to access control and status
* registers.
*
* Returns:
@@ -422,8 +422,8 @@ static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data)
*
* Arguments:
* bdev - pointer to device information
- * bar_start - pointer to store the start address
- * bar_len - pointer to store the length of the area
+ * bar_start - pointer to store the start addresses
+ * bar_len - pointer to store the lengths of the areas
*
* Assumptions:
* I am sure there are some.
@@ -442,38 +442,47 @@ static void dfx_get_bars(struct device *bdev,
if (dfx_bus_pci) {
int num = dfx_use_mmio ? 0 : 1;
- *bar_start = pci_resource_start(to_pci_dev(bdev), num);
- *bar_len = pci_resource_len(to_pci_dev(bdev), num);
+ bar_start[0] = pci_resource_start(to_pci_dev(bdev), num);
+ bar_len[0] = pci_resource_len(to_pci_dev(bdev), num);
+ bar_start[2] = bar_start[1] = 0;
+ bar_len[2] = bar_len[1] = 0;
}
if (dfx_bus_eisa) {
unsigned long base_addr = to_eisa_device(bdev)->base_addr;
- resource_size_t bar;
+ resource_size_t bar_lo;
+ resource_size_t bar_hi;
if (dfx_use_mmio) {
- bar = inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_2);
- bar <<= 8;
- bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_1);
- bar <<= 8;
- bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_0);
- bar <<= 16;
- *bar_start = bar;
- bar = inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_2);
- bar <<= 8;
- bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_1);
- bar <<= 8;
- bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_0);
- bar <<= 16;
- *bar_len = (bar | PI_MEM_ADD_MASK_M) + 1;
+ bar_lo = inb(base_addr + PI_ESIC_K_MEM_ADD_LO_CMP_2);
+ bar_lo <<= 8;
+ bar_lo |= inb(base_addr + PI_ESIC_K_MEM_ADD_LO_CMP_1);
+ bar_lo <<= 8;
+ bar_lo |= inb(base_addr + PI_ESIC_K_MEM_ADD_LO_CMP_0);
+ bar_lo <<= 8;
+ bar_start[0] = bar_lo;
+ bar_hi = inb(base_addr + PI_ESIC_K_MEM_ADD_HI_CMP_2);
+ bar_hi <<= 8;
+ bar_hi |= inb(base_addr + PI_ESIC_K_MEM_ADD_HI_CMP_1);
+ bar_hi <<= 8;
+ bar_hi |= inb(base_addr + PI_ESIC_K_MEM_ADD_HI_CMP_0);
+ bar_hi <<= 8;
+ bar_len[0] = ((bar_hi - bar_lo) | PI_MEM_ADD_MASK_M) +
+ 1;
} else {
- *bar_start = base_addr;
- *bar_len = PI_ESIC_K_CSR_IO_LEN +
- PI_ESIC_K_BURST_HOLDOFF_LEN;
+ bar_start[0] = base_addr;
+ bar_len[0] = PI_ESIC_K_CSR_IO_LEN;
}
+ bar_start[1] = base_addr + PI_DEFEA_K_BURST_HOLDOFF;
+ bar_len[1] = PI_ESIC_K_BURST_HOLDOFF_LEN;
+ bar_start[2] = base_addr + PI_ESIC_K_ESIC_CSR;
+ bar_len[2] = PI_ESIC_K_ESIC_CSR_LEN;
}
if (dfx_bus_tc) {
- *bar_start = to_tc_dev(bdev)->resource.start +
- PI_TC_K_CSR_OFFSET;
- *bar_len = PI_TC_K_CSR_LEN;
+ bar_start[0] = to_tc_dev(bdev)->resource.start +
+ PI_TC_K_CSR_OFFSET;
+ bar_len[0] = PI_TC_K_CSR_LEN;
+ bar_start[2] = bar_start[1] = 0;
+ bar_len[2] = bar_len[1] = 0;
}
}
@@ -518,13 +527,14 @@ static int dfx_register(struct device *bdev)
{
static int version_disp;
int dfx_bus_pci = dev_is_pci(bdev);
+ int dfx_bus_eisa = DFX_BUS_EISA(bdev);
int dfx_bus_tc = DFX_BUS_TC(bdev);
int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
const char *print_name = dev_name(bdev);
struct net_device *dev;
DFX_board_t *bp; /* board pointer */
- resource_size_t bar_start = 0; /* pointer to port */
- resource_size_t bar_len = 0; /* resource length */
+ resource_size_t bar_start[3]; /* pointers to ports */
+ resource_size_t bar_len[3]; /* resource length */
int alloc_size; /* total buffer size used */
struct resource *region;
int err = 0;
@@ -542,10 +552,13 @@ static int dfx_register(struct device *bdev)
}
/* Enable PCI device. */
- if (dfx_bus_pci && pci_enable_device(to_pci_dev(bdev))) {
- printk(KERN_ERR "%s: Cannot enable PCI device, aborting\n",
- print_name);
- goto err_out;
+ if (dfx_bus_pci) {
+ err = pci_enable_device(to_pci_dev(bdev));
+ if (err) {
+ pr_err("%s: Cannot enable PCI device, aborting\n",
+ print_name);
+ goto err_out;
+ }
}
SET_NETDEV_DEV(dev, bdev);
@@ -554,31 +567,62 @@ static int dfx_register(struct device *bdev)
bp->bus_dev = bdev;
dev_set_drvdata(bdev, dev);
- dfx_get_bars(bdev, &bar_start, &bar_len);
+ dfx_get_bars(bdev, bar_start, bar_len);
+ if (dfx_bus_eisa && dfx_use_mmio && bar_start[0] == 0) {
+ pr_err("%s: Cannot use MMIO, no address set, aborting\n",
+ print_name);
+ pr_err("%s: Run ECU and set adapter's MMIO location\n",
+ print_name);
+ pr_err("%s: Or recompile driver with \"CONFIG_DEFXX_MMIO=n\""
+ "\n", print_name);
+ err = -ENXIO;
+ goto err_out;
+ }
if (dfx_use_mmio)
- region = request_mem_region(bar_start, bar_len, print_name);
+ region = request_mem_region(bar_start[0], bar_len[0],
+ print_name);
else
- region = request_region(bar_start, bar_len, print_name);
+ region = request_region(bar_start[0], bar_len[0], print_name);
if (!region) {
- printk(KERN_ERR "%s: Cannot reserve I/O resource "
- "0x%lx @ 0x%lx, aborting\n",
- print_name, (long)bar_len, (long)bar_start);
+ pr_err("%s: Cannot reserve %s resource 0x%lx @ 0x%lx, "
+ "aborting\n", dfx_use_mmio ? "MMIO" : "I/O", print_name,
+ (long)bar_len[0], (long)bar_start[0]);
err = -EBUSY;
goto err_out_disable;
}
+ if (bar_start[1] != 0) {
+ region = request_region(bar_start[1], bar_len[1], print_name);
+ if (!region) {
+ pr_err("%s: Cannot reserve I/O resource "
+ "0x%lx @ 0x%lx, aborting\n", print_name,
+ (long)bar_len[1], (long)bar_start[1]);
+ err = -EBUSY;
+ goto err_out_csr_region;
+ }
+ }
+ if (bar_start[2] != 0) {
+ region = request_region(bar_start[2], bar_len[2], print_name);
+ if (!region) {
+ pr_err("%s: Cannot reserve I/O resource "
+ "0x%lx @ 0x%lx, aborting\n", print_name,
+ (long)bar_len[2], (long)bar_start[2]);
+ err = -EBUSY;
+ goto err_out_bh_region;
+ }
+ }
/* Set up I/O base address. */
if (dfx_use_mmio) {
- bp->base.mem = ioremap_nocache(bar_start, bar_len);
+ bp->base.mem = ioremap_nocache(bar_start[0], bar_len[0]);
if (!bp->base.mem) {
printk(KERN_ERR "%s: Cannot map MMIO\n", print_name);
err = -ENOMEM;
- goto err_out_region;
+ goto err_out_esic_region;
}
} else {
- bp->base.port = bar_start;
- dev->base_addr = bar_start;
+ bp->base.port = bar_start[0];
+ dev->base_addr = bar_start[0];
}
/* Initialize new device structure */
@@ -587,7 +631,7 @@ static int dfx_register(struct device *bdev)
if (dfx_bus_pci)
pci_set_master(to_pci_dev(bdev));
- if (dfx_driver_init(dev, print_name, bar_start) != DFX_K_SUCCESS) {
+ if (dfx_driver_init(dev, print_name, bar_start[0]) != DFX_K_SUCCESS) {
err = -ENODEV;
goto err_out_unmap;
}
@@ -615,11 +659,19 @@ err_out_unmap:
if (dfx_use_mmio)
iounmap(bp->base.mem);
-err_out_region:
+err_out_esic_region:
+ if (bar_start[2] != 0)
+ release_region(bar_start[2], bar_len[2]);
+
+err_out_bh_region:
+ if (bar_start[1] != 0)
+ release_region(bar_start[1], bar_len[1]);
+
+err_out_csr_region:
if (dfx_use_mmio)
- release_mem_region(bar_start, bar_len);
+ release_mem_region(bar_start[0], bar_len[0]);
else
- release_region(bar_start, bar_len);
+ release_region(bar_start[0], bar_len[0]);
err_out_disable:
if (dfx_bus_pci)
@@ -711,13 +763,14 @@ static void dfx_bus_init(struct net_device *dev)
}
/*
- * Enable memory decoding (MEMCS0) and/or port decoding
+ * Enable memory decoding (MEMCS1) and/or port decoding
* (IOCS1/IOCS0) as appropriate in Function Control
- * Register. IOCS0 is used for PDQ registers, taking 16
- * 32-bit words, while IOCS1 is used for the Burst Holdoff
- * register, taking a single 32-bit word only. We use the
- * slot-specific I/O range as per the ESIC spec, that is
- * set bits 15:12 in the mask registers to mask them out.
+ * Register. MEMCS1 or IOCS0 is used for PDQ registers,
+ * taking 16 32-bit words, while IOCS1 is used for the
+ * Burst Holdoff register, taking a single 32-bit word
+ * only. We use the slot-specific I/O range as per the
+ * ESIC spec, that is set bits 15:12 in the mask registers
+ * to mask them out.
*/
/* Set the decode range of the board. */
@@ -742,9 +795,11 @@ static void dfx_bus_init(struct net_device *dev)
outb(val, base_addr + PI_ESIC_K_IO_ADD_MASK_1_0);
/* Enable the decoders. */
- val = PI_FUNCTION_CNTRL_M_IOCS1 | PI_FUNCTION_CNTRL_M_IOCS0;
+ val = PI_FUNCTION_CNTRL_M_IOCS1;
if (dfx_use_mmio)
- val |= PI_FUNCTION_CNTRL_M_MEMCS0;
+ val |= PI_FUNCTION_CNTRL_M_MEMCS1;
+ else
+ val |= PI_FUNCTION_CNTRL_M_IOCS0;
outb(val, base_addr + PI_ESIC_K_FUNCTION_CNTRL);
/*
@@ -838,6 +893,12 @@ static void dfx_bus_uninit(struct net_device *dev)
val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
val &= ~PI_CONFIG_STAT_0_M_INT_ENB;
outb(val, base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
+
+ /* Disable the board. */
+ outb(0, base_addr + PI_ESIC_K_SLOT_CNTRL);
+
+ /* Disable memory and port decoders. */
+ outb(0, base_addr + PI_ESIC_K_FUNCTION_CNTRL);
}
if (dfx_bus_pci) {
/* Disable interrupts at PCI bus interface chip (PFI) */
@@ -1061,8 +1122,8 @@ static int dfx_driver_init(struct net_device *dev, const char *print_name,
board_name = "DEFEA";
if (dfx_bus_pci)
board_name = "DEFPA";
- pr_info("%s: %s at %saddr = 0x%llx, IRQ = %d, Hardware addr = %pMF\n",
- print_name, board_name, dfx_use_mmio ? "" : "I/O ",
+ pr_info("%s: %s at %s addr = 0x%llx, IRQ = %d, Hardware addr = %pMF\n",
+ print_name, board_name, dfx_use_mmio ? "MMIO" : "I/O",
(long long)bar_start, dev->irq, dev->dev_addr);
/*
@@ -3636,8 +3697,8 @@ static void dfx_unregister(struct device *bdev)
int dfx_bus_pci = dev_is_pci(bdev);
int dfx_bus_tc = DFX_BUS_TC(bdev);
int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
- resource_size_t bar_start = 0; /* pointer to port */
- resource_size_t bar_len = 0; /* resource length */
+ resource_size_t bar_start[3]; /* pointers to ports */
+ resource_size_t bar_len[3]; /* resource lengths */
int alloc_size; /* total buffer size used */
unregister_netdev(dev);
@@ -3655,12 +3716,16 @@ static void dfx_unregister(struct device *bdev)
dfx_bus_uninit(dev);
- dfx_get_bars(bdev, &bar_start, &bar_len);
+ dfx_get_bars(bdev, bar_start, bar_len);
+ if (bar_start[2] != 0)
+ release_region(bar_start[2], bar_len[2]);
+ if (bar_start[1] != 0)
+ release_region(bar_start[1], bar_len[1]);
if (dfx_use_mmio) {
iounmap(bp->base.mem);
- release_mem_region(bar_start, bar_len);
+ release_mem_region(bar_start[0], bar_len[0]);
} else
- release_region(bar_start, bar_len);
+ release_region(bar_start[0], bar_len[0]);
if (dfx_bus_pci)
pci_disable_device(to_pci_dev(bdev));