Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

FDDI: defxx: Implement dynamic CSR I/O address space selection

Recent versions of the PCI Express specification have deprecated support
for I/O transactions and actually some PCIe host bridges, such as Power
Systems Host Bridge 4 (PHB4), do not implement them. Conversely a DEFEA
adapter can have its MMIO decoding disabled with ECU (EISA Configuration
Utility) and therefore not available for us with the resource allocation
infrastructure we implement.

However either I/O address space will always be available for use with
the DEFEA (EISA) and DEFPA (PCI) adapters and both have double address
decoding implemented in hardware for Control and Status Register access.
The two kinds of adapters can be present both at once in a single mixed
PCI/EISA system. For the DEFTA (TURBOchannel) variant there is no issue
as there has been no port I/O address space defined for that bus.

To make people's life easier and the driver more robust remove the
DEFXX_MMIO configuration option so as to rather than making the choice
for the I/O address space to use at build time for all the adapters
installed in the system let the driver choose the most suitable address
space dynamically on a case-by-case basis at run time. Make MMIO the
default and resort to port I/O should the default fail for some reason.

This way multiple adapters installed in one system can use different I/O
address spaces each, in particular in the presence of DEFEA adapters in
a pure-EISA or a mixed EISA/PCI system (it is expected that DEFPA boards
will use MMIO in normal circumstances).

The choice of the I/O address space to use continues being reported by
the driver on startup, e.g.:

eisa 00:05: EISA: slot 5: DEC3002 detected
defxx: v1.12 2021/03/10 Lawrence V. Stefani and others
00:05: DEFEA at I/O addr = 0x5000, IRQ = 10, Hardware addr = 00-00-f8-c8-b3-b6
00:05: registered as fddi0

and:

defxx: v1.12 2021/03/10 Lawrence V. Stefani and others
0031:02:04.0: DEFPA at MMIO addr = 0x620c080020000, IRQ = 57, Hardware addr = 00-60-6d-93-91-98
0031:02:04.0: registered as fddi0

and:

defxx: v1.12 2021/03/10 Lawrence V. Stefani and others
tc2: DEFTA at MMIO addr = 0x1f100000, IRQ = 21, Hardware addr = 08-00-2b-b0-8b-1e
tc2: registered as fddi0

so there is no need to add further information.

The change is supposed to cause a negligible performance hit as I/O
accessors will now have code executed conditionally at run time.

Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Maciej W. Rozycki and committed by
David S. Miller
795e272e 193ced4a

