Commit 72f02ba6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull SCSI updates from James Bottomley:
 "This is mostly updates to the usual drivers: mpt3sas, lpfc, qla2xxx,
  hisi_sas, smartpqi, megaraid_sas, arcmsr.

  In addition, with the continuing absence of Nic we have target updates
  for tcmu and target core (all with reviews and acks).

  The biggest observable change is going to be that we're (again) trying
  to switch to mulitqueue as the default (a user can still override the
  setting on the kernel command line).

  Other major core stuff is the removal of the remaining Microchannel
  drivers, an update of the internal timers and some reworks of
  completion and result handling"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (203 commits)
  scsi: core: use blk_mq_run_hw_queues in scsi_kick_queue
  scsi: ufs: remove unnecessary query(DM) UPIU trace
  scsi: qla2xxx: Fix issue reported by static checker for qla2x00_els_dcmd2_sp_done()
  scsi: aacraid: Spelling fix in comment
  scsi: mpt3sas: Fix calltrace observed while running IO & reset
  scsi: aic94xx: fix an error code in aic94xx_init()
  scsi: st: remove redundant pointer STbuffer
  scsi: qla2xxx: Update driver version to 10.00.00.08-k
  scsi: qla2xxx: Migrate NVME N2N handling into state machine
  scsi: qla2xxx: Save frame payload size from ICB
  scsi: qla2xxx: Fix stalled relogin
  scsi: qla2xxx: Fix race between switch cmd completion and timeout
  scsi: qla2xxx: Fix Management Server NPort handle reservation logic
  scsi: qla2xxx: Flush mailbox commands on chip reset
  scsi: qla2xxx: Fix unintended Logout
  scsi: qla2xxx: Fix session state stuck in Get Port DB
  scsi: qla2xxx: Fix redundant fc_rport registration
  scsi: qla2xxx: Silent erroneous message
  scsi: qla2xxx: Prevent sysfs access when chip is down
  scsi: qla2xxx: Add longer window for chip reset
  ...
