Re: [Patch v2] wd719x: pass GFP_ATOMIC instead of GFP_KERNEL linux-ker...@vger.kernel.org
On Thursday 30 May 2019 20:10:44 Hariprasad Kelam wrote: > On Wed, May 29, 2019 at 02:13:18PM -0700, David Rientjes wrote: > > On Wed, 29 May 2019, Hariprasad Kelam wrote: > > > > > dont acquire lock before calling wd719x_chip_init. > > > > > > Issue identified by coccicheck > > > > > > Signed-off-by: Hariprasad Kelam > > > - > > > changes in v1: Replace GFP_KERNEL with GFP_ATOMIC. > > > changes in v2: Call wd719x_chip_init without lock as suggested > > > in review > > > > Why was host_lock taken here initially? I assume it's to protect some > > race in init that leads to an undefined state. > > wd719x_chip_init is getting called from wd719x_host_reset > and wd719x_board_found. > > In wd719x_board_found case its not acquiring any lock. > In wd719x_host_reset it is called under spin_lock. > > Acquiring spin_lock in wd719x_host_reset is there from initial commit > so its better we wont remove this lock. Looks like I haven't tested it properly before. Host reset is broken - sg_reset -N -H /dev/sdX will oops: wd719x :02:01.0: host reset requested [ cut here ] kernel BUG at fs/buffer.c:1218! invalid opcode: [#1] SMP CPU: 0 PID: 1913 Comm: sg_reset Not tainted 5.1.0+ #323 Hardware name: /848P-ICH5, BIOS 6.00 PG 02/03/2005 EIP: check_irqs_on+0xb/0xf ... That's because of request_firmware called under the spin lock, as Christoph pointed out. Patch v2 is also wrong - wd719x_finish_cmd must be called under lock. I'm currently testing a proper fix (disable chip and flush SCBs under lock, then initialize chip without lock). It works mostly but I can crash it easily by doing a device reset under load (e.g. dd from a SCSI drive) and then doing a host reset - NULL pointer dereference in list_del. > I think we Patch v1 is correct fix(pass GFP_ATOMIC instead of GPF_KERNEL ) > > -- Ondrej Zary
[PATCH 1/4 v2] fdomain: Resurrect driver (core)
Future Domain TMC-16xx/TMC-3260 SCSI driver. This is the core driver, common for PCI, ISA and PCMCIA cards. Signed-off-by: Ondrej Zary --- Changes in v2: - fdomain_reset marked static --- drivers/scsi/Kconfig | 4 + drivers/scsi/Makefile | 1 + drivers/scsi/fdomain.c | 600 + drivers/scsi/fdomain.h | 63 ++ 4 files changed, 668 insertions(+) create mode 100644 drivers/scsi/fdomain.c create mode 100644 drivers/scsi/fdomain.h diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index d528018e6fa8..3d6b1f47cbb5 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -663,6 +663,10 @@ config SCSI_DMX3191D To compile this driver as a module, choose M here: the module will be called dmx3191d. +config SCSI_FDOMAIN + tristate + depends on SCSI + config SCSI_GDTH tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support" depends on PCI && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 8826111fdf4a..b8fbc6d2de54 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_SCSI_AIC94XX)+= aic94xx/ obj-$(CONFIG_SCSI_PM8001) += pm8001/ obj-$(CONFIG_SCSI_ISCI)+= isci/ obj-$(CONFIG_SCSI_IPS) += ips.o +obj-$(CONFIG_SCSI_FDOMAIN) += fdomain.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o obj-$(CONFIG_PCMCIA_QLOGIC)+= qlogicfas408.o diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c new file mode 100644 index ..e43fdd1ab3a8 --- /dev/null +++ b/drivers/scsi/fdomain.c @@ -0,0 +1,600 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Future Domain TMC-16x0 and TMC-3260 SCSI host adapters + * Copyright 2019 Ondrej Zary + * + * Original driver by + * Rickard E. Faith, fa...@cs.unc.edu + * + * Future Domain BIOS versions supported for autodetect: + *2.0, 3.0, 3.2, 3.4 (1.0), 3.5 (2.0), 3.6, 3.61 + * Chips supported: + *TMC-1800, TMC-18C50, TMC-18C30, TMC-36C70 + * Boards supported: + *Future Domain TMC-1650, TMC-1660, TMC-1670, TMC-1680, TMC-1610M/MER/MEX + *Future Domain TMC-3260 (PCI) + *Quantum ISA-200S, ISA-250MG + *Adaptec AHA-2920A (PCI) [BUT *NOT* AHA-2920C -- use aic7xxx instead] + *IBM ? + * + * NOTE: + * + * The Adaptec AHA-2920C has an Adaptec AIC-7850 chip on it. + * Use the aic7xxx driver for this board. + * + * The Adaptec AHA-2920A has a Future Domain chip on it, so this is the right + * driver for that card. Unfortunately, the boxes will probably just say + * "2920", so you'll have to look on the card for a Future Domain logo, or a + * letter after the 2920. + * + * If you have a TMC-8xx or TMC-9xx board, then this is not the driver for + * your board. + * + * DESCRIPTION: + * + * This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680 + * TMC-1650/1670, and TMC-3260 SCSI host adapters. The 1650 and 1670 have a + * 25-pin external connector, whereas the 1660 and 1680 have a SCSI-2 50-pin + * high-density external connector. The 1670 and 1680 have floppy disk + * controllers built in. The TMC-3260 is a PCI bus card. + * + * Future Domain's older boards are based on the TMC-1800 chip, and this + * driver was originally written for a TMC-1680 board with the TMC-1800 chip. + * More recently, boards are being produced with the TMC-18C50 and TMC-18C30 + * chips. + * + * Please note that the drive ordering that Future Domain implemented in BIOS + * versions 3.4 and 3.5 is the opposite of the order (currently) used by the + * rest of the SCSI industry. + * + * + * REFERENCES USED: + * + * "TMC-1800 SCSI Chip Specification (FDC-1800T)", Future Domain Corporation, + * 1990. + * + * "Technical Reference Manual: 18C50 SCSI Host Adapter Chip", Future Domain + * Corporation, January 1992. + * + * "LXT SCSI Products: Specifications and OEM Technical Manual (Revision + * B/September 1991)", Maxtor Corporation, 1991. + * + * "7213S product Manual (Revision P3)", Maxtor Corporation, 1992. + * + * "Draft Proposed American National Standard: Small Computer System + * Interface - 2 (SCSI-2)", Global Engineering Documents. (X3T9.2/86-109, + * revision 10h, October 17, 1991) + * + * Private communications, Drew Eckhardt (d...@cs.colorado.edu) and Eric + * Youngdale (er...@cais.com), 1992. + * + * Private communication, Tuong Le (Future Domain Engineering department), + * 1994. (Disk geometry computations for Future Domain BIOS version 3.4, and + * TMC-18C30 detection.) + * + * Hogan, Thom. The Programmer's PC Sourcebook. Microsoft Press, 1988. Page + * 60 (2.39: Disk Partition Table Layout). + * + * "18C30 Technical Reference Manual", Future Domain Corporation, 1993, page + * 6-1. + */ + +#include +#include +#include +#include +#include +
[PATCH 1/4] fdomain: Resurrect driver (core)
Future Domain TMC-16xx/TMC-3260 SCSI driver. This is the core driver, common for PCI, ISA and PCMCIA cards. Signed-off-by: Ondrej Zary --- drivers/scsi/Kconfig | 4 + drivers/scsi/Makefile | 1 + drivers/scsi/fdomain.c | 600 + drivers/scsi/fdomain.h | 63 ++ 4 files changed, 668 insertions(+) create mode 100644 drivers/scsi/fdomain.c create mode 100644 drivers/scsi/fdomain.h diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index d528018e6fa8..3d6b1f47cbb5 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -663,6 +663,10 @@ config SCSI_DMX3191D To compile this driver as a module, choose M here: the module will be called dmx3191d. +config SCSI_FDOMAIN + tristate + depends on SCSI + config SCSI_GDTH tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support" depends on PCI && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 8826111fdf4a..b8fbc6d2de54 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_SCSI_AIC94XX)+= aic94xx/ obj-$(CONFIG_SCSI_PM8001) += pm8001/ obj-$(CONFIG_SCSI_ISCI)+= isci/ obj-$(CONFIG_SCSI_IPS) += ips.o +obj-$(CONFIG_SCSI_FDOMAIN) += fdomain.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o obj-$(CONFIG_PCMCIA_QLOGIC)+= qlogicfas408.o diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c new file mode 100644 index ..edf75c7f8e3f --- /dev/null +++ b/drivers/scsi/fdomain.c @@ -0,0 +1,600 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Future Domain TMC-16x0 and TMC-3260 SCSI host adapters + * Copyright 2019 Ondrej Zary + * + * Original driver by + * Rickard E. Faith, fa...@cs.unc.edu + * + * Future Domain BIOS versions supported for autodetect: + *2.0, 3.0, 3.2, 3.4 (1.0), 3.5 (2.0), 3.6, 3.61 + * Chips supported: + *TMC-1800, TMC-18C50, TMC-18C30, TMC-36C70 + * Boards supported: + *Future Domain TMC-1650, TMC-1660, TMC-1670, TMC-1680, TMC-1610M/MER/MEX + *Future Domain TMC-3260 (PCI) + *Quantum ISA-200S, ISA-250MG + *Adaptec AHA-2920A (PCI) [BUT *NOT* AHA-2920C -- use aic7xxx instead] + *IBM ? + * + * NOTE: + * + * The Adaptec AHA-2920C has an Adaptec AIC-7850 chip on it. + * Use the aic7xxx driver for this board. + * + * The Adaptec AHA-2920A has a Future Domain chip on it, so this is the right + * driver for that card. Unfortunately, the boxes will probably just say + * "2920", so you'll have to look on the card for a Future Domain logo, or a + * letter after the 2920. + * + * If you have a TMC-8xx or TMC-9xx board, then this is not the driver for + * your board. + * + * DESCRIPTION: + * + * This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680 + * TMC-1650/1670, and TMC-3260 SCSI host adapters. The 1650 and 1670 have a + * 25-pin external connector, whereas the 1660 and 1680 have a SCSI-2 50-pin + * high-density external connector. The 1670 and 1680 have floppy disk + * controllers built in. The TMC-3260 is a PCI bus card. + * + * Future Domain's older boards are based on the TMC-1800 chip, and this + * driver was originally written for a TMC-1680 board with the TMC-1800 chip. + * More recently, boards are being produced with the TMC-18C50 and TMC-18C30 + * chips. + * + * Please note that the drive ordering that Future Domain implemented in BIOS + * versions 3.4 and 3.5 is the opposite of the order (currently) used by the + * rest of the SCSI industry. + * + * + * REFERENCES USED: + * + * "TMC-1800 SCSI Chip Specification (FDC-1800T)", Future Domain Corporation, + * 1990. + * + * "Technical Reference Manual: 18C50 SCSI Host Adapter Chip", Future Domain + * Corporation, January 1992. + * + * "LXT SCSI Products: Specifications and OEM Technical Manual (Revision + * B/September 1991)", Maxtor Corporation, 1991. + * + * "7213S product Manual (Revision P3)", Maxtor Corporation, 1992. + * + * "Draft Proposed American National Standard: Small Computer System + * Interface - 2 (SCSI-2)", Global Engineering Documents. (X3T9.2/86-109, + * revision 10h, October 17, 1991) + * + * Private communications, Drew Eckhardt (d...@cs.colorado.edu) and Eric + * Youngdale (er...@cais.com), 1992. + * + * Private communication, Tuong Le (Future Domain Engineering department), + * 1994. (Disk geometry computations for Future Domain BIOS version 3.4, and + * TMC-18C30 detection.) + * + * Hogan, Thom. The Programmer's PC Sourcebook. Microsoft Press, 1988. Page + * 60 (2.39: Disk Partition Table Layout). + * + * "18C30 Technical Reference Manual", Future Domain Corporation, 1993, page + * 6-1. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +
[PATCH 4/4] fdomain: Resurrect driver (PCMCIA support)
Future Domain PCMCIA SCSI support card support. Currently untested. Signed-off-by: Ondrej Zary --- drivers/scsi/pcmcia/Kconfig | 10 + drivers/scsi/pcmcia/Makefile | 1 + drivers/scsi/pcmcia/fdomain_cs.c | 89 3 files changed, 100 insertions(+) create mode 100644 drivers/scsi/pcmcia/fdomain_cs.c diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig index 2d435f105b16..169d93f90a30 100644 --- a/drivers/scsi/pcmcia/Kconfig +++ b/drivers/scsi/pcmcia/Kconfig @@ -19,6 +19,16 @@ config PCMCIA_AHA152X To compile this driver as a module, choose M here: the module will be called aha152x_cs. +config PCMCIA_FDOMAIN + tristate "Future Domain PCMCIA support" + select SCSI_FDOMAIN + help + Say Y here if you intend to attach this type of PCMCIA SCSI host + adapter to your computer. + + To compile this driver as a module, choose M here: the + module will be called fdomain_cs. + config PCMCIA_NINJA_SCSI tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support" depends on !64BIT diff --git a/drivers/scsi/pcmcia/Makefile b/drivers/scsi/pcmcia/Makefile index a5a24dd44e7e..02f5b44a2685 100644 --- a/drivers/scsi/pcmcia/Makefile +++ b/drivers/scsi/pcmcia/Makefile @@ -4,6 +4,7 @@ ccflags-y := -I $(srctree)/drivers/scsi # 16-bit client drivers obj-$(CONFIG_PCMCIA_QLOGIC)+= qlogic_cs.o +obj-$(CONFIG_PCMCIA_FDOMAIN) += fdomain_cs.o obj-$(CONFIG_PCMCIA_AHA152X) += aha152x_cs.o obj-$(CONFIG_PCMCIA_NINJA_SCSI)+= nsp_cs.o obj-$(CONFIG_PCMCIA_SYM53C500) += sym53c500_cs.o diff --git a/drivers/scsi/pcmcia/fdomain_cs.c b/drivers/scsi/pcmcia/fdomain_cs.c new file mode 100644 index ..eee1379ad67b --- /dev/null +++ b/drivers/scsi/pcmcia/fdomain_cs.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) +/* + * Driver for Future Domain-compatible PCMCIA SCSI cards + * Copyright 2019 Ondrej Zary + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include "fdomain.h" + +MODULE_AUTHOR("Ondrej Zary, David Hinds"); +MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver"); +MODULE_LICENSE("Dual MPL/GPL"); + +static int fdomain_config_check(struct pcmcia_device *p_dev, void *priv_data) +{ + p_dev->io_lines = 10; + p_dev->resource[0]->end = 0x10; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; + return pcmcia_request_io(p_dev); +} + +static int fdomain_probe(struct pcmcia_device *link) +{ + int ret; + struct Scsi_Host *sh; + + link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; + link->config_regs = PRESENT_OPTION; + + ret = pcmcia_loop_config(link, fdomain_config_check, NULL); + if (ret) + return ret; + + ret = pcmcia_enable_device(link); + if (ret) + goto fail; + + sh = fdomain_create(link->resource[0]->start, link->irq, 7, 0, NULL, + &link->dev); + if (!sh) { + dev_err(&link->dev, "Controller initialization failed"); + ret = -ENODEV; + goto fail; + } + + link->priv = sh; + + return 0; + +fail: + pcmcia_disable_device(link); + return ret; +} + +static void fdomain_remove(struct pcmcia_device *link) +{ + fdomain_destroy(link->priv); + pcmcia_disable_device(link); +} + +static const struct pcmcia_device_id fdomain_ids[] = { + PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "SCSI PCMCIA Card", 0xe3736c88, + 0x859cad20), + PCMCIA_DEVICE_PROD_ID1("SCSI PCMCIA Adapter Card", 0x8dacb57e), + PCMCIA_DEVICE_PROD_ID12(" SIMPLE TECHNOLOGY Corporation", + "SCSI PCMCIA Credit Card Controller", + 0x182bdafe, 0xc80d106f), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, fdomain_ids); + +static struct pcmcia_driver fdomain_cs_driver = { + .owner = THIS_MODULE, + .name = "fdomain_cs", + .probe = fdomain_probe, + .remove = fdomain_remove, + .id_table = fdomain_ids, +}; + +module_pcmcia_driver(fdomain_cs_driver); -- Ondrej Zary
[PATCH 2/4] fdomain: Resurrect driver (PCI support)
Future Domain TMC-3260/AHA-2920A PCI card support. Tested on Adaptec AHA-2920A PCI card. Signed-off-by: Ondrej Zary --- drivers/scsi/Kconfig | 17 drivers/scsi/Makefile | 1 + drivers/scsi/fdomain_pci.c | 68 ++ 3 files changed, 86 insertions(+) create mode 100644 drivers/scsi/fdomain_pci.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 3d6b1f47cbb5..f9d058a07e2a 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -667,6 +667,23 @@ config SCSI_FDOMAIN tristate depends on SCSI +config SCSI_FDOMAIN_PCI + tristate "Future Domain TMC-3260/AHA-2920A PCI SCSI support" + depends on PCI && SCSI + select SCSI_FDOMAIN + help + This is support for Future Domain's PCI SCSI host adapters (TMC-3260) + and other adapters with PCI bus based on the Future Domain chipsets + (Adaptec AHA-2920A). + + NOTE: Newer Adaptec AHA-2920C boards use the Adaptec AIC-7850 chip + and should use the aic7xxx driver ("Adaptec AIC7xxx chipset SCSI + controller support"). This Future Domain driver works with the older + Adaptec AHA-2920A boards with a Future Domain chip on them. + + To compile this driver as a module, choose M here: the + module will be called fdomain_pci. + config SCSI_GDTH tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support" depends on PCI && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index b8fbc6d2de54..f6cc4fbe6957 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_SCSI_PM8001) += pm8001/ obj-$(CONFIG_SCSI_ISCI)+= isci/ obj-$(CONFIG_SCSI_IPS) += ips.o obj-$(CONFIG_SCSI_FDOMAIN) += fdomain.o +obj-$(CONFIG_SCSI_FDOMAIN_PCI) += fdomain_pci.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o obj-$(CONFIG_PCMCIA_QLOGIC)+= qlogicfas408.o diff --git a/drivers/scsi/fdomain_pci.c b/drivers/scsi/fdomain_pci.c new file mode 100644 index ..381a7157c078 --- /dev/null +++ b/drivers/scsi/fdomain_pci.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include "fdomain.h" + +static int fdomain_pci_probe(struct pci_dev *pdev, +const struct pci_device_id *d) +{ + int err; + struct Scsi_Host *sh; + + err = pci_enable_device(pdev); + if (err) + goto fail; + + err = pci_request_regions(pdev, "fdomain_pci"); + if (err) + goto disable_device; + + err = -ENODEV; + if (pci_resource_len(pdev, 0) == 0) + goto release_region; + + sh = fdomain_create(pci_resource_start(pdev, 0), pdev->irq, 7, 0, NULL, + &pdev->dev); + if (!sh) + goto release_region; + + pci_set_drvdata(pdev, sh); + return 0; + +release_region: + pci_release_regions(pdev); +disable_device: + pci_disable_device(pdev); +fail: + return err; +} + +static void fdomain_pci_remove(struct pci_dev *pdev) +{ + struct Scsi_Host *sh = pci_get_drvdata(pdev); + + fdomain_destroy(sh); + pci_release_regions(pdev); + pci_disable_device(pdev); +} + +static struct pci_device_id fdomain_pci_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70) }, + {} +}; +MODULE_DEVICE_TABLE(pci, fdomain_pci_table); + +static struct pci_driver fdomain_pci_driver = { + .name = "fdomain_pci", + .id_table = fdomain_pci_table, + .probe = fdomain_pci_probe, + .remove = fdomain_pci_remove, + .driver.pm = FDOMAIN_PM_OPS, +}; + +module_pci_driver(fdomain_pci_driver); + +MODULE_AUTHOR("Ondrej Zary, Rickard E. Faith"); +MODULE_DESCRIPTION("Future Domain TMC-3260 PCI SCSI driver"); +MODULE_LICENSE("GPL"); -- Ondrej Zary
[PATCH 0/4] fdomain: Resurrect driver (modular version)
Resurrect previously removed fdomain driver, in modern style. Initialization is rewritten completely, with support for multiple cards, no more global state variables. Most of the code from interrupt handler is moved to a workqueue. This is a modularized version with core separated from bus-specific drivers (PCI, ISA and PCMCIA). Only PCI driver is tested for now. The other two could be dropped until they get tested. Changes since RFC: - multi-line comment style, some coding style - usage of scsi_k(un)map_atomic_sg for buffer access - static marking of fdomain_host_reset and fdomain_template - IRQ lookup moved to ISA bus driver - EXPORT_SYMBOL_GPL -- Ondrej Zary
[PATCH 3/4] fdomain: Resurrect driver (ISA support)
Future Domain 16xx ISA SCSI support card support. Currently untested. Signed-off-by: Ondrej Zary --- drivers/scsi/Kconfig | 14 +++ drivers/scsi/Makefile | 1 + drivers/scsi/fdomain_isa.c | 231 + 3 files changed, 246 insertions(+) create mode 100644 drivers/scsi/fdomain_isa.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index f9d058a07e2a..2ea77dafbc00 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -684,6 +684,20 @@ config SCSI_FDOMAIN_PCI To compile this driver as a module, choose M here: the module will be called fdomain_pci. +config SCSI_FDOMAIN_ISA + tristate "Future Domain 16xx ISA SCSI support" + depends on ISA && SCSI + select CHECK_SIGNATURE + select SCSI_FDOMAIN + help + This is support for Future Domain's 16-bit SCSI host adapters + (TMC-1660/1680, TMC-1650/1670, TMC-1610M/MER/MEX) and other adapters + with ISA bus based on the Future Domain chipsets (Quantum ISA-200S, + ISA-250MG; and at least one IBM board). + + To compile this driver as a module, choose M here: the + module will be called fdomain_isa. + config SCSI_GDTH tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support" depends on PCI && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index f6cc4fbe6957..2e2c777d 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -78,6 +78,7 @@ obj-$(CONFIG_SCSI_ISCI) += isci/ obj-$(CONFIG_SCSI_IPS) += ips.o obj-$(CONFIG_SCSI_FDOMAIN) += fdomain.o obj-$(CONFIG_SCSI_FDOMAIN_PCI) += fdomain_pci.o +obj-$(CONFIG_SCSI_FDOMAIN_ISA) += fdomain_isa.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o obj-$(CONFIG_PCMCIA_QLOGIC)+= qlogicfas408.o diff --git a/drivers/scsi/fdomain_isa.c b/drivers/scsi/fdomain_isa.c new file mode 100644 index ..3008d5118d7a --- /dev/null +++ b/drivers/scsi/fdomain_isa.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include "fdomain.h" + +#define MAXBOARDS_PARAM 4 +static int io[MAXBOARDS_PARAM] = { 0, 0, 0, 0 }; +module_param_hw_array(io, int, ioport, NULL, 0); +MODULE_PARM_DESC(io, "base I/O address of controller (0x140, 0x150, 0x160, 0x170)"); + +static int irq[MAXBOARDS_PARAM] = { 0, 0, 0, 0 }; +module_param_hw_array(irq, int, irq, NULL, 0); +MODULE_PARM_DESC(irq, "IRQ of controller (0=auto [default])"); + +static int scsi_id[MAXBOARDS_PARAM] = { 0, 0, 0, 0 }; +module_param_hw_array(scsi_id, int, other, NULL, 0); +MODULE_PARM_DESC(scsi_id, "SCSI ID of controller (default = 6)"); + +static unsigned long addresses[] = { + 0xc8000, + 0xca000, + 0xce000, + 0xde000, +}; +#define ADDRESS_COUNT ARRAY_SIZE(addresses) + +static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 }; +#define PORT_COUNT ARRAY_SIZE(ports) + +static unsigned short irqs[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; + +/* This driver works *ONLY* for Future Domain cards using the TMC-1800, + * TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670, + * and 1680. These are all 16-bit cards. + * + * The following BIOS signature signatures are for boards which do *NOT* + * work with this driver (these TMC-8xx and TMC-9xx boards may work with the + * Seagate driver): + * + * FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88 + * FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89 + * FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89 + * FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90 + * FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90 + * FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90 + * FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92 + * + * (The cards which do *NOT* work are all 8-bit cards -- although some of + * them have a 16-bit form-factor, the upper 8-bits are used only for IRQs + * and are *NOT* used for data. You can tell the difference by following + * the tracings on the circuit board -- if only the IRQ lines are involved, + * you have a "8-bit" card, and should *NOT* use this driver.) + */ + +static struct signature signatures[] = { +/* 1 2 3 4 5 6 */ +/* 123456789012345678901234567890123456789012345678901234567890 */ +{ "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 }, +{ "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 }, +{ "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 }, +{ "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0", 73, 43, 2, 0, 3 }, +{ "FUTURE DOMAIN CORP. (C) 1991 1800-V2.0.", 72, 39, 2, 0, 4 }, +{ "FUTURE DOMAIN CORP. (C) 1992 V3.00.0
Re: [RFC PATCH 1/4] fdomain: Resurrect driver (core)
On Wednesday 24 April 2019 08:02:12 Christoph Hellwig wrote: > > +static void fdomain_work(struct work_struct *work) > > +{ > > + struct fdomain *fd = container_of(work, struct fdomain, work); > > + struct Scsi_Host *sh = container_of((void *)fd, struct Scsi_Host, > > + hostdata); > > This looks odd. We should never need a void cast for container_of. This cast is present in all drivers involving container_of, struct Scsi_Host and hostdata. hostdata in struct Scsi_Host is defined as "unsigned long hostdata[0]"... -- Ondrej Zary
[RFC PATCH 4/4] fdomain: Resurrect driver (PCMCIA support)
Future Domain PCMCIA SCSI support card support. Currently untested. Signed-off-by: Ondrej Zary --- drivers/scsi/pcmcia/Kconfig | 10 + drivers/scsi/pcmcia/Makefile | 1 + drivers/scsi/pcmcia/fdomain_cs.c | 89 3 files changed, 100 insertions(+) create mode 100644 drivers/scsi/pcmcia/fdomain_cs.c diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig index 2d435f105b16..169d93f90a30 100644 --- a/drivers/scsi/pcmcia/Kconfig +++ b/drivers/scsi/pcmcia/Kconfig @@ -19,6 +19,16 @@ config PCMCIA_AHA152X To compile this driver as a module, choose M here: the module will be called aha152x_cs. +config PCMCIA_FDOMAIN + tristate "Future Domain PCMCIA support" + select SCSI_FDOMAIN + help + Say Y here if you intend to attach this type of PCMCIA SCSI host + adapter to your computer. + + To compile this driver as a module, choose M here: the + module will be called fdomain_cs. + config PCMCIA_NINJA_SCSI tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support" depends on !64BIT diff --git a/drivers/scsi/pcmcia/Makefile b/drivers/scsi/pcmcia/Makefile index a5a24dd44e7e..02f5b44a2685 100644 --- a/drivers/scsi/pcmcia/Makefile +++ b/drivers/scsi/pcmcia/Makefile @@ -4,6 +4,7 @@ ccflags-y := -I $(srctree)/drivers/scsi # 16-bit client drivers obj-$(CONFIG_PCMCIA_QLOGIC)+= qlogic_cs.o +obj-$(CONFIG_PCMCIA_FDOMAIN) += fdomain_cs.o obj-$(CONFIG_PCMCIA_AHA152X) += aha152x_cs.o obj-$(CONFIG_PCMCIA_NINJA_SCSI)+= nsp_cs.o obj-$(CONFIG_PCMCIA_SYM53C500) += sym53c500_cs.o diff --git a/drivers/scsi/pcmcia/fdomain_cs.c b/drivers/scsi/pcmcia/fdomain_cs.c new file mode 100644 index ..eee1379ad67b --- /dev/null +++ b/drivers/scsi/pcmcia/fdomain_cs.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) +/* + * Driver for Future Domain-compatible PCMCIA SCSI cards + * Copyright 2019 Ondrej Zary + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include "fdomain.h" + +MODULE_AUTHOR("Ondrej Zary, David Hinds"); +MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver"); +MODULE_LICENSE("Dual MPL/GPL"); + +static int fdomain_config_check(struct pcmcia_device *p_dev, void *priv_data) +{ + p_dev->io_lines = 10; + p_dev->resource[0]->end = 0x10; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; + return pcmcia_request_io(p_dev); +} + +static int fdomain_probe(struct pcmcia_device *link) +{ + int ret; + struct Scsi_Host *sh; + + link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; + link->config_regs = PRESENT_OPTION; + + ret = pcmcia_loop_config(link, fdomain_config_check, NULL); + if (ret) + return ret; + + ret = pcmcia_enable_device(link); + if (ret) + goto fail; + + sh = fdomain_create(link->resource[0]->start, link->irq, 7, 0, NULL, + &link->dev); + if (!sh) { + dev_err(&link->dev, "Controller initialization failed"); + ret = -ENODEV; + goto fail; + } + + link->priv = sh; + + return 0; + +fail: + pcmcia_disable_device(link); + return ret; +} + +static void fdomain_remove(struct pcmcia_device *link) +{ + fdomain_destroy(link->priv); + pcmcia_disable_device(link); +} + +static const struct pcmcia_device_id fdomain_ids[] = { + PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "SCSI PCMCIA Card", 0xe3736c88, + 0x859cad20), + PCMCIA_DEVICE_PROD_ID1("SCSI PCMCIA Adapter Card", 0x8dacb57e), + PCMCIA_DEVICE_PROD_ID12(" SIMPLE TECHNOLOGY Corporation", + "SCSI PCMCIA Credit Card Controller", + 0x182bdafe, 0xc80d106f), + PCMCIA_DEVICE_NULL, +}; +MODULE_DEVICE_TABLE(pcmcia, fdomain_ids); + +static struct pcmcia_driver fdomain_cs_driver = { + .owner = THIS_MODULE, + .name = "fdomain_cs", + .probe = fdomain_probe, + .remove = fdomain_remove, + .id_table = fdomain_ids, +}; + +module_pcmcia_driver(fdomain_cs_driver); -- Ondrej Zary
[RFC PATCH 2/4] fdomain: Resurrect driver (PCI support)
Future Domain TMC-3260/AHA-2920A PCI card support. Tested on Adaptec AHA-2920A PCI card. Signed-off-by: Ondrej Zary --- drivers/scsi/Kconfig | 17 drivers/scsi/Makefile | 1 + drivers/scsi/fdomain_pci.c | 68 ++ 3 files changed, 86 insertions(+) create mode 100644 drivers/scsi/fdomain_pci.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 3d6b1f47cbb5..f9d058a07e2a 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -667,6 +667,23 @@ config SCSI_FDOMAIN tristate depends on SCSI +config SCSI_FDOMAIN_PCI + tristate "Future Domain TMC-3260/AHA-2920A PCI SCSI support" + depends on PCI && SCSI + select SCSI_FDOMAIN + help + This is support for Future Domain's PCI SCSI host adapters (TMC-3260) + and other adapters with PCI bus based on the Future Domain chipsets + (Adaptec AHA-2920A). + + NOTE: Newer Adaptec AHA-2920C boards use the Adaptec AIC-7850 chip + and should use the aic7xxx driver ("Adaptec AIC7xxx chipset SCSI + controller support"). This Future Domain driver works with the older + Adaptec AHA-2920A boards with a Future Domain chip on them. + + To compile this driver as a module, choose M here: the + module will be called fdomain_pci. + config SCSI_GDTH tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support" depends on PCI && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index b8fbc6d2de54..f6cc4fbe6957 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_SCSI_PM8001) += pm8001/ obj-$(CONFIG_SCSI_ISCI)+= isci/ obj-$(CONFIG_SCSI_IPS) += ips.o obj-$(CONFIG_SCSI_FDOMAIN) += fdomain.o +obj-$(CONFIG_SCSI_FDOMAIN_PCI) += fdomain_pci.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o obj-$(CONFIG_PCMCIA_QLOGIC)+= qlogicfas408.o diff --git a/drivers/scsi/fdomain_pci.c b/drivers/scsi/fdomain_pci.c new file mode 100644 index ..381a7157c078 --- /dev/null +++ b/drivers/scsi/fdomain_pci.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include "fdomain.h" + +static int fdomain_pci_probe(struct pci_dev *pdev, +const struct pci_device_id *d) +{ + int err; + struct Scsi_Host *sh; + + err = pci_enable_device(pdev); + if (err) + goto fail; + + err = pci_request_regions(pdev, "fdomain_pci"); + if (err) + goto disable_device; + + err = -ENODEV; + if (pci_resource_len(pdev, 0) == 0) + goto release_region; + + sh = fdomain_create(pci_resource_start(pdev, 0), pdev->irq, 7, 0, NULL, + &pdev->dev); + if (!sh) + goto release_region; + + pci_set_drvdata(pdev, sh); + return 0; + +release_region: + pci_release_regions(pdev); +disable_device: + pci_disable_device(pdev); +fail: + return err; +} + +static void fdomain_pci_remove(struct pci_dev *pdev) +{ + struct Scsi_Host *sh = pci_get_drvdata(pdev); + + fdomain_destroy(sh); + pci_release_regions(pdev); + pci_disable_device(pdev); +} + +static struct pci_device_id fdomain_pci_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70) }, + {} +}; +MODULE_DEVICE_TABLE(pci, fdomain_pci_table); + +static struct pci_driver fdomain_pci_driver = { + .name = "fdomain_pci", + .id_table = fdomain_pci_table, + .probe = fdomain_pci_probe, + .remove = fdomain_pci_remove, + .driver.pm = FDOMAIN_PM_OPS, +}; + +module_pci_driver(fdomain_pci_driver); + +MODULE_AUTHOR("Ondrej Zary, Rickard E. Faith"); +MODULE_DESCRIPTION("Future Domain TMC-3260 PCI SCSI driver"); +MODULE_LICENSE("GPL"); -- Ondrej Zary
[RFC PATCH 1/4] fdomain: Resurrect driver (core)
Future Domain TMC-16xx/TMC-3260 SCSI driver. This is the core driver, common for PCI, ISA and PCMCIA cards. Signed-off-by: Ondrej Zary --- drivers/scsi/Kconfig | 4 + drivers/scsi/Makefile | 1 + drivers/scsi/fdomain.c | 666 + drivers/scsi/fdomain.h | 25 ++ 4 files changed, 696 insertions(+) create mode 100644 drivers/scsi/fdomain.c create mode 100644 drivers/scsi/fdomain.h diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index d528018e6fa8..3d6b1f47cbb5 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -663,6 +663,10 @@ config SCSI_DMX3191D To compile this driver as a module, choose M here: the module will be called dmx3191d. +config SCSI_FDOMAIN + tristate + depends on SCSI + config SCSI_GDTH tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support" depends on PCI && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 8826111fdf4a..b8fbc6d2de54 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_SCSI_AIC94XX)+= aic94xx/ obj-$(CONFIG_SCSI_PM8001) += pm8001/ obj-$(CONFIG_SCSI_ISCI)+= isci/ obj-$(CONFIG_SCSI_IPS) += ips.o +obj-$(CONFIG_SCSI_FDOMAIN) += fdomain.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o obj-$(CONFIG_PCMCIA_QLOGIC)+= qlogicfas408.o diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c new file mode 100644 index ..19ae4e0bd00e --- /dev/null +++ b/drivers/scsi/fdomain.c @@ -0,0 +1,666 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Future Domain TMC-16x0 and TMC-3260 SCSI host adapters + * Copyright 2019 Ondrej Zary + * + * Original driver by + * Rickard E. Faith, fa...@cs.unc.edu + * + * Future Domain BIOS versions supported for autodetect: + *2.0, 3.0, 3.2, 3.4 (1.0), 3.5 (2.0), 3.6, 3.61 + * Chips supported: + *TMC-1800, TMC-18C50, TMC-18C30, TMC-36C70 + * Boards supported: + *Future Domain TMC-1650, TMC-1660, TMC-1670, TMC-1680, TMC-1610M/MER/MEX + *Future Domain TMC-3260 (PCI) + *Quantum ISA-200S, ISA-250MG + *Adaptec AHA-2920A (PCI) [BUT *NOT* AHA-2920C -- use aic7xxx instead] + *IBM ? + * + * NOTE: + * + * The Adaptec AHA-2920C has an Adaptec AIC-7850 chip on it. + * Use the aic7xxx driver for this board. + * + * The Adaptec AHA-2920A has a Future Domain chip on it, so this is the right + * driver for that card. Unfortunately, the boxes will probably just say + * "2920", so you'll have to look on the card for a Future Domain logo, or a + * letter after the 2920. + * + * If you have a TMC-8xx or TMC-9xx board, then this is not the driver for + * your board. + * + * DESCRIPTION: + * + * This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680 + * TMC-1650/1670, and TMC-3260 SCSI host adapters. The 1650 and 1670 have a + * 25-pin external connector, whereas the 1660 and 1680 have a SCSI-2 50-pin + * high-density external connector. The 1670 and 1680 have floppy disk + * controllers built in. The TMC-3260 is a PCI bus card. + * + * Future Domain's older boards are based on the TMC-1800 chip, and this + * driver was originally written for a TMC-1680 board with the TMC-1800 chip. + * More recently, boards are being produced with the TMC-18C50 and TMC-18C30 + * chips. + * + * Please note that the drive ordering that Future Domain implemented in BIOS + * versions 3.4 and 3.5 is the opposite of the order (currently) used by the + * rest of the SCSI industry. + * + * + * REFERENCES USED: + * + * "TMC-1800 SCSI Chip Specification (FDC-1800T)", Future Domain Corporation, + * 1990. + * + * "Technical Reference Manual: 18C50 SCSI Host Adapter Chip", Future Domain + * Corporation, January 1992. + * + * "LXT SCSI Products: Specifications and OEM Technical Manual (Revision + * B/September 1991)", Maxtor Corporation, 1991. + * + * "7213S product Manual (Revision P3)", Maxtor Corporation, 1992. + * + * "Draft Proposed American National Standard: Small Computer System + * Interface - 2 (SCSI-2)", Global Engineering Documents. (X3T9.2/86-109, + * revision 10h, October 17, 1991) + * + * Private communications, Drew Eckhardt (d...@cs.colorado.edu) and Eric + * Youngdale (er...@cais.com), 1992. + * + * Private communication, Tuong Le (Future Domain Engineering department), + * 1994. (Disk geometry computations for Future Domain BIOS version 3.4, and + * TMC-18C30 detection.) + * + * Hogan, Thom. The Programmer's PC Sourcebook. Microsoft Press, 1988. Page + * 60 (2.39: Disk Partition Table Layout). + * + * "18C30 Technical Reference Manual", Future Domain Corporation, 1993, page + * 6-1. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#inclu
[RFC PATCH 0/4] fdomain: Resurrect driver (modular version)
Resurrect previously removed fdomain driver, in modern style. Initialization is rewritten completely, with support for multiple cards, no more global state variables. Most of the code from interrupt handler is moved to a workqueue. This is a modularized version with core separated from bus-specific drivers (PCI, ISA and PCMCIA). Only PCI driver is tested for now. The other two could be dropped until they get tested. -- Ondrej Zary
[RFC PATCH 3/4] fdomain: Resurrect driver (ISA support)
Future Domain 16xx ISA SCSI support card support. Currently untested. Signed-off-by: Ondrej Zary --- drivers/scsi/Kconfig | 14 +++ drivers/scsi/Makefile | 1 + drivers/scsi/fdomain_isa.c | 227 + 3 files changed, 242 insertions(+) create mode 100644 drivers/scsi/fdomain_isa.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index f9d058a07e2a..2ea77dafbc00 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -684,6 +684,20 @@ config SCSI_FDOMAIN_PCI To compile this driver as a module, choose M here: the module will be called fdomain_pci. +config SCSI_FDOMAIN_ISA + tristate "Future Domain 16xx ISA SCSI support" + depends on ISA && SCSI + select CHECK_SIGNATURE + select SCSI_FDOMAIN + help + This is support for Future Domain's 16-bit SCSI host adapters + (TMC-1660/1680, TMC-1650/1670, TMC-1610M/MER/MEX) and other adapters + with ISA bus based on the Future Domain chipsets (Quantum ISA-200S, + ISA-250MG; and at least one IBM board). + + To compile this driver as a module, choose M here: the + module will be called fdomain_isa. + config SCSI_GDTH tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support" depends on PCI && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index f6cc4fbe6957..2e2c777d 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -78,6 +78,7 @@ obj-$(CONFIG_SCSI_ISCI) += isci/ obj-$(CONFIG_SCSI_IPS) += ips.o obj-$(CONFIG_SCSI_FDOMAIN) += fdomain.o obj-$(CONFIG_SCSI_FDOMAIN_PCI) += fdomain_pci.o +obj-$(CONFIG_SCSI_FDOMAIN_ISA) += fdomain_isa.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o obj-$(CONFIG_PCMCIA_QLOGIC)+= qlogicfas408.o diff --git a/drivers/scsi/fdomain_isa.c b/drivers/scsi/fdomain_isa.c new file mode 100644 index ..9f8bf02f175f --- /dev/null +++ b/drivers/scsi/fdomain_isa.c @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include "fdomain.h" + +#define MAXBOARDS_PARAM 4 +static int io[MAXBOARDS_PARAM] = { 0, 0, 0, 0 }; +module_param_hw_array(io, int, ioport, NULL, 0); +MODULE_PARM_DESC(io, "base I/O address of controller (0x140, 0x150, 0x160, 0x170)"); + +static int irq[MAXBOARDS_PARAM] = { 0, 0, 0, 0 }; +module_param_hw_array(irq, int, irq, NULL, 0); +MODULE_PARM_DESC(irq, "IRQ of controller (0=auto [default])"); + +static int scsi_id[MAXBOARDS_PARAM] = { 0, 0, 0, 0 }; +module_param_hw_array(scsi_id, int, other, NULL, 0); +MODULE_PARM_DESC(scsi_id, "SCSI ID of controller (default = 6)"); + +static unsigned long addresses[] = { + 0xc8000, + 0xca000, + 0xce000, + 0xde000, +}; +#define ADDRESS_COUNT ARRAY_SIZE(addresses) + +static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 }; +#define PORT_COUNT ARRAY_SIZE(ports) + +/* This driver works *ONLY* for Future Domain cards using the TMC-1800, + * TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670, + * and 1680. These are all 16-bit cards. + * + * The following BIOS signature signatures are for boards which do *NOT* + * work with this driver (these TMC-8xx and TMC-9xx boards may work with the + * Seagate driver): + * + * FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88 + * FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89 + * FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89 + * FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90 + * FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90 + * FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90 + * FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92 + * + * (The cards which do *NOT* work are all 8-bit cards -- although some of + * them have a 16-bit form-factor, the upper 8-bits are used only for IRQs + * and are *NOT* used for data. You can tell the difference by following + * the tracings on the circuit board -- if only the IRQ lines are involved, + * you have a "8-bit" card, and should *NOT* use this driver.) + */ + +static struct signature signatures[] = { +/* 1 2 3 4 5 6 */ +/* 123456789012345678901234567890123456789012345678901234567890 */ +{ "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 }, +{ "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 }, +{ "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 }, +{ "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0", 73, 43, 2, 0, 3 }, +{ "FUTURE DOMAIN CORP. (C) 1991 1800-V2.0.", 72, 39, 2, 0, 4 }, +{ "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 }, +{ "FUTURE DOMAIN TM
[RFC PATCH] fdomain: Resurrect driver
Resurrect previously removed fdomain driver, in modern style. Initialization is rewritten completely, with support for multiple cards, no more global state variables. Most of the code from interrupt handler is moved to a workqueue. Tested on Adaptec AHA-2920A PCI card. ISA and PCMCIA code is untested as I don't have the hardware. Signed-off-by: Ondrej Zary --- drivers/scsi/Kconfig | 18 + drivers/scsi/Makefile | 1 + drivers/scsi/fdomain.c | 992 + drivers/scsi/fdomain.h | 7 + drivers/scsi/pcmcia/Kconfig| 9 + drivers/scsi/pcmcia/Makefile | 2 + drivers/scsi/pcmcia/fdomain_core.c | 2 + drivers/scsi/pcmcia/fdomain_stub.c | 89 8 files changed, 1120 insertions(+) create mode 100644 drivers/scsi/fdomain.c create mode 100644 drivers/scsi/fdomain.h create mode 100644 drivers/scsi/pcmcia/fdomain_core.c create mode 100644 drivers/scsi/pcmcia/fdomain_stub.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index d528018e6fa8..90950d875f2d 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -663,6 +663,24 @@ config SCSI_DMX3191D To compile this driver as a module, choose M here: the module will be called dmx3191d. +config SCSI_FUTURE_DOMAIN + tristate "Future Domain 16xx SCSI/AHA-2920A support" + depends on (ISA || PCI) && SCSI + select CHECK_SIGNATURE + help + This is support for Future Domain's 16-bit SCSI host adapters + (TMC-1660/1680, TMC-1650/1670, TMC-3260, TMC-1610M/MER/MEX) and + other adapters based on the Future Domain chipsets (Quantum + ISA-200S, ISA-250MG; Adaptec AHA-2920A; and at least one IBM board). + + NOTE: Newer Adaptec AHA-2920C boards use the Adaptec AIC-7850 chip + and should use the aic7xxx driver ("Adaptec AIC7xxx chipset SCSI + controller support"). This Future Domain driver works with the older + Adaptec AHA-2920A boards with a Future Domain chip on them. + + To compile this driver as a module, choose M here: the + module will be called fdomain. + config SCSI_GDTH tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support" depends on PCI && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 8826111fdf4a..a9f80770d989 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_SCSI_AIC94XX)+= aic94xx/ obj-$(CONFIG_SCSI_PM8001) += pm8001/ obj-$(CONFIG_SCSI_ISCI)+= isci/ obj-$(CONFIG_SCSI_IPS) += ips.o +obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o obj-$(CONFIG_PCMCIA_QLOGIC)+= qlogicfas408.o diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c new file mode 100644 index ..814fd1b94797 --- /dev/null +++ b/drivers/scsi/fdomain.c @@ -0,0 +1,992 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Future Domain TMC-16x0 and TMC-3260 SCSI host adapters + * Copyright 2019 Ondrej Zary + * + * Original driver by + * Rickard E. Faith, fa...@cs.unc.edu + * + * Future Domain BIOS versions supported for autodetect: + *2.0, 3.0, 3.2, 3.4 (1.0), 3.5 (2.0), 3.6, 3.61 + * Chips supported: + *TMC-1800, TMC-18C50, TMC-18C30, TMC-36C70 + * Boards supported: + *Future Domain TMC-1650, TMC-1660, TMC-1670, TMC-1680, TMC-1610M/MER/MEX + *Future Domain TMC-3260 (PCI) + *Quantum ISA-200S, ISA-250MG + *Adaptec AHA-2920A (PCI) [BUT *NOT* AHA-2920C -- use aic7xxx instead] + *IBM ? + * + * NOTE: + * + * The Adaptec AHA-2920C has an Adaptec AIC-7850 chip on it. + * Use the aic7xxx driver for this board. + * + * The Adaptec AHA-2920A has a Future Domain chip on it, so this is the right + * driver for that card. Unfortunately, the boxes will probably just say + * "2920", so you'll have to look on the card for a Future Domain logo, or a + * letter after the 2920. + * + * If you have a TMC-8xx or TMC-9xx board, then this is not the driver for + * your board. + * + * DESCRIPTION: + * + * This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680 + * TMC-1650/1670, and TMC-3260 SCSI host adapters. The 1650 and 1670 have a + * 25-pin external connector, whereas the 1660 and 1680 have a SCSI-2 50-pin + * high-density external connector. The 1670 and 1680 have floppy disk + * controllers built in. The TMC-3260 is a PCI bus card. + * + * Future Domain's older boards are based on the TMC-1800 chip, and this + * driver was originally written for a TMC-1680 board with the TMC-1800 chip. + * More recently, boards are being produced with the TMC-18C50 and TMC-18C30 + * chips. + * + * Please note that the drive ordering that Future Domain implemented in BIOS + * versions 3.4 and 3
[RFC PATCH 3/2] fdomain: Use SCSI host private data instead of global variables
Move global variables into SCSI host private data in order to support multiple cards. Signed-off-by: Ondrej Zary --- drivers/scsi/fdomain.c | 593 + 1 file changed, 307 insertions(+), 286 deletions(-) diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index fe9e373c27a8..83294cf6b668 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -384,29 +384,32 @@ enum out_port_type { /* .bss will zero all the static variables below */ static int port_base; -static unsigned long bios_base; -static void __iomem *bios_mem; -static int bios_major; -static int bios_minor; -static int PCI_bus; -#ifdef CONFIG_PCI -static struct pci_dev *PCI_dev; -#endif -static int Quantum; /* Quantum board variant */ static int interrupt_level; -static volatile int in_command; -static struct scsi_cmnd *current_SC; -static enum chip_typechip = unknown; -static int adapter_mask; static int this_id; static int setup_called; +struct fdomain { + int port_base; + unsigned long bios_base; + void __iomem *bios_mem; + int bios_major; + int bios_minor; + int PCI_bus; +#ifdef CONFIG_PCI + struct pci_dev *PCI_dev; +#endif + int Quantum;/* Quantum board variant */ + int interrupt_level; + volatile int in_command; + struct scsi_cmnd *current_SC; + enum chip_type chip; + int adapter_mask; + int this_id; #if DEBUG_RACE -static volatile int in_interrupt_flag; + volatile int in_interrupt_flag; #endif - -static int FIFO_Size = 0x2000; /* 8k FIFO for - pre-tmc18c30 chips */ + int FIFO_Size; +}; static irqreturn_t do_fdomain_16x0_intr( int irq, void *dev_id ); /* Allow insmod parameters to be like LILO parameters. For example: @@ -518,22 +521,22 @@ static struct signature { static void print_banner( struct Scsi_Host *shpnt ) { - if (!shpnt) return; /* This won't ever happen */ + struct fdomain *fd = shost_priv(shpnt); - if (bios_major < 0 && bios_minor < 0) { + if (fd->bios_major < 0 && fd->bios_minor < 0) { printk(KERN_INFO "scsi%d: No BIOS; using scsi id %d\n", shpnt->host_no, shpnt->this_id); } else { printk(KERN_INFO "scsi%d: BIOS version ", shpnt->host_no); - if (bios_major >= 0) printk("%d.", bios_major); + if (fd->bios_major >= 0) printk("%d.", fd->bios_major); else printk("?."); - if (bios_minor >= 0) printk("%d", bios_minor); + if (fd->bios_minor >= 0) printk("%d", fd->bios_minor); else printk("?."); printk( " at 0x%lx using scsi id %d\n", - bios_base, shpnt->this_id ); + fd->bios_base, shpnt->this_id ); } /* If this driver works for later FD PCI @@ -542,11 +545,11 @@ static void print_banner( struct Scsi_Host *shpnt ) it's PCI it's a TMC-3260 - JTM */ printk(KERN_INFO "scsi%d: %s chip at 0x%x irq ", shpnt->host_no, - chip == tmc1800 ? "TMC-1800" : (chip == tmc18c50 ? "TMC-18C50" : (chip == tmc18c30 ? (PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30") : "Unknown")), - port_base); + fd->chip == tmc1800 ? "TMC-1800" : (fd->chip == tmc18c50 ? "TMC-18C50" : (fd->chip == tmc18c30 ? (fd->PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30") : "Unknown")), + fd->port_base); - if (interrupt_level) - printk("%d", interrupt_level); + if (fd->interrupt_level) + printk("%d", fd->interrupt_level); else printk(""); @@ -568,8 +571,7 @@ int fdomain_setup(char *str) port_base = ints[0] >= 1 ? ints[1] : 0; interrupt_level = ints[0] >= 2 ? ints[2] : 0; this_id = ints[0] >= 3 ? ints[3] : 0; - - bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */ + ++setup_called; return 1; } @@ -582,22 +584,24 @@ static void do_pause(unsigned amount) /* Pause for amount*10 milliseconds */ mdelay(10*amount); } -static inline void fdomain_make_bus_idle( void ) +static inline void fdomain_make_bus_idle(struct fdomain *fd) { - outb(0, port_base + SCSI_Cntl); - outb(0, port_base + SCSI_Mode_Cntl); - if (chip == tmc18c50 || chip == tmc18c30) -outb(0x21 | PARITY_MASK, port_base + TMC_Cntl); /* Clear
[RFC PATCH 2/2] fdomain: Fix compilation
Remove usage of scsi_module.c, .use_clustering and scsi_(un)register. This allows the driver to compile and also work (tested with PCI card). Signed-off-by: Ondrej Zary --- drivers/scsi/fdomain.c | 48 -- drivers/scsi/pcmcia/fdomain_stub.c | 2 +- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index ebbe5a3e665d..fe9e373c27a8 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -415,6 +415,7 @@ static char * fdomain = NULL; module_param(fdomain, charp, 0); #ifndef PCMCIA +static struct Scsi_Host*fdomain_shost; static unsigned long addresses[] = { 0xc8000, @@ -959,7 +960,7 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt ) /* Print out a banner here in case we can't get resources. */ - shpnt = scsi_register( tpnt, 0 ); + shpnt = scsi_host_alloc( tpnt, 0 ); if(shpnt == NULL) { release_region(port_base, 0x10); return NULL; @@ -1003,13 +1004,6 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt ) return NULL; } -static int fdomain_16x0_detect(struct scsi_host_template *tpnt) -{ - if (fdomain) - fdomain_setup(fdomain); - return (__fdomain_16x0_detect(tpnt) != NULL); -} - static const char *fdomain_16x0_info( struct Scsi_Host *ignore ) { static char buffer[128]; @@ -1739,6 +1733,7 @@ static int fdomain_16x0_biosparam(struct scsi_device *sdev, return 0; } +#ifndef PCMCIA static int fdomain_16x0_release(struct Scsi_Host *shpnt) { if (shpnt->irq) @@ -1749,22 +1744,21 @@ static int fdomain_16x0_release(struct Scsi_Host *shpnt) pci_dev_put(PCI_dev); return 0; } +#endif struct scsi_host_template fdomain_driver_template = { .module = THIS_MODULE, .name = "fdomain", .proc_name = "fdomain", - .detect = fdomain_16x0_detect, .info = fdomain_16x0_info, .queuecommand = fdomain_16x0_queue, .eh_abort_handler = fdomain_16x0_abort, .eh_host_reset_handler = fdomain_16x0_host_reset, .bios_param = fdomain_16x0_biosparam, - .release= fdomain_16x0_release, .can_queue = 1, .this_id= 6, .sg_tablesize = 64, - .use_clustering = DISABLE_CLUSTERING, + .dma_boundary = PAGE_SIZE - 1, }; #ifndef PCMCIA @@ -1778,6 +1772,36 @@ static struct pci_device_id fdomain_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, fdomain_pci_tbl); #endif #define driver_template fdomain_driver_template -#include "scsi_module.c" + +static int __init fdomain_16x0_init(void) +{ + int ret; + + if (fdomain) + fdomain_setup(fdomain); + fdomain_shost = __fdomain_16x0_detect(&driver_template); + if (!fdomain_shost) + return -ENODEV; + + ret = scsi_add_host(fdomain_shost, NULL); + if (ret) + goto fail; + scsi_scan_host(fdomain_shost); + + return 0; +fail: + scsi_remove_host(fdomain_shost); + return ret; +} + +static void __exit fdomain_16x0_exit(void) +{ + scsi_remove_host(fdomain_shost); + fdomain_16x0_release(fdomain_shost); + scsi_host_put(fdomain_shost); +} + +module_init(fdomain_16x0_init); +module_exit(fdomain_16x0_exit); #endif diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 953a792150ae..5febbb7d611b 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -166,7 +166,7 @@ static void fdomain_release(struct pcmcia_device *link) scsi_remove_host(info->host); pcmcia_disable_device(link); - scsi_unregister(info->host); + scsi_host_put(info->host); } /*====*/ -- Ondrej Zary
[RFC PATCH 0/2] fdomain: Resurrect driver
Hello, the removal of fdomain driver caused regressions: https://alioth-lists.debian.net/pipermail/sane-devel/2019-January/036552.html I've got a fdomain-based AHA-2920A card so I'll try to resurrect the driver and then clean it up.
[RFC PATCH 1/2] fdomain: Resurrect fdomain and fdomain_cs drivers
This reverts commit e184f2bf4d9f1a3c612a8c1d67e73e9cf8ab5ab9. It does not compile but following patches will fix that. Signed-off-by: Ondrej Zary --- MAINTAINERS|6 + drivers/scsi/Kconfig | 20 + drivers/scsi/Makefile |1 + drivers/scsi/fdomain.c | 1783 drivers/scsi/fdomain.h | 24 + drivers/scsi/pcmcia/Kconfig|9 + drivers/scsi/pcmcia/Makefile |2 + drivers/scsi/pcmcia/fdomain_core.c |2 + drivers/scsi/pcmcia/fdomain_stub.c | 209 + 9 files changed, 2056 insertions(+) create mode 100644 drivers/scsi/fdomain.c create mode 100644 drivers/scsi/fdomain.h create mode 100644 drivers/scsi/pcmcia/fdomain_core.c create mode 100644 drivers/scsi/pcmcia/fdomain_stub.c diff --git a/MAINTAINERS b/MAINTAINERS index 2359e12e4c41..4ff767f79454 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6416,6 +6416,12 @@ F: tools/testing/selftests/futex/ F: tools/perf/bench/futex* F: Documentation/*futex* +FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit) +M: Rik Faith +L: linux-scsi@vger.kernel.org +S: Odd Fixes (e.g., new signatures) +F: drivers/scsi/fdomain.* + GCC PLUGINS M: Kees Cook R: Emese Revfy diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index d528018e6fa8..58690189c8cf 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -663,6 +663,26 @@ config SCSI_DMX3191D To compile this driver as a module, choose M here: the module will be called dmx3191d. +config SCSI_FUTURE_DOMAIN + tristate "Future Domain 16xx SCSI/AHA-2920A support" + depends on (ISA || PCI) && SCSI + select CHECK_SIGNATURE + ---help--- + This is support for Future Domain's 16-bit SCSI host adapters + (TMC-1660/1680, TMC-1650/1670, TMC-3260, TMC-1610M/MER/MEX) and + other adapters based on the Future Domain chipsets (Quantum + ISA-200S, ISA-250MG; Adaptec AHA-2920A; and at least one IBM board). + It is explained in section 3.7 of the SCSI-HOWTO, available from + <http://www.tldp.org/docs.html#howto>. + + NOTE: Newer Adaptec AHA-2920C boards use the Adaptec AIC-7850 chip + and should use the aic7xxx driver ("Adaptec AIC7xxx chipset SCSI + controller support"). This Future Domain driver works with the older + Adaptec AHA-2920A boards with a Future Domain chip on them. + + To compile this driver as a module, choose M here: the + module will be called fdomain. + config SCSI_GDTH tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support" depends on PCI && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 8826111fdf4a..a9f80770d989 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_SCSI_AIC94XX)+= aic94xx/ obj-$(CONFIG_SCSI_PM8001) += pm8001/ obj-$(CONFIG_SCSI_ISCI)+= isci/ obj-$(CONFIG_SCSI_IPS) += ips.o +obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o obj-$(CONFIG_PCMCIA_QLOGIC)+= qlogicfas408.o diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c new file mode 100644 index ..ebbe5a3e665d --- /dev/null +++ b/drivers/scsi/fdomain.c @@ -0,0 +1,1783 @@ +/* fdomain.c -- Future Domain TMC-16x0 SCSI driver + * Created: Sun May 3 18:53:19 1992 by fa...@cs.unc.edu + * Revised: Mon Dec 28 21:59:02 1998 by fa...@acm.org + * Author: Rickard E. Faith, fa...@cs.unc.edu + * Copyright 1992-1996, 1998 Rickard E. Faith (fa...@acm.org) + * Shared IRQ supported added 7/7/2001 Alan Cox + + * 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, or (at your option) any + * later version. + + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + + ** + + SUMMARY: + + Future Domain BIOS versions supported for autodetect: +2.0, 3.0, 3.2, 3.4 (1.0), 3.5 (2.0), 3.6, 3.61 + Chips are supported: +TMC-1800, TMC-18C50, TMC-18C30, TMC-36C70 + Boards supported: +Future Domain TMC-1650, TMC-1660, TMC-1670, TMC-1680, TMC-1610M/MER/MEX +Future Domain TMC-3260 (PCI) +Quantum ISA-200S, ISA-250MG
Re: [PATCH] aha1542: convert to DMA mapping API
On Friday 09 November 2018 16:45:54 Christoph Hellwig wrote: > aha1542 is one of the last users of the legacy isa_*_to_bus APIs, which > also isn't portable enough. Convert it to the proper DMA mapping API. > > Thanks to Ondrej Zary for testing and finding and fixing a crucial > bug. > > Signed-off-by: Christoph Hellwig > Tested-by: Ondrej Zary > --- > drivers/scsi/aha1542.c | 126 + > 1 file changed, 91 insertions(+), 35 deletions(-) > > diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c > index 41add33e3f1f..398fcdc6f4c9 100644 > --- a/drivers/scsi/aha1542.c > +++ b/drivers/scsi/aha1542.c > @@ -58,8 +58,15 @@ struct aha1542_hostdata { > int aha1542_last_mbi_used; > int aha1542_last_mbo_used; > struct scsi_cmnd *int_cmds[AHA1542_MAILBOXES]; > - struct mailbox mb[2 * AHA1542_MAILBOXES]; > - struct ccb ccb[AHA1542_MAILBOXES]; > + struct mailbox *mb; > + dma_addr_t mb_handle; > + struct ccb *ccb; > + dma_addr_t ccb_handle; > +}; > + > +struct aha1542_cmd { > + struct chain *chain; > + dma_addr_t chain_handle; > }; > > static inline void aha1542_intr_reset(u16 base) > @@ -233,6 +240,21 @@ static int aha1542_test_port(struct Scsi_Host *sh) > return 1; > } > > +static void aha1542_free_cmd(struct scsi_cmnd *cmd) > +{ > + struct aha1542_cmd *acmd = scsi_cmd_priv(cmd); > + struct device *dev = cmd->device->host->dma_dev; > + size_t len = scsi_sg_count(cmd) * sizeof(struct chain); > + > + if (acmd->chain) { > + dma_unmap_single(dev, acmd->chain_handle, len, DMA_TO_DEVICE); > + kfree(acmd->chain); > + } > + > + acmd->chain = NULL; > + scsi_dma_unmap(cmd); > +} > + > static irqreturn_t aha1542_interrupt(int irq, void *dev_id) > { > struct Scsi_Host *sh = dev_id; > @@ -303,7 +325,7 @@ static irqreturn_t aha1542_interrupt(int irq, void > *dev_id) > return IRQ_HANDLED; > }; > > - mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus(&ccb[0]))) / > sizeof(struct ccb); > + mbo = (scsi2int(mb[mbi].ccbptr) - aha1542->ccb_handle) / > sizeof(struct ccb); > mbistatus = mb[mbi].status; > mb[mbi].status = 0; > aha1542->aha1542_last_mbi_used = mbi; > @@ -331,8 +353,7 @@ static irqreturn_t aha1542_interrupt(int irq, void > *dev_id) > return IRQ_HANDLED; > } > my_done = tmp_cmd->scsi_done; > - kfree(tmp_cmd->host_scribble); > - tmp_cmd->host_scribble = NULL; > + aha1542_free_cmd(tmp_cmd); > /* Fetch the sense data, and tuck it away, in the required > slot. The > Adaptec automatically fetches it, and there is no guarantee > that > we will still have it in the cdb when we come back */ > @@ -369,6 +390,7 @@ static irqreturn_t aha1542_interrupt(int irq, void > *dev_id) > > static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd) > { > + struct aha1542_cmd *acmd = scsi_cmd_priv(cmd); > struct aha1542_hostdata *aha1542 = shost_priv(sh); > u8 direction; > u8 target = cmd->device->id; > @@ -378,7 +400,6 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, > struct scsi_cmnd *cmd) > int mbo, sg_count; > struct mailbox *mb = aha1542->mb; > struct ccb *ccb = aha1542->ccb; > - struct chain *cptr; > > if (*cmd->cmnd == REQUEST_SENSE) { > /* Don't do the command - we have the sense data already */ > @@ -398,15 +419,17 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, > struct scsi_cmnd *cmd) > print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, cmd->cmnd, > cmd->cmd_len); > } > #endif > - if (bufflen) { /* allocate memory before taking host_lock */ > - sg_count = scsi_sg_count(cmd); > - cptr = kmalloc_array(sg_count, sizeof(*cptr), > - GFP_KERNEL | GFP_DMA); > - if (!cptr) > - return SCSI_MLQUEUE_HOST_BUSY; > - } else { > - sg_count = 0; > - cptr = NULL; > + sg_count = scsi_dma_map(cmd); > + if (sg_count) { > + size_t len = sg_count * sizeof(struct chain); > + > + acmd->chain = kmalloc(len, GFP_DMA); > + if (!acmd->chain) > + goto out_unmap; > + acmd->chain_ha
Re: [PATCH] aha1542: convert to DMA mapping API
On Thursday 09 August 2018 07:35:33 Christoph Hellwig wrote: > On Wed, Aug 08, 2018 at 10:30:19PM +0200, Ondrej Zary wrote: > > Then it crashes with null-pointer dereference in aha1542_reset. > > Must be the dma_unmap. Updated patch below: > > --- > From 98a9c770430cde972923838b990b2b9cf7b95816 Mon Sep 17 00:00:00 2001 > From: Christoph Hellwig > Date: Thu, 2 Aug 2018 14:22:46 +0200 > Subject: aha1542: convert to DMA mapping API > > aha1542 is one of the last users of the legacy isa_*_to_bus APIs, which > also isn't portable enough. Convert it to the proper DMA mapping API. > > Signed-off-by: Christoph Hellwig > --- > drivers/scsi/aha1542.c | 126 + > 1 file changed, 91 insertions(+), 35 deletions(-) > > diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c > index 41add33e3f1f..d09e19dde177 100644 > --- a/drivers/scsi/aha1542.c > +++ b/drivers/scsi/aha1542.c > @@ -58,8 +58,15 @@ struct aha1542_hostdata { > int aha1542_last_mbi_used; > int aha1542_last_mbo_used; > struct scsi_cmnd *int_cmds[AHA1542_MAILBOXES]; > - struct mailbox mb[2 * AHA1542_MAILBOXES]; > - struct ccb ccb[AHA1542_MAILBOXES]; > + struct mailbox *mb; > + dma_addr_t mb_handle; > + struct ccb *ccb; > + dma_addr_t ccb_handle; > +}; > + > +struct aha1542_cmd { > + struct chain *chain; > + dma_addr_t chain_handle; > }; > > static inline void aha1542_intr_reset(u16 base) > @@ -233,6 +240,21 @@ static int aha1542_test_port(struct Scsi_Host *sh) > return 1; > } > > +static void aha1542_free_cmd(struct scsi_cmnd *cmd) > +{ > + struct aha1542_cmd *acmd = scsi_cmd_priv(cmd); > + struct device *dev = cmd->device->host->dma_dev; > + size_t len = scsi_sg_count(cmd) * sizeof(struct chain); > + > + if (acmd->chain) { > + dma_unmap_single(dev, acmd->chain_handle, len, DMA_TO_DEVICE); > + kfree(acmd->chain); > + } > + > + acmd->chain = NULL; > + scsi_dma_unmap(cmd); > +} > + > static irqreturn_t aha1542_interrupt(int irq, void *dev_id) > { > struct Scsi_Host *sh = dev_id; > @@ -303,7 +325,7 @@ static irqreturn_t aha1542_interrupt(int irq, void > *dev_id) > return IRQ_HANDLED; > }; > > - mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus(&ccb[0]))) / > sizeof(struct ccb); > + mbo = (scsi2int(mb[mbi].ccbptr) - aha1542->ccb_handle) / > sizeof(struct ccb); > mbistatus = mb[mbi].status; > mb[mbi].status = 0; > aha1542->aha1542_last_mbi_used = mbi; > @@ -331,8 +353,7 @@ static irqreturn_t aha1542_interrupt(int irq, void > *dev_id) > return IRQ_HANDLED; > } > my_done = tmp_cmd->scsi_done; > - kfree(tmp_cmd->host_scribble); > - tmp_cmd->host_scribble = NULL; > + aha1542_free_cmd(tmp_cmd); > /* Fetch the sense data, and tuck it away, in the required > slot. The > Adaptec automatically fetches it, and there is no guarantee > that > we will still have it in the cdb when we come back */ > @@ -369,6 +390,7 @@ static irqreturn_t aha1542_interrupt(int irq, void > *dev_id) > > static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd) > { > + struct aha1542_cmd *acmd = scsi_cmd_priv(cmd); > struct aha1542_hostdata *aha1542 = shost_priv(sh); > u8 direction; > u8 target = cmd->device->id; > @@ -378,7 +400,6 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, > struct scsi_cmnd *cmd) > int mbo, sg_count; > struct mailbox *mb = aha1542->mb; > struct ccb *ccb = aha1542->ccb; > - struct chain *cptr; > > if (*cmd->cmnd == REQUEST_SENSE) { > /* Don't do the command - we have the sense data already */ > @@ -398,15 +419,17 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, > struct scsi_cmnd *cmd) > print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, cmd->cmnd, > cmd->cmd_len); > } > #endif > - if (bufflen) { /* allocate memory before taking host_lock */ > - sg_count = scsi_sg_count(cmd); > - cptr = kmalloc_array(sg_count, sizeof(*cptr), > - GFP_KERNEL | GFP_DMA); > - if (!cptr) > - return SCSI_MLQUEUE_HOST_BUSY; > - } else { > - sg_count = 0; > - cptr = NULL; > +
Re: dma related cleanups for wd719x
On Thursday 18 October 2018 15:01:14 Christoph Hellwig wrote: > Hi Ondrej, > > can you look over this series, which cleans up a few dma-related > bits in the wd719x driver? Hello, this patch is needed to make it work: diff --git a/drivers/scsi/wd719x.c b/drivers/scsi/wd719x.c index d47190f08ed6..b73e7f24a1c4 100644 --- a/drivers/scsi/wd719x.c +++ b/drivers/scsi/wd719x.c @@ -183,7 +183,7 @@ static void wd719x_finish_cmd(struct wd719x_scb *scb, int result) list_del(&scb->list); dma_unmap_single(&wd->pdev->dev, scb->phys, - sizeof(struct wd719x_scb), DMA_TO_DEVICE); + sizeof(struct wd719x_scb), DMA_BIDIRECTIONAL); scsi_dma_unmap(cmd); dma_unmap_single(&wd->pdev->dev, cmd->SCp.dma_handle, SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE); @@ -209,12 +209,19 @@ static int wd719x_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd) /* copy the command */ memcpy(scb->CDB, cmd->cmnd, cmd->cmd_len); + /* map SCB */ + scb->phys = dma_map_single(&wd->pdev->dev, scb, sizeof(*scb), + DMA_BIDIRECTIONAL); + + if (dma_mapping_error(&wd->pdev->dev, scb->phys)) + goto out_error; + /* map sense buffer */ scb->sense_buf_length = SCSI_SENSE_BUFFERSIZE; cmd->SCp.dma_handle = dma_map_single(&wd->pdev->dev, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE); if (dma_mapping_error(&wd->pdev->dev, cmd->SCp.dma_handle)) - goto out_error; + goto out_unmap_scb; scb->sense_buf = cpu_to_le32(cmd->SCp.dma_handle); /* request autosense */ @@ -246,11 +253,6 @@ static int wd719x_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd) scb->sg_list[i].length = cpu_to_le32(sg_dma_len(sg)); } scb->SCB_options |= WD719X_SCB_FLAGS_DO_SCATTER_GATHER; - - scb->phys = dma_map_single(&wd->pdev->dev, scb, sizeof(*scb), - DMA_TO_DEVICE); - if (dma_mapping_error(&wd->pdev->dev, scb->phys)) - goto out_unmap_scsi_cmd; } else { /* zero length */ scb->data_length = 0; scb->data_p = 0; @@ -274,11 +276,12 @@ static int wd719x_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd) spin_unlock_irqrestore(wd->sh->host_lock, flags); return 0; -out_unmap_scsi_cmd: - scsi_dma_unmap(cmd); out_unmap_sense: dma_unmap_single(&wd->pdev->dev, cmd->SCp.dma_handle, SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE); +out_unmap_scb: + dma_unmap_single(&wd->pdev->dev, scb->phys, sizeof(*scb), +DMA_BIDIRECTIONAL); out_error: cmd->result = DID_ERROR << 16; cmd->scsi_done(cmd); -- Ondrej Zary
Re: dma related cleanups for wd719x
On Thursday 18 October 2018 15:01:14 Christoph Hellwig wrote: > Hi Ondrej, > > can you look over this series, which cleans up a few dma-related > bits in the wd719x driver? > This makes it work a bit (can detect drive and read partitions) but it hangs completely after hdparm -t. diff --git a/drivers/scsi/wd719x.c b/drivers/scsi/wd719x.c index d47190f08ed6..55a7a542e653 100644 --- a/drivers/scsi/wd719x.c +++ b/drivers/scsi/wd719x.c @@ -183,7 +183,7 @@ static void wd719x_finish_cmd(struct wd719x_scb *scb, int result) list_del(&scb->list); dma_unmap_single(&wd->pdev->dev, scb->phys, - sizeof(struct wd719x_scb), DMA_TO_DEVICE); + sizeof(struct wd719x_scb), DMA_BIDIRECTIONAL); scsi_dma_unmap(cmd); dma_unmap_single(&wd->pdev->dev, cmd->SCp.dma_handle, SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE); @@ -236,6 +236,12 @@ static int wd719x_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd) if (count_sg) { struct scatterlist *sg; + scb->phys = dma_map_single(&wd->pdev->dev, scb, sizeof(*scb), + DMA_BIDIRECTIONAL); + + if (dma_mapping_error(&wd->pdev->dev, scb->phys)) + goto out_unmap_scsi_cmd; + scb->data_length = cpu_to_le32(count_sg * sizeof(struct wd719x_sglist)); scb->data_p = cpu_to_le32(scb->phys + @@ -246,11 +252,6 @@ static int wd719x_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd) scb->sg_list[i].length = cpu_to_le32(sg_dma_len(sg)); } scb->SCB_options |= WD719X_SCB_FLAGS_DO_SCATTER_GATHER; - - scb->phys = dma_map_single(&wd->pdev->dev, scb, sizeof(*scb), - DMA_TO_DEVICE); - if (dma_mapping_error(&wd->pdev->dev, scb->phys)) - goto out_unmap_scsi_cmd; } else { /* zero length */ scb->data_length = 0; scb->data_p = 0; -- Ondrej Zary
Re: bioset changes in 4.18 broke aha1542
On Thursday 18 October 2018 22:28:35 Jens Axboe wrote: > On 10/18/18 2:22 PM, Ondrej Zary wrote: > > On Thursday 18 October 2018 22:10:31 Jens Axboe wrote: > >> On 10/18/18 2:04 PM, Ondrej Zary wrote: > >>> On Thursday 18 October 2018 21:59:09 Jens Axboe wrote: > >>>> On 10/18/18 1:55 PM, Ondrej Zary wrote: > >>>>> On Thursday 18 October 2018 20:58:57 Jens Axboe wrote: > >>>>>> On 10/18/18 12:34 PM, Ondrej Zary wrote: > >>>>>>> Hello, > >>>>>>> aha1542 works fine in 4.17 but crashes in 4.18. It's hard to bisect > >>>>>>> because > >>>>>>> of many commits that don't compile. > >>>>>>> # only skipped commits left to test > >>>>>>> # possible first bad commit: > >>>>>>> [52190f8abe7f2bf2b4e5f9760cbcc1427ca2136b] fs: convert block_dev.c to > >>>>>>> bioset_init() > >>>>>>> # possible first bad commit: > >>>>>>> [a47a28b74a5c7c27bf621276b85ad6c124651236] target: convert to > >>>>>>> bioset_init()/mempool_init() > >>>>>>> # possible first bad commit: > >>>>>>> [6f1c819c219f7841079f0f43ab62727a55b0d849] dm: convert to > >>>>>>> bioset_init()/mempool_init() > >>>>>>> # possible first bad commit: > >>>>>>> [afeee514ce7f4cab605beedd03be71ebaf0c5fc8] md: convert to > >>>>>>> bioset_init()/mempool_init() > >>>>>>> # possible first bad commit: > >>>>>>> [d19936a26658a7a53edd5619d631ee2c2c3151a2] bcache: convert to > >>>>>>> bioset_init()/mempool_init() > >>>>>>> # possible first bad commit: > >>>>>>> [b906bbb6997785d9ea0bd3f5585537afa6257c43] lightnvm: convert to > >>>>>>> bioset_init()/mempool_init() > >>>>>>> > >>>>>>> Testing manually, a47a28b74a5c7c27bf621276b85ad6c124651236 works. > >>>>>>> 52190f8abe7f2bf2b4e5f9760cbcc1427ca2136b does not compile > >>>>>>> 8ac9f7c1fd1d342e82ddf078425423b050652ba0 does not compile > >>>>>>> e292d7bc63c8f2adb3dfda27910e805f1b6557f9 does not compile > >>>>>>> dad08527525f9a8ac9c7f278864c65f94bc5e9b3 does not compile > >>>>>>> 943cf9f3ca16133dbd00f9a4cbfea46512fcb0e8 works > >>>>>>> .. > >>>>>>> fedc3abe7bd2dcc4c80bcf3cff8708a3908d8219 works > >>>>>>> 04c4950d5b373ba712d928592e05e73510785bca crashes > >>>>>> > >>>>>> It looks like the ISA bioset pool isn't being initialized. You should > >>>>>> have messages like this in your dmesg: > >>>>>> > >>>>>> isa pool size: 16 pages > >>>>>> > >>>>>> (which you do), but also something on the bioset section. Do you have > >>>>>> this one: > >>>>>> > >>>>>> pool size: 64 pages > >>>>>> > >>>>>> as well? > >>>>>> > >>>>> > >>>>> No, it's not there. > >>>> > >>>> Can you attach your .config? I'm guessing CONFIG_HIGHMEM* isn't set. > >>>> > >>> > >>> It is. > >> > >> Puzzled... Does this work? > >> > >> > >> diff --git a/block/bounce.c b/block/bounce.c > >> index b30071ac4ec6..49564a1bfd22 100644 > >> --- a/block/bounce.c > >> +++ b/block/bounce.c > >> @@ -35,10 +35,6 @@ static mempool_t page_pool, isa_page_pool; > >> static __init int init_emergency_pool(void) > >> { > >>int ret; > >> -#if defined(CONFIG_HIGHMEM) && !defined(CONFIG_MEMORY_HOTPLUG) > >> - if (max_pfn <= max_low_pfn) > >> - return 0; > >> -#endif > >> > >>ret = mempool_init_page_pool(&page_pool, POOL_SIZE, 0); > >>BUG_ON(ret); > >> > > > > Yes, it does! > > bounce: pool size: 64 pages > > and aha1542 works. > > > > Also added printks for pfn: > > max_pfn=65520, max_low_pfn=65520 > > This should be a better fix, though I'm still puzzled why we need > it now. Can you test this one? > > > diff --git a/block/bounce.c b/
Re: bioset changes in 4.18 broke aha1542
On Thursday 18 October 2018 22:10:31 Jens Axboe wrote: > On 10/18/18 2:04 PM, Ondrej Zary wrote: > > On Thursday 18 October 2018 21:59:09 Jens Axboe wrote: > >> On 10/18/18 1:55 PM, Ondrej Zary wrote: > >>> On Thursday 18 October 2018 20:58:57 Jens Axboe wrote: > >>>> On 10/18/18 12:34 PM, Ondrej Zary wrote: > >>>>> Hello, > >>>>> aha1542 works fine in 4.17 but crashes in 4.18. It's hard to bisect > >>>>> because > >>>>> of many commits that don't compile. > >>>>> # only skipped commits left to test > >>>>> # possible first bad commit: [52190f8abe7f2bf2b4e5f9760cbcc1427ca2136b] > >>>>> fs: convert block_dev.c to bioset_init() > >>>>> # possible first bad commit: [a47a28b74a5c7c27bf621276b85ad6c124651236] > >>>>> target: convert to bioset_init()/mempool_init() > >>>>> # possible first bad commit: [6f1c819c219f7841079f0f43ab62727a55b0d849] > >>>>> dm: convert to bioset_init()/mempool_init() > >>>>> # possible first bad commit: [afeee514ce7f4cab605beedd03be71ebaf0c5fc8] > >>>>> md: convert to bioset_init()/mempool_init() > >>>>> # possible first bad commit: [d19936a26658a7a53edd5619d631ee2c2c3151a2] > >>>>> bcache: convert to bioset_init()/mempool_init() > >>>>> # possible first bad commit: [b906bbb6997785d9ea0bd3f5585537afa6257c43] > >>>>> lightnvm: convert to bioset_init()/mempool_init() > >>>>> > >>>>> Testing manually, a47a28b74a5c7c27bf621276b85ad6c124651236 works. > >>>>> 52190f8abe7f2bf2b4e5f9760cbcc1427ca2136b does not compile > >>>>> 8ac9f7c1fd1d342e82ddf078425423b050652ba0 does not compile > >>>>> e292d7bc63c8f2adb3dfda27910e805f1b6557f9 does not compile > >>>>> dad08527525f9a8ac9c7f278864c65f94bc5e9b3 does not compile > >>>>> 943cf9f3ca16133dbd00f9a4cbfea46512fcb0e8 works > >>>>> .. > >>>>> fedc3abe7bd2dcc4c80bcf3cff8708a3908d8219 works > >>>>> 04c4950d5b373ba712d928592e05e73510785bca crashes > >>>> > >>>> It looks like the ISA bioset pool isn't being initialized. You should > >>>> have messages like this in your dmesg: > >>>> > >>>> isa pool size: 16 pages > >>>> > >>>> (which you do), but also something on the bioset section. Do you have > >>>> this one: > >>>> > >>>> pool size: 64 pages > >>>> > >>>> as well? > >>>> > >>> > >>> No, it's not there. > >> > >> Can you attach your .config? I'm guessing CONFIG_HIGHMEM* isn't set. > >> > > > > It is. > > Puzzled... Does this work? > > > diff --git a/block/bounce.c b/block/bounce.c > index b30071ac4ec6..49564a1bfd22 100644 > --- a/block/bounce.c > +++ b/block/bounce.c > @@ -35,10 +35,6 @@ static mempool_t page_pool, isa_page_pool; > static __init int init_emergency_pool(void) > { > int ret; > -#if defined(CONFIG_HIGHMEM) && !defined(CONFIG_MEMORY_HOTPLUG) > - if (max_pfn <= max_low_pfn) > - return 0; > -#endif > > ret = mempool_init_page_pool(&page_pool, POOL_SIZE, 0); > BUG_ON(ret); > Yes, it does! bounce: pool size: 64 pages and aha1542 works. Also added printks for pfn: max_pfn=65520, max_low_pfn=65520 -- Ondrej Zary
Re: bioset changes in 4.18 broke aha1542
On Thursday 18 October 2018 21:59:09 Jens Axboe wrote: > On 10/18/18 1:55 PM, Ondrej Zary wrote: > > On Thursday 18 October 2018 20:58:57 Jens Axboe wrote: > >> On 10/18/18 12:34 PM, Ondrej Zary wrote: > >>> Hello, > >>> aha1542 works fine in 4.17 but crashes in 4.18. It's hard to bisect > >>> because > >>> of many commits that don't compile. > >>> # only skipped commits left to test > >>> # possible first bad commit: [52190f8abe7f2bf2b4e5f9760cbcc1427ca2136b] > >>> fs: convert block_dev.c to bioset_init() > >>> # possible first bad commit: [a47a28b74a5c7c27bf621276b85ad6c124651236] > >>> target: convert to bioset_init()/mempool_init() > >>> # possible first bad commit: [6f1c819c219f7841079f0f43ab62727a55b0d849] > >>> dm: convert to bioset_init()/mempool_init() > >>> # possible first bad commit: [afeee514ce7f4cab605beedd03be71ebaf0c5fc8] > >>> md: convert to bioset_init()/mempool_init() > >>> # possible first bad commit: [d19936a26658a7a53edd5619d631ee2c2c3151a2] > >>> bcache: convert to bioset_init()/mempool_init() > >>> # possible first bad commit: [b906bbb6997785d9ea0bd3f5585537afa6257c43] > >>> lightnvm: convert to bioset_init()/mempool_init() > >>> > >>> Testing manually, a47a28b74a5c7c27bf621276b85ad6c124651236 works. > >>> 52190f8abe7f2bf2b4e5f9760cbcc1427ca2136b does not compile > >>> 8ac9f7c1fd1d342e82ddf078425423b050652ba0 does not compile > >>> e292d7bc63c8f2adb3dfda27910e805f1b6557f9 does not compile > >>> dad08527525f9a8ac9c7f278864c65f94bc5e9b3 does not compile > >>> 943cf9f3ca16133dbd00f9a4cbfea46512fcb0e8 works > >>> .. > >>> fedc3abe7bd2dcc4c80bcf3cff8708a3908d8219 works > >>> 04c4950d5b373ba712d928592e05e73510785bca crashes > >> > >> It looks like the ISA bioset pool isn't being initialized. You should > >> have messages like this in your dmesg: > >> > >> isa pool size: 16 pages > >> > >> (which you do), but also something on the bioset section. Do you have > >> this one: > >> > >> pool size: 64 pages > >> > >> as well? > >> > > > > No, it's not there. > > Can you attach your .config? I'm guessing CONFIG_HIGHMEM* isn't set. > It is. -- Ondrej Zary # # Automatically generated file; DO NOT EDIT. # Linux/x86 4.19.0-rc7 Kernel Configuration # # # Compiler: gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516 # CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=60300 CONFIG_CLANG_VERSION=0 CONFIG_IRQ_WORK=y CONFIG_BUILDTIME_EXTABLE_SORT=y CONFIG_THREAD_INFO_IN_TASK=y # # General setup # CONFIG_INIT_ENV_ARG_LIMIT=32 # CONFIG_COMPILE_TEST is not set CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_BUILD_SALT="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y CONFIG_HAVE_KERNEL_XZ=y CONFIG_HAVE_KERNEL_LZO=y CONFIG_HAVE_KERNEL_LZ4=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set # CONFIG_KERNEL_XZ is not set # CONFIG_KERNEL_LZO is not set # CONFIG_KERNEL_LZ4 is not set CONFIG_DEFAULT_HOSTNAME="(none)" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set CONFIG_CROSS_MEMORY_ATTACH=y CONFIG_USELIB=y # CONFIG_AUDIT is not set CONFIG_HAVE_ARCH_AUDITSYSCALL=y # # IRQ subsystem # CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_PENDING_IRQ=y CONFIG_GENERIC_IRQ_MIGRATION=y CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_DOMAIN_HIERARCHY=y CONFIG_GENERIC_MSI_IRQ=y CONFIG_GENERIC_MSI_IRQ_DOMAIN=y CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y CONFIG_GENERIC_IRQ_RESERVATION_MODE=y CONFIG_IRQ_FORCED_THREADING=y CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_IRQ_DEBUGFS is not set CONFIG_CLOCKSOURCE_WATCHDOG=y CONFIG_ARCH_CLOCKSOURCE_DATA=y CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y CONFIG_GENERIC_CMOS_UPDATE=y # # Timers subsystem # CONFIG_TICK_ONESHOT=y CONFIG_NO_HZ_COMMON=y # CONFIG_HZ_PERIODIC is not set CONFIG_NO_HZ_IDLE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set # # CPU/Task time and stats accounting # CONFIG_TICK_CPU_ACCOUNTING=y # CONFIG_IRQ_TIME_ACCOUNTING is not set CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y # CONFIG_CPU_ISOLATION is not set # # RCU Subsystem # CONFIG_TREE_RCU=y # CONFIG_RCU_EXPERT is
Re: bioset changes in 4.18 broke aha1542
On Thursday 18 October 2018 20:58:57 Jens Axboe wrote: > On 10/18/18 12:34 PM, Ondrej Zary wrote: > > Hello, > > aha1542 works fine in 4.17 but crashes in 4.18. It's hard to bisect because > > of many commits that don't compile. > > # only skipped commits left to test > > # possible first bad commit: [52190f8abe7f2bf2b4e5f9760cbcc1427ca2136b] fs: > > convert block_dev.c to bioset_init() > > # possible first bad commit: [a47a28b74a5c7c27bf621276b85ad6c124651236] > > target: convert to bioset_init()/mempool_init() > > # possible first bad commit: [6f1c819c219f7841079f0f43ab62727a55b0d849] dm: > > convert to bioset_init()/mempool_init() > > # possible first bad commit: [afeee514ce7f4cab605beedd03be71ebaf0c5fc8] md: > > convert to bioset_init()/mempool_init() > > # possible first bad commit: [d19936a26658a7a53edd5619d631ee2c2c3151a2] > > bcache: convert to bioset_init()/mempool_init() > > # possible first bad commit: [b906bbb6997785d9ea0bd3f5585537afa6257c43] > > lightnvm: convert to bioset_init()/mempool_init() > > > > Testing manually, a47a28b74a5c7c27bf621276b85ad6c124651236 works. > > 52190f8abe7f2bf2b4e5f9760cbcc1427ca2136b does not compile > > 8ac9f7c1fd1d342e82ddf078425423b050652ba0 does not compile > > e292d7bc63c8f2adb3dfda27910e805f1b6557f9 does not compile > > dad08527525f9a8ac9c7f278864c65f94bc5e9b3 does not compile > > 943cf9f3ca16133dbd00f9a4cbfea46512fcb0e8 works > > .. > > fedc3abe7bd2dcc4c80bcf3cff8708a3908d8219 works > > 04c4950d5b373ba712d928592e05e73510785bca crashes > > It looks like the ISA bioset pool isn't being initialized. You should > have messages like this in your dmesg: > > isa pool size: 16 pages > > (which you do), but also something on the bioset section. Do you have > this one: > > pool size: 64 pages > > as well? > No, it's not there. -- Ondrej Zary
Re: dma related cleanups for wd719x
On Thursday 18 October 2018 15:01:14 Christoph Hellwig wrote: > Hi Ondrej, > > can you look over this series, which cleans up a few dma-related > bits in the wd719x driver? > Looks nice but does not work. The first patch works, but the 2nd one causes hang on modprobe: [ 408.350359] wd719x :00:0c.0: RISC initialized with firmware version 03.10 [ 408.949225] wd719x :00:0c.0: WD7193 at I/O 0xe800, IRQ 5, SCSI ID 7 [ 408.954450] scsi host2: Western Digital 719x [ 409.263961] wd719x :00:0c.0: invalid SCSI phase [ 409.297203] wd719x :00:0c.0: invalid SCSI phase [ 409.325714] scsi 2:0:1:0: Direct-Access QUANTUM LP240S GM240S01X 4.6 PQ: 0 ANSI: 2 CCS [ 409.346106] wd719x :00:0c.0: invalid SCSI phase [ 409.380731] wd719x :00:0c.0: invalid SCSI phase [ 410.748579] sd 2:0:1:0: Attached scsi generic sg1 type 0 -- Ondrej Zary
bioset changes in 4.18 broke aha1542
8b 4d e8 64 a1 9c 56 74 c7 83 b8 1c 04 00 [ 86.020095] ---[ end trace f40f2545ef2bd465 ]--- [ 86.259982] BUG: unable to handle kernel NULL pointer dereference at 004c [ 86.263681] *pde = [ 86.263681] Oops: [#1] SMP [ 86.263681] Modules linked in: aha1542 i2c_dev nouveau psmouse serio_raw 8139cp sg wmi hwmon ttm parport_pc parport intel_agp [ 86.263681] CPU: 0 PID: 50 Comm: kworker/u2:1 Tainted: GW 4.17.0-rc4+ #288 [ 86.263681] Hardware name: /i440ZX-W977TF, BIOS 4.51 PG 07/12/00 [ 86.263681] Workqueue: events_unbound async_run_entry_fn [ 86.263681] EIP: blk_queue_bounce+0x179/0x25c [ 86.263681] EFLAGS: 00010286 CPU: 0 [ 86.263681] EAX: EBX: 0001 ECX: c77948a0 EDX: 0001 [ 86.263681] ESI: 0001 EDI: 0002 EBP: cf985c2c ESP: cf985be8 [ 86.263681] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [ 86.263681] CR0: 80050033 CR2: 004c CR3: 0c711000 CR4: 0290 [ 86.263681] Call Trace: [ 86.263681] blk_mq_make_request+0x5a/0x295 [ 86.263681] ? blk_mq_try_issue_directly+0x8b/0x8b [ 86.263681] generic_make_request+0x184/0x246 [ 86.263681] ? alloc_buffer_head+0x13/0x49 [ 86.263681] submit_bio+0xd9/0xf1 [ 86.263681] ? bio_alloc_bioset+0xe1/0x185 [ 86.263681] ? alloc_page_buffers+0x6a/0x8a [ 86.263681] ? guard_bio_eod+0x2c/0xae [ 86.263681] submit_bh_wbc.isra.45+0x109/0x113 [ 86.263681] submit_bh+0xa/0xc [ 86.263681] block_read_full_page+0x1be/0x1df [ 86.263681] ? bd_may_claim+0x35/0x35 [ 86.263681] ? add_to_page_cache_lru+0x94/0xaf [ 86.263681] blkdev_readpage+0xf/0x11 [ 86.263681] do_read_cache_page+0x75/0x118 [ 86.263681] ? blkdev_writepages+0xa/0xa [ 86.263681] ? blkdev_writepages+0xa/0xa [ 86.263681] read_cache_page+0xe/0x10 [ 86.263681] read_dev_sector+0x23/0x73 [ 86.263681] adfspart_check_ICS+0x3c/0x1c6 [ 86.263681] ? vsnprintf+0x8a/0x323 [ 86.263681] ? snprintf+0x15/0x17 [ 86.263681] check_partition+0xe3/0x16a [ 86.263681] rescan_partitions+0x7d/0x33e [ 86.263681] ? down_write+0xb/0x2c [ 86.263681] ? bd_set_size+0x3e/0x6f [ 86.263681] __blkdev_get+0x1b0/0x38a [ 86.263681] ? get_nr_inodes_unused+0x25/0x3b [ 86.263681] blkdev_get+0x8b/0x243 [ 86.263681] ? wake_up_bit+0x14/0x17 [ 86.263681] ? put_device+0xf/0x11 [ 86.263681] ? disk_put_part+0xf/0x11 [ 86.263681] __device_add_disk+0x338/0x36a [ 86.263681] device_add_disk+0xd/0xf [ 86.263681] sd_probe_async+0xf1/0x178 [ 86.263681] ? sd_revalidate_disk+0x1476/0x1476 [ 86.263681] async_run_entry_fn+0x33/0xb7 [ 86.263681] process_one_work+0xed/0x17e [ 86.263681] worker_thread+0x168/0x1fb [ 86.263681] kthread+0xcc/0xce [ 86.263681] ? rescuer_thread+0x219/0x219 [ 86.263681] ? kthread_cancel_delayed_work_sync+0xf/0xf [ 86.263681] ret_from_fork+0x2e/0x38 [ 86.263681] Code: d4 8b 00 e8 8a ac fe ff 8b 45 d4 89 18 58 b9 a0 48 79 c7 8b 45 c0 ba 00 00 40 01 83 e0 01 89 45 c0 8b 45 d4 8b 00 e8 81 6e fe ff <8b> 58 4c 89 45 d0 8b 45 d0 0f b7 40 44 39 45 cc 73 62 8b 33 8b [ 86.263681] EIP: blk_queue_bounce+0x179/0x25c SS:ESP: 0068:cf985be8 [ 86.263681] CR2: 004c [ 86.263681] ---[ end trace f40f2545ef2bd466 ]--- -- Ondrej Zary
Re: [PATCH] aha1542: convert to DMA mapping API
On Thursday 09 August 2018 07:35:33 Christoph Hellwig wrote: > On Wed, Aug 08, 2018 at 10:30:19PM +0200, Ondrej Zary wrote: > > Then it crashes with null-pointer dereference in aha1542_reset. > > Must be the dma_unmap. Updated patch below: No change in behavior, unfortunately. The crash is probably just a result of the bad things that happen before, starting with: scsi host2: Unexpected interrupt -- Ondrej Zary
Re: [PATCH] aha1542: convert to DMA mapping API
On Wednesday 08 August 2018 18:35:13 Christoph Hellwig wrote: > On Wed, Aug 08, 2018 at 06:26:25PM +0200, Ondrej Zary wrote: > > Looks like you attached wrong file (same as the previous one). > > This should be better: > > --- > From afa1c18bd98168fb690d905fc84a2db6f0d617b6 Mon Sep 17 00:00:00 2001 > From: Christoph Hellwig > Date: Thu, 2 Aug 2018 14:22:46 +0200 > Subject: aha1542: convert to DMA mapping API It's better but still not working: [ 1647.365259] scsi host2: Adaptec AHA-1542 (SCSI-ID 7) at IO 0x330, IRQ 11, DMA 7 [ 1647.441220] scsi host2: Adaptec 1542 [ 1647.453163] bounce: isa pool size: 16 pages [ 1647.976008] scsi host2: Unexpected interrupt [ 1647.979955] scsi host2: tarstat=0, hastat=11 idlun=0 ccb#=0 [ 1661.503064] systemd-logind[1788]: Failed to start user service, ignoring: Unknown unit: user@0.service [ 1661.626254] systemd-logind[1788]: New session c2 of user root. [ 1669.112324] scsi 2:0:1:0: tag#0 Trying device reset for target [ 1669.121544] scsi 2:0:1:0: tag#0 Trying device reset for target [ 1669.129428] scsi host2: Sent BUS RESET to scsi host 2 [ 1669.375367] scsi host2: Unexpected interrupt [ 1669.379061] scsi host2: tarstat=0, hastat=11 idlun=0 ccb#=0 [ 1679.588276] scsi 2:0:1:0: tag#0 Trying device reset for target [ 1679.596179] scsi host2: Sent BUS RESET to scsi host 2 [ 1689.828278] scsi 2:0:1:0: tag#0 Trying device reset for target [ 1689.832302] scsi 2:0:1:0: Device offlined - not ready after error recovery [ 1690.331351] scsi host2: Unexpected interrupt [ 1690.335275] scsi host2: tarstat=0, hastat=0 idlun=20 ccb#=0 Then it crashes with null-pointer dereference in aha1542_reset. -- Ondrej Zary
Re: [PATCH] aha1542: convert to DMA mapping API
On Wednesday 08 August 2018 11:14:33 Christoph Hellwig wrote: > On Tue, Aug 07, 2018 at 07:30:17PM +0200, Ondrej Zary wrote: > > On Tuesday 07 August 2018 09:29:59 Christoph Hellwig wrote: > > > Looks like the dma allocation is too late. Updated version below: > > > > > > ... > > > > Crashes a bit later now: > > Next try: > > --- > From 9dd7a3eb89d1cc72c001daeb80e44de7c5fb5b00 Mon Sep 17 00:00:00 2001 > From: Christoph Hellwig > Date: Thu, 2 Aug 2018 14:22:46 +0200 > Subject: aha1542: convert to DMA mapping API Looks like you attached wrong file (same as the previous one). -- Ondrej Zary
Re: [PATCH] aha1542: convert to DMA mapping API
psmouse serio_raw sg 8139cp wmi hwmon ttm parport_pc parport intel_agp [ 122.093295] CPU: 0 PID: 1821 Comm: scsi_eh_2 Tainted: GW 4.17.0+ #263 [ 122.093295] Hardware name: /i440ZX-W977TF, BIOS 4.51 PG 07/12/00 [ 122.093295] EIP: dma_free_attrs.constprop.8+0x29/0x76 [aha1542] [ 122.093295] EFLAGS: 00010086 CPU: 0 [ 122.093295] EAX: cfbda200 EBX: 0086 ECX: EDX: 0006 [ 122.093295] ESI: c009 EDI: cf514aa0 EBP: cbe89ebc ESP: cbe89eac [ 122.093295] DS: 007b ES: 007b FS: 00d8 GS: SS: 0068 [ 122.093295] CR0: 80050033 CR2: 08321408 CR3: 0bcee000 CR4: 0290 [ 122.093295] Call Trace: [ 122.093295] aha1542_free_cmd+0x29/0x40 [aha1542] [ 122.093295] aha1542_reset+0xb0/0xe5 [aha1542] [ 122.093295] aha1542_host_reset+0xd/0xf [aha1542] [ 122.093295] scsi_try_host_reset+0x4c/0x95 [ 122.093295] scsi_eh_ready_devs+0x689/0x781 [ 122.093295] scsi_error_handler+0x268/0x4b0 [ 122.093295] ? __schedule+0x38f/0x3dd [ 122.093295] kthread+0xcc/0xce [ 122.093295] ? scsi_eh_get_sense+0x16e/0x16e [ 122.093295] ? kthread_cancel_delayed_work_sync+0xf/0xf [ 122.093295] ret_from_fork+0x2e/0x38 [ 122.093295] Code: 5d c3 55 85 c0 89 e5 57 56 53 53 74 0a 8b b8 20 01 00 00 85 ff 75 0c 8b 3d 08 aa 66 cf 85 ff 75 02 0f 0b 9c 5b 0f ba e3 09 72 02 <0f> 0b 89 45 f0 8d 42 ff 89 cb c1 e8 0c 83 c9 ff 89 d6 0f bd d0 [ 122.093295] ---[ end trace 3524d2ff63a5e03d ]--- [ 122.093295] WARNING: CPU: 0 PID: 1821 at ./include/linux/dma-mapping.h:541 dma_free_attrs.constprop.8+0x29/0x76 [aha1542] [ 122.093295] Modules linked in: aha1542 i2c_dev nouveau psmouse serio_raw sg 8139cp wmi hwmon ttm parport_pc parport intel_agp [ 122.093295] CPU: 0 PID: 1821 Comm: scsi_eh_2 Tainted: GW 4.17.0+ #263 [ 122.093295] Hardware name: /i440ZX-W977TF, BIOS 4.51 PG 07/12/00 [ 122.093295] EIP: dma_free_attrs.constprop.8+0x29/0x76 [aha1542] [ 122.093295] EFLAGS: 00010086 CPU: 0 [ 122.093295] EAX: cfbda200 EBX: 0086 ECX: EDX: 0006 [ 122.093295] ESI: c009 EDI: cf514aa0 EBP: cbe89ebc ESP: cbe89eac [ 122.093295] DS: 007b ES: 007b FS: 00d8 GS: SS: 0068 [ 122.093295] CR0: 80050033 CR2: 08321408 CR3: 0bcee000 CR4: 0290 [ 122.093295] Call Trace: [ 122.093295] aha1542_free_cmd+0x29/0x40 [aha1542] [ 122.093295] aha1542_reset+0xb0/0xe5 [aha1542] [ 122.093295] aha1542_host_reset+0xd/0xf [aha1542] [ 122.093295] scsi_try_host_reset+0x4c/0x95 [ 122.093295] scsi_eh_ready_devs+0x689/0x781 [ 122.093295] scsi_error_handler+0x268/0x4b0 [ 122.093295] ? __schedule+0x38f/0x3dd [ 122.093295] kthread+0xcc/0xce [ 122.093295] ? scsi_eh_get_sense+0x16e/0x16e [ 122.093295] ? kthread_cancel_delayed_work_sync+0xf/0xf [ 122.093295] ret_from_fork+0x2e/0x38 [ 122.093295] Code: 5d c3 55 85 c0 89 e5 57 56 53 53 74 0a 8b b8 20 01 00 00 85 ff 75 0c 8b 3d 08 aa 66 cf 85 ff 75 02 0f 0b 9c 5b 0f ba e3 09 72 02 <0f> 0b 89 45 f0 8d 42 ff 89 cb c1 e8 0c 83 c9 ff 89 d6 0f bd d0 [ 122.093295] ---[ end trace 3524d2ff63a5e03e ]--- [ 132.580275] scsi 2:0:1:0: tag#0 Trying device reset for target [ 132.585659] scsi 2:0:1:0: Device offlined - not ready after error recovery [ 132.830010] scsi host2: Unexpected interrupt [ 132.833680] scsi host2: tarstat=0, hastat=0 idlun=20 ccb#=0 [ 133.083186] scsi host2: Unexpected interrupt [ 133.087100] scsi host2: tarstat=0, hastat=0 idlun=20 ccb#=0 -- Ondrej Zary
Re: [PATCH] aha1542: convert to DMA mapping API
> + aha1542->ccb, aha1542->ccb_handle); > + dma_free_coherent(dev, AHA1542_MAILBOXES * 2 * sizeof(struct mailbox), > + aha1542->mb, aha1542->mb_handle); > if (sh->dma_channel != 0xff) > free_dma(sh->dma_channel); > if (sh->irq) > @@ -826,7 +868,8 @@ static int aha1542_dev_reset(struct scsi_cmnd *cmd) > > aha1542->aha1542_last_mbo_used = mbo; > > - any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets > trashed for some reason */ + /* This gets trashed for some reason */ > + any2scsi(mb[mbo].ccbptr, aha1542->ccb_handle + mbo * sizeof(ccb)); > > memset(&ccb[mbo], 0, sizeof(struct ccb)); > > @@ -889,8 +932,7 @@ static int aha1542_reset(struct scsi_cmnd *cmd, u8 > reset_cmd) > > for (i = 0; i < AHA1542_MAILBOXES; i++) { > if (aha1542->int_cmds[i] != NULL) { > - struct scsi_cmnd *tmp_cmd; > - tmp_cmd = aha1542->int_cmds[i]; > + struct scsi_cmnd *tmp_cmd = aha1542->int_cmds[i]; > > if (tmp_cmd->device->soft_reset) { > /* > @@ -901,8 +943,7 @@ static int aha1542_reset(struct scsi_cmnd *cmd, u8 > reset_cmd) */ > continue; > } > - kfree(tmp_cmd->host_scribble); > - tmp_cmd->host_scribble = NULL; > + aha1542_free_cmd(tmp_cmd); > aha1542->int_cmds[i] = NULL; > aha1542->mb[i].status = 0; > } > @@ -946,6 +987,7 @@ static struct scsi_host_template driver_template = { > .module = THIS_MODULE, > .proc_name = "aha1542", > .name = "Adaptec 1542", > + .cmd_size = sizeof(struct aha1542_cmd), > .queuecommand = aha1542_queuecommand, > .eh_device_reset_handler= aha1542_dev_reset, > .eh_bus_reset_handler = aha1542_bus_reset, Doesn't seem to work: [ 159.185536] scsi host2: Adaptec AHA-1542 (SCSI-ID 7) at IO 0x330, IRQ 11, DMA 7 [ 159.262108] BUG: unable to handle kernel NULL pointer dereference at [ 159.264103] *pde = [ 159.264103] Oops: 0002 [#1] SMP [ 159.264103] Modules linked in: aha1542(+) sr_mod cdrom i2c_dev psmouse serio_raw 8139cp nouveau sg parport_pc parport wmi hwmon ttm intel_agp [last unloaded: aha1542] [ 159.264103] CPU: 0 PID: 1848 Comm: modprobe Not tainted 4.17.0+ #263 [ 159.264103] Hardware name: /i440ZX-W977TF, BIOS 4.51 PG 07/12/00 [ 159.264103] EIP: setup_mailboxes+0x1a/0xb5 [aha1542] [ 159.264103] EFLAGS: 00010246 CPU: 0 [ 159.264103] EAX: EBX: c009 ECX: cfde2164 EDX: [ 159.264103] ESI: c009 EDI: cbf07d25 EBP: cbf07d08 ESP: cbf07cf8 [ 159.264103] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 [ 159.264103] CR0: 80050033 CR2: b7e9f050 CR3: 0bc7 CR4: 0290 [ 159.264103] Call Trace: [ 159.264103] aha1542_hw_init.constprop.7+0x5a8/0x702 [aha1542] [ 159.264103] aha1542_isa_match+0xb/0x1e [aha1542] [ 159.264103] isa_bus_match+0x20/0x40 [ 159.264103] __device_attach_driver+0x25/0x71 [ 159.264103] bus_for_each_drv+0x5c/0x68 [ 159.264103] __device_attach+0x79/0xcd [ 159.264103] ? driver_allows_async_probing+0x28/0x28 [ 159.264103] device_initial_probe+0xd/0xf [ 159.264103] bus_probe_device+0x22/0x65 [ 159.264103] device_add+0x368/0x434 [ 159.264103] ? pm_runtime_init+0xa5/0xac [ 159.264103] device_register+0x12/0x15 [ 159.264103] isa_register_driver+0xad/0x10a [ 159.264103] ? 0xd0d24000 [ 159.264103] aha1542_init+0x33/0x1000 [aha1542] [ 159.264103] do_one_initcall+0x60/0x11f [ 159.264103] ? _cond_resched+0x1e/0x22 [ 159.264103] ? slab_pre_alloc_hook+0x25/0x35 [ 159.264103] ? do_init_module+0x17/0x1ad [ 159.264103] ? kmem_cache_alloc+0x79/0x9c [ 159.264103] ? do_init_module+0x17/0x1ad [ 159.264103] do_init_module+0x46/0x1ad [ 159.264103] load_module+0x1708/0x1b23 [ 159.264103] ? kernel_read_file+0x116/0x143 [ 159.264103] sys_finit_module+0x62/0x67 [ 159.264103] do_int80_syscall_32+0x50/0x62 [ 159.264103] entry_INT80_32+0x2a/0x2a [ 159.264103] EIP: 0xb7f66a02 [ 159.264103] EFLAGS: 0292 CPU: 0 [ 159.264103] EAX: ffda EBX: 0003 ECX: 004fa970 EDX: [ 159.264103] ESI: 00563e30 EDI: 00563ef8 EBP: ESP: bf9100d8 [ 159.264103] DS: 007b ES: 007b FS: GS: 0033 SS: 007b [ 159.264103] Code: 40 54 e8 44 ff ff ff c7 43 54 00 00 00 00 5b 5d c3 55 89 e5 56 53 89 c3 83 ec 08 31 c0 c6 45 f3 01 c6 45 f4 08 8b 93 7c 04 00 00 04 02 00 6b d0 0b 8b b3 7c 04 00 00 03 93 88 04 00 00 01 c6 [ 159.264103] EIP: setup_mailboxes+0x1a/0xb5 [aha1542] SS:ESP: 0068:cbf07cf8 [ 159.264103] CR2: [ 159.479491] ---[ end trace 139123655cd08eca ]--- -- Ondrej Zary
Re: [PATCH v7 0/6] g_NCR5380: PDMA fixes and cleanup
On Monday 03 July 2017 09:59:05 Finn Thain wrote: > Ondrej, would you please test this new series? > > Changed since v1: > - PDMA transfer residual is calculated earlier. > - End of DMA flag check is now polled (if there is any residual). > > Changed since v2: > - Bail out of transfer loops when Gated IRQ gets asserted. > - Make udelay conditional on board type. > - Drop sg_tablesize patch due to performance regression. > > Changed since v3: > - Add Ondrej's workaround for corrupt WRITE commands on DTC boards. > - Reset the 53c400 logic after any short PDMA transfer. > - Don't fail the transfer if the 53c400 logic got a reset. > > Changed since v4: > - Bail out of transfer loops when Gated IRQ gets asserted. (Again.) > - Always call wait_for_53c80_registers() at end of transfer. > - Drain chip buffers after PDMA receive is interrupted. > - Rework residual calculation. > - Add new patch to correct DMA terminology. > > Changed since v5: > - Rework residual calculation to account for on-chip buffer swap. > - Attempt to retain the disconnect/IRQ detection in the DTC436 workaround. > - Move all DTC436 workarounds to final patch. > > Changed since v6: > - Fix residual calculation for the buffer timeout case. > - Iterate after sending final 128 bytes to check for buffer timeout. > - Don't log the residual value when it is known to be zero. > > > Finn Thain (2): > g_NCR5380: Cleanup comments and whitespace > g_NCR5380: Use unambiguous terminology for PDMA send and receive > > Ondrej Zary (4): > g_NCR5380: Fix PDMA transfer size > g_NCR5380: End PDMA transfer correctly on target disconnection > g_NCR5380: Re-work PDMA loops > g_NCR5380: Two DTC436 PDMA workarounds > > drivers/scsi/g_NCR5380.c | 277 > ++- 1 file changed, 155 > insertions(+), 122 deletions(-) Everything works fine! No corruption, no hangs, rescan-scsi-bus works. Tested cards: Canon FG2-5202 (53C400 chip, MMIO) DTC-3181L (DTCT-436P chip, PIO) HP C2502 (53C400A chip, PIO) Tested devices: QUANTUM LP240S GM240S01X 4.6 IBM DORS-32160 WA0A SONY CD-ROM CDU-415 1.1g SONY CD-ROM CDU-55S 1.0t Tested-by: Ondrej Zary -- Ondrej Zary
Re: [PATCH v6 0/6] g_NCR5380: PDMA fixes and cleanup
On Sunday 02 July 2017 05:11:27 Finn Thain wrote: > On Sat, 1 Jul 2017, Ondrej Zary wrote: > > The write corruption is still present - "start" must be rolled back in > > both IRQ and timeout cases. > > Your original algorithm aborts the transfer for a timeout. Same with mine. I do "start -= 2 * 128" even after timeout. > The bug must be a elsewhere. > > > And 128 B is not enough , 256 is OK (why did it work last time?). > > When I get contradictory results it usually means I booted the wrong build > or built the wrong branch. I've just retested PATCHv5, it really misses 128 bytes and works if I add "residual += 128;". > Actually, I think that adding 128 to the residual is correct in some > sitations, and 256 is correct in other situations. > > > We just wrote a buffer to the chip but the chip is writing the previous > > one to the drive - so if a problem arises, both buffers are lost. > > I see. I guess we have to take buffer swaps into account. > > > This fixes the corruption (although the "start > 0" check seems wrong > > now): --- a/drivers/scsi/g_NCR5380.c > > +++ b/drivers/scsi/g_NCR5380.c > > @@ -598,23 +598,17 @@ static inline int generic_NCR5380_psend(struct > > NCR5380_hostdata *hostdata, CSR_HOST_BUF_NOT_RDY, 0, > >hostdata->c400_ctl_status, > >CSR_GATED_53C80_IRQ, > > - CSR_GATED_53C80_IRQ, HZ / 64) < 0) > > - break; > > - > > - if (NCR5380_read(hostdata->c400_ctl_status) & > > - CSR_HOST_BUF_NOT_RDY) { > > + CSR_GATED_53C80_IRQ, HZ / 64) < 0 || > > + (NCR5380_read(hostdata->c400_ctl_status) & > > +(CSR_HOST_BUF_NOT_RDY | CSR_GATED_53C80_IRQ))) { > > You could add a printk to the timeout branch. If it executes, something is > seriously wrong. E.g. > > - break; > + { pr_err("send timeout %02x, %d/%d\n", > NCR5380_read(hostdata->c400_ctl_status), start, len); break; } Yes, timeouts do happen: [ 9671.909223] send timeout 14, 3840/4096 [ 9672.978079] send timeout 14, 2816/4096 [ 9675.323751] send timeout 14, 1280/4096 > > /* The chip has done a 128 B buffer swap but the first > > * buffer still has not reached the SCSI bus. > > */ > > if (start > 0) > > - start -= 128; > > + start -= 256; > > break; > > } > > BTW, that change carries the risk of 'start' going negative and the > residual exceeding the length of the original transfer. > > But I agree with you that there's a problem with the residual. > > If I understand correctly, the 53c400 can't do a buffer swap until the > disk acknowledges each of the 128 bytes from the buffer. But I guess the > first buffer is special because the disk will not see the first byte of > the transfer until after the first buffer swap. > > And it appears that the last buffer is also special: we have to wait for > CSR_HOST_BUF_NOT_RDY even after start == len otherwise we may not detect a > failure and fix the residual. So I think the datasheet is right; we have > to iterate until the block counter goes to zero. > > I think it is safe to say that when CSR_HOST_BUF_NOT_RDY, 'start' is > between 128 and 256 B ahead of the disk. Otherwise, the host buffer is > empty and 'start' is no more than 128 B ahead of the disk. > > > - if (NCR5380_read(hostdata->c400_ctl_status) & > > - CSR_GATED_53C80_IRQ) > > - break; > > - > > if (hostdata->io_port && hostdata->io_width == 2) > > outsw(hostdata->io_port + hostdata->c400_host_buf, > > src + start, 64); > > > > > > DTC seems to work too. > > OK. Thanks for testing. Please try the patch below on top of v6. It misses 256B blocks. It's caused by the timeouts, this patch fixes it: --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -598,11 +598,9 @@ static inline int generic_NCR5380_psend(struct NCR5380_hostdata *hostdata, CSR_HOST_BUF_NOT_RDY, 0, hostdata->c400_ctl_status, CSR_GATED_53C80_IRQ, - CSR_GATED_53C80_IRQ, HZ / 64) < 0) - break; - - if (NCR5380_read(hostdata->c400_ctl_status) & - CSR_HOST_BUF_NOT_RDY) { + CSR_GATED_53C80_IRQ, HZ / 64) < 0 || + (NCR5380_read(hostdata->c400_ctl_status) & +CSR_HOST_BUF_NOT_RDY)) { /* Both 128 B buffers are in use */ if (start >= 128) start -= 128; -- Ondrej Zary
Re: [PATCH v6 0/6] g_NCR5380: PDMA fixes and cleanup
On Saturday 01 July 2017 04:40:53 Finn Thain wrote: > Ondrej, would you please test this new series? > > Changed since v1: > - PDMA transfer residual is calculated earlier. > - End of DMA flag check is now polled (if there is any residual). > > Changed since v2: > - Bail out of transfer loops when Gated IRQ gets asserted. > - Make udelay conditional on board type. > - Drop sg_tablesize patch due to performance regression. > > Changed since v3: > - Add Ondrej's workaround for corrupt WRITE commands on DTC boards. > - Reset the 53c400 logic after any short PDMA transfer. > - Don't fail the transfer if the 53c400 logic got a reset. > > Changed since v4: > - Bail out of transfer loops when Gated IRQ gets asserted. (Again.) > - Always call wait_for_53c80_registers() at end of transfer. > - Drain chip buffers after PDMA receive is interrupted. > - Rework residual calculation. > - Add new patch to correct DMA terminology. > > Changed since v5: > - Rework residual calculation to account for on-chip buffer swap. > - Attempt to retain the disconnect/IRQ detection in the DTC436 workaround. > - Move all DTC436 workarounds to final patch. > > > Finn Thain (2): > g_NCR5380: Cleanup comments and whitespace > g_NCR5380: Use unambiguous terminology for PDMA send and receive > > Ondrej Zary (4): > g_NCR5380: Fix PDMA transfer size > g_NCR5380: End PDMA transfer correctly on target disconnection > g_NCR5380: Re-work PDMA loops > g_NCR5380: Various DTC436 workarounds > > drivers/scsi/g_NCR5380.c | 273 > ++- 1 file changed, 151 > insertions(+), 122 deletions(-) The write corruption is still present - "start" must be rolled back in both IRQ and timeout cases. And 128 B is not enough , 256 is OK (why did it work last time?). We just wrote a buffer to the chip but the chip is writing the previous one to the drive - so if a problem arises, both buffers are lost. This fixes the corruption (although the "start > 0" check seems wrong now): --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -598,23 +598,17 @@ static inline int generic_NCR5380_psend(struct NCR5380_hostdata *hostdata, CSR_HOST_BUF_NOT_RDY, 0, hostdata->c400_ctl_status, CSR_GATED_53C80_IRQ, - CSR_GATED_53C80_IRQ, HZ / 64) < 0) - break; - - if (NCR5380_read(hostdata->c400_ctl_status) & - CSR_HOST_BUF_NOT_RDY) { + CSR_GATED_53C80_IRQ, HZ / 64) < 0 || + (NCR5380_read(hostdata->c400_ctl_status) & +(CSR_HOST_BUF_NOT_RDY | CSR_GATED_53C80_IRQ))) { /* The chip has done a 128 B buffer swap but the first * buffer still has not reached the SCSI bus. */ if (start > 0) - start -= 128; + start -= 256; break; } - if (NCR5380_read(hostdata->c400_ctl_status) & - CSR_GATED_53C80_IRQ) - break; - if (hostdata->io_port && hostdata->io_width == 2) outsw(hostdata->io_port + hostdata->c400_host_buf, src + start, 64); DTC seems to work too. -- Ondrej Zary
Re: [PATCH v5 0/6] g_NCR5380: PDMA fixes and cleanup
On Friday 30 June 2017 09:12:37 Finn Thain wrote: > On Thu, 29 Jun 2017, Ondrej Zary wrote: > > The write corruption is still there. I'm afraid it can't be fixed > > without rolling "start" back (or inceasing residual) if an error > > occured, something like this: > > > > --- a/drivers/scsi/g_NCR5380.c > > +++ b/drivers/scsi/g_NCR5380.c > > @@ -619,6 +621,9 @@ static inline int generic_NCR5380_psend(struct > >(int)NCR5380_read(hostdata->c400_blk_cnt) * 128); > > > > if (residual != 0) { > > + residual += 128; > > /* 53c80 interrupt or transfer timeout. Reset 53c400 logic. */ > > NCR5380_write(hostdata->c400_ctl_status, CSR_RESET); > > NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); > > > > (seems to work - wrote 230MB and read it back with no differences) > > > > The corruption mechanism is: > > 1. Host buffer is ready so we write 128 B of data there and increment > >"start". > > 2. Chip swaps the buffers, decrements the block counter and starts > >writing the data to drive. > > 3. Drive does not like it (e.g. its buffer is full) so it disconnects. > > 4. Chip stops writing and asserts an IRQ. > > 5. We detect the IRQ. The block counter is already decremented, "start" > >is already incremented but the data was not written to the drive. > > OK. Thanks for that analysis. > > It sounds like the c400_blk_cnt value gives the number of buffer swaps > remaining. If so, that value isn't useful for calculating a residual. I'll > rework that calculation again. > > In your patch, the residual gets increased regardless of the actual cause > of the short transfer. Nothing prevents the residual from being increased > beyond the original length of the transfer (due to a flaky target or bus). > Therefore I've taken a slightly different approach in my patch (below). Yes, that's wrong. My original patch had "start -= 128" and then check for negative value. > > No more log spamming on DTC but reads are corrupted even more than > > before. The IRQ check after data transfer increases the chance of > > catching an IRQ before the buffer could become ready. > > If we delay the IRQ check, that just means that CSR_GATED_53C80_IRQ will > be detected a bit later (128 bytes later)... so not much difference. The main difference is that my original patch read the CSR once and then: - transfer data if the buffer is ready, ignoring any IRQ - if the buffer is not ready, check for an IRQ - if neither buffer is ready nor IRQ was asserted, check for timeout So yes, the IRQ will be detected 128 bytes later - but the IRQ is asserted at 3968 bytes which means the transfer will then be complete. > > This patch: > > --- a/drivers/scsi/g_NCR5380.c > > +++ b/drivers/scsi/g_NCR5380.c > > @@ -548,8 +548,10 @@ static inline int generic_NCR5380_precv(struct > > start += 128; > > > > if (NCR5380_read(hostdata->c400_ctl_status) & > > - CSR_GATED_53C80_IRQ) > > + CSR_GATED_53C80_IRQ) { > > + printk("r irq at start=%d basr=0x%02x\n", start, > > NCR5380_read(BUS_AND_STATUS_REG)); break; > > + } > > } > > > > residual = len - start; > > > > produces lots of these lines: > > [ 896.194054] r irq at start=128 basr=0x98 > > [ 896.197758] r irq at start=3968 basr=0x98 > > Assuming that the registers are available and valid, the value 0x98 means > BASR_END_DMA_TRANSFER | BASR_IRQ | BASR_PHASE_MATCH. There is no > BASR_BUSY_ERROR here, so the cause of the CSR_GATED_53C80_IRQ must be that > the 53c400 has terminated the transfer by asserting /EOP. That shouldn't > happen before before the counters run down. > > It doesn't make sense. So maybe the 53c80 registers are not valid at this > point? That means a phase mismatch can't be excluded... unlikely at 128 > bytes into the transfer. Busy error? Also unlikely. > > I have to conclude that CSR_GATED_53C80_IRQ and BASR_END_DMA_TRANSFER > can't be trusted on this board. I guess that's why you examine the BASR > directly in your original algorithm but ignore BASR_END_DMA_TRANSFER. Exactly, BASR_END_DMA_TRANSFER causes problems on DTC. > It does look like some kind of timing issue: the "start" value above > changes from one log message to the next. Who knows? Only that two values (128 and 3968) appeared. 3968 = 4096-128, one block before the end of transfer. So probably BASR_END_DMA_TRANSFER is asserted one block earlier (i.e.
Re: [PATCH v5 0/6] g_NCR5380: PDMA fixes and cleanup
On Thursday 29 June 2017 07:24:18 Finn Thain wrote: > Ondrej, would you please test this new series? > > Changed since v1: > - PDMA transfer residual is calculated earlier. > - End of DMA flag check is now polled (if there is any residual). > > Changed since v2: > - Bail out of transfer loops when Gated IRQ gets asserted. > - Make udelay conditional on board type. > - Drop sg_tablesize patch due to performance regression. > > Changed since v3: > - Add Ondrej's workaround for corrupt WRITE commands on DTC boards. > - Reset the 53c400 logic after any short PDMA transfer. > - Don't fail the transfer if the 53c400 logic got a reset. > > Changed since v4: > - Bail out of transfer loops when Gated IRQ gets asserted. (Again.) > - Always call wait_for_53c80_registers() at end of transfer. > - Drain chip buffers after PDMA receive is interrupted. > - Rework residual calculation. > - Add new patch to correct DMA terminology. > > > Finn Thain (2): > g_NCR5380: Cleanup comments and whitespace > g_NCR5380: Use unambiguous terminology for PDMA send and receive > > Ondrej Zary (4): > g_NCR5380: Fix PDMA transfer size > g_NCR5380: End PDMA transfer correctly on target disconnection > g_NCR5380: Limit PDMA send to 512 B to avoid data corruption on > DTC3181E > g_NCR5380: Re-work PDMA loops > > drivers/scsi/g_NCR5380.c | 260 > +-- 1 file changed, 139 > insertions(+), 121 deletions(-) This fixes the DTC read corruption, although I don't like the repeated ctl_status register reads: --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -533,7 +533,7 @@ static inline int generic_NCR5380_precv(struct NCR5380_hostdata *hostdata, break; if (NCR5380_read(hostdata->c400_ctl_status) & - CSR_HOST_BUF_NOT_RDY) + CSR_GATED_53C80_IRQ && (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)) break; if (hostdata->io_port && hostdata->io_width == 2) @@ -546,10 +546,6 @@ static inline int generic_NCR5380_precv(struct NCR5380_hostdata *hostdata, memcpy_fromio(dst + start, hostdata->io + NCR53C400_host_buffer, 128); start += 128; - - if (NCR5380_read(hostdata->c400_ctl_status) & - CSR_GATED_53C80_IRQ) - break; } residual = len - start; Writes seem to work correctly. -- Ondrej Zary
Re: [PATCH v5 0/6] g_NCR5380: PDMA fixes and cleanup
On Thursday 29 June 2017 07:24:18 Finn Thain wrote: > Ondrej, would you please test this new series? > > Changed since v1: > - PDMA transfer residual is calculated earlier. > - End of DMA flag check is now polled (if there is any residual). > > Changed since v2: > - Bail out of transfer loops when Gated IRQ gets asserted. > - Make udelay conditional on board type. > - Drop sg_tablesize patch due to performance regression. > > Changed since v3: > - Add Ondrej's workaround for corrupt WRITE commands on DTC boards. > - Reset the 53c400 logic after any short PDMA transfer. > - Don't fail the transfer if the 53c400 logic got a reset. > > Changed since v4: > - Bail out of transfer loops when Gated IRQ gets asserted. (Again.) > - Always call wait_for_53c80_registers() at end of transfer. > - Drain chip buffers after PDMA receive is interrupted. > - Rework residual calculation. > - Add new patch to correct DMA terminology. > > > Finn Thain (2): > g_NCR5380: Cleanup comments and whitespace > g_NCR5380: Use unambiguous terminology for PDMA send and receive > > Ondrej Zary (4): > g_NCR5380: Fix PDMA transfer size > g_NCR5380: End PDMA transfer correctly on target disconnection > g_NCR5380: Limit PDMA send to 512 B to avoid data corruption on > DTC3181E > g_NCR5380: Re-work PDMA loops > > drivers/scsi/g_NCR5380.c | 260 > +-- 1 file changed, 139 > insertions(+), 121 deletions(-) The write corruption is still there. I'm afraid it can't be fixed without rolling "start" back (or inceasing residual) if an error occured, something like this: --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -619,6 +621,9 @@ static inline int generic_NCR5380_psend(struct NCR5380_hostdata *hostdata, (int)NCR5380_read(hostdata->c400_blk_cnt) * 128); if (residual != 0) { + residual += 128; /* 53c80 interrupt or transfer timeout. Reset 53c400 logic. */ NCR5380_write(hostdata->c400_ctl_status, CSR_RESET); NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); (seems to work - wrote 230MB and read it back with no differences) The corruption mechanism is: 1. Host buffer is ready so we write 128 B of data there and increment "start". 2. Chip swaps the buffers, decrements the block counter and starts writing the data to drive. 3. Drive does not like it (e.g. its buffer is full) so it disconnects. 4. Chip stops writing and asserts an IRQ. 5. We detect the IRQ. The block counter is already decremented, "start" is already incremented but the data was not written to the drive. No more log spamming on DTC but reads are corrupted even more than before. The IRQ check after data transfer increases the chance of catching an IRQ before the buffer could become ready. This patch: --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -548,8 +548,10 @@ static inline int generic_NCR5380_precv(struct NCR5380_hostdata *hostdata, start += 128; if (NCR5380_read(hostdata->c400_ctl_status) & - CSR_GATED_53C80_IRQ) + CSR_GATED_53C80_IRQ) { + printk("r irq at start=%d basr=0x%02x\n", start, NCR5380_read(BUS_AND_STATUS_REG)); break; + } } residual = len - start; produces lots of these lines: [ 896.194054] r irq at start=128 basr=0x98 [ 896.197758] r irq at start=3968 basr=0x98 -- Ondrej Zary
Re: [PATCH v4 0/5] g_NCR5380: PDMA fixes and cleanup
On Wednesday 28 June 2017 06:04:36 Finn Thain wrote: > Ondrej, would you please test this new series? > > Changed since v1: > - PDMA transfer residual is calculated earlier. > - End of DMA flag check is now polled (if there is any residual). > > Changed since v2: > - Bail out of transfer loops when Gated IRQ gets asserted. > - Make udelay conditional on board type. > - Drop sg_tablesize patch due to performance regression. > > Changed since v3: > - Add Ondrej's workaround for corrupt WRITE commands on DTC boards. > - Reset the 53c400 logic after any short PDMA transfer. > - Don't fail the transfer if the 53c400 logic got a reset. > > > Finn Thain (1): > g_NCR5380: Cleanup comments and whitespace > > Ondrej Zary (4): > g_NCR5380: Fix PDMA transfer size > g_NCR5380: End PDMA transfer correctly on target disconnection > g_NCR5380: Limit PDMA send to 512 B to avoid random corruption on > DTC3181E > g_NCR5380: Re-work PDMA loops > > drivers/scsi/g_NCR5380.c | 239 > --- 1 file changed, 120 > insertions(+), 119 deletions(-) Now read seems to work on non-DTC chips. Writes continue in PDMA after disconnect but there's a corruption - one 128 B block missing on disconnect. On DTC, the log is spammed with errors like this: sd 2:0:1:0: [sdb] tag#0 generic_NCR5380_pread: End of DMA timeout (0) They're cause by read corruption on DTC: pread() is breaking at start=3968 because of an end-of-DMA IRQ (BASR=0x98) but pdma_residual is set to zero (block counter is zero because the data was read into the buffer but we did not read it from there). So we lose one buffer of data on each 4 KB read. The PDMA is then reset which probably means BASR_END_DMA_TRANSFER will not be asserted. -- Ondrej Zary
Re: [PATCH v3 0/4] g_NCR5380: PDMA fixes and cleanup
On Tuesday 27 June 2017 03:49:16 Finn Thain wrote: > On Mon, 26 Jun 2017, Ondrej Zary wrote: > > No apparent change in behavior, the first write test resulted in: > > [ 842.830802] sd 2:0:1:0: [sdb] tag#0 53c80 registers not accessible, > > device will be reset [ 842.830802] sd 2:0:1:0: [sdb] tag#0 switching to > > slow handshake > > > > Checking for IRQ after poll_politely2 does not seem right because we can > > miss the buffer ready signal. > > How so? As long as there's no gated IRQ, we poll for buffer readiness > until timeout. And when there is a gated IRQ, we break both the polling > loop and the transfer loop immediately. Your code and mine are basically > in agreement here. Yes, it stops transfer when an IRQ arrives. But the host buffer could be ready at the same time. The IRQ can be an "end-of-DMA" IRQ (IIRC DTC chips assert this earlier than 53C400). Or just a disconnect that occured right now but the chip already read a buffer full of data. > > According to my tests, buffer ready signal is most important - if there > > is any data to read/write, do the transfer. If not, only then check why > > - maybe we got an IRQ (that terminated PDMA). Or no IRQ, sometimes the > > wait for buffer ready times out - we need to terminate PDMA manually > > then (reset). > > > > Then 53C80 registers should become ready. > > You seem to be saying that we should ignore the IRQ signal if the buffers > have become ready. Maybe so. Can we try simply resetting the block > counter? (I could imagine that the 53c400 core might leave the 53c80 > registers inaccessible unless we keep accessing the buffers in the 53c400 > core until the transfer is done.) We can't reset the block counter because 0 means 256 blocks to transfer (page 13 in datasheet). Yes, the 53C80 registers seem to become available only when the PDMA transfer ends by either: 1. transferring all blocks (block counter decrementing to zero) 2. IRQ 3. reset > BTW, with regard to your patch, note that this construct is race prone: > > while (1) { /* monitor IRQ while waiting for host buffer */ > csr = NCR5380_read(hostdata->c400_ctl_status); > if (!(csr & CSR_HOST_BUF_NOT_RDY)) > break; > if (csr & CSR_GATED_53C80_IRQ) { > basr = NCR5380_read(BUS_AND_STATUS_REG); > if (!(basr & BASR_PHASE_MATCH) || > (basr & BASR_BUSY_ERROR)) { > printk("basr=0x%02x csr=0x%02x at start=%d\n", basr, > csr, start); > goto out_wait; > } > } > if (retries-- < 1) { > shost_printk(KERN_ERR, hostdata->host, "53C400r: host buffer > not ready in > time\n"); NCR5380_write(hostdata->c400_ctl_status, CSR_RESET); > NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); > goto out_wait; > } > } > > This code can "goto out_wait" when !(csr & CSR_HOST_BUF_NOT_RDY). It > depends on timing. This would seem to be contrary to your stated aim. > > Moreover, this code can also "break" when (csr & CSR_GATED_53C80_IRQ). > That depends on timing too. But this may be an improvement on my code if > it allows the 53c80 registers to become accessible, by allowing the block > counter to be decremented. Yes, it continue the transfer even if the IRQ is asserted - as long as the buffer is ready. That's intended. > The uncertainty here was one of the reasons I reworked this code. My version reads CSR only once per loop but that probably does not help at all as the HW state could change anytime. The chip's design seems to be very race-prone. > > This is a log from writing 230 MB file using my code with some debug > > prints, on a NCR53C400. No 53C80 timeouts, only disconnects and some > > host buffer timeouts (maybe the drive sometimes just slows down without > > disconnecting?) > > > > [ 3378.503828] basr=0x10 csr=0xd5 at start=512 > > [ 3461.257973] w basr=0x10 csr=0x95 at start=3840 > > [ 3461.838225] w basr=0x10 csr=0x95 at start=3840 > > [ 3462.683446] w basr=0x10 csr=0x95 at start=3840 > > [ 3463.416911] w basr=0x10 csr=0x95 at start=3840 > > [ 3465.117804] scsi host2: 53C400w: host buffer not ready in time > > [ 3465.276375] w basr=0x10 csr=0x95 at start=3328 > > [ 3466.457701] w basr=0x10 csr=0x95 at start=1792 > > [ 3467.019643] scsi host2: 53C400w: host buffer not ready in time > > [ 3467.619058] scsi host2: 53C400w: host buffer not ready in time > > [ 3467.799619] w basr=0x10 csr=0x95 at start=3840 > > [ 3552.123501] w basr=0x10 csr=0x95 at start=2304 > > [ 3552.77
Re: [PATCH v3 0/4] g_NCR5380: PDMA fixes and cleanup
On Tuesday 27 June 2017 14:42:29 Finn Thain wrote: > On Tue, 27 Jun 2017, Ondrej Zary wrote: > > BTW. I've probably found the DTC write corruption. Added the following > > check (13 is host buffer index register) - > > That register is not mentioned in my 53c400 datasheet. Yes, it's not there. But we don't have 53C400A and DTC436 datasheets (this register works on both). > > and it triggers sometimes: the value is 1 instead of 0. As we use only > > 16-bit writes, I don't see how the value could ever be odd. Looks like a > > bug in the chip. The index register corrupts during the transfer, not > > after IRQ or timeout. The same check at beginning of pwrite() did not > > trigger. > > Are you reading this register at the right moment? Have you tried waiting > for it to reach zero, as in, > > if (NCR5380_poll_politely(hostdata, 13, 0xff, 0, HZ / 64) < 0) > /* printk, reset etc */; I have not but will try (expecting that it will not change by itself). > Even if this is a reliable way to detect a short transfer, it would be > nice to know the root cause. But I'm being unrealistic: the DTC436 vendor > never responded to my requests for technical documentation. According to the data corruption observed, it's not a short transfer. The corruption is always the same: one byte missing at the beginning of a 128 B block. It happens only with slow Quantum LPS 240 drive, not with faster IBM DORS-32160. > > The index register is not writable so we must(?) reset the PDMA engine > > to recover. However, this quick attempt to fix does not work, maybe we > > should reload the block count and continue? > > I don't know if it is possible to recover. If the last byte never reached > the scsi bus, then once you reset the 53c400 core, you need the driver to > perform a single-byte PIO transfer after the short PDMA transfer. This > would require that you set the residual appropriately (though in my > experience that may not be sufficient). > > It may be better to simply limit the transfer to 512 bytes instead of > attempting to recover based on an undocumented (?) register, etc. Seems > like a bit of a hack. > > > --- a/drivers/scsi/g_NCR5380.c > > +++ b/drivers/scsi/g_NCR5380.c > > @@ -595,7 +603,13 @@ static inline int generic_NCR5380_pwrite(struct > > NCR5380_hostdata *hostdata, > > goto out_wait; > > } > > } > > - > > + idx = NCR5380_read(13); > > + if (idx != 0) { > > + printk("host idx=%d, start=%d\n", idx, start); > > + NCR5380_write(hostdata->c400_ctl_status, > > CSR_RESET); + > > NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); + > > goto out_wait; > > + } > > if (hostdata->io_port && hostdata->io_width == 2) > > outsw(hostdata->io_port + > > hostdata->c400_host_buf, src + start, 64); > > I find it hard to reason about this code. For example, out_wait is to be > removed. Let's get the preceding patches working and signed-off. Please go > ahead and use a 512 B transfer for DTC436 testing if that will help get > this patch series over the line. OK, I agree. Let's fix the problems first and leave this hack for later. -- Ondrej Zary
Re: [PATCH v3 0/4] g_NCR5380: PDMA fixes and cleanup
On Monday 26 June 2017, Ondrej Zary wrote: > On Monday 26 June 2017 09:30:33 Finn Thain wrote: > > Ondrej, would you please test this new series? > > > > Changed since v1: > > - PDMA transfer residual is calculated earlier. > > - End of DMA flag check is now polled (if there is any residual). > > > > Changed since v2: > > - Bail out of transfer loops when Gated IRQ gets asserted. > > - Make udelay conditional on board type. > > - Drop sg_tablesize patch due to performance regression. > > > > > > Finn Thain (1): > > g_NCR5380: Cleanup comments and whitespace > > > > Ondrej Zary (3): > > g_NCR5380: Fix PDMA transfer size > > g_NCR5380: End PDMA transfer correctly on target disconnection > > g_NCR5380: Re-work PDMA loops > > > > drivers/scsi/g_NCR5380.c | 239 > > +++ 1 file changed, 116 > > insertions(+), 123 deletions(-) BTW. I've probably found the DTC write corruption. Added the following check (13 is host buffer index register) - and it triggers sometimes: the value is 1 instead of 0. As we use only 16-bit writes, I don't see how the value could ever be odd. Looks like a bug in the chip. The index register corrupts during the transfer, not after IRQ or timeout. The same check at beginning of pwrite() did not trigger. The index register is not writable so we must(?) reset the PDMA engine to recover. However, this quick attempt to fix does not work, maybe we should reload the block count and continue? --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -595,7 +603,13 @@ static inline int generic_NCR5380_pwrite(struct NCR5380_hostdata *hostdata, goto out_wait; } } - + idx = NCR5380_read(13); + if (idx != 0) { + printk("host idx=%d, start=%d\n", idx, start); + NCR5380_write(hostdata->c400_ctl_status, CSR_RESET); + NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); + goto out_wait; + } if (hostdata->io_port && hostdata->io_width == 2) outsw(hostdata->io_port + hostdata->c400_host_buf, src + start, 64); -- Ondrej Zary
Re: [PATCH v3 0/4] g_NCR5380: PDMA fixes and cleanup
On Monday 26 June 2017 09:30:33 Finn Thain wrote: > Ondrej, would you please test this new series? > > Changed since v1: > - PDMA transfer residual is calculated earlier. > - End of DMA flag check is now polled (if there is any residual). > > Changed since v2: > - Bail out of transfer loops when Gated IRQ gets asserted. > - Make udelay conditional on board type. > - Drop sg_tablesize patch due to performance regression. > > > Finn Thain (1): > g_NCR5380: Cleanup comments and whitespace > > Ondrej Zary (3): > g_NCR5380: Fix PDMA transfer size > g_NCR5380: End PDMA transfer correctly on target disconnection > g_NCR5380: Re-work PDMA loops > > drivers/scsi/g_NCR5380.c | 239 > +++ 1 file changed, 116 > insertions(+), 123 deletions(-) No apparent change in behavior, the first write test resulted in: [ 842.830802] sd 2:0:1:0: [sdb] tag#0 53c80 registers not accessible, device will be reset [ 842.830802] sd 2:0:1:0: [sdb] tag#0 switching to slow handshake Checking for IRQ after poll_politely2 does not seem right because we can miss the buffer ready signal. According to my tests, buffer ready signal is most important - if there is any data to read/write, do the transfer. If not, only then check why - maybe we got an IRQ (that terminated PDMA). Or no IRQ, sometimes the wait for buffer ready times out - we need to terminate PDMA manually then (reset). Then 53C80 registers should become ready. This is a log from writing 230 MB file using my code with some debug prints, on a NCR53C400. No 53C80 timeouts, only disconnects and some host buffer timeouts (maybe the drive sometimes just slows down without disconnecting?) [ 3378.503828] basr=0x10 csr=0xd5 at start=512 [ 3461.257973] w basr=0x10 csr=0x95 at start=3840 [ 3461.838225] w basr=0x10 csr=0x95 at start=3840 [ 3462.683446] w basr=0x10 csr=0x95 at start=3840 [ 3463.416911] w basr=0x10 csr=0x95 at start=3840 [ 3465.117804] scsi host2: 53C400w: host buffer not ready in time [ 3465.276375] w basr=0x10 csr=0x95 at start=3328 [ 3466.457701] w basr=0x10 csr=0x95 at start=1792 [ 3467.019643] scsi host2: 53C400w: host buffer not ready in time [ 3467.619058] scsi host2: 53C400w: host buffer not ready in time [ 3467.799619] w basr=0x10 csr=0x95 at start=3840 [ 3552.123501] w basr=0x10 csr=0x95 at start=2304 [ 3552.771223] w basr=0x10 csr=0x95 at start=1280 [ 3554.556451] w basr=0x10 csr=0x95 at start=2816 [ 3555.229646] w basr=0x10 csr=0x95 at start=1792 [ 3555.630632] scsi host2: 53C400w: host buffer not ready in time [ 3555.774560] w basr=0x10 csr=0x95 at start=768 [ 3625.541608] w basr=0x10 csr=0x95 at start=3328 [ 3640.099861] w basr=0x10 csr=0x95 at start=1792 [ 3641.442671] w basr=0x10 csr=0x95 at start=2816 [ 3641.865469] w basr=0x10 csr=0x95 at start=768 [ 3642.939223] w basr=0x10 csr=0x95 at start=1280 [ 3643.356858] w basr=0x10 csr=0x95 at start=3328 [ 3643.701636] w basr=0x10 csr=0x95 at start=3840 [ 3645.153405] w basr=0x10 csr=0x95 at start=2304 [ 3646.135642] w basr=0x10 csr=0x95 at start=1280 [ 3647.007321] w basr=0x10 csr=0x95 at start=2816 [ 3648.065874] w basr=0x10 csr=0x95 at start=3328 [ 3650.071961] w basr=0x10 csr=0x95 at start=1280 [ 3650.827630] w basr=0x10 csr=0x95 at start=1792 [ 3651.827011] w basr=0x10 csr=0x95 at start=2816 [ 3652.559984] w basr=0x10 csr=0x95 at start=2816 [ 3653.203566] w basr=0x10 csr=0x95 at start=3328 [ 3653.594376] w basr=0x10 csr=0x95 at start=1280 [ 3653.903437] w basr=0x10 csr=0x95 at start=3840 [ 3654.305753] w basr=0x10 csr=0x95 at start=1792 [ 3654.676009] w basr=0x10 csr=0x95 at start=2304 [ 3655.367686] w basr=0x10 csr=0x95 at start=2816 [ 3655.733854] w basr=0x10 csr=0x95 at start=768 [ 3656.075023] w basr=0x10 csr=0x95 at start=3328 [ 3656.493046] w basr=0x10 csr=0x95 at start=2816 [ 3657.208089] w basr=0x10 csr=0x95 at start=1280 [ 3657.537223] w basr=0x10 csr=0x95 at start=1280 And this is from reading the file back: [ 3799.053067] basr=0x10 csr=0xd5 at start=512 [ 3801.056337] basr=0x10 csr=0xd5 at start=3584 [ 3976.323836] scsi host2: 53C400r: host buffer not ready in time [ 3976.404699] basr=0x10 csr=0xd5 at start=512 [ 3977.800647] basr=0x10 csr=0xd5 at start=512 [ 3979.240611] scsi host2: 53C400r: host buffer not ready in time [ 3979.320698] basr=0x10 csr=0xd5 at start=512 [ 3980.040220] scsi host2: 53C400r: host buffer not ready in time [ 3980.096401] basr=0x10 csr=0xd5 at start=512 [ 3980.394854] scsi host2: 53C400r: host buffer not ready in time -- Ondrej Zary
Re: [PATCH v2 0/5] g_NCR5380: PDMA fixes and cleanup
On Monday 26 June 2017, Finn Thain wrote: > On Sun, 25 Jun 2017, Ondrej Zary wrote: > > It mostly works, but there are some problems: > > > > It's not reliable - we continue the data transfer after poll_politely2 > > returns zero but we don't know if it returned because of host buffer > > being ready of because of an IRQ. So if a device disconnects during > > write, we continue to fill the buffer and only then find out that wait > > for 53c80 registers timed out. Then PDMA gets disabled: > > [ 3458.774251] sd 2:0:1:0: [sdb] tag#0 53c80 registers not accessible, > > device will be reset [ 3458.774251] sd 2:0:1:0: [sdb] tag#0 switching to > > slow handshake > > Sorry about that. I messed up the Gated-IRQ-is-asserted case when I > changed the algorithm to avoid adding more polling loops. > > > We can just reset and continue with a new PDMA transfer. > > We should only reset the 53c400 logic when there is a real failure (like > no access to 53c80 registers). If a reset is needed to handle normal > target behaviour (like disconnection during a slow transfer) then we are > doing something wrong. The reset is probably the only way to terminate a PDMA transfer. > > Found no problems with reads. But when this happens during a write, we > > might have lost some data buffers that we need to transfer again. The > > chip's PDMA block counter does not seem to be very helpful here - > > testing shows that either one buffer is missing in the file or is > > duplicated. > > > > That's why my code had separate host buffer ready and IRQ checks. Host > > buffer first - if it's ready, transfer the data. If not, check for IRQ - > > if it was an error, rollback 2 buffers (the same if the host buffer is > > not ready in time). > > In v3 of the patch series I've fixed the Gated IRQ logic so the transfer > loop will terminate early. > > > There's also a performance regression on DTC436 - the sg_tablesize limit > > affects performance badly. > > Before: > > # hdparm -t --direct /dev/sdb > > > > /dev/sdb: > > Timing O_DIRECT disk reads: 4 MB in 3.21 seconds = 1.25 MB/sec > > > > Now: > > # hdparm -t --direct /dev/sdb > > > > /dev/sdb: > > Timing O_DIRECT disk reads: 4 MB in 4.89 seconds = 837.69 kB/sec > > The lost throughput can perhaps be explained by extra kernel-mode CPU > overhead. Next time maybe check for that with "time hdparm". Anyway, since > you have a patch, we should try to avoid this regression. I don't think the CPU is that slow. It probably decreases the SCSI read command length and we must wait for the drive to process each command (it probably does no read-ahead). > > We should limit the transfer size instead: > > --- a/drivers/scsi/g_NCR5380.c > > +++ b/drivers/scsi/g_NCR5380.c > > @@ -45,7 +45,8 @@ > > int c400_blk_cnt; \ > > int c400_host_buf; \ > > int io_width; \ > > - int pdma_residual > > + int pdma_residual; \ > > + int board; > > > > #define NCR5380_dma_xfer_lengeneric_NCR5380_dma_xfer_len > > #define NCR5380_dma_recv_setup generic_NCR5380_pread > > @@ -247,7 +248,6 @@ static int generic_NCR5380_init_one(struct > > scsi_host_template *tpnt, case BOARD_DTC3181E: > > ports = dtc_3181e_ports; > > magic = ncr_53c400a_magic; > > - tpnt->sg_tablesize = 1; > > break; > > } > > I've dropped my "sg_tablesize = 1" patch from the v3 series. > > > @@ -317,6 +317,7 @@ static int generic_NCR5380_init_one(struct > > scsi_host_template *tpnt, } > > hostdata = shost_priv(instance); > > > > + hostdata->board = board; > > hostdata->io = iomem; > > hostdata->region_size = region_size; > > I've added the hostdata->board variable in v3. It looks like we are going > to need it one way or another. > > > @@ -625,6 +626,9 @@ static int generic_NCR5380_dma_xfer_len(struct > > NCR5380_hostdata *hostdata, /* 53C400 datasheet: non-modulo-128-byte > > transfers should use PIO */ if (transfersize % 128) > > transfersize = 0; > > + /* Limit transfers to 512B to prevent random write corruption on > > DTC */ + if (hostdata->board == BOARD_DTC3181E && transfersize > > > 512) + transfersize = 512; > > > > return min(transfersize, DMA_MAX_SIZE); > > } > > > > > > No data corruption > > How did you confirm
Re: [PATCH v2 0/5] g_NCR5380: PDMA fixes and cleanup
On Saturday 24 June 2017 08:37:36 Finn Thain wrote: > Ondrej, would you please test this new series? > > Changed since v1: > - PDMA transfer residual is calculated earlier. > - End of DMA flag check is now polled (if there is any residual). > > > Finn Thain (2): > g_NCR5380: Limit sg_tablesize to avoid PDMA read overruns on DTC436 > g_NCR5380: Cleanup comments and whitespace > > Ondrej Zary (3): > g_NCR5380: Fix PDMA transfer size > g_NCR5380: End PDMA transfer correctly on target disconnection > g_NCR5380: Re-work PDMA loops > > drivers/scsi/g_NCR5380.c | 231 > ++- 1 file changed, 107 > insertions(+), 124 deletions(-) It mostly works, but there are some problems: It's not reliable - we continue the data transfer after poll_politely2 returns zero but we don't know if it returned because of host buffer being ready of because of an IRQ. So if a device disconnects during write, we continue to fill the buffer and only then find out that wait for 53c80 registers timed out. Then PDMA gets disabled: [ 3458.774251] sd 2:0:1:0: [sdb] tag#0 53c80 registers not accessible, device will be reset [ 3458.774251] sd 2:0:1:0: [sdb] tag#0 switching to slow handshake We can just reset and continue with a new PDMA transfer. Found no problems with reads. But when this happens during a write, we might have lost some data buffers that we need to transfer again. The chip's PDMA block counter does not seem to be very helpful here - testing shows that either one buffer is missing in the file or is duplicated. That's why my code had separate host buffer ready and IRQ checks. Host buffer first - if it's ready, transfer the data. If not, check for IRQ - if it was an error, rollback 2 buffers (the same if the host buffer is not ready in time). There's also a performance regression on DTC436 - the sg_tablesize limit affects performance badly. Before: # hdparm -t --direct /dev/sdb /dev/sdb: Timing O_DIRECT disk reads: 4 MB in 3.21 seconds = 1.25 MB/sec Now: # hdparm -t --direct /dev/sdb /dev/sdb: Timing O_DIRECT disk reads: 4 MB in 4.89 seconds = 837.69 kB/sec We should limit the transfer size instead: --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -45,7 +45,8 @@ int c400_blk_cnt; \ int c400_host_buf; \ int io_width; \ - int pdma_residual + int pdma_residual; \ + int board; #define NCR5380_dma_xfer_lengeneric_NCR5380_dma_xfer_len #define NCR5380_dma_recv_setup generic_NCR5380_pread @@ -247,7 +248,6 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, case BOARD_DTC3181E: ports = dtc_3181e_ports; magic = ncr_53c400a_magic; - tpnt->sg_tablesize = 1; break; } @@ -317,6 +317,7 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, } hostdata = shost_priv(instance); + hostdata->board = board; hostdata->io = iomem; hostdata->region_size = region_size; @@ -625,6 +626,9 @@ static int generic_NCR5380_dma_xfer_len(struct NCR5380_hostdata *hostdata, /* 53C400 datasheet: non-modulo-128-byte transfers should use PIO */ if (transfersize % 128) transfersize = 0; + /* Limit transfers to 512B to prevent random write corruption on DTC */ + if (hostdata->board == BOARD_DTC3181E && transfersize > 512) + transfersize = 512; return min(transfersize, DMA_MAX_SIZE); } No data corruption and no performance regression: # hdparm -t --direct /dev/sdb /dev/sdb: Timing O_DIRECT disk reads: 4 MB in 3.25 seconds = 1.23 MB/sec As the data corruption affects only writes, we could keep transfersize unlimited for reads: + /* Limit write transfers to 512B to prevent random corruption on DTC */ + if (hostdata->board == BOARD_DTC3181E && + cmd->sc_data_direction == DMA_TO_DEVICE && transfersize > 512) + transfersize = 512; So we can get some performance gain at least for reads: # hdparm -t --direct /dev/sdb /dev/sdb: Timing O_DIRECT disk reads: 6 MB in 4.17 seconds = 1.44 MB/sec -- Ondrej Zary
Re: [PATCH 0/4] g_NCR5380: PDMA fixes and cleanup
On Friday 23 June 2017 13:01:53 Finn Thain wrote: > On Fri, 23 Jun 2017, I wrote: > > Does this patch help? It should be applied on top of this series of 4. > > Sorry, I sent the wrong diff. Please try this patch instead. Thanks, much better now: both HDD and CD-ROM seem to work on DTC and non-DTC chips. I get many of these messages with CD-ROM: [ 912.397076] generic_NCR5380_pread: No end dma signal (4096/4096) [ 913.141225] generic_NCR5380_pread: No end dma signal (4096/4096) Maybe just remove this error message as in my original patch? -- Ondrej Zary
Re: [PATCH 0/4] g_NCR5380: PDMA fixes and cleanup
On Thursday 15 June 2017 14:17:56 Finn Thain wrote: > Ondrej, would you please test this patch series? One of your patches > has been modified slightly and the two I wrote are untested. Works only with HDD on non-DTC chips. CD-ROM hangs. DTC hangs even with HDD. The PDMA code really needs to be fixed. -- Ondrej Zary
Re: g_NCR5380 PDMA, was Re: [PATCH 0/6] ncr5380: Miscellaneous minor patches
On Sunday 19 February 2017 00:27:55 Finn Thain wrote: > On Sat, 18 Feb 2017, Ondrej Zary wrote: > > On Friday 17 February 2017 23:38:12 Finn Thain wrote: > > > On Thu, 16 Feb 2017, Ondrej Zary wrote: > > > > On Tuesday 31 January 2017 02:31:45 Finn Thain wrote: > > > > [...] > > > > > > > > > Are you trying to figure out which commands are going to > > > > > disconnect during a transfer? This is really a function of the > > > > > firmware in the target; there are no good heuristics AFAICT, so > > > > > the PDMA algorithm has to be robust. mac_scsi has to cope with > > > > > this too. > > > > > > > > > > Does the problem go away when you assign no IRQ? When > > > > > instance->irq == NO_IRQ, the core driver will inhibit disconnect > > > > > privileges. > > > > > > > > Yes, it seems to run fine with IRQ/disconnect disabled. With IRQ > > > > enabled, "dd if=/dev/sr0 of=anything" stops after a while. > > > > > > When you say "stops", do you mean an infinite loop in > > > generic_NCR5380_pread or does the loop complete (which would > > > presumably leave the target stuck in DATA IN phase, and a scsi command > > > timeout would probably follow after 30 seconds...) > > > > I've added timeouts to the possibly-infinite loops. It times out waiting > > for the host buffer to become ready. > > In mac_scsi you'll find that the PDMA loop exploits the 15ms poll_politely > time limit to give the target device time to catch up. You might want to > do something similar. > > > Then everything breaks. Now I found why: pread() returns without waiting > > for the 53C80 registers to be ready. > > Ouch! You can't return control to the core driver when the 53C80 core is > unavailable. That would need special handling: the core driver would have > to fail the scsi command and reset the device (and bus), based on the > result you return from NCR5380_dma_recv_setup/NCR5380_dma_send_setup. > > > Adding the wait allows to continue in PIO mode with "tag#0 switching to > > slow handshake". > > I don't think this is the code path you want. The target isn't really > broken. But yes, we could use PIO as a slow workaround for fragile PDMA > logic. Yes, we don't want that. > > > > I get gated 53C80 IRQ, BASR=0x10, MODE=0x0e, STATUS=0x7c. > > > > > > You can use NCR5380_print() to get a decoded register dump. > > > > > > When I decode the above values I get, > > > > > > BASR = 0x10 = BASR_IRQ > > > MODE = 0x0e = MR_ENABLE_EOP_INTR | MR_MONITOR_BSY | MR_DMA_MODE > > > STATUS = 0x7c = SR_BSY | SR_REQ | SR_MSG | SR_CD | SR_IO > > > > > > Since BASR_PHASE_MATCH is not set, the interrupt is almost certainly a > > > phase mismatch. The new phase is SR_MSG | SR_CD | SR_IO = PHASE_MSGIN, > > > which shows that the target has given up on the DATA IN phase and is > > > presumably trying to send a DISCONNECT message. > > > > Looks you're right. The transfersize is 4096, i.e. 2 CD-ROM sectors. > > When the 2nd sector is not ready in the drive internal buffer, the drive > > probably disconnects which breaks the fragile pdma transfer. When the > > transfersize is limited to 2048 bytes, the problem goes away. > > OK. > > > The problem also went away with enabled interrupts because I had some > > debug printks added which were slowing down the transfer enough for the > > drive (SONY CDU-55S) to keep up and not disconnect. Got the same result > > by inserting udelay(100) after each 128 byte block trasnferred in > > pread(). > > Well, yeah, if you change the timing and omit to mention that, as well as > changing the spinlock_irq_save/restore pairs, then it's going to be > difficult for me to make sense of your results. Anyway, I'm glad that you > got to the bottom of this mystery. > > > > > When I enable interrupts during PDMA (like the removed UNSAFE macro > > > > did), the problems go away. I see an IRQ after each pread call. These two patches are enough to make PDMA work with CD-ROM drives on 53C400(A), with IRQ enabled or not. They even improve transfer rates with HDDs because of bigger block size. But DTC436 breaks with CDU-55S, immediately after modprobe. 1) Seems that IRQ timing is slightly different so I rewrote the wait for the host buffer to include check for CSR_GATED_53C80_IRQ. This allows some data to be transferred but 2) DTC436 likes to hang (return only 0xff from all registe
Re: g_NCR5380 PDMA, was Re: [PATCH 0/6] ncr5380: Miscellaneous minor patches
On Friday 17 February 2017 23:38:12 Finn Thain wrote: > On Thu, 16 Feb 2017, Ondrej Zary wrote: > > On Tuesday 31 January 2017 02:31:45 Finn Thain wrote: > > [...] > > > > > Are you trying to figure out which commands are going to disconnect > > > during a transfer? This is really a function of the firmware in the > > > target; there are no good heuristics AFAICT, so the PDMA algorithm has > > > to be robust. mac_scsi has to cope with this too. > > > > > > Does the problem go away when you assign no IRQ? When instance->irq == > > > NO_IRQ, the core driver will inhibit disconnect privileges. > > > > Yes, it seems to run fine with IRQ/disconnect disabled. With IRQ > > enabled, "dd if=/dev/sr0 of=anything" stops after a while. > > When you say "stops", do you mean an infinite loop in > generic_NCR5380_pread or does the loop complete (which would presumably > leave the target stuck in DATA IN phase, and a scsi command timeout would > probably follow after 30 seconds...) I've added timeouts to the possibly-infinite loops. It times out waiting for the host buffer to become ready. Then everything breaks. Now I found why: pread() returns without waiting for the 53C80 registers to be ready. Adding the wait allows to continue in PIO mode with "tag#0 switching to slow handshake". > > I get gated 53C80 IRQ, BASR=0x10, MODE=0x0e, STATUS=0x7c. > > You can use NCR5380_print() to get a decoded register dump. > > When I decode the above values I get, > > BASR = 0x10 = BASR_IRQ > MODE = 0x0e = MR_ENABLE_EOP_INTR | MR_MONITOR_BSY | MR_DMA_MODE > STATUS = 0x7c = SR_BSY | SR_REQ | SR_MSG | SR_CD | SR_IO > > Since BASR_PHASE_MATCH is not set, the interrupt is almost certainly a > phase mismatch. The new phase is SR_MSG | SR_CD | SR_IO = PHASE_MSGIN, > which shows that the target has given up on the DATA IN phase and is > presumably trying to send a DISCONNECT message. Looks you're right. The transfersize is 4096, i.e. 2 CD-ROM sectors. When the 2nd sector is not ready in the drive internal buffer, the drive probably disconnects which breaks the fragile pdma transfer. When the transfersize is limited to 2048 bytes, the problem goes away. The problem also went away with enabled interrupts because I had some debug printks added which were slowing down the transfer enough for the drive (SONY CDU-55S) to keep up and not disconnect. Got the same result by inserting udelay(100) after each 128 byte block trasnferred in pread(). > > When I enable interrupts during PDMA (like the removed UNSAFE macro > > did), the problems go away. I see an IRQ after each pread call. > > You shouldn't need an interrupt, because NCR5380_dma_complete() gets > called regardless. AFAICT, the only difference is the timing, which > becomes less predictable. Calling spinlock_irq_restore() before the > transfer seems to create a race condition between hostdata->dma_len store > and load. > > I think that the pread call has not yet returned when the interrupt fires > and NCR5380_dma_complete() is called. Hence hostdata->dma_len has not yet > been initialized. So when NCR5380_dma_complete() is called by the > interrupt handler, SCp.this_residual will not change at all because > hostdata->dma_len is still zero. > > > (had to disable "no 53C80 gated irq after transfer" and "no end dma > > signal" messages to reduce log spam) > > That may provide a quick way to detect the failed PDMA transfer, at least > for testing purposes. There may be a more conclusive test for a partial > transfer. > > We could to implement something like macscsi_dma_residual() to take care > of a failed PDMA transfer. That way, the failure can be taken into account > when NCR5380_dma_complete() is called at the end of the transfer. > > See patch below for example. It should confirm the theory above though it > really needs some timeouts added (NCR5380_poll_politely()). And perhaps we > could do something more clever than retry indefinitely, though we can > still rely on the command timeout. Thanks for idea > diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c > index 6f9665d..75cfaf3 100644 > --- a/drivers/scsi/g_NCR5380.c > +++ b/drivers/scsi/g_NCR5380.c > @@ -497,15 +497,17 @@ static inline int generic_NCR5380_pread(struct > NCR5380_hostdata *hostdata, blocks--; > } > > + hostdata->pdma_residual = 0; > + > if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) > - printk("53C400r: no 53C80 gated irq after transfer"); > + hostdata->pdma_residual = hostdata->dma_len; > > /* wait for 53C80 registe
Re: g_NCR5380 PDMA, was Re: [PATCH 0/6] ncr5380: Miscellaneous minor patches
On Tuesday 31 January 2017 02:31:45 Finn Thain wrote: [...] > Are you trying to figure out which commands are going to disconnect during > a transfer? This is really a function of the firmware in the target; there > are no good heuristics AFAICT, so the PDMA algorithm has to be robust. > mac_scsi has to cope with this too. > > Does the problem go away when you assign no IRQ? When instance->irq == > NO_IRQ, the core driver will inhibit disconnect privileges. Yes, it seems to run fine with IRQ/disconnect disabled. With IRQ enabled, "dd if=/dev/sr0 of=anything" stops after a while. I get gated 53C80 IRQ, BASR=0x10, MODE=0x0e, STATUS=0x7c. When I enable interrupts during PDMA (like the removed UNSAFE macro did), the problems go away. I see an IRQ after each pread call. (had to disable "no 53C80 gated irq after transfer" and "no end dma signal" messages to reduce log spam) -- Ondrej Zary
Re: [PATCH 0/6] ncr5380: Miscellaneous minor patches
On Sunday 29 January 2017 02:05:02 Finn Thain wrote: > On Sat, 28 Jan 2017, Ondrej Zary wrote: > > On Monday 16 January 2017 00:50:57 Finn Thain wrote: > > > This series removes some unused code and related comments, addresses > > > the warnings generated by 'make W=1' and 'make C=1' and fixes a > > > theoretical bug in the bus reset method in atari_scsi. > > > > > > There's also a patch to add a missing error check during target > > > selection. The only target I tested was a QUANTUM DAYTONA514S disk as > > > that's all I have access to right now. Some testing with other targets > > > would be prudent. > > > > > > Michael, Ondrej, can I get you to review/test please? > > > > Tested on HP C2502 (53C400A chip), Canon FG2-5202 (53C400 chip), > > DTC-3181L (DTCT-436P chip) and MS-PNR (53C400A chip) ISA cards - > > everything works fine! > > > > Targets tested: > > QUANTUM LP240S GM240S01X > > IBM DORS-32160 > > IBM 0663L12 > > > > Thanks. > > > > Tested-by: Ondrej Zary > > Very helpful. Thank you, Ondrej. Also tested two CD-ROM drives and they didn't work (machine hangs). They didn't work before and looks like they never worked with PDMA. The fundamental problem of PDMA is that it either transfers all required data or it breaks horribly. Even when I added timeouts to the possibly infinite loops (to avoid hangs), the chip remained in some bad state. Sometimes the 53C80 gated IRQ check triggers. This can be hopefully fixed but there is a HW limitation: if less than 128 bytes were read from SCSI device, they get lost in chip buffer (the 128B buffers don't swap until full). Fortunately, most of the requests for too much data are bogus. The problem is that generic_NCR5380_dma_xfer_len() uses cmd->transfersize which seems to be wrong. All other NCR5380 drivers use cmd->SCp.this_residual. This is also why rescan-scsi-bus hangs (cmd->transfersize is 8192 but cmd->SCp.this_residual is only 96). This quick fix allows CD-ROM and also rescan-scsi-bus to work. But it's not complete. Seems that we need: - fix pread and pwrite to terminate gracefully - something like atari_scsi_dma_xfer_len to allow DMA only for block commands @@ -588,22 +619,19 @@ static inline int generic_NCR5380_pwrite(struct NCR5380_hostdata *hostdata, static int generic_NCR5380_dma_xfer_len(struct NCR5380_hostdata *hostdata, struct scsi_cmnd *cmd) { - int transfersize = cmd->transfersize; + int transfersize = cmd->SCp.this_residual; if (hostdata->flags & FLAG_NO_PSEUDO_DMA) return 0; - /* Limit transfers to 32K, for xx400 & xx406 -* pseudoDMA that transfers in 128 bytes blocks. -*/ - if (transfersize > 32 * 1024 && cmd->SCp.this_residual && - !(cmd->SCp.this_residual % transfersize)) - transfersize = 32 * 1024; - /* 53C400 datasheet: non-modulo-128-byte transfers should use PIO */ if (transfersize % 128) transfersize = 0; + /* Limit transfers to 32K */ + if (transfersize > 32 * 1024) + transfersize = 32 * 1024; + return transfersize; } -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 0/6] ncr5380: Miscellaneous minor patches
On Monday 16 January 2017 00:50:57 Finn Thain wrote: > This series removes some unused code and related comments, > addresses the warnings generated by 'make W=1' and 'make C=1' > and fixes a theoretical bug in the bus reset method in atari_scsi. > > There's also a patch to add a missing error check during target > selection. The only target I tested was a QUANTUM DAYTONA514S disk > as that's all I have access to right now. Some testing with other > targets would be prudent. > > Michael, Ondrej, can I get you to review/test please? Tested on HP C2502 (53C400A chip), Canon FG2-5202 (53C400 chip), DTC-3181L (DTCT-436P chip) and MS-PNR (53C400A chip) ISA cards - everything works fine! Targets tested: QUANTUM LP240S GM240S01X IBM DORS-32160 IBM 0663L12 Thanks. Tested-by: Ondrej Zary -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 0/4] g_NCR5380: Bug fix and some enhancements
On Monday 05 December 2016 07:07:19 Finn Thain wrote: > This patch series is based on the one submitted recently by Ondrej Zary. > > This version has a different irq probing fix for HP C2502 boards and > a more comprehensive patch to change the default irq parameter. > > It needs testing on actual ISA hardware. Tested on HP C2502 (53C400A chip), Canon FG2-5202 (53C400 chip), DTC-3181L (DTCT-436P chip) and MS-PNR (53C400A chip) ISA cards - everything works fine! Thanks. Tested-by: Ondrej Zary BTW. The release-region fix (my previous patch 6/6) has disappeared somehow. Should I resubmit? -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/6] g_NCR5380: Add IRQ auto-configuration for HP C2502
On Thursday 03 November 2016, Finn Thain wrote: > On Wed, 2 Nov 2016, Ondrej Zary wrote: > > > Also, you've ignored the irq module parameters. From the user's point > > > of view, surely the least surprising thing is to attempt to configure > > > the card for whatever irq the user asked for. > > > > I haven't. NCR5380_find_irq is only called when irq is set to IRQ_AUTO. > > My mistake. > > > > If the specified irq isn't supported by the board, just log an error > > > and fail. If you want to be user friendly, print a message to tell > > > them what irqs the card supports. > > > > If the IRQ is not supported (or does not work), user gets a warning and > > the driver continues with IRQ disabled. > > > > > If the user asks for IRQ_AUTO, just configure the board for a > > > hard-coded default, say 9, and print a warning message to say so. > > > > The card is almost Plug&Play. The base address is already configured > > automatically by the driver so doing the same for IRQ makes sense. > > Why don't we see any other drivers doing this? Many ISA sound card drivers do this - there's even a function for this: static int snd_legacy_find_free_irq(int *irq_table) Unfortunately, it's defined in ALSA headers and even protected with an #ifdef. > If the card was really plug and play, I expect we would just call > pnp_irq(), as the other PNP drivers do. The card predates the PnP standard so we can't. > > > Either way, if request_irq fails just continue with NO_IRQ, as per > > > usual. > > > > > > To me that's the most flexible and least surprising behaviour. But > > > again, if someone with more ISA knowledge wishes to weigh in, that's > > > fine too. -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/6] g_NCR5380: Test the IRQ before accepting it
On Wednesday 02 November 2016 08:45:26 Finn Thain wrote: > On Mon, 31 Oct 2016, Ondrej Zary wrote: > > Trigger an IRQ first with a test IRQ handler to find out if it really > > works. Disable the IRQ if not. > > > > This prevents hang when incorrect IRQ was specified by user. > > Once again, how does it cause a hang? Kernel scans the bus, finds a HDD, then attempts to read MBR. modprobe process is stuck but the system is still running. Then the transfer probably times out and everything locks up hard, even fbcon cursor stops blinking. I guess that kernel is trying to abort or reset. BTW. rescan-scsi-bus also causes hang, anytime, even without IRQ. > If the user specifies an IRQ, we should trust them. If they don't specify > an IRQ then probe (as in patch 5/6). > > > Signed-off-by: Ondrej Zary > > --- > > drivers/scsi/g_NCR5380.c | 44 > > +--- 1 file changed, 41 > > insertions(+), 3 deletions(-) > > > > diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c > > index 09c660b..0d1f6ad 100644 > > --- a/drivers/scsi/g_NCR5380.c > > +++ b/drivers/scsi/g_NCR5380.c > > @@ -115,6 +115,32 @@ static int NCR5380_probe_irq(struct Scsi_Host > > *instance) return irq; > > } > > > > +static bool irq_working; > > + > > +static irqreturn_t test_irq(int irq, void *dev_id) > > +{ > > + irq_working = true; > > + return IRQ_HANDLED; > > +} > > + > > +/* test if the IRQ is working */ > > +static int NCR5380_test_irq(struct Scsi_Host *instance, int irq) > > +{ > > + struct NCR5380_hostdata *hostdata = shost_priv(instance); > > + > > + irq_working = false; > > + if (request_irq(irq, test_irq, 0, "NCR5380-irqtest", NULL)) > > + return -EBUSY; > > + NCR5380_trigger_irq(instance); > > + NCR5380_read(RESET_PARITY_INTERRUPT_REG); > > + free_irq(irq, NULL); > > + > > + if (!irq_working) > > + return -EIO; > > + > > + return 0; > > +} > > + > > IMO the extra complexity is not justified by the possibility of machines > with misconfigured BIOS or incorrect module parameters. > > I don't want another irq probing mechanism. We just got rid of one. > > But I won't mind if the SCSI maintainers who know ISA better than I do > would like to review this. > > > /* > > * Configure I/O address of 53C400A or DTC436 by writing magic numbers > > * to ports 0x779 and 0x379. > > @@ -323,9 +349,21 @@ static int generic_NCR5380_init_one(struct > > scsi_host_template *tpnt, /* set IRQ for HP C2502 */ > > if (board == BOARD_HP_C2502) > > magic_configure(port_idx, instance->irq, magic); > > - if (request_irq(instance->irq, generic_NCR5380_intr, > > - 0, "NCR5380", instance)) { > > - printk(KERN_WARNING "scsi%d : IRQ%d not free, > > interrupts disabled\n", > > instance->host_no, instance->irq); +ret = > > NCR5380_test_irq(instance, > > instance->irq); > > + if (ret) { > > + printk(KERN_WARNING "scsi%d : IRQ%d not %s, interrupts > > disabled\n", > > + instance->host_no, instance->irq, > > + (ret == -EBUSY) ? "free" : "working"); > > + instance->irq = NO_IRQ; > > + } > > + } > > + > > + if (instance->irq != NO_IRQ) { > > + if (request_irq(instance->irq, generic_NCR5380_intr, 0, > > + "NCR5380", instance)) { > > + printk(KERN_WARNING "scsi%d : IRQ%d not free, > > interrupts disabled\n", > > + instance->host_no, > > + instance->irq); > > instance->irq = NO_IRQ; > > } > > } -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/6] g_NCR5380: Add IRQ auto-configuration for HP C2502
On Wednesday 02 November 2016, Finn Thain wrote: > On Mon, 31 Oct 2016, Ondrej Zary wrote: > > Find free and working IRQ automatically on HP C2502 cards. > > Also allow IRQ 9 to work (aliases to IRQ 2 on the card). > > > > Signed-off-by: Ondrej Zary > > --- > > drivers/scsi/g_NCR5380.c | 29 +++-- > > 1 file changed, 27 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c > > index e713dba..27fc499 100644 > > --- a/drivers/scsi/g_NCR5380.c > > +++ b/drivers/scsi/g_NCR5380.c > > @@ -156,6 +156,8 @@ static void magic_configure(int idx, u8 irq, u8 > > magic[]) outb(magic[4], 0x379); > > > > /* allowed IRQs for HP C2502 */ > > + if (irq == 9) > > + irq = 2; > > if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7) > > irq = 0; > > if (idx >= 0 && idx <= 7) > > @@ -163,6 +165,21 @@ static void magic_configure(int idx, u8 irq, u8 > > magic[]) outb(cfg, 0x379); > > } > > > > +/* find a free and working IRQ (for HP C2502) */ > > +static int NCR5380_find_irq(struct Scsi_Host *instance, u8 irqs[], > > + int port_idx, u8 magic[]) > > +{ > > + int i; > > + > > + for (i = 0; irqs[i]; i++) { > > + magic_configure(port_idx, irqs[i], magic); > > + if (NCR5380_test_irq(instance, irqs[i]) == 0) > > + return irqs[i]; > > The NCR5380_test_irq routine in patch 2/6 doesn't work for shared irqs, so > you may not get the IRQ you would expect. (The core driver does support > shared irqs, BTW.) ISA bus does not support IRQ sharing. > Also, you've ignored the irq module parameters. From the user's point of > view, surely the least surprising thing is to attempt to configure the > card for whatever irq the user asked for. I haven't. NCR5380_find_irq is only called when irq is set to IRQ_AUTO. > If the specified irq isn't supported by the board, just log an error and > fail. If you want to be user friendly, print a message to tell them what > irqs the card supports. If the IRQ is not supported (or does not work), user gets a warning and the driver continues with IRQ disabled. > If the user asks for IRQ_AUTO, just configure the board for a hard-coded > default, say 9, and print a warning message to say so. The card is almost Plug&Play. The base address is already configured automatically by the driver so doing the same for IRQ makes sense. > Either way, if request_irq fails just continue with NO_IRQ, as per usual. > > To me that's the most flexible and least surprising behaviour. But again, > if someone with more ISA knowledge wishes to weigh in, that's fine too. > > > + } > > + magic_configure(port_idx, 0, magic); > > + return NO_IRQ; > > +} > > + > > static unsigned int ncr_53c400a_ports[] = { > > 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 > > }; > > @@ -175,6 +192,9 @@ static void magic_configure(int idx, u8 irq, u8 > > magic[]) static u8 hp_c2502_magic[] = { /* HP C2502 */ > > 0x0f, 0x22, 0xf0, 0x20, 0x80 > > }; > > +static u8 hp_c2502_irqs[] = { > > + 9, 5, 7, 3, 4, 0 > > +}; > > > > static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, > > struct device *pdev, int base, int irq, int board) > > @@ -345,8 +365,13 @@ static int generic_NCR5380_init_one(struct > > scsi_host_template *tpnt, > > > > if (irq != IRQ_AUTO) > > instance->irq = irq; > > - else > > - instance->irq = NCR5380_probe_irq(instance); > > + else { > > + if (board == BOARD_HP_C2502) > > + instance->irq = NCR5380_find_irq(instance, > > + hp_c2502_irqs, port_idx, magic); > > + else > > + instance->irq = NCR5380_probe_irq(instance); > > + } > > > > /* Compatibility with documented NCR5380 kernel parameters */ > > if (instance->irq == 255) -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/6] NCR5380: Use probe_irq_*() for IRQ probing
On Wednesday 02 November 2016, Finn Thain wrote: > On Mon, 31 Oct 2016, Ondrej Zary wrote: > > Use standard probe_irq_on() and probe_irq_off() functions instead of own > > implementation. This prevents warning messages like this in the kernel > > log: genirq: Flags mismatch irq 1. (NCR-probe) vs. 0080 > > (i8042) > > > > Move the IRQ trigger code to a separate function so it can be used for > > other purposes (testing if the IRQ works) and move the code from NCR5380 > > to g_NCR5380. > > > > Also add missing IRQ reset before and after the probe. > > > > Signed-off-by: Ondrej Zary > > --- > > drivers/scsi/NCR5380.c | 77 > > +- drivers/scsi/NCR5380.h | > >1 - > > drivers/scsi/g_NCR5380.c | 50 +- > > 3 files changed, 50 insertions(+), 78 deletions(-) > > > > diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c > > index d849ffa..4f5ca79 100644 > > --- a/drivers/scsi/NCR5380.c > > +++ b/drivers/scsi/NCR5380.c > > @@ -97,9 +97,6 @@ > > * and macros and include this file in your driver. > > * > > * These macros control options : > > - * AUTOPROBE_IRQ - if defined, the NCR5380_probe_irq() function will be > > - * defined. > > - * > > * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically > > * for commands that return with a CHECK CONDITION status. > > * > > @@ -127,9 +124,7 @@ > > * NCR5380_dma_residual - residual byte count > > * > > * The generic driver is initialized by calling NCR5380_init(instance), > > - * after setting the appropriate host specific fields and ID. If the > > - * driver wishes to autoprobe for an IRQ line, the > > NCR5380_probe_irq(instance, - * possible) function may be used. > > + * after setting the appropriate host specific fields and ID. > > */ > > > > #ifndef NCR5380_io_delay > > @@ -351,76 +346,6 @@ static void NCR5380_print_phase(struct Scsi_Host > > *instance) } > > #endif > > > > - > > -static int probe_irq; > > - > > -/** > > - * probe_intr - helper for IRQ autoprobe > > - * @irq: interrupt number > > - * @dev_id: unused > > - * @regs: unused > > - * > > - * Set a flag to indicate the IRQ in question was received. This is > > - * used by the IRQ probe code. > > - */ > > - > > -static irqreturn_t probe_intr(int irq, void *dev_id) > > -{ > > - probe_irq = irq; > > - return IRQ_HANDLED; > > -} > > - > > -/** > > - * NCR5380_probe_irq - find the IRQ of an NCR5380 > > - * @instance: NCR5380 controller > > - * @possible: bitmask of ISA IRQ lines > > - * > > - * Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ > > - * and then looking to see what interrupt actually turned up. > > - */ > > - > > -static int __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, > > - int possible) > > -{ > > - struct NCR5380_hostdata *hostdata = shost_priv(instance); > > - unsigned long timeout; > > - int trying_irqs, i, mask; > > - > > - for (trying_irqs = 0, i = 1, mask = 2; i < 16; ++i, mask <<= 1) > > - if ((mask & possible) && (request_irq(i, &probe_intr, 0, > > "NCR-probe", > > NULL) == 0)) - trying_irqs |= mask; > > - > > - timeout = jiffies + msecs_to_jiffies(250); > > - probe_irq = NO_IRQ; > > - > > - /* > > -* A interrupt is triggered whenever BSY = false, SEL = true > > -* and a bit set in the SELECT_ENABLE_REG is asserted on the > > -* SCSI bus. > > -* > > -* Note that the bus is only driven when the phase control signals > > -* (I/O, C/D, and MSG) match those in the TCR, so we must reset that > > -* to zero. > > -*/ > > - > > - NCR5380_write(TARGET_COMMAND_REG, 0); > > - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); > > - NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); > > - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | > > ICR_ASSERT_SEL); - > > - while (probe_irq == NO_IRQ && time_before(jiffies, timeout)) > > - schedule_timeout_uninterruptible(1); > > - > > - NCR5380_write(SELECT_ENABLE_REG, 0); > > - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); > > - > > - for (i = 1, mask = 2; i < 16; ++i,
[PATCH 2/6] g_NCR5380: Test the IRQ before accepting it
Trigger an IRQ first with a test IRQ handler to find out if it really works. Disable the IRQ if not. This prevents hang when incorrect IRQ was specified by user. Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c | 44 +--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 09c660b..0d1f6ad 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -115,6 +115,32 @@ static int NCR5380_probe_irq(struct Scsi_Host *instance) return irq; } +static bool irq_working; + +static irqreturn_t test_irq(int irq, void *dev_id) +{ + irq_working = true; + return IRQ_HANDLED; +} + +/* test if the IRQ is working */ +static int NCR5380_test_irq(struct Scsi_Host *instance, int irq) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + + irq_working = false; + if (request_irq(irq, test_irq, 0, "NCR5380-irqtest", NULL)) + return -EBUSY; + NCR5380_trigger_irq(instance); + NCR5380_read(RESET_PARITY_INTERRUPT_REG); + free_irq(irq, NULL); + + if (!irq_working) + return -EIO; + + return 0; +} + /* * Configure I/O address of 53C400A or DTC436 by writing magic numbers * to ports 0x779 and 0x379. @@ -323,9 +349,21 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, /* set IRQ for HP C2502 */ if (board == BOARD_HP_C2502) magic_configure(port_idx, instance->irq, magic); - if (request_irq(instance->irq, generic_NCR5380_intr, - 0, "NCR5380", instance)) { - printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); + ret = NCR5380_test_irq(instance, instance->irq); + if (ret) { + printk(KERN_WARNING "scsi%d : IRQ%d not %s, interrupts disabled\n", + instance->host_no, instance->irq, + (ret == -EBUSY) ? "free" : "working"); + instance->irq = NO_IRQ; + } + } + + if (instance->irq != NO_IRQ) { + if (request_irq(instance->irq, generic_NCR5380_intr, 0, + "NCR5380", instance)) { + printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", + instance->host_no, + instance->irq); instance->irq = NO_IRQ; } } -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/6] (g_)NCR5380: Improve IRQ probing and some fixes
Hello, this patch series improves IRQ probing and moves it from NCR5380 to g_NCR5380, adds IRQ auto-configuration for HP C2502 and enables all this by default. It also adds IRQ and base address checks to prevent hangs when wrong values are specified by user. There's also a small release region fix in error handling. -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/6] g_NCR5380: Check for chip presence before calling NCR5380_init()
Write and read back MODE_REG to check if the chip is really there before doing more initialization. This prevents hang when incorrect I/O address was specified by user (in the most common case where no device is present there so all reads result in 0xff). Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c |7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 0d1f6ad..e713dba 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -322,6 +322,13 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, } } + /* check if the chip is really there */ + NCR5380_write(MODE_REG, 0); + if (NCR5380_read(MODE_REG) != 0) { + ret = -ENODEV; + goto out_unregister; + } + ret = NCR5380_init(instance, flags | FLAG_LATE_DMA_SETUP); if (ret) goto out_unregister; -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/6] g_NCR5380: Add IRQ auto-configuration for HP C2502
Find free and working IRQ automatically on HP C2502 cards. Also allow IRQ 9 to work (aliases to IRQ 2 on the card). Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c | 29 +++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index e713dba..27fc499 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -156,6 +156,8 @@ static void magic_configure(int idx, u8 irq, u8 magic[]) outb(magic[4], 0x379); /* allowed IRQs for HP C2502 */ + if (irq == 9) + irq = 2; if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7) irq = 0; if (idx >= 0 && idx <= 7) @@ -163,6 +165,21 @@ static void magic_configure(int idx, u8 irq, u8 magic[]) outb(cfg, 0x379); } +/* find a free and working IRQ (for HP C2502) */ +static int NCR5380_find_irq(struct Scsi_Host *instance, u8 irqs[], + int port_idx, u8 magic[]) +{ + int i; + + for (i = 0; irqs[i]; i++) { + magic_configure(port_idx, irqs[i], magic); + if (NCR5380_test_irq(instance, irqs[i]) == 0) + return irqs[i]; + } + magic_configure(port_idx, 0, magic); + return NO_IRQ; +} + static unsigned int ncr_53c400a_ports[] = { 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 }; @@ -175,6 +192,9 @@ static void magic_configure(int idx, u8 irq, u8 magic[]) static u8 hp_c2502_magic[] = { /* HP C2502 */ 0x0f, 0x22, 0xf0, 0x20, 0x80 }; +static u8 hp_c2502_irqs[] = { + 9, 5, 7, 3, 4, 0 +}; static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, struct device *pdev, int base, int irq, int board) @@ -345,8 +365,13 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, if (irq != IRQ_AUTO) instance->irq = irq; - else - instance->irq = NCR5380_probe_irq(instance); + else { + if (board == BOARD_HP_C2502) + instance->irq = NCR5380_find_irq(instance, + hp_c2502_irqs, port_idx, magic); + else + instance->irq = NCR5380_probe_irq(instance); + } /* Compatibility with documented NCR5380 kernel parameters */ if (instance->irq == 255) -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/6] NCR5380: Use probe_irq_*() for IRQ probing
Use standard probe_irq_on() and probe_irq_off() functions instead of own implementation. This prevents warning messages like this in the kernel log: genirq: Flags mismatch irq 1. (NCR-probe) vs. 0080 (i8042) Move the IRQ trigger code to a separate function so it can be used for other purposes (testing if the IRQ works) and move the code from NCR5380 to g_NCR5380. Also add missing IRQ reset before and after the probe. Signed-off-by: Ondrej Zary --- drivers/scsi/NCR5380.c | 77 +- drivers/scsi/NCR5380.h |1 - drivers/scsi/g_NCR5380.c | 50 +- 3 files changed, 50 insertions(+), 78 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index d849ffa..4f5ca79 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -97,9 +97,6 @@ * and macros and include this file in your driver. * * These macros control options : - * AUTOPROBE_IRQ - if defined, the NCR5380_probe_irq() function will be - * defined. - * * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically * for commands that return with a CHECK CONDITION status. * @@ -127,9 +124,7 @@ * NCR5380_dma_residual - residual byte count * * The generic driver is initialized by calling NCR5380_init(instance), - * after setting the appropriate host specific fields and ID. If the - * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance, - * possible) function may be used. + * after setting the appropriate host specific fields and ID. */ #ifndef NCR5380_io_delay @@ -351,76 +346,6 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) } #endif - -static int probe_irq; - -/** - * probe_intr - helper for IRQ autoprobe - * @irq: interrupt number - * @dev_id: unused - * @regs: unused - * - * Set a flag to indicate the IRQ in question was received. This is - * used by the IRQ probe code. - */ - -static irqreturn_t probe_intr(int irq, void *dev_id) -{ - probe_irq = irq; - return IRQ_HANDLED; -} - -/** - * NCR5380_probe_irq - find the IRQ of an NCR5380 - * @instance: NCR5380 controller - * @possible: bitmask of ISA IRQ lines - * - * Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ - * and then looking to see what interrupt actually turned up. - */ - -static int __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, - int possible) -{ - struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned long timeout; - int trying_irqs, i, mask; - - for (trying_irqs = 0, i = 1, mask = 2; i < 16; ++i, mask <<= 1) - if ((mask & possible) && (request_irq(i, &probe_intr, 0, "NCR-probe", NULL) == 0)) - trying_irqs |= mask; - - timeout = jiffies + msecs_to_jiffies(250); - probe_irq = NO_IRQ; - - /* -* A interrupt is triggered whenever BSY = false, SEL = true -* and a bit set in the SELECT_ENABLE_REG is asserted on the -* SCSI bus. -* -* Note that the bus is only driven when the phase control signals -* (I/O, C/D, and MSG) match those in the TCR, so we must reset that -* to zero. -*/ - - NCR5380_write(TARGET_COMMAND_REG, 0); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL); - - while (probe_irq == NO_IRQ && time_before(jiffies, timeout)) - schedule_timeout_uninterruptible(1); - - NCR5380_write(SELECT_ENABLE_REG, 0); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - for (i = 1, mask = 2; i < 16; ++i, mask <<= 1) - if (trying_irqs & mask) - free_irq(i, NULL); - - return probe_irq; -} - /** * NCR58380_info - report driver and host information * @instance: relevant scsi host instance diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 3c6ce54..4724558 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -290,7 +290,6 @@ static inline struct scsi_cmnd *NCR5380_to_scmd(struct NCR5380_cmd *ncmd_ptr) #define NCR5380_dprint_phase(flg, arg) do {} while (0) #endif -static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible); static int NCR5380_init(struct Scsi_Host *instance, int flags); static int NCR5380_maybe_reset_bus(struct Scsi_Host *); static void NCR5380_exit(struct Scsi_Host *instance); diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 7299ad9..09c660b 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -67,6 +67,54 @@ MODULE_ALIAS("g_NCR5380_mmio"); MODULE_LICENSE("GPL"); +static void NCR5380_trigger_irq(struct Scsi_
[PATCH 5/6] g_NCR5380: Autoprobe IRQ by default
IRQ probing seems to work fine now. Default to autoprobe for IRQ instead of disabling it. Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 27fc499..6a08d3e 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -52,9 +52,9 @@ module_param(dtc_3181e, int, 0); module_param(hp_c2502, int, 0); -static int irq[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static int irq[] = { IRQ_AUTO, IRQ_AUTO, IRQ_AUTO, IRQ_AUTO, IRQ_AUTO, IRQ_AUTO, IRQ_AUTO, IRQ_AUTO }; module_param_array(irq, int, NULL, 0); -MODULE_PARM_DESC(irq, "IRQ number(s)"); +MODULE_PARM_DESC(irq, "IRQ number(s) (0=disable, 254=auto [default])"); static int base[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; module_param_array(base, int, NULL, 0); -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 6/6] g_NCR5380: Fix release region in error handling
When a SW-configurable card is specified but not found, the driver releases wrong region, causing the following message in kernel log: Trying to free nonexistent resource <-000f> Fix it by assigning base earlier. Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c |6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 6a08d3e..d33e71f 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -258,12 +258,12 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, if (ports[i]) { /* At this point we have our region reserved */ magic_configure(i, 0, magic); /* no IRQ yet */ - outb(0xc0, ports[i] + 9); - if (inb(ports[i] + 9) != 0x80) { + base = ports[i]; + outb(0xc0, base + 9); + if (inb(base + 9) != 0x80) { ret = -ENODEV; goto out_release; } - base = ports[i]; port_idx = i; } else return -EINVAL; -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/3] g_NCR5380: Test the IRQ before accepting it
On Monday 31 October 2016, Finn Thain wrote: > On Sun, 30 Oct 2016, Ondrej Zary wrote: > > Trigger an IRQ first with a test IRQ handler to find out if it really > > works. Disable the IRQ if not. > > > > This prevents hang when incorrect IRQ was specified by user. > > > > Signed-off-by: Ondrej Zary > > --- > > drivers/scsi/g_NCR5380.c | 32 ++-- > > 1 file changed, 30 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c > > index 3790ed5..261e168 100644 > > --- a/drivers/scsi/g_NCR5380.c > > +++ b/drivers/scsi/g_NCR5380.c > > @@ -67,6 +67,14 @@ > > MODULE_ALIAS("g_NCR5380_mmio"); > > MODULE_LICENSE("GPL"); > > > > +static bool irq_working; > > + > > +static irqreturn_t test_irq(int irq, void *dev_id) > > +{ > > + irq_working = true; > > + return IRQ_HANDLED; > > +} > > + > > /* > > * Configure I/O address of 53C400A or DTC436 by writing magic numbers > > * to ports 0x779 and 0x379. > > @@ -275,10 +283,30 @@ static int generic_NCR5380_init_one(struct > > scsi_host_template *tpnt, /* set IRQ for HP C2502 */ > > if (board == BOARD_HP_C2502) > > magic_configure(port_idx, instance->irq, magic); > > - if (request_irq(instance->irq, generic_NCR5380_intr, > > - 0, "NCR5380", instance)) { > > + /* test if the IRQ is working */ > > + irq_working = false; > > + if (request_irq(instance->irq, test_irq, > > + 0, "NCR5380-irqtest", NULL)) { > > printk(KERN_WARNING "scsi%d : IRQ%d not free, > > interrupts disabled\n", > > instance->host_no, instance->irq); instance->irq = NO_IRQ; > > + } else { > > + NCR5380_trigger_irq(instance); > > + NCR5380_read(RESET_PARITY_INTERRUPT_REG); > > + free_irq(instance->irq, NULL); > > + if (irq_working) { > > + if (request_irq(instance->irq, > > + generic_NCR5380_intr, 0, > > + "NCR5380", instance)) { > > + printk(KERN_WARNING "scsi%d : IRQ%d not > > free, interrupts > > disabled\n", + > > instance->host_no, > > + instance->irq); > > + instance->irq = NO_IRQ; > > + } > > + } else { > > + printk(KERN_WARNING "scsi%d : IRQ%d not > > working, interrupts > > disabled\n", + instance->host_no, > > instance->irq); > > + instance->irq = NO_IRQ; > > + } > > } > > } > > If the user omits to specify an irq, you can just default to IRQ_AUTO. > This might result in NO_IRQ, which gives the same result as this patch. Looks like a good idea. > And when the user does specify an IRQ, we should trust them. So this > compexity doesn't add any value AFAICT. Thanks but no thanks. This fixes a real problem: specifying wrong IRQ hangs the machine completely. It's really easy - if the IRQ is free but configured in BIOS as PCI IRQ (not ISA). Everything seems fine except the IRQ will never trigger. -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/3] NCR5380: Use probe_irq_*() for IRQ probing
On Monday 31 October 2016, Finn Thain wrote: > On Sun, 30 Oct 2016, Ondrej Zary wrote: > > Use standard probe_irq_on() and probe_irq_off() functions instead of own > > implementation. > > Thanks for doing this. > > > This prevents warning messages like this in the kernel log: > > genirq: Flags mismatch irq 1. (NCR-probe) vs. 0080 (i8042) > > > > Move the IRQ trigger code to a separate function so it can be used for > > other purposes (testing if the IRQ works). > > > > Also add missing IRQ reset after probe. > > > > Signed-off-by: Ondrej Zary > > --- > > drivers/scsi/NCR5380.c | 72 > > +- drivers/scsi/NCR5380.h | > >3 +- > > drivers/scsi/g_NCR5380.c |2 +- > > 3 files changed, 29 insertions(+), 48 deletions(-) > > > > diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c > > index d849ffa..01c0027 100644 > > --- a/drivers/scsi/NCR5380.c > > +++ b/drivers/scsi/NCR5380.c > > @@ -351,50 +351,13 @@ static void NCR5380_print_phase(struct Scsi_Host > > *instance) } > > #endif > > > > - > > -static int probe_irq; > > - > > -/** > > - * probe_intr - helper for IRQ autoprobe > > - * @irq: interrupt number > > - * @dev_id: unused > > - * @regs: unused > > - * > > - * Set a flag to indicate the IRQ in question was received. This is > > - * used by the IRQ probe code. > > - */ > > - > > -static irqreturn_t probe_intr(int irq, void *dev_id) > > -{ > > - probe_irq = irq; > > - return IRQ_HANDLED; > > -} > > - > > -/** > > - * NCR5380_probe_irq - find the IRQ of an NCR5380 > > - * @instance: NCR5380 controller > > - * @possible: bitmask of ISA IRQ lines > > - * > > - * Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ > > - * and then looking to see what interrupt actually turned up. > > - */ > > - > > -static int __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, > > - int possible) > > +static void NCR5380_trigger_irq(struct Scsi_Host *instance) > > { > > struct NCR5380_hostdata *hostdata = shost_priv(instance); > > - unsigned long timeout; > > - int trying_irqs, i, mask; > > - > > - for (trying_irqs = 0, i = 1, mask = 2; i < 16; ++i, mask <<= 1) > > - if ((mask & possible) && (request_irq(i, &probe_intr, 0, > > "NCR-probe", > > NULL) == 0)) - trying_irqs |= mask; > > - > > - timeout = jiffies + msecs_to_jiffies(250); > > - probe_irq = NO_IRQ; > > + unsigned long timeout = jiffies + msecs_to_jiffies(2500); > > > > /* > > -* A interrupt is triggered whenever BSY = false, SEL = true > > +* An interrupt is triggered whenever BSY = false, SEL = true > > * and a bit set in the SELECT_ENABLE_REG is asserted on the > > * SCSI bus. > > * > > @@ -402,23 +365,40 @@ static int __maybe_unused NCR5380_probe_irq(struct > > Scsi_Host *instance, * (I/O, C/D, and MSG) match those in the TCR, so we > > must reset that * to zero. > > */ > > - > > NCR5380_write(TARGET_COMMAND_REG, 0); > > NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); > > NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); > > NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | > > ICR_ASSERT_SEL); > > > > - while (probe_irq == NO_IRQ && time_before(jiffies, timeout)) > > + while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_IRQ) && > > + time_before(jiffies, timeout)) > > schedule_timeout_uninterruptible(1); > > You don't need a 2.5 second timeout here. To raise the interrupt the chip > should not need more than a bus settle delay (400ns). Calling msleep(1) > should be plenty. Yes, 2.5s is a mistake (leftover from testing), sorry. > Better still, please drop the loop, the delay and the BASR_IRQ test here, > and if need be, put the delay in the caller. This routine discards the > result of that sequence anyway. Will if work if the following lines are executed before the delay? > > > NCR5380_write(SELECT_ENABLE_REG, 0); > > NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); > > +} > > > > - for (i = 1, mask = 2; i < 16; ++i, mask <<= 1) > > - if (trying_irqs & mask) > > - free_irq(i, NULL); > > +/** > > + * NCR538
Re: [PATCH 3/3] NCR5380: Check for chip presence in NCR5380_init()
On Monday 31 October 2016, Finn Thain wrote: > On Sun, 30 Oct 2016, Ondrej Zary wrote: > > Read back MODE_REG after writing it in NCR5380_init() to check if the > > chip is really there. > > > > This prevents hang when incorrect I/O address was specified by user. > > > > Signed-off-by: Ondrej Zary > > --- > > drivers/scsi/NCR5380.c |5 + > > 1 file changed, 5 insertions(+) > > > > diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c > > index 01c0027..ce3156d 100644 > > --- a/drivers/scsi/NCR5380.c > > +++ b/drivers/scsi/NCR5380.c > > @@ -495,6 +495,11 @@ static int NCR5380_init(struct Scsi_Host *instance, > > int flags) > > > > NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); > > NCR5380_write(MODE_REG, MR_BASE); > > + /* check if the chip is really there */ > > + if (NCR5380_read(MODE_REG) != MR_BASE) { > > + NCR5380_exit(instance); > > + return -ENODEV; > > + } > > This doesn't belong in the core driver. Only the 5380 ISA drivers have > configurable base addresses. > > Also, MR_BASE == 0, so that test is likely to be ineffectual anyway. This > patch doesn't really add any value AFAICT. This fixes the most common problem: no device present at the specified I/O address, all reads result in 0xff. -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/3] NCR5380: Check for chip presence in NCR5380_init()
Read back MODE_REG after writing it in NCR5380_init() to check if the chip is really there. This prevents hang when incorrect I/O address was specified by user. Signed-off-by: Ondrej Zary --- drivers/scsi/NCR5380.c |5 + 1 file changed, 5 insertions(+) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 01c0027..ce3156d 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -495,6 +495,11 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(MODE_REG, MR_BASE); + /* check if the chip is really there */ + if (NCR5380_read(MODE_REG) != MR_BASE) { + NCR5380_exit(instance); + return -ENODEV; + } NCR5380_write(TARGET_COMMAND_REG, 0); NCR5380_write(SELECT_ENABLE_REG, 0); -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3] g_NCR5380: Test the IRQ before accepting it
Trigger an IRQ first with a test IRQ handler to find out if it really works. Disable the IRQ if not. This prevents hang when incorrect IRQ was specified by user. Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c | 32 ++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 3790ed5..261e168 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -67,6 +67,14 @@ MODULE_ALIAS("g_NCR5380_mmio"); MODULE_LICENSE("GPL"); +static bool irq_working; + +static irqreturn_t test_irq(int irq, void *dev_id) +{ + irq_working = true; + return IRQ_HANDLED; +} + /* * Configure I/O address of 53C400A or DTC436 by writing magic numbers * to ports 0x779 and 0x379. @@ -275,10 +283,30 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, /* set IRQ for HP C2502 */ if (board == BOARD_HP_C2502) magic_configure(port_idx, instance->irq, magic); - if (request_irq(instance->irq, generic_NCR5380_intr, - 0, "NCR5380", instance)) { + /* test if the IRQ is working */ + irq_working = false; + if (request_irq(instance->irq, test_irq, + 0, "NCR5380-irqtest", NULL)) { printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); instance->irq = NO_IRQ; + } else { + NCR5380_trigger_irq(instance); + NCR5380_read(RESET_PARITY_INTERRUPT_REG); + free_irq(instance->irq, NULL); + if (irq_working) { + if (request_irq(instance->irq, + generic_NCR5380_intr, 0, + "NCR5380", instance)) { + printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", + instance->host_no, + instance->irq); + instance->irq = NO_IRQ; + } + } else { + printk(KERN_WARNING "scsi%d : IRQ%d not working, interrupts disabled\n", + instance->host_no, instance->irq); + instance->irq = NO_IRQ; + } } } -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3] NCR5380: Use probe_irq_*() for IRQ probing
Use standard probe_irq_on() and probe_irq_off() functions instead of own implementation. This prevents warning messages like this in the kernel log: genirq: Flags mismatch irq 1. (NCR-probe) vs. 0080 (i8042) Move the IRQ trigger code to a separate function so it can be used for other purposes (testing if the IRQ works). Also add missing IRQ reset after probe. Signed-off-by: Ondrej Zary --- drivers/scsi/NCR5380.c | 72 +- drivers/scsi/NCR5380.h |3 +- drivers/scsi/g_NCR5380.c |2 +- 3 files changed, 29 insertions(+), 48 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index d849ffa..01c0027 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -351,50 +351,13 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) } #endif - -static int probe_irq; - -/** - * probe_intr - helper for IRQ autoprobe - * @irq: interrupt number - * @dev_id: unused - * @regs: unused - * - * Set a flag to indicate the IRQ in question was received. This is - * used by the IRQ probe code. - */ - -static irqreturn_t probe_intr(int irq, void *dev_id) -{ - probe_irq = irq; - return IRQ_HANDLED; -} - -/** - * NCR5380_probe_irq - find the IRQ of an NCR5380 - * @instance: NCR5380 controller - * @possible: bitmask of ISA IRQ lines - * - * Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ - * and then looking to see what interrupt actually turned up. - */ - -static int __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, - int possible) +static void NCR5380_trigger_irq(struct Scsi_Host *instance) { struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned long timeout; - int trying_irqs, i, mask; - - for (trying_irqs = 0, i = 1, mask = 2; i < 16; ++i, mask <<= 1) - if ((mask & possible) && (request_irq(i, &probe_intr, 0, "NCR-probe", NULL) == 0)) - trying_irqs |= mask; - - timeout = jiffies + msecs_to_jiffies(250); - probe_irq = NO_IRQ; + unsigned long timeout = jiffies + msecs_to_jiffies(2500); /* -* A interrupt is triggered whenever BSY = false, SEL = true +* An interrupt is triggered whenever BSY = false, SEL = true * and a bit set in the SELECT_ENABLE_REG is asserted on the * SCSI bus. * @@ -402,23 +365,40 @@ static int __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, * (I/O, C/D, and MSG) match those in the TCR, so we must reset that * to zero. */ - NCR5380_write(TARGET_COMMAND_REG, 0); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL); - while (probe_irq == NO_IRQ && time_before(jiffies, timeout)) + while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_IRQ) && + time_before(jiffies, timeout)) schedule_timeout_uninterruptible(1); NCR5380_write(SELECT_ENABLE_REG, 0); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); +} - for (i = 1, mask = 2; i < 16; ++i, mask <<= 1) - if (trying_irqs & mask) - free_irq(i, NULL); +/** + * NCR5380_probe_irq - find the IRQ of an NCR5380 + * @instance: NCR5380 controller + * + * Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ + * and then looking to see what interrupt actually turned up. + */ + +static int NCR5380_probe_irq(struct Scsi_Host *instance) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + int irqs, irq; + + irqs = probe_irq_on(); + NCR5380_trigger_irq(instance); + irq = probe_irq_off(irqs); + NCR5380_read(RESET_PARITY_INTERRUPT_REG); + if (irq < 0) + irq = 0; - return probe_irq; + return irq; } /** diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 3c6ce54..b2fca52 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -290,7 +290,8 @@ static inline struct scsi_cmnd *NCR5380_to_scmd(struct NCR5380_cmd *ncmd_ptr) #define NCR5380_dprint_phase(flg, arg) do {} while (0) #endif -static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible); +static void NCR5380_trigger_irq(struct Scsi_Host *instance); +static int NCR5380_probe_irq(struct Scsi_Host *instance); static int NCR5380_init(struct Scsi_Host *instance, int flags); static int NCR5380_maybe_reset_bus(struct Scsi_Host *); static void NCR5380_exit(struct Scsi_Host *instance); diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 7299ad9..3790ed5 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -265,7 +
[PATCH 1/2] NCR5380: Use probe_irq_*() for IRQ probing
Use standard probe_irq_on() and probe_irq_off() functions instead of own implementation. This prevents warning messages like this in the kernel log: genirq: Flags mismatch irq 1. (NCR-probe) vs. 0080 (i8042) Move the IRQ trigger code to a separate function so it can be used for other purposes (testing if the IRQ works). Also add missing IRQ reset after probe. Signed-off-by: Ondrej Zary --- drivers/scsi/NCR5380.c | 72 +- drivers/scsi/NCR5380.h |3 +- drivers/scsi/g_NCR5380.c |2 +- 3 files changed, 29 insertions(+), 48 deletions(-) diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index d849ffa..01c0027 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -351,50 +351,13 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) } #endif - -static int probe_irq; - -/** - * probe_intr - helper for IRQ autoprobe - * @irq: interrupt number - * @dev_id: unused - * @regs: unused - * - * Set a flag to indicate the IRQ in question was received. This is - * used by the IRQ probe code. - */ - -static irqreturn_t probe_intr(int irq, void *dev_id) -{ - probe_irq = irq; - return IRQ_HANDLED; -} - -/** - * NCR5380_probe_irq - find the IRQ of an NCR5380 - * @instance: NCR5380 controller - * @possible: bitmask of ISA IRQ lines - * - * Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ - * and then looking to see what interrupt actually turned up. - */ - -static int __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, - int possible) +static void NCR5380_trigger_irq(struct Scsi_Host *instance) { struct NCR5380_hostdata *hostdata = shost_priv(instance); - unsigned long timeout; - int trying_irqs, i, mask; - - for (trying_irqs = 0, i = 1, mask = 2; i < 16; ++i, mask <<= 1) - if ((mask & possible) && (request_irq(i, &probe_intr, 0, "NCR-probe", NULL) == 0)) - trying_irqs |= mask; - - timeout = jiffies + msecs_to_jiffies(250); - probe_irq = NO_IRQ; + unsigned long timeout = jiffies + msecs_to_jiffies(2500); /* -* A interrupt is triggered whenever BSY = false, SEL = true +* An interrupt is triggered whenever BSY = false, SEL = true * and a bit set in the SELECT_ENABLE_REG is asserted on the * SCSI bus. * @@ -402,23 +365,40 @@ static int __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, * (I/O, C/D, and MSG) match those in the TCR, so we must reset that * to zero. */ - NCR5380_write(TARGET_COMMAND_REG, 0); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL); - while (probe_irq == NO_IRQ && time_before(jiffies, timeout)) + while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_IRQ) && + time_before(jiffies, timeout)) schedule_timeout_uninterruptible(1); NCR5380_write(SELECT_ENABLE_REG, 0); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); +} - for (i = 1, mask = 2; i < 16; ++i, mask <<= 1) - if (trying_irqs & mask) - free_irq(i, NULL); +/** + * NCR5380_probe_irq - find the IRQ of an NCR5380 + * @instance: NCR5380 controller + * + * Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ + * and then looking to see what interrupt actually turned up. + */ + +static int NCR5380_probe_irq(struct Scsi_Host *instance) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + int irqs, irq; + + irqs = probe_irq_on(); + NCR5380_trigger_irq(instance); + irq = probe_irq_off(irqs); + NCR5380_read(RESET_PARITY_INTERRUPT_REG); + if (irq < 0) + irq = 0; - return probe_irq; + return irq; } /** diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 3c6ce54..b2fca52 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -290,7 +290,8 @@ static inline struct scsi_cmnd *NCR5380_to_scmd(struct NCR5380_cmd *ncmd_ptr) #define NCR5380_dprint_phase(flg, arg) do {} while (0) #endif -static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible); +static void NCR5380_trigger_irq(struct Scsi_Host *instance); +static int NCR5380_probe_irq(struct Scsi_Host *instance); static int NCR5380_init(struct Scsi_Host *instance, int flags); static int NCR5380_maybe_reset_bus(struct Scsi_Host *); static void NCR5380_exit(struct Scsi_Host *instance); diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 7299ad9..3790ed5 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -265,7 +
[PATCH 2/2] g_NCR5380: Test the IRQ before accepting it
Trigger an IRQ first with a test IRQ handler to find out if it really works. Disable the IRQ if not. This prevents hang when incorrect IRQ was specified by user. Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c | 31 +-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 3790ed5..f0c5b10 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -67,6 +67,14 @@ MODULE_ALIAS("g_NCR5380_mmio"); MODULE_LICENSE("GPL"); +static bool irq_working; + +static irqreturn_t test_irq(int irq, void *dev_id) +{ + irq_working = true; + return IRQ_HANDLED; +} + /* * Configure I/O address of 53C400A or DTC436 by writing magic numbers * to ports 0x779 and 0x379. @@ -275,10 +283,29 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, /* set IRQ for HP C2502 */ if (board == BOARD_HP_C2502) magic_configure(port_idx, instance->irq, magic); - if (request_irq(instance->irq, generic_NCR5380_intr, - 0, "NCR5380", instance)) { + /* test if the IRQ is working */ + irq_working = false; + if (request_irq(instance->irq, test_irq, + 0, "NCR5380-irqtest", NULL)) { printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); instance->irq = NO_IRQ; + } else { + NCR5380_trigger_irq(instance); + free_irq(instance->irq, NULL); + if (irq_working) { + if (request_irq(instance->irq, + generic_NCR5380_intr, 0, + "NCR5380", instance)) { + printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", + instance->host_no, + instance->irq); + instance->irq = NO_IRQ; + } + } else { + printk(KERN_WARNING "scsi%d : IRQ%d not working, interrupts disabled\n", + instance->host_no, instance->irq); + instance->irq = NO_IRQ; + } } } -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] scsi: NCR5380: no longer mark irq probing as __init
On Tuesday 11 October 2016 11:39:57 Finn Thain wrote: > Acked-by: Finn Thain > > Thanks. > > On Tue, 11 Oct 2016, Arnd Bergmann wrote: > > The g_NCR5380 has been converted to more regular probing, which > > means its probe function can now be invoked after the __init section > > is discarded, as pointed out by this kbuild warning: > > > > WARNING: drivers/scsi/built-in.o(.text+0x3a105): Section mismatch in > > reference from the function generic_NCR5380_isa_match() to the function > > .init.text:probe_intr() WARNING: drivers/scsi/built-in.o(.text+0x3a145): > > Section mismatch in reference from the function > > generic_NCR5380_isa_match() to the variable .init.data:probe_irq > > > > To make sure this works correctly in all cases, let's remove > > the __init and __initdata annotations. > > > > Fixes: a8cfbcaec0c1 ("scsi: g_NCR5380: Stop using scsi_module.c") > > Signed-off-by: Arnd Bergmann > > --- > > drivers/scsi/NCR5380.c | 6 +++--- > > 1 file changed, 3 insertions(+), 3 deletions(-) > > > > diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c > > index 7053de5bd468..61f34aca2fa0 100644 > > --- a/drivers/scsi/NCR5380.c > > +++ b/drivers/scsi/NCR5380.c > > @@ -353,7 +353,7 @@ static void NCR5380_print_phase(struct Scsi_Host > > *instance) #endif > > > > > > -static int probe_irq __initdata; > > +static int probe_irq; > > > > /** > > * probe_intr - helper for IRQ autoprobe > > @@ -365,7 +365,7 @@ static int probe_irq __initdata; > > * used by the IRQ probe code. > > */ > > > > -static irqreturn_t __init probe_intr(int irq, void *dev_id) > > +static irqreturn_t probe_intr(int irq, void *dev_id) > > { > > probe_irq = irq; > > return IRQ_HANDLED; > > @@ -380,7 +380,7 @@ static irqreturn_t __init probe_intr(int irq, void > > *dev_id) * and then looking to see what interrupt actually turned up. > > */ > > > > -static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host > > *instance, +static int __maybe_unused NCR5380_probe_irq(struct Scsi_Host > > *instance, int possible) > > { > > struct NCR5380_hostdata *hostdata = shost_priv(instance); I've tested IRQ probing on my IRQ7-hardwired ISA card without any success some time ago. No IRQ was detected because it wasn't even generated (no increment in /proc/interruptts). It also produced some warnings in dmesg about conflicting interrupt flags. Can't the IRQ probing be simply deleted? -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 00/12] Fixes, cleanup and g_NCR5380_mmio/g_NCR5380 merger
On Friday 07 October 2016 01:41:06 Finn Thain wrote: > This patch series has fixes for compatibility, reliability and > performance issues and some cleanup. It also includes a new version > of Ondrej Zary's patch that merges g_NCR5380_mmio into g_NCR5380. > > I've tested this patch series on a Powerbook 180. If someone would > test some of the other platforms that would be very helpful. All > drivers were compile-tested. > > Changes since v1: > - rebased on 4.9/scsi-queue > - added reviewed-by tags > - tweaked the order of struct members in patch 7/12 > > > Finn Thain (12): > scsi/g_NCR5380: Merge g_NCR5380 and g_NCR5380_mmio drivers > scsi/cumana_1: Remove unused cumanascsi_setup() function > scsi/atari_scsi: Make device register accessors re-enterant > scsi/ncr5380: Simplify register polling limit > scsi/ncr5380: Increase register polling limit > scsi/ncr5380: Improve hostdata struct member alignment and > cache-ability > scsi/ncr5380: Store IO ports and addresses in host private data > scsi/ncr5380: Use correct types for device register accessors > scsi/ncr5380: Pass hostdata pointer to register polling routines > scsi/ncr5380: Expedite register polling > scsi/ncr5380: Use correct types for DMA routines > scsi/ncr5380: Suppress unhelpful "interrupt without IRQ bit" message Tested on HP C2502 (53C400A chip), Canon FG2-5202 (53C400 chip) and DTC-3181L (DTCT-436P chip) ISA cards - everything works fine! Thanks. Tested-by: Ondrej Zary -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 00/12] Fixes, cleanup and g_NCR5380_mmio/g_NCR5380 merger
On Tuesday 04 October 2016 07:40:50 Finn Thain wrote: > This patch series has fixes for compatibility, reliability and > performance issues and some cleanup. It also includes a new version > of Ondrej Zary's patch that merges g_NCR5380_mmio into g_NCR5380. > > I've tested this patch series on a Powerbook 180. If someone would > test some of the other platforms that would be very helpful. All > drivers were compile-tested. > > (Apologies for any duplicate messages.) The patches won't apply against: 4.9/scsi-queue Linus' master with my patches applied What tree should I try? > Finn Thain (12): > scsi/g_NCR5380: Merge g_NCR5380 and g_NCR5380_mmio drivers > scsi/cumana_1: Remove unused cumanascsi_setup() function > scsi/atari_scsi: Make device register accessors re-enterant > scsi/ncr5380: Simplify register polling limit > scsi/ncr5380: Increase register polling limit > scsi/ncr5380: Improve hostdata struct member alignment and > cache-ability > scsi/ncr5380: Store IO ports and addresses in host private data > scsi/ncr5380: Use correct types for device register accessors > scsi/ncr5380: Pass hostdata pointer to register polling routines > scsi/ncr5380: Expedite register polling > scsi/ncr5380: Use correct types for DMA routines > scsi/ncr5380: Suppress unhelpful "interrupt without IRQ bit" message > > MAINTAINERS | 1 - > drivers/scsi/Kconfig | 32 + > drivers/scsi/Makefile | 1 - > drivers/scsi/NCR5380.c| 137 +++- > drivers/scsi/NCR5380.h| 87 + > drivers/scsi/arm/cumana_1.c | 98 +++--- > drivers/scsi/arm/oak.c| 34 +++-- > drivers/scsi/atari_scsi.c | 77 ++- > drivers/scsi/dmx3191d.c | 20 +-- > drivers/scsi/g_NCR5380.c | 290 > -- drivers/scsi/g_NCR5380.h | > 32 + > drivers/scsi/g_NCR5380_mmio.c | 10 -- > drivers/scsi/mac_scsi.c | 83 +--- > drivers/scsi/sun3_scsi.c | 80 ++-- > 14 files changed, 495 insertions(+), 487 deletions(-) > delete mode 100644 drivers/scsi/g_NCR5380_mmio.c -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/3] g_NCR5380: Modernization
This small patch series removes deprecated code from g_NCR5380 driver and converts it from scsi_module.c to scsi_add_host(). Tested with: HP C2502 (53C400A chip) Canon FG2-5202 (53C400 chip, memory-mapped) DTC-3181L (DTCT-436P chip, PnP) --- Changes in v2: - updated Documentation/scsi/g_NCR5380.txt - kept old-style module parameters for compatibility - added missing NCR5380_exit() call - fixed error propagation from init - simplified driver registration -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/3] g_NCR5380: Stop using scsi_module.c
Convert g_NCR5380 to use scsi_add_host instead of scsi_module.c Use pnp_driver and isa_driver to manage cards. In order to support multiple cards, new module parameter format is introduced. The old parameters are kept for compatibility. Signed-off-by: Ondrej Zary --- Documentation/scsi/g_NCR5380.txt | 24 ++- drivers/scsi/g_NCR5380.c | 335 ++ drivers/scsi/g_NCR5380.h |8 - 3 files changed, 215 insertions(+), 152 deletions(-) diff --git a/Documentation/scsi/g_NCR5380.txt b/Documentation/scsi/g_NCR5380.txt index 843cbae..e2c1879 100644 --- a/Documentation/scsi/g_NCR5380.txt +++ b/Documentation/scsi/g_NCR5380.txt @@ -28,6 +28,16 @@ time. More info to come in the future. This driver works as a module. When included as a module, parameters can be passed on the insmod/modprobe command line: + irq=xx[,...] the interrupt(s) + base=xx[,...]the port or base address(es) (for port or memory mapped, resp.) + card=xx[,...]card type(s): + 0 = NCR5380, + 1 = NCR53C400, + 2 = NCR53C400A, + 3 = Domex Technology Corp 3181E (DTC3181E) + 4 = Hewlett Packard C2502 + +These old-style parameters can support only one card: ncr_irq=xx the interrupt ncr_addr=xx the port or base address (for port or memory mapped, resp.) @@ -36,11 +46,19 @@ command line: ncr_53c400a=1 to set up for a NCR53C400A board dtc_3181e=1 to set up for a Domex Technology Corp 3181E board hp_c2502=1 to set up for a Hewlett Packard C2502 board + e.g. -modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1 +OLD: modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1 +NEW: modprobe g_NCR5380 irq=5 base=0x350 card=0 for a port mapped NCR5380 board or -modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1 - for a memory mapped NCR53C400 board with interrupts disabled. + +OLD: modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1 +NEW: modprobe g_NCR5380 irq=255 base=0xc8000 card=1 + for a memory mapped NCR53C400 board with interrupts disabled or + +NEW: modprobe g_NCR5380 irq=0,7 base=0x240,0x300 card=3,4 + for two cards: DTC3181 (in non-PnP mode) at 0x240 with no IRQ + and HP C2502 at 0x300 with IRQ 7 (255 should be specified for no or DMA interrupt, 254 to autoprobe for an IRQ line if overridden on the command line.) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 5162de6..cbf0103 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -30,24 +30,41 @@ #include "NCR5380.h" #include #include -#include +#include +#include #include +#define MAX_CARDS 8 + +/* old-style parameters for compatibility */ static int ncr_irq; -static int ncr_dma; static int ncr_addr; static int ncr_5380; static int ncr_53c400; static int ncr_53c400a; static int dtc_3181e; static int hp_c2502; +module_param(ncr_irq, int, 0); +module_param(ncr_addr, int, 0); +module_param(ncr_5380, int, 0); +module_param(ncr_53c400, int, 0); +module_param(ncr_53c400a, int, 0); +module_param(dtc_3181e, int, 0); +module_param(hp_c2502, int, 0); + +static int irq[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +module_param_array(irq, int, NULL, 0); +MODULE_PARM_DESC(irq, "IRQ number(s)"); -static struct card { - NCR5380_map_type NCR5380_map_name; - int irq; - int dma; - int board; /* Use NCR53c400, Ricoh, etc. extensions ? */ -} card; +static int base[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +module_param_array(base, int, NULL, 0); +MODULE_PARM_DESC(base, "base address(es)"); + +static int card[] = { -1, -1, -1, -1, -1, -1, -1, -1 }; +module_param_array(card, int, NULL, 0); +MODULE_PARM_DESC(card, "card type (0=NCR5380, 1=NCR53C400, 2=NCR53C400A, 3=DTC3181E, 4=HP C2502)"); + +MODULE_LICENSE("GPL"); #ifndef SCSI_G_NCR5380_MEM /* @@ -73,17 +90,8 @@ static void magic_configure(int idx, u8 irq, u8 magic[]) } #endif -/** - * generic_NCR5380_detect - look for NCR5380 controllers - * @tpnt: the scsi template - * - * Scan for the present of NCR5380, NCR53C400, NCR53C400A, DTC3181E - * and DTC436(ISAPnP) controllers. - * - * Locks: none - */ - -static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) +static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, + struct device *pdev, int base, int irq, int board) { unsigned int *ports; u8 *magic = NULL; @@ -92,80 +100,29 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) int port_idx = -1; unsigned long region_size; #endif - static unsigned int __initdata ncr_53c400a_ports[] = { + static unsigned int ncr_53c400a_ports[] = { 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 }; - static unsigned int __initdata dtc_3181e_ports
[PATCH 1/3] g_NCR5380: Remove deprecated __setup
Remove deprecated __setup for parsing command line parameters. g_NCR5380.* parameters could be used instead. This might break existing setups with g_NCR5380 built-in (if there are any). But it has to go in order to remove the overrides[] array. Signed-off-by: Ondrej Zary --- Documentation/scsi/g_NCR5380.txt | 10 --- drivers/scsi/g_NCR5380.c | 135 -- 2 files changed, 145 deletions(-) diff --git a/Documentation/scsi/g_NCR5380.txt b/Documentation/scsi/g_NCR5380.txt index fd88015..843cbae 100644 --- a/Documentation/scsi/g_NCR5380.txt +++ b/Documentation/scsi/g_NCR5380.txt @@ -21,16 +21,6 @@ NCR53c400 card, the Trantor T130B in its default configuration: The NCR53c400 does not support DMA but it does have Pseudo-DMA which is supported by the driver. -If the default configuration does not work for you, you can use the kernel -command lines (eg using the lilo append command): - ncr5380=addr,irq - ncr53c400=addr,irq - ncr53c400a=addr,irq - dtc3181e=addr,irq - -The driver does not probe for any addresses or ports other than those in -the OVERRIDE or given to the kernel as above. - This driver provides some information on what it has detected in /proc/scsi/g_NCR5380/x where x is the scsi card number as detected at boot time. More info to come in the future. diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 516bd6c..7e50b44e 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -56,136 +56,6 @@ static struct override { #define NO_OVERRIDES ARRAY_SIZE(overrides) -#ifndef MODULE - -/** - * internal_setup - handle lilo command string override - * @board: BOARD_* identifier for the board - * @str: unused - * @ints: numeric parameters - * - * Do LILO command line initialization of the overrides array. Display - * errors when needed - * - * Locks: none - */ - -static void __init internal_setup(int board, char *str, int *ints) -{ - static int commandline_current; - switch (board) { - case BOARD_NCR5380: - if (ints[0] != 2 && ints[0] != 3) { - printk(KERN_ERR "generic_NCR5380_setup : usage ncr5380=" STRVAL(NCR5380_map_name) ",irq,dma\n"); - return; - } - break; - case BOARD_NCR53C400: - if (ints[0] != 2) { - printk(KERN_ERR "generic_NCR53C400_setup : usage ncr53c400=" STRVAL(NCR5380_map_name) ",irq\n"); - return; - } - break; - case BOARD_NCR53C400A: - if (ints[0] != 2) { - printk(KERN_ERR "generic_NCR53C400A_setup : usage ncr53c400a=" STRVAL(NCR5380_map_name) ",irq\n"); - return; - } - break; - case BOARD_DTC3181E: - if (ints[0] != 2) { - printk("generic_DTC3181E_setup : usage dtc3181e=" STRVAL(NCR5380_map_name) ",irq\n"); - return; - } - break; - } - - if (commandline_current < NO_OVERRIDES) { - overrides[commandline_current].NCR5380_map_name = (NCR5380_map_type) ints[1]; - overrides[commandline_current].irq = ints[2]; - if (ints[0] == 3) - overrides[commandline_current].dma = ints[3]; - else - overrides[commandline_current].dma = DMA_NONE; - overrides[commandline_current].board = board; - ++commandline_current; - } -} - - -/** - * do_NCR53C80_setup - set up entry point - * @str: unused - * - * Setup function invoked at boot to parse the ncr5380= command - * line. - */ - -static int __init do_NCR5380_setup(char *str) -{ - int ints[10]; - - get_options(str, ARRAY_SIZE(ints), ints); - internal_setup(BOARD_NCR5380, str, ints); - return 1; -} - -/** - * do_NCR53C400_setup - set up entry point - * @str: unused - * @ints: integer parameters from kernel setup code - * - * Setup function invoked at boot to parse the ncr53c400= command - * line. - */ - -static int __init do_NCR53C400_setup(char *str) -{ - int ints[10]; - - get_options(str, ARRAY_SIZE(ints), ints); - internal_setup(BOARD_NCR53C400, str, ints); - return 1; -} - -/** - * do_NCR53C400A_setup - set up entry point - * @str: unused - * @ints: integer parameters from kernel setup code - * - * Setup function invoked at boot to parse the ncr53c400a= command - * line. - */ - -static int __init do_NCR53C400A_setup(char *str) -{ - int ints[10]; - - get_options(str, ARRAY_SIZE(ints), ints); - internal_setup(BOARD_NCR53C400A, s
[PATCH 2/3] g_NCR5380: Reduce overrides[] from array to struct
Remove compile-time card type definition GENERIC_NCR5380_OVERRIDE. Then remove all code iterating the overrides[] array and reduce it to struct card. Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c | 351 ++ 1 file changed, 167 insertions(+), 184 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 7e50b44e..5162de6 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -42,19 +42,12 @@ static int ncr_53c400a; static int dtc_3181e; static int hp_c2502; -static struct override { +static struct card { NCR5380_map_type NCR5380_map_name; int irq; int dma; int board; /* Use NCR53c400, Ricoh, etc. extensions ? */ -} overrides -#ifdef GENERIC_NCR5380_OVERRIDE -[] __initdata = GENERIC_NCR5380_OVERRIDE; -#else -[1] __initdata = { { 0,},}; -#endif - -#define NO_OVERRIDES ARRAY_SIZE(overrides) +} card; #ifndef SCSI_G_NCR5380_MEM /* @@ -85,16 +78,13 @@ static void magic_configure(int idx, u8 irq, u8 magic[]) * @tpnt: the scsi template * * Scan for the present of NCR5380, NCR53C400, NCR53C400A, DTC3181E - * and DTC436(ISAPnP) controllers. If overrides have been set we use - * them. + * and DTC436(ISAPnP) controllers. * * Locks: none */ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) { - static int current_override; - int count; unsigned int *ports; u8 *magic = NULL; #ifndef SCSI_G_NCR5380_MEM @@ -124,28 +114,25 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) #endif if (ncr_irq) - overrides[0].irq = ncr_irq; + card.irq = ncr_irq; if (ncr_dma) - overrides[0].dma = ncr_dma; + card.dma = ncr_dma; if (ncr_addr) - overrides[0].NCR5380_map_name = (NCR5380_map_type) ncr_addr; + card.NCR5380_map_name = (NCR5380_map_type) ncr_addr; if (ncr_5380) - overrides[0].board = BOARD_NCR5380; + card.board = BOARD_NCR5380; else if (ncr_53c400) - overrides[0].board = BOARD_NCR53C400; + card.board = BOARD_NCR53C400; else if (ncr_53c400a) - overrides[0].board = BOARD_NCR53C400A; + card.board = BOARD_NCR53C400A; else if (dtc_3181e) - overrides[0].board = BOARD_DTC3181E; + card.board = BOARD_DTC3181E; else if (hp_c2502) - overrides[0].board = BOARD_HP_C2502; + card.board = BOARD_HP_C2502; #ifndef SCSI_G_NCR5380_MEM - if (!current_override && isapnp_present()) { + if (isapnp_present()) { struct pnp_dev *dev = NULL; - count = 0; while ((dev = pnp_find_dev(NULL, ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e), dev))) { - if (count >= NO_OVERRIDES) - break; if (pnp_device_attach(dev) < 0) continue; if (pnp_activate_dev(dev) < 0) { @@ -159,202 +146,198 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) continue; } if (pnp_irq_valid(dev, 0)) - overrides[count].irq = pnp_irq(dev, 0); + card.irq = pnp_irq(dev, 0); else - overrides[count].irq = NO_IRQ; + card.irq = NO_IRQ; if (pnp_dma_valid(dev, 0)) - overrides[count].dma = pnp_dma(dev, 0); + card.dma = pnp_dma(dev, 0); else - overrides[count].dma = DMA_NONE; - overrides[count].NCR5380_map_name = (NCR5380_map_type) pnp_port_start(dev, 0); - overrides[count].board = BOARD_DTC3181E; - count++; + card.dma = DMA_NONE; + card.NCR5380_map_name = (NCR5380_map_type) pnp_port_start(dev, 0); + card.board = BOARD_DTC3181E; + break; } } #endif - for (count = 0; current_override < NO_OVERRIDES; ++current_override) { - if (!(overrides[current_override].NCR5380_map_name)) - continue; + if (!(card.NCR5380_map_name)) + return 0; - ports = NULL; - flags = 0; - switch (overrides[current_override].board) { - case BOARD_NCR5380: - flags = FLAG_NO_PSEUDO_DMA | FLAG_DMA_FIXUP; -
Re: [PATCH 3/3] g_NCR5380: Stop using scsi_module.c
On Monday 26 September 2016, Finn Thain wrote: [...] > Instead of this: > > + if (scsi_add_host(instance, pdev)) { > > + free_irq(irq, instance); > > + goto out_unregister; > > + } > > + scsi_scan_host(instance); > > + return instance; > > please use the following (note the missing NCR5380_exit() call): > > + if (scsi_add_host(instance, pdev)) > + goto out_free_irq; > + scsi_scan_host(instance); > + return(instance); > + > +out_free_irq: > + if (instance->irq != NO_IRQ) > + free_irq(instance->irq, instance); > + NCR5380_exit(instance); > > > out_unregister: > > - scsi_unregister(instance); > > + scsi_host_put(instance); > > out_release: > > #ifndef SCSI_G_NCR5380_MEM > > - release_region(card.NCR5380_map_name, region_size); > > + release_region(base, region_size); > > #else > > iounmap(iomem); > > release_mem_region(base, iomem_size); > > #endif > > - return 0; > > + return NULL; > > } > > > > -/** > > - * generic_NCR5380_release_resources - free resources > > - * @instance: host adapter to clean up > > - * > > - * Free the generic interface resources from this adapter. > > - * > > - * Locks: none > > - */ > > - > > -static int generic_NCR5380_release_resources(struct Scsi_Host *instance) > > +static void generic_NCR5380_release_resources(struct Scsi_Host > > *instance) { > > + scsi_remove_host(instance); > > if (instance->irq != NO_IRQ) > > free_irq(instance->irq, instance); > > NCR5380_exit(instance); > > @@ -364,7 +304,7 @@ static int generic_NCR5380_release_resources(struct > > Scsi_Host *instance) release_mem_region(instance->base, > > hostdata->iomem_size); > > } > > #endif > > - return 0; > > + scsi_host_put(instance); > > The sequence of operations here should be the same as the error path > above. I put scsi_host_put() call at the end because the release_mem_region code (in the MMIO case) dereferences the hostdata pointer. I don't think it's safe to do after scsi_host_put(). [...] > > +static int pnp_registered; > > +#endif /* !defined(SCSI_G_NCR5380_MEM) && defined(CONFIG_PNP) */ > > + > > +static int __init generic_NCR5380_init(void) > > +{ > > + int ret = 0; > > + > > +#if !defined(SCSI_G_NCR5380_MEM) && defined(CONFIG_PNP) > > + ret = pnp_register_driver(&generic_NCR5380_pnp_driver); > > + if (!ret) > > + pnp_registered = 1; > > #endif > > + ret = isa_register_driver(&generic_NCR5380_isa_driver, MAX_CARDS); > > + if (!ret) > > + isa_registered = 1; > > + > > +#if !defined(SCSI_G_NCR5380_MEM) && defined(CONFIG_PNP) > > + if (pnp_registered) > > + ret = 0; > > +#endif > > + if (isa_registered) > > + ret = 0; > > + > > + return ret; > > +} > > + > > +static void __exit generic_NCR5380_exit(void) > > +{ > > +#if !defined(SCSI_G_NCR5380_MEM) && defined(CONFIG_PNP) > > + if (pnp_registered) > > + pnp_unregister_driver(&generic_NCR5380_pnp_driver); > > +#endif > > + if (isa_registered) > > + isa_unregister_driver(&generic_NCR5380_isa_driver); > > +} > > + > > I find that hard to follow. This should be equivalent and simpler: > > static int __init generic_NCR5380_init(void) > { > isa_ret = isa_register_driver(&generic_NCR5380_isa_driver, MAX_CARDS); > #if !defined(SCSI_G_NCR5380_MEM) && defined(CONFIG_PNP) > pnp_ret = pnp_register_driver(&generic_NCR5380_pnp_driver); > return pnp_ret ? isa_ret : 0; > #endif > return isa_ret; > } > > static void __exit generic_NCR5380_exit(void) > { > if (!isa_ret) > isa_unregister_driver(&generic_NCR5380_isa_driver); > #if !defined(SCSI_G_NCR5380_MEM) && defined(CONFIG_PNP) > if (!pnp_ret) > pnp_unregister_driver(&generic_NCR5380_pnp_driver); > #endif > } Doesn't make it any better, IMHO. Good that it's shorter but not cleaner - especially this: > return pnp_ret ? isa_ret : 0; Also looking at the _exit function, meaning of isa_ret and pnp_ret is not obvious there. Maybe we should have a module_isa_pnp_driver() macro. -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/3] g_NCR5380: Merge g_NCR5380 and g_NCR5380_mmio
Merge the PIO and MMIO code (with the help of ioport_map) in g_NCR5380 and delete g_NCR5380_mmio. Signed-off-by: Ondrej Zary --- drivers/scsi/Kconfig | 32 ++--- drivers/scsi/g_NCR5380.c | 257 +++-- drivers/scsi/g_NCR5380.h | 33 ++ drivers/scsi/g_NCR5380_mmio.c | 10 -- 4 files changed, 135 insertions(+), 197 deletions(-) delete mode 100644 drivers/scsi/g_NCR5380_mmio.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 7d1b431..fd1bca1 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -780,40 +780,22 @@ config SCSI_ISCI control unit found in the Intel(R) C600 series chipset. config SCSI_GENERIC_NCR5380 - tristate "Generic NCR5380/53c400 SCSI PIO support" + tristate "Generic NCR5380/53c400 SCSI" depends on ISA && SCSI select SCSI_SPI_ATTRS ---help--- - This is a driver for the old NCR 53c80 series of SCSI controllers - on boards using PIO. Most boards such as the Trantor T130 fit this - category, along with a large number of ISA 8bit controllers shipped - for free with SCSI scanners. If you have a PAS16, T128 or DMX3191 - you should select the specific driver for that card rather than - generic 5380 support. + This is a driver for the old NCR 53c80 series of SCSI controllers. + Most boards such as the Trantor T130 fit this category, along with + a large number of ISA 8bit controllers shipped for free with SCSI + scanners. If you have a PAS16, T128 or DMX3191 you should select the + specific driver for that card rather than generic 5380 support. It is explained in section 3.8 of the SCSI-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. If it doesn't work out - of the box, you may have to change some settings in - . + <http://www.tldp.org/docs.html#howto>. To compile this driver as a module, choose M here: the module will be called g_NCR5380. -config SCSI_GENERIC_NCR5380_MMIO - tristate "Generic NCR5380/53c400 SCSI MMIO support" - depends on ISA && SCSI - select SCSI_SPI_ATTRS - ---help--- - This is a driver for the old NCR 53c80 series of SCSI controllers - on boards using memory mapped I/O. - It is explained in section 3.8 of the SCSI-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. If it doesn't work out - of the box, you may have to change some settings in - . - - To compile this driver as a module, choose M here: the - module will be called g_NCR5380_mmio. - config SCSI_IPS tristate "IBM ServeRAID support" depends on PCI && SCSI diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 6cf6b00..7d8fcbf 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -50,7 +50,6 @@ MODULE_PARM_DESC(card, "card type (0=NCR5380, 1=NCR53C400, 2=NCR53C400A, 3=DTC31 MODULE_LICENSE("GPL"); -#ifndef SCSI_G_NCR5380_MEM /* * Configure I/O address of 53C400A or DTC436 by writing magic numbers * to ports 0x779 and 0x379. @@ -72,41 +71,33 @@ static void magic_configure(int idx, u8 irq, u8 magic[]) cfg = 0x80 | idx | (irq << 4); outb(cfg, 0x379); } -#endif + +static unsigned int ncr_53c400a_ports[] __initdata = { + 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 +}; +static unsigned int dtc_3181e_ports[] __initdata = { + 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0 +}; +static u8 ncr_53c400a_magic[] __initdata = { /* 53C400A & DTC436 */ + 0x59, 0xb9, 0xc5, 0xae, 0xa6 +}; +static u8 hp_c2502_magic[] __initdata = { /* HP C2502 */ + 0x0f, 0x22, 0xf0, 0x20, 0x80 +}; static struct Scsi_Host *generic_NCR5380_hw_init( struct scsi_host_template *tpnt, struct device *pdev, int base, int irq, int board) { - unsigned int *ports; + unsigned int *ports = NULL; u8 *magic = NULL; -#ifndef SCSI_G_NCR5380_MEM - int i; - int port_idx = -1; + int i, port_idx = -1, flags = 0; unsigned long region_size; -#endif - static unsigned int __initdata ncr_53c400a_ports[] = { - 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 - }; - static unsigned int __initdata dtc_3181e_ports[] = { - 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0 - }; - static u8 ncr_53c400a_magic[] __initdata = {/* 53C400A & DTC436 */ - 0x59, 0xb9, 0xc5, 0xae, 0xa6 - }; - static u8 hp_c2502_magic[] __initdata = { /* HP C2502 */ - 0x0f, 0x22, 0xf0, 0x20, 0x80 - }; - int flags;
[PATCH 0/3] g_NCR5380: Modernization
This small patch series removes deprecated code from g_NCR5380 driver and converts it from scsi_module.c to scsi_add_host(). Tested with: HP C2502 (53C400A chip) Canon FG2-5202 (53C400 chip, memory-mapped) DTC-3181L (DTCT-436P chip, PnP) P.S. I don't like the ifdef mess needed for g_NCR5380_mmio. Should I try to merge the code so g_NCR5380 will support both PIO and MMIO cards (and g_NCR5380_mmio could be removed)? -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3] g_NCR5380: Reduce overrides[] from array to struct
Remove compile-time card type definition GENERIC_NCR5380_OVERRIDE. Then remove all code iterating the overrides[] array and reduce it to struct card. Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c | 351 ++ 1 file changed, 167 insertions(+), 184 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 7e50b44e..5162de6 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -42,19 +42,12 @@ static int ncr_53c400a; static int dtc_3181e; static int hp_c2502; -static struct override { +static struct card { NCR5380_map_type NCR5380_map_name; int irq; int dma; int board; /* Use NCR53c400, Ricoh, etc. extensions ? */ -} overrides -#ifdef GENERIC_NCR5380_OVERRIDE -[] __initdata = GENERIC_NCR5380_OVERRIDE; -#else -[1] __initdata = { { 0,},}; -#endif - -#define NO_OVERRIDES ARRAY_SIZE(overrides) +} card; #ifndef SCSI_G_NCR5380_MEM /* @@ -85,16 +78,13 @@ static void magic_configure(int idx, u8 irq, u8 magic[]) * @tpnt: the scsi template * * Scan for the present of NCR5380, NCR53C400, NCR53C400A, DTC3181E - * and DTC436(ISAPnP) controllers. If overrides have been set we use - * them. + * and DTC436(ISAPnP) controllers. * * Locks: none */ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) { - static int current_override; - int count; unsigned int *ports; u8 *magic = NULL; #ifndef SCSI_G_NCR5380_MEM @@ -124,28 +114,25 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) #endif if (ncr_irq) - overrides[0].irq = ncr_irq; + card.irq = ncr_irq; if (ncr_dma) - overrides[0].dma = ncr_dma; + card.dma = ncr_dma; if (ncr_addr) - overrides[0].NCR5380_map_name = (NCR5380_map_type) ncr_addr; + card.NCR5380_map_name = (NCR5380_map_type) ncr_addr; if (ncr_5380) - overrides[0].board = BOARD_NCR5380; + card.board = BOARD_NCR5380; else if (ncr_53c400) - overrides[0].board = BOARD_NCR53C400; + card.board = BOARD_NCR53C400; else if (ncr_53c400a) - overrides[0].board = BOARD_NCR53C400A; + card.board = BOARD_NCR53C400A; else if (dtc_3181e) - overrides[0].board = BOARD_DTC3181E; + card.board = BOARD_DTC3181E; else if (hp_c2502) - overrides[0].board = BOARD_HP_C2502; + card.board = BOARD_HP_C2502; #ifndef SCSI_G_NCR5380_MEM - if (!current_override && isapnp_present()) { + if (isapnp_present()) { struct pnp_dev *dev = NULL; - count = 0; while ((dev = pnp_find_dev(NULL, ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e), dev))) { - if (count >= NO_OVERRIDES) - break; if (pnp_device_attach(dev) < 0) continue; if (pnp_activate_dev(dev) < 0) { @@ -159,202 +146,198 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) continue; } if (pnp_irq_valid(dev, 0)) - overrides[count].irq = pnp_irq(dev, 0); + card.irq = pnp_irq(dev, 0); else - overrides[count].irq = NO_IRQ; + card.irq = NO_IRQ; if (pnp_dma_valid(dev, 0)) - overrides[count].dma = pnp_dma(dev, 0); + card.dma = pnp_dma(dev, 0); else - overrides[count].dma = DMA_NONE; - overrides[count].NCR5380_map_name = (NCR5380_map_type) pnp_port_start(dev, 0); - overrides[count].board = BOARD_DTC3181E; - count++; + card.dma = DMA_NONE; + card.NCR5380_map_name = (NCR5380_map_type) pnp_port_start(dev, 0); + card.board = BOARD_DTC3181E; + break; } } #endif - for (count = 0; current_override < NO_OVERRIDES; ++current_override) { - if (!(overrides[current_override].NCR5380_map_name)) - continue; + if (!(card.NCR5380_map_name)) + return 0; - ports = NULL; - flags = 0; - switch (overrides[current_override].board) { - case BOARD_NCR5380: - flags = FLAG_NO_PSEUDO_DMA | FLAG_DMA_FIXUP; -
[PATCH 1/3] g_NCR5380: Remove deprecated __setup
Remove deprecated __setup for parsing command line parameters. g_NCR5380.* parameters could be used instead. Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c | 135 -- 1 file changed, 135 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 516bd6c..7e50b44e 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -56,136 +56,6 @@ static struct override { #define NO_OVERRIDES ARRAY_SIZE(overrides) -#ifndef MODULE - -/** - * internal_setup - handle lilo command string override - * @board: BOARD_* identifier for the board - * @str: unused - * @ints: numeric parameters - * - * Do LILO command line initialization of the overrides array. Display - * errors when needed - * - * Locks: none - */ - -static void __init internal_setup(int board, char *str, int *ints) -{ - static int commandline_current; - switch (board) { - case BOARD_NCR5380: - if (ints[0] != 2 && ints[0] != 3) { - printk(KERN_ERR "generic_NCR5380_setup : usage ncr5380=" STRVAL(NCR5380_map_name) ",irq,dma\n"); - return; - } - break; - case BOARD_NCR53C400: - if (ints[0] != 2) { - printk(KERN_ERR "generic_NCR53C400_setup : usage ncr53c400=" STRVAL(NCR5380_map_name) ",irq\n"); - return; - } - break; - case BOARD_NCR53C400A: - if (ints[0] != 2) { - printk(KERN_ERR "generic_NCR53C400A_setup : usage ncr53c400a=" STRVAL(NCR5380_map_name) ",irq\n"); - return; - } - break; - case BOARD_DTC3181E: - if (ints[0] != 2) { - printk("generic_DTC3181E_setup : usage dtc3181e=" STRVAL(NCR5380_map_name) ",irq\n"); - return; - } - break; - } - - if (commandline_current < NO_OVERRIDES) { - overrides[commandline_current].NCR5380_map_name = (NCR5380_map_type) ints[1]; - overrides[commandline_current].irq = ints[2]; - if (ints[0] == 3) - overrides[commandline_current].dma = ints[3]; - else - overrides[commandline_current].dma = DMA_NONE; - overrides[commandline_current].board = board; - ++commandline_current; - } -} - - -/** - * do_NCR53C80_setup - set up entry point - * @str: unused - * - * Setup function invoked at boot to parse the ncr5380= command - * line. - */ - -static int __init do_NCR5380_setup(char *str) -{ - int ints[10]; - - get_options(str, ARRAY_SIZE(ints), ints); - internal_setup(BOARD_NCR5380, str, ints); - return 1; -} - -/** - * do_NCR53C400_setup - set up entry point - * @str: unused - * @ints: integer parameters from kernel setup code - * - * Setup function invoked at boot to parse the ncr53c400= command - * line. - */ - -static int __init do_NCR53C400_setup(char *str) -{ - int ints[10]; - - get_options(str, ARRAY_SIZE(ints), ints); - internal_setup(BOARD_NCR53C400, str, ints); - return 1; -} - -/** - * do_NCR53C400A_setup - set up entry point - * @str: unused - * @ints: integer parameters from kernel setup code - * - * Setup function invoked at boot to parse the ncr53c400a= command - * line. - */ - -static int __init do_NCR53C400A_setup(char *str) -{ - int ints[10]; - - get_options(str, ARRAY_SIZE(ints), ints); - internal_setup(BOARD_NCR53C400A, str, ints); - return 1; -} - -/** - * do_DTC3181E_setup - set up entry point - * @str: unused - * @ints: integer parameters from kernel setup code - * - * Setup function invoked at boot to parse the dtc3181e= command - * line. - */ - -static int __init do_DTC3181E_setup(char *str) -{ - int ints[10]; - - get_options(str, ARRAY_SIZE(ints), ints); - internal_setup(BOARD_DTC3181E, str, ints); - return 1; -} - -#endif - #ifndef SCSI_G_NCR5380_MEM /* * Configure I/O address of 53C400A or DTC436 by writing magic numbers @@ -741,8 +611,3 @@ static struct isapnp_device_id id_table[] = { MODULE_DEVICE_TABLE(isapnp, id_table); #endif - -__setup("ncr5380=", do_NCR5380_setup); -__setup("ncr53c400=", do_NCR53C400_setup); -__setup("ncr53c400a=", do_NCR53C400A_setup); -__setup("dtc3181e=", do_DTC3181E_setup); -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/3] g_NCR5380: Stop using scsi_module.c
Convert g_NCR5380 to use scsi_add_host instead of scsi_module.c Use pnp_driver and isa_driver to manage cards. Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c | 310 +- drivers/scsi/g_NCR5380.h |8 -- 2 files changed, 169 insertions(+), 149 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 5162de6..6cf6b00 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -30,24 +30,25 @@ #include "NCR5380.h" #include #include -#include +#include +#include #include -static int ncr_irq; -static int ncr_dma; -static int ncr_addr; -static int ncr_5380; -static int ncr_53c400; -static int ncr_53c400a; -static int dtc_3181e; -static int hp_c2502; - -static struct card { - NCR5380_map_type NCR5380_map_name; - int irq; - int dma; - int board; /* Use NCR53c400, Ricoh, etc. extensions ? */ -} card; +#define MAX_CARDS 8 + +static int irq[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +module_param_array(irq, int, NULL, 0); +MODULE_PARM_DESC(irq, "IRQ number(s)"); + +static int base[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +module_param_array(base, int, NULL, 0); +MODULE_PARM_DESC(base, "base address(es)"); + +static int card[] = { -1, -1, -1, -1, -1, -1, -1, -1 }; +module_param_array(card, int, NULL, 0); +MODULE_PARM_DESC(card, "card type (0=NCR5380, 1=NCR53C400, 2=NCR53C400A, 3=DTC3181E, 4=HP C2502)"); + +MODULE_LICENSE("GPL"); #ifndef SCSI_G_NCR5380_MEM /* @@ -73,17 +74,9 @@ static void magic_configure(int idx, u8 irq, u8 magic[]) } #endif -/** - * generic_NCR5380_detect - look for NCR5380 controllers - * @tpnt: the scsi template - * - * Scan for the present of NCR5380, NCR53C400, NCR53C400A, DTC3181E - * and DTC436(ISAPnP) controllers. - * - * Locks: none - */ - -static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) +static struct Scsi_Host *generic_NCR5380_hw_init( + struct scsi_host_template *tpnt, struct device *pdev, + int base, int irq, int board) { unsigned int *ports; u8 *magic = NULL; @@ -108,64 +101,13 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) struct Scsi_Host *instance; struct NCR5380_hostdata *hostdata; #ifdef SCSI_G_NCR5380_MEM - unsigned long base; void __iomem *iomem; resource_size_t iomem_size; #endif - if (ncr_irq) - card.irq = ncr_irq; - if (ncr_dma) - card.dma = ncr_dma; - if (ncr_addr) - card.NCR5380_map_name = (NCR5380_map_type) ncr_addr; - if (ncr_5380) - card.board = BOARD_NCR5380; - else if (ncr_53c400) - card.board = BOARD_NCR53C400; - else if (ncr_53c400a) - card.board = BOARD_NCR53C400A; - else if (dtc_3181e) - card.board = BOARD_DTC3181E; - else if (hp_c2502) - card.board = BOARD_HP_C2502; -#ifndef SCSI_G_NCR5380_MEM - if (isapnp_present()) { - struct pnp_dev *dev = NULL; - while ((dev = pnp_find_dev(NULL, ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e), dev))) { - if (pnp_device_attach(dev) < 0) - continue; - if (pnp_activate_dev(dev) < 0) { - printk(KERN_ERR "dtc436e probe: activate failed\n"); - pnp_device_detach(dev); - continue; - } - if (!pnp_port_valid(dev, 0)) { - printk(KERN_ERR "dtc436e probe: no valid port\n"); - pnp_device_detach(dev); - continue; - } - if (pnp_irq_valid(dev, 0)) - card.irq = pnp_irq(dev, 0); - else - card.irq = NO_IRQ; - if (pnp_dma_valid(dev, 0)) - card.dma = pnp_dma(dev, 0); - else - card.dma = DMA_NONE; - card.NCR5380_map_name = (NCR5380_map_type) pnp_port_start(dev, 0); - card.board = BOARD_DTC3181E; - break; - } - } -#endif - - if (!(card.NCR5380_map_name)) - return 0; - ports = NULL; flags = 0; - switch (card.board) { + switch (board) { case BOARD_NCR5380: flags = FLAG_NO_PSEUDO_DMA | FLAG_DMA_FIXUP; break; @@ -191,17 +133,20 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) magic_configure(-
Re: RFC: should we deprecate unmaintained isa-only drivers?
On Sunday 11 September 2016 19:01:55 Christoph Hellwig wrote: > On Wed, Mar 25, 2015 at 09:52:53PM +0100, Ondrej Zary wrote: > > > - wd7000 > > > - aha1542 > > > - in2000 > > > - NCR53c406 > > > - sym53c416 > > > - u14-34f > > > - ultrastor > > > > NCR53c406a and sym53c416 look very similar. The register numbers and > > commands are almost the same so NCR53c406 support could probably be added > > to sym53c416 driver (looks better of the two) and NCR53c406a driver > > removed. Now I have cards with both chips so I'll try. > > Did you get a chance to look at this project? At first try (with some quick hacking only), the 53c406 card didn't work with sym53c416 driver. I haven't had time for more serious work back then. Hopefully I'll try harder soon. -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: status of NCR5380-based ISA drivers
On Sunday 11 September 2016 19:12:49 Christoph Hellwig wrote: > Hi all, > > you seem to the currently active NCR580 cabal. Which frontends to NCR5380 > do you test at the moment, or could you test? > > NCR5380-based ISA drivers make up a significant part of those drivers still > using scsi_module.c after it's 15 year deprecation period, and I'd like to > either move them to this century or to the dust bin. > > The drivers in question are: dtc, g_NCR5380, pas16 and t128. > > Thanks, > Christoph I have the HW to test g_NCR5380 - it currently works fine as it did never before. I started a patch to for scsi_module.c removal (and other good things) but haven't had time to finish it. Hopefully, it will be ready soon. -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 00/23] ncr5380: Eliminate macros, reduce code duplication, fix bugs etc
On Monday 21 March 2016 03:31:49 Finn Thain wrote: > > This patch series has more macro elimination and some tweaks to the > DMA hooks so that all the wrapper drivers can share the same core > DMA algorithm. This resolves the major discrepancies between the two > core drivers, which relate to code conditional on the REAL_DMA and > PSEUDO_DMA macros. > > After all the wrapper drivers agree on the DMA hook api, the core driver > fork gets resolved. NCR5380.c is adopted by atari_scsi and sun3_scsi and > atari_NCR5380.c is then deleted. > > Historically, the 5380 drivers suffered from over-use of conditional > compilation, which caused the compile-time configuration space to explode, > leading to core driver code that was practically untestable, unmaintainable > and difficult to reason about. It also prevented driver modules from > sharing object code. > > Along with REAL_DMA, REAL_DMA_POLL and PSEUDO_DMA, most of the remaining > macros are also eradicated, such as CONFIG_SCSI_GENERIC_NCR53C400, > SUPPORT_TAGS, DONT_USE_INTR, AUTOPROBE_IRQ and BIOSPARAM. > > Also in this patch series, some duplicated documentation is removed and > the PDMA implementation in mac_scsi finally gets fixed. > > This patch series was tested by exercising the dmx3191d and mac_scsi modules > on suitable hardware. Michael has tested atari_scsi on an Atari Falcon. > Help with driver testing on ISA cards is sought as I don't have such > hardware. Likewise RiscPC ecards and Sun 3. Tested on HP C2502 (53C400A chip), Canon FG2-5202 (53C400 chip) and DTC-3181L (DTCT-436P chip) ISA cards - everything works fine! Thanks. Tested-by: Ondrej Zary HP C2502: scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x280, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { }, options { } Canon FG2-5202: scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x0, n_io_port 0, base 0xd8000, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { }, options { } DTC-3181L: scsi host2: Generic NCR5380/NCR53C400 SCSI, io_port 0x240, n_io_port 16, base 0x0, irq 0, can_queue 16, cmd_per_lun 2, sg_tablesize 128, this_id 7, flags { }, options { } -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 00/77] More fixes, cleanup and modernization for NCR5380 drivers
On Tuesday 22 December 2015 02:17:38 Finn Thain wrote: > > Like my previous work on the NCR5380 drivers, this patch series has bug > fixes, code cleanup and modernization. These drivers suffer from mistakes, > poor style and neglect and this long series addresses the worst of it, > covering all ten wrapper drivers and both of the core driver forks. The > combined size of the drivers is reduced by over 700 LoC. > > This series continues to reduce divergence between the two core driver > forks, often by copying a bug fix from one to the other. Most patches are > larger for having to keep the two forks in sync. Making the same change to > both is churn if one of them is to be removed but neither can be as yet. > By the end of this series the diff between the two forks is minimal, so it > becomes clear what caused the fork and what can be done about it. > > This patch series did benefit from scripts/checkpatch.pl but not too much. > Decades ago, these drivers started out with 4-space tabs and if the 80 > column limit were to be strictly enforced now, it would require adding new > functions and shortening identifiers. I would defer this sort of activity > until after the fork has been resolved. > > All patches to all NCR5380 drivers (x86, ARM, m68k) have been compile- > tested. The mac_scsi, dmx3191d, g_NCR5380 and atari_scsi modules were > regression tested on suitable hardware. Tested on HP C2502 (53C400A chip), Canon FG2-5202 (53C400 chip) and DTC-3181L (DTCT-436P chip) ISA cards - everything works fine! Thanks. Tested-by: Ondrej Zary -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 74/71] ncr5380: Enable PDMA for NCR53C400A
On Tuesday 08 December 2015 03:05:11 Finn Thain wrote: > > On Sun, 6 Dec 2015, Ondrej Zary wrote: > > > Add I/O register mapping for NCR53C400A and enable PDMA mode to > > improve performance and fix non-working IRQ. > > > > Tested with HP C2502 (and user-space enabler). > > > > Signed-off-by: Ondrej Zary > > --- > > drivers/scsi/g_NCR5380.c | 14 +++--- > > 1 file changed, 11 insertions(+), 3 deletions(-) > > > > diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c > > index 86740fd..099fdac 100644 > > --- a/drivers/scsi/g_NCR5380.c > > +++ b/drivers/scsi/g_NCR5380.c > > @@ -324,7 +324,7 @@ static int __init generic_NCR5380_detect(struct > > scsi_host_template *tpnt) > > #endif > > break; > > case BOARD_NCR53C400A: > > - flags = FLAG_NO_PSEUDO_DMA; > > + flags = FLAG_NO_DMA_FIXUP; > > ports = ncr_53c400a_ports; > > break; > > case BOARD_DTC3181E: > > @@ -406,11 +406,18 @@ static int __init generic_NCR5380_detect(struct > > scsi_host_template *tpnt) > > * On NCR53C400 boards, NCR5380 registers are mapped 8 past > > * the base address. > > */ > > - if (overrides[current_override].board == BOARD_NCR53C400) { > > + switch (overrides[current_override].board) { > > + case BOARD_NCR53C400: > > instance->io_port += 8; > > hostdata->c400_ctl_status = 0; > > hostdata->c400_blk_cnt = 1; > > hostdata->c400_host_buf = 4; > > + break; > > + case BOARD_NCR53C400A: > > + hostdata->c400_ctl_status = 9; > > + hostdata->c400_blk_cnt = 10; > > + hostdata->c400_host_buf = 8; > > + break; > > } > > #else > > instance->base = overrides[current_override].NCR5380_map_name; > > > For SCSI_G_NCR5380_MEM and BOARD_NCR53C400A (or BOARD_DTC3181E), you have > not assigned c400_ctl_status, c400_blk_cnt and c400_host_buf. Perhaps we > should throw an error, something like this? > > hostdata->iomem = iomem; > - if (overrides[current_override].board == BOARD_NCR53C400) { > + switch (overrides[current_override].board) { > + case BOARD_NCR53C400: > hostdata->c400_ctl_status = 0x100; > hostdata->c400_blk_cnt = 0x101; > hostdata->c400_host_buf = 0x104; > + break; > + case BOARD_NCR53C400A: > + pr_err(DRV_MODULE_NAME ": unknown register offsets\n"); > + goto out_unregister; > } > #endif We don't need to fail, just disable PDMA by setting: flags = FLAG_NO_PSEUDO_DMA; And BTW. this: if (overrides[current_override].board == BOARD_NCR53C400 || overrides[current_override].board == BOARD_NCR53C400A) NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); should then be, solving the problem of growing if condition: if (!(flags & FLAG_NO_PSEUDO_DMA)) NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 78/71] ncr5380: Add support for HP 53C400A-based cards (C2502)
HP C2502 cards (based on 53C400A chips) use different magic numbers for software-based I/O address configuration than other cards. The configuration is also extended to allow setting the IRQ. Move the configuration to a new function magic_configure() and move magic the magic numbers into an array. Add new magic numbers for these HP cards and hp_c2502 module parameter to use them, e.g.: modprobe g_NCR5380 ncr_irq=7 ncr_addr=0x280 ncr_53c400a=1 hp_c2502=1 Tested with HP C2502 and DTCT-436P. Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c | 74 -- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 42fdeaf..dd32c68 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -80,12 +80,14 @@ static int ncr_5380; static int ncr_53c400; static int ncr_53c400a; static int dtc_3181e; +static int hp_c2502; static struct override { NCR5380_map_type NCR5380_map_name; int irq; int dma; int board; /* Use NCR53c400, Ricoh, etc. extensions ? */ + bool hp_c2502; } overrides #ifdef GENERIC_NCR5380_OVERRIDE [] __initdata = GENERIC_NCR5380_OVERRIDE; @@ -225,6 +227,32 @@ static int __init do_DTC3181E_setup(char *str) #endif +#ifndef SCSI_G_NCR5380_MEM +/* + * Configure I/O address of 53C400A or DTC436 by writing magic numbers + * to ports 0x779 and 0x379. Two magic number sequences are known: + * 1. for generic NCR 53C400A-based cards and DTC436 chips + * 2. for HP C2502 card (also based on 53C400A but different decode logic) + */ +static void magic_configure(int idx, u8 irq, u8 magic[]) +{ + u8 cfg = 0; + + outb(magic[0], 0x779); + outb(magic[1], 0x379); + outb(magic[2], 0x379); + outb(magic[3], 0x379); + outb(magic[4], 0x379); + + /* allowed IRQs for HP 53C400A */ + if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7) + irq = 0; + if (idx >= 0 && idx <= 7) + cfg = 0x80 | idx | (irq << 4); + outb(cfg, 0x379); +} +#endif + /** * generic_NCR5380_detect - look for NCR5380 controllers * @tpnt: the scsi template @@ -241,8 +269,9 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) static int current_override; int count; unsigned int *ports; + u8 *magic; #ifndef SCSI_G_NCR5380_MEM - int i; + int i, port_idx; unsigned long region_size = 16; #endif static unsigned int __initdata ncr_53c400a_ports[] = { @@ -251,6 +280,12 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) static unsigned int __initdata dtc_3181e_ports[] = { 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0 }; + static u8 ncr_53c400a_magic[] __initdata = {/* 53C400A & DTC436 */ + 0x59, 0xb9, 0xc5, 0xae, 0xa6 + }; + static u8 hp_c2502_magic[] __initdata = { /* HP C2502 */ + 0x0f, 0x22, 0xf0, 0x20, 0x80 + }; int flags; struct Scsi_Host *instance; struct NCR5380_hostdata *hostdata; @@ -273,6 +308,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) overrides[0].board = BOARD_NCR53C400A; else if (dtc_3181e) overrides[0].board = BOARD_DTC3181E; + if (hp_c2502) + overrides[0].hp_c2502 = true; #ifndef SCSI_G_NCR5380_MEM if (!current_override && isapnp_present()) { struct pnp_dev *dev = NULL; @@ -326,24 +363,25 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) case BOARD_NCR53C400A: flags = FLAG_NO_DMA_FIXUP; ports = ncr_53c400a_ports; + magic = ncr_53c400a_magic; break; case BOARD_DTC3181E: flags = FLAG_NO_DMA_FIXUP; ports = dtc_3181e_ports; + magic = ncr_53c400a_magic; break; } + if (overrides[current_override].hp_c2502) + magic = hp_c2502_magic; + else + magic = ncr_53c400a_magic; #ifndef SCSI_G_NCR5380_MEM if (ports) { /* wakeup sequence for the NCR53C400A and DTC3181E */ /* Disable the adapter and look for a free io port */ - outb(0x59, 0x779); - outb(0xb9, 0x379); - outb(0xc5, 0x379); - outb(0xae, 0x379); - outb(0xa6, 0x379); - outb(0x00, 0x379); + magic_configure(-1, 0, magic);
Re: [patch RESEND] atp870u: 64 bit bug in atp885_init()
On Wednesday 09 December 2015 12:53:39 One Thousand Gnomes wrote: > On Wed, 9 Dec 2015 13:24:53 +0300 > Dan Carpenter wrote: > > > On 64 bit CPUs there is a memory corruption bug on probe(). It should > > be a u32 pointer instead of an unsigned long pointer or we write past > > the end of the setupdata[] array. > > > > Signed-off-by: Dan Carpenter > > Reviewed-by: Hannes Reinecke > > --- > > Resending because we have shuffled the code around so the patch needed > > to be refreshed against linux-next. Although I do wonder why we are > > still working on this code since it has never worked on 64 bit systems > > so probably all the users gave up a decade ago. > > So this is untested ? If so please make it very clear in the commit > message because the kernel is IMHO getting too full of polished, neat, > recently modified, never tested, never used code. > > I agree it would be better if the driver was simply deleted. I've not > even seen an ATP870 bug report in years. Maybe because it worked. Although the code was horrible. I've done some big changes to this driver recently (tested, of course). I can't test this patch as I don't have ATP885 card, only ATP870. -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 78/71] ncr5380: Add support for HP 53C400A-based cards (C2502)
On Tuesday 08 December 2015 12:40:18 Finn Thain wrote: > > On Tue, 8 Dec 2015, Ondrej Zary wrote: > > > HP C2502 cards (based on 53C400A chips) use different magic numbers for > > software-based I/O address configuration than other cards. The > > configuration is also extended to allow setting the IRQ. > > > > Move the configuration to a new function magic_configure() and move > > magic the magic numbers into an array. Add new magic numbers for these > > HP cards and hp_53c400a module parameter to use them. > > > > Tested with HP C2502 and DTCT-436P. > > > > Signed-off-by: Ondrej Zary > > --- > > drivers/scsi/g_NCR5380.c | 76 > > -- > > drivers/scsi/g_NCR5380.h |1 + > > 2 files changed, 61 insertions(+), 16 deletions(-) > > > > diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c > > index 42fdeaf..121d143 100644 > > --- a/drivers/scsi/g_NCR5380.c > > +++ b/drivers/scsi/g_NCR5380.c > > @@ -80,6 +80,7 @@ static int ncr_5380; > > static int ncr_53c400; > > static int ncr_53c400a; > > static int dtc_3181e; > > +static int hp_53c400a; > > From the photos that I've seen, the HP cards have either NCR or SYMBIOS > 53C400A devices. > > You've added a new setup option and a new board type, but the name you've > chosen is neither the board type nor the device type. It is a combination. Because it's a HP board with NCR/SYMBIOS 53C400A chip. Windows driver calls it "Symbios Logic 53C400A (HP Version)", suggesting that there might be more compatible cards. But search did not found any on the web, only C2502. So I'll rename it to hp_c2502. > > > > static struct override { > > NCR5380_map_type NCR5380_map_name; > > @@ -225,6 +226,32 @@ static int __init do_DTC3181E_setup(char *str) > > > > #endif > > > > +#ifndef SCSI_G_NCR5380_MEM > > +/* > > + * Configure I/O address of 53C400A or DTC 3181 by writing magic numbers > > + * to ports 0x779 and 0x379. Two magic number sequences are known: > > + * 1. for generic NCR 53C400A-based cards and DTC436 chips > > + * 2. for HP C2502 card (also based on 53C400A but different decode logic) > > Forgive my ignorance of ISA card design, but that suggests that these > magic numbers are only relevant to HP C2502 boards and not SYM 53C400A > devices in general (?) ... Looks like the original magic numbers (they came from the outb() calls, now in ncr_53c400a_magic[]) are hardcoded in the 53C400A chip (and also DTC chips). HP C2502 card has some PALCE chips between the ISA bus and 53C400A. They probably react to the HP-specific magic numbers (and don't pass the "original" magic numbers to the 53C400A chip). > > + */ > > +static void magic_configure(int idx, u8 irq, u8 magic[]) > > +{ > > + u8 cfg = 0; > > + > > + outb(magic[0], 0x779); > > + outb(magic[1], 0x379); > > + outb(magic[2], 0x379); > > + outb(magic[3], 0x379); > > + outb(magic[4], 0x379); > > + > > + /* allowed IRQs for HP 53C400A */ > > + if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7) > > + irq = 0; > > + if (idx >= 0 && idx <= 7) > > + cfg = 0x80 | idx | (irq << 4); > > + outb(cfg, 0x379); > > +} > > +#endif > > + > > /** > > * generic_NCR5380_detect - look for NCR5380 controllers > > * @tpnt: the scsi template > > @@ -241,8 +268,9 @@ static int __init generic_NCR5380_detect(struct > > scsi_host_template *tpnt) > > static int current_override; > > int count; > > unsigned int *ports; > > + u8 *magic; > > #ifndef SCSI_G_NCR5380_MEM > > - int i; > > + int i, port_idx; > > unsigned long region_size = 16; > > #endif > > static unsigned int __initdata ncr_53c400a_ports[] = { > > @@ -251,6 +279,12 @@ static int __init generic_NCR5380_detect(struct > > scsi_host_template *tpnt) > > static unsigned int __initdata dtc_3181e_ports[] = { > > 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0 > > }; > > + static u8 ncr_53c400a_magic[] __initdata = {/* 53C400A & DTC 3181 */ > > + 0x59, 0xb9, 0xc5, 0xae, 0xa6 > > + }; > > + static u8 hp_53c400a_magic[] __initdata = { /* HP C2502 */ > > + 0x0f, 0x22, 0xf0, 0x20, 0x80 > > + }; > > ... so maybe that should be called 'hp_c2502_magic'? Yes. > > int fl
[PATCH v2 78/71] ncr5380: Add support for HP 53C400A-based cards (C2502)
HP C2502 cards (based on 53C400A chips) use different magic numbers for software-based I/O address configuration than other cards. The configuration is also extended to allow setting the IRQ. Move the configuration to a new function magic_configure() and move magic the magic numbers into an array. Add new magic numbers for these HP cards and hp_53c400a module parameter to use them. Tested with HP C2502 and DTCT-436P. Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c | 76 -- drivers/scsi/g_NCR5380.h |1 + 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 42fdeaf..121d143 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -80,6 +80,7 @@ static int ncr_5380; static int ncr_53c400; static int ncr_53c400a; static int dtc_3181e; +static int hp_53c400a; static struct override { NCR5380_map_type NCR5380_map_name; @@ -225,6 +226,32 @@ static int __init do_DTC3181E_setup(char *str) #endif +#ifndef SCSI_G_NCR5380_MEM +/* + * Configure I/O address of 53C400A or DTC 3181 by writing magic numbers + * to ports 0x779 and 0x379. Two magic number sequences are known: + * 1. for generic NCR 53C400A-based cards and DTC436 chips + * 2. for HP C2502 card (also based on 53C400A but different decode logic) + */ +static void magic_configure(int idx, u8 irq, u8 magic[]) +{ + u8 cfg = 0; + + outb(magic[0], 0x779); + outb(magic[1], 0x379); + outb(magic[2], 0x379); + outb(magic[3], 0x379); + outb(magic[4], 0x379); + + /* allowed IRQs for HP 53C400A */ + if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7) + irq = 0; + if (idx >= 0 && idx <= 7) + cfg = 0x80 | idx | (irq << 4); + outb(cfg, 0x379); +} +#endif + /** * generic_NCR5380_detect - look for NCR5380 controllers * @tpnt: the scsi template @@ -241,8 +268,9 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) static int current_override; int count; unsigned int *ports; + u8 *magic; #ifndef SCSI_G_NCR5380_MEM - int i; + int i, port_idx; unsigned long region_size = 16; #endif static unsigned int __initdata ncr_53c400a_ports[] = { @@ -251,6 +279,12 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) static unsigned int __initdata dtc_3181e_ports[] = { 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0 }; + static u8 ncr_53c400a_magic[] __initdata = {/* 53C400A & DTC 3181 */ + 0x59, 0xb9, 0xc5, 0xae, 0xa6 + }; + static u8 hp_53c400a_magic[] __initdata = { /* HP C2502 */ + 0x0f, 0x22, 0xf0, 0x20, 0x80 + }; int flags; struct Scsi_Host *instance; struct NCR5380_hostdata *hostdata; @@ -273,6 +307,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) overrides[0].board = BOARD_NCR53C400A; else if (dtc_3181e) overrides[0].board = BOARD_DTC3181E; + else if (hp_53c400a) + overrides[0].board = BOARD_HP53C400A; #ifndef SCSI_G_NCR5380_MEM if (!current_override && isapnp_present()) { struct pnp_dev *dev = NULL; @@ -326,10 +362,17 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) case BOARD_NCR53C400A: flags = FLAG_NO_DMA_FIXUP; ports = ncr_53c400a_ports; + magic = ncr_53c400a_magic; + break; + case BOARD_HP53C400A: + flags = FLAG_NO_DMA_FIXUP; + ports = ncr_53c400a_ports; + magic = hp_53c400a_magic; break; case BOARD_DTC3181E: flags = FLAG_NO_DMA_FIXUP; ports = dtc_3181e_ports; + magic = ncr_53c400a_magic; break; } @@ -338,12 +381,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) /* wakeup sequence for the NCR53C400A and DTC3181E */ /* Disable the adapter and look for a free io port */ - outb(0x59, 0x779); - outb(0xb9, 0x379); - outb(0xc5, 0x379); - outb(0xae, 0x379); - outb(0xa6, 0x379); - outb(0x00, 0x379); + magic_configure(-1, 0, magic); if (overrides[current_override].NCR5380_map_name != PORT_AUTO) for (i = 0; ports[i]; i++) { @@ -362,17 +400,14 @@ sta
Re: [PATCH v2 77/71] ncr5380: Fix wait for 53C80 registers registers after PDMA
On Monday 07 December 2015 04:16:14 Finn Thain wrote: > > On Mon, 7 Dec 2015, Ondrej Zary wrote: > > > The check for 53C80 registers accessibility was commented out because > > it was broken (inverted). Fix and enable it. > > > > Signed-off-by: Ondrej Zary > > --- > > drivers/scsi/g_NCR5380.c | 37 ++--- > > 1 file changed, 6 insertions(+), 31 deletions(-) > > > > diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c > > index 038dddf..a7479c6 100644 > > --- a/drivers/scsi/g_NCR5380.c > > +++ b/drivers/scsi/g_NCR5380.c > > @@ -603,14 +603,10 @@ static inline int NCR5380_pread(struct Scsi_Host > > *instance, unsigned char *dst, > > if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) > > printk("53C400r: no 53C80 gated irq after transfer"); > > > > -#if 0 > > - /* > > -* DON'T DO THIS - THEY NEVER ARRIVE! > > -*/ > > - printk("53C400r: Waiting for 53C80 registers\n"); > > - while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG) > > + /* wait for 53C80 registers to be available */ > > + while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)) > > ; > > In the previous patch, udelay(4) was added to a CSR_GATED_53C80_IRQ > polling loop. It is interesting that you don't need it here when polling > CSR_53C80_REG. Yes, it's weird. Reads work fine without the delay. Small writes work most of the time without the delay but crash sometimes. Large writes crash the chip consistently without the delay. > > -#endif > > + > > if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) > > printk(KERN_ERR "53C400r: no end dma signal\n"); > > > > @@ -632,7 +628,6 @@ static inline int NCR5380_pwrite(struct Scsi_Host > > *instance, unsigned char *src, > > struct NCR5380_hostdata *hostdata = shost_priv(instance); > > int blocks = len / 128; > > int start = 0; > > - int i; > > > > NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); > > NCR5380_write(hostdata->c400_blk_cnt, blocks); > > @@ -681,36 +676,16 @@ static inline int NCR5380_pwrite(struct Scsi_Host > > *instance, unsigned char *src, > > blocks--; > > } > > > > -#if 0 > > - printk("53C400w: waiting for registers to be available\n"); > > - THEY NEVER DO ! while (NCR5380_read(hostdata->c400_ctl_status) & > > CSR_53C80_REG); > > - printk("53C400w: Got em\n"); > > -#endif > > - > > - /* Let's wait for this instead - could be ugly */ > > - /* All documentation says to check for this. Maybe my hardware is too > > -* fast. Waiting for it seems to work fine! KLL > > -*/ > > - while (!(i = NCR5380_read(hostdata->c400_ctl_status) & > > CSR_GATED_53C80_IRQ)) { > > + /* wait for 53C80 registers to be available */ > > + while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)) { > > udelay(4); /* DTC436 chip hangs without this */ > > ... based on the above, this udelay is probably not needed. > > (Or perhaps it is only needed once, in between the final host_buf register > access and the first ctl_status access??) I guess that the delay is needed when the chip does write in the background. But why only on the last block? Adding delays inside the while(1) loop does not help, it crashes anyway. Single delay before the first ctl_status does not help either (perhaps only if it's long enough for the write to complete). The chip also crashes in transfer_pio during bigger transfers in a similar way. With Quantum HDD, it did not crash once I got PDMA working. But with a faster IBM HDD, it crashes even with smaller PIO trasnfers. > Is there any reference in the docs to timing sensitivity? Haven't found anything in NCR docs. Unfortunately, we don't have any DTC docs. > > /* FIXME - no timeout */ > > } > > > > - /* > > -* I know. i is certainly != 0 here but the loop is new. See previous > > -* comment. > > -*/ > > Thanks for cleaning up this mess! > -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 76/71] ncr5380: Enable PDMA for DTC chips
Add I/O register mapping for DTC chips and enable PDMA mode. These chips have 16-bit wide HOST BUFFER register and it must be read by 16-bit accesses (we lose data otherwise). Large PIO transfers crash at least the DTCT-436P chip (all reads result in 0xFF) so this patch actually makes it work. The chip also crashes when we bang the C400 host status register too heavily after PDMA write - a small udelay is needed. Tested on DTCT-436P and verified that it does not break 53C400A. Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c | 39 +++ drivers/scsi/g_NCR5380.h |3 ++- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 578d4fa..ef719cf0 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -328,7 +328,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) ports = ncr_53c400a_ports; break; case BOARD_DTC3181E: - flags = FLAG_NO_PSEUDO_DMA; + flags = FLAG_NO_DMA_FIXUP; ports = dtc_3181e_ports; break; } @@ -401,6 +401,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) #ifndef SCSI_G_NCR5380_MEM instance->io_port = overrides[current_override].NCR5380_map_name; instance->n_io_port = region_size; + hostdata->io_width = 1; /* 8-bit PDMA by default */ /* * On NCR53C400 boards, NCR5380 registers are mapped 8 past @@ -413,6 +414,9 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) hostdata->c400_blk_cnt = 1; hostdata->c400_host_buf = 4; break; + case BOARD_DTC3181E: + hostdata->io_width = 2; /* 16-bit PDMA */ + /* fall through */ case BOARD_NCR53C400A: hostdata->c400_ctl_status = 9; hostdata->c400_blk_cnt = 10; @@ -433,7 +437,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) goto out_unregister; if (overrides[current_override].board == BOARD_NCR53C400 || - overrides[current_override].board == BOARD_NCR53C400A) + overrides[current_override].board == BOARD_NCR53C400A || + overrides[current_override].board == BOARD_DTC3181E) NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); NCR5380_maybe_reset_bus(instance); @@ -559,7 +564,11 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, ; /* FIXME - no timeout */ #ifndef SCSI_G_NCR5380_MEM - insb(instance->io_port + hostdata->c400_host_buf, + if (hostdata->io_width == 2) + insw(instance->io_port + hostdata->c400_host_buf, + dst + start, 64); + else + insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128); #else /* implies SCSI_G_NCR5380_MEM */ @@ -575,7 +584,11 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, ; /* FIXME - no timeout */ #ifndef SCSI_G_NCR5380_MEM - insb(instance->io_port + hostdata->c400_host_buf, + if (hostdata->io_width == 2) + insw(instance->io_port + hostdata->c400_host_buf, + dst + start, 64); + else + insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128); #else /* implies SCSI_G_NCR5380_MEM */ @@ -633,7 +646,11 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) ; // FIXME - timeout #ifndef SCSI_G_NCR5380_MEM - outsb(instance->io_port + hostdata->c400_host_buf, + if (hostdata->io_width == 2) + outsw(instance->io_port + hostdata->c400_host_buf, + src + start, 64); + else + outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128); #else /* implies SCSI_G_NCR5380_MEM */ @@ -648,7 +665,11 @@ static inline int N
[PATCH v2 77/71] ncr5380: Fix wait for 53C80 registers registers after PDMA
The check for 53C80 registers accessibility was commented out because it was broken (inverted). Fix and enable it. Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c | 37 ++--- 1 file changed, 6 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 038dddf..a7479c6 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -603,14 +603,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) printk("53C400r: no 53C80 gated irq after transfer"); -#if 0 - /* -* DON'T DO THIS - THEY NEVER ARRIVE! -*/ - printk("53C400r: Waiting for 53C80 registers\n"); - while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG) + /* wait for 53C80 registers to be available */ + while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)) ; -#endif + if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) printk(KERN_ERR "53C400r: no end dma signal\n"); @@ -632,7 +628,6 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, struct NCR5380_hostdata *hostdata = shost_priv(instance); int blocks = len / 128; int start = 0; - int i; NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); NCR5380_write(hostdata->c400_blk_cnt, blocks); @@ -681,36 +676,16 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, blocks--; } -#if 0 - printk("53C400w: waiting for registers to be available\n"); - THEY NEVER DO ! while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG); - printk("53C400w: Got em\n"); -#endif - - /* Let's wait for this instead - could be ugly */ - /* All documentation says to check for this. Maybe my hardware is too -* fast. Waiting for it seems to work fine! KLL -*/ - while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) { + /* wait for 53C80 registers to be available */ + while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)) { udelay(4); /* DTC436 chip hangs without this */ /* FIXME - no timeout */ } - /* -* I know. i is certainly != 0 here but the loop is new. See previous -* comment. -*/ - if (i) { - if (!((i = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_END_DMA_TRANSFER)) - printk(KERN_ERR "53C400w: No END OF DMA bit - WHOOPS! BASR=%0x\n", i); - } else - printk(KERN_ERR "53C400w: no 53C80 gated irq after transfer (last block)\n"); - -#if 0 if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) { printk(KERN_ERR "53C400w: no end dma signal\n"); } -#endif + while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT)) ; // TIMEOUT return 0; -- Ondrej Zary -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 76/71] ncr5380: Enable PDMA for DTC chips
Add I/O register mapping for DTC chips and enable PDMA mode. These chips have 16-bit wide HOST BUFFER register and it must be read by 16-bit accesses (we lose data otherwise). Large PIO transfers crash at least the DTCT-436P chip (all reads result in 0xFF) so this patch actually makes it work. The chip also crashes when we bang the C400 host status register too heavily after PDMA write - a small udelay is needed. Tested on DTCT-436P and verified that it does not break 53C400A. Signed-off-by: Ondrej Zary --- drivers/scsi/g_NCR5380.c | 40 drivers/scsi/g_NCR5380.h |4 +++- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 578d4fa..038dddf 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -328,7 +328,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) ports = ncr_53c400a_ports; break; case BOARD_DTC3181E: - flags = FLAG_NO_PSEUDO_DMA; + flags = FLAG_NO_DMA_FIXUP; ports = dtc_3181e_ports; break; } @@ -401,6 +401,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) #ifndef SCSI_G_NCR5380_MEM instance->io_port = overrides[current_override].NCR5380_map_name; instance->n_io_port = region_size; + hostdata->io_width = 1; /* 8-bit PDMA by default */ /* * On NCR53C400 boards, NCR5380 registers are mapped 8 past @@ -413,10 +414,14 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) hostdata->c400_blk_cnt = 1; hostdata->c400_host_buf = 4; break; + case BOARD_DTC3181E: + hostdata->io_width = 2; /* 16-bit PDMA */ + /* fall through */ case BOARD_NCR53C400A: hostdata->c400_ctl_status = 9; hostdata->c400_blk_cnt = 10; hostdata->c400_host_buf = 8; + hostdata->c400_host_idx = 13; break; } #else @@ -433,7 +438,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) goto out_unregister; if (overrides[current_override].board == BOARD_NCR53C400 || - overrides[current_override].board == BOARD_NCR53C400A) + overrides[current_override].board == BOARD_NCR53C400A || + overrides[current_override].board == BOARD_DTC3181E) NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); NCR5380_maybe_reset_bus(instance); @@ -559,7 +565,11 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, ; /* FIXME - no timeout */ #ifndef SCSI_G_NCR5380_MEM - insb(instance->io_port + hostdata->c400_host_buf, + if (hostdata->io_width == 2) + insw(instance->io_port + hostdata->c400_host_buf, + dst + start, 64); + else + insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128); #else /* implies SCSI_G_NCR5380_MEM */ @@ -575,7 +585,11 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, ; /* FIXME - no timeout */ #ifndef SCSI_G_NCR5380_MEM - insb(instance->io_port + hostdata->c400_host_buf, + if (hostdata->io_width == 2) + insw(instance->io_port + hostdata->c400_host_buf, + dst + start, 64); + else + insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128); #else /* implies SCSI_G_NCR5380_MEM */ @@ -633,7 +647,11 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) ; // FIXME - timeout #ifndef SCSI_G_NCR5380_MEM - outsb(instance->io_port + hostdata->c400_host_buf, + if (hostdata->io_width == 2) + outsw(instance->io_port + hostdata->c400_host_buf, + src + start, 64); + else + outsb(instance->io_port + hostda
Re: [PATCH 76/71] ncr5380: Enable PDMA for DTC chips
On Sunday 06 December 2015 04:40:56 Finn Thain wrote: > > On Fri, 4 Dec 2015, Ondrej Zary wrote: > > > Add I/O register mapping for DTC chips and enable PDMA mode. > > > > These chips have 16-bit wide HOST BUFFER register (counter register at > > offset 0x0d increments by 2 on each HOST BUFFER read). Detect it > > automatically. > > > > Large PIO transfers crash at least the DTCT-436P chip (all reads result > > in 0xFF) so this patch actually makes it work. > > > > The chip also crashes when we bang the C400 host status register too > > heavily after PDMA write - a small udelay is needed. > > > > Tested on DTCT-436P and verified that it does not break 53C400A. > > > > Signed-off-by: Ondrej Zary > > --- > > drivers/scsi/g_NCR5380.c | 59 > > -- > > drivers/scsi/g_NCR5380.h |4 +++- > > 2 files changed, 39 insertions(+), 24 deletions(-) > > > > diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c > > index 85da3c2..9816b81 100644 > > --- a/drivers/scsi/g_NCR5380.c > > +++ b/drivers/scsi/g_NCR5380.c > > @@ -328,7 +328,7 @@ static int __init generic_NCR5380_detect(struct > > scsi_host_template *tpnt) > > ports = ncr_53c400a_ports; > > break; > > case BOARD_DTC3181E: > > - flags = FLAG_NO_PSEUDO_DMA; > > + flags = FLAG_NO_DMA_FIXUP; > > Nice! > > > ports = dtc_3181e_ports; > > break; > > } > > @@ -412,10 +412,12 @@ static int __init generic_NCR5380_detect(struct > > scsi_host_template *tpnt) > > hostdata->c400_blk_cnt = 1; > > hostdata->c400_host_buf = 4; > > } > > - if (overrides[current_override].board == BOARD_NCR53C400A) { > > + if (overrides[current_override].board == BOARD_NCR53C400A || > > + overrides[current_override].board == BOARD_DTC3181E) { > > hostdata->c400_ctl_status = 9; > > hostdata->c400_blk_cnt = 10; > > hostdata->c400_host_buf = 8; > > + hostdata->c400_host_idx = 13; > > } > > #else > > instance->base = overrides[current_override].NCR5380_map_name; > > @@ -430,8 +432,20 @@ static int __init generic_NCR5380_detect(struct > > scsi_host_template *tpnt) > > if (NCR5380_init(instance, flags)) > > goto out_unregister; > > > > +#ifndef SCSI_G_NCR5380_MEM > > + /* read initial value of index register */ > > + i = NCR5380_read(hostdata->c400_host_idx); > > + /* read something from host buffer */ > > + NCR5380_read(hostdata->c400_host_buf); > > + /* I/O width = index register increment */ > > + hostdata->io_width = NCR5380_read(hostdata->c400_host_idx) - i; > > + if (hostdata->io_width < 0) > > + hostdata->io_width += 128; > > +#endif > > Will the result depend on the initial state of the chip, such as > CSR_TRANS_DIR or CSR_HOST_BUF_NOT_RDY? > > It is possible to generate an interrupt with the buffer read, which should > be masked at the chip. > > This buffer read may cause the 53C400 control logic to signal the 53C80 > core. I suppose it is unlikely to cause any signalling on the SCSI bus > unless the 53C80 happened to be in DMA mode. > > The possibility that io_width == 0 is not handled; wouldn't this result > indicate that PDMA shouldn't be used? > > io_width can be calculated without a conditional statement, which may be > easier to read. > > Can we be confident that detection will fail for all devices that don't > support word-sized IO, to avoid a regression? > > The patch seems to assume that no memory-mapped card needs word-sized IO > for PDMA. Can you confirm? My memory-mapped Canon card is a 8-bit ISA card so it can't do 16-bit I/O by definition. Don't know if there are any 16-bit memory-mapped cards. > The previous version of this patch was simpler and more predictable. You > enabled word-size IO for DTC3181E which is testable. Does this version > benefit any other cards? Probably not. Looks like this code creates more problems that it solves. I'll revert to the original approach. > > + > > if (overrides[current_override].board == BOARD_NCR53C400 || > > - overri