+25 -57
-19
drivers/net/fddi/Kconfig
··· 38 38 To compile this driver as a module, choose M here: the module 39 39 will be called defxx. If unsure, say N. 40 40 41 - config DEFXX_MMIO 42 - bool 43 - prompt "Use MMIO instead of IOP" if PCI || EISA 44 - depends on DEFXX 45 - default n if EISA 46 - default y 47 - help 48 - This instructs the driver to use EISA or PCI memory-mapped I/O 49 - (MMIO) as appropriate instead of programmed I/O ports (IOP). 50 - Enabling this gives an improvement in processing time in parts 51 - of the driver, but it requires a memory window to be configured 52 - for EISA (DEFEA) adapters that may not always be available. 53 - Conversely some PCIe host bridges do not support IOP, so MMIO 54 - may be required to access PCI (DEFPA) adapters on downstream PCI 55 - buses with some systems. TURBOchannel does not have the concept 56 - of I/O ports, so MMIO is always used for these (DEFTA) adapters. 57 - 58 - If unsure, say N. 59 - 60 41 config SKFP 61 42 tristate "SysKonnect FDDI PCI support" 62 43 depends on FDDI && PCI
+22 -38
drivers/net/fddi/defxx.c
··· 197 197 * 23 Oct 2006 macro Big-endian host support. 198 198 * 14 Dec 2006 macro TURBOchannel support. 199 199 * 01 Jul 2014 macro Fixes for DMA on 64-bit hosts. 200 + * 10 Mar 2021 macro Dynamic MMIO vs port I/O. 200 201 */ 201 202 202 203 /* Include files */ ··· 226 225 227 226 /* Version information string should be updated prior to each new release! */ 228 227 #define DRV_NAME "defxx" 229 - #define DRV_VERSION "v1.11" 230 - #define DRV_RELDATE "2014/07/01" 228 + #define DRV_VERSION "v1.12" 229 + #define DRV_RELDATE "2021/03/10" 231 230 232 231 static const char version[] = 233 232 DRV_NAME ": " DRV_VERSION " " DRV_RELDATE ··· 254 253 #define DFX_BUS_TC(dev) 0 255 254 #endif 256 255 257 - #ifdef CONFIG_DEFXX_MMIO 258 - #define DFX_MMIO 1 256 + #if defined(CONFIG_EISA) || defined(CONFIG_PCI) 257 + #define dfx_use_mmio bp->mmio 259 258 #else 260 - #define DFX_MMIO 0 259 + #define dfx_use_mmio true 261 260 #endif 262 261 263 262 /* Define module-wide (static) routines */ ··· 375 374 static void dfx_port_write_long(DFX_board_t *bp, int offset, u32 data) 376 375 { 377 376 struct device __maybe_unused *bdev = bp->bus_dev; 378 - int dfx_bus_tc = DFX_BUS_TC(bdev); 379 - int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; 380 377 381 378 if (dfx_use_mmio) 382 379 dfx_writel(bp, offset, data); ··· 397 398 static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data) 398 399 { 399 400 struct device __maybe_unused *bdev = bp->bus_dev; 400 - int dfx_bus_tc = DFX_BUS_TC(bdev); 401 - int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; 402 401 403 402 if (dfx_use_mmio) 404 403 dfx_readl(bp, offset, data); ··· 418 421 * None 419 422 * 420 423 * Arguments: 421 - * bdev - pointer to device information 424 + * bp - pointer to board information 422 425 * bar_start - pointer to store the start addresses 423 426 * bar_len - pointer to store the lengths of the areas 424 427 * ··· 428 431 * Side Effects: 429 432 * None 430 433 */ 431 - static void dfx_get_bars(struct device *bdev, 434 + static void dfx_get_bars(DFX_board_t *bp, 432 435 resource_size_t *bar_start, resource_size_t *bar_len) 433 436 { 437 + struct device *bdev = bp->bus_dev; 434 438 int dfx_bus_pci = dev_is_pci(bdev); 435 439 int dfx_bus_eisa = DFX_BUS_EISA(bdev); 436 440 int dfx_bus_tc = DFX_BUS_TC(bdev); 437 - int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; 438 441 439 442 if (dfx_bus_pci) { 440 443 int num = dfx_use_mmio ? 0 : 1; ··· 492 495 .ndo_set_mac_address = dfx_ctl_set_mac_address, 493 496 }; 494 497 495 - static void dfx_register_res_alloc_err(const char *print_name, bool mmio, 496 - bool eisa) 497 - { 498 - pr_err("%s: Cannot use %s, no address set, aborting\n", 499 - print_name, mmio ? "MMIO" : "I/O"); 500 - pr_err("%s: Recompile driver with \"CONFIG_DEFXX_MMIO=%c\"\n", 501 - print_name, mmio ? 'n' : 'y'); 502 - if (eisa && mmio) 503 - pr_err("%s: Or run ECU and set adapter's MMIO location\n", 504 - print_name); 505 - } 506 - 507 498 static void dfx_register_res_err(const char *print_name, bool mmio, 508 499 unsigned long start, unsigned long len) 509 500 { ··· 532 547 static int version_disp; 533 548 int dfx_bus_pci = dev_is_pci(bdev); 534 549 int dfx_bus_eisa = DFX_BUS_EISA(bdev); 535 - int dfx_bus_tc = DFX_BUS_TC(bdev); 536 - int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; 537 550 const char *print_name = dev_name(bdev); 538 551 struct net_device *dev; 539 552 DFX_board_t *bp; /* board pointer */ ··· 569 586 bp->bus_dev = bdev; 570 587 dev_set_drvdata(bdev, dev); 571 588 572 - dfx_get_bars(bdev, bar_start, bar_len); 589 + bp->mmio = true; 590 + 591 + dfx_get_bars(bp, bar_start, bar_len); 573 592 if (bar_len[0] == 0 || 574 593 (dfx_bus_eisa && dfx_use_mmio && bar_start[0] == 0)) { 575 - dfx_register_res_alloc_err(print_name, dfx_use_mmio, 576 - dfx_bus_eisa); 577 - err = -ENXIO; 578 - goto err_out_disable; 594 + bp->mmio = false; 595 + dfx_get_bars(bp, bar_start, bar_len); 579 596 } 580 597 581 - if (dfx_use_mmio) 598 + if (dfx_use_mmio) { 582 599 region = request_mem_region(bar_start[0], bar_len[0], 583 600 print_name); 584 - else 601 + if (!region && (dfx_bus_eisa || dfx_bus_pci)) { 602 + bp->mmio = false; 603 + dfx_get_bars(bp, bar_start, bar_len); 604 + } 605 + } 606 + if (!dfx_use_mmio) 585 607 region = request_region(bar_start[0], bar_len[0], print_name); 586 608 if (!region) { 587 609 dfx_register_res_err(print_name, dfx_use_mmio, ··· 722 734 int dfx_bus_pci = dev_is_pci(bdev); 723 735 int dfx_bus_eisa = DFX_BUS_EISA(bdev); 724 736 int dfx_bus_tc = DFX_BUS_TC(bdev); 725 - int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; 726 737 u8 val; 727 738 728 739 DBG_printk("In dfx_bus_init...\n"); ··· 1041 1054 int dfx_bus_pci = dev_is_pci(bdev); 1042 1055 int dfx_bus_eisa = DFX_BUS_EISA(bdev); 1043 1056 int dfx_bus_tc = DFX_BUS_TC(bdev); 1044 - int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; 1045 1057 int alloc_size; /* total buffer size needed */ 1046 1058 char *top_v, *curr_v; /* virtual addrs into memory block */ 1047 1059 dma_addr_t top_p, curr_p; /* physical addrs into memory block */ ··· 3694 3708 struct net_device *dev = dev_get_drvdata(bdev); 3695 3709 DFX_board_t *bp = netdev_priv(dev); 3696 3710 int dfx_bus_pci = dev_is_pci(bdev); 3697 - int dfx_bus_tc = DFX_BUS_TC(bdev); 3698 - int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; 3699 3711 resource_size_t bar_start[3] = {0}; /* pointers to ports */ 3700 3712 resource_size_t bar_len[3] = {0}; /* resource lengths */ 3701 3713 int alloc_size; /* total buffer size used */ ··· 3713 3729 3714 3730 dfx_bus_uninit(dev); 3715 3731 3716 - dfx_get_bars(bdev, bar_start, bar_len); 3732 + dfx_get_bars(bp, bar_start, bar_len); 3717 3733 if (bar_start[2] != 0) 3718 3734 release_region(bar_start[2], bar_len[2]); 3719 3735 if (bar_start[1] != 0)
+3
drivers/net/fddi/defxx.h
··· 27 27 * 04 Aug 2003 macro Converted to the DMA API. 28 28 * 23 Oct 2006 macro Big-endian host support. 29 29 * 14 Dec 2006 macro TURBOchannel support. 30 + * 10 Mar 2021 macro Dynamic MMIO vs port I/O. 30 31 */ 31 32 32 33 #ifndef _DEFXX_H_ ··· 1777 1776 int port; 1778 1777 } base; /* base address */ 1779 1778 struct device *bus_dev; 1779 + /* Whether to use MMIO or port I/O. */ 1780 + bool mmio; 1780 1781 u32 full_duplex_enb; /* FDDI Full Duplex enable (1 == on, 2 == off) */ 1781 1782 u32 req_ttrt; /* requested TTRT value (in 80ns units) */ 1782 1783 u32 burst_size; /* adapter burst size (enumerated) */