提交 cdc19470 编写于 作者: L 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 update includes the usual round of major driver updates (ncr5380,
  ufs, lpfc, be2iscsi, hisi_sas, storvsc, cxlflash, aacraid,
  megaraid_sas, ...).

  There's also an assortment of minor fixes and the major update of
  switching a bunch of drivers to pci_alloc_irq_vectors from Christoph"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (188 commits)
  scsi: megaraid_sas: handle dma_addr_t right on 32-bit
  scsi: megaraid_sas: array overflow in megasas_dump_frame()
  scsi: snic: switch to pci_irq_alloc_vectors
  scsi: megaraid_sas: driver version upgrade
  scsi: megaraid_sas: Change RAID_1_10_RMW_CMDS to RAID_1_PEER_CMDS and set value to 2
  scsi: megaraid_sas: Indentation and smatch warning fixes
  scsi: megaraid_sas: Cleanup VD_EXT_DEBUG and SPAN_DEBUG related debug prints
  scsi: megaraid_sas: Increase internal command pool
  scsi: megaraid_sas: Use synchronize_irq to wait for IRQs to complete
  scsi: megaraid_sas: Bail out the driver load if ld_list_query fails
  scsi: megaraid_sas: Change build_mpt_mfi_pass_thru to return void
  scsi: megaraid_sas: During OCR, if get_ctrl_info fails do not continue with OCR
  scsi: megaraid_sas: Do not set fp_possible if TM capable for non-RW syspdIO, change fp_possible to bool
  scsi: megaraid_sas: Remove unused pd_index from megasas_build_ld_nonrw_fusion
  scsi: megaraid_sas: megasas_return_cmd does not memset IO frame to zero
  scsi: megaraid_sas: max_fw_cmds are decremented twice, remove duplicate
  scsi: megaraid_sas: update can_queue only if the new value is less
  scsi: megaraid_sas: Change max_cmd from u32 to u16 in all functions
  scsi: megaraid_sas: set pd_after_lb from MR_BuildRaidContext and initialize pDevHandle to MR_DEVHANDLE_INVALID
  scsi: megaraid_sas: latest controller OCR capability from FW before sending shutdown DCMD
  ...