parents db06f826 51372570
* Hisilicon Universal Flash Storage (UFS) Host Controller
UFS nodes are defined to describe on-chip UFS hardware macro.
Each UFS Host Controller should have its own node.
Required properties:
- compatible : compatible list, contains one of the following -
"hisilicon,hi3660-ufs", "jedec,ufs-1.1" for hisi ufs
host controller present on Hi36xx chipset.
- reg : should contain UFS register address space & UFS SYS CTRL register address,
- interrupt-parent : interrupt device
- interrupts : interrupt number
- clocks : List of phandle and clock specifier pairs
- clock-names : List of clock input name strings sorted in the same
order as the clocks property. "ref_clk", "phy_clk" is optional
- freq-table-hz : Array of <min max> operating frequencies stored in the same
order as the clocks property. If this property is not
defined or a value in the array is "0" then it is assumed
that the frequency is set by the parent clock or a
fixed rate clock source.
- resets : describe reset node register
- reset-names : reset node register, the "rst" corresponds to reset the whole UFS IP.
Example:
ufs: ufs@ff3b0000 {
compatible = "hisilicon,hi3660-ufs", "jedec,ufs-1.1";
/* 0: HCI standard */
/* 1: UFS SYS CTRL */
reg = <0x0 0xff3b0000 0x0 0x1000>,
<0x0 0xff3b1000 0x0 0x1000>;
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&crg_ctrl HI3660_CLK_GATE_UFSIO_REF>,
<&crg_ctrl HI3660_CLK_GATE_UFSPHY_CFG>;
clock-names = "ref_clk", "phy_clk";
freq-table-hz = <0 0>, <0 0>;
/* offset: 0x84; bit: 12 */
resets = <&crg_rst 0x84 12>;
reset-names = "rst";
};
......@@ -41,6 +41,8 @@ Optional properties:
-lanes-per-direction : number of lanes available per direction - either 1 or 2.
Note that it is assume same number of lanes is used both
directions at once. If not specified, default is 2 lanes per direction.
- resets : reset node register
- reset-names : describe reset node register, the "rst" corresponds to reset the whole UFS IP.
Note: If above properties are not defined it can be assumed that the supply
regulators or clocks are always on.
......@@ -61,9 +63,11 @@ Example:
vccq-max-microamp = 200000;
vccq2-max-microamp = 200000;
clocks = <&core 0>, <&ref 0>, <&iface 0>;
clock-names = "core_clk", "ref_clk", "iface_clk";
freq-table-hz = <100000000 200000000>, <0 0>, <0 0>;
clocks = <&core 0>, <&ref 0>, <&phy 0>, <&iface 0>;
clock-names = "core_clk", "ref_clk", "phy_clk", "iface_clk";
freq-table-hz = <100000000 200000000>, <0 0>, <0 0>, <0 0>;
resets = <&reset 0 1>;
reset-names = "rst";
phys = <&ufsphy1>;
phy-names = "ufsphy";
};
......@@ -9847,12 +9847,6 @@ F: drivers/scsi/mac_scsi.*
F: drivers/scsi/sun3_scsi.*
F: drivers/scsi/sun3_scsi_vme.c
NCR DUAL 700 SCSI DRIVER (MICROCHANNEL)
M: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
L: linux-scsi@vger.kernel.org
S: Maintained
F: drivers/scsi/NCR_D700.*
NCSI LIBRARY:
M: Samuel Mendoza-Jonas <sam@mendozajonas.com>
S: Maintained
......
......@@ -1000,6 +1000,24 @@
reset-gpios = <&gpio11 1 0 >;
};
/* UFS */
ufs: ufs@ff3b0000 {
compatible = "hisilicon,hi3660-ufs", "jedec,ufs-1.1";
/* 0: HCI standard */
/* 1: UFS SYS CTRL */
reg = <0x0 0xff3b0000 0x0 0x1000>,
<0x0 0xff3b1000 0x0 0x1000>;
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&crg_ctrl HI3660_CLK_GATE_UFSIO_REF>,
<&crg_ctrl HI3660_CLK_GATE_UFSPHY_CFG>;
clock-names = "ref_clk", "phy_clk";
freq-table-hz = <0 0>, <0 0>;
/* offset: 0x84; bit: 12 */
resets = <&crg_rst 0x84 12>;
reset-names = "rst";
};
/* SD */
dwmmc1: dwmmc1@ff37f000 {
#address-cells = <1>;
......
......@@ -193,6 +193,7 @@ CONFIG_SCSI_HISI_SAS=y
CONFIG_SCSI_HISI_SAS_PCI=y
CONFIG_SCSI_UFSHCD=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_HISI=y
CONFIG_SCSI_UFS_QCOM=m
CONFIG_ATA=y
CONFIG_SATA_AHCI=y
......
......@@ -6424,6 +6424,7 @@ void ata_host_init(struct ata_host *host, struct device *dev,
host->n_tags = ATA_MAX_QUEUE;
host->dev = dev;
host->ops = ops;
kref_init(&host->kref);
}
void __ata_port_probe(struct ata_port *ap)
......@@ -7391,3 +7392,5 @@ EXPORT_SYMBOL_GPL(ata_cable_80wire);
EXPORT_SYMBOL_GPL(ata_cable_unknown);
EXPORT_SYMBOL_GPL(ata_cable_ignore);
EXPORT_SYMBOL_GPL(ata_cable_sata);
EXPORT_SYMBOL_GPL(ata_host_get);
EXPORT_SYMBOL_GPL(ata_host_put);
\ No newline at end of file
......@@ -100,8 +100,6 @@ extern int ata_port_probe(struct ata_port *ap);
extern void __ata_port_probe(struct ata_port *ap);
extern unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
u8 page, void *buf, unsigned int sectors);
extern void ata_host_get(struct ata_host *host);
extern void ata_host_put(struct ata_host *host);
#define to_ata_port(d) container_of(d, struct ata_port, tdev)
......
......@@ -2029,8 +2029,7 @@ static void srpt_release_channel_work(struct work_struct *w)
target_sess_cmd_list_set_waiting(se_sess);
target_wait_for_sess_cmds(se_sess);
transport_deregister_session_configfs(se_sess);
transport_deregister_session(se_sess);
target_remove_session(se_sess);
ch->sess = NULL;
if (ch->using_rdma_cm)
......@@ -2221,16 +2220,16 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev,
pr_debug("registering session %s\n", ch->sess_name);
if (sport->port_guid_tpg.se_tpg_wwn)
ch->sess = target_alloc_session(&sport->port_guid_tpg, 0, 0,
ch->sess = target_setup_session(&sport->port_guid_tpg, 0, 0,
TARGET_PROT_NORMAL,
ch->sess_name, ch, NULL);
if (sport->port_gid_tpg.se_tpg_wwn && IS_ERR_OR_NULL(ch->sess))
ch->sess = target_alloc_session(&sport->port_gid_tpg, 0, 0,
ch->sess = target_setup_session(&sport->port_gid_tpg, 0, 0,
TARGET_PROT_NORMAL, i_port_id, ch,
NULL);
/* Retry without leading "0x" */
if (sport->port_gid_tpg.se_tpg_wwn && IS_ERR_OR_NULL(ch->sess))
ch->sess = target_alloc_session(&sport->port_gid_tpg, 0, 0,
ch->sess = target_setup_session(&sport->port_gid_tpg, 0, 0,
TARGET_PROT_NORMAL,
i_port_id + 2, ch, NULL);
if (IS_ERR_OR_NULL(ch->sess)) {
......@@ -3597,11 +3596,9 @@ static struct configfs_attribute *srpt_tpg_attrs[] = {
/**
* srpt_make_tpg - configfs callback invoked for mkdir /sys/kernel/config/target/$driver/$port/$tpg
* @wwn: Corresponds to $driver/$port.
* @group: Not used.
* @name: $tpg.
*/
static struct se_portal_group *srpt_make_tpg(struct se_wwn *wwn,
struct config_group *group,
const char *name)
{
struct srpt_port *sport = wwn->priv;
......
......@@ -642,6 +642,7 @@ mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply)
freereq = 0;
if (event != MPI_EVENT_EVENT_CHANGE)
break;
/* else: fall through */
case MPI_FUNCTION_CONFIG:
case MPI_FUNCTION_SAS_IO_UNIT_CONTROL:
ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
......@@ -1779,7 +1780,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
struct proc_dir_entry *dent;
#endif
ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_KERNEL);
if (ioc == NULL) {
printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
return -ENOMEM;
......@@ -1886,6 +1887,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
case MPI_MANUFACTPAGE_DEVICEID_FC939X:
case MPI_MANUFACTPAGE_DEVICEID_FC949X:
ioc->errata_flag_1064 = 1;
/* fall through */
case MPI_MANUFACTPAGE_DEVICEID_FC909:
case MPI_MANUFACTPAGE_DEVICEID_FC929:
case MPI_MANUFACTPAGE_DEVICEID_FC919:
......@@ -1930,6 +1932,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
pcixcmd &= 0x8F;
pci_write_config_byte(pdev, 0x6a, pcixcmd);
}
/* fall through */
case MPI_MANUFACTPAGE_DEVID_1030_53C1035:
ioc->bus_type = SPI;
......
......@@ -2514,8 +2514,8 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
if (mpt_config(ioc, &cfg) == 0) {
ManufacturingPage0_t *pdata = (ManufacturingPage0_t *) pbuf;
if (strlen(pdata->BoardTracerNumber) > 1) {
strncpy(karg.serial_number, pdata->BoardTracerNumber, 24);
karg.serial_number[24-1]='\0';
strlcpy(karg.serial_number,
pdata->BoardTracerNumber, 24);
}
}
pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
......
......@@ -1292,7 +1292,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* SCSI needs scsi_cmnd lookup table!
* (with size equal to req_depth*PtrSz!)
*/
ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_KERNEL);
if (!ioc->ScsiLookup) {
error = -ENOMEM;
goto out_mptfc_probe;
......
......@@ -4327,6 +4327,7 @@ mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
}
}
mpt_findImVolumes(ioc);
/* fall through */
case MPTSAS_ADD_DEVICE:
memset(&sas_device, 0, sizeof(struct mptsas_devinfo));
......
......@@ -2038,6 +2038,7 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
if (twa_initialize_device_extension(tw_dev)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x25, "Failed to initialize device extension");
retval = -ENOMEM;
goto out_free_device_extension;
}
......@@ -2060,6 +2061,7 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
tw_dev->base_addr = ioremap(mem_addr, mem_len);
if (!tw_dev->base_addr) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x35, "Failed to ioremap");
retval = -ENOMEM;
goto out_release_mem_region;
}
......@@ -2067,8 +2069,10 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
TW_DISABLE_INTERRUPTS(tw_dev);
/* Initialize the card */
if (twa_reset_sequence(tw_dev, 0))
if (twa_reset_sequence(tw_dev, 0)) {
retval = -ENOMEM;
goto out_iounmap;
}
/* Set host specific parameters */
if ((pdev->device == PCI_DEVICE_ID_3WARE_9650SE) ||
......
......@@ -1594,6 +1594,7 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
if (twl_initialize_device_extension(tw_dev)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Failed to initialize device extension");
retval = -ENOMEM;
goto out_free_device_extension;
}
......@@ -1608,6 +1609,7 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
tw_dev->base_addr = pci_iomap(pdev, 1, 0);
if (!tw_dev->base_addr) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to ioremap");
retval = -ENOMEM;
goto out_release_mem_region;
}
......@@ -1617,6 +1619,7 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
/* Initialize the card */
if (twl_reset_sequence(tw_dev, 0)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1d, "Controller reset failed during probe");
retval = -ENOMEM;
goto out_iounmap;
}
......
......@@ -1925,7 +1925,7 @@ static int tw_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_c
if (test_bit(TW_IN_RESET, &tw_dev->flags))
return SCSI_MLQUEUE_HOST_BUSY;
/* Save done function into Scsi_Cmnd struct */
/* Save done function into struct scsi_cmnd */
SCpnt->scsi_done = done;
/* Queue the command and get a request id */
......@@ -2280,6 +2280,7 @@ static int tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
if (tw_initialize_device_extension(tw_dev)) {
printk(KERN_WARNING "3w-xxxx: Failed to initialize device extension.");
retval = -ENOMEM;
goto out_free_device_extension;
}
......@@ -2294,6 +2295,7 @@ static int tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
tw_dev->base_addr = pci_resource_start(pdev, 0);
if (!tw_dev->base_addr) {
printk(KERN_WARNING "3w-xxxx: Failed to get io address.");
retval = -ENOMEM;
goto out_release_mem_region;
}
......
......@@ -49,6 +49,7 @@ config SCSI_NETLINK
config SCSI_MQ_DEFAULT
bool "SCSI: use blk-mq I/O path by default"
default y
depends on SCSI
---help---
This option enables the new blk-mq based I/O path for SCSI
......@@ -841,18 +842,6 @@ config SCSI_IZIP_SLOW_CTR
Generally, saying N is fine.
config SCSI_NCR_D700
tristate "NCR Dual 700 MCA SCSI support"
depends on MCA && SCSI
select SCSI_SPI_ATTRS
help
This is a driver for the MicroChannel Dual 700 card produced by
NCR and commonly used in 345x/35xx/4100 class machines. It always
tries to negotiate sync and uses tag command queueing.
Unless you have an NCR manufactured machine, the chances are that
you do not have this SCSI card, so say N.
config SCSI_LASI700
tristate "HP Lasi SCSI support for 53c700/710"
depends on GSC && SCSI
......@@ -1000,21 +989,9 @@ config SCSI_ZALON
used on the add-in Bluefish, Barracuda & Shrike SCSI cards.
Say Y here if you have one of these machines or cards.
config SCSI_NCR_Q720
tristate "NCR Quad 720 MCA SCSI support"
depends on MCA && SCSI
select SCSI_SPI_ATTRS
help
This is a driver for the MicroChannel Quad 720 card produced by
NCR and commonly used in 345x/35xx/4100 class machines. It always
tries to negotiate sync and uses tag command queueing.
Unless you have an NCR manufactured machine, the chances are that
you do not have this SCSI card, so say N.
config SCSI_NCR53C8XX_DEFAULT_TAGS
int "default tagged command queue depth"
depends on SCSI_ZALON || SCSI_NCR_Q720
depends on SCSI_ZALON
default "8"
---help---
"Tagged command queuing" is a feature of SCSI-2 which improves
......@@ -1040,7 +1017,7 @@ config SCSI_NCR53C8XX_DEFAULT_TAGS
config SCSI_NCR53C8XX_MAX_TAGS
int "maximum number of queued commands"
depends on SCSI_ZALON || SCSI_NCR_Q720
depends on SCSI_ZALON
default "32"
---help---
This option allows you to specify the maximum number of commands
......@@ -1057,7 +1034,7 @@ config SCSI_NCR53C8XX_MAX_TAGS
config SCSI_NCR53C8XX_SYNC
int "synchronous transfers frequency in MHz"
depends on SCSI_ZALON || SCSI_NCR_Q720
depends on SCSI_ZALON
default "20"
---help---
The SCSI Parallel Interface-2 Standard defines 5 classes of transfer
......@@ -1091,7 +1068,7 @@ config SCSI_NCR53C8XX_SYNC
config SCSI_NCR53C8XX_NO_DISCONNECT
bool "not allow targets to disconnect"
depends on (SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0
depends on SCSI_ZALON && SCSI_NCR53C8XX_DEFAULT_TAGS=0
help
This option is only provided for safety if you suspect some SCSI
device of yours to not support properly the target-disconnect
......
......@@ -77,8 +77,6 @@ obj-$(CONFIG_SCSI_PM8001) += pm8001/
obj-$(CONFIG_SCSI_ISCI) += isci/
obj-$(CONFIG_SCSI_IPS) += ips.o
obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o
obj-$(CONFIG_SCSI_NCR_D700) += 53c700.o NCR_D700.o
obj-$(CONFIG_SCSI_NCR_Q720) += NCR_Q720_mod.o
obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o
obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o
obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o
......@@ -180,7 +178,6 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
-DCONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS
CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m)
zalon7xx-objs := zalon.o ncr53c8xx.o
NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o
# Files generated that shall be removed upon make clean
clean-files := 53c700_d.h 53c700_u.h scsi_devinfo_tbl.c
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/* -*- mode: c; c-basic-offset: 8 -*- */
/* NCR Dual 700 MCA SCSI Driver
*
* Copyright (C) 2001 by James.Bottomley@HansenPartnership.com
*/
#ifndef _NCR_D700_H
#define _NCR_D700_H
/* Don't turn on debugging messages */
#undef NCR_D700_DEBUG
/* The MCA identifier */
#define NCR_D700_MCA_ID 0x0092
/* Defines for the Board registers */
#define BOARD_RESET 0x80 /* board level reset */
#define ADD_PARENB 0x04 /* Address Parity Enabled */
#define DAT_PARENB 0x01 /* Data Parity Enabled */
#define SFBK_ENB 0x10 /* SFDBK Interrupt Enabled */
#define LED0GREEN 0x20 /* Led 0 (red 0; green 1) */
#define LED1GREEN 0x40 /* Led 1 (red 0; green 1) */
#define LED0RED 0xDF /* Led 0 (red 0; green 1) */
#define LED1RED 0xBF /* Led 1 (red 0; green 1) */
#define NCR_D700_CLOCK_MHZ 50
#endif
/* -*- mode: c; c-basic-offset: 8 -*- */
/* NCR Quad 720 MCA SCSI Driver
*
* Copyright (C) 2003 by James.Bottomley@HansenPartnership.com
*/
#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mca.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/io.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include "ncr53c8xx.h"
#include "NCR_Q720.h"
static struct ncr_chip q720_chip __initdata = {
.revision_id = 0x0f,
.burst_max = 3,
.offset_max = 8,
.nr_divisor = 4,
.features = FE_WIDE | FE_DIFF | FE_VARCLK,
};
MODULE_AUTHOR("James Bottomley");
MODULE_DESCRIPTION("NCR Quad 720 SCSI Driver");
MODULE_LICENSE("GPL");
#define NCR_Q720_VERSION "0.9"
/* We needs this helper because we have up to four hosts per struct device */
struct NCR_Q720_private {
struct device *dev;
void __iomem * mem_base;
__u32 phys_mem_base;
__u32 mem_size;
__u8 irq;
__u8 siops;
__u8 irq_enable;
struct Scsi_Host *hosts[4];
};
static struct scsi_host_template NCR_Q720_tpnt = {
.module = THIS_MODULE,
.proc_name = "NCR_Q720",
};
static irqreturn_t
NCR_Q720_intr(int irq, void *data)
{
struct NCR_Q720_private *p = (struct NCR_Q720_private *)data;
__u8 sir = (readb(p->mem_base + 0x0d) & 0xf0) >> 4;
__u8 siop;
sir |= ~p->irq_enable;
if(sir == 0xff)
return IRQ_NONE;
while((siop = ffz(sir)) < p->siops) {
sir |= 1<<siop;
ncr53c8xx_intr(irq, p->hosts[siop]);
}
return IRQ_HANDLED;
}
static int __init
NCR_Q720_probe_one(struct NCR_Q720_private *p, int siop,
int irq, int slot, __u32 paddr, void __iomem *vaddr)
{
struct ncr_device device;
__u8 scsi_id;
static int unit = 0;
__u8 scsr1 = readb(vaddr + NCR_Q720_SCSR_OFFSET + 1);
__u8 differential = readb(vaddr + NCR_Q720_SCSR_OFFSET) & 0x20;
__u8 version;
int error;
scsi_id = scsr1 >> 4;
/* enable burst length 16 (FIXME: should allow this) */
scsr1 |= 0x02;
/* force a siop reset */
scsr1 |= 0x04;
writeb(scsr1, vaddr + NCR_Q720_SCSR_OFFSET + 1);
udelay(10);
version = readb(vaddr + 0x18) >> 4;
memset(&device, 0, sizeof(struct ncr_device));
/* Initialise ncr_device structure with items required by ncr_attach. */
device.chip = q720_chip;
device.chip.revision_id = version;
device.host_id = scsi_id;
device.dev = p->dev;
device.slot.base = paddr;
device.slot.base_c = paddr;
device.slot.base_v = vaddr;
device.slot.irq = irq;
device.differential = differential ? 2 : 0;
printk("Q720 probe unit %d (siop%d) at 0x%lx, diff = %d, vers = %d\n", unit, siop,
(unsigned long)paddr, differential, version);
p->hosts[siop] = ncr_attach(&NCR_Q720_tpnt, unit++, &device);
if (!p->hosts[siop])
goto fail;
p->irq_enable |= (1<<siop);
scsr1 = readb(vaddr + NCR_Q720_SCSR_OFFSET + 1);
/* clear the disable interrupt bit */
scsr1 &= ~0x01;
writeb(scsr1, vaddr + NCR_Q720_SCSR_OFFSET + 1);
error = scsi_add_host(p->hosts[siop], p->dev);
if (error)
ncr53c8xx_release(p->hosts[siop]);
else
scsi_scan_host(p->hosts[siop]);
return error;
fail:
return -ENODEV;
}
/* Detect a Q720 card. Note, because of the setup --- the chips are
* essentially connectecd to the MCA bus independently, it is easier
* to set them up as two separate host adapters, rather than one
* adapter with two channels */
static int __init
NCR_Q720_probe(struct device *dev)
{
struct NCR_Q720_private *p;
static int banner = 1;
struct mca_device *mca_dev = to_mca_device(dev);
int slot = mca_dev->slot;
int found = 0;
int irq, i, siops;
__u8 pos2, pos4, asr2, asr9, asr10;
__u16 io_base;
__u32 base_addr, mem_size;
void __iomem *mem_base;
p = kzalloc(sizeof(*p), GFP_KERNEL);
if (!p)
return -ENOMEM;
pos2 = mca_device_read_pos(mca_dev, 2);
/* enable device */
pos2 |= NCR_Q720_POS2_BOARD_ENABLE | NCR_Q720_POS2_INTERRUPT_ENABLE;
mca_device_write_pos(mca_dev, 2, pos2);
io_base = (pos2 & NCR_Q720_POS2_IO_MASK) << NCR_Q720_POS2_IO_SHIFT;