......@@ -549,6 +549,7 @@ enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
DPRINTK("EXIT, ret=%d\n", ret);
return ret;
}
EXPORT_SYMBOL(ata_scsi_timed_out);
static void ata_eh_unload(struct ata_port *ap)
{
......
......@@ -716,7 +716,6 @@ struct scsi_transport_template *ata_attach_transport(void)
return NULL;
i->t.eh_strategy_handler = ata_scsi_error;
i->t.eh_timed_out = ata_scsi_timed_out;
i->t.user_scan = ata_scsi_user_scan;
i->t.host_attrs.ac.attrs = &i->port_attrs[0];
......
......@@ -159,7 +159,6 @@ extern unsigned long ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd);
extern void ata_internal_cmd_timed_out(struct ata_device *dev, u8 cmd);
extern void ata_eh_acquire(struct ata_port *ap);
extern void ata_eh_release(struct ata_port *ap);
extern enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
extern void ata_scsi_error(struct Scsi_Host *host);
extern void ata_eh_fastdrain_timerfn(unsigned long arg);
extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);
......
......@@ -400,27 +400,27 @@ static bool SA5_performant_intr_pending(ctlr_info_t *h)
}
static struct access_method SA5_access = {
SA5_submit_command,
SA5_intr_mask,
SA5_fifo_full,
SA5_intr_pending,
SA5_completed,
.submit_command = SA5_submit_command,
.set_intr_mask = SA5_intr_mask,
.fifo_full = SA5_fifo_full,
.intr_pending = SA5_intr_pending,
.command_completed = SA5_completed,
};
static struct access_method SA5B_access = {
SA5_submit_command,
SA5B_intr_mask,
SA5_fifo_full,
SA5B_intr_pending,
SA5_completed,
.submit_command = SA5_submit_command,
.set_intr_mask = SA5B_intr_mask,
.fifo_full = SA5_fifo_full,
.intr_pending = SA5B_intr_pending,
.command_completed = SA5_completed,
};
static struct access_method SA5_performant_access = {
SA5_submit_command,
SA5_performant_intr_mask,
SA5_fifo_full,
SA5_performant_intr_pending,
SA5_performant_completed,
.submit_command = SA5_submit_command,
.set_intr_mask = SA5_performant_intr_mask,
.fifo_full = SA5_fifo_full,
.intr_pending = SA5_performant_intr_pending,
.command_completed = SA5_performant_completed,
};
struct board_type {
......
......@@ -994,6 +994,7 @@ static struct scsi_host_template iscsi_iser_sht = {
.change_queue_depth = scsi_change_queue_depth,
.sg_tablesize = ISCSI_ISER_DEF_SG_TABLESIZE,
.cmd_per_lun = ISER_DEF_CMD_PER_LUN,
.eh_timed_out = iscsi_eh_cmd_timed_out,
.eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler= iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_recover_target,
......
......@@ -2869,6 +2869,7 @@ static struct scsi_host_template srp_template = {
.info = srp_target_info,
.queuecommand = srp_queuecommand,
.change_queue_depth = srp_change_queue_depth,
.eh_timed_out = srp_timed_out,
.eh_abort_handler = srp_abort,
.eh_device_reset_handler = srp_reset_device,
.eh_host_reset_handler = srp_reset_host,
......
......@@ -119,6 +119,7 @@ static struct scsi_host_template mptfc_driver_template = {
.target_destroy = mptfc_target_destroy,
.slave_destroy = mptscsih_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = mptfc_abort,
.eh_device_reset_handler = mptfc_dev_reset,
.eh_bus_reset_handler = mptfc_bus_reset,
......
......@@ -65,7 +65,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
......
......@@ -1983,6 +1983,7 @@ static struct scsi_host_template mptsas_driver_template = {
.target_destroy = mptsas_target_destroy,
.slave_destroy = mptscsih_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_timed_out = mptsas_eh_timed_out,
.eh_abort_handler = mptscsih_abort,
.eh_device_reset_handler = mptscsih_dev_reset,
.eh_host_reset_handler = mptscsih_host_reset,
......@@ -5398,7 +5399,6 @@ mptsas_init(void)
sas_attach_transport(&mptsas_transport_functions);
if (!mptsas_transport_template)
return -ENODEV;
mptsas_transport_template->eh_timed_out = mptsas_eh_timed_out;
mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER,
"mptscsih_io_done");
......
......@@ -330,6 +330,7 @@ static struct scsi_host_template zfcp_scsi_host_template = {
.module = THIS_MODULE,
.name = "zfcp",
.queuecommand = zfcp_scsi_queuecommand,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = zfcp_scsi_eh_abort_handler,
.eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
.eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler,
......
......@@ -96,17 +96,6 @@
* of chips. To use it, you write an architecture specific functions
* and macros and include this file in your driver.
*
* These macros control options :
* AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
* for commands that return with a CHECK CONDITION status.
*
* DIFFERENTIAL - if defined, NCR53c81 chips will use external differential
* transceivers.
*
* PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases.
*
* REAL_DMA - if defined, REAL DMA is used during the data transfer phases.
*
* These macros MUST be defined :
*
* NCR5380_read(register) - read from the specified register
......@@ -347,7 +336,7 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
#endif
/**
* NCR58380_info - report driver and host information
* NCR5380_info - report driver and host information
* @instance: relevant scsi host instance
*
* For use as the host template info() handler.
......@@ -360,33 +349,6 @@ static const char *NCR5380_info(struct Scsi_Host *instance)
return hostdata->info;
}
static void prepare_info(struct Scsi_Host *instance)
{
struct NCR5380_hostdata *hostdata = shost_priv(instance);
snprintf(hostdata->info, sizeof(hostdata->info),
"%s, irq %d, "
"io_port 0x%lx, base 0x%lx, "
"can_queue %d, cmd_per_lun %d, "
"sg_tablesize %d, this_id %d, "
"flags { %s%s%s}, "
"options { %s} ",
instance->hostt->name, instance->irq,
hostdata->io_port, hostdata->base,
instance->can_queue, instance->cmd_per_lun,
instance->sg_tablesize, instance->this_id,
hostdata->flags & FLAG_DMA_FIXUP ? "DMA_FIXUP " : "",
hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "",
hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "",
#ifdef DIFFERENTIAL
"DIFFERENTIAL "
#endif
#ifdef PARITY
"PARITY "
#endif
"");
}
/**
* NCR5380_init - initialise an NCR5380
* @instance: adapter to configure
......@@ -436,7 +398,14 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
if (!hostdata->work_q)
return -ENOMEM;
prepare_info(instance);
snprintf(hostdata->info, sizeof(hostdata->info),
"%s, irq %d, io_port 0x%lx, base 0x%lx, can_queue %d, cmd_per_lun %d, sg_tablesize %d, this_id %d, flags { %s%s%s}",
instance->hostt->name, instance->irq, hostdata->io_port,
hostdata->base, instance->can_queue, instance->cmd_per_lun,
instance->sg_tablesize, instance->this_id,
hostdata->flags & FLAG_DMA_FIXUP ? "DMA_FIXUP " : "",
hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "",
hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "");
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
NCR5380_write(MODE_REG, MR_BASE);
......@@ -622,8 +591,9 @@ static inline void maybe_release_dma_irq(struct Scsi_Host *instance)
list_empty(&hostdata->unissued) &&
list_empty(&hostdata->autosense) &&
!hostdata->connected &&
!hostdata->selecting)
!hostdata->selecting) {
NCR5380_release_dma_irq(instance);
}
}
/**
......@@ -962,6 +932,7 @@ static irqreturn_t __maybe_unused NCR5380_intr(int irq, void *dev_id)
static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
struct scsi_cmnd *cmd)
__releases(&hostdata->lock) __acquires(&hostdata->lock)
{
struct NCR5380_hostdata *hostdata = shost_priv(instance);
unsigned char tmp[3], phase;
......@@ -1194,8 +1165,16 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
data = tmp;
phase = PHASE_MSGOUT;
NCR5380_transfer_pio(instance, &phase, &len, &data);
if (len) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
cmd->result = DID_ERROR << 16;
complete_cmd(instance, cmd);
dsprintk(NDEBUG_SELECTION, instance, "IDENTIFY message transfer failed\n");
cmd = NULL;
goto out;
}
dsprintk(NDEBUG_SELECTION, instance, "nexus established.\n");
/* XXX need to handle errors here */
hostdata->connected = cmd;
hostdata->busy[cmd->device->id] |= 1 << cmd->device->lun;
......@@ -1654,6 +1633,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
*/
static void NCR5380_information_transfer(struct Scsi_Host *instance)
__releases(&hostdata->lock) __acquires(&hostdata->lock)
{
struct NCR5380_hostdata *hostdata = shost_priv(instance);
unsigned char msgout = NOP;
......
......@@ -81,11 +81,7 @@
#define ICR_ASSERT_ATN 0x02 /* rw Set to assert ATN */
#define ICR_ASSERT_DATA 0x01 /* rw SCSI_DATA_REG is asserted */
#ifdef DIFFERENTIAL
#define ICR_BASE ICR_DIFF_ENABLE
#else
#define ICR_BASE 0
#endif
#define MODE_REG 2
/*
......@@ -102,11 +98,7 @@
#define MR_DMA_MODE 0x02 /* rw DMA / pseudo DMA mode */
#define MR_ARBITRATE 0x01 /* rw start arbitration */
#ifdef PARITY
#define MR_BASE MR_ENABLE_PAR_CHECK
#else
#define MR_BASE 0
#endif
#define TARGET_COMMAND_REG 3
#define TCR_LAST_BYTE_SENT 0x80 /* ro DMA done */
......@@ -174,11 +166,7 @@
#define CSR_SCSI_BUF_RDY 0x02 /* ro SCSI buffer read */
#define CSR_GATED_53C80_IRQ 0x01 /* ro Last block xferred */
#if 0
#define CSR_BASE CSR_SCSI_BUFF_INTR | CSR_53C80_INTR
#else
#define CSR_BASE CSR_53C80_INTR
#endif
/* Note : PHASE_* macros are based on the values of the STATUS register */
#define PHASE_MASK (SR_MSG | SR_CD | SR_IO)
......@@ -234,11 +222,9 @@ struct NCR5380_hostdata {
unsigned char id_higher_mask; /* All bits above id_mask */
unsigned char last_message; /* Last Message Out */
unsigned long region_size; /* Size of address/port range */
char info[256];
char info[168]; /* Host banner message */
};
#ifdef __KERNEL__
struct NCR5380_cmd {
struct list_head list;
};
......@@ -331,5 +317,4 @@ static inline int NCR5380_dma_residual_none(struct NCR5380_hostdata *hostdata)
return 0;
}
#endif /* __KERNEL__ */
#endif /* NCR5380_H */
此差异已折叠。
此差异已折叠。
......@@ -6,7 +6,8 @@
* Adaptec aacraid device driver for Linux.
*
* Copyright (c) 2000-2010 Adaptec, Inc.
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
* 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
* 2016-2017 Microsemi Corp. (aacraid@microsemi.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -477,20 +478,24 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
struct fib* srbfib;
int status;
struct aac_srb *srbcmd = NULL;
struct aac_hba_cmd_req *hbacmd = NULL;
struct user_aac_srb *user_srbcmd = NULL;
struct user_aac_srb __user *user_srb = arg;
struct aac_srb_reply __user *user_reply;
struct aac_srb_reply* reply;
u32 chn;
u32 fibsize = 0;
u32 flags = 0;
s32 rcode = 0;
u32 data_dir;
void __user *sg_user[32];
void *sg_list[32];
void __user *sg_user[HBA_MAX_SG_EMBEDDED];
void *sg_list[HBA_MAX_SG_EMBEDDED];
u32 sg_count[HBA_MAX_SG_EMBEDDED];
u32 sg_indx = 0;
u32 byte_count = 0;
u32 actual_fibsize64, actual_fibsize = 0;
int i;
int is_native_device;
u64 address;
if (dev->in_reset) {
......@@ -507,11 +512,6 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
if (!(srbfib = aac_fib_alloc(dev))) {
return -ENOMEM;
}
aac_fib_init(srbfib);
/* raw_srb FIB is not FastResponseCapable */
srbfib->hw_fib_va->header.XferState &= ~cpu_to_le32(FastResponseCapable);
srbcmd = (struct aac_srb*) fib_data(srbfib);
memset(sg_list, 0, sizeof(sg_list)); /* cleanup may take issue */
if(copy_from_user(&fibsize, &user_srb->count,sizeof(u32))){
......@@ -538,21 +538,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
goto cleanup;
}
user_reply = arg+fibsize;
flags = user_srbcmd->flags; /* from user in cpu order */
// Fix up srb for endian and force some values
srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this
srbcmd->channel = cpu_to_le32(user_srbcmd->channel);
srbcmd->id = cpu_to_le32(user_srbcmd->id);
srbcmd->lun = cpu_to_le32(user_srbcmd->lun);
srbcmd->timeout = cpu_to_le32(user_srbcmd->timeout);
srbcmd->flags = cpu_to_le32(flags);
srbcmd->retry_limit = 0; // Obsolete parameter
srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);
memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb));
switch (flags & (SRB_DataIn | SRB_DataOut)) {
case SRB_DataOut:
data_dir = DMA_TO_DEVICE;
......@@ -568,7 +554,12 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
}
if (user_srbcmd->sg.count > ARRAY_SIZE(sg_list)) {
dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n",
le32_to_cpu(srbcmd->sg.count)));
user_srbcmd->sg.count));
rcode = -EINVAL;
goto cleanup;
}
if ((data_dir == DMA_NONE) && user_srbcmd->sg.count) {
dprintk((KERN_DEBUG"aacraid:SG with no direction specified\n"));
rcode = -EINVAL;
goto cleanup;
}
......@@ -588,13 +579,136 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -EINVAL;
goto cleanup;
}
if ((data_dir == DMA_NONE) && user_srbcmd->sg.count) {
dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
rcode = -EINVAL;
goto cleanup;
chn = aac_logical_to_phys(user_srbcmd->channel);
if (chn < AAC_MAX_BUSES && user_srbcmd->id < AAC_MAX_TARGETS &&
dev->hba_map[chn][user_srbcmd->id].devtype ==
AAC_DEVTYPE_NATIVE_RAW) {
is_native_device = 1;
hbacmd = (struct aac_hba_cmd_req *)srbfib->hw_fib_va;
memset(hbacmd, 0, 96); /* sizeof(*hbacmd) is not necessary */
/* iu_type is a parameter of aac_hba_send */
switch (data_dir) {
case DMA_TO_DEVICE:
hbacmd->byte1 = 2;
break;
case DMA_FROM_DEVICE:
case DMA_BIDIRECTIONAL:
hbacmd->byte1 = 1;
break;
case DMA_NONE:
default:
break;
}
hbacmd->lun[1] = cpu_to_le32(user_srbcmd->lun);
hbacmd->it_nexus = dev->hba_map[chn][user_srbcmd->id].rmw_nexus;
/*
* we fill in reply_qid later in aac_src_deliver_message
* we fill in iu_type, request_id later in aac_hba_send
* we fill in emb_data_desc_count, data_length later
* in sg list build
*/
memcpy(hbacmd->cdb, user_srbcmd->cdb, sizeof(hbacmd->cdb));
address = (u64)srbfib->hw_error_pa;
hbacmd->error_ptr_hi = cpu_to_le32((u32)(address >> 32));
hbacmd->error_ptr_lo = cpu_to_le32((u32)(address & 0xffffffff));
hbacmd->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE);
hbacmd->emb_data_desc_count =
cpu_to_le32(user_srbcmd->sg.count);
srbfib->hbacmd_size = 64 +
user_srbcmd->sg.count * sizeof(struct aac_hba_sgl);
} else {
is_native_device = 0;
aac_fib_init(srbfib);
/* raw_srb FIB is not FastResponseCapable */
srbfib->hw_fib_va->header.XferState &=
~cpu_to_le32(FastResponseCapable);
srbcmd = (struct aac_srb *) fib_data(srbfib);
// Fix up srb for endian and force some values
srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this
srbcmd->channel = cpu_to_le32(user_srbcmd->channel);
srbcmd->id = cpu_to_le32(user_srbcmd->id);
srbcmd->lun = cpu_to_le32(user_srbcmd->lun);
srbcmd->timeout = cpu_to_le32(user_srbcmd->timeout);
srbcmd->flags = cpu_to_le32(flags);
srbcmd->retry_limit = 0; // Obsolete parameter
srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);
memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb));
}
byte_count = 0;
if (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64) {
if (is_native_device) {
struct user_sgmap *usg32 = &user_srbcmd->sg;
struct user_sgmap64 *usg64 =
(struct user_sgmap64 *)&user_srbcmd->sg;
for (i = 0; i < usg32->count; i++) {
void *p;
u64 addr;
sg_count[i] = (actual_fibsize64 == fibsize) ?
usg64->sg[i].count : usg32->sg[i].count;
if (sg_count[i] >
(dev->scsi_host_ptr->max_sectors << 9)) {
pr_err("aacraid: upsg->sg[%d].count=%u>%u\n",
i, sg_count[i],
dev->scsi_host_ptr->max_sectors << 9);
rcode = -EINVAL;
goto cleanup;
}
p = kmalloc(sg_count[i], GFP_KERNEL|__GFP_DMA);
if (!p) {
rcode = -ENOMEM;
goto cleanup;
}
if (actual_fibsize64 == fibsize) {
addr = (u64)usg64->sg[i].addr[0];
addr += ((u64)usg64->sg[i].addr[1]) << 32;
} else {
addr = (u64)usg32->sg[i].addr;
}
sg_user[i] = (void __user *)(uintptr_t)addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;
if (flags & SRB_DataOut) {
if (copy_from_user(p, sg_user[i],
sg_count[i])) {
rcode = -EFAULT;
goto cleanup;
}
}
addr = pci_map_single(dev->pdev, p, sg_count[i],
data_dir);
hbacmd->sge[i].addr_hi = cpu_to_le32((u32)(addr>>32));
hbacmd->sge[i].addr_lo = cpu_to_le32(
(u32)(addr & 0xffffffff));
hbacmd->sge[i].len = cpu_to_le32(sg_count[i]);
hbacmd->sge[i].flags = 0;
byte_count += sg_count[i];
}
if (usg32->count > 0) /* embedded sglist */
hbacmd->sge[usg32->count-1].flags =
cpu_to_le32(0x40000000);
hbacmd->data_length = cpu_to_le32(byte_count);
status = aac_hba_send(HBA_IU_TYPE_SCSI_CMD_REQ, srbfib,
NULL, NULL);
} else if (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64) {
struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;
......@@ -606,7 +720,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
for (i = 0; i < upsg->count; i++) {
u64 addr;
void* p;
if (upsg->sg[i].count >
sg_count[i] = upsg->sg[i].count;
if (sg_count[i] >
((dev->adapter_info.options &
AAC_OPT_NEW_COMM) ?
(dev->scsi_host_ptr->max_sectors << 9) :
......@@ -615,10 +731,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
goto cleanup;
}
/* Does this really need to be GFP_DMA? */
p = kmalloc(upsg->sg[i].count,GFP_KERNEL|__GFP_DMA);
p = kmalloc(sg_count[i], GFP_KERNEL|__GFP_DMA);
if(!p) {
dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
upsg->sg[i].count,i,upsg->count));
sg_count[i], i, upsg->count));
rcode = -ENOMEM;
goto cleanup;
}
......@@ -629,18 +745,20 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
sg_indx = i;
if (flags & SRB_DataOut) {
if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
if (copy_from_user(p, sg_user[i],
sg_count[i])){
dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
rcode = -EFAULT;
goto cleanup;
}
}
addr = pci_map_single(dev->pdev, p, upsg->sg[i].count, data_dir);
addr = pci_map_single(dev->pdev, p,
sg_count[i], data_dir);
psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
byte_count += upsg->sg[i].count;
psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
byte_count += sg_count[i];
psg->sg[i].count = cpu_to_le32(sg_count[i]);
}
} else {
struct user_sgmap* usg;
......@@ -657,7 +775,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
for (i = 0; i < usg->count; i++) {
u64 addr;
void* p;
if (usg->sg[i].count >
sg_count[i] = usg->sg[i].count;
if (sg_count[i] >
((dev->adapter_info.options &
AAC_OPT_NEW_COMM) ?
(dev->scsi_host_ptr->max_sectors << 9) :
......@@ -667,10 +787,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
goto cleanup;
}
/* Does this really need to be GFP_DMA? */
p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
p = kmalloc(sg_count[i], GFP_KERNEL|__GFP_DMA);
if(!p) {
dprintk((KERN_DEBUG "aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
usg->sg[i].count,i,usg->count));
sg_count[i], i, usg->count));
kfree(usg);
rcode = -ENOMEM;
goto cleanup;
......@@ -680,19 +800,21 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
sg_indx = i;
if (flags & SRB_DataOut) {
if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
if (copy_from_user(p, sg_user[i],
sg_count[i])) {
kfree (usg);
dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
rcode = -EFAULT;
goto cleanup;
}
}
addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
addr = pci_map_single(dev->pdev, p,
sg_count[i], data_dir);
psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
byte_count += usg->sg[i].count;
psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
byte_count += sg_count[i];
psg->sg[i].count = cpu_to_le32(sg_count[i]);
}
kfree (usg);
}
......@@ -711,7 +833,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
for (i = 0; i < upsg->count; i++) {
uintptr_t addr;
void* p;
if (usg->sg[i].count >
sg_count[i] = usg->sg[i].count;
if (sg_count[i] >
((dev->adapter_info.options &
AAC_OPT_NEW_COMM) ?
(dev->scsi_host_ptr->max_sectors << 9) :
......@@ -720,10 +844,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
goto cleanup;
}
/* Does this really need to be GFP_DMA? */
p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
if(!p) {
p = kmalloc(sg_count[i], GFP_KERNEL|__GFP_DMA);
if (!p) {
dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
usg->sg[i].count,i,usg->count));
sg_count[i], i, usg->count));
rcode = -ENOMEM;
goto cleanup;
}
......@@ -734,7 +858,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
sg_indx = i;
if (flags & SRB_DataOut) {
if(copy_from_user(p,sg_user[i],usg->sg[i].count)){
if (copy_from_user(p, sg_user[i],
sg_count[i])){
dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
rcode = -EFAULT;
goto cleanup;
......@@ -744,13 +869,15 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
psg->sg[i].addr = cpu_to_le32(addr & 0xffffffff);
byte_count += usg->sg[i].count;
psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
psg->sg[i].count = cpu_to_le32(sg_count[i]);
}
} else {
for (i = 0; i < upsg->count; i++) {
dma_addr_t addr;
void* p;
if (upsg->sg[i].count >
sg_count[i] = upsg->sg[i].count;
if (sg_count[i] >
((dev->adapter_info.options &
AAC_OPT_NEW_COMM) ?
(dev->scsi_host_ptr->max_sectors << 9) :
......@@ -758,10 +885,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -EINVAL;
goto cleanup;
}
p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
p = kmalloc(sg_count[i], GFP_KERNEL);
if (!p) {
dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
upsg->sg[i].count, i, upsg->count));
sg_count[i], i, upsg->count));
rcode = -ENOMEM;
goto cleanup;
}
......@@ -770,19 +897,19 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
sg_indx = i;
if (flags & SRB_DataOut) {
if(copy_from_user(p, sg_user[i],
upsg->sg[i].count)) {
if (copy_from_user(p, sg_user[i],
sg_count[i])) {
dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
rcode = -EFAULT;
goto cleanup;
}
}
addr = pci_map_single(dev->pdev, p,
upsg->sg[i].count, data_dir);
sg_count[i], data_dir);
psg->sg[i].addr = cpu_to_le32(addr);
byte_count += upsg->sg[i].count;
psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
byte_count += sg_count[i];
psg->sg[i].count = cpu_to_le32(sg_count[i]);
}
}
srbcmd->count = cpu_to_le32(byte_count);
......@@ -792,12 +919,13 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
psg->count = 0;
status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
}
if (status == -ERESTARTSYS) {
rcode = -ERESTARTSYS;
goto cleanup;
}
if (status != 0){
if (status != 0) {
dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n"));
rcode = -ENXIO;
goto cleanup;
......@@ -805,11 +933,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
if (flags & SRB_DataIn) {
for(i = 0 ; i <= sg_indx; i++){
byte_count = le32_to_cpu(
(dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)
? ((struct sgmap64*)&srbcmd->sg)->sg[i].count
: srbcmd->sg.sg[i].count);
if(copy_to_user(sg_user[i], sg_list[i], byte_count)){
if (copy_to_user(sg_user[i], sg_list[i], sg_count[i])) {
dprintk((KERN_DEBUG"aacraid: Could not copy sg data to user\n"));
rcode = -EFAULT;
goto cleanup;
......@@ -818,19 +942,50 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
}
}
reply = (struct aac_srb_reply *) fib_data(srbfib);
if(copy_to_user(user_reply,reply,sizeof(struct aac_srb_reply))){
dprintk((KERN_DEBUG"aacraid: Could not copy reply to user\n"));
rcode = -EFAULT;
goto cleanup;
user_reply = arg + fibsize;
if (is_native_device) {
struct aac_hba_resp *err =
&((struct aac_native_hba *)srbfib->hw_fib_va)->resp.err;
struct aac_srb_reply reply;
reply.status = ST_OK;
if (srbfib->flags & FIB_CONTEXT_FLAG_FASTRESP) {
/* fast response */
reply.srb_status = SRB_STATUS_SUCCESS;
reply.scsi_status = 0;
reply.data_xfer_length = byte_count;
} else {
reply.srb_status = err->service_response;
reply.scsi_status = err->status;
reply.data_xfer_length = byte_count -
le32_to_cpu(err->residual_count);
reply.sense_data_size = err->sense_response_data_len;
memcpy(reply.sense_data, err->sense_response_buf,
AAC_SENSE_BUFFERSIZE);
}
if (copy_to_user(user_reply, &reply,
sizeof(struct aac_srb_reply))) {
dprintk((KERN_DEBUG"aacraid: Copy to user failed\n"));
rcode = -EFAULT;
goto cleanup;
}
} else {
struct aac_srb_reply *reply;
reply = (struct aac_srb_reply *) fib_data(srbfib);
if (copy_to_user(user_reply, reply,
sizeof(struct aac_srb_reply))) {
dprintk((KERN_DEBUG"aacraid: Copy to user failed\n"));
rcode = -EFAULT;
goto cleanup;
}
}
cleanup:
kfree(user_srbcmd);
for(i=0; i <= sg_indx; i++){
kfree(sg_list[i]);
}
if (rcode != -ERESTARTSYS) {
for (i = 0; i <= sg_indx; i++)
kfree(sg_list[i]);
aac_fib_complete(srbfib);
aac_fib_free(srbfib);
}
......@@ -858,6 +1013,44 @@ static int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
return 0;
}
static int aac_get_hba_info(struct aac_dev *dev, void __user *arg)
{
struct aac_hba_info hbainfo;
hbainfo.adapter_number = (u8) dev->id;
hbainfo.system_io_bus_number = dev->pdev->bus->number;
hbainfo.device_number = (dev->pdev->devfn >> 3);
hbainfo.function_number = (dev->pdev->devfn & 0x0007);
hbainfo.vendor_id = dev->pdev->vendor;
hbainfo.device_id = dev->pdev->device;
hbainfo.sub_vendor_id = dev->pdev->subsystem_vendor;
hbainfo.sub_system_id = dev->pdev->subsystem_device;
if (copy_to_user(arg, &hbainfo, sizeof(struct aac_hba_info))) {
dprintk((KERN_DEBUG "aacraid: Could not copy hba info\n"));
return -EFAULT;
}
return 0;
}
struct aac_reset_iop {
u8 reset_type;
};
static int aac_send_reset_adapter(struct aac_dev *dev, void __user *arg)
{
struct aac_reset_iop reset;
int retval;
if (copy_from_user((void *)&reset, arg, sizeof(struct aac_reset_iop)))
return -EFAULT;
retval = aac_reset_adapter(dev, 0, reset.reset_type);
return retval;
}
int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg)
{
......@@ -901,6 +1094,13 @@ int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg)
case FSACTL_GET_PCI_INFO:
status = aac_get_pci_info(dev,arg);
break;
case FSACTL_GET_HBA_INFO:
status = aac_get_hba_info(dev, arg);
break;
case FSACTL_RESET_IOP:
status = aac_send_reset_adapter(dev, arg);
break;
default:
status = -ENOTTY;
break;
......
......@@ -6,7 +6,8 @@
* Adaptec aacraid device driver for Linux.
*
* Copyright (c) 2000-2010 Adaptec, Inc.
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
* 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
* 2016-2017 Microsemi Corp. (aacraid@microsemi.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -72,104 +73,175 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
unsigned long size, align;
const unsigned long fibsize = dev->max_fib_size;
const unsigned long printfbufsiz = 256;
unsigned long host_rrq_size = 0;
struct aac_init *init;
unsigned long host_rrq_size, aac_init_size;
union aac_init *init;
dma_addr_t phys;
unsigned long aac_max_hostphysmempages;
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1 ||
dev->comm_interface == AAC_COMM_MESSAGE_TYPE2)
if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) ||
(dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) ||
(dev->comm_interface == AAC_COMM_MESSAGE_TYPE3 &&
!dev->sa_firmware)) {
host_rrq_size =
(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)
* sizeof(u32);
aac_init_size = sizeof(union aac_init);
} else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE3 &&
dev->sa_firmware) {
host_rrq_size = (dev->scsi_host_ptr->can_queue
+ AAC_NUM_MGT_FIB) * sizeof(u32);
size = fibsize + sizeof(struct aac_init) + commsize +
commalign + printfbufsiz + host_rrq_size;
+ AAC_NUM_MGT_FIB) * sizeof(u32) * AAC_MAX_MSIX;
aac_init_size = sizeof(union aac_init) +
(AAC_MAX_HRRQ - 1) * sizeof(struct _rrq);
} else {
host_rrq_size = 0;
aac_init_size = sizeof(union aac_init);
}
size = fibsize + aac_init_size + commsize + commalign +
printfbufsiz + host_rrq_size;
base = pci_alloc_consistent(dev->pdev, size, &phys);
if(base == NULL)
{
if (base == NULL) {
printk(KERN_ERR "aacraid: unable to create mapping.\n");
return 0;
}
dev->comm_addr = (void *)base;
dev->comm_phys = phys;
dev->comm_size = size;
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1 ||
dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) {
if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) ||
(dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) ||
(dev->comm_interface == AAC_COMM_MESSAGE_TYPE3)) {
dev->host_rrq = (u32 *)(base + fibsize);
dev->host_rrq_pa = phys + fibsize;
memset(dev->host_rrq, 0, host_rrq_size);
}
dev->init = (struct aac_init *)(base + fibsize + host_rrq_size);
dev->init = (union aac_init *)(base + fibsize + host_rrq_size);
dev->init_pa = phys + fibsize + host_rrq_size;
init = dev->init;
init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION);
if (dev->max_fib_size != sizeof(struct hw_fib))
init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4);
init->Sa_MSIXVectors = cpu_to_le32(SA_INIT_NUM_MSIXVECTORS);
init->fsrev = cpu_to_le32(dev->fsrev);
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) {
int i;
u64 addr;
init->r8.init_struct_revision =
cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_8);
init->r8.init_flags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED |
INITFLAGS_DRIVER_USES_UTC_TIME |
INITFLAGS_DRIVER_SUPPORTS_PM);
init->r8.init_flags |=
cpu_to_le32(INITFLAGS_DRIVER_SUPPORTS_HBA_MODE);
init->r8.rr_queue_count = cpu_to_le32(dev->max_msix);
init->r8.max_io_size =
cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
init->r8.max_num_aif = init->r8.reserved1 =
init->r8.reserved2 = 0;
for (i = 0; i < dev->max_msix; i++) {
addr = (u64)dev->host_rrq_pa + dev->vector_cap * i *
sizeof(u32);
init->r8.rrq[i].host_addr_high = cpu_to_le32(
upper_32_bits(addr));
init->r8.rrq[i].host_addr_low = cpu_to_le32(
lower_32_bits(addr));
init->r8.rrq[i].msix_id = i;
init->r8.rrq[i].element_count = cpu_to_le16(
(u16)dev->vector_cap);
init->r8.rrq[i].comp_thresh =
init->r8.rrq[i].unused = 0;
}
/*
* Adapter Fibs are the first thing allocated so that they
* start page aligned
*/
dev->aif_base_va = (struct hw_fib *)base;
init->AdapterFibsVirtualAddress = 0;
init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys);
init->AdapterFibsSize = cpu_to_le32(fibsize);
init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib));
/*
* number of 4k pages of host physical memory. The aacraid fw needs
* this number to be less than 4gb worth of pages. New firmware doesn't
* have any issues with the mapping system, but older Firmware did, and
* had *troubles* dealing with the math overloading past 32 bits, thus
* we must limit this field.
*/
aac_max_hostphysmempages = dma_get_required_mask(&dev->pdev->dev) >> 12;
if (aac_max_hostphysmempages < AAC_MAX_HOSTPHYSMEMPAGES)
init->HostPhysMemPages = cpu_to_le32(aac_max_hostphysmempages);
else
init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
init->InitFlags = cpu_to_le32(INITFLAGS_DRIVER_USES_UTC_TIME |
INITFLAGS_DRIVER_SUPPORTS_PM);
init->MaxIoCommands = cpu_to_le32(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB);
init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
init->MaxFibSize = cpu_to_le32(dev->max_fib_size);
init->MaxNumAif = cpu_to_le32(dev->max_num_aif);
if (dev->comm_interface == AAC_COMM_MESSAGE) {
init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED);
dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n"));
} else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) {
init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_6);
init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED |
INITFLAGS_NEW_COMM_TYPE1_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED);
init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32));
init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff));
dprintk((KERN_WARNING"aacraid: New Comm Interface type1 enabled\n"));
} else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) {
init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_7);
init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED |
INITFLAGS_NEW_COMM_TYPE2_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED);
init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32));
init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff));
/* number of MSI-X */
init->Sa_MSIXVectors = cpu_to_le32(dev->max_msix);
dprintk((KERN_WARNING"aacraid: New Comm Interface type2 enabled\n"));
pr_warn("aacraid: Comm Interface type3 enabled\n");
} else {
init->r7.init_struct_revision =
cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION);
if (dev->max_fib_size != sizeof(struct hw_fib))
init->r7.init_struct_revision =
cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4);
init->r7.no_of_msix_vectors = cpu_to_le32(SA_MINIPORT_REVISION);
init->r7.fsrev = cpu_to_le32(dev->fsrev);
/*
* Adapter Fibs are the first thing allocated so that they
* start page aligned
*/
dev->aif_base_va = (struct hw_fib *)base;
init->r7.adapter_fibs_virtual_address = 0;
init->r7.adapter_fibs_physical_address = cpu_to_le32((u32)phys);
init->r7.adapter_fibs_size = cpu_to_le32(fibsize);
init->r7.adapter_fib_align = cpu_to_le32(sizeof(struct hw_fib));
/*
* number of 4k pages of host physical memory. The aacraid fw
* needs this number to be less than 4gb worth of pages. New
* firmware doesn't have any issues with the mapping system, but
* older Firmware did, and had *troubles* dealing with the math
* overloading past 32 bits, thus we must limit this field.
*/
aac_max_hostphysmempages =
dma_get_required_mask(&dev->pdev->dev) >> 12;
if (aac_max_hostphysmempages < AAC_MAX_HOSTPHYSMEMPAGES)
init->r7.host_phys_mem_pages =
cpu_to_le32(aac_max_hostphysmempages);
else
init->r7.host_phys_mem_pages =
cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
init->r7.init_flags =
cpu_to_le32(INITFLAGS_DRIVER_USES_UTC_TIME |
INITFLAGS_DRIVER_SUPPORTS_PM);
init->r7.max_io_commands =
cpu_to_le32(dev->scsi_host_ptr->can_queue +
AAC_NUM_MGT_FIB);
init->r7.max_io_size =
cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
init->r7.max_fib_size = cpu_to_le32(dev->max_fib_size);
init->r7.max_num_aif = cpu_to_le32(dev->max_num_aif);
if (dev->comm_interface == AAC_COMM_MESSAGE) {
init->r7.init_flags |=
cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED);
pr_warn("aacraid: Comm Interface enabled\n");
} else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) {
init->r7.init_struct_revision =
cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_6);
init->r7.init_flags |=
cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED |
INITFLAGS_NEW_COMM_TYPE1_SUPPORTED |
INITFLAGS_FAST_JBOD_SUPPORTED);
init->r7.host_rrq_addr_high =
cpu_to_le32(upper_32_bits(dev->host_rrq_pa));
init->r7.host_rrq_addr_low =
cpu_to_le32(lower_32_bits(dev->host_rrq_pa));
pr_warn("aacraid: Comm Interface type1 enabled\n");
} else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) {
init->r7.init_struct_revision =
cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_7);
init->r7.init_flags |=
cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED |
INITFLAGS_NEW_COMM_TYPE2_SUPPORTED |
INITFLAGS_FAST_JBOD_SUPPORTED);
init->r7.host_rrq_addr_high =
cpu_to_le32(upper_32_bits(dev->host_rrq_pa));
init->r7.host_rrq_addr_low =
cpu_to_le32(lower_32_bits(dev->host_rrq_pa));
init->r7.no_of_msix_vectors =
cpu_to_le32(dev->max_msix);
/* must be the COMM_PREFERRED_SETTINGS values */
pr_warn("aacraid: Comm Interface type2 enabled\n");
}
}
/*
* Increment the base address by the amount already used
*/
base = base + fibsize + host_rrq_size + sizeof(struct aac_init);
base = base + fibsize + host_rrq_size + aac_init_size;
phys = (dma_addr_t)((ulong)phys + fibsize + host_rrq_size +
sizeof(struct aac_init));
aac_init_size);
/*
* Align the beginning of Headers to commalign
......@@ -181,7 +253,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
* Fill in addresses of the Comm Area Headers and Queues
*/
*commaddr = base;
init->CommHeaderAddress = cpu_to_le32((u32)phys);
if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE3)
init->r7.comm_header_address = cpu_to_le32((u32)phys);
/*
* Increment the base address by the size of the CommArea
*/
......@@ -191,12 +264,14 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
* Place the Printf buffer area after the Fast I/O comm area.
*/
dev->printfbuf = (void *)base;
init->printfbuf = cpu_to_le32(phys);
init->printfbufsiz = cpu_to_le32(printfbufsiz);
if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE3) {
init->r7.printfbuf = cpu_to_le32(phys);
init->r7.printfbufsiz = cpu_to_le32(printfbufsiz);
}
memset(base, 0, printfbufsiz);
return 1;
}
static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, int qsize)
{
atomic_set(&q->numpending, 0);
......@@ -404,9 +479,13 @@ void aac_define_int_mode(struct aac_dev *dev)
if (dev->max_msix > msi_count)
dev->max_msix = msi_count;
}
dev->vector_cap =
(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) /
msi_count;
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE3 && dev->sa_firmware)
dev->vector_cap = dev->scsi_host_ptr->can_queue +
AAC_NUM_MGT_FIB;
else
dev->vector_cap = (dev->scsi_host_ptr->can_queue +
AAC_NUM_MGT_FIB) / msi_count;
}
struct aac_dev *aac_init_adapter(struct aac_dev *dev)
{
......@@ -440,30 +519,37 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
0, 0, 0, 0, 0, 0,
status+0, status+1, status+2, status+3, NULL)) &&
(status[0] == 0x00000001)) {
status+0, status+1, status+2, status+3, status+4)) &&
(status[0] == 0x00000001)) {
dev->doorbell_mask = status[3];
if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64))
if (status[1] & AAC_OPT_NEW_COMM_64)
dev->raw_io_64 = 1;
dev->sync_mode = aac_sync_mode;
if (dev->a_ops.adapter_comm &&
(status[1] & le32_to_cpu(AAC_OPT_NEW_COMM))) {
(status[1] & AAC_OPT_NEW_COMM)) {
dev->comm_interface = AAC_COMM_MESSAGE;
dev->raw_io_interface = 1;
if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE1))) {
if ((status[1] & AAC_OPT_NEW_COMM_TYPE1)) {
/* driver supports TYPE1 (Tupelo) */
dev->comm_interface = AAC_COMM_MESSAGE_TYPE1;
} else if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE2))) {
/* driver supports TYPE2 (Denali) */
} else if (status[1] & AAC_OPT_NEW_COMM_TYPE2) {
/* driver supports TYPE2 (Denali, Yosemite) */
dev->comm_interface = AAC_COMM_MESSAGE_TYPE2;
} else if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE4)) ||
(status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE3))) {
/* driver doesn't TYPE3 and TYPE4 */
/* switch to sync. mode */
} else if (status[1] & AAC_OPT_NEW_COMM_TYPE3) {
/* driver supports TYPE3 (Yosemite, Thor) */
dev->comm_interface = AAC_COMM_MESSAGE_TYPE3;
} else if (status[1] & AAC_OPT_NEW_COMM_TYPE4) {
/* not supported TYPE - switch to sync. mode */
dev->comm_interface = AAC_COMM_MESSAGE_TYPE2;
dev->sync_mode = 1;
}
}
if ((status[1] & le32_to_cpu(AAC_OPT_EXTENDED)) &&
(status[4] & le32_to_cpu(AAC_EXTOPT_SA_FIRMWARE)))
dev->sa_firmware = 1;
else
dev->sa_firmware = 0;
if ((dev->comm_interface == AAC_COMM_MESSAGE) &&
(status[2] > dev->base_size)) {
aac_adapter_ioremap(dev, 0);
......@@ -500,61 +586,25 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
dev->sg_tablesize = status[2] & 0xFFFF;
if (dev->pdev->device == PMC_DEVICE_S7 ||
dev->pdev->device == PMC_DEVICE_S8 ||
dev->pdev->device == PMC_DEVICE_S9)
host->can_queue = ((status[3] >> 16) ? (status[3] >> 16) :
(status[3] & 0xFFFF)) - AAC_NUM_MGT_FIB;
else
host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB;
dev->pdev->device == PMC_DEVICE_S9) {
if (host->can_queue > (status[3] >> 16) -
AAC_NUM_MGT_FIB)
host->can_queue = (status[3] >> 16) -
AAC_NUM_MGT_FIB;
} else if (host->can_queue > (status[3] & 0xFFFF) -
AAC_NUM_MGT_FIB)
host->can_queue = (status[3] & 0xFFFF) -
AAC_NUM_MGT_FIB;
dev->max_num_aif = status[4] & 0xFFFF;
/*
* NOTE:
* All these overrides are based on a fixed internal
* knowledge and understanding of existing adapters,
* acbsize should be set with caution.
*/
if (acbsize == 512) {
host->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
dev->max_fib_size = 512;
dev->sg_tablesize = host->sg_tablesize
= (512 - sizeof(struct aac_fibhdr)
- sizeof(struct aac_write) + sizeof(struct sgentry))
/ sizeof(struct sgentry);
host->can_queue = AAC_NUM_IO_FIB;
} else if (acbsize == 2048) {
host->max_sectors = 512;
dev->max_fib_size = 2048;
host->sg_tablesize = 65;
dev->sg_tablesize = 81;
host->can_queue = 512 - AAC_NUM_MGT_FIB;
} else if (acbsize == 4096) {
host->max_sectors = 1024;
dev->max_fib_size = 4096;
host->sg_tablesize = 129;
dev->sg_tablesize = 166;
host->can_queue = 256 - AAC_NUM_MGT_FIB;
} else if (acbsize == 8192) {
host->max_sectors = 2048;
dev->max_fib_size = 8192;
host->sg_tablesize = 257;
dev->sg_tablesize = 337;
host->can_queue = 128 - AAC_NUM_MGT_FIB;
} else if (acbsize > 0) {
printk("Illegal acbsize=%d ignored\n", acbsize);
}
}
{
if (numacb > 0) {
if (numacb < host->can_queue)
host->can_queue = numacb;
else
printk("numacb=%d ignored\n", numacb);
}
if (numacb > 0) {
if (numacb < host->can_queue)
host->can_queue = numacb;
else
pr_warn("numacb=%d ignored\n", numacb);
}
if (host->can_queue > AAC_NUM_IO_FIB)
host->can_queue = AAC_NUM_IO_FIB;
if (dev->pdev->device == PMC_DEVICE_S6 ||
dev->pdev->device == PMC_DEVICE_S7 ||
dev->pdev->device == PMC_DEVICE_S8 ||
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -5,7 +5,8 @@
* Adaptec aacraid device driver for Linux.
*
* Copyright (c) 2000-2010 Adaptec, Inc.
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
* 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
* 2016-2017 Microsemi Corp. (aacraid@microsemi.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......
......@@ -6,7 +6,8 @@
* Adaptec aacraid device driver for Linux.
*
* Copyright (c) 2000-2010 Adaptec, Inc.
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
* 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
* 2016-2017 Microsemi Corp. (aacraid@microsemi.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -60,7 +61,7 @@ static int aac_rkt_select_comm(struct aac_dev *dev, int comm)
* case warrants this half baked, but convenient, check here.
*/
if (dev->scsi_host_ptr->can_queue > AAC_NUM_IO_FIB_RKT) {
dev->init->MaxIoCommands =
dev->init->r7.max_io_commands =
cpu_to_le32(AAC_NUM_IO_FIB_RKT + AAC_NUM_MGT_FIB);
dev->scsi_host_ptr->can_queue = AAC_NUM_IO_FIB_RKT;
}
......
......@@ -6,7 +6,8 @@
* Adaptec aacraid device driver for Linux.
*
* Copyright (c) 2000-2010 Adaptec, Inc.
* 2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
* 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
* 2016-2017 Microsemi Corp. (aacraid@microsemi.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -315,10 +316,10 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
static void aac_rx_start_adapter(struct aac_dev *dev)
{
struct aac_init *init;
union aac_init *init;
init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds());
init->r7.host_elapsed_seconds = cpu_to_le32(get_seconds());
// We can only use a 32 bit address here
rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
......@@ -470,7 +471,7 @@ static int aac_rx_ioremap(struct aac_dev * dev, u32 size)
return 0;
}
static int aac_rx_restart_adapter(struct aac_dev *dev, int bled)
static int aac_rx_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type)
{
u32 var = 0;
......@@ -559,7 +560,7 @@ int _aac_rx_init(struct aac_dev *dev)
dev->a_ops.adapter_enable_int = aac_rx_disable_interrupt;
dev->OIMR = status = rx_readb (dev, MUnit.OIMR);
if ((((status & 0x0c) != 0x0c) || aac_reset_devices || reset_devices) &&
!aac_rx_restart_adapter(dev, 0))
!aac_rx_restart_adapter(dev, 0, IOP_HWSOFT_RESET))
/* Make sure the Hardware FIFO is empty */
while ((++restart < 512) &&
(rx_readl(dev, MUnit.OutboundQueue) != 0xFFFFFFFFL));
......@@ -568,7 +569,8 @@ int _aac_rx_init(struct aac_dev *dev)
*/
status = rx_readl(dev, MUnit.OMRx[0]);
if (status & KERNEL_PANIC) {
if (aac_rx_restart_adapter(dev, aac_rx_check_health(dev)))
if (aac_rx_restart_adapter(dev,
aac_rx_check_health(dev), IOP_HWSOFT_RESET))
goto error_iounmap;
++restart;
}
......@@ -606,7 +608,8 @@ int _aac_rx_init(struct aac_dev *dev)
((startup_timeout > 60)
? (startup_timeout - 60)
: (startup_timeout / 2))))) {
if (likely(!aac_rx_restart_adapter(dev, aac_rx_check_health(dev))))
if (likely(!aac_rx_restart_adapter(dev,
aac_rx_check_health(dev), IOP_HWSOFT_RESET)))
start = jiffies;
++restart;
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -84,7 +84,6 @@ static inline void queue_tail_inc(struct be_queue_info *q)
/*ISCSI */
struct be_aic_obj { /* Adaptive interrupt coalescing (AIC) info */
bool enable;
u32 min_eqd; /* in usecs */
u32 max_eqd; /* in usecs */
u32 prev_eqd; /* in usecs */
......@@ -94,8 +93,6 @@ struct be_aic_obj { /* Adaptive interrupt coalescing (AIC) info */
};
struct be_eq_obj {
bool todo_mcc_cq;
bool todo_cq;
u32 cq_count;
struct be_queue_info q;
struct beiscsi_hba *phba;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -2947,6 +2947,7 @@ static struct scsi_host_template bnx2fc_shost_template = {
.module = THIS_MODULE,
.name = "QLogic Offload FCoE Initiator",
.queuecommand = bnx2fc_queuecommand,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = bnx2fc_eh_abort, /* abts */
.eh_device_reset_handler = bnx2fc_eh_device_reset, /* lun reset */
.eh_target_reset_handler = bnx2fc_eh_target_reset, /* tgt reset */
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册