SCSI misc on 20170220

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.
 
 Signed-off-by: James E.J. Bottomley <jejb@linux.vnet.ibm.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABAgAGBQJYq5adAAoJEAVr7HOZEZN4bjUP/Atk7CSZVnC75pcYmncbEGCx
 ysOlEHK4uW2HhiAYk3PlYMk+pKrMHet2zsbbM9PHJfopdOHZ7Sq1+UZZVeqE1Zun
 8pe0NhON+fZx7XAnevdEvnSSULQZ+AGfjZO72iUwkJiN3ozYaFtCITOyn49l4GpR
 ra9emskBh7CQOFW2voGn1AKeDijPYGx3+TO4AUrWjVMiByR06gb1bmImx+ljiUrs
 jzRJPfrt90ORcTdpMateyN2EXxudcASMhX03SJ6fRI84hPAhMCROMbTv8RnzOTE4
 DPbnvbYUowlHt43iUhJHSwGdkRRaRBnkzQENBp1fNrNzZgF6vB7+kShxbonrYB2p
 gC4ewaJr0BNj+HsUnvTpe3WseiPOcfsnBsKilPLKBlm2dCKEXqFox/dj/T1uexxg
 HoyFrl3u8fyEqVHrzRS4M9t/njWh0NFmXxb0wBdj+lkVFTRErGSKQ8SfOqshuSGs
 P8NN88jy8vC7uqgzKBJ+UH3ehzn3qfBxasFHIC/e2awY9FqKjHGTxKMmSVpjXVxy
 wCvE2FQ3k/qEj2XSM6f7/NGytlSOlju5q1rFtHPW2M+TFSh0LJWCnmVjR/Zle9em
 pBWmtIgCv8W5b41zL2H94nLWAZbfdrrNU/XnX88l47LKnmorte/PGhpxu36NEsMS
 VCgreQmFMdMRY+WzDWl1
 =cBQx
 -----END PGP SIGNATURE-----

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
  ...
This commit is contained in:
Linus Torvalds 2017-02-21 11:51:42 -08:00
commit cdc194705d
129 changed files with 9312 additions and 3946 deletions

View File

@ -549,6 +549,7 @@ enum blk_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
DPRINTK("EXIT, ret=%d\n", ret); DPRINTK("EXIT, ret=%d\n", ret);
return ret; return ret;
} }
EXPORT_SYMBOL(ata_scsi_timed_out);
static void ata_eh_unload(struct ata_port *ap) static void ata_eh_unload(struct ata_port *ap)
{ {

View File

@ -716,7 +716,6 @@ struct scsi_transport_template *ata_attach_transport(void)
return NULL; return NULL;
i->t.eh_strategy_handler = ata_scsi_error; 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.user_scan = ata_scsi_user_scan;
i->t.host_attrs.ac.attrs = &i->port_attrs[0]; i->t.host_attrs.ac.attrs = &i->port_attrs[0];

View File

@ -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_internal_cmd_timed_out(struct ata_device *dev, u8 cmd);
extern void ata_eh_acquire(struct ata_port *ap); extern void ata_eh_acquire(struct ata_port *ap);
extern void ata_eh_release(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_scsi_error(struct Scsi_Host *host);
extern void ata_eh_fastdrain_timerfn(unsigned long arg); extern void ata_eh_fastdrain_timerfn(unsigned long arg);
extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc); extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);

View File

@ -400,27 +400,27 @@ static bool SA5_performant_intr_pending(ctlr_info_t *h)
} }
static struct access_method SA5_access = { static struct access_method SA5_access = {
SA5_submit_command, .submit_command = SA5_submit_command,
SA5_intr_mask, .set_intr_mask = SA5_intr_mask,
SA5_fifo_full, .fifo_full = SA5_fifo_full,
SA5_intr_pending, .intr_pending = SA5_intr_pending,
SA5_completed, .command_completed = SA5_completed,
}; };
static struct access_method SA5B_access = { static struct access_method SA5B_access = {
SA5_submit_command, .submit_command = SA5_submit_command,
SA5B_intr_mask, .set_intr_mask = SA5B_intr_mask,
SA5_fifo_full, .fifo_full = SA5_fifo_full,
SA5B_intr_pending, .intr_pending = SA5B_intr_pending,
SA5_completed, .command_completed = SA5_completed,
}; };
static struct access_method SA5_performant_access = { static struct access_method SA5_performant_access = {
SA5_submit_command, .submit_command = SA5_submit_command,
SA5_performant_intr_mask, .set_intr_mask = SA5_performant_intr_mask,
SA5_fifo_full, .fifo_full = SA5_fifo_full,
SA5_performant_intr_pending, .intr_pending = SA5_performant_intr_pending,
SA5_performant_completed, .command_completed = SA5_performant_completed,
}; };
struct board_type { struct board_type {

View File

@ -994,6 +994,7 @@ static struct scsi_host_template iscsi_iser_sht = {
.change_queue_depth = scsi_change_queue_depth, .change_queue_depth = scsi_change_queue_depth,
.sg_tablesize = ISCSI_ISER_DEF_SG_TABLESIZE, .sg_tablesize = ISCSI_ISER_DEF_SG_TABLESIZE,
.cmd_per_lun = ISER_DEF_CMD_PER_LUN, .cmd_per_lun = ISER_DEF_CMD_PER_LUN,
.eh_timed_out = iscsi_eh_cmd_timed_out,
.eh_abort_handler = iscsi_eh_abort, .eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler= iscsi_eh_device_reset, .eh_device_reset_handler= iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_recover_target, .eh_target_reset_handler = iscsi_eh_recover_target,

View File

@ -2869,6 +2869,7 @@ static struct scsi_host_template srp_template = {
.info = srp_target_info, .info = srp_target_info,
.queuecommand = srp_queuecommand, .queuecommand = srp_queuecommand,
.change_queue_depth = srp_change_queue_depth, .change_queue_depth = srp_change_queue_depth,
.eh_timed_out = srp_timed_out,
.eh_abort_handler = srp_abort, .eh_abort_handler = srp_abort,
.eh_device_reset_handler = srp_reset_device, .eh_device_reset_handler = srp_reset_device,
.eh_host_reset_handler = srp_reset_host, .eh_host_reset_handler = srp_reset_host,

View File

@ -119,6 +119,7 @@ static struct scsi_host_template mptfc_driver_template = {
.target_destroy = mptfc_target_destroy, .target_destroy = mptfc_target_destroy,
.slave_destroy = mptscsih_slave_destroy, .slave_destroy = mptscsih_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth, .change_queue_depth = mptscsih_change_queue_depth,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = mptfc_abort, .eh_abort_handler = mptfc_abort,
.eh_device_reset_handler = mptfc_dev_reset, .eh_device_reset_handler = mptfc_dev_reset,
.eh_bus_reset_handler = mptfc_bus_reset, .eh_bus_reset_handler = mptfc_bus_reset,

View File

@ -65,7 +65,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/delay.h> #include <linux/delay.h>

View File

@ -1983,6 +1983,7 @@ static struct scsi_host_template mptsas_driver_template = {
.target_destroy = mptsas_target_destroy, .target_destroy = mptsas_target_destroy,
.slave_destroy = mptscsih_slave_destroy, .slave_destroy = mptscsih_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth, .change_queue_depth = mptscsih_change_queue_depth,
.eh_timed_out = mptsas_eh_timed_out,
.eh_abort_handler = mptscsih_abort, .eh_abort_handler = mptscsih_abort,
.eh_device_reset_handler = mptscsih_dev_reset, .eh_device_reset_handler = mptscsih_dev_reset,
.eh_host_reset_handler = mptscsih_host_reset, .eh_host_reset_handler = mptscsih_host_reset,
@ -5398,7 +5399,6 @@ mptsas_init(void)
sas_attach_transport(&mptsas_transport_functions); sas_attach_transport(&mptsas_transport_functions);
if (!mptsas_transport_template) if (!mptsas_transport_template)
return -ENODEV; return -ENODEV;
mptsas_transport_template->eh_timed_out = mptsas_eh_timed_out;
mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER, mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER,
"mptscsih_io_done"); "mptscsih_io_done");

View File

@ -330,6 +330,7 @@ static struct scsi_host_template zfcp_scsi_host_template = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "zfcp", .name = "zfcp",
.queuecommand = zfcp_scsi_queuecommand, .queuecommand = zfcp_scsi_queuecommand,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = zfcp_scsi_eh_abort_handler, .eh_abort_handler = zfcp_scsi_eh_abort_handler,
.eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
.eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler, .eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler,

View File

@ -96,17 +96,6 @@
* of chips. To use it, you write an architecture specific functions * of chips. To use it, you write an architecture specific functions
* and macros and include this file in your driver. * 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 : * These macros MUST be defined :
* *
* NCR5380_read(register) - read from the specified register * NCR5380_read(register) - read from the specified register
@ -347,7 +336,7 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
#endif #endif
/** /**
* NCR58380_info - report driver and host information * NCR5380_info - report driver and host information
* @instance: relevant scsi host instance * @instance: relevant scsi host instance
* *
* For use as the host template info() handler. * For use as the host template info() handler.
@ -360,33 +349,6 @@ static const char *NCR5380_info(struct Scsi_Host *instance)
return hostdata->info; 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 * NCR5380_init - initialise an NCR5380
* @instance: adapter to configure * @instance: adapter to configure
@ -436,7 +398,14 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
if (!hostdata->work_q) if (!hostdata->work_q)
return -ENOMEM; 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(INITIATOR_COMMAND_REG, ICR_BASE);
NCR5380_write(MODE_REG, MR_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->unissued) &&
list_empty(&hostdata->autosense) && list_empty(&hostdata->autosense) &&
!hostdata->connected && !hostdata->connected &&
!hostdata->selecting) !hostdata->selecting) {
NCR5380_release_dma_irq(instance); 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, static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
struct scsi_cmnd *cmd) struct scsi_cmnd *cmd)
__releases(&hostdata->lock) __acquires(&hostdata->lock)
{ {
struct NCR5380_hostdata *hostdata = shost_priv(instance); struct NCR5380_hostdata *hostdata = shost_priv(instance);
unsigned char tmp[3], phase; unsigned char tmp[3], phase;
@ -1194,8 +1165,16 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
data = tmp; data = tmp;
phase = PHASE_MSGOUT; phase = PHASE_MSGOUT;
NCR5380_transfer_pio(instance, &phase, &len, &data); 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"); dsprintk(NDEBUG_SELECTION, instance, "nexus established.\n");
/* XXX need to handle errors here */
hostdata->connected = cmd; hostdata->connected = cmd;
hostdata->busy[cmd->device->id] |= 1 << cmd->device->lun; 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) static void NCR5380_information_transfer(struct Scsi_Host *instance)
__releases(&hostdata->lock) __acquires(&hostdata->lock)
{ {
struct NCR5380_hostdata *hostdata = shost_priv(instance); struct NCR5380_hostdata *hostdata = shost_priv(instance);
unsigned char msgout = NOP; unsigned char msgout = NOP;

View File

@ -81,11 +81,7 @@
#define ICR_ASSERT_ATN 0x02 /* rw Set to assert ATN */ #define ICR_ASSERT_ATN 0x02 /* rw Set to assert ATN */
#define ICR_ASSERT_DATA 0x01 /* rw SCSI_DATA_REG is asserted */ #define ICR_ASSERT_DATA 0x01 /* rw SCSI_DATA_REG is asserted */
#ifdef DIFFERENTIAL
#define ICR_BASE ICR_DIFF_ENABLE
#else
#define ICR_BASE 0 #define ICR_BASE 0
#endif
#define MODE_REG 2 #define MODE_REG 2
/* /*
@ -102,11 +98,7 @@
#define MR_DMA_MODE 0x02 /* rw DMA / pseudo DMA mode */ #define MR_DMA_MODE 0x02 /* rw DMA / pseudo DMA mode */
#define MR_ARBITRATE 0x01 /* rw start arbitration */ #define MR_ARBITRATE 0x01 /* rw start arbitration */
#ifdef PARITY
#define MR_BASE MR_ENABLE_PAR_CHECK
#else
#define MR_BASE 0 #define MR_BASE 0
#endif
#define TARGET_COMMAND_REG 3 #define TARGET_COMMAND_REG 3
#define TCR_LAST_BYTE_SENT 0x80 /* ro DMA done */ #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_SCSI_BUF_RDY 0x02 /* ro SCSI buffer read */
#define CSR_GATED_53C80_IRQ 0x01 /* ro Last block xferred */ #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 #define CSR_BASE CSR_53C80_INTR
#endif
/* Note : PHASE_* macros are based on the values of the STATUS register */ /* Note : PHASE_* macros are based on the values of the STATUS register */
#define PHASE_MASK (SR_MSG | SR_CD | SR_IO) #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 id_higher_mask; /* All bits above id_mask */
unsigned char last_message; /* Last Message Out */ unsigned char last_message; /* Last Message Out */
unsigned long region_size; /* Size of address/port range */ unsigned long region_size; /* Size of address/port range */
char info[256]; char info[168]; /* Host banner message */
}; };
#ifdef __KERNEL__
struct NCR5380_cmd { struct NCR5380_cmd {
struct list_head list; struct list_head list;
}; };
@ -331,5 +317,4 @@ static inline int NCR5380_dma_residual_none(struct NCR5380_hostdata *hostdata)
return 0; return 0;
} }
#endif /* __KERNEL__ */
#endif /* NCR5380_H */ #endif /* NCR5380_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,37 @@
/*
* Adaptec AAC series RAID controller driver
* (c) Copyright 2001 Red Hat Inc. <alan@redhat.com>
*
* based on the old aacraid driver that is..
* Adaptec aacraid device driver for Linux.
*
* Copyright (c) 2000-2010 Adaptec, Inc.
* 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
* 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; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Module Name:
* aacraid.h
*
* Abstract: Contains all routines for control of the aacraid driver
*
*/
#ifndef _AACRAID_H_
#define _AACRAID_H_
#ifndef dprintk #ifndef dprintk
# define dprintk(x) # define dprintk(x)
#endif #endif
@ -63,8 +97,8 @@ enum {
#define PMC_GLOBAL_INT_BIT0 0x00000001 #define PMC_GLOBAL_INT_BIT0 0x00000001
#ifndef AAC_DRIVER_BUILD #ifndef AAC_DRIVER_BUILD
# define AAC_DRIVER_BUILD 41066 # define AAC_DRIVER_BUILD 50740
# define AAC_DRIVER_BRANCH "-ms" # define AAC_DRIVER_BRANCH "-custom"
#endif #endif
#define MAXIMUM_NUM_CONTAINERS 32 #define MAXIMUM_NUM_CONTAINERS 32
@ -72,13 +106,311 @@ enum {
#define AAC_NUM_IO_FIB (1024 - AAC_NUM_MGT_FIB) #define AAC_NUM_IO_FIB (1024 - AAC_NUM_MGT_FIB)
#define AAC_NUM_FIB (AAC_NUM_IO_FIB + AAC_NUM_MGT_FIB) #define AAC_NUM_FIB (AAC_NUM_IO_FIB + AAC_NUM_MGT_FIB)
#define AAC_MAX_LUN (8) #define AAC_MAX_LUN 256
#define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff) #define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff)
#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)256) #define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)256)
#define AAC_DEBUG_INSTRUMENT_AIF_DELETE #define AAC_DEBUG_INSTRUMENT_AIF_DELETE
#define AAC_MAX_NATIVE_TARGETS 1024
/* Thor: 5 phys. buses: #0: empty, 1-4: 256 targets each */
#define AAC_MAX_BUSES 5
#define AAC_MAX_TARGETS 256
#define AAC_MAX_NATIVE_SIZE 2048
#define FW_ERROR_BUFFER_SIZE 512
/* Thor AIF events */
#define SA_AIF_HOTPLUG (1<<1)
#define SA_AIF_HARDWARE (1<<2)
#define SA_AIF_PDEV_CHANGE (1<<4)
#define SA_AIF_LDEV_CHANGE (1<<5)
#define SA_AIF_BPSTAT_CHANGE (1<<30)
#define SA_AIF_BPCFG_CHANGE (1<<31)
#define HBA_MAX_SG_EMBEDDED 28
#define HBA_MAX_SG_SEPARATE 90
#define HBA_SENSE_DATA_LEN_MAX 32
#define HBA_REQUEST_TAG_ERROR_FLAG 0x00000002
#define HBA_SGL_FLAGS_EXT 0x80000000UL
struct aac_hba_sgl {
u32 addr_lo; /* Lower 32-bits of SGL element address */
u32 addr_hi; /* Upper 32-bits of SGL element address */
u32 len; /* Length of SGL element in bytes */
u32 flags; /* SGL element flags */
};
enum {
HBA_IU_TYPE_SCSI_CMD_REQ = 0x40,
HBA_IU_TYPE_SCSI_TM_REQ = 0x41,
HBA_IU_TYPE_SATA_REQ = 0x42,
HBA_IU_TYPE_RESP = 0x60,
HBA_IU_TYPE_COALESCED_RESP = 0x61,
HBA_IU_TYPE_INT_COALESCING_CFG_REQ = 0x70
};
enum {
HBA_CMD_BYTE1_DATA_DIR_IN = 0x1,
HBA_CMD_BYTE1_DATA_DIR_OUT = 0x2,
HBA_CMD_BYTE1_DATA_TYPE_DDR = 0x4,
HBA_CMD_BYTE1_CRYPTO_ENABLE = 0x8
};
enum {
HBA_CMD_BYTE1_BITOFF_DATA_DIR_IN = 0x0,
HBA_CMD_BYTE1_BITOFF_DATA_DIR_OUT,
HBA_CMD_BYTE1_BITOFF_DATA_TYPE_DDR,
HBA_CMD_BYTE1_BITOFF_CRYPTO_ENABLE
};
enum {
HBA_RESP_DATAPRES_NO_DATA = 0x0,
HBA_RESP_DATAPRES_RESPONSE_DATA,
HBA_RESP_DATAPRES_SENSE_DATA
};
enum {
HBA_RESP_SVCRES_TASK_COMPLETE = 0x0,
HBA_RESP_SVCRES_FAILURE,
HBA_RESP_SVCRES_TMF_COMPLETE,
HBA_RESP_SVCRES_TMF_SUCCEEDED,
HBA_RESP_SVCRES_TMF_REJECTED,
HBA_RESP_SVCRES_TMF_LUN_INVALID
};
enum {
HBA_RESP_STAT_IO_ERROR = 0x1,
HBA_RESP_STAT_IO_ABORTED,
HBA_RESP_STAT_NO_PATH_TO_DEVICE,
HBA_RESP_STAT_INVALID_DEVICE,
HBA_RESP_STAT_HBAMODE_DISABLED = 0xE,
HBA_RESP_STAT_UNDERRUN = 0x51,
HBA_RESP_STAT_OVERRUN = 0x75
};
struct aac_hba_cmd_req {
u8 iu_type; /* HBA information unit type */
/*
* byte1:
* [1:0] DIR - 0=No data, 0x1 = IN, 0x2 = OUT
* [2] TYPE - 0=PCI, 1=DDR
* [3] CRYPTO_ENABLE - 0=Crypto disabled, 1=Crypto enabled
*/
u8 byte1;
u8 reply_qid; /* Host reply queue to post response to */
u8 reserved1;
__le32 it_nexus; /* Device handle for the request */
__le32 request_id; /* Sender context */
/* Lower 32-bits of tweak value for crypto enabled IOs */
__le32 tweak_value_lo;
u8 cdb[16]; /* SCSI CDB of the command */
u8 lun[8]; /* SCSI LUN of the command */
/* Total data length in bytes to be read/written (if any) */
__le32 data_length;
/* [2:0] Task Attribute, [6:3] Command Priority */
u8 attr_prio;
/* Number of SGL elements embedded in the HBA req */
u8 emb_data_desc_count;
__le16 dek_index; /* DEK index for crypto enabled IOs */
/* Lower 32-bits of reserved error data target location on the host */
__le32 error_ptr_lo;
/* Upper 32-bits of reserved error data target location on the host */
__le32 error_ptr_hi;
/* Length of reserved error data area on the host in bytes */
__le32 error_length;
/* Upper 32-bits of tweak value for crypto enabled IOs */
__le32 tweak_value_hi;
struct aac_hba_sgl sge[HBA_MAX_SG_SEPARATE+2]; /* SG list space */
/*
* structure must not exceed
* AAC_MAX_NATIVE_SIZE-FW_ERROR_BUFFER_SIZE
*/
};
/* Task Management Functions (TMF) */
#define HBA_TMF_ABORT_TASK 0x01
#define HBA_TMF_LUN_RESET 0x08
struct aac_hba_tm_req {
u8 iu_type; /* HBA information unit type */
u8 reply_qid; /* Host reply queue to post response to */
u8 tmf; /* Task management function */
u8 reserved1;
__le32 it_nexus; /* Device handle for the command */
u8 lun[8]; /* SCSI LUN */
/* Used to hold sender context. */
__le32 request_id; /* Sender context */
__le32 reserved2;
/* Request identifier of managed task */
__le32 managed_request_id; /* Sender context being managed */
__le32 reserved3;
/* Lower 32-bits of reserved error data target location on the host */
__le32 error_ptr_lo;
/* Upper 32-bits of reserved error data target location on the host */
__le32 error_ptr_hi;
/* Length of reserved error data area on the host in bytes */
__le32 error_length;
};
struct aac_hba_reset_req {
u8 iu_type; /* HBA information unit type */
/* 0 - reset specified device, 1 - reset all devices */
u8 reset_type;
u8 reply_qid; /* Host reply queue to post response to */
u8 reserved1;
__le32 it_nexus; /* Device handle for the command */
__le32 request_id; /* Sender context */
/* Lower 32-bits of reserved error data target location on the host */
__le32 error_ptr_lo;
/* Upper 32-bits of reserved error data target location on the host */
__le32 error_ptr_hi;
/* Length of reserved error data area on the host in bytes */
__le32 error_length;
};
struct aac_hba_resp {
u8 iu_type; /* HBA information unit type */
u8 reserved1[3];
__le32 request_identifier; /* sender context */
__le32 reserved2;
u8 service_response; /* SCSI service response */
u8 status; /* SCSI status */
u8 datapres; /* [1:0] - data present, [7:2] - reserved */
u8 sense_response_data_len; /* Sense/response data length */
__le32 residual_count; /* Residual data length in bytes */
/* Sense/response data */
u8 sense_response_buf[HBA_SENSE_DATA_LEN_MAX];
};
struct aac_native_hba {
union {
struct aac_hba_cmd_req cmd;
struct aac_hba_tm_req tmr;
u8 cmd_bytes[AAC_MAX_NATIVE_SIZE-FW_ERROR_BUFFER_SIZE];
} cmd;
union {
struct aac_hba_resp err;
u8 resp_bytes[FW_ERROR_BUFFER_SIZE];
} resp;
};
#define CISS_REPORT_PHYSICAL_LUNS 0xc3
#define WRITE_HOST_WELLNESS 0xa5
#define CISS_IDENTIFY_PHYSICAL_DEVICE 0x15
#define BMIC_IN 0x26
#define BMIC_OUT 0x27
struct aac_ciss_phys_luns_resp {
u8 list_length[4]; /* LUN list length (N-7, big endian) */
u8 resp_flag; /* extended response_flag */
u8 reserved[3];
struct _ciss_lun {
u8 tid[3]; /* Target ID */
u8 bus; /* Bus, flag (bits 6,7) */
u8 level3[2];
u8 level2[2];
u8 node_ident[16]; /* phys. node identifier */
} lun[1]; /* List of phys. devices */
};
/*
* Interrupts
*/
#define AAC_MAX_HRRQ 64
struct aac_ciss_identify_pd {
u8 scsi_bus; /* SCSI Bus number on controller */
u8 scsi_id; /* SCSI ID on this bus */
u16 block_size; /* sector size in bytes */
u32 total_blocks; /* number for sectors on drive */
u32 reserved_blocks; /* controller reserved (RIS) */
u8 model[40]; /* Physical Drive Model */
u8 serial_number[40]; /* Drive Serial Number */
u8 firmware_revision[8]; /* drive firmware revision */
u8 scsi_inquiry_bits; /* inquiry byte 7 bits */
u8 compaq_drive_stamp; /* 0 means drive not stamped */
u8 last_failure_reason;
u8 flags;
u8 more_flags;
u8 scsi_lun; /* SCSI LUN for phys drive */
u8 yet_more_flags;
u8 even_more_flags;
u32 spi_speed_rules; /* SPI Speed :Ultra disable diagnose */
u8 phys_connector[2]; /* connector number on controller */
u8 phys_box_on_bus; /* phys enclosure this drive resides */
u8 phys_bay_in_box; /* phys drv bay this drive resides */
u32 rpm; /* Drive rotational speed in rpm */
u8 device_type; /* type of drive */
u8 sata_version; /* only valid when drive_type is SATA */
u64 big_total_block_count;
u64 ris_starting_lba;
u32 ris_size;
u8 wwid[20];
u8 controller_phy_map[32];
u16 phy_count;
u8 phy_connected_dev_type[256];
u8 phy_to_drive_bay_num[256];
u16 phy_to_attached_dev_index[256];
u8 box_index;
u8 spitfire_support;
u16 extra_physical_drive_flags;
u8 negotiated_link_rate[256];
u8 phy_to_phy_map[256];
u8 redundant_path_present_map;
u8 redundant_path_failure_map;
u8 active_path_number;
u16 alternate_paths_phys_connector[8];
u8 alternate_paths_phys_box_on_port[8];
u8 multi_lun_device_lun_count;
u8 minimum_good_fw_revision[8];
u8 unique_inquiry_bytes[20];
u8 current_temperature_degreesC;
u8 temperature_threshold_degreesC;
u8 max_temperature_degreesC;
u8 logical_blocks_per_phys_block_exp; /* phyblocksize = 512 * 2^exp */
u16 current_queue_depth_limit;
u8 switch_name[10];
u16 switch_port;
u8 alternate_paths_switch_name[40];
u8 alternate_paths_switch_port[8];
u16 power_on_hours; /* valid only if gas gauge supported */
u16 percent_endurance_used; /* valid only if gas gauge supported. */
u8 drive_authentication;
u8 smart_carrier_authentication;
u8 smart_carrier_app_fw_version;
u8 smart_carrier_bootloader_fw_version;
u8 SanitizeSecureEraseSupport;
u8 DriveKeyFlags;
u8 encryption_key_name[64];
u32 misc_drive_flags;
u16 dek_index;
u16 drive_encryption_flags;
u8 sanitize_maximum_time[6];
u8 connector_info_mode;
u8 connector_info_number[4];
u8 long_connector_name[64];
u8 device_unique_identifier[16];
u8 padto_2K[17];
} __packed;
/* /*
* These macros convert from physical channels to virtual channels * These macros convert from physical channels to virtual channels
*/ */
@ -86,6 +418,7 @@ enum {
#define CONTAINER_TO_CHANNEL(cont) (CONTAINER_CHANNEL) #define CONTAINER_TO_CHANNEL(cont) (CONTAINER_CHANNEL)
#define CONTAINER_TO_ID(cont) (cont) #define CONTAINER_TO_ID(cont) (cont)
#define CONTAINER_TO_LUN(cont) (0) #define CONTAINER_TO_LUN(cont) (0)
#define ENCLOSURE_CHANNEL (3)
#define PMC_DEVICE_S6 0x28b #define PMC_DEVICE_S6 0x28b
#define PMC_DEVICE_S7 0x28c #define PMC_DEVICE_S7 0x28c
@ -351,10 +684,10 @@ enum aac_queue_types {
/* transport FIB header (PMC) */ /* transport FIB header (PMC) */
struct aac_fib_xporthdr { struct aac_fib_xporthdr {
u64 HostAddress; /* FIB host address w/o xport header */ __le64 HostAddress; /* FIB host address w/o xport header */
u32 Size; /* FIB size excluding xport header */ __le32 Size; /* FIB size excluding xport header */
u32 Handle; /* driver handle to reference the FIB */ __le32 Handle; /* driver handle to reference the FIB */
u64 Reserved[2]; __le64 Reserved[2];
}; };
#define ALIGN32 32 #define ALIGN32 32
@ -379,7 +712,7 @@ struct aac_fibhdr {
__le32 SenderFibAddressHigh;/* upper 32bit of phys. FIB address */ __le32 SenderFibAddressHigh;/* upper 32bit of phys. FIB address */
__le32 TimeStamp; /* otherwise timestamp for FW internal use */ __le32 TimeStamp; /* otherwise timestamp for FW internal use */
} u; } u;
u32 Handle; /* FIB handle used for MSGU commnunication */ __le32 Handle; /* FIB handle used for MSGU commnunication */
u32 Previous; /* FW internal use */ u32 Previous; /* FW internal use */
u32 Next; /* FW internal use */ u32 Next; /* FW internal use */
}; };
@ -489,41 +822,64 @@ enum fib_xfer_state {
#define ADAPTER_INIT_STRUCT_REVISION_4 4 // rocket science #define ADAPTER_INIT_STRUCT_REVISION_4 4 // rocket science
#define ADAPTER_INIT_STRUCT_REVISION_6 6 /* PMC src */ #define ADAPTER_INIT_STRUCT_REVISION_6 6 /* PMC src */
#define ADAPTER_INIT_STRUCT_REVISION_7 7 /* Denali */ #define ADAPTER_INIT_STRUCT_REVISION_7 7 /* Denali */
#define ADAPTER_INIT_STRUCT_REVISION_8 8 // Thor
struct aac_init union aac_init
{ {
__le32 InitStructRevision; struct _r7 {
__le32 Sa_MSIXVectors; __le32 init_struct_revision;
__le32 fsrev; __le32 no_of_msix_vectors;
__le32 CommHeaderAddress; __le32 fsrev;
__le32 FastIoCommAreaAddress; __le32 comm_header_address;
__le32 AdapterFibsPhysicalAddress; __le32 fast_io_comm_area_address;
__le32 AdapterFibsVirtualAddress; __le32 adapter_fibs_physical_address;
__le32 AdapterFibsSize; __le32 adapter_fibs_virtual_address;
__le32 AdapterFibAlign; __le32 adapter_fibs_size;
__le32 printfbuf; __le32 adapter_fib_align;
__le32 printfbufsiz; __le32 printfbuf;
__le32 HostPhysMemPages; /* number of 4k pages of host __le32 printfbufsiz;
physical memory */ /* number of 4k pages of host phys. mem. */
__le32 HostElapsedSeconds; /* number of seconds since 1970. */ __le32 host_phys_mem_pages;
/* /* number of seconds since 1970. */
* ADAPTER_INIT_STRUCT_REVISION_4 begins here __le32 host_elapsed_seconds;
*/ /* ADAPTER_INIT_STRUCT_REVISION_4 begins here */
__le32 InitFlags; /* flags for supported features */ __le32 init_flags; /* flags for supported features */
#define INITFLAGS_NEW_COMM_SUPPORTED 0x00000001 #define INITFLAGS_NEW_COMM_SUPPORTED 0x00000001
#define INITFLAGS_DRIVER_USES_UTC_TIME 0x00000010 #define INITFLAGS_DRIVER_USES_UTC_TIME 0x00000010
#define INITFLAGS_DRIVER_SUPPORTS_PM 0x00000020 #define INITFLAGS_DRIVER_SUPPORTS_PM 0x00000020
#define INITFLAGS_NEW_COMM_TYPE1_SUPPORTED 0x00000040 #define INITFLAGS_NEW_COMM_TYPE1_SUPPORTED 0x00000040
#define INITFLAGS_FAST_JBOD_SUPPORTED 0x00000080 #define INITFLAGS_FAST_JBOD_SUPPORTED 0x00000080
#define INITFLAGS_NEW_COMM_TYPE2_SUPPORTED 0x00000100 #define INITFLAGS_NEW_COMM_TYPE2_SUPPORTED 0x00000100
__le32 MaxIoCommands; /* max outstanding commands */ #define INITFLAGS_DRIVER_SUPPORTS_HBA_MODE 0x00000400
__le32 MaxIoSize; /* largest I/O command */ __le32 max_io_commands; /* max outstanding commands */
__le32 MaxFibSize; /* largest FIB to adapter */ __le32 max_io_size; /* largest I/O command */
/* ADAPTER_INIT_STRUCT_REVISION_5 begins here */ __le32 max_fib_size; /* largest FIB to adapter */
__le32 MaxNumAif; /* max number of aif */ /* ADAPTER_INIT_STRUCT_REVISION_5 begins here */
/* ADAPTER_INIT_STRUCT_REVISION_6 begins here */ __le32 max_num_aif; /* max number of aif */
__le32 HostRRQ_AddrLow; /* ADAPTER_INIT_STRUCT_REVISION_6 begins here */
__le32 HostRRQ_AddrHigh; /* Host RRQ (response queue) for SRC */ /* Host RRQ (response queue) for SRC */
__le32 host_rrq_addr_low;
__le32 host_rrq_addr_high;
} r7;
struct _r8 {
/* ADAPTER_INIT_STRUCT_REVISION_8 */
__le32 init_struct_revision;
__le32 rr_queue_count;
__le32 host_elapsed_seconds; /* number of secs since 1970. */
__le32 init_flags;
__le32 max_io_size; /* largest I/O command */
__le32 max_num_aif; /* max number of aif */
__le32 reserved1;
__le32 reserved2;
struct _rrq {
__le32 host_addr_low;
__le32 host_addr_high;
__le16 msix_id;
__le16 element_count;
__le16 comp_thresh;
__le16 unused;
} rrq[1]; /* up to 64 RRQ addresses */
} r8;
}; };
enum aac_log_level { enum aac_log_level {
@ -554,7 +910,7 @@ struct adapter_ops
void (*adapter_enable_int)(struct aac_dev *dev); void (*adapter_enable_int)(struct aac_dev *dev);
int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4); int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
int (*adapter_check_health)(struct aac_dev *dev); int (*adapter_check_health)(struct aac_dev *dev);
int (*adapter_restart)(struct aac_dev *dev, int bled); int (*adapter_restart)(struct aac_dev *dev, int bled, u8 reset_type);
void (*adapter_start)(struct aac_dev *dev); void (*adapter_start)(struct aac_dev *dev);
/* Transport operations */ /* Transport operations */
int (*adapter_ioremap)(struct aac_dev * dev, u32 size); int (*adapter_ioremap)(struct aac_dev * dev, u32 size);
@ -727,6 +1083,7 @@ struct sa_registers {
#define SA_INIT_NUM_MSIXVECTORS 1 #define SA_INIT_NUM_MSIXVECTORS 1
#define SA_MINIPORT_REVISION SA_INIT_NUM_MSIXVECTORS
#define sa_readw(AEP, CSR) readl(&((AEP)->regs.sa->CSR)) #define sa_readw(AEP, CSR) readl(&((AEP)->regs.sa->CSR))
#define sa_readl(AEP, CSR) readl(&((AEP)->regs.sa->CSR)) #define sa_readl(AEP, CSR) readl(&((AEP)->regs.sa->CSR))
@ -820,32 +1177,37 @@ struct rkt_registers {
#define src_inbound rx_inbound #define src_inbound rx_inbound
struct src_mu_registers { struct src_mu_registers {
/* PCI*| Name */ /* PCI*| Name */
__le32 reserved0[6]; /* 00h | Reserved */ __le32 reserved0[6]; /* 00h | Reserved */
__le32 IOAR[2]; /* 18h | IOA->host interrupt register */ __le32 IOAR[2]; /* 18h | IOA->host interrupt register */
__le32 IDR; /* 20h | Inbound Doorbell Register */ __le32 IDR; /* 20h | Inbound Doorbell Register */
__le32 IISR; /* 24h | Inbound Int. Status Register */ __le32 IISR; /* 24h | Inbound Int. Status Register */
__le32 reserved1[3]; /* 28h | Reserved */ __le32 reserved1[3]; /* 28h | Reserved */
__le32 OIMR; /* 34h | Outbound Int. Mask Register */ __le32 OIMR; /* 34h | Outbound Int. Mask Register */
__le32 reserved2[25]; /* 38h | Reserved */ __le32 reserved2[25]; /* 38h | Reserved */
__le32 ODR_R; /* 9ch | Outbound Doorbell Read */ __le32 ODR_R; /* 9ch | Outbound Doorbell Read */
__le32 ODR_C; /* a0h | Outbound Doorbell Clear */ __le32 ODR_C; /* a0h | Outbound Doorbell Clear */
__le32 reserved3[6]; /* a4h | Reserved */ __le32 reserved3[3]; /* a4h | Reserved */
__le32 OMR; /* bch | Outbound Message Register */ __le32 SCR0; /* b0h | Scratchpad 0 */
__le32 reserved4[2]; /* b4h | Reserved */
__le32 OMR; /* bch | Outbound Message Register */
__le32 IQ_L; /* c0h | Inbound Queue (Low address) */ __le32 IQ_L; /* c0h | Inbound Queue (Low address) */
__le32 IQ_H; /* c4h | Inbound Queue (High address) */ __le32 IQ_H; /* c4h | Inbound Queue (High address) */
__le32 ODR_MSI; /* c8h | MSI register for sync./AIF */ __le32 ODR_MSI; /* c8h | MSI register for sync./AIF */
__le32 reserved5; /* cch | Reserved */
__le32 IQN_L; /* d0h | Inbound (native cmd) low */
__le32 IQN_H; /* d4h | Inbound (native cmd) high */
}; };
struct src_registers { struct src_registers {
struct src_mu_registers MUnit; /* 00h - cbh */ struct src_mu_registers MUnit; /* 00h - cbh */
union { union {
struct { struct {
__le32 reserved1[130789]; /* cch - 7fc5fh */ __le32 reserved1[130786]; /* d8h - 7fc5fh */
struct src_inbound IndexRegs; /* 7fc60h */ struct src_inbound IndexRegs; /* 7fc60h */
} tupelo; } tupelo;
struct { struct {
__le32 reserved1[973]; /* cch - fffh */ __le32 reserved1[970]; /* d8h - fffh */
struct src_inbound IndexRegs; /* 1000h */ struct src_inbound IndexRegs; /* 1000h */
} denali; } denali;
} u; } u;
@ -930,6 +1292,7 @@ struct fsa_dev_info {
char devname[8]; char devname[8];
struct sense_data sense_data; struct sense_data sense_data;
u32 block_size; u32 block_size;
u8 identifier[16];
}; };
struct fib { struct fib {
@ -958,8 +1321,30 @@ struct fib {
struct list_head fiblink; struct list_head fiblink;
void *data; void *data;
u32 vector_no; u32 vector_no;
struct hw_fib *hw_fib_va; /* Actual shared object */ struct hw_fib *hw_fib_va; /* also used for native */
dma_addr_t hw_fib_pa; /* physical address of hw_fib*/ dma_addr_t hw_fib_pa; /* physical address of hw_fib*/
dma_addr_t hw_sgl_pa; /* extra sgl for native */
dma_addr_t hw_error_pa; /* error buffer for native */
u32 hbacmd_size; /* cmd size for native */
};
#define AAC_INIT 0
#define AAC_RESCAN 1
#define AAC_DEVTYPE_RAID_MEMBER 1
#define AAC_DEVTYPE_ARC_RAW 2
#define AAC_DEVTYPE_NATIVE_RAW 3
#define AAC_EXPOSE_DISK 0
#define AAC_HIDE_DISK 3
struct aac_hba_map_info {
__le32 rmw_nexus; /* nexus for native HBA devices */
u8 devtype; /* device type */
u8 new_devtype;
u8 reset_state; /* 0 - no reset, 1..x - */
/* after xth TM LUN reset */
u16 qd_limit;
u8 expose; /*checks if to expose or not*/
}; };
/* /*
@ -1025,7 +1410,28 @@ struct aac_supplement_adapter_info
/* StructExpansion == 1 */ /* StructExpansion == 1 */
__le32 FeatureBits3; __le32 FeatureBits3;
__le32 SupportedPerformanceModes; __le32 SupportedPerformanceModes;
__le32 ReservedForFutureGrowth[80]; u8 HostBusType; /* uses HOST_BUS_TYPE_xxx defines */
u8 HostBusWidth; /* actual width in bits or links */
u16 HostBusSpeed; /* actual bus speed/link rate in MHz */
u8 MaxRRCDrives; /* max. number of ITP-RRC drives/pool */
u8 MaxDiskXtasks; /* max. possible num of DiskX Tasks */
u8 CpldVerLoaded;
u8 CpldVerInFlash;
__le64 MaxRRCCapacity;
__le32 CompiledMaxHistLogLevel;
u8 CustomBoardName[12];
u16 SupportedCntlrMode; /* identify supported controller mode */
u16 ReservedForFuture16;
__le32 SupportedOptions3; /* reserved for future options */
__le16 VirtDeviceBus; /* virt. SCSI device for Thor */
__le16 VirtDeviceTarget;
__le16 VirtDeviceLUN;
__le16 Unused;
__le32 ReservedForFutureGrowth[68];
}; };
#define AAC_FEATURE_FALCON cpu_to_le32(0x00000010) #define AAC_FEATURE_FALCON cpu_to_le32(0x00000010)
#define AAC_FEATURE_JBOD cpu_to_le32(0x08000000) #define AAC_FEATURE_JBOD cpu_to_le32(0x08000000)
@ -1099,11 +1505,21 @@ struct aac_bus_info_response {
#define AAC_OPT_SUPPLEMENT_ADAPTER_INFO cpu_to_le32(1<<16) #define AAC_OPT_SUPPLEMENT_ADAPTER_INFO cpu_to_le32(1<<16)
#define AAC_OPT_NEW_COMM cpu_to_le32(1<<17) #define AAC_OPT_NEW_COMM cpu_to_le32(1<<17)
#define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18) #define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18)
#define AAC_OPT_EXTENDED cpu_to_le32(1<<23)
#define AAC_OPT_NATIVE_HBA cpu_to_le32(1<<25)
#define AAC_OPT_NEW_COMM_TYPE1 cpu_to_le32(1<<28) #define AAC_OPT_NEW_COMM_TYPE1 cpu_to_le32(1<<28)
#define AAC_OPT_NEW_COMM_TYPE2 cpu_to_le32(1<<29) #define AAC_OPT_NEW_COMM_TYPE2 cpu_to_le32(1<<29)
#define AAC_OPT_NEW_COMM_TYPE3 cpu_to_le32(1<<30) #define AAC_OPT_NEW_COMM_TYPE3 cpu_to_le32(1<<30)
#define AAC_OPT_NEW_COMM_TYPE4 cpu_to_le32(1<<31) #define AAC_OPT_NEW_COMM_TYPE4 cpu_to_le32(1<<31)
#define AAC_COMM_PRODUCER 0
#define AAC_COMM_MESSAGE 1
#define AAC_COMM_MESSAGE_TYPE1 3
#define AAC_COMM_MESSAGE_TYPE2 4
#define AAC_COMM_MESSAGE_TYPE3 5
#define AAC_EXTOPT_SA_FIRMWARE cpu_to_le32(1<<1)
/* MSIX context */ /* MSIX context */
struct aac_msix_ctx { struct aac_msix_ctx {
int vector_no; int vector_no;
@ -1119,15 +1535,17 @@ struct aac_dev
/* /*
* negotiated FIB settings * negotiated FIB settings
*/ */
unsigned max_fib_size; unsigned int max_fib_size;
unsigned sg_tablesize; unsigned int sg_tablesize;
unsigned max_num_aif; unsigned int max_num_aif;
unsigned int max_cmd_size; /* max_fib_size or MAX_NATIVE */
/* /*
* Map for 128 fib objects (64k) * Map for 128 fib objects (64k)
*/ */
dma_addr_t hw_fib_pa; dma_addr_t hw_fib_pa; /* also used for native cmd */
struct hw_fib *hw_fib_va; struct hw_fib *hw_fib_va; /* also used for native cmd */
struct hw_fib *aif_base_va; struct hw_fib *aif_base_va;
/* /*
* Fib Headers * Fib Headers
@ -1157,21 +1575,23 @@ struct aac_dev
resource_size_t base_size, dbg_size; /* Size of resource_size_t base_size, dbg_size; /* Size of
* mapped in region */ * mapped in region */
/*
struct aac_init *init; /* Holds initialization info to communicate with adapter */ * Holds initialization info
* to communicate with adapter
*/
union aac_init *init;
dma_addr_t init_pa; /* Holds physical address of the init struct */ dma_addr_t init_pa; /* Holds physical address of the init struct */
/* response queue (if AAC_COMM_MESSAGE_TYPE1) */
u32 *host_rrq; /* response queue __le32 *host_rrq;
* if AAC_COMM_MESSAGE_TYPE1 */
dma_addr_t host_rrq_pa; /* phys. address */ dma_addr_t host_rrq_pa; /* phys. address */
/* index into rrq buffer */ /* index into rrq buffer */
u32 host_rrq_idx[AAC_MAX_MSIX]; u32 host_rrq_idx[AAC_MAX_MSIX];
atomic_t rrq_outstanding[AAC_MAX_MSIX]; atomic_t rrq_outstanding[AAC_MAX_MSIX];
u32 fibs_pushed_no; u32 fibs_pushed_no;
struct pci_dev *pdev; /* Our PCI interface */ struct pci_dev *pdev; /* Our PCI interface */
void * printfbuf; /* pointer to buffer used for printf's from the adapter */ /* pointer to buffer used for printf's from the adapter */
void * comm_addr; /* Base address of Comm area */ void *printfbuf;
void *comm_addr; /* Base address of Comm area */
dma_addr_t comm_phys; /* Physical Address of Comm area */ dma_addr_t comm_phys; /* Physical Address of Comm area */
size_t comm_size; size_t comm_size;
@ -1227,15 +1647,12 @@ struct aac_dev
u8 needs_dac; u8 needs_dac;
u8 raid_scsi_mode; u8 raid_scsi_mode;
u8 comm_interface; u8 comm_interface;
# define AAC_COMM_PRODUCER 0
# define AAC_COMM_MESSAGE 1
# define AAC_COMM_MESSAGE_TYPE1 3
# define AAC_COMM_MESSAGE_TYPE2 4
u8 raw_io_interface; u8 raw_io_interface;
u8 raw_io_64; u8 raw_io_64;
u8 printf_enabled; u8 printf_enabled;
u8 in_reset; u8 in_reset;
u8 msi; u8 msi;
u8 sa_firmware;
int management_fib_count; int management_fib_count;
spinlock_t manage_lock; spinlock_t manage_lock;
spinlock_t sync_lock; spinlock_t sync_lock;
@ -1246,7 +1663,10 @@ struct aac_dev
u32 max_msix; /* max. MSI-X vectors */ u32 max_msix; /* max. MSI-X vectors */
u32 vector_cap; /* MSI-X vector capab.*/ u32 vector_cap; /* MSI-X vector capab.*/
int msi_enabled; /* MSI/MSI-X enabled */ int msi_enabled; /* MSI/MSI-X enabled */
atomic_t msix_counter;
struct msix_entry msixentry[AAC_MAX_MSIX];
struct aac_msix_ctx aac_msix[AAC_MAX_MSIX]; /* context */ struct aac_msix_ctx aac_msix[AAC_MAX_MSIX]; /* context */
struct aac_hba_map_info hba_map[AAC_MAX_BUSES][AAC_MAX_TARGETS];
u8 adapter_shutdown; u8 adapter_shutdown;
u32 handle_pci_error; u32 handle_pci_error;
}; };
@ -1269,8 +1689,8 @@ struct aac_dev
#define aac_adapter_check_health(dev) \ #define aac_adapter_check_health(dev) \
(dev)->a_ops.adapter_check_health(dev) (dev)->a_ops.adapter_check_health(dev)
#define aac_adapter_restart(dev,bled) \ #define aac_adapter_restart(dev, bled, reset_type) \
(dev)->a_ops.adapter_restart(dev,bled) ((dev)->a_ops.adapter_restart(dev, bled, reset_type))
#define aac_adapter_start(dev) \ #define aac_adapter_start(dev) \
((dev)->a_ops.adapter_start(dev)) ((dev)->a_ops.adapter_start(dev))
@ -1300,6 +1720,8 @@ struct aac_dev
#define FIB_CONTEXT_FLAG (0x00000002) #define FIB_CONTEXT_FLAG (0x00000002)
#define FIB_CONTEXT_FLAG_WAIT (0x00000004) #define FIB_CONTEXT_FLAG_WAIT (0x00000004)
#define FIB_CONTEXT_FLAG_FASTRESP (0x00000008) #define FIB_CONTEXT_FLAG_FASTRESP (0x00000008)
#define FIB_CONTEXT_FLAG_NATIVE_HBA (0x00000010)
#define FIB_CONTEXT_FLAG_NATIVE_HBA_TMF (0x00000020)
/* /*
* Define the command values * Define the command values
@ -1358,6 +1780,7 @@ struct aac_dev
#define ST_IO 5 #define ST_IO 5
#define ST_NXIO 6 #define ST_NXIO 6
#define ST_E2BIG 7 #define ST_E2BIG 7
#define ST_MEDERR 8
#define ST_ACCES 13 #define ST_ACCES 13
#define ST_EXIST 17 #define ST_EXIST 17
#define ST_XDEV 18 #define ST_XDEV 18
@ -1715,6 +2138,8 @@ struct aac_fsinfo {
struct aac_blockdevinfo { struct aac_blockdevinfo {
__le32 block_size; __le32 block_size;
__le32 logical_phys_map;
u8 identifier[16];
}; };
union aac_contentinfo { union aac_contentinfo {
@ -1940,6 +2365,15 @@ struct revision
#define FSACTL_FORCE_DELETE_DISK CTL_CODE(2120, METHOD_NEITHER) #define FSACTL_FORCE_DELETE_DISK CTL_CODE(2120, METHOD_NEITHER)
#define FSACTL_GET_CONTAINERS 2131 #define FSACTL_GET_CONTAINERS 2131
#define FSACTL_SEND_LARGE_FIB CTL_CODE(2138, METHOD_BUFFERED) #define FSACTL_SEND_LARGE_FIB CTL_CODE(2138, METHOD_BUFFERED)
#define FSACTL_RESET_IOP CTL_CODE(2140, METHOD_BUFFERED)
#define FSACTL_GET_HBA_INFO CTL_CODE(2150, METHOD_BUFFERED)
/* flags defined for IOP & HW SOFT RESET */
#define HW_IOP_RESET 0x01
#define HW_SOFT_RESET 0x02
#define IOP_HWSOFT_RESET (HW_IOP_RESET | HW_SOFT_RESET)
/* HW Soft Reset register offset */
#define IBW_SWR_OFFSET 0x4000
#define SOFT_RESET_TIME 60
struct aac_common struct aac_common
@ -1958,6 +2392,8 @@ struct aac_common
#ifdef DBG #ifdef DBG
u32 FibsSent; u32 FibsSent;
u32 FibRecved; u32 FibRecved;
u32 NativeSent;
u32 NativeRecved;
u32 NoResponseSent; u32 NoResponseSent;
u32 NoResponseRecved; u32 NoResponseRecved;
u32 AsyncSent; u32 AsyncSent;
@ -1969,6 +2405,56 @@ struct aac_common
extern struct aac_common aac_config; extern struct aac_common aac_config;
/*
* This is for management ioctl purpose only.
*/
struct aac_hba_info {
u8 driver_name[50];
u8 adapter_number;
u8 system_io_bus_number;
u8 device_number;
u32 function_number;
u32 vendor_id;
u32 device_id;
u32 sub_vendor_id;
u32 sub_system_id;
u32 mapped_base_address_size;
u32 base_physical_address_high_part;
u32 base_physical_address_low_part;
u32 max_command_size;
u32 max_fib_size;
u32 max_scatter_gather_from_os;
u32 max_scatter_gather_to_fw;
u32 max_outstanding_fibs;
u32 queue_start_threshold;
u32 queue_dump_threshold;
u32 max_io_size_queued;
u32 outstanding_io;
u32 firmware_build_number;
u32 bios_build_number;
u32 driver_build_number;
u32 serial_number_high_part;
u32 serial_number_low_part;
u32 supported_options;
u32 feature_bits;
u32 currentnumber_ports;
u8 new_comm_interface:1;
u8 new_commands_supported:1;
u8 disable_passthrough:1;
u8 expose_non_dasd:1;
u8 queue_allowed:1;
u8 bled_check_enabled:1;
u8 reserved1:1;
u8 reserted2:1;
u32 reserved3[10];
};
/* /*
* The following macro is used when sending and receiving FIBs. It is * The following macro is used when sending and receiving FIBs. It is
@ -2096,9 +2582,10 @@ extern struct aac_common aac_config;
/* PMC NEW COMM: Request the event data */ /* PMC NEW COMM: Request the event data */
#define AifReqEvent 200 #define AifReqEvent 200
#define AifRawDeviceRemove 203 /* RAW device deleted */
#define AifNativeDeviceAdd 204 /* native HBA device added */
#define AifNativeDeviceRemove 205 /* native HBA device removed */
/* RAW device deleted */
#define AifRawDeviceRemove 203
/* /*
* Adapter Initiated FIB command structures. Start with the adapter * Adapter Initiated FIB command structures. Start with the adapter
@ -2131,6 +2618,8 @@ static inline unsigned int cap_to_cyls(sector_t capacity, unsigned divisor)
int aac_acquire_irq(struct aac_dev *dev); int aac_acquire_irq(struct aac_dev *dev);
void aac_free_irq(struct aac_dev *dev); void aac_free_irq(struct aac_dev *dev);
int aac_report_phys_luns(struct aac_dev *dev, struct fib *fibptr, int rescan);
int aac_issue_bmic_identify(struct aac_dev *dev, u32 bus, u32 target);
const char *aac_driverinfo(struct Scsi_Host *); const char *aac_driverinfo(struct Scsi_Host *);
void aac_fib_vector_assign(struct aac_dev *dev); void aac_fib_vector_assign(struct aac_dev *dev);
struct fib *aac_fib_alloc(struct aac_dev *dev); struct fib *aac_fib_alloc(struct aac_dev *dev);
@ -2141,9 +2630,12 @@ void aac_fib_free(struct fib * context);
void aac_fib_init(struct fib * context); void aac_fib_init(struct fib * context);
void aac_printf(struct aac_dev *dev, u32 val); void aac_printf(struct aac_dev *dev, u32 val);
int aac_fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt); int aac_fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
int aac_hba_send(u8 command, struct fib *context,
fib_callback callback, void *ctxt);
int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry); int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum); void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
int aac_fib_complete(struct fib * context); int aac_fib_complete(struct fib * context);
void aac_hba_callback(void *context, struct fib *fibptr);
#define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data) #define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data)
struct aac_dev *aac_init_adapter(struct aac_dev *dev); struct aac_dev *aac_init_adapter(struct aac_dev *dev);
void aac_src_access_devreg(struct aac_dev *dev, int mode); void aac_src_access_devreg(struct aac_dev *dev, int mode);
@ -2169,7 +2661,7 @@ unsigned int aac_command_normal(struct aac_queue * q);
unsigned int aac_intr_normal(struct aac_dev *dev, u32 Index, unsigned int aac_intr_normal(struct aac_dev *dev, u32 Index,
int isAif, int isFastResponse, int isAif, int isFastResponse,
struct hw_fib *aif_fib); struct hw_fib *aif_fib);
int aac_reset_adapter(struct aac_dev * dev, int forced); int aac_reset_adapter(struct aac_dev *dev, int forced, u8 reset_type);
int aac_check_health(struct aac_dev * dev); int aac_check_health(struct aac_dev * dev);
int aac_command_thread(void *data); int aac_command_thread(void *data);
int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx); int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
@ -2183,7 +2675,6 @@ int aac_rx_select_comm(struct aac_dev *dev, int comm);
int aac_rx_deliver_producer(struct fib * fib); int aac_rx_deliver_producer(struct fib * fib);
char * get_container_type(unsigned type); char * get_container_type(unsigned type);
extern int numacb; extern int numacb;
extern int acbsize;
extern char aac_driver_version[]; extern char aac_driver_version[];
extern int startup_timeout; extern int startup_timeout;
extern int aif_timeout; extern int aif_timeout;
@ -2194,3 +2685,4 @@ extern int aac_commit;
extern int update_interval; extern int update_interval;
extern int check_interval; extern int check_interval;
extern int aac_check_reset; extern int aac_check_reset;
#endif

View File

@ -6,7 +6,8 @@
* Adaptec aacraid device driver for Linux. * Adaptec aacraid device driver for Linux.
* *
* Copyright (c) 2000-2010 Adaptec, Inc. * 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 * 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 * 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; struct fib* srbfib;
int status; int status;
struct aac_srb *srbcmd = NULL; struct aac_srb *srbcmd = NULL;
struct aac_hba_cmd_req *hbacmd = NULL;
struct user_aac_srb *user_srbcmd = NULL; struct user_aac_srb *user_srbcmd = NULL;
struct user_aac_srb __user *user_srb = arg; struct user_aac_srb __user *user_srb = arg;
struct aac_srb_reply __user *user_reply; struct aac_srb_reply __user *user_reply;
struct aac_srb_reply* reply; u32 chn;
u32 fibsize = 0; u32 fibsize = 0;
u32 flags = 0; u32 flags = 0;
s32 rcode = 0; s32 rcode = 0;
u32 data_dir; u32 data_dir;
void __user *sg_user[32]; void __user *sg_user[HBA_MAX_SG_EMBEDDED];
void *sg_list[32]; void *sg_list[HBA_MAX_SG_EMBEDDED];
u32 sg_count[HBA_MAX_SG_EMBEDDED];
u32 sg_indx = 0; u32 sg_indx = 0;
u32 byte_count = 0; u32 byte_count = 0;
u32 actual_fibsize64, actual_fibsize = 0; u32 actual_fibsize64, actual_fibsize = 0;
int i; int i;
int is_native_device;
u64 address;
if (dev->in_reset) { 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))) { if (!(srbfib = aac_fib_alloc(dev))) {
return -ENOMEM; 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 */ memset(sg_list, 0, sizeof(sg_list)); /* cleanup may take issue */
if(copy_from_user(&fibsize, &user_srb->count,sizeof(u32))){ 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; goto cleanup;
} }
user_reply = arg+fibsize;
flags = user_srbcmd->flags; /* from user in cpu order */ 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)) { switch (flags & (SRB_DataIn | SRB_DataOut)) {
case SRB_DataOut: case SRB_DataOut:
data_dir = DMA_TO_DEVICE; 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)) { if (user_srbcmd->sg.count > ARRAY_SIZE(sg_list)) {
dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n", 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; rcode = -EINVAL;
goto cleanup; goto cleanup;
} }
@ -588,13 +579,136 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -EINVAL; rcode = -EINVAL;
goto cleanup; 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")); chn = aac_logical_to_phys(user_srbcmd->channel);
rcode = -EINVAL; if (chn < AAC_MAX_BUSES && user_srbcmd->id < AAC_MAX_TARGETS &&
goto cleanup; 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; 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 user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
struct sgmap64* psg = (struct sgmap64*)&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++) { for (i = 0; i < upsg->count; i++) {
u64 addr; u64 addr;
void* p; void* p;
if (upsg->sg[i].count >
sg_count[i] = upsg->sg[i].count;
if (sg_count[i] >
((dev->adapter_info.options & ((dev->adapter_info.options &
AAC_OPT_NEW_COMM) ? AAC_OPT_NEW_COMM) ?
(dev->scsi_host_ptr->max_sectors << 9) : (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; goto cleanup;
} }
/* Does this really need to be GFP_DMA? */ /* 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) { if(!p) {
dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", 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; rcode = -ENOMEM;
goto cleanup; goto cleanup;
} }
@ -629,18 +745,20 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
sg_indx = i; sg_indx = i;
if (flags & SRB_DataOut) { 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")); dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; 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[0] = cpu_to_le32(addr & 0xffffffff);
psg->sg[i].addr[1] = cpu_to_le32(addr>>32); psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
byte_count += upsg->sg[i].count; byte_count += sg_count[i];
psg->sg[i].count = cpu_to_le32(upsg->sg[i].count); psg->sg[i].count = cpu_to_le32(sg_count[i]);
} }
} else { } else {
struct user_sgmap* usg; 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++) { for (i = 0; i < usg->count; i++) {
u64 addr; u64 addr;
void* p; void* p;
if (usg->sg[i].count >
sg_count[i] = usg->sg[i].count;
if (sg_count[i] >
((dev->adapter_info.options & ((dev->adapter_info.options &
AAC_OPT_NEW_COMM) ? AAC_OPT_NEW_COMM) ?
(dev->scsi_host_ptr->max_sectors << 9) : (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; goto cleanup;
} }
/* Does this really need to be GFP_DMA? */ /* 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) { if(!p) {
dprintk((KERN_DEBUG "aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", 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); kfree(usg);
rcode = -ENOMEM; rcode = -ENOMEM;
goto cleanup; goto cleanup;
@ -680,19 +800,21 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
sg_indx = i; sg_indx = i;
if (flags & SRB_DataOut) { 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); kfree (usg);
dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; 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[0] = cpu_to_le32(addr & 0xffffffff);
psg->sg[i].addr[1] = cpu_to_le32(addr>>32); psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
byte_count += usg->sg[i].count; byte_count += sg_count[i];
psg->sg[i].count = cpu_to_le32(usg->sg[i].count); psg->sg[i].count = cpu_to_le32(sg_count[i]);
} }
kfree (usg); 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++) { for (i = 0; i < upsg->count; i++) {
uintptr_t addr; uintptr_t addr;
void* p; void* p;
if (usg->sg[i].count >
sg_count[i] = usg->sg[i].count;
if (sg_count[i] >
((dev->adapter_info.options & ((dev->adapter_info.options &
AAC_OPT_NEW_COMM) ? AAC_OPT_NEW_COMM) ?
(dev->scsi_host_ptr->max_sectors << 9) : (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; goto cleanup;
} }
/* Does this really need to be GFP_DMA? */ /* 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) { if (!p) {
dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", 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; rcode = -ENOMEM;
goto cleanup; goto cleanup;
} }
@ -734,7 +858,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
sg_indx = i; sg_indx = i;
if (flags & SRB_DataOut) { 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")); dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; 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); psg->sg[i].addr = cpu_to_le32(addr & 0xffffffff);
byte_count += usg->sg[i].count; 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 { } else {
for (i = 0; i < upsg->count; i++) { for (i = 0; i < upsg->count; i++) {
dma_addr_t addr; dma_addr_t addr;
void* p; void* p;
if (upsg->sg[i].count >
sg_count[i] = upsg->sg[i].count;
if (sg_count[i] >
((dev->adapter_info.options & ((dev->adapter_info.options &
AAC_OPT_NEW_COMM) ? AAC_OPT_NEW_COMM) ?
(dev->scsi_host_ptr->max_sectors << 9) : (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; rcode = -EINVAL;
goto cleanup; goto cleanup;
} }
p = kmalloc(upsg->sg[i].count, GFP_KERNEL); p = kmalloc(sg_count[i], GFP_KERNEL);
if (!p) { if (!p) {
dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", 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; rcode = -ENOMEM;
goto cleanup; goto cleanup;
} }
@ -770,19 +897,19 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
sg_indx = i; sg_indx = i;
if (flags & SRB_DataOut) { if (flags & SRB_DataOut) {
if(copy_from_user(p, sg_user[i], if (copy_from_user(p, sg_user[i],
upsg->sg[i].count)) { sg_count[i])) {
dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; goto cleanup;
} }
} }
addr = pci_map_single(dev->pdev, p, 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); psg->sg[i].addr = cpu_to_le32(addr);
byte_count += upsg->sg[i].count; byte_count += sg_count[i];
psg->sg[i].count = cpu_to_le32(upsg->sg[i].count); psg->sg[i].count = cpu_to_le32(sg_count[i]);
} }
} }
srbcmd->count = cpu_to_le32(byte_count); 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; psg->count = 0;
status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
} }
if (status == -ERESTARTSYS) { if (status == -ERESTARTSYS) {
rcode = -ERESTARTSYS; rcode = -ERESTARTSYS;
goto cleanup; goto cleanup;
} }
if (status != 0){ if (status != 0) {
dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n")); dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n"));
rcode = -ENXIO; rcode = -ENXIO;
goto cleanup; goto cleanup;
@ -805,11 +933,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
if (flags & SRB_DataIn) { if (flags & SRB_DataIn) {
for(i = 0 ; i <= sg_indx; i++){ for(i = 0 ; i <= sg_indx; i++){
byte_count = le32_to_cpu( if (copy_to_user(sg_user[i], sg_list[i], sg_count[i])) {
(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)){
dprintk((KERN_DEBUG"aacraid: Could not copy sg data to user\n")); dprintk((KERN_DEBUG"aacraid: Could not copy sg data to user\n"));
rcode = -EFAULT; rcode = -EFAULT;
goto cleanup; 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); user_reply = arg + fibsize;
if(copy_to_user(user_reply,reply,sizeof(struct aac_srb_reply))){ if (is_native_device) {
dprintk((KERN_DEBUG"aacraid: Could not copy reply to user\n")); struct aac_hba_resp *err =
rcode = -EFAULT; &((struct aac_native_hba *)srbfib->hw_fib_va)->resp.err;
goto cleanup; 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: cleanup:
kfree(user_srbcmd); kfree(user_srbcmd);
for(i=0; i <= sg_indx; i++){
kfree(sg_list[i]);
}
if (rcode != -ERESTARTSYS) { if (rcode != -ERESTARTSYS) {
for (i = 0; i <= sg_indx; i++)
kfree(sg_list[i]);
aac_fib_complete(srbfib); aac_fib_complete(srbfib);
aac_fib_free(srbfib); aac_fib_free(srbfib);
} }
@ -858,6 +1013,44 @@ static int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
return 0; 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) 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: case FSACTL_GET_PCI_INFO:
status = aac_get_pci_info(dev,arg); status = aac_get_pci_info(dev,arg);
break; 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: default:
status = -ENOTTY; status = -ENOTTY;
break; break;

View File

@ -6,7 +6,8 @@
* Adaptec aacraid device driver for Linux. * Adaptec aacraid device driver for Linux.
* *
* Copyright (c) 2000-2010 Adaptec, Inc. * 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 * 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 * 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; unsigned long size, align;
const unsigned long fibsize = dev->max_fib_size; const unsigned long fibsize = dev->max_fib_size;
const unsigned long printfbufsiz = 256; const unsigned long printfbufsiz = 256;
unsigned long host_rrq_size = 0; unsigned long host_rrq_size, aac_init_size;
struct aac_init *init; union aac_init *init;
dma_addr_t phys; dma_addr_t phys;
unsigned long aac_max_hostphysmempages; unsigned long aac_max_hostphysmempages;
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1 || if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) ||
dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) (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 host_rrq_size = (dev->scsi_host_ptr->can_queue
+ AAC_NUM_MGT_FIB) * sizeof(u32); + AAC_NUM_MGT_FIB) * sizeof(u32) * AAC_MAX_MSIX;
size = fibsize + sizeof(struct aac_init) + commsize + aac_init_size = sizeof(union aac_init) +
commalign + printfbufsiz + host_rrq_size; (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); base = pci_alloc_consistent(dev->pdev, size, &phys);
if(base == NULL) if (base == NULL) {
{
printk(KERN_ERR "aacraid: unable to create mapping.\n"); printk(KERN_ERR "aacraid: unable to create mapping.\n");
return 0; return 0;
} }
dev->comm_addr = (void *)base; dev->comm_addr = (void *)base;
dev->comm_phys = phys; dev->comm_phys = phys;
dev->comm_size = size; dev->comm_size = size;
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1 || if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) ||
dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) { (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) ||
(dev->comm_interface == AAC_COMM_MESSAGE_TYPE3)) {
dev->host_rrq = (u32 *)(base + fibsize); dev->host_rrq = (u32 *)(base + fibsize);
dev->host_rrq_pa = phys + fibsize; dev->host_rrq_pa = phys + fibsize;
memset(dev->host_rrq, 0, host_rrq_size); 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; dev->init_pa = phys + fibsize + host_rrq_size;
init = dev->init; init = dev->init;
init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) {
if (dev->max_fib_size != sizeof(struct hw_fib)) int i;
init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4); u64 addr;
init->Sa_MSIXVectors = cpu_to_le32(SA_INIT_NUM_MSIXVECTORS);
init->fsrev = cpu_to_le32(dev->fsrev);
/* init->r8.init_struct_revision =
* Adapter Fibs are the first thing allocated so that they cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_8);
* start page aligned init->r8.init_flags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED |
*/ INITFLAGS_DRIVER_USES_UTC_TIME |
dev->aif_base_va = (struct hw_fib *)base; INITFLAGS_DRIVER_SUPPORTS_PM);
init->r8.init_flags |=
init->AdapterFibsVirtualAddress = 0; cpu_to_le32(INITFLAGS_DRIVER_SUPPORTS_HBA_MODE);
init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys); init->r8.rr_queue_count = cpu_to_le32(dev->max_msix);
init->AdapterFibsSize = cpu_to_le32(fibsize); init->r8.max_io_size =
init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib)); cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
/* init->r8.max_num_aif = init->r8.reserved1 =
* number of 4k pages of host physical memory. The aacraid fw needs init->r8.reserved2 = 0;
* 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 | for (i = 0; i < dev->max_msix; i++) {
INITFLAGS_DRIVER_SUPPORTS_PM); addr = (u64)dev->host_rrq_pa + dev->vector_cap * i *
init->MaxIoCommands = cpu_to_le32(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); sizeof(u32);
init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9); init->r8.rrq[i].host_addr_high = cpu_to_le32(
init->MaxFibSize = cpu_to_le32(dev->max_fib_size); upper_32_bits(addr));
init->MaxNumAif = cpu_to_le32(dev->max_num_aif); 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;
}
if (dev->comm_interface == AAC_COMM_MESSAGE) { pr_warn("aacraid: Comm Interface type3 enabled\n");
init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED); } else {
dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n")); init->r7.init_struct_revision =
} else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) { cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION);
init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_6); if (dev->max_fib_size != sizeof(struct hw_fib))
init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED | init->r7.init_struct_revision =
INITFLAGS_NEW_COMM_TYPE1_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED); cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4);
init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32)); init->r7.no_of_msix_vectors = cpu_to_le32(SA_MINIPORT_REVISION);
init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff)); init->r7.fsrev = cpu_to_le32(dev->fsrev);
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); * Adapter Fibs are the first thing allocated so that they
init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED | * start page aligned
INITFLAGS_NEW_COMM_TYPE2_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED); */
init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32)); dev->aif_base_va = (struct hw_fib *)base;
init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff));
/* number of MSI-X */ init->r7.adapter_fibs_virtual_address = 0;
init->Sa_MSIXVectors = cpu_to_le32(dev->max_msix); init->r7.adapter_fibs_physical_address = cpu_to_le32((u32)phys);
dprintk((KERN_WARNING"aacraid: New Comm Interface type2 enabled\n")); 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 * 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 + phys = (dma_addr_t)((ulong)phys + fibsize + host_rrq_size +
sizeof(struct aac_init)); aac_init_size);
/* /*
* Align the beginning of Headers to commalign * 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 * Fill in addresses of the Comm Area Headers and Queues
*/ */
*commaddr = base; *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 * 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. * Place the Printf buffer area after the Fast I/O comm area.
*/ */
dev->printfbuf = (void *)base; dev->printfbuf = (void *)base;
init->printfbuf = cpu_to_le32(phys); if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE3) {
init->printfbufsiz = cpu_to_le32(printfbufsiz); init->r7.printfbuf = cpu_to_le32(phys);
init->r7.printfbufsiz = cpu_to_le32(printfbufsiz);
}
memset(base, 0, printfbufsiz); memset(base, 0, printfbufsiz);
return 1; return 1;
} }
static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, int qsize) static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, int qsize)
{ {
atomic_set(&q->numpending, 0); atomic_set(&q->numpending, 0);
@ -404,9 +479,13 @@ void aac_define_int_mode(struct aac_dev *dev)
if (dev->max_msix > msi_count) if (dev->max_msix > msi_count)
dev->max_msix = msi_count; dev->max_msix = msi_count;
} }
dev->vector_cap = if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE3 && dev->sa_firmware)
(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) / dev->vector_cap = dev->scsi_host_ptr->can_queue +
msi_count; 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) 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, if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
status+0, status+1, status+2, status+3, NULL)) && status+0, status+1, status+2, status+3, status+4)) &&
(status[0] == 0x00000001)) { (status[0] == 0x00000001)) {
dev->doorbell_mask = status[3]; 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->raw_io_64 = 1;
dev->sync_mode = aac_sync_mode; dev->sync_mode = aac_sync_mode;
if (dev->a_ops.adapter_comm && 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->comm_interface = AAC_COMM_MESSAGE;
dev->raw_io_interface = 1; 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) */ /* driver supports TYPE1 (Tupelo) */
dev->comm_interface = AAC_COMM_MESSAGE_TYPE1; dev->comm_interface = AAC_COMM_MESSAGE_TYPE1;
} else if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE2))) { } else if (status[1] & AAC_OPT_NEW_COMM_TYPE2) {
/* driver supports TYPE2 (Denali) */ /* driver supports TYPE2 (Denali, Yosemite) */
dev->comm_interface = AAC_COMM_MESSAGE_TYPE2; dev->comm_interface = AAC_COMM_MESSAGE_TYPE2;
} else if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE4)) || } else if (status[1] & AAC_OPT_NEW_COMM_TYPE3) {
(status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE3))) { /* driver supports TYPE3 (Yosemite, Thor) */
/* driver doesn't TYPE3 and TYPE4 */ dev->comm_interface = AAC_COMM_MESSAGE_TYPE3;
/* switch to sync. mode */ } else if (status[1] & AAC_OPT_NEW_COMM_TYPE4) {
/* not supported TYPE - switch to sync. mode */
dev->comm_interface = AAC_COMM_MESSAGE_TYPE2; dev->comm_interface = AAC_COMM_MESSAGE_TYPE2;
dev->sync_mode = 1; 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) && if ((dev->comm_interface == AAC_COMM_MESSAGE) &&
(status[2] > dev->base_size)) { (status[2] > dev->base_size)) {
aac_adapter_ioremap(dev, 0); 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; dev->sg_tablesize = status[2] & 0xFFFF;
if (dev->pdev->device == PMC_DEVICE_S7 || if (dev->pdev->device == PMC_DEVICE_S7 ||
dev->pdev->device == PMC_DEVICE_S8 || dev->pdev->device == PMC_DEVICE_S8 ||
dev->pdev->device == PMC_DEVICE_S9) dev->pdev->device == PMC_DEVICE_S9) {
host->can_queue = ((status[3] >> 16) ? (status[3] >> 16) : if (host->can_queue > (status[3] >> 16) -
(status[3] & 0xFFFF)) - AAC_NUM_MGT_FIB; AAC_NUM_MGT_FIB)
else host->can_queue = (status[3] >> 16) -
host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB; 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; 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)
if (numacb > 0) { host->can_queue = numacb;
if (numacb < host->can_queue) else
host->can_queue = numacb; pr_warn("numacb=%d ignored\n", numacb);
else
printk("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 || if (dev->pdev->device == PMC_DEVICE_S6 ||
dev->pdev->device == PMC_DEVICE_S7 || dev->pdev->device == PMC_DEVICE_S7 ||
dev->pdev->device == PMC_DEVICE_S8 || dev->pdev->device == PMC_DEVICE_S8 ||

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,8 @@
* Adaptec aacraid device driver for Linux. * Adaptec aacraid device driver for Linux.
* *
* Copyright (c) 2000-2010 Adaptec, Inc. * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -122,7 +123,6 @@ unsigned int aac_response_normal(struct aac_queue * q)
* NOTE: we cannot touch the fib after this * NOTE: we cannot touch the fib after this
* call, because it may have been deallocated. * call, because it may have been deallocated.
*/ */
fib->flags &= FIB_CONTEXT_FLAG_FASTRESP;
fib->callback(fib->callback_data, fib); fib->callback(fib->callback_data, fib);
} else { } else {
unsigned long flagv; unsigned long flagv;
@ -251,8 +251,9 @@ static void aac_aif_callback(void *context, struct fib * fibptr)
BUG_ON(fibptr == NULL); BUG_ON(fibptr == NULL);
dev = fibptr->dev; dev = fibptr->dev;
if (fibptr->hw_fib_va->header.XferState & if ((fibptr->hw_fib_va->header.XferState &
cpu_to_le32(NoMoreAifDataAvailable)) { cpu_to_le32(NoMoreAifDataAvailable)) ||
dev->sa_firmware) {
aac_fib_complete(fibptr); aac_fib_complete(fibptr);
aac_fib_free(fibptr); aac_fib_free(fibptr);
return; return;
@ -282,8 +283,8 @@ static void aac_aif_callback(void *context, struct fib * fibptr)
* know there is a response on our normal priority queue. We will pull off * know there is a response on our normal priority queue. We will pull off
* all QE there are and wake up all the waiters before exiting. * all QE there are and wake up all the waiters before exiting.
*/ */
unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, int isAif,
int isAif, int isFastResponse, struct hw_fib *aif_fib) int isFastResponse, struct hw_fib *aif_fib)
{ {
unsigned long mflags; unsigned long mflags;
dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, index)); dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, index));
@ -305,12 +306,14 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index,
kfree (fib); kfree (fib);
return 1; return 1;
} }
if (aif_fib != NULL) { if (dev->sa_firmware) {
fib->hbacmd_size = index; /* store event type */
} else if (aif_fib != NULL) {
memcpy(hw_fib, aif_fib, sizeof(struct hw_fib)); memcpy(hw_fib, aif_fib, sizeof(struct hw_fib));
} else { } else {
memcpy(hw_fib, memcpy(hw_fib, (struct hw_fib *)
(struct hw_fib *)(((uintptr_t)(dev->regs.sa)) + (((uintptr_t)(dev->regs.sa)) + index),
index), sizeof(struct hw_fib)); sizeof(struct hw_fib));
} }
INIT_LIST_HEAD(&fib->fiblink); INIT_LIST_HEAD(&fib->fiblink);
fib->type = FSAFS_NTC_FIB_CONTEXT; fib->type = FSAFS_NTC_FIB_CONTEXT;
@ -344,7 +347,7 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index,
(fib_callback)aac_aif_callback, fibctx); (fib_callback)aac_aif_callback, fibctx);
} else { } else {
struct fib *fib = &dev->fibs[index]; struct fib *fib = &dev->fibs[index];
struct hw_fib * hwfib = fib->hw_fib_va; int start_callback = 0;
/* /*
* Remove this fib from the Outstanding I/O queue. * Remove this fib from the Outstanding I/O queue.
@ -362,60 +365,104 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index,
return 0; return 0;
} }
if (isFastResponse) {
/*
* Doctor the fib
*/
*(__le32 *)hwfib->data = cpu_to_le32(ST_OK);
hwfib->header.XferState |= cpu_to_le32(AdapterProcessed);
fib->flags |= FIB_CONTEXT_FLAG_FASTRESP;
}
FIB_COUNTER_INCREMENT(aac_config.FibRecved); FIB_COUNTER_INCREMENT(aac_config.FibRecved);
if (hwfib->header.Command == cpu_to_le16(NuFileSystem)) if (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) {
{
__le32 *pstatus = (__le32 *)hwfib->data; if (isFastResponse)
if (*pstatus & cpu_to_le32(0xffff0000)) fib->flags |= FIB_CONTEXT_FLAG_FASTRESP;
*pstatus = cpu_to_le32(ST_OK);
if (fib->callback) {
start_callback = 1;
} else {
unsigned long flagv;
int complete = 0;
dprintk((KERN_INFO "event_wait up\n"));
spin_lock_irqsave(&fib->event_lock, flagv);
if (fib->done == 2) {
fib->done = 1;
complete = 1;
} else {
fib->done = 1;
up(&fib->event_wait);
}
spin_unlock_irqrestore(&fib->event_lock, flagv);
spin_lock_irqsave(&dev->manage_lock, mflags);
dev->management_fib_count--;
spin_unlock_irqrestore(&dev->manage_lock,
mflags);
FIB_COUNTER_INCREMENT(aac_config.NativeRecved);
if (complete)
aac_fib_complete(fib);
}
} else {
struct hw_fib *hwfib = fib->hw_fib_va;
if (isFastResponse) {
/* Doctor the fib */
*(__le32 *)hwfib->data = cpu_to_le32(ST_OK);
hwfib->header.XferState |=
cpu_to_le32(AdapterProcessed);
fib->flags |= FIB_CONTEXT_FLAG_FASTRESP;
}
if (hwfib->header.Command ==
cpu_to_le16(NuFileSystem)) {
__le32 *pstatus = (__le32 *)hwfib->data;
if (*pstatus & cpu_to_le32(0xffff0000))
*pstatus = cpu_to_le32(ST_OK);
}
if (hwfib->header.XferState &
cpu_to_le32(NoResponseExpected | Async)) {
if (hwfib->header.XferState & cpu_to_le32(
NoResponseExpected))
FIB_COUNTER_INCREMENT(
aac_config.NoResponseRecved);
else
FIB_COUNTER_INCREMENT(
aac_config.AsyncRecved);
start_callback = 1;
} else {
unsigned long flagv;
int complete = 0;
dprintk((KERN_INFO "event_wait up\n"));
spin_lock_irqsave(&fib->event_lock, flagv);
if (fib->done == 2) {
fib->done = 1;
complete = 1;
} else {
fib->done = 1;
up(&fib->event_wait);
}
spin_unlock_irqrestore(&fib->event_lock, flagv);
spin_lock_irqsave(&dev->manage_lock, mflags);
dev->management_fib_count--;
spin_unlock_irqrestore(&dev->manage_lock,
mflags);
FIB_COUNTER_INCREMENT(aac_config.NormalRecved);
if (complete)
aac_fib_complete(fib);
}
} }
if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected | Async))
{
if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected)) if (start_callback) {
FIB_COUNTER_INCREMENT(aac_config.NoResponseRecved);
else
FIB_COUNTER_INCREMENT(aac_config.AsyncRecved);
/* /*
* NOTE: we cannot touch the fib after this * NOTE: we cannot touch the fib after this
* call, because it may have been deallocated. * call, because it may have been deallocated.
*/ */
if (likely(fib->callback && fib->callback_data)) { if (likely(fib->callback && fib->callback_data)) {
fib->flags &= FIB_CONTEXT_FLAG_FASTRESP;
fib->callback(fib->callback_data, fib); fib->callback(fib->callback_data, fib);
} else } else {
dev_info(&dev->pdev->dev,
"Invalid callback_fib[%d] (*%p)(%p)\n",
index, fib->callback, fib->callback_data);
} else {
unsigned long flagv;
dprintk((KERN_INFO "event_wait up\n"));
spin_lock_irqsave(&fib->event_lock, flagv);
if (!fib->done) {
fib->done = 1;
up(&fib->event_wait);
}
spin_unlock_irqrestore(&fib->event_lock, flagv);
spin_lock_irqsave(&dev->manage_lock, mflags);
dev->management_fib_count--;
spin_unlock_irqrestore(&dev->manage_lock, mflags);
FIB_COUNTER_INCREMENT(aac_config.NormalRecved);
if (fib->done == 2) {
spin_lock_irqsave(&fib->event_lock, flagv);
fib->done = 0;
spin_unlock_irqrestore(&fib->event_lock, flagv);
aac_fib_complete(fib); aac_fib_complete(fib);
aac_fib_free(fib);
} }
} }

View File

@ -6,7 +6,8 @@
* Adaptec aacraid device driver for Linux. * Adaptec aacraid device driver for Linux.
* *
* Copyright (c) 2000-2010 Adaptec, Inc. * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -57,7 +58,7 @@
#include "aacraid.h" #include "aacraid.h"
#define AAC_DRIVER_VERSION "1.2-1" #define AAC_DRIVER_VERSION "1.2.1"
#ifndef AAC_DRIVER_BRANCH #ifndef AAC_DRIVER_BRANCH
#define AAC_DRIVER_BRANCH "" #define AAC_DRIVER_BRANCH ""
#endif #endif
@ -401,61 +402,89 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev,
static int aac_slave_configure(struct scsi_device *sdev) static int aac_slave_configure(struct scsi_device *sdev)
{ {
struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata; struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata;
int chn, tid;
unsigned int depth = 0;
unsigned int set_timeout = 0;
chn = aac_logical_to_phys(sdev_channel(sdev));
tid = sdev_id(sdev);
if (chn < AAC_MAX_BUSES && tid < AAC_MAX_TARGETS &&
aac->hba_map[chn][tid].devtype == AAC_DEVTYPE_NATIVE_RAW) {
depth = aac->hba_map[chn][tid].qd_limit;
set_timeout = 1;
goto common_config;
}
if (aac->jbod && (sdev->type == TYPE_DISK)) if (aac->jbod && (sdev->type == TYPE_DISK))
sdev->removable = 1; sdev->removable = 1;
if ((sdev->type == TYPE_DISK) &&
(sdev_channel(sdev) != CONTAINER_CHANNEL) && if (sdev->type == TYPE_DISK
(!aac->jbod || sdev->inq_periph_qual) && && sdev_channel(sdev) != CONTAINER_CHANNEL
(!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))) { && (!aac->jbod || sdev->inq_periph_qual)
&& (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))) {
if (expose_physicals == 0) if (expose_physicals == 0)
return -ENXIO; return -ENXIO;
if (expose_physicals < 0) if (expose_physicals < 0)
sdev->no_uld_attach = 1; sdev->no_uld_attach = 1;
} }
if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
(!aac->raid_scsi_mode || (sdev_channel(sdev) != 2)) && if (sdev->tagged_supported
!sdev->no_uld_attach) { && sdev->type == TYPE_DISK
&& (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))
&& !sdev->no_uld_attach) {
struct scsi_device * dev; struct scsi_device * dev;
struct Scsi_Host *host = sdev->host; struct Scsi_Host *host = sdev->host;
unsigned num_lsu = 0; unsigned num_lsu = 0;
unsigned num_one = 0; unsigned num_one = 0;
unsigned depth;
unsigned cid; unsigned cid;
/* set_timeout = 1;
* Firmware has an individual device recovery time typically
* of 35 seconds, give us a margin.
*/
if (sdev->request_queue->rq_timeout < (45 * HZ))
blk_queue_rq_timeout(sdev->request_queue, 45*HZ);
for (cid = 0; cid < aac->maximum_num_containers; ++cid) for (cid = 0; cid < aac->maximum_num_containers; ++cid)
if (aac->fsa_dev[cid].valid) if (aac->fsa_dev[cid].valid)
++num_lsu; ++num_lsu;
__shost_for_each_device(dev, host) { __shost_for_each_device(dev, host) {
if (dev->tagged_supported && (dev->type == TYPE_DISK) && if (dev->tagged_supported
(!aac->raid_scsi_mode || && dev->type == TYPE_DISK
(sdev_channel(sdev) != 2)) && && (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))
!dev->no_uld_attach) { && !dev->no_uld_attach) {
if ((sdev_channel(dev) != CONTAINER_CHANNEL) if ((sdev_channel(dev) != CONTAINER_CHANNEL)
|| !aac->fsa_dev[sdev_id(dev)].valid) || !aac->fsa_dev[sdev_id(dev)].valid) {
++num_lsu; ++num_lsu;
} else }
} else {
++num_one; ++num_one;
}
} }
if (num_lsu == 0) if (num_lsu == 0)
++num_lsu; ++num_lsu;
depth = (host->can_queue - num_one) / num_lsu;
if (depth > 256)
depth = 256;
else if (depth < 2)
depth = 2;
scsi_change_queue_depth(sdev, depth);
} else {
scsi_change_queue_depth(sdev, 1);
sdev->tagged_supported = 1; depth = (host->can_queue - num_one) / num_lsu;
} }
common_config:
/*
* Firmware has an individual device recovery time typically
* of 35 seconds, give us a margin.
*/
if (set_timeout && sdev->request_queue->rq_timeout < (45 * HZ))
blk_queue_rq_timeout(sdev->request_queue, 45*HZ);
if (depth > 256)
depth = 256;
else if (depth < 1)
depth = 1;
scsi_change_queue_depth(sdev, depth);
sdev->tagged_supported = 1;
return 0; return 0;
} }
@ -470,6 +499,15 @@ static int aac_slave_configure(struct scsi_device *sdev)
static int aac_change_queue_depth(struct scsi_device *sdev, int depth) static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
{ {
struct aac_dev *aac = (struct aac_dev *)(sdev->host->hostdata);
int chn, tid, is_native_device = 0;
chn = aac_logical_to_phys(sdev_channel(sdev));
tid = sdev_id(sdev);
if (chn < AAC_MAX_BUSES && tid < AAC_MAX_TARGETS &&
aac->hba_map[chn][tid].devtype == AAC_DEVTYPE_NATIVE_RAW)
is_native_device = 1;
if (sdev->tagged_supported && (sdev->type == TYPE_DISK) && if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
(sdev_channel(sdev) == CONTAINER_CHANNEL)) { (sdev_channel(sdev) == CONTAINER_CHANNEL)) {
struct scsi_device * dev; struct scsi_device * dev;
@ -491,9 +529,12 @@ static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
else if (depth < 2) else if (depth < 2)
depth = 2; depth = 2;
return scsi_change_queue_depth(sdev, depth); return scsi_change_queue_depth(sdev, depth);
} else if (is_native_device) {
scsi_change_queue_depth(sdev, aac->hba_map[chn][tid].qd_limit);
} else {
scsi_change_queue_depth(sdev, 1);
} }
return sdev->queue_depth;
return scsi_change_queue_depth(sdev, 1);
} }
static ssize_t aac_show_raid_level(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t aac_show_raid_level(struct device *dev, struct device_attribute *attr, char *buf)
@ -516,8 +557,39 @@ static struct device_attribute aac_raid_level_attr = {
.show = aac_show_raid_level .show = aac_show_raid_level
}; };
static ssize_t aac_show_unique_id(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct aac_dev *aac = (struct aac_dev *)(sdev->host->hostdata);
unsigned char sn[16];
memset(sn, 0, sizeof(sn));
if (sdev_channel(sdev) == CONTAINER_CHANNEL)
memcpy(sn, aac->fsa_dev[sdev_id(sdev)].identifier, sizeof(sn));
return snprintf(buf, 16 * 2 + 2,
"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
sn[0], sn[1], sn[2], sn[3],
sn[4], sn[5], sn[6], sn[7],
sn[8], sn[9], sn[10], sn[11],
sn[12], sn[13], sn[14], sn[15]);
}
static struct device_attribute aac_unique_id_attr = {
.attr = {
.name = "unique_id",
.mode = 0444,
},
.show = aac_show_unique_id
};
static struct device_attribute *aac_dev_attrs[] = { static struct device_attribute *aac_dev_attrs[] = {
&aac_raid_level_attr, &aac_raid_level_attr,
&aac_unique_id_attr,
NULL, NULL,
}; };
@ -534,46 +606,136 @@ static int aac_eh_abort(struct scsi_cmnd* cmd)
struct scsi_device * dev = cmd->device; struct scsi_device * dev = cmd->device;
struct Scsi_Host * host = dev->host; struct Scsi_Host * host = dev->host;
struct aac_dev * aac = (struct aac_dev *)host->hostdata; struct aac_dev * aac = (struct aac_dev *)host->hostdata;
int count; int count, found;
u32 bus, cid;
int ret = FAILED; int ret = FAILED;
printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%llu)\n", bus = aac_logical_to_phys(scmd_channel(cmd));
AAC_DRIVERNAME, cid = scmd_id(cmd);
host->host_no, sdev_channel(dev), sdev_id(dev), dev->lun); if (aac->hba_map[bus][cid].devtype == AAC_DEVTYPE_NATIVE_RAW) {
switch (cmd->cmnd[0]) { struct fib *fib;
case SERVICE_ACTION_IN_16: struct aac_hba_tm_req *tmf;
if (!(aac->raw_io_interface) || int status;
!(aac->raw_io_64) || u64 address;
((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16)) __le32 managed_request_id;
break;
case INQUIRY: pr_err("%s: Host adapter abort request (%d,%d,%d,%d)\n",
case READ_CAPACITY: AAC_DRIVERNAME,
/* Mark associated FIB to not complete, eh handler does this */ host->host_no, sdev_channel(dev), sdev_id(dev), (int)dev->lun);
found = 0;
for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
struct fib * fib = &aac->fibs[count]; fib = &aac->fibs[count];
if (fib->hw_fib_va->header.XferState && if (*(u8 *)fib->hw_fib_va != 0 &&
(fib->flags & FIB_CONTEXT_FLAG) && (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) &&
(fib->callback_data == cmd)) { (fib->callback_data == cmd)) {
fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; found = 1;
cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER; managed_request_id = ((struct aac_hba_cmd_req *)
ret = SUCCESS; fib->hw_fib_va)->request_id;
break;
} }
} }
break; if (!found)
case TEST_UNIT_READY: return ret;
/* Mark associated FIB to not complete, eh handler does this */
for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { /* start a HBA_TMF_ABORT_TASK TMF request */
struct scsi_cmnd * command; fib = aac_fib_alloc(aac);
struct fib * fib = &aac->fibs[count]; if (!fib)
if ((fib->hw_fib_va->header.XferState & cpu_to_le32(Async | NoResponseExpected)) && return ret;
(fib->flags & FIB_CONTEXT_FLAG) &&
((command = fib->callback_data)) && tmf = (struct aac_hba_tm_req *)fib->hw_fib_va;
(command->device == cmd->device)) { memset(tmf, 0, sizeof(*tmf));
fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; tmf->tmf = HBA_TMF_ABORT_TASK;
command->SCp.phase = AAC_OWNER_ERROR_HANDLER; tmf->it_nexus = aac->hba_map[bus][cid].rmw_nexus;
if (command == cmd) tmf->lun[1] = cmd->device->lun;
ret = SUCCESS;
address = (u64)fib->hw_error_pa;
tmf->error_ptr_hi = cpu_to_le32((u32)(address >> 32));
tmf->error_ptr_lo = cpu_to_le32((u32)(address & 0xffffffff));
tmf->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE);
fib->hbacmd_size = sizeof(*tmf);
cmd->SCp.sent_command = 0;
status = aac_hba_send(HBA_IU_TYPE_SCSI_TM_REQ, fib,
(fib_callback) aac_hba_callback,
(void *) cmd);
/* Wait up to 2 minutes for completion */
for (count = 0; count < 120; ++count) {
if (cmd->SCp.sent_command) {
ret = SUCCESS;
break;
} }
msleep(1000);
}
if (ret != SUCCESS)
pr_err("%s: Host adapter abort request timed out\n",
AAC_DRIVERNAME);
} else {
pr_err(
"%s: Host adapter abort request.\n"
"%s: Outstanding commands on (%d,%d,%d,%d):\n",
AAC_DRIVERNAME, AAC_DRIVERNAME,
host->host_no, sdev_channel(dev), sdev_id(dev),
(int)dev->lun);
switch (cmd->cmnd[0]) {
case SERVICE_ACTION_IN_16:
if (!(aac->raw_io_interface) ||
!(aac->raw_io_64) ||
((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
break;
case INQUIRY:
case READ_CAPACITY:
/*
* Mark associated FIB to not complete,
* eh handler does this
*/
for (count = 0;
count < (host->can_queue + AAC_NUM_MGT_FIB);
++count) {
struct fib *fib = &aac->fibs[count];
if (fib->hw_fib_va->header.XferState &&
(fib->flags & FIB_CONTEXT_FLAG) &&
(fib->callback_data == cmd)) {
fib->flags |=
FIB_CONTEXT_FLAG_TIMED_OUT;
cmd->SCp.phase =
AAC_OWNER_ERROR_HANDLER;
ret = SUCCESS;
}
}
break;
case TEST_UNIT_READY:
/*
* Mark associated FIB to not complete,
* eh handler does this
*/
for (count = 0;
count < (host->can_queue + AAC_NUM_MGT_FIB);
++count) {
struct scsi_cmnd *command;
struct fib *fib = &aac->fibs[count];
command = fib->callback_data;
if ((fib->hw_fib_va->header.XferState &
cpu_to_le32
(Async | NoResponseExpected)) &&
(fib->flags & FIB_CONTEXT_FLAG) &&
((command)) &&
(command->device == cmd->device)) {
fib->flags |=
FIB_CONTEXT_FLAG_TIMED_OUT;
command->SCp.phase =
AAC_OWNER_ERROR_HANDLER;
if (command == cmd)
ret = SUCCESS;
}
}
break;
} }
} }
return ret; return ret;
@ -588,70 +750,165 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
{ {
struct scsi_device * dev = cmd->device; struct scsi_device * dev = cmd->device;
struct Scsi_Host * host = dev->host; struct Scsi_Host * host = dev->host;
struct scsi_cmnd * command;
int count;
struct aac_dev * aac = (struct aac_dev *)host->hostdata; struct aac_dev * aac = (struct aac_dev *)host->hostdata;
unsigned long flags; int count;
u32 bus, cid;
int ret = FAILED;
/* Mark the associated FIB to not complete, eh handler does this */ bus = aac_logical_to_phys(scmd_channel(cmd));
for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { cid = scmd_id(cmd);
struct fib * fib = &aac->fibs[count]; if (bus < AAC_MAX_BUSES && cid < AAC_MAX_TARGETS &&
if (fib->hw_fib_va->header.XferState && aac->hba_map[bus][cid].devtype == AAC_DEVTYPE_NATIVE_RAW) {
(fib->flags & FIB_CONTEXT_FLAG) && struct fib *fib;
(fib->callback_data == cmd)) { int status;
fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; u64 address;
cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER; u8 command;
pr_err("%s: Host adapter reset request. SCSI hang ?\n",
AAC_DRIVERNAME);
fib = aac_fib_alloc(aac);
if (!fib)
return ret;
if (aac->hba_map[bus][cid].reset_state == 0) {
struct aac_hba_tm_req *tmf;
/* start a HBA_TMF_LUN_RESET TMF request */
tmf = (struct aac_hba_tm_req *)fib->hw_fib_va;
memset(tmf, 0, sizeof(*tmf));
tmf->tmf = HBA_TMF_LUN_RESET;
tmf->it_nexus = aac->hba_map[bus][cid].rmw_nexus;
tmf->lun[1] = cmd->device->lun;
address = (u64)fib->hw_error_pa;
tmf->error_ptr_hi = cpu_to_le32
((u32)(address >> 32));
tmf->error_ptr_lo = cpu_to_le32
((u32)(address & 0xffffffff));
tmf->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE);
fib->hbacmd_size = sizeof(*tmf);
command = HBA_IU_TYPE_SCSI_TM_REQ;
aac->hba_map[bus][cid].reset_state++;
} else if (aac->hba_map[bus][cid].reset_state >= 1) {
struct aac_hba_reset_req *rst;
/* already tried, start a hard reset now */
rst = (struct aac_hba_reset_req *)fib->hw_fib_va;
memset(rst, 0, sizeof(*rst));
/* reset_type is already zero... */
rst->it_nexus = aac->hba_map[bus][cid].rmw_nexus;
address = (u64)fib->hw_error_pa;
rst->error_ptr_hi = cpu_to_le32((u32)(address >> 32));
rst->error_ptr_lo = cpu_to_le32
((u32)(address & 0xffffffff));
rst->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE);
fib->hbacmd_size = sizeof(*rst);
command = HBA_IU_TYPE_SATA_REQ;
aac->hba_map[bus][cid].reset_state = 0;
} }
} cmd->SCp.sent_command = 0;
printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n",
status = aac_hba_send(command, fib,
(fib_callback) aac_hba_callback,
(void *) cmd);
/* Wait up to 2 minutes for completion */
for (count = 0; count < 120; ++count) {
if (cmd->SCp.sent_command) {
ret = SUCCESS;
break;
}
msleep(1000);
}
if (ret != SUCCESS)
pr_err("%s: Host adapter reset request timed out\n",
AAC_DRIVERNAME);
} else {
struct scsi_cmnd *command;
unsigned long flags;
/* Mark the assoc. FIB to not complete, eh handler does this */
for (count = 0;
count < (host->can_queue + AAC_NUM_MGT_FIB);
++count) {
struct fib *fib = &aac->fibs[count];
if (fib->hw_fib_va->header.XferState &&
(fib->flags & FIB_CONTEXT_FLAG) &&
(fib->callback_data == cmd)) {
fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
}
}
pr_err("%s: Host adapter reset request. SCSI hang ?\n",
AAC_DRIVERNAME); AAC_DRIVERNAME);
if ((count = aac_check_health(aac))) count = aac_check_health(aac);
return count; if (count)
/* return count;
* Wait for all commands to complete to this specific
* target (block maximum 60 seconds).
*/
for (count = 60; count; --count) {
int active = aac->in_reset;
if (active == 0)
__shost_for_each_device(dev, host) {
spin_lock_irqsave(&dev->list_lock, flags);
list_for_each_entry(command, &dev->cmd_list, list) {
if ((command != cmd) &&
(command->SCp.phase == AAC_OWNER_FIRMWARE)) {
active++;
break;
}
}
spin_unlock_irqrestore(&dev->list_lock, flags);
if (active)
break;
}
/* /*
* We can exit If all the commands are complete * Wait for all commands to complete to this specific
* target (block maximum 60 seconds).
*/ */
if (active == 0) for (count = 60; count; --count) {
return SUCCESS; int active = aac->in_reset;
ssleep(1);
if (active == 0)
__shost_for_each_device(dev, host) {
spin_lock_irqsave(&dev->list_lock, flags);
list_for_each_entry(command, &dev->cmd_list,
list) {
if ((command != cmd) &&
(command->SCp.phase ==
AAC_OWNER_FIRMWARE)) {
active++;
break;
}
}
spin_unlock_irqrestore(&dev->list_lock, flags);
if (active)
break;
}
/*
* We can exit If all the commands are complete
*/
if (active == 0)
return SUCCESS;
ssleep(1);
}
pr_err("%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
/*
* This adapter needs a blind reset, only do so for
* Adapters that support a register, instead of a commanded,
* reset.
*/
if (((aac->supplement_adapter_info.SupportedOptions2 &
AAC_OPTION_MU_RESET) ||
(aac->supplement_adapter_info.SupportedOptions2 &
AAC_OPTION_DOORBELL_RESET)) &&
aac_check_reset &&
((aac_check_reset != 1) ||
!(aac->supplement_adapter_info.SupportedOptions2 &
AAC_OPTION_IGNORE_RESET))) {
/* Bypass wait for command quiesce */
aac_reset_adapter(aac, 2, IOP_HWSOFT_RESET);
}
ret = SUCCESS;
} }
printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
/* /*
* This adapter needs a blind reset, only do so for Adapters that * Cause an immediate retry of the command with a ten second delay
* support a register, instead of a commanded, reset. * after successful tur
*/ */
if (((aac->supplement_adapter_info.SupportedOptions2 & return ret;
AAC_OPTION_MU_RESET) ||
(aac->supplement_adapter_info.SupportedOptions2 &
AAC_OPTION_DOORBELL_RESET)) &&
aac_check_reset &&
((aac_check_reset != 1) ||
!(aac->supplement_adapter_info.SupportedOptions2 &
AAC_OPTION_IGNORE_RESET)))
aac_reset_adapter(aac, 2); /* Bypass wait for command quiesce */
return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */
} }
/** /**
@ -911,10 +1168,16 @@ static ssize_t aac_store_reset_adapter(struct device *device,
const char *buf, size_t count) const char *buf, size_t count)
{ {
int retval = -EACCES; int retval = -EACCES;
int bled = 0;
struct aac_dev *aac;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return retval; return retval;
retval = aac_reset_adapter((struct aac_dev*)class_to_shost(device)->hostdata, buf[0] == '!');
aac = (struct aac_dev *)class_to_shost(device)->hostdata;
bled = buf[0] == '!' ? 1:0;
retval = aac_reset_adapter(aac, bled, IOP_HWSOFT_RESET);
if (retval >= 0) if (retval >= 0)
retval = count; retval = count;
return retval; return retval;
@ -1070,6 +1333,7 @@ static void __aac_shutdown(struct aac_dev * aac)
{ {
int i; int i;
aac->adapter_shutdown = 1;
aac_send_shutdown(aac); aac_send_shutdown(aac);
if (aac->aif_thread) { if (aac->aif_thread) {
@ -1285,7 +1549,7 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
else else
shost->this_id = shost->max_id; shost->this_id = shost->max_id;
if (aac_drivers[index].quirks & AAC_QUIRK_SRC) if (!aac->sa_firmware && aac_drivers[index].quirks & AAC_QUIRK_SRC)
aac_intr_normal(aac, 0, 2, 0, NULL); aac_intr_normal(aac, 0, 2, 0, NULL);
/* /*
@ -1327,35 +1591,12 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
static void aac_release_resources(struct aac_dev *aac) static void aac_release_resources(struct aac_dev *aac)
{ {
int i;
aac_adapter_disable_int(aac); aac_adapter_disable_int(aac);
if (aac->pdev->device == PMC_DEVICE_S6 || aac_free_irq(aac);
aac->pdev->device == PMC_DEVICE_S7 ||
aac->pdev->device == PMC_DEVICE_S8 ||
aac->pdev->device == PMC_DEVICE_S9) {
if (aac->max_msix > 1) {
for (i = 0; i < aac->max_msix; i++)
free_irq(pci_irq_vector(aac->pdev, i),
&(aac->aac_msix[i]));
} else {
free_irq(aac->pdev->irq, &(aac->aac_msix[0]));
}
} else {
free_irq(aac->pdev->irq, aac);
}
if (aac->msi)
pci_disable_msi(aac->pdev);
else if (aac->max_msix > 1)
pci_disable_msix(aac->pdev);
} }
static int aac_acquire_resources(struct aac_dev *dev) static int aac_acquire_resources(struct aac_dev *dev)
{ {
int i, j;
int instance = dev->id;
const char *name = dev->name;
unsigned long status; unsigned long status;
/* /*
* First clear out all interrupts. Then enable the one's that we * First clear out all interrupts. Then enable the one's that we
@ -1377,37 +1618,8 @@ static int aac_acquire_resources(struct aac_dev *dev)
if (dev->msi_enabled) if (dev->msi_enabled)
aac_src_access_devreg(dev, AAC_ENABLE_MSIX); aac_src_access_devreg(dev, AAC_ENABLE_MSIX);
if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) { if (aac_acquire_irq(dev))
for (i = 0; i < dev->max_msix; i++) { goto error_iounmap;
dev->aac_msix[i].vector_no = i;
dev->aac_msix[i].dev = dev;
if (request_irq(pci_irq_vector(dev->pdev, i),
dev->a_ops.adapter_intr,
0, "aacraid", &(dev->aac_msix[i]))) {
printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n",
name, instance, i);
for (j = 0 ; j < i ; j++)
free_irq(pci_irq_vector(dev->pdev, j),
&(dev->aac_msix[j]));
pci_disable_msix(dev->pdev);
goto error_iounmap;
}
}
} else {
dev->aac_msix[0].vector_no = 0;
dev->aac_msix[0].dev = dev;
if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
IRQF_SHARED, "aacraid",
&(dev->aac_msix[0])) < 0) {
if (dev->msi)
pci_disable_msi(dev->pdev);
printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
name, instance);
goto error_iounmap;
}
}
aac_adapter_enable_int(dev); aac_adapter_enable_int(dev);
@ -1420,7 +1632,7 @@ static int aac_acquire_resources(struct aac_dev *dev)
/* After EEH recovery or suspend resume, max_msix count /* After EEH recovery or suspend resume, max_msix count
* may change, therfore updating in init as well. * may change, therfore updating in init as well.
*/ */
dev->init->Sa_MSIXVectors = cpu_to_le32(dev->max_msix); dev->init->r7.no_of_msix_vectors = cpu_to_le32(dev->max_msix);
aac_adapter_start(dev); aac_adapter_start(dev);
} }
return 0; return 0;

View File

@ -5,7 +5,8 @@
* Adaptec aacraid device driver for Linux. * Adaptec aacraid device driver for Linux.
* *
* Copyright (c) 2000-2010 Adaptec, Inc. * 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 * 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 * it under the terms of the GNU General Public License as published by

View File

@ -6,7 +6,8 @@
* Adaptec aacraid device driver for Linux. * Adaptec aacraid device driver for Linux.
* *
* Copyright (c) 2000-2010 Adaptec, Inc. * 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 * 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 * 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. * case warrants this half baked, but convenient, check here.
*/ */
if (dev->scsi_host_ptr->can_queue > AAC_NUM_IO_FIB_RKT) { 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); cpu_to_le32(AAC_NUM_IO_FIB_RKT + AAC_NUM_MGT_FIB);
dev->scsi_host_ptr->can_queue = AAC_NUM_IO_FIB_RKT; dev->scsi_host_ptr->can_queue = AAC_NUM_IO_FIB_RKT;
} }

View File

@ -6,7 +6,8 @@
* Adaptec aacraid device driver for Linux. * Adaptec aacraid device driver for Linux.
* *
* Copyright (c) 2000-2010 Adaptec, Inc. * 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 * 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 * 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) static void aac_rx_start_adapter(struct aac_dev *dev)
{ {
struct aac_init *init; union aac_init *init;
init = dev->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 // We can only use a 32 bit address here
rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL); 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; 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; 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->a_ops.adapter_enable_int = aac_rx_disable_interrupt;
dev->OIMR = status = rx_readb (dev, MUnit.OIMR); dev->OIMR = status = rx_readb (dev, MUnit.OIMR);
if ((((status & 0x0c) != 0x0c) || aac_reset_devices || reset_devices) && 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 */ /* Make sure the Hardware FIFO is empty */
while ((++restart < 512) && while ((++restart < 512) &&
(rx_readl(dev, MUnit.OutboundQueue) != 0xFFFFFFFFL)); (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]); status = rx_readl(dev, MUnit.OMRx[0]);
if (status & KERNEL_PANIC) { 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; goto error_iounmap;
++restart; ++restart;
} }
@ -606,7 +608,8 @@ int _aac_rx_init(struct aac_dev *dev)
((startup_timeout > 60) ((startup_timeout > 60)
? (startup_timeout - 60) ? (startup_timeout - 60)
: (startup_timeout / 2))))) { : (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; start = jiffies;
++restart; ++restart;
} }

View File

@ -6,7 +6,8 @@
* Adaptec aacraid device driver for Linux. * Adaptec aacraid device driver for Linux.
* *
* Copyright (c) 2000-2010 Adaptec, Inc. * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -245,19 +246,19 @@ static void aac_sa_interrupt_adapter (struct aac_dev *dev)
static void aac_sa_start_adapter(struct aac_dev *dev) static void aac_sa_start_adapter(struct aac_dev *dev)
{ {
struct aac_init *init; union aac_init *init;
/* /*
* Fill in the remaining pieces of the init. * Fill in the remaining pieces of the init.
*/ */
init = dev->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 */ /* We can only use a 32 bit address here */
sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS,
(u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0, (u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL, NULL);
} }
static int aac_sa_restart_adapter(struct aac_dev *dev, int bled) static int aac_sa_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type)
{ {
return -EINVAL; return -EINVAL;
} }

View File

@ -6,7 +6,8 @@
* Adaptec aacraid device driver for Linux. * Adaptec aacraid device driver for Linux.
* *
* Copyright (c) 2000-2010 Adaptec, Inc. * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -135,8 +136,16 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
if (mode & AAC_INT_MODE_AIF) { if (mode & AAC_INT_MODE_AIF) {
/* handle AIF */ /* handle AIF */
if (dev->aif_thread && dev->fsa_dev) if (dev->sa_firmware) {
aac_intr_normal(dev, 0, 2, 0, NULL); u32 events = src_readl(dev, MUnit.SCR0);
aac_intr_normal(dev, events, 1, 0, NULL);
writel(events, &dev->IndexRegs->Mailbox[0]);
src_writel(dev, MUnit.IDR, 1 << 23);
} else {
if (dev->aif_thread && dev->fsa_dev)
aac_intr_normal(dev, 0, 2, 0, NULL);
}
if (dev->msi_enabled) if (dev->msi_enabled)
aac_src_access_devreg(dev, AAC_CLEAR_AIF_BIT); aac_src_access_devreg(dev, AAC_CLEAR_AIF_BIT);
mode = 0; mode = 0;
@ -148,17 +157,19 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
for (;;) { for (;;) {
isFastResponse = 0; isFastResponse = 0;
/* remove toggle bit (31) */ /* remove toggle bit (31) */
handle = (dev->host_rrq[index] & 0x7fffffff); handle = le32_to_cpu((dev->host_rrq[index])
/* check fast response bit (30) */ & 0x7fffffff);
/* check fast response bits (30, 1) */
if (handle & 0x40000000) if (handle & 0x40000000)
isFastResponse = 1; isFastResponse = 1;
handle &= 0x0000ffff; handle &= 0x0000ffff;
if (handle == 0) if (handle == 0)
break; break;
handle >>= 2;
if (dev->msi_enabled && dev->max_msix > 1) if (dev->msi_enabled && dev->max_msix > 1)
atomic_dec(&dev->rrq_outstanding[vector_no]); atomic_dec(&dev->rrq_outstanding[vector_no]);
aac_intr_normal(dev, handle, 0, isFastResponse, NULL);
dev->host_rrq[index++] = 0; dev->host_rrq[index++] = 0;
aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL);
if (index == (vector_no + 1) * dev->vector_cap) if (index == (vector_no + 1) * dev->vector_cap)
index = vector_no * dev->vector_cap; index = vector_no * dev->vector_cap;
dev->host_rrq_idx[vector_no] = index; dev->host_rrq_idx[vector_no] = index;
@ -384,7 +395,7 @@ static void aac_src_notify_adapter(struct aac_dev *dev, u32 event)
static void aac_src_start_adapter(struct aac_dev *dev) static void aac_src_start_adapter(struct aac_dev *dev)
{ {
struct aac_init *init; union aac_init *init;
int i; int i;
/* reset host_rrq_idx first */ /* reset host_rrq_idx first */
@ -392,14 +403,26 @@ static void aac_src_start_adapter(struct aac_dev *dev)
dev->host_rrq_idx[i] = i * dev->vector_cap; dev->host_rrq_idx[i] = i * dev->vector_cap;
atomic_set(&dev->rrq_outstanding[i], 0); atomic_set(&dev->rrq_outstanding[i], 0);
} }
atomic_set(&dev->msix_counter, 0);
dev->fibs_pushed_no = 0; dev->fibs_pushed_no = 0;
init = dev->init; init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds()); if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) {
init->r8.host_elapsed_seconds = cpu_to_le32(get_seconds());
src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS,
lower_32_bits(dev->init_pa),
upper_32_bits(dev->init_pa),
sizeof(struct _r8) +
(AAC_MAX_HRRQ - 1) * sizeof(struct _rrq),
0, 0, 0, NULL, NULL, NULL, NULL, NULL);
} else {
init->r7.host_elapsed_seconds = cpu_to_le32(get_seconds());
// We can only use a 32 bit address here
src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS,
(u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL);
}
/* We can only use a 32 bit address here */
src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
} }
/** /**
@ -435,6 +458,11 @@ static int aac_src_check_health(struct aac_dev *dev)
return 0; return 0;
} }
static inline u32 aac_get_vector(struct aac_dev *dev)
{
return atomic_inc_return(&dev->msix_counter)%dev->max_msix;
}
/** /**
* aac_src_deliver_message * aac_src_deliver_message
* @fib: fib to issue * @fib: fib to issue
@ -448,66 +476,125 @@ static int aac_src_deliver_message(struct fib *fib)
u32 fibsize; u32 fibsize;
dma_addr_t address; dma_addr_t address;
struct aac_fib_xporthdr *pFibX; struct aac_fib_xporthdr *pFibX;
int native_hba;
#if !defined(writeq) #if !defined(writeq)
unsigned long flags; unsigned long flags;
#endif #endif
u16 hdr_size = le16_to_cpu(fib->hw_fib_va->header.Size);
u16 vector_no; u16 vector_no;
atomic_inc(&q->numpending); atomic_inc(&q->numpending);
if (dev->msi_enabled && fib->hw_fib_va->header.Command != AifRequest && native_hba = (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA) ? 1 : 0;
dev->max_msix > 1) {
vector_no = fib->vector_no;
fib->hw_fib_va->header.Handle += (vector_no << 16); if (dev->msi_enabled && dev->max_msix > 1 &&
(native_hba || fib->hw_fib_va->header.Command != AifRequest)) {
if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE3)
&& dev->sa_firmware)
vector_no = aac_get_vector(dev);
else
vector_no = fib->vector_no;
if (native_hba) {
if (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA_TMF) {
struct aac_hba_tm_req *tm_req;
tm_req = (struct aac_hba_tm_req *)
fib->hw_fib_va;
if (tm_req->iu_type ==
HBA_IU_TYPE_SCSI_TM_REQ) {
((struct aac_hba_tm_req *)
fib->hw_fib_va)->reply_qid
= vector_no;
((struct aac_hba_tm_req *)
fib->hw_fib_va)->request_id
+= (vector_no << 16);
} else {
((struct aac_hba_reset_req *)
fib->hw_fib_va)->reply_qid
= vector_no;
((struct aac_hba_reset_req *)
fib->hw_fib_va)->request_id
+= (vector_no << 16);
}
} else {
((struct aac_hba_cmd_req *)
fib->hw_fib_va)->reply_qid
= vector_no;
((struct aac_hba_cmd_req *)
fib->hw_fib_va)->request_id
+= (vector_no << 16);
}
} else {
fib->hw_fib_va->header.Handle += (vector_no << 16);
}
} else { } else {
vector_no = 0; vector_no = 0;
} }
atomic_inc(&dev->rrq_outstanding[vector_no]); atomic_inc(&dev->rrq_outstanding[vector_no]);
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) { if (native_hba) {
/* Calculate the amount to the fibsize bits */
fibsize = (hdr_size + 127) / 128 - 1;
if (fibsize > (ALIGN32 - 1))
return -EMSGSIZE;
/* New FIB header, 32-bit */
address = fib->hw_fib_pa; address = fib->hw_fib_pa;
fib->hw_fib_va->header.StructType = FIB_MAGIC2; fibsize = (fib->hbacmd_size + 127) / 128 - 1;
fib->hw_fib_va->header.SenderFibAddress = (u32)address; if (fibsize > 31)
fib->hw_fib_va->header.u.TimeStamp = 0; fibsize = 31;
BUG_ON(upper_32_bits(address) != 0L);
address |= fibsize; address |= fibsize;
} else {
/* Calculate the amount to the fibsize bits */
fibsize = (sizeof(struct aac_fib_xporthdr) + hdr_size + 127) / 128 - 1;
if (fibsize > (ALIGN32 - 1))
return -EMSGSIZE;
/* Fill XPORT header */
pFibX = (void *)fib->hw_fib_va - sizeof(struct aac_fib_xporthdr);
pFibX->Handle = cpu_to_le32(fib->hw_fib_va->header.Handle);
pFibX->HostAddress = cpu_to_le64(fib->hw_fib_pa);
pFibX->Size = cpu_to_le32(hdr_size);
/*
* The xport header has been 32-byte aligned for us so that fibsize
* can be masked out of this address by hardware. -- BenC
*/
address = fib->hw_fib_pa - sizeof(struct aac_fib_xporthdr);
if (address & (ALIGN32 - 1))
return -EINVAL;
address |= fibsize;
}
#if defined(writeq) #if defined(writeq)
src_writeq(dev, MUnit.IQ_L, (u64)address); src_writeq(dev, MUnit.IQN_L, (u64)address);
#else #else
spin_lock_irqsave(&fib->dev->iq_lock, flags); spin_lock_irqsave(&fib->dev->iq_lock, flags);
src_writel(dev, MUnit.IQ_H, upper_32_bits(address) & 0xffffffff); src_writel(dev, MUnit.IQN_H,
src_writel(dev, MUnit.IQ_L, address & 0xffffffff); upper_32_bits(address) & 0xffffffff);
spin_unlock_irqrestore(&fib->dev->iq_lock, flags); src_writel(dev, MUnit.IQN_L, address & 0xffffffff);
spin_unlock_irqrestore(&fib->dev->iq_lock, flags);
#endif #endif
} else {
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2 ||
dev->comm_interface == AAC_COMM_MESSAGE_TYPE3) {
/* Calculate the amount to the fibsize bits */
fibsize = (le16_to_cpu(fib->hw_fib_va->header.Size)
+ 127) / 128 - 1;
/* New FIB header, 32-bit */
address = fib->hw_fib_pa;
fib->hw_fib_va->header.StructType = FIB_MAGIC2;
fib->hw_fib_va->header.SenderFibAddress =
cpu_to_le32((u32)address);
fib->hw_fib_va->header.u.TimeStamp = 0;
WARN_ON(upper_32_bits(address) != 0L);
} else {
/* Calculate the amount to the fibsize bits */
fibsize = (sizeof(struct aac_fib_xporthdr) +
le16_to_cpu(fib->hw_fib_va->header.Size)
+ 127) / 128 - 1;
/* Fill XPORT header */
pFibX = (struct aac_fib_xporthdr *)
((unsigned char *)fib->hw_fib_va -
sizeof(struct aac_fib_xporthdr));
pFibX->Handle = fib->hw_fib_va->header.Handle;
pFibX->HostAddress =
cpu_to_le64((u64)fib->hw_fib_pa);
pFibX->Size = cpu_to_le32(
le16_to_cpu(fib->hw_fib_va->header.Size));
address = fib->hw_fib_pa -
(u64)sizeof(struct aac_fib_xporthdr);
}
if (fibsize > 31)
fibsize = 31;
address |= fibsize;
#if defined(writeq)
src_writeq(dev, MUnit.IQ_L, (u64)address);
#else
spin_lock_irqsave(&fib->dev->iq_lock, flags);
src_writel(dev, MUnit.IQ_H,
upper_32_bits(address) & 0xffffffff);
src_writel(dev, MUnit.IQ_L, address & 0xffffffff);
spin_unlock_irqrestore(&fib->dev->iq_lock, flags);
#endif
}
return 0; return 0;
} }
@ -553,52 +640,117 @@ static int aac_srcv_ioremap(struct aac_dev *dev, u32 size)
dev->base = dev->regs.src.bar0 = NULL; dev->base = dev->regs.src.bar0 = NULL;
return 0; return 0;
} }
dev->base = dev->regs.src.bar0 = ioremap(dev->base_start, size);
if (dev->base == NULL) dev->regs.src.bar1 =
ioremap(pci_resource_start(dev->pdev, 2), AAC_MIN_SRCV_BAR1_SIZE);
dev->base = NULL;
if (dev->regs.src.bar1 == NULL)
return -1; return -1;
dev->base = dev->regs.src.bar0 = ioremap(dev->base_start, size);
if (dev->base == NULL) {
iounmap(dev->regs.src.bar1);
dev->regs.src.bar1 = NULL;
return -1;
}
dev->IndexRegs = &((struct src_registers __iomem *) dev->IndexRegs = &((struct src_registers __iomem *)
dev->base)->u.denali.IndexRegs; dev->base)->u.denali.IndexRegs;
return 0; return 0;
} }
static int aac_src_restart_adapter(struct aac_dev *dev, int bled) static void aac_set_intx_mode(struct aac_dev *dev)
{
if (dev->msi_enabled) {
aac_src_access_devreg(dev, AAC_ENABLE_INTX);
dev->msi_enabled = 0;
msleep(5000); /* Delay 5 seconds */
}
}
static void aac_send_iop_reset(struct aac_dev *dev, int bled)
{ {
u32 var, reset_mask; u32 var, reset_mask;
if (bled >= 0) { bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
if (bled) 0, 0, 0, 0, 0, 0, &var,
printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", &reset_mask, NULL, NULL, NULL);
dev->name, dev->id, bled);
dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL);
if ((bled || (var != 0x00000001)) &&
!dev->doorbell_mask)
return -EINVAL;
else if (dev->doorbell_mask) {
reset_mask = dev->doorbell_mask;
bled = 0;
var = 0x00000001;
}
if ((dev->pdev->device == PMC_DEVICE_S7 || if ((bled || var != 0x00000001) && !dev->doorbell_mask)
dev->pdev->device == PMC_DEVICE_S8 || bled = -EINVAL;
dev->pdev->device == PMC_DEVICE_S9) && dev->msi_enabled) { else if (dev->doorbell_mask) {
aac_src_access_devreg(dev, AAC_ENABLE_INTX); reset_mask = dev->doorbell_mask;
dev->msi_enabled = 0; bled = 0;
msleep(5000); /* Delay 5 seconds */ var = 0x00000001;
}
if (!bled && (dev->supplement_adapter_info.SupportedOptions2 &
AAC_OPTION_DOORBELL_RESET)) {
src_writel(dev, MUnit.IDR, reset_mask);
ssleep(45);
} else {
src_writel(dev, MUnit.IDR, 0x100);
ssleep(45);
}
} }
aac_set_intx_mode(dev);
if (!bled && (dev->supplement_adapter_info.SupportedOptions2 &
AAC_OPTION_DOORBELL_RESET)) {
src_writel(dev, MUnit.IDR, reset_mask);
} else {
src_writel(dev, MUnit.IDR, 0x100);
}
msleep(30000);
}
static void aac_send_hardware_soft_reset(struct aac_dev *dev)
{
u_int32_t val;
val = readl(((char *)(dev->base) + IBW_SWR_OFFSET));
val |= 0x01;
writel(val, ((char *)(dev->base) + IBW_SWR_OFFSET));
msleep_interruptible(20000);
}
static int aac_src_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type)
{
unsigned long status, start;
if (bled < 0)
goto invalid_out;
if (bled)
pr_err("%s%d: adapter kernel panic'd %x.\n",
dev->name, dev->id, bled);
dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
switch (reset_type) {
case IOP_HWSOFT_RESET:
aac_send_iop_reset(dev, bled);
/*
* Check to see if KERNEL_UP_AND_RUNNING
* Wait for the adapter to be up and running.
* If !KERNEL_UP_AND_RUNNING issue HW Soft Reset
*/
status = src_readl(dev, MUnit.OMR);
if (dev->sa_firmware
&& !(status & KERNEL_UP_AND_RUNNING)) {
start = jiffies;
do {
status = src_readl(dev, MUnit.OMR);
if (time_after(jiffies,
start+HZ*SOFT_RESET_TIME)) {
aac_send_hardware_soft_reset(dev);
start = jiffies;
}
} while (!(status & KERNEL_UP_AND_RUNNING));
}
break;
case HW_SOFT_RESET:
if (dev->sa_firmware) {
aac_send_hardware_soft_reset(dev);
aac_set_intx_mode(dev);
}
break;
default:
aac_send_iop_reset(dev, bled);
break;
}
invalid_out:
if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC) if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC)
return -ENODEV; return -ENODEV;
@ -653,14 +805,15 @@ int aac_src_init(struct aac_dev *dev)
dev->a_ops.adapter_sync_cmd = src_sync_cmd; dev->a_ops.adapter_sync_cmd = src_sync_cmd;
dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
if ((aac_reset_devices || reset_devices) && if ((aac_reset_devices || reset_devices) &&
!aac_src_restart_adapter(dev, 0)) !aac_src_restart_adapter(dev, 0, IOP_HWSOFT_RESET))
++restart; ++restart;
/* /*
* Check to see if the board panic'd while booting. * Check to see if the board panic'd while booting.
*/ */
status = src_readl(dev, MUnit.OMR); status = src_readl(dev, MUnit.OMR);
if (status & KERNEL_PANIC) { if (status & KERNEL_PANIC) {
if (aac_src_restart_adapter(dev, aac_src_check_health(dev))) if (aac_src_restart_adapter(dev,
aac_src_check_health(dev), IOP_HWSOFT_RESET))
goto error_iounmap; goto error_iounmap;
++restart; ++restart;
} }
@ -701,7 +854,7 @@ int aac_src_init(struct aac_dev *dev)
? (startup_timeout - 60) ? (startup_timeout - 60)
: (startup_timeout / 2))))) { : (startup_timeout / 2))))) {
if (likely(!aac_src_restart_adapter(dev, if (likely(!aac_src_restart_adapter(dev,
aac_src_check_health(dev)))) aac_src_check_health(dev), IOP_HWSOFT_RESET)))
start = jiffies; start = jiffies;
++restart; ++restart;
} }
@ -798,7 +951,7 @@ int aac_srcv_init(struct aac_dev *dev)
dev->a_ops.adapter_sync_cmd = src_sync_cmd; dev->a_ops.adapter_sync_cmd = src_sync_cmd;
dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
if ((aac_reset_devices || reset_devices) && if ((aac_reset_devices || reset_devices) &&
!aac_src_restart_adapter(dev, 0)) !aac_src_restart_adapter(dev, 0, IOP_HWSOFT_RESET))
++restart; ++restart;
/* /*
* Check to see if flash update is running. * Check to see if flash update is running.
@ -827,7 +980,8 @@ int aac_srcv_init(struct aac_dev *dev)
*/ */
status = src_readl(dev, MUnit.OMR); status = src_readl(dev, MUnit.OMR);
if (status & KERNEL_PANIC) { if (status & KERNEL_PANIC) {
if (aac_src_restart_adapter(dev, aac_src_check_health(dev))) if (aac_src_restart_adapter(dev,
aac_src_check_health(dev), IOP_HWSOFT_RESET))
goto error_iounmap; goto error_iounmap;
++restart; ++restart;
} }
@ -866,7 +1020,8 @@ int aac_srcv_init(struct aac_dev *dev)
((startup_timeout > 60) ((startup_timeout > 60)
? (startup_timeout - 60) ? (startup_timeout - 60)
: (startup_timeout / 2))))) { : (startup_timeout / 2))))) {
if (likely(!aac_src_restart_adapter(dev, aac_src_check_health(dev)))) if (likely(!aac_src_restart_adapter(dev,
aac_src_check_health(dev), IOP_HWSOFT_RESET)))
start = jiffies; start = jiffies;
++restart; ++restart;
} }
@ -897,7 +1052,8 @@ int aac_srcv_init(struct aac_dev *dev)
if (aac_init_adapter(dev) == NULL) if (aac_init_adapter(dev) == NULL)
goto error_iounmap; goto error_iounmap;
if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE2) if ((dev->comm_interface != AAC_COMM_MESSAGE_TYPE2) &&
(dev->comm_interface != AAC_COMM_MESSAGE_TYPE3))
goto error_iounmap; goto error_iounmap;
if (dev->msi_enabled) if (dev->msi_enabled)
aac_src_access_devreg(dev, AAC_ENABLE_MSIX); aac_src_access_devreg(dev, AAC_ENABLE_MSIX);
@ -905,9 +1061,9 @@ int aac_srcv_init(struct aac_dev *dev)
if (aac_acquire_irq(dev)) if (aac_acquire_irq(dev))
goto error_iounmap; goto error_iounmap;
dev->dbg_base = dev->base_start; dev->dbg_base = pci_resource_start(dev->pdev, 2);
dev->dbg_base_mapped = dev->base; dev->dbg_base_mapped = dev->regs.src.bar1;
dev->dbg_size = dev->base_size; dev->dbg_size = AAC_MIN_SRCV_BAR1_SIZE;
dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message; dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message;
aac_adapter_enable_int(dev); aac_adapter_enable_int(dev);

View File

@ -178,37 +178,6 @@ static int scsi_dma_is_ignored_buserr(unsigned char dma_stat)
} }
#if 0
/* Dead code... wasn't called anyway :-) and causes some trouble, because at
* end-of-DMA, both SCSI ints are triggered simultaneously, so the NCR int has
* to clear the DMA int pending bit before it allows other level 6 interrupts.
*/
static void scsi_dma_buserr(int irq, void *dummy)
{
unsigned char dma_stat = tt_scsi_dma.dma_ctrl;
/* Don't do anything if a NCR interrupt is pending. Probably it's just
* masked... */
if (atari_irq_pending(IRQ_TT_MFP_SCSI))
return;
printk("Bad SCSI DMA interrupt! dma_addr=0x%08lx dma_stat=%02x dma_cnt=%08lx\n",
SCSI_DMA_READ_P(dma_addr), dma_stat, SCSI_DMA_READ_P(dma_cnt));
if (dma_stat & 0x80) {
if (!scsi_dma_is_ignored_buserr(dma_stat))
printk("SCSI DMA bus error -- bad DMA programming!\n");
} else {
/* Under normal circumstances we never should get to this point,
* since both interrupts are triggered simultaneously and the 5380
* int has higher priority. When this irq is handled, that DMA
* interrupt is cleared. So a warning message is printed here.
*/
printk("SCSI DMA intr ?? -- this shouldn't happen!\n");
}
}
#endif
static irqreturn_t scsi_tt_intr(int irq, void *dev) static irqreturn_t scsi_tt_intr(int irq, void *dev)
{ {
struct Scsi_Host *instance = dev; struct Scsi_Host *instance = dev;
@ -713,7 +682,8 @@ static int atari_scsi_bus_reset(struct scsi_cmnd *cmd)
if (IS_A_TT()) { if (IS_A_TT()) {
tt_scsi_dma.dma_ctrl = 0; tt_scsi_dma.dma_ctrl = 0;
} else { } else {
st_dma.dma_mode_status = 0x90; if (stdma_is_locked_by(scsi_falcon_intr))
st_dma.dma_mode_status = 0x90;
atari_dma_active = 0; atari_dma_active = 0;
atari_dma_orig_addr = NULL; atari_dma_orig_addr = NULL;
} }
@ -813,7 +783,7 @@ static int __init atari_scsi_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer); atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer);
atari_dma_orig_addr = 0; atari_dma_orig_addr = NULL;
} }
instance = scsi_host_alloc(&atari_scsi_template, instance = scsi_host_alloc(&atari_scsi_template,

View File

@ -84,7 +84,6 @@ static inline void queue_tail_inc(struct be_queue_info *q)
/*ISCSI */ /*ISCSI */
struct be_aic_obj { /* Adaptive interrupt coalescing (AIC) info */ struct be_aic_obj { /* Adaptive interrupt coalescing (AIC) info */
bool enable;
u32 min_eqd; /* in usecs */ u32 min_eqd; /* in usecs */
u32 max_eqd; /* in usecs */ u32 max_eqd; /* in usecs */
u32 prev_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 { struct be_eq_obj {
bool todo_mcc_cq;
bool todo_cq;
u32 cq_count; u32 cq_count;
struct be_queue_info q; struct be_queue_info q;
struct beiscsi_hba *phba; struct beiscsi_hba *phba;

View File

@ -676,10 +676,10 @@ void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
bool embedded, u8 sge_cnt) bool embedded, u8 sge_cnt)
{ {
if (embedded) if (embedded)
wrb->embedded |= MCC_WRB_EMBEDDED_MASK; wrb->emb_sgecnt_special |= MCC_WRB_EMBEDDED_MASK;
else else
wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) << wrb->emb_sgecnt_special |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) <<
MCC_WRB_SGE_CNT_SHIFT; MCC_WRB_SGE_CNT_SHIFT;
wrb->payload_length = payload_len; wrb->payload_length = payload_len;
be_dws_cpu_to_le(wrb, 8); be_dws_cpu_to_le(wrb, 8);
} }
@ -1599,7 +1599,7 @@ int beiscsi_cmd_function_reset(struct beiscsi_hba *phba)
{ {
struct be_ctrl_info *ctrl = &phba->ctrl; struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
struct be_post_sgl_pages_req *req = embedded_payload(wrb); struct be_post_sgl_pages_req *req;
int status; int status;
mutex_lock(&ctrl->mbox_lock); mutex_lock(&ctrl->mbox_lock);
@ -1700,31 +1700,34 @@ int beiscsi_cmd_iscsi_cleanup(struct beiscsi_hba *phba, unsigned short ulp)
struct be_ctrl_info *ctrl = &phba->ctrl; struct be_ctrl_info *ctrl = &phba->ctrl;
struct iscsi_cleanup_req_v1 *req_v1; struct iscsi_cleanup_req_v1 *req_v1;
struct iscsi_cleanup_req *req; struct iscsi_cleanup_req *req;
u16 hdr_ring_id, data_ring_id;
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
int status; int status;
mutex_lock(&ctrl->mbox_lock); mutex_lock(&ctrl->mbox_lock);
wrb = wrb_from_mbox(&ctrl->mbox_mem); wrb = wrb_from_mbox(&ctrl->mbox_mem);
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req));
/** hdr_ring_id = HWI_GET_DEF_HDRQ_ID(phba, ulp);
* TODO: Check with FW folks the chute value to be set. data_ring_id = HWI_GET_DEF_BUFQ_ID(phba, ulp);
* For now, use the ULP_MASK as the chute value.
*/
if (is_chip_be2_be3r(phba)) { if (is_chip_be2_be3r(phba)) {
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req));
req->chute = (1 << ulp); req->chute = (1 << ulp);
req->hdr_ring_id = HWI_GET_DEF_HDRQ_ID(phba, ulp); /* BE2/BE3 FW creates 8-bit ring id */
req->data_ring_id = HWI_GET_DEF_BUFQ_ID(phba, ulp); req->hdr_ring_id = hdr_ring_id;
req->data_ring_id = data_ring_id;
} else { } else {
req_v1 = (struct iscsi_cleanup_req_v1 *)req; req_v1 = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req_v1), true, 0);
be_cmd_hdr_prepare(&req_v1->hdr, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_CLEANUP,
sizeof(*req_v1));
req_v1->hdr.version = 1; req_v1->hdr.version = 1;
req_v1->hdr_ring_id = cpu_to_le16(HWI_GET_DEF_HDRQ_ID(phba, req_v1->chute = (1 << ulp);
ulp)); req_v1->hdr_ring_id = cpu_to_le16(hdr_ring_id);
req_v1->data_ring_id = cpu_to_le16(HWI_GET_DEF_BUFQ_ID(phba, req_v1->data_ring_id = cpu_to_le16(data_ring_id);
ulp));
} }
status = be_mbox_notify(ctrl); status = be_mbox_notify(ctrl);

View File

@ -31,10 +31,16 @@ struct be_sge {
__le32 len; __le32 len;
}; };
#define MCC_WRB_SGE_CNT_SHIFT 3 /* bits 3 - 7 of dword 0 */
#define MCC_WRB_SGE_CNT_MASK 0x1F /* bits 3 - 7 of dword 0 */
struct be_mcc_wrb { struct be_mcc_wrb {
u32 embedded; /* dword 0 */ u32 emb_sgecnt_special; /* dword 0 */
/* bits 0 - embedded */
/* bits 1 - 2 reserved */
/* bits 3 - 7 sge count */
/* bits 8 - 23 reserved */
/* bits 24 - 31 special */
#define MCC_WRB_EMBEDDED_MASK 1
#define MCC_WRB_SGE_CNT_SHIFT 3
#define MCC_WRB_SGE_CNT_MASK 0x1F
u32 payload_length; /* dword 1 */ u32 payload_length; /* dword 1 */
u32 tag0; /* dword 2 */ u32 tag0; /* dword 2 */
u32 tag1; /* dword 3 */ u32 tag1; /* dword 3 */
@ -1133,11 +1139,6 @@ struct tcp_connect_and_offload_out {
} __packed; } __packed;
struct be_mcc_wrb_context {
struct MCC_WRB *wrb;
int *users_final_status;
} __packed;
#define DB_DEF_PDU_RING_ID_MASK 0x3FFF /* bits 0 - 13 */ #define DB_DEF_PDU_RING_ID_MASK 0x3FFF /* bits 0 - 13 */
#define DB_DEF_PDU_CQPROC_MASK 0x3FFF /* bits 16 - 29 */ #define DB_DEF_PDU_CQPROC_MASK 0x3FFF /* bits 16 - 29 */
#define DB_DEF_PDU_REARM_SHIFT 14 #define DB_DEF_PDU_REARM_SHIFT 14

View File

@ -165,33 +165,6 @@ beiscsi_conn_create(struct iscsi_cls_session *cls_session, u32 cid)
return cls_conn; return cls_conn;
} }
/**
* beiscsi_bindconn_cid - Bind the beiscsi_conn with phba connection table
* @beiscsi_conn: The pointer to beiscsi_conn structure
* @phba: The phba instance
* @cid: The cid to free
*/
static int beiscsi_bindconn_cid(struct beiscsi_hba *phba,
struct beiscsi_conn *beiscsi_conn,
unsigned int cid)
{
uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
if (phba->conn_table[cri_index]) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : Connection table already occupied. Detected clash\n");
return -EINVAL;
} else {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : phba->conn_table[%d]=%p(beiscsi_conn)\n",
cri_index, beiscsi_conn);
phba->conn_table[cri_index] = beiscsi_conn;
}
return 0;
}
/** /**
* beiscsi_conn_bind - Binds iscsi session/connection with TCP connection * beiscsi_conn_bind - Binds iscsi session/connection with TCP connection
* @cls_session: pointer to iscsi cls session * @cls_session: pointer to iscsi cls session
@ -212,6 +185,7 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
struct hwi_wrb_context *pwrb_context; struct hwi_wrb_context *pwrb_context;
struct beiscsi_endpoint *beiscsi_ep; struct beiscsi_endpoint *beiscsi_ep;
struct iscsi_endpoint *ep; struct iscsi_endpoint *ep;
uint16_t cri_index;
ep = iscsi_lookup_endpoint(transport_fd); ep = iscsi_lookup_endpoint(transport_fd);
if (!ep) if (!ep)
@ -229,20 +203,34 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
return -EEXIST; return -EEXIST;
} }
cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid);
pwrb_context = &phwi_ctrlr->wrb_context[BE_GET_CRI_FROM_CID( if (phba->conn_table[cri_index]) {
beiscsi_ep->ep_cid)]; if (beiscsi_conn != phba->conn_table[cri_index] ||
beiscsi_ep != phba->conn_table[cri_index]->ep) {
__beiscsi_log(phba, KERN_ERR,
"BS_%d : conn_table not empty at %u: cid %u conn %p:%p\n",
cri_index,
beiscsi_ep->ep_cid,
beiscsi_conn,
phba->conn_table[cri_index]);
return -EINVAL;
}
}
beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid; beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid;
beiscsi_conn->ep = beiscsi_ep; beiscsi_conn->ep = beiscsi_ep;
beiscsi_ep->conn = beiscsi_conn; beiscsi_ep->conn = beiscsi_conn;
/**
* Each connection is associated with a WRBQ kept in wrb_context.
* Store doorbell offset for transmit path.
*/
pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
beiscsi_conn->doorbell_offset = pwrb_context->doorbell_offset; beiscsi_conn->doorbell_offset = pwrb_context->doorbell_offset;
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : beiscsi_conn=%p conn=%p ep_cid=%d\n", "BS_%d : cid %d phba->conn_table[%u]=%p\n",
beiscsi_conn, conn, beiscsi_ep->ep_cid); beiscsi_ep->ep_cid, cri_index, beiscsi_conn);
phba->conn_table[cri_index] = beiscsi_conn;
return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid); return 0;
} }
static int beiscsi_iface_create_ipv4(struct beiscsi_hba *phba) static int beiscsi_iface_create_ipv4(struct beiscsi_hba *phba)
@ -973,9 +961,9 @@ int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
*/ */
static int beiscsi_get_cid(struct beiscsi_hba *phba) static int beiscsi_get_cid(struct beiscsi_hba *phba)
{ {
unsigned short cid = 0xFFFF, cid_from_ulp;
struct ulp_cid_info *cid_info = NULL;
uint16_t cid_avlbl_ulp0, cid_avlbl_ulp1; uint16_t cid_avlbl_ulp0, cid_avlbl_ulp1;
unsigned short cid, cid_from_ulp;
struct ulp_cid_info *cid_info;
/* Find the ULP which has more CID available */ /* Find the ULP which has more CID available */
cid_avlbl_ulp0 = (phba->cid_array_info[BEISCSI_ULP0]) ? cid_avlbl_ulp0 = (phba->cid_array_info[BEISCSI_ULP0]) ?
@ -984,20 +972,27 @@ static int beiscsi_get_cid(struct beiscsi_hba *phba)
BEISCSI_ULP1_AVLBL_CID(phba) : 0; BEISCSI_ULP1_AVLBL_CID(phba) : 0;
cid_from_ulp = (cid_avlbl_ulp0 > cid_avlbl_ulp1) ? cid_from_ulp = (cid_avlbl_ulp0 > cid_avlbl_ulp1) ?
BEISCSI_ULP0 : BEISCSI_ULP1; BEISCSI_ULP0 : BEISCSI_ULP1;
/**
* If iSCSI protocol is loaded only on ULP 0, and when cid_avlbl_ulp
* is ZERO for both, ULP 1 is returned.
* Check if ULP is loaded before getting new CID.
*/
if (!test_bit(cid_from_ulp, (void *)&phba->fw_config.ulp_supported))
return BE_INVALID_CID;
if (test_bit(cid_from_ulp, (void *)&phba->fw_config.ulp_supported)) { cid_info = phba->cid_array_info[cid_from_ulp];
cid_info = phba->cid_array_info[cid_from_ulp]; cid = cid_info->cid_array[cid_info->cid_alloc];
if (!cid_info->avlbl_cids) if (!cid_info->avlbl_cids || cid == BE_INVALID_CID) {
return cid; __beiscsi_log(phba, KERN_ERR,
"BS_%d : failed to get cid: available %u:%u\n",
cid = cid_info->cid_array[cid_info->cid_alloc++]; cid_info->avlbl_cids, cid_info->cid_free);
return BE_INVALID_CID;
if (cid_info->cid_alloc == BEISCSI_GET_CID_COUNT(
phba, cid_from_ulp))
cid_info->cid_alloc = 0;
cid_info->avlbl_cids--;
} }
/* empty the slot */
cid_info->cid_array[cid_info->cid_alloc++] = BE_INVALID_CID;
if (cid_info->cid_alloc == BEISCSI_GET_CID_COUNT(phba, cid_from_ulp))
cid_info->cid_alloc = 0;
cid_info->avlbl_cids--;
return cid; return cid;
} }
@ -1008,22 +1003,28 @@ static int beiscsi_get_cid(struct beiscsi_hba *phba)
*/ */
static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
{ {
uint16_t cid_post_ulp;
struct hwi_controller *phwi_ctrlr;
struct hwi_wrb_context *pwrb_context;
struct ulp_cid_info *cid_info = NULL;
uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
struct hwi_wrb_context *pwrb_context;
struct hwi_controller *phwi_ctrlr;
struct ulp_cid_info *cid_info;
uint16_t cid_post_ulp;
phwi_ctrlr = phba->phwi_ctrlr; phwi_ctrlr = phba->phwi_ctrlr;
pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
cid_post_ulp = pwrb_context->ulp_num; cid_post_ulp = pwrb_context->ulp_num;
cid_info = phba->cid_array_info[cid_post_ulp]; cid_info = phba->cid_array_info[cid_post_ulp];
cid_info->avlbl_cids++; /* fill only in empty slot */
if (cid_info->cid_array[cid_info->cid_free] != BE_INVALID_CID) {
__beiscsi_log(phba, KERN_ERR,
"BS_%d : failed to put cid %u: available %u:%u\n",
cid, cid_info->avlbl_cids, cid_info->cid_free);
return;
}
cid_info->cid_array[cid_info->cid_free++] = cid; cid_info->cid_array[cid_info->cid_free++] = cid;
if (cid_info->cid_free == BEISCSI_GET_CID_COUNT(phba, cid_post_ulp)) if (cid_info->cid_free == BEISCSI_GET_CID_COUNT(phba, cid_post_ulp))
cid_info->cid_free = 0; cid_info->cid_free = 0;
cid_info->avlbl_cids++;
} }
/** /**
@ -1037,8 +1038,8 @@ static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep)
beiscsi_put_cid(phba, beiscsi_ep->ep_cid); beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
beiscsi_ep->phba = NULL; beiscsi_ep->phba = NULL;
phba->ep_array[BE_GET_CRI_FROM_CID /* clear this to track freeing in beiscsi_ep_disconnect */
(beiscsi_ep->ep_cid)] = NULL; phba->ep_array[BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid)] = NULL;
/** /**
* Check if any connection resource allocated by driver * Check if any connection resource allocated by driver
@ -1049,6 +1050,11 @@ static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep)
return; return;
beiscsi_conn = beiscsi_ep->conn; beiscsi_conn = beiscsi_ep->conn;
/**
* Break ep->conn link here so that completions after
* this are ignored.
*/
beiscsi_ep->conn = NULL;
if (beiscsi_conn->login_in_progress) { if (beiscsi_conn->login_in_progress) {
beiscsi_free_mgmt_task_handles(beiscsi_conn, beiscsi_free_mgmt_task_handles(beiscsi_conn,
beiscsi_conn->task); beiscsi_conn->task);
@ -1079,7 +1085,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
"BS_%d : In beiscsi_open_conn\n"); "BS_%d : In beiscsi_open_conn\n");
beiscsi_ep->ep_cid = beiscsi_get_cid(phba); beiscsi_ep->ep_cid = beiscsi_get_cid(phba);
if (beiscsi_ep->ep_cid == 0xFFFF) { if (beiscsi_ep->ep_cid == BE_INVALID_CID) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : No free cid available\n"); "BS_%d : No free cid available\n");
return ret; return ret;
@ -1114,7 +1120,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
nonemb_cmd.size = req_memsize; nonemb_cmd.size = req_memsize;
memset(nonemb_cmd.va, 0, nonemb_cmd.size); memset(nonemb_cmd.va, 0, nonemb_cmd.size);
tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd); tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd);
if (tag <= 0) { if (!tag) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : mgmt_open_connection Failed for cid=%d\n", "BS_%d : mgmt_open_connection Failed for cid=%d\n",
beiscsi_ep->ep_cid); beiscsi_ep->ep_cid);
@ -1284,26 +1290,6 @@ static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag)
return ret; return ret;
} }
/**
* beiscsi_unbind_conn_to_cid - Unbind the beiscsi_conn from phba conn table
* @phba: The phba instance
* @cid: The cid to free
*/
static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba,
unsigned int cid)
{
uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
if (phba->conn_table[cri_index])
phba->conn_table[cri_index] = NULL;
else {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : Connection table Not occupied.\n");
return -EINVAL;
}
return 0;
}
/** /**
* beiscsi_ep_disconnect - Tears down the TCP connection * beiscsi_ep_disconnect - Tears down the TCP connection
* @ep: endpoint to be used * @ep: endpoint to be used
@ -1318,13 +1304,23 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
unsigned int tag; unsigned int tag;
uint8_t mgmt_invalidate_flag, tcp_upload_flag; uint8_t mgmt_invalidate_flag, tcp_upload_flag;
unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH; unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;
uint16_t cri_index;
beiscsi_ep = ep->dd_data; beiscsi_ep = ep->dd_data;
phba = beiscsi_ep->phba; phba = beiscsi_ep->phba;
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BS_%d : In beiscsi_ep_disconnect for ep_cid = %d\n", "BS_%d : In beiscsi_ep_disconnect for ep_cid = %u\n",
beiscsi_ep->ep_cid); beiscsi_ep->ep_cid);
cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid);
if (!phba->ep_array[cri_index]) {
__beiscsi_log(phba, KERN_ERR,
"BS_%d : ep_array at %u cid %u empty\n",
cri_index,
beiscsi_ep->ep_cid);
return;
}
if (beiscsi_ep->conn) { if (beiscsi_ep->conn) {
beiscsi_conn = beiscsi_ep->conn; beiscsi_conn = beiscsi_ep->conn;
iscsi_suspend_queue(beiscsi_conn->conn); iscsi_suspend_queue(beiscsi_conn->conn);
@ -1356,7 +1352,12 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
free_ep: free_ep:
msleep(BEISCSI_LOGOUT_SYNC_DELAY); msleep(BEISCSI_LOGOUT_SYNC_DELAY);
beiscsi_free_ep(beiscsi_ep); beiscsi_free_ep(beiscsi_ep);
beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); if (!phba->conn_table[cri_index])
__beiscsi_log(phba, KERN_ERR,
"BS_%d : conn_table empty at %u: cid %u\n",
cri_index,
beiscsi_ep->ep_cid);
phba->conn_table[cri_index] = NULL;
iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
} }

View File

@ -67,8 +67,6 @@ beiscsi_##_name##_disp(struct device *dev,\
{ \ { \
struct Scsi_Host *shost = class_to_shost(dev);\ struct Scsi_Host *shost = class_to_shost(dev);\
struct beiscsi_hba *phba = iscsi_host_priv(shost); \ struct beiscsi_hba *phba = iscsi_host_priv(shost); \
uint32_t param_val = 0; \
param_val = phba->attr_##_name;\
return snprintf(buf, PAGE_SIZE, "%d\n",\ return snprintf(buf, PAGE_SIZE, "%d\n",\
phba->attr_##_name);\ phba->attr_##_name);\
} }
@ -218,160 +216,156 @@ static int beiscsi_slave_configure(struct scsi_device *sdev)
static int beiscsi_eh_abort(struct scsi_cmnd *sc) static int beiscsi_eh_abort(struct scsi_cmnd *sc)
{ {
struct iscsi_task *abrt_task = (struct iscsi_task *)sc->SCp.ptr;
struct iscsi_cls_session *cls_session; struct iscsi_cls_session *cls_session;
struct iscsi_task *aborted_task = (struct iscsi_task *)sc->SCp.ptr; struct beiscsi_io_task *abrt_io_task;
struct beiscsi_io_task *aborted_io_task;
struct iscsi_conn *conn;
struct beiscsi_conn *beiscsi_conn; struct beiscsi_conn *beiscsi_conn;
struct beiscsi_hba *phba;
struct iscsi_session *session; struct iscsi_session *session;
struct invalidate_command_table *inv_tbl; struct invldt_cmd_tbl inv_tbl;
struct be_dma_mem nonemb_cmd; struct beiscsi_hba *phba;
unsigned int cid, tag, num_invalidate; struct iscsi_conn *conn;
int rc; int rc;
cls_session = starget_to_session(scsi_target(sc->device)); cls_session = starget_to_session(scsi_target(sc->device));
session = cls_session->dd_data; session = cls_session->dd_data;
spin_lock_bh(&session->frwd_lock); /* check if we raced, task just got cleaned up under us */
if (!aborted_task || !aborted_task->sc) { spin_lock_bh(&session->back_lock);
/* we raced */ if (!abrt_task || !abrt_task->sc) {
spin_unlock_bh(&session->frwd_lock); spin_unlock_bh(&session->back_lock);
return SUCCESS; return SUCCESS;
} }
/* get a task ref till FW processes the req for the ICD used */
aborted_io_task = aborted_task->dd_data; __iscsi_get_task(abrt_task);
if (!aborted_io_task->scsi_cmnd) { abrt_io_task = abrt_task->dd_data;
/* raced or invalid command */ conn = abrt_task->conn;
spin_unlock_bh(&session->frwd_lock);
return SUCCESS;
}
spin_unlock_bh(&session->frwd_lock);
/* Invalidate WRB Posted for this Task */
AMAP_SET_BITS(struct amap_iscsi_wrb, invld,
aborted_io_task->pwrb_handle->pwrb,
1);
conn = aborted_task->conn;
beiscsi_conn = conn->dd_data; beiscsi_conn = conn->dd_data;
phba = beiscsi_conn->phba; phba = beiscsi_conn->phba;
/* mark WRB invalid which have been not processed by FW yet */
/* invalidate iocb */ if (is_chip_be2_be3r(phba)) {
cid = beiscsi_conn->beiscsi_conn_cid; AMAP_SET_BITS(struct amap_iscsi_wrb, invld,
inv_tbl = phba->inv_tbl; abrt_io_task->pwrb_handle->pwrb, 1);
memset(inv_tbl, 0x0, sizeof(*inv_tbl)); } else {
inv_tbl->cid = cid; AMAP_SET_BITS(struct amap_iscsi_wrb_v2, invld,
inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index; abrt_io_task->pwrb_handle->pwrb, 1);
num_invalidate = 1;
nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
sizeof(struct invalidate_commands_params_in),
&nonemb_cmd.dma);
if (nonemb_cmd.va == NULL) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH,
"BM_%d : Failed to allocate memory for"
"mgmt_invalidate_icds\n");
return FAILED;
} }
nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); inv_tbl.cid = beiscsi_conn->beiscsi_conn_cid;
inv_tbl.icd = abrt_io_task->psgl_handle->sgl_index;
spin_unlock_bh(&session->back_lock);
tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, rc = beiscsi_mgmt_invalidate_icds(phba, &inv_tbl, 1);
cid, &nonemb_cmd); iscsi_put_task(abrt_task);
if (!tag) { if (rc) {
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH, beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH,
"BM_%d : mgmt_invalidate_icds could not be" "BM_%d : sc %p invalidation failed %d\n",
"submitted\n"); sc, rc);
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return FAILED; return FAILED;
} }
rc = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd);
if (rc != -EBUSY)
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return iscsi_eh_abort(sc); return iscsi_eh_abort(sc);
} }
static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
{ {
struct iscsi_task *abrt_task; struct beiscsi_invldt_cmd_tbl {
struct beiscsi_io_task *abrt_io_task; struct invldt_cmd_tbl tbl[BE_INVLDT_CMD_TBL_SZ];
struct iscsi_conn *conn; struct iscsi_task *task[BE_INVLDT_CMD_TBL_SZ];
struct beiscsi_conn *beiscsi_conn; } *inv_tbl;
struct beiscsi_hba *phba;
struct iscsi_session *session;
struct iscsi_cls_session *cls_session; struct iscsi_cls_session *cls_session;
struct invalidate_command_table *inv_tbl; struct beiscsi_conn *beiscsi_conn;
struct be_dma_mem nonemb_cmd; struct beiscsi_io_task *io_task;
unsigned int cid, tag, i, num_invalidate; struct iscsi_session *session;
int rc; struct beiscsi_hba *phba;
struct iscsi_conn *conn;
struct iscsi_task *task;
unsigned int i, nents;
int rc, more = 0;
/* invalidate iocbs */
cls_session = starget_to_session(scsi_target(sc->device)); cls_session = starget_to_session(scsi_target(sc->device));
session = cls_session->dd_data; session = cls_session->dd_data;
spin_lock_bh(&session->frwd_lock); spin_lock_bh(&session->frwd_lock);
if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) { if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) {
spin_unlock_bh(&session->frwd_lock); spin_unlock_bh(&session->frwd_lock);
return FAILED; return FAILED;
} }
conn = session->leadconn; conn = session->leadconn;
beiscsi_conn = conn->dd_data; beiscsi_conn = conn->dd_data;
phba = beiscsi_conn->phba; phba = beiscsi_conn->phba;
cid = beiscsi_conn->beiscsi_conn_cid;
inv_tbl = phba->inv_tbl;
memset(inv_tbl, 0x0, sizeof(*inv_tbl) * BE2_CMDS_PER_CXN);
num_invalidate = 0;
for (i = 0; i < conn->session->cmds_max; i++) {
abrt_task = conn->session->cmds[i];
abrt_io_task = abrt_task->dd_data;
if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE)
continue;
if (sc->device->lun != abrt_task->sc->device->lun) inv_tbl = kzalloc(sizeof(*inv_tbl), GFP_ATOMIC);
continue; if (!inv_tbl) {
spin_unlock_bh(&session->frwd_lock);
/* Invalidate WRB Posted for this Task */
AMAP_SET_BITS(struct amap_iscsi_wrb, invld,
abrt_io_task->pwrb_handle->pwrb,
1);
inv_tbl->cid = cid;
inv_tbl->icd = abrt_io_task->psgl_handle->sgl_index;
num_invalidate++;
inv_tbl++;
}
spin_unlock_bh(&session->frwd_lock);
inv_tbl = phba->inv_tbl;
nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
sizeof(struct invalidate_commands_params_in),
&nonemb_cmd.dma);
if (nonemb_cmd.va == NULL) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH,
"BM_%d : Failed to allocate memory for" "BM_%d : invldt_cmd_tbl alloc failed\n");
"mgmt_invalidate_icds\n");
return FAILED; return FAILED;
} }
nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); nents = 0;
memset(nonemb_cmd.va, 0, nonemb_cmd.size); /* take back_lock to prevent task from getting cleaned up under us */
tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, spin_lock(&session->back_lock);
cid, &nonemb_cmd); for (i = 0; i < conn->session->cmds_max; i++) {
if (!tag) { task = conn->session->cmds[i];
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH, if (!task->sc)
"BM_%d : mgmt_invalidate_icds could not be" continue;
" submitted\n");
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, if (sc->device->lun != task->sc->device->lun)
nonemb_cmd.va, nonemb_cmd.dma); continue;
return FAILED; /**
* Can't fit in more cmds? Normally this won't happen b'coz
* BEISCSI_CMD_PER_LUN is same as BE_INVLDT_CMD_TBL_SZ.
*/
if (nents == BE_INVLDT_CMD_TBL_SZ) {
more = 1;
break;
}
/* get a task ref till FW processes the req for the ICD used */
__iscsi_get_task(task);
io_task = task->dd_data;
/* mark WRB invalid which have been not processed by FW yet */
if (is_chip_be2_be3r(phba)) {
AMAP_SET_BITS(struct amap_iscsi_wrb, invld,
io_task->pwrb_handle->pwrb, 1);
} else {
AMAP_SET_BITS(struct amap_iscsi_wrb_v2, invld,
io_task->pwrb_handle->pwrb, 1);
}
inv_tbl->tbl[nents].cid = beiscsi_conn->beiscsi_conn_cid;
inv_tbl->tbl[nents].icd = io_task->psgl_handle->sgl_index;
inv_tbl->task[nents] = task;
nents++;
}
spin_unlock_bh(&session->back_lock);
spin_unlock_bh(&session->frwd_lock);
rc = SUCCESS;
if (!nents)
goto end_reset;
if (more) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH,
"BM_%d : number of cmds exceeds size of invalidation table\n");
rc = FAILED;
goto end_reset;
} }
rc = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd); if (beiscsi_mgmt_invalidate_icds(phba, &inv_tbl->tbl[0], nents)) {
if (rc != -EBUSY) beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH,
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, "BM_%d : cid %u scmds invalidation failed\n",
nonemb_cmd.va, nonemb_cmd.dma); beiscsi_conn->beiscsi_conn_cid);
return iscsi_eh_device_reset(sc); rc = FAILED;
}
end_reset:
for (i = 0; i < nents; i++)
iscsi_put_task(inv_tbl->task[i]);
kfree(inv_tbl);
if (rc == SUCCESS)
rc = iscsi_eh_device_reset(sc);
return rc;
} }
/*------------------- PCI Driver operations and data ----------------- */ /*------------------- PCI Driver operations and data ----------------- */
@ -395,6 +389,7 @@ static struct scsi_host_template beiscsi_sht = {
.change_queue_depth = scsi_change_queue_depth, .change_queue_depth = scsi_change_queue_depth,
.slave_configure = beiscsi_slave_configure, .slave_configure = beiscsi_slave_configure,
.target_alloc = iscsi_target_alloc, .target_alloc = iscsi_target_alloc,
.eh_timed_out = iscsi_eh_cmd_timed_out,
.eh_abort_handler = beiscsi_eh_abort, .eh_abort_handler = beiscsi_eh_abort,
.eh_device_reset_handler = beiscsi_eh_device_reset, .eh_device_reset_handler = beiscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_session_reset, .eh_target_reset_handler = iscsi_eh_session_reset,
@ -646,7 +641,6 @@ static void beiscsi_get_params(struct beiscsi_hba *phba)
phba->params.num_sge_per_io = BE2_SGE; phba->params.num_sge_per_io = BE2_SGE;
phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ; phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ;
phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ; phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ;
phba->params.eq_timer = 64;
phba->params.num_eq_entries = 1024; phba->params.num_eq_entries = 1024;
phba->params.num_cq_entries = 1024; phba->params.num_cq_entries = 1024;
phba->params.wrbs_per_cxn = 256; phba->params.wrbs_per_cxn = 256;
@ -964,6 +958,10 @@ beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context,
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&pwrb_context->wrb_lock, flags); spin_lock_irqsave(&pwrb_context->wrb_lock, flags);
if (!pwrb_context->wrb_handles_available) {
spin_unlock_irqrestore(&pwrb_context->wrb_lock, flags);
return NULL;
}
pwrb_handle = pwrb_context->pwrb_handle_base[pwrb_context->alloc_index]; pwrb_handle = pwrb_context->pwrb_handle_base[pwrb_context->alloc_index];
pwrb_context->wrb_handles_available--; pwrb_context->wrb_handles_available--;
if (pwrb_context->alloc_index == (wrbs_per_cxn - 1)) if (pwrb_context->alloc_index == (wrbs_per_cxn - 1))
@ -1014,6 +1012,7 @@ beiscsi_put_wrb_handle(struct hwi_wrb_context *pwrb_context,
pwrb_context->free_index = 0; pwrb_context->free_index = 0;
else else
pwrb_context->free_index++; pwrb_context->free_index++;
pwrb_handle->pio_handle = NULL;
spin_unlock_irqrestore(&pwrb_context->wrb_lock, flags); spin_unlock_irqrestore(&pwrb_context->wrb_lock, flags);
} }
@ -1224,6 +1223,7 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
uint16_t wrb_index, cid, cri_index; uint16_t wrb_index, cid, cri_index;
struct hwi_controller *phwi_ctrlr; struct hwi_controller *phwi_ctrlr;
struct wrb_handle *pwrb_handle; struct wrb_handle *pwrb_handle;
struct iscsi_session *session;
struct iscsi_task *task; struct iscsi_task *task;
phwi_ctrlr = phba->phwi_ctrlr; phwi_ctrlr = phba->phwi_ctrlr;
@ -1242,8 +1242,12 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,
cri_index = BE_GET_CRI_FROM_CID(cid); cri_index = BE_GET_CRI_FROM_CID(cid);
pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index]; pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index];
session = beiscsi_conn->conn->session;
spin_lock_bh(&session->back_lock);
task = pwrb_handle->pio_handle; task = pwrb_handle->pio_handle;
iscsi_put_task(task); if (task)
__iscsi_put_task(task);
spin_unlock_bh(&session->back_lock);
} }
static void static void
@ -1323,16 +1327,15 @@ static void adapter_get_sol_cqe(struct beiscsi_hba *phba,
static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
struct beiscsi_hba *phba, struct sol_cqe *psol) struct beiscsi_hba *phba, struct sol_cqe *psol)
{ {
struct hwi_wrb_context *pwrb_context;
struct wrb_handle *pwrb_handle;
struct iscsi_wrb *pwrb = NULL;
struct hwi_controller *phwi_ctrlr;
struct iscsi_task *task;
unsigned int type;
struct iscsi_conn *conn = beiscsi_conn->conn; struct iscsi_conn *conn = beiscsi_conn->conn;
struct iscsi_session *session = conn->session; struct iscsi_session *session = conn->session;
struct common_sol_cqe csol_cqe = {0}; struct common_sol_cqe csol_cqe = {0};
struct hwi_wrb_context *pwrb_context;
struct hwi_controller *phwi_ctrlr;
struct wrb_handle *pwrb_handle;
struct iscsi_task *task;
uint16_t cri_index = 0; uint16_t cri_index = 0;
uint8_t type;
phwi_ctrlr = phba->phwi_ctrlr; phwi_ctrlr = phba->phwi_ctrlr;
@ -1345,11 +1348,14 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,
pwrb_handle = pwrb_context->pwrb_handle_basestd[ pwrb_handle = pwrb_context->pwrb_handle_basestd[
csol_cqe.wrb_index]; csol_cqe.wrb_index];
spin_lock_bh(&session->back_lock);
task = pwrb_handle->pio_handle; task = pwrb_handle->pio_handle;
pwrb = pwrb_handle->pwrb; if (!task) {
spin_unlock_bh(&session->back_lock);
return;
}
type = ((struct beiscsi_io_task *)task->dd_data)->wrb_type; type = ((struct beiscsi_io_task *)task->dd_data)->wrb_type;
spin_lock_bh(&session->back_lock);
switch (type) { switch (type) {
case HWH_TYPE_IO: case HWH_TYPE_IO:
case HWH_TYPE_IO_RD: case HWH_TYPE_IO_RD:
@ -1711,13 +1717,12 @@ beiscsi_hdq_post_handles(struct beiscsi_hba *phba,
struct list_head *hfree_list; struct list_head *hfree_list;
struct phys_addr *pasync_sge; struct phys_addr *pasync_sge;
u32 ring_id, doorbell = 0; u32 ring_id, doorbell = 0;
u16 index, num_entries;
u32 doorbell_offset; u32 doorbell_offset;
u16 prod = 0, cons; u16 prod = 0, cons;
u16 index;
phwi_ctrlr = phba->phwi_ctrlr; phwi_ctrlr = phba->phwi_ctrlr;
pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num); pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num);
num_entries = pasync_ctx->num_entries;
if (header) { if (header) {
cons = pasync_ctx->async_header.free_entries; cons = pasync_ctx->async_header.free_entries;
hfree_list = &pasync_ctx->async_header.free_list; hfree_list = &pasync_ctx->async_header.free_list;
@ -2374,13 +2379,10 @@ static int hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
static void beiscsi_find_mem_req(struct beiscsi_hba *phba) static void beiscsi_find_mem_req(struct beiscsi_hba *phba)
{ {
uint8_t mem_descr_index, ulp_num; uint8_t mem_descr_index, ulp_num;
unsigned int num_cq_pages, num_async_pdu_buf_pages; unsigned int num_async_pdu_buf_pages;
unsigned int num_async_pdu_data_pages, wrb_sz_per_cxn; unsigned int num_async_pdu_data_pages, wrb_sz_per_cxn;
unsigned int num_async_pdu_buf_sgl_pages, num_async_pdu_data_sgl_pages; unsigned int num_async_pdu_buf_sgl_pages, num_async_pdu_data_sgl_pages;
num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \
sizeof(struct sol_cqe));
phba->params.hwi_ws_sz = sizeof(struct hwi_controller); phba->params.hwi_ws_sz = sizeof(struct hwi_controller);
phba->mem_req[ISCSI_MEM_GLOBAL_HEADER] = 2 * phba->mem_req[ISCSI_MEM_GLOBAL_HEADER] = 2 *
@ -2737,7 +2739,7 @@ static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)
for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {
if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) {
/* get async_ctx for each ULP */ /* get async_ctx for each ULP */
mem_descr = (struct be_mem_descriptor *)phba->init_mem; mem_descr = (struct be_mem_descriptor *)phba->init_mem;
mem_descr += (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + mem_descr += (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 +
(ulp_num * MEM_DESCR_OFFSET)); (ulp_num * MEM_DESCR_OFFSET));
@ -3367,7 +3369,7 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba,
struct hwi_context_memory *phwi_context, struct hwi_context_memory *phwi_context,
struct hwi_controller *phwi_ctrlr) struct hwi_controller *phwi_ctrlr)
{ {
unsigned int wrb_mem_index, offset, size, num_wrb_rings; unsigned int num_wrb_rings;
u64 pa_addr_lo; u64 pa_addr_lo;
unsigned int idx, num, i, ulp_num; unsigned int idx, num, i, ulp_num;
struct mem_array *pwrb_arr; struct mem_array *pwrb_arr;
@ -3432,10 +3434,6 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba,
} }
for (i = 0; i < phba->params.cxns_per_ctrl; i++) { for (i = 0; i < phba->params.cxns_per_ctrl; i++) {
wrb_mem_index = 0;
offset = 0;
size = 0;
if (ulp_count > 1) { if (ulp_count > 1) {
ulp_base_num = (ulp_base_num + 1) % BEISCSI_ULP_COUNT; ulp_base_num = (ulp_base_num + 1) % BEISCSI_ULP_COUNT;
@ -3663,7 +3661,6 @@ static void hwi_cleanup_port(struct beiscsi_hba *phba)
struct be_ctrl_info *ctrl = &phba->ctrl; struct be_ctrl_info *ctrl = &phba->ctrl;
struct hwi_controller *phwi_ctrlr; struct hwi_controller *phwi_ctrlr;
struct hwi_context_memory *phwi_context; struct hwi_context_memory *phwi_context;
struct hd_async_context *pasync_ctx;
int i, eq_for_mcc, ulp_num; int i, eq_for_mcc, ulp_num;
for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++)
@ -3700,8 +3697,6 @@ static void hwi_cleanup_port(struct beiscsi_hba *phba)
q = &phwi_context->be_def_dataq[ulp_num]; q = &phwi_context->be_def_dataq[ulp_num];
if (q->created) if (q->created)
beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ);
pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num];
} }
} }
@ -3804,7 +3799,6 @@ static int hwi_init_port(struct beiscsi_hba *phba)
/** /**
* Now that the default PDU rings have been created, * Now that the default PDU rings have been created,
* let EP know about it. * let EP know about it.
* Call beiscsi_cmd_iscsi_cleanup before posting?
*/ */
beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_HDR, beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_HDR,
ulp_num); ulp_num);
@ -3850,14 +3844,6 @@ static int hwi_init_port(struct beiscsi_hba *phba)
phwi_ctrlr->wrb_context[cri].cid] = phwi_ctrlr->wrb_context[cri].cid] =
async_arr_idx++; async_arr_idx++;
} }
/**
* Now that the default PDU rings have been created,
* let EP know about it.
*/
beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_HDR,
ulp_num);
beiscsi_hdq_post_handles(phba, BEISCSI_DEFQ_DATA,
ulp_num);
} }
} }
@ -3934,31 +3920,6 @@ static void beiscsi_free_mem(struct beiscsi_hba *phba)
kfree(phba->phwi_ctrlr); kfree(phba->phwi_ctrlr);
} }
static int beiscsi_init_controller(struct beiscsi_hba *phba)
{
int ret = -ENOMEM;
ret = beiscsi_get_memory(phba);
if (ret < 0) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : beiscsi_dev_probe -"
"Failed in beiscsi_alloc_memory\n");
return ret;
}
ret = hwi_init_controller(phba);
if (ret)
goto free_init;
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
"BM_%d : Return success from beiscsi_init_controller");
return 0;
free_init:
beiscsi_free_mem(phba);
return ret;
}
static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)
{ {
struct be_mem_descriptor *mem_descr_sglh, *mem_descr_sg; struct be_mem_descriptor *mem_descr_sglh, *mem_descr_sg;
@ -4089,9 +4050,10 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
} }
/* Allocate memory for CID array */ /* Allocate memory for CID array */
ptr_cid_info->cid_array = kzalloc(sizeof(void *) * ptr_cid_info->cid_array =
BEISCSI_GET_CID_COUNT(phba, kcalloc(BEISCSI_GET_CID_COUNT(phba, ulp_num),
ulp_num), GFP_KERNEL); sizeof(*ptr_cid_info->cid_array),
GFP_KERNEL);
if (!ptr_cid_info->cid_array) { if (!ptr_cid_info->cid_array) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : Failed to allocate memory" "BM_%d : Failed to allocate memory"
@ -4231,33 +4193,30 @@ static int beiscsi_init_port(struct beiscsi_hba *phba)
{ {
int ret; int ret;
ret = beiscsi_init_controller(phba); ret = hwi_init_controller(phba);
if (ret < 0) { if (ret < 0) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : beiscsi_dev_probe - Failed in" "BM_%d : init controller failed\n");
"beiscsi_init_controller\n");
return ret; return ret;
} }
ret = beiscsi_init_sgl_handle(phba); ret = beiscsi_init_sgl_handle(phba);
if (ret < 0) { if (ret < 0) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : beiscsi_dev_probe - Failed in" "BM_%d : init sgl handles failed\n");
"beiscsi_init_sgl_handle\n"); goto cleanup_port;
goto do_cleanup_ctrlr;
} }
ret = hba_setup_cid_tbls(phba); ret = hba_setup_cid_tbls(phba);
if (ret < 0) { if (ret < 0) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : Failed in hba_setup_cid_tbls\n"); "BM_%d : setup CID table failed\n");
kfree(phba->io_sgl_hndl_base); kfree(phba->io_sgl_hndl_base);
kfree(phba->eh_sgl_hndl_base); kfree(phba->eh_sgl_hndl_base);
goto do_cleanup_ctrlr; goto cleanup_port;
} }
return ret; return ret;
do_cleanup_ctrlr: cleanup_port:
hwi_cleanup_port(phba); hwi_cleanup_port(phba);
return ret; return ret;
} }
@ -5417,10 +5376,10 @@ static int beiscsi_enable_port(struct beiscsi_hba *phba)
phba->shost->max_id = phba->params.cxns_per_ctrl; phba->shost->max_id = phba->params.cxns_per_ctrl;
phba->shost->can_queue = phba->params.ios_per_ctrl; phba->shost->can_queue = phba->params.ios_per_ctrl;
ret = hwi_init_controller(phba); ret = beiscsi_init_port(phba);
if (ret) { if (ret < 0) {
__beiscsi_log(phba, KERN_ERR, __beiscsi_log(phba, KERN_ERR,
"BM_%d : init controller failed %d\n", ret); "BM_%d : init port failed\n");
goto disable_msix; goto disable_msix;
} }
@ -5526,6 +5485,7 @@ static void beiscsi_disable_port(struct beiscsi_hba *phba, int unload)
cancel_work_sync(&pbe_eq->mcc_work); cancel_work_sync(&pbe_eq->mcc_work);
} }
hwi_cleanup_port(phba); hwi_cleanup_port(phba);
beiscsi_cleanup_port(phba);
} }
static void beiscsi_sess_work(struct work_struct *work) static void beiscsi_sess_work(struct work_struct *work)
@ -5638,11 +5598,12 @@ static void beiscsi_eeh_resume(struct pci_dev *pdev)
static int beiscsi_dev_probe(struct pci_dev *pcidev, static int beiscsi_dev_probe(struct pci_dev *pcidev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
struct beiscsi_hba *phba = NULL;
struct hwi_controller *phwi_ctrlr;
struct hwi_context_memory *phwi_context; struct hwi_context_memory *phwi_context;
struct hwi_controller *phwi_ctrlr;
struct beiscsi_hba *phba = NULL;
struct be_eq_obj *pbe_eq; struct be_eq_obj *pbe_eq;
unsigned int s_handle; unsigned int s_handle;
char wq_name[20];
int ret, i; int ret, i;
ret = beiscsi_enable_pci(pcidev); ret = beiscsi_enable_pci(pcidev);
@ -5680,6 +5641,8 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
case OC_DEVICE_ID2: case OC_DEVICE_ID2:
phba->generation = BE_GEN2; phba->generation = BE_GEN2;
phba->iotask_fn = beiscsi_iotask; phba->iotask_fn = beiscsi_iotask;
dev_warn(&pcidev->dev,
"Obsolete/Unsupported BE2 Adapter Family\n");
break; break;
case BE_DEVICE_ID2: case BE_DEVICE_ID2:
case OC_DEVICE_ID3: case OC_DEVICE_ID3:
@ -5735,11 +5698,18 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
phba->shost->max_id = phba->params.cxns_per_ctrl; phba->shost->max_id = phba->params.cxns_per_ctrl;
phba->shost->can_queue = phba->params.ios_per_ctrl; phba->shost->can_queue = phba->params.ios_per_ctrl;
ret = beiscsi_get_memory(phba);
if (ret < 0) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : alloc host mem failed\n");
goto free_port;
}
ret = beiscsi_init_port(phba); ret = beiscsi_init_port(phba);
if (ret < 0) { if (ret < 0) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : beiscsi_dev_probe-" "BM_%d : init port failed\n");
"Failed in beiscsi_init_port\n"); beiscsi_free_mem(phba);
goto free_port; goto free_port;
} }
@ -5754,9 +5724,9 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0; phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0;
snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_%02x_wq", snprintf(wq_name, sizeof(wq_name), "beiscsi_%02x_wq",
phba->shost->host_no); phba->shost->host_no);
phba->wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, phba->wq_name); phba->wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, wq_name);
if (!phba->wq) { if (!phba->wq) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : beiscsi_dev_probe-" "BM_%d : beiscsi_dev_probe-"
@ -5881,7 +5851,6 @@ static void beiscsi_remove(struct pci_dev *pcidev)
/* free all resources */ /* free all resources */
destroy_workqueue(phba->wq); destroy_workqueue(phba->wq);
beiscsi_cleanup_port(phba);
beiscsi_free_mem(phba); beiscsi_free_mem(phba);
/* ctrl uninit */ /* ctrl uninit */

View File

@ -36,7 +36,7 @@
#include <scsi/scsi_transport_iscsi.h> #include <scsi/scsi_transport_iscsi.h>
#define DRV_NAME "be2iscsi" #define DRV_NAME "be2iscsi"
#define BUILD_STR "11.2.0.0" #define BUILD_STR "11.2.1.0"
#define BE_NAME "Emulex OneConnect" \ #define BE_NAME "Emulex OneConnect" \
"Open-iSCSI Driver version" BUILD_STR "Open-iSCSI Driver version" BUILD_STR
#define DRV_DESC BE_NAME " " "Driver" #define DRV_DESC BE_NAME " " "Driver"
@ -57,7 +57,6 @@
#define BE2_IO_DEPTH 1024 #define BE2_IO_DEPTH 1024
#define BE2_MAX_SESSIONS 256 #define BE2_MAX_SESSIONS 256
#define BE2_CMDS_PER_CXN 128
#define BE2_TMFS 16 #define BE2_TMFS 16
#define BE2_NOPOUT_REQ 16 #define BE2_NOPOUT_REQ 16
#define BE2_SGE 32 #define BE2_SGE 32
@ -72,8 +71,13 @@
#define BEISCSI_SGLIST_ELEMENTS 30 #define BEISCSI_SGLIST_ELEMENTS 30
#define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ /**
#define BEISCSI_MAX_SECTORS 1024 /* scsi_host->max_sectors */ * BE_INVLDT_CMD_TBL_SZ is 128 which is total number commands that can
* be invalidated at a time, consider it before changing the value of
* BEISCSI_CMD_PER_LUN.
*/
#define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */
#define BEISCSI_MAX_SECTORS 1024 /* scsi_host->max_sectors */
#define BEISCSI_TEMPLATE_HDR_PER_CXN_SIZE 128 /* Template size per cxn */ #define BEISCSI_TEMPLATE_HDR_PER_CXN_SIZE 128 /* Template size per cxn */
#define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */
@ -239,19 +243,7 @@ struct hba_parameters {
unsigned int num_cq_entries; unsigned int num_cq_entries;
unsigned int num_eq_entries; unsigned int num_eq_entries;
unsigned int wrbs_per_cxn; unsigned int wrbs_per_cxn;
unsigned int crashmode;
unsigned int hba_num;
unsigned int mgmt_ws_sz;
unsigned int hwi_ws_sz; unsigned int hwi_ws_sz;
unsigned int eto;
unsigned int ldto;
unsigned int dbg_flags;
unsigned int num_cxn;
unsigned int eq_timer;
/** /**
* These are calculated from other params. They're here * These are calculated from other params. They're here
* for debug purposes * for debug purposes
@ -272,11 +264,6 @@ struct hba_parameters {
unsigned int num_sge; unsigned int num_sge;
}; };
struct invalidate_command_table {
unsigned short icd;
unsigned short cid;
} __packed;
#define BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cri) \ #define BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cri) \
(phwi_ctrlr->wrb_context[cri].ulp_num) (phwi_ctrlr->wrb_context[cri].ulp_num)
struct hwi_wrb_context { struct hwi_wrb_context {
@ -334,7 +321,6 @@ struct beiscsi_hba {
struct be_bus_address pci_pa; /* CSR */ struct be_bus_address pci_pa; /* CSR */
/* PCI representation of our HBA */ /* PCI representation of our HBA */
struct pci_dev *pcidev; struct pci_dev *pcidev;
unsigned short asic_revision;
unsigned int num_cpus; unsigned int num_cpus;
unsigned int nxt_cqid; unsigned int nxt_cqid;
struct msix_entry msix_entries[MAX_CPUS]; struct msix_entry msix_entries[MAX_CPUS];
@ -355,9 +341,9 @@ struct beiscsi_hba {
spinlock_t io_sgl_lock; spinlock_t io_sgl_lock;
spinlock_t mgmt_sgl_lock; spinlock_t mgmt_sgl_lock;
spinlock_t async_pdu_lock; spinlock_t async_pdu_lock;
unsigned int age;
struct list_head hba_queue; struct list_head hba_queue;
#define BE_MAX_SESSION 2048 #define BE_MAX_SESSION 2048
#define BE_INVALID_CID 0xffff
#define BE_SET_CID_TO_CRI(cri_index, cid) \ #define BE_SET_CID_TO_CRI(cri_index, cid) \
(phba->cid_to_cri_map[cid] = cri_index) (phba->cid_to_cri_map[cid] = cri_index)
#define BE_GET_CRI_FROM_CID(cid) (phba->cid_to_cri_map[cid]) #define BE_GET_CRI_FROM_CID(cid) (phba->cid_to_cri_map[cid])
@ -425,12 +411,10 @@ struct beiscsi_hba {
u8 port_name; u8 port_name;
u8 port_speed; u8 port_speed;
char fw_ver_str[BEISCSI_VER_STRLEN]; char fw_ver_str[BEISCSI_VER_STRLEN];
char wq_name[20];
struct workqueue_struct *wq; /* The actuak work queue */ struct workqueue_struct *wq; /* The actuak work queue */
struct be_ctrl_info ctrl; struct be_ctrl_info ctrl;
unsigned int generation; unsigned int generation;
unsigned int interface_handle; unsigned int interface_handle;
struct invalidate_command_table inv_tbl[128];
struct be_aic_obj aic_obj[MAX_CPUS]; struct be_aic_obj aic_obj[MAX_CPUS];
unsigned int attr_log_enable; unsigned int attr_log_enable;
@ -525,10 +509,6 @@ struct beiscsi_io_task {
struct scsi_cmnd *scsi_cmnd; struct scsi_cmnd *scsi_cmnd;
int num_sg; int num_sg;
struct hwi_wrb_context *pwrb_context; struct hwi_wrb_context *pwrb_context;
unsigned int cmd_sn;
unsigned int flags;
unsigned short cid;
unsigned short header_len;
itt_t libiscsi_itt; itt_t libiscsi_itt;
struct be_cmd_bhs *cmd_bhs; struct be_cmd_bhs *cmd_bhs;
struct be_bus_address bhs_pa; struct be_bus_address bhs_pa;
@ -842,7 +822,7 @@ struct amap_iscsi_wrb_v2 {
u8 diff_enbl; /* DWORD 11 */ u8 diff_enbl; /* DWORD 11 */
u8 u_run; /* DWORD 11 */ u8 u_run; /* DWORD 11 */
u8 o_run; /* DWORD 11 */ u8 o_run; /* DWORD 11 */
u8 invalid; /* DWORD 11 */ u8 invld; /* DWORD 11 */
u8 dsp; /* DWORD 11 */ u8 dsp; /* DWORD 11 */
u8 dmsg; /* DWORD 11 */ u8 dmsg; /* DWORD 11 */
u8 rsvd4; /* DWORD 11 */ u8 rsvd4; /* DWORD 11 */
@ -1042,10 +1022,8 @@ struct hwi_controller {
struct list_head io_sgl_list; struct list_head io_sgl_list;
struct list_head eh_sgl_list; struct list_head eh_sgl_list;
struct sgl_handle *psgl_handle_base; struct sgl_handle *psgl_handle_base;
unsigned int wrb_mem_index;
struct hwi_wrb_context *wrb_context; struct hwi_wrb_context *wrb_context;
struct mcc_wrb *pmcc_wrb_base;
struct be_ring default_pdu_hdr[BEISCSI_ULP_COUNT]; struct be_ring default_pdu_hdr[BEISCSI_ULP_COUNT];
struct be_ring default_pdu_data[BEISCSI_ULP_COUNT]; struct be_ring default_pdu_data[BEISCSI_ULP_COUNT];
struct hwi_context_memory *phwi_ctxt; struct hwi_context_memory *phwi_ctxt;
@ -1062,9 +1040,7 @@ enum hwh_type_enum {
}; };
struct wrb_handle { struct wrb_handle {
enum hwh_type_enum type;
unsigned short wrb_index; unsigned short wrb_index;
struct iscsi_task *pio_handle; struct iscsi_task *pio_handle;
struct iscsi_wrb *pwrb; struct iscsi_wrb *pwrb;
}; };

View File

@ -66,7 +66,6 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
struct bsg_job *job, struct bsg_job *job,
struct be_dma_mem *nonemb_cmd) struct be_dma_mem *nonemb_cmd)
{ {
struct be_cmd_resp_hdr *resp;
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
struct be_sge *mcc_sge; struct be_sge *mcc_sge;
unsigned int tag = 0; unsigned int tag = 0;
@ -76,7 +75,6 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
nonemb_cmd->size = job->request_payload.payload_len; nonemb_cmd->size = job->request_payload.payload_len;
memset(nonemb_cmd->va, 0, nonemb_cmd->size); memset(nonemb_cmd->va, 0, nonemb_cmd->size);
resp = nonemb_cmd->va;
region = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; region = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
sector_size = bsg_req->rqst_data.h_vendor.vendor_cmd[2]; sector_size = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
sector = bsg_req->rqst_data.h_vendor.vendor_cmd[3]; sector = bsg_req->rqst_data.h_vendor.vendor_cmd[3];
@ -128,50 +126,6 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
return tag; return tag;
} }
unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
struct invalidate_command_table *inv_tbl,
unsigned int num_invalidate, unsigned int cid,
struct be_dma_mem *nonemb_cmd)
{
struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb;
struct be_sge *sge;
struct invalidate_commands_params_in *req;
unsigned int i, tag;
mutex_lock(&ctrl->mbox_lock);
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
return 0;
}
req = nonemb_cmd->va;
memset(req, 0, sizeof(*req));
sge = nonembedded_sgl(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS,
sizeof(*req));
req->ref_handle = 0;
req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE;
for (i = 0; i < num_invalidate; i++) {
req->table[i].icd = inv_tbl->icd;
req->table[i].cid = inv_tbl->cid;
req->icd_count++;
inv_tbl++;
}
sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
sge->len = cpu_to_le32(nonemb_cmd->size);
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
return tag;
}
unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba, unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba,
struct beiscsi_endpoint *beiscsi_ep, struct beiscsi_endpoint *beiscsi_ep,
unsigned short cid, unsigned short cid,
@ -1066,7 +1020,6 @@ unsigned int beiscsi_boot_reopen_sess(struct beiscsi_hba *phba)
unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba) unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba)
{ {
struct be_ctrl_info *ctrl = &phba->ctrl; struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_cmd_get_session_resp *resp;
struct be_cmd_get_session_req *req; struct be_cmd_get_session_req *req;
struct be_dma_mem *nonemb_cmd; struct be_dma_mem *nonemb_cmd;
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
@ -1081,7 +1034,7 @@ unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba)
} }
nonemb_cmd = &phba->boot_struct.nonemb_cmd; nonemb_cmd = &phba->boot_struct.nonemb_cmd;
nonemb_cmd->size = sizeof(*resp); nonemb_cmd->size = sizeof(struct be_cmd_get_session_resp);
nonemb_cmd->va = pci_alloc_consistent(phba->ctrl.pdev, nonemb_cmd->va = pci_alloc_consistent(phba->ctrl.pdev,
nonemb_cmd->size, nonemb_cmd->size,
&nonemb_cmd->dma); &nonemb_cmd->dma);
@ -1096,7 +1049,7 @@ unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba)
be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
OPCODE_ISCSI_INI_SESSION_GET_A_SESSION, OPCODE_ISCSI_INI_SESSION_GET_A_SESSION,
sizeof(*resp)); sizeof(struct be_cmd_get_session_resp));
req->session_handle = phba->boot_struct.s_handle; req->session_handle = phba->boot_struct.s_handle;
sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
@ -1309,7 +1262,8 @@ beiscsi_adap_family_disp(struct device *dev, struct device_attribute *attr,
case BE_DEVICE_ID1: case BE_DEVICE_ID1:
case OC_DEVICE_ID1: case OC_DEVICE_ID1:
case OC_DEVICE_ID2: case OC_DEVICE_ID2:
return snprintf(buf, PAGE_SIZE, "BE2 Adapter Family\n"); return snprintf(buf, PAGE_SIZE,
"Obsolete/Unsupported BE2 Adapter Family\n");
break; break;
case BE_DEVICE_ID2: case BE_DEVICE_ID2:
case OC_DEVICE_ID3: case OC_DEVICE_ID3:
@ -1341,7 +1295,7 @@ beiscsi_phys_port_disp(struct device *dev, struct device_attribute *attr,
struct Scsi_Host *shost = class_to_shost(dev); struct Scsi_Host *shost = class_to_shost(dev);
struct beiscsi_hba *phba = iscsi_host_priv(shost); struct beiscsi_hba *phba = iscsi_host_priv(shost);
return snprintf(buf, PAGE_SIZE, "Port Identifier : %d\n", return snprintf(buf, PAGE_SIZE, "Port Identifier : %u\n",
phba->fw_config.phys_port); phba->fw_config.phys_port);
} }
@ -1494,3 +1448,64 @@ void beiscsi_offload_cxn_v2(struct beiscsi_offload_params *params,
(params->dw[offsetof(struct amap_beiscsi_offload_params, (params->dw[offsetof(struct amap_beiscsi_offload_params,
exp_statsn) / 32] + 1)); exp_statsn) / 32] + 1));
} }
int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba,
struct invldt_cmd_tbl *inv_tbl,
unsigned int nents)
{
struct be_ctrl_info *ctrl = &phba->ctrl;
struct invldt_cmds_params_in *req;
struct be_dma_mem nonemb_cmd;
struct be_mcc_wrb *wrb;
unsigned int i, tag;
struct be_sge *sge;
int rc;
if (!nents || nents > BE_INVLDT_CMD_TBL_SZ)
return -EINVAL;
nonemb_cmd.size = sizeof(union be_invldt_cmds_params);
nonemb_cmd.va = pci_zalloc_consistent(phba->ctrl.pdev,
nonemb_cmd.size,
&nonemb_cmd.dma);
if (!nonemb_cmd.va) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH,
"BM_%d : invldt_cmds_params alloc failed\n");
return -ENOMEM;
}
mutex_lock(&ctrl->mbox_lock);
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return -ENOMEM;
}
req = nonemb_cmd.va;
be_wrb_hdr_prepare(wrb, nonemb_cmd.size, false, 1);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS,
sizeof(*req));
req->ref_handle = 0;
req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE;
for (i = 0; i < nents; i++) {
req->table[i].icd = inv_tbl[i].icd;
req->table[i].cid = inv_tbl[i].cid;
req->icd_count++;
}
sge = nonembedded_sgl(wrb);
sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma));
sge->pa_lo = cpu_to_le32(lower_32_bits(nonemb_cmd.dma));
sge->len = cpu_to_le32(nonemb_cmd.size);
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
rc = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd);
if (rc != -EBUSY)
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return rc;
}

View File

@ -36,66 +36,6 @@
#define PCICFG_UE_STATUS_MASK_LOW 0xA8 #define PCICFG_UE_STATUS_MASK_LOW 0xA8
#define PCICFG_UE_STATUS_MASK_HI 0xAC #define PCICFG_UE_STATUS_MASK_HI 0xAC
/**
* Pseudo amap definition in which each bit of the actual structure is defined
* as a byte: used to calculate offset/shift/mask of each field
*/
struct amap_mcc_sge {
u8 pa_lo[32]; /* dword 0 */
u8 pa_hi[32]; /* dword 1 */
u8 length[32]; /* DWORD 2 */
} __packed;
/**
* Pseudo amap definition in which each bit of the actual structure is defined
* as a byte: used to calculate offset/shift/mask of each field
*/
struct amap_mcc_wrb_payload {
union {
struct amap_mcc_sge sgl[19];
u8 embedded[59 * 32]; /* DWORDS 57 to 115 */
} u;
} __packed;
/**
* Pseudo amap definition in which each bit of the actual structure is defined
* as a byte: used to calculate offset/shift/mask of each field
*/
struct amap_mcc_wrb {
u8 embedded; /* DWORD 0 */
u8 rsvd0[2]; /* DWORD 0 */
u8 sge_count[5]; /* DWORD 0 */
u8 rsvd1[16]; /* DWORD 0 */
u8 special[8]; /* DWORD 0 */
u8 payload_length[32];
u8 tag[64]; /* DWORD 2 */
u8 rsvd2[32]; /* DWORD 4 */
struct amap_mcc_wrb_payload payload;
};
struct mcc_sge {
u32 pa_lo; /* dword 0 */
u32 pa_hi; /* dword 1 */
u32 length; /* DWORD 2 */
} __packed;
struct mcc_wrb_payload {
union {
struct mcc_sge sgl[19];
u32 embedded[59]; /* DWORDS 57 to 115 */
} u;
} __packed;
#define MCC_WRB_EMBEDDED_MASK 0x00000001
struct mcc_wrb {
u32 dw[0]; /* DWORD 0 */
u32 payload_length;
u32 tag[2]; /* DWORD 2 */
u32 rsvd2[1]; /* DWORD 4 */
struct mcc_wrb_payload payload;
};
int mgmt_open_connection(struct beiscsi_hba *phba, int mgmt_open_connection(struct beiscsi_hba *phba,
struct sockaddr *dst_addr, struct sockaddr *dst_addr,
struct beiscsi_endpoint *beiscsi_ep, struct beiscsi_endpoint *beiscsi_ep,
@ -104,10 +44,6 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, unsigned int mgmt_upload_connection(struct beiscsi_hba *phba,
unsigned short cid, unsigned short cid,
unsigned int upload_flag); unsigned int upload_flag);
unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
struct invalidate_command_table *inv_tbl,
unsigned int num_invalidate, unsigned int cid,
struct be_dma_mem *nonemb_cmd);
unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
struct beiscsi_hba *phba, struct beiscsi_hba *phba,
struct bsg_job *job, struct bsg_job *job,
@ -134,24 +70,31 @@ union iscsi_invalidate_connection_params {
struct iscsi_invalidate_connection_params_out response; struct iscsi_invalidate_connection_params_out response;
} __packed; } __packed;
struct invalidate_commands_params_in { #define BE_INVLDT_CMD_TBL_SZ 128
struct invldt_cmd_tbl {
unsigned short icd;
unsigned short cid;
} __packed;
struct invldt_cmds_params_in {
struct be_cmd_req_hdr hdr; struct be_cmd_req_hdr hdr;
unsigned int ref_handle; unsigned int ref_handle;
unsigned int icd_count; unsigned int icd_count;
struct invalidate_command_table table[128]; struct invldt_cmd_tbl table[BE_INVLDT_CMD_TBL_SZ];
unsigned short cleanup_type; unsigned short cleanup_type;
unsigned short unused; unsigned short unused;
} __packed; } __packed;
struct invalidate_commands_params_out { struct invldt_cmds_params_out {
struct be_cmd_resp_hdr hdr;
unsigned int ref_handle; unsigned int ref_handle;
unsigned int icd_count; unsigned int icd_count;
unsigned int icd_status[128]; unsigned int icd_status[BE_INVLDT_CMD_TBL_SZ];
} __packed; } __packed;
union invalidate_commands_params { union be_invldt_cmds_params {
struct invalidate_commands_params_in request; struct invldt_cmds_params_in request;
struct invalidate_commands_params_out response; struct invldt_cmds_params_out response;
} __packed; } __packed;
struct mgmt_hba_attributes { struct mgmt_hba_attributes {
@ -231,16 +174,6 @@ struct be_bsg_vendor_cmd {
#define GET_MGMT_CONTROLLER_WS(phba) (phba->pmgmt_ws) #define GET_MGMT_CONTROLLER_WS(phba) (phba->pmgmt_ws)
/* MGMT CMD flags */
#define MGMT_CMDH_FREE (1<<0)
/* --- MGMT_ERROR_CODES --- */
/* Error Codes returned in the status field of the CMD response header */
#define MGMT_STATUS_SUCCESS 0 /* The CMD completed without errors */
#define MGMT_STATUS_FAILED 1 /* Error status in the Status field of */
/* the CMD_RESPONSE_HEADER */
#define ISCSI_GET_PDU_TEMPLATE_ADDRESS(pc, pa) {\ #define ISCSI_GET_PDU_TEMPLATE_ADDRESS(pc, pa) {\
pa->lo = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\ pa->lo = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\
bus_address.u.a32.address_lo; \ bus_address.u.a32.address_lo; \
@ -270,6 +203,9 @@ unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba,
unsigned short cid, unsigned short cid,
unsigned short issue_reset, unsigned short issue_reset,
unsigned short savecfg_flag); unsigned short savecfg_flag);
int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba,
struct invldt_cmd_tbl *inv_tbl,
unsigned int nents);
int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type); int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type);

View File

@ -27,24 +27,6 @@
BFA_TRC_FILE(FCS, FCS); BFA_TRC_FILE(FCS, FCS);
/*
* FCS sub-modules
*/
struct bfa_fcs_mod_s {
void (*attach) (struct bfa_fcs_s *fcs);
void (*modinit) (struct bfa_fcs_s *fcs);
void (*modexit) (struct bfa_fcs_s *fcs);
};
#define BFA_FCS_MODULE(_mod) { _mod ## _modinit, _mod ## _modexit }
static struct bfa_fcs_mod_s fcs_modules[] = {
{ bfa_fcs_port_attach, NULL, NULL },
{ bfa_fcs_uf_attach, NULL, NULL },
{ bfa_fcs_fabric_attach, bfa_fcs_fabric_modinit,
bfa_fcs_fabric_modexit },
};
/* /*
* fcs_api BFA FCS API * fcs_api BFA FCS API
*/ */
@ -58,53 +40,20 @@ bfa_fcs_exit_comp(void *fcs_cbarg)
complete(&bfad->comp); complete(&bfad->comp);
} }
/*
* fcs_api BFA FCS API
*/
/*
* fcs attach -- called once to initialize data structures at driver attach time
*/
void
bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
bfa_boolean_t min_cfg)
{
int i;
struct bfa_fcs_mod_s *mod;
fcs->bfa = bfa;
fcs->bfad = bfad;
fcs->min_cfg = min_cfg;
fcs->num_rport_logins = 0;
bfa->fcs = BFA_TRUE;
fcbuild_init();
for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
mod = &fcs_modules[i];
if (mod->attach)
mod->attach(fcs);
}
}
/* /*
* fcs initialization, called once after bfa initialization is complete * fcs initialization, called once after bfa initialization is complete
*/ */
void void
bfa_fcs_init(struct bfa_fcs_s *fcs) bfa_fcs_init(struct bfa_fcs_s *fcs)
{ {
int i; bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE);
struct bfa_fcs_mod_s *mod; bfa_trc(fcs, 0);
for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) {
mod = &fcs_modules[i];
if (mod->modinit)
mod->modinit(fcs);
}
} }
/*
* fcs_api BFA FCS API
*/
/* /*
* FCS update cfg - reset the pwwn/nwwn of fabric base logical port * FCS update cfg - reset the pwwn/nwwn of fabric base logical port
* with values learned during bfa_init firmware GETATTR REQ. * with values learned during bfa_init firmware GETATTR REQ.
@ -180,26 +129,14 @@ bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs,
void void
bfa_fcs_exit(struct bfa_fcs_s *fcs) bfa_fcs_exit(struct bfa_fcs_s *fcs)
{ {
struct bfa_fcs_mod_s *mod;
int nmods, i;
bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs); bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs);
bfa_wc_up(&fcs->wc);
nmods = ARRAY_SIZE(fcs_modules); bfa_trc(fcs, 0);
bfa_lps_delete(fcs->fabric.lps);
for (i = 0; i < nmods; i++) { bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_DELETE);
mod = &fcs_modules[i];
if (mod->modexit) {
bfa_wc_up(&fcs->wc);
mod->modexit(fcs);
}
}
bfa_wc_wait(&fcs->wc); bfa_wc_wait(&fcs->wc);
} }
/* /*
* Fabric module implementation. * Fabric module implementation.
*/ */
@ -1127,62 +1064,6 @@ bfa_fcs_fabric_stop_comp(void *cbarg)
* fcs_fabric_public fabric public functions * fcs_fabric_public fabric public functions
*/ */
/*
* Attach time initialization.
*/
void
bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs)
{
struct bfa_fcs_fabric_s *fabric;
fabric = &fcs->fabric;
memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));
/*
* Initialize base fabric.
*/
fabric->fcs = fcs;
INIT_LIST_HEAD(&fabric->vport_q);
INIT_LIST_HEAD(&fabric->vf_q);
fabric->lps = bfa_lps_alloc(fcs->bfa);
WARN_ON(!fabric->lps);
/*
* Initialize fabric delete completion handler. Fabric deletion is
* complete when the last vport delete is complete.
*/
bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);
bfa_wc_up(&fabric->wc); /* For the base port */
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL);
}
void
bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs)
{
bfa_sm_send_event(&fcs->fabric, BFA_FCS_FABRIC_SM_CREATE);
bfa_trc(fcs, 0);
}
/*
* Module cleanup
*/
void
bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs)
{
struct bfa_fcs_fabric_s *fabric;
bfa_trc(fcs, 0);
/*
* Cleanup base fabric.
*/
fabric = &fcs->fabric;
bfa_lps_delete(fabric->lps);
bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE);
}
/* /*
* Fabric module stop -- stop FCS actions * Fabric module stop -- stop FCS actions
*/ */
@ -1633,12 +1514,6 @@ bfa_fcs_port_event_handler(void *cbarg, enum bfa_port_linkstate event)
} }
} }
void
bfa_fcs_port_attach(struct bfa_fcs_s *fcs)
{
bfa_fcport_event_register(fcs->bfa, bfa_fcs_port_event_handler, fcs);
}
/* /*
* BFA FCS UF ( Unsolicited Frames) * BFA FCS UF ( Unsolicited Frames)
*/ */
@ -1706,8 +1581,44 @@ bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf)
bfa_uf_free(uf); bfa_uf_free(uf);
} }
/*
* fcs attach -- called once to initialize data structures at driver attach time
*/
void void
bfa_fcs_uf_attach(struct bfa_fcs_s *fcs) bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad,
bfa_boolean_t min_cfg)
{ {
struct bfa_fcs_fabric_s *fabric = &fcs->fabric;
fcs->bfa = bfa;
fcs->bfad = bfad;
fcs->min_cfg = min_cfg;
fcs->num_rport_logins = 0;
bfa->fcs = BFA_TRUE;
fcbuild_init();
bfa_fcport_event_register(fcs->bfa, bfa_fcs_port_event_handler, fcs);
bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs); bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs);
memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s));
/*
* Initialize base fabric.
*/
fabric->fcs = fcs;
INIT_LIST_HEAD(&fabric->vport_q);
INIT_LIST_HEAD(&fabric->vf_q);
fabric->lps = bfa_lps_alloc(fcs->bfa);
WARN_ON(!fabric->lps);
/*
* Initialize fabric delete completion handler. Fabric deletion is
* complete when the last vport delete is complete.
*/
bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric);
bfa_wc_up(&fabric->wc); /* For the base port */
bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit);
bfa_fcs_lport_attach(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, NULL);
} }

View File

@ -808,9 +808,7 @@ void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports);
/* /*
* fabric protected interface functions * fabric protected interface functions
*/ */
void bfa_fcs_fabric_attach(struct bfa_fcs_s *fcs);
void bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs); void bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs);
void bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs);
void bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric); void bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric);
void bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric); void bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric);
void bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric, void bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric,
@ -827,8 +825,6 @@ void bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric);
void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric, void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
wwn_t fabric_name); wwn_t fabric_name);
u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric); u16 bfa_fcs_fabric_get_switch_oui(struct bfa_fcs_fabric_s *fabric);
void bfa_fcs_uf_attach(struct bfa_fcs_s *fcs);
void bfa_fcs_port_attach(struct bfa_fcs_s *fcs);
void bfa_fcs_fabric_modstop(struct bfa_fcs_s *fcs); void bfa_fcs_fabric_modstop(struct bfa_fcs_s *fcs);
void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric,
enum bfa_fcs_fabric_event event); enum bfa_fcs_fabric_event event);

View File

@ -813,6 +813,7 @@ struct scsi_host_template bfad_im_scsi_host_template = {
.name = BFAD_DRIVER_NAME, .name = BFAD_DRIVER_NAME,
.info = bfad_im_info, .info = bfad_im_info,
.queuecommand = bfad_im_queuecommand, .queuecommand = bfad_im_queuecommand,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = bfad_im_abort_handler, .eh_abort_handler = bfad_im_abort_handler,
.eh_device_reset_handler = bfad_im_reset_lun_handler, .eh_device_reset_handler = bfad_im_reset_lun_handler,
.eh_bus_reset_handler = bfad_im_reset_bus_handler, .eh_bus_reset_handler = bfad_im_reset_bus_handler,
@ -835,6 +836,7 @@ struct scsi_host_template bfad_im_vport_template = {
.name = BFAD_DRIVER_NAME, .name = BFAD_DRIVER_NAME,
.info = bfad_im_info, .info = bfad_im_info,
.queuecommand = bfad_im_queuecommand, .queuecommand = bfad_im_queuecommand,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = bfad_im_abort_handler, .eh_abort_handler = bfad_im_abort_handler,
.eh_device_reset_handler = bfad_im_reset_lun_handler, .eh_device_reset_handler = bfad_im_reset_lun_handler,
.eh_bus_reset_handler = bfad_im_reset_bus_handler, .eh_bus_reset_handler = bfad_im_reset_bus_handler,

View File

@ -2947,6 +2947,7 @@ static struct scsi_host_template bnx2fc_shost_template = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = "QLogic Offload FCoE Initiator", .name = "QLogic Offload FCoE Initiator",
.queuecommand = bnx2fc_queuecommand, .queuecommand = bnx2fc_queuecommand,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = bnx2fc_eh_abort, /* abts */ .eh_abort_handler = bnx2fc_eh_abort, /* abts */
.eh_device_reset_handler = bnx2fc_eh_device_reset, /* lun reset */ .eh_device_reset_handler = bnx2fc_eh_device_reset, /* lun reset */
.eh_target_reset_handler = bnx2fc_eh_target_reset, /* tgt reset */ .eh_target_reset_handler = bnx2fc_eh_target_reset, /* tgt reset */

View File

@ -2259,6 +2259,7 @@ static struct scsi_host_template bnx2i_host_template = {
.name = "QLogic Offload iSCSI Initiator", .name = "QLogic Offload iSCSI Initiator",
.proc_name = "bnx2i", .proc_name = "bnx2i",
.queuecommand = iscsi_queuecommand, .queuecommand = iscsi_queuecommand,
.eh_timed_out = iscsi_eh_cmd_timed_out,
.eh_abort_handler = iscsi_eh_abort, .eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler = iscsi_eh_device_reset, .eh_device_reset_handler = iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_recover_target, .eh_target_reset_handler = iscsi_eh_recover_target,

View File

@ -2270,6 +2270,7 @@ struct scsi_host_template csio_fcoe_shost_template = {
.name = CSIO_DRV_DESC, .name = CSIO_DRV_DESC,
.proc_name = KBUILD_MODNAME, .proc_name = KBUILD_MODNAME,
.queuecommand = csio_queuecommand, .queuecommand = csio_queuecommand,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = csio_eh_abort_handler, .eh_abort_handler = csio_eh_abort_handler,
.eh_device_reset_handler = csio_eh_lun_reset_handler, .eh_device_reset_handler = csio_eh_lun_reset_handler,
.slave_alloc = csio_slave_alloc, .slave_alloc = csio_slave_alloc,
@ -2289,6 +2290,7 @@ struct scsi_host_template csio_fcoe_shost_vport_template = {
.name = CSIO_DRV_DESC, .name = CSIO_DRV_DESC,
.proc_name = KBUILD_MODNAME, .proc_name = KBUILD_MODNAME,
.queuecommand = csio_queuecommand, .queuecommand = csio_queuecommand,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = csio_eh_abort_handler, .eh_abort_handler = csio_eh_abort_handler,
.eh_device_reset_handler = csio_eh_lun_reset_handler, .eh_device_reset_handler = csio_eh_lun_reset_handler,
.slave_alloc = csio_slave_alloc, .slave_alloc = csio_slave_alloc,

View File

@ -90,6 +90,7 @@ static struct scsi_host_template cxgb3i_host_template = {
.sg_tablesize = SG_ALL, .sg_tablesize = SG_ALL,
.max_sectors = 0xFFFF, .max_sectors = 0xFFFF,
.cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
.eh_timed_out = iscsi_eh_cmd_timed_out,
.eh_abort_handler = iscsi_eh_abort, .eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler = iscsi_eh_device_reset, .eh_device_reset_handler = iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_recover_target, .eh_target_reset_handler = iscsi_eh_recover_target,

View File

@ -103,6 +103,7 @@ static struct scsi_host_template cxgb4i_host_template = {
.sg_tablesize = SG_ALL, .sg_tablesize = SG_ALL,
.max_sectors = 0xFFFF, .max_sectors = 0xFFFF,
.cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
.eh_timed_out = iscsi_eh_cmd_timed_out,
.eh_abort_handler = iscsi_eh_abort, .eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler = iscsi_eh_device_reset, .eh_device_reset_handler = iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_recover_target, .eh_target_reset_handler = iscsi_eh_recover_target,

View File

@ -54,6 +54,9 @@ extern const struct file_operations cxlflash_cxl_fops;
/* RRQ for master issued cmds */ /* RRQ for master issued cmds */
#define NUM_RRQ_ENTRY CXLFLASH_MAX_CMDS #define NUM_RRQ_ENTRY CXLFLASH_MAX_CMDS
/* SQ for master issued cmds */
#define NUM_SQ_ENTRY CXLFLASH_MAX_CMDS
static inline void check_sizes(void) static inline void check_sizes(void)
{ {
@ -155,8 +158,8 @@ static inline struct afu_cmd *sc_to_afucz(struct scsi_cmnd *sc)
struct afu { struct afu {
/* Stuff requiring alignment go first. */ /* Stuff requiring alignment go first. */
struct sisl_ioarcb sq[NUM_SQ_ENTRY]; /* 16K SQ */
u64 rrq_entry[NUM_RRQ_ENTRY]; /* 2K RRQ */ u64 rrq_entry[NUM_RRQ_ENTRY]; /* 2K RRQ */
/* Beware of alignment till here. Preferably introduce new /* Beware of alignment till here. Preferably introduce new
* fields after this point * fields after this point
@ -171,9 +174,13 @@ struct afu {
struct sisl_host_map __iomem *host_map; /* MC host map */ struct sisl_host_map __iomem *host_map; /* MC host map */
struct sisl_ctrl_map __iomem *ctrl_map; /* MC control map */ struct sisl_ctrl_map __iomem *ctrl_map; /* MC control map */
struct kref mapcount;
ctx_hndl_t ctx_hndl; /* master's context handle */ ctx_hndl_t ctx_hndl; /* master's context handle */
atomic_t hsq_credits;
spinlock_t hsq_slock;
struct sisl_ioarcb *hsq_start;
struct sisl_ioarcb *hsq_end;
struct sisl_ioarcb *hsq_curr;
u64 *hrrq_start; u64 *hrrq_start;
u64 *hrrq_end; u64 *hrrq_end;
u64 *hrrq_curr; u64 *hrrq_curr;
@ -191,6 +198,23 @@ struct afu {
}; };
static inline bool afu_is_cmd_mode(struct afu *afu, u64 cmd_mode)
{
u64 afu_cap = afu->interface_version >> SISL_INTVER_CAP_SHIFT;
return afu_cap & cmd_mode;
}
static inline bool afu_is_sq_cmd_mode(struct afu *afu)
{
return afu_is_cmd_mode(afu, SISL_INTVER_CAP_SQ_CMD_MODE);
}
static inline bool afu_is_ioarrin_cmd_mode(struct afu *afu)
{
return afu_is_cmd_mode(afu, SISL_INTVER_CAP_IOARRIN_CMD_MODE);
}
static inline u64 lun_to_lunid(u64 lun) static inline u64 lun_to_lunid(u64 lun)
{ {
__be64 lun_id; __be64 lun_id;

View File

@ -32,11 +32,13 @@
*/ */
static struct llun_info *create_local(struct scsi_device *sdev, u8 *wwid) static struct llun_info *create_local(struct scsi_device *sdev, u8 *wwid)
{ {
struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev;
struct llun_info *lli = NULL; struct llun_info *lli = NULL;
lli = kzalloc(sizeof(*lli), GFP_KERNEL); lli = kzalloc(sizeof(*lli), GFP_KERNEL);
if (unlikely(!lli)) { if (unlikely(!lli)) {
pr_err("%s: could not allocate lli\n", __func__); dev_err(dev, "%s: could not allocate lli\n", __func__);
goto out; goto out;
} }
@ -58,11 +60,13 @@ out:
*/ */
static struct glun_info *create_global(struct scsi_device *sdev, u8 *wwid) static struct glun_info *create_global(struct scsi_device *sdev, u8 *wwid)
{ {
struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev;
struct glun_info *gli = NULL; struct glun_info *gli = NULL;
gli = kzalloc(sizeof(*gli), GFP_KERNEL); gli = kzalloc(sizeof(*gli), GFP_KERNEL);
if (unlikely(!gli)) { if (unlikely(!gli)) {
pr_err("%s: could not allocate gli\n", __func__); dev_err(dev, "%s: could not allocate gli\n", __func__);
goto out; goto out;
} }
@ -129,10 +133,10 @@ static struct glun_info *lookup_global(u8 *wwid)
*/ */
static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid) static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid)
{ {
struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev;
struct llun_info *lli = NULL; struct llun_info *lli = NULL;
struct glun_info *gli = NULL; struct glun_info *gli = NULL;
struct Scsi_Host *shost = sdev->host;
struct cxlflash_cfg *cfg = shost_priv(shost);
if (unlikely(!wwid)) if (unlikely(!wwid))
goto out; goto out;
@ -165,7 +169,7 @@ static struct llun_info *find_and_create_lun(struct scsi_device *sdev, u8 *wwid)
list_add(&gli->list, &global.gluns); list_add(&gli->list, &global.gluns);
out: out:
pr_debug("%s: returning %p\n", __func__, lli); dev_dbg(dev, "%s: returning lli=%p, gli=%p\n", __func__, lli, gli);
return lli; return lli;
} }
@ -225,17 +229,18 @@ void cxlflash_term_global_luns(void)
int cxlflash_manage_lun(struct scsi_device *sdev, int cxlflash_manage_lun(struct scsi_device *sdev,
struct dk_cxlflash_manage_lun *manage) struct dk_cxlflash_manage_lun *manage)
{ {
int rc = 0; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev;
struct llun_info *lli = NULL; struct llun_info *lli = NULL;
int rc = 0;
u64 flags = manage->hdr.flags; u64 flags = manage->hdr.flags;
u32 chan = sdev->channel; u32 chan = sdev->channel;
mutex_lock(&global.mutex); mutex_lock(&global.mutex);
lli = find_and_create_lun(sdev, manage->wwid); lli = find_and_create_lun(sdev, manage->wwid);
pr_debug("%s: ENTER: WWID = %016llX%016llX, flags = %016llX li = %p\n", dev_dbg(dev, "%s: WWID=%016llx%016llx, flags=%016llx lli=%p\n",
__func__, get_unaligned_be64(&manage->wwid[0]), __func__, get_unaligned_be64(&manage->wwid[0]),
get_unaligned_be64(&manage->wwid[8]), get_unaligned_be64(&manage->wwid[8]), manage->hdr.flags, lli);
manage->hdr.flags, lli);
if (unlikely(!lli)) { if (unlikely(!lli)) {
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto out;
@ -265,11 +270,11 @@ int cxlflash_manage_lun(struct scsi_device *sdev,
} }
} }
pr_debug("%s: port_sel = %08X chan = %u lun_id = %016llX\n", __func__, dev_dbg(dev, "%s: port_sel=%08x chan=%u lun_id=%016llx\n",
lli->port_sel, chan, lli->lun_id[chan]); __func__, lli->port_sel, chan, lli->lun_id[chan]);
out: out:
mutex_unlock(&global.mutex); mutex_unlock(&global.mutex);
pr_debug("%s: returning rc=%d\n", __func__, rc); dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
return rc; return rc;
} }

File diff suppressed because it is too large Load Diff

View File

@ -72,7 +72,10 @@ struct sisl_ioarcb {
u16 timeout; /* in units specified by req_flags */ u16 timeout; /* in units specified by req_flags */
u32 rsvd1; u32 rsvd1;
u8 cdb[16]; /* must be in big endian */ u8 cdb[16]; /* must be in big endian */
u64 reserved; /* Reserved area */ union {
u64 reserved; /* Reserved for IOARRIN mode */
struct sisl_ioasa *ioasa; /* IOASA EA for SQ Mode */
};
} __packed; } __packed;
struct sisl_rc { struct sisl_rc {
@ -260,6 +263,11 @@ struct sisl_host_map {
__be64 cmd_room; __be64 cmd_room;
__be64 ctx_ctrl; /* least significant byte or b56:63 is LISN# */ __be64 ctx_ctrl; /* least significant byte or b56:63 is LISN# */
__be64 mbox_w; /* restricted use */ __be64 mbox_w; /* restricted use */
__be64 sq_start; /* Submission Queue (R/W): write sequence and */
__be64 sq_end; /* inclusion semantics are the same as RRQ */
__be64 sq_head; /* Submission Queue Head (R): for debugging */
__be64 sq_tail; /* Submission Queue TAIL (R/W): next IOARCB */
__be64 sq_ctx_reset; /* Submission Queue Context Reset (R/W) */
}; };
/* per context provisioning & control MMIO */ /* per context provisioning & control MMIO */
@ -348,6 +356,15 @@ struct sisl_global_regs {
__be64 rsvd[0xf8]; __be64 rsvd[0xf8];
__le64 afu_version; __le64 afu_version;
__be64 interface_version; __be64 interface_version;
#define SISL_INTVER_CAP_SHIFT 16
#define SISL_INTVER_MAJ_SHIFT 8
#define SISL_INTVER_CAP_MASK 0xFFFFFFFF00000000ULL
#define SISL_INTVER_MAJ_MASK 0x00000000FFFF0000ULL
#define SISL_INTVER_MIN_MASK 0x000000000000FFFFULL
#define SISL_INTVER_CAP_IOARRIN_CMD_MODE 0x800000000000ULL
#define SISL_INTVER_CAP_SQ_CMD_MODE 0x400000000000ULL
#define SISL_INTVER_CAP_RESERVED_CMD_MODE_A 0x200000000000ULL
#define SISL_INTVER_CAP_RESERVED_CMD_MODE_B 0x100000000000ULL
}; };
#define CXLFLASH_NUM_FC_PORTS 2 #define CXLFLASH_NUM_FC_PORTS 2

View File

@ -212,7 +212,7 @@ struct ctx_info *get_context(struct cxlflash_cfg *cfg, u64 rctxid,
} }
out: out:
dev_dbg(dev, "%s: rctxid=%016llX ctxinfo=%p ctxpid=%u pid=%u " dev_dbg(dev, "%s: rctxid=%016llx ctxinfo=%p ctxpid=%u pid=%u "
"ctx_ctrl=%u\n", __func__, rctxid, ctxi, ctxpid, pid, "ctx_ctrl=%u\n", __func__, rctxid, ctxi, ctxpid, pid,
ctx_ctrl); ctx_ctrl);
@ -260,7 +260,7 @@ static int afu_attach(struct cxlflash_cfg *cfg, struct ctx_info *ctxi)
writeq_be(val, &ctrl_map->ctx_cap); writeq_be(val, &ctrl_map->ctx_cap);
val = readq_be(&ctrl_map->ctx_cap); val = readq_be(&ctrl_map->ctx_cap);
if (val != (SISL_CTX_CAP_READ_CMD | SISL_CTX_CAP_WRITE_CMD)) { if (val != (SISL_CTX_CAP_READ_CMD | SISL_CTX_CAP_WRITE_CMD)) {
dev_err(dev, "%s: ctx may be closed val=%016llX\n", dev_err(dev, "%s: ctx may be closed val=%016llx\n",
__func__, val); __func__, val);
rc = -EAGAIN; rc = -EAGAIN;
goto out; goto out;
@ -302,7 +302,7 @@ out:
*/ */
static int read_cap16(struct scsi_device *sdev, struct llun_info *lli) static int read_cap16(struct scsi_device *sdev, struct llun_info *lli)
{ {
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev; struct device *dev = &cfg->dev->dev;
struct glun_info *gli = lli->parent; struct glun_info *gli = lli->parent;
u8 *cmd_buf = NULL; u8 *cmd_buf = NULL;
@ -326,7 +326,7 @@ retry:
scsi_cmd[1] = SAI_READ_CAPACITY_16; /* service action */ scsi_cmd[1] = SAI_READ_CAPACITY_16; /* service action */
put_unaligned_be32(CMD_BUFSIZE, &scsi_cmd[10]); put_unaligned_be32(CMD_BUFSIZE, &scsi_cmd[10]);
dev_dbg(dev, "%s: %ssending cmd(0x%x)\n", __func__, dev_dbg(dev, "%s: %ssending cmd(%02x)\n", __func__,
retry_cnt ? "re" : "", scsi_cmd[0]); retry_cnt ? "re" : "", scsi_cmd[0]);
/* Drop the ioctl read semahpore across lengthy call */ /* Drop the ioctl read semahpore across lengthy call */
@ -336,7 +336,7 @@ retry:
down_read(&cfg->ioctl_rwsem); down_read(&cfg->ioctl_rwsem);
rc = check_state(cfg); rc = check_state(cfg);
if (rc) { if (rc) {
dev_err(dev, "%s: Failed state! result=0x08%X\n", dev_err(dev, "%s: Failed state result=%08x\n",
__func__, result); __func__, result);
rc = -ENODEV; rc = -ENODEV;
goto out; goto out;
@ -378,7 +378,7 @@ retry:
} }
if (result) { if (result) {
dev_err(dev, "%s: command failed, result=0x%x\n", dev_err(dev, "%s: command failed, result=%08x\n",
__func__, result); __func__, result);
rc = -EIO; rc = -EIO;
goto out; goto out;
@ -415,29 +415,32 @@ out:
struct sisl_rht_entry *get_rhte(struct ctx_info *ctxi, res_hndl_t rhndl, struct sisl_rht_entry *get_rhte(struct ctx_info *ctxi, res_hndl_t rhndl,
struct llun_info *lli) struct llun_info *lli)
{ {
struct cxlflash_cfg *cfg = ctxi->cfg;
struct device *dev = &cfg->dev->dev;
struct sisl_rht_entry *rhte = NULL; struct sisl_rht_entry *rhte = NULL;
if (unlikely(!ctxi->rht_start)) { if (unlikely(!ctxi->rht_start)) {
pr_debug("%s: Context does not have allocated RHT!\n", dev_dbg(dev, "%s: Context does not have allocated RHT\n",
__func__); __func__);
goto out; goto out;
} }
if (unlikely(rhndl >= MAX_RHT_PER_CONTEXT)) { if (unlikely(rhndl >= MAX_RHT_PER_CONTEXT)) {
pr_debug("%s: Bad resource handle! (%d)\n", __func__, rhndl); dev_dbg(dev, "%s: Bad resource handle rhndl=%d\n",
__func__, rhndl);
goto out; goto out;
} }
if (unlikely(ctxi->rht_lun[rhndl] != lli)) { if (unlikely(ctxi->rht_lun[rhndl] != lli)) {
pr_debug("%s: Bad resource handle LUN! (%d)\n", dev_dbg(dev, "%s: Bad resource handle LUN rhndl=%d\n",
__func__, rhndl); __func__, rhndl);
goto out; goto out;
} }
rhte = &ctxi->rht_start[rhndl]; rhte = &ctxi->rht_start[rhndl];
if (unlikely(rhte->nmask == 0)) { if (unlikely(rhte->nmask == 0)) {
pr_debug("%s: Unopened resource handle! (%d)\n", dev_dbg(dev, "%s: Unopened resource handle rhndl=%d\n",
__func__, rhndl); __func__, rhndl);
rhte = NULL; rhte = NULL;
goto out; goto out;
} }
@ -456,6 +459,8 @@ out:
struct sisl_rht_entry *rhte_checkout(struct ctx_info *ctxi, struct sisl_rht_entry *rhte_checkout(struct ctx_info *ctxi,
struct llun_info *lli) struct llun_info *lli)
{ {
struct cxlflash_cfg *cfg = ctxi->cfg;
struct device *dev = &cfg->dev->dev;
struct sisl_rht_entry *rhte = NULL; struct sisl_rht_entry *rhte = NULL;
int i; int i;
@ -470,7 +475,7 @@ struct sisl_rht_entry *rhte_checkout(struct ctx_info *ctxi,
if (likely(rhte)) if (likely(rhte))
ctxi->rht_lun[i] = lli; ctxi->rht_lun[i] = lli;
pr_debug("%s: returning rhte=%p (%d)\n", __func__, rhte, i); dev_dbg(dev, "%s: returning rhte=%p index=%d\n", __func__, rhte, i);
return rhte; return rhte;
} }
@ -547,7 +552,7 @@ int cxlflash_lun_attach(struct glun_info *gli, enum lun_mode mode, bool locked)
if (gli->mode == MODE_NONE) if (gli->mode == MODE_NONE)
gli->mode = mode; gli->mode = mode;
else if (gli->mode != mode) { else if (gli->mode != mode) {
pr_debug("%s: LUN operating in mode %d, requested mode %d\n", pr_debug("%s: gli_mode=%d requested_mode=%d\n",
__func__, gli->mode, mode); __func__, gli->mode, mode);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
@ -605,7 +610,7 @@ int _cxlflash_disk_release(struct scsi_device *sdev,
struct ctx_info *ctxi, struct ctx_info *ctxi,
struct dk_cxlflash_release *release) struct dk_cxlflash_release *release)
{ {
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev; struct device *dev = &cfg->dev->dev;
struct llun_info *lli = sdev->hostdata; struct llun_info *lli = sdev->hostdata;
struct glun_info *gli = lli->parent; struct glun_info *gli = lli->parent;
@ -622,13 +627,13 @@ int _cxlflash_disk_release(struct scsi_device *sdev,
struct sisl_rht_entry *rhte; struct sisl_rht_entry *rhte;
struct sisl_rht_entry_f1 *rhte_f1; struct sisl_rht_entry_f1 *rhte_f1;
dev_dbg(dev, "%s: ctxid=%llu rhndl=0x%llx gli->mode=%u gli->users=%u\n", dev_dbg(dev, "%s: ctxid=%llu rhndl=%llu gli->mode=%u gli->users=%u\n",
__func__, ctxid, release->rsrc_handle, gli->mode, gli->users); __func__, ctxid, release->rsrc_handle, gli->mode, gli->users);
if (!ctxi) { if (!ctxi) {
ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK); ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK);
if (unlikely(!ctxi)) { if (unlikely(!ctxi)) {
dev_dbg(dev, "%s: Bad context! (%llu)\n", dev_dbg(dev, "%s: Bad context ctxid=%llu\n",
__func__, ctxid); __func__, ctxid);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
@ -639,7 +644,7 @@ int _cxlflash_disk_release(struct scsi_device *sdev,
rhte = get_rhte(ctxi, rhndl, lli); rhte = get_rhte(ctxi, rhndl, lli);
if (unlikely(!rhte)) { if (unlikely(!rhte)) {
dev_dbg(dev, "%s: Bad resource handle! (%d)\n", dev_dbg(dev, "%s: Bad resource handle rhndl=%d\n",
__func__, rhndl); __func__, rhndl);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
@ -758,13 +763,13 @@ static struct ctx_info *create_context(struct cxlflash_cfg *cfg)
lli = kzalloc((MAX_RHT_PER_CONTEXT * sizeof(*lli)), GFP_KERNEL); lli = kzalloc((MAX_RHT_PER_CONTEXT * sizeof(*lli)), GFP_KERNEL);
ws = kzalloc((MAX_RHT_PER_CONTEXT * sizeof(*ws)), GFP_KERNEL); ws = kzalloc((MAX_RHT_PER_CONTEXT * sizeof(*ws)), GFP_KERNEL);
if (unlikely(!ctxi || !lli || !ws)) { if (unlikely(!ctxi || !lli || !ws)) {
dev_err(dev, "%s: Unable to allocate context!\n", __func__); dev_err(dev, "%s: Unable to allocate context\n", __func__);
goto err; goto err;
} }
rhte = (struct sisl_rht_entry *)get_zeroed_page(GFP_KERNEL); rhte = (struct sisl_rht_entry *)get_zeroed_page(GFP_KERNEL);
if (unlikely(!rhte)) { if (unlikely(!rhte)) {
dev_err(dev, "%s: Unable to allocate RHT!\n", __func__); dev_err(dev, "%s: Unable to allocate RHT\n", __func__);
goto err; goto err;
} }
@ -858,7 +863,7 @@ static int _cxlflash_disk_detach(struct scsi_device *sdev,
struct ctx_info *ctxi, struct ctx_info *ctxi,
struct dk_cxlflash_detach *detach) struct dk_cxlflash_detach *detach)
{ {
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev; struct device *dev = &cfg->dev->dev;
struct llun_info *lli = sdev->hostdata; struct llun_info *lli = sdev->hostdata;
struct lun_access *lun_access, *t; struct lun_access *lun_access, *t;
@ -875,7 +880,7 @@ static int _cxlflash_disk_detach(struct scsi_device *sdev,
if (!ctxi) { if (!ctxi) {
ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK); ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK);
if (unlikely(!ctxi)) { if (unlikely(!ctxi)) {
dev_dbg(dev, "%s: Bad context! (%llu)\n", dev_dbg(dev, "%s: Bad context ctxid=%llu\n",
__func__, ctxid); __func__, ctxid);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
@ -964,7 +969,7 @@ static int cxlflash_cxl_release(struct inode *inode, struct file *file)
ctxid = cxl_process_element(ctx); ctxid = cxl_process_element(ctx);
if (unlikely(ctxid < 0)) { if (unlikely(ctxid < 0)) {
dev_err(dev, "%s: Context %p was closed! (%d)\n", dev_err(dev, "%s: Context %p was closed ctxid=%d\n",
__func__, ctx, ctxid); __func__, ctx, ctxid);
goto out; goto out;
} }
@ -973,18 +978,18 @@ static int cxlflash_cxl_release(struct inode *inode, struct file *file)
if (unlikely(!ctxi)) { if (unlikely(!ctxi)) {
ctxi = get_context(cfg, ctxid, file, ctrl | CTX_CTRL_CLONE); ctxi = get_context(cfg, ctxid, file, ctrl | CTX_CTRL_CLONE);
if (!ctxi) { if (!ctxi) {
dev_dbg(dev, "%s: Context %d already free!\n", dev_dbg(dev, "%s: ctxid=%d already free\n",
__func__, ctxid); __func__, ctxid);
goto out_release; goto out_release;
} }
dev_dbg(dev, "%s: Another process owns context %d!\n", dev_dbg(dev, "%s: Another process owns ctxid=%d\n",
__func__, ctxid); __func__, ctxid);
put_context(ctxi); put_context(ctxi);
goto out; goto out;
} }
dev_dbg(dev, "%s: close for context %d\n", __func__, ctxid); dev_dbg(dev, "%s: close for ctxid=%d\n", __func__, ctxid);
detach.context_id = ctxi->ctxid; detach.context_id = ctxi->ctxid;
list_for_each_entry_safe(lun_access, t, &ctxi->luns, list) list_for_each_entry_safe(lun_access, t, &ctxi->luns, list)
@ -1011,17 +1016,20 @@ static void unmap_context(struct ctx_info *ctxi)
/** /**
* get_err_page() - obtains and allocates the error notification page * get_err_page() - obtains and allocates the error notification page
* @cfg: Internal structure associated with the host.
* *
* Return: error notification page on success, NULL on failure * Return: error notification page on success, NULL on failure
*/ */
static struct page *get_err_page(void) static struct page *get_err_page(struct cxlflash_cfg *cfg)
{ {
struct page *err_page = global.err_page; struct page *err_page = global.err_page;
struct device *dev = &cfg->dev->dev;
if (unlikely(!err_page)) { if (unlikely(!err_page)) {
err_page = alloc_page(GFP_KERNEL); err_page = alloc_page(GFP_KERNEL);
if (unlikely(!err_page)) { if (unlikely(!err_page)) {
pr_err("%s: Unable to allocate err_page!\n", __func__); dev_err(dev, "%s: Unable to allocate err_page\n",
__func__);
goto out; goto out;
} }
@ -1039,7 +1047,7 @@ static struct page *get_err_page(void)
} }
out: out:
pr_debug("%s: returning err_page=%p\n", __func__, err_page); dev_dbg(dev, "%s: returning err_page=%p\n", __func__, err_page);
return err_page; return err_page;
} }
@ -1074,14 +1082,14 @@ static int cxlflash_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
ctxid = cxl_process_element(ctx); ctxid = cxl_process_element(ctx);
if (unlikely(ctxid < 0)) { if (unlikely(ctxid < 0)) {
dev_err(dev, "%s: Context %p was closed! (%d)\n", dev_err(dev, "%s: Context %p was closed ctxid=%d\n",
__func__, ctx, ctxid); __func__, ctx, ctxid);
goto err; goto err;
} }
ctxi = get_context(cfg, ctxid, file, ctrl); ctxi = get_context(cfg, ctxid, file, ctrl);
if (unlikely(!ctxi)) { if (unlikely(!ctxi)) {
dev_dbg(dev, "%s: Bad context! (%d)\n", __func__, ctxid); dev_dbg(dev, "%s: Bad context ctxid=%d\n", __func__, ctxid);
goto err; goto err;
} }
@ -1091,13 +1099,12 @@ static int cxlflash_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
rc = ctxi->cxl_mmap_vmops->fault(vma, vmf); rc = ctxi->cxl_mmap_vmops->fault(vma, vmf);
} else { } else {
dev_dbg(dev, "%s: err recovery active, use err_page!\n", dev_dbg(dev, "%s: err recovery active, use err_page\n",
__func__); __func__);
err_page = get_err_page(); err_page = get_err_page(cfg);
if (unlikely(!err_page)) { if (unlikely(!err_page)) {
dev_err(dev, "%s: Could not obtain error page!\n", dev_err(dev, "%s: Could not get err_page\n", __func__);
__func__);
rc = VM_FAULT_RETRY; rc = VM_FAULT_RETRY;
goto out; goto out;
} }
@ -1147,7 +1154,7 @@ static int cxlflash_cxl_mmap(struct file *file, struct vm_area_struct *vma)
ctxid = cxl_process_element(ctx); ctxid = cxl_process_element(ctx);
if (unlikely(ctxid < 0)) { if (unlikely(ctxid < 0)) {
dev_err(dev, "%s: Context %p was closed! (%d)\n", dev_err(dev, "%s: Context %p was closed ctxid=%d\n",
__func__, ctx, ctxid); __func__, ctx, ctxid);
rc = -EIO; rc = -EIO;
goto out; goto out;
@ -1155,7 +1162,7 @@ static int cxlflash_cxl_mmap(struct file *file, struct vm_area_struct *vma)
ctxi = get_context(cfg, ctxid, file, ctrl); ctxi = get_context(cfg, ctxid, file, ctrl);
if (unlikely(!ctxi)) { if (unlikely(!ctxi)) {
dev_dbg(dev, "%s: Bad context! (%d)\n", __func__, ctxid); dev_dbg(dev, "%s: Bad context ctxid=%d\n", __func__, ctxid);
rc = -EIO; rc = -EIO;
goto out; goto out;
} }
@ -1251,7 +1258,7 @@ retry:
break; break;
goto retry; goto retry;
case STATE_FAILTERM: case STATE_FAILTERM:
dev_dbg(dev, "%s: Failed/Terminating!\n", __func__); dev_dbg(dev, "%s: Failed/Terminating\n", __func__);
rc = -ENODEV; rc = -ENODEV;
break; break;
default: default:
@ -1276,7 +1283,7 @@ retry:
static int cxlflash_disk_attach(struct scsi_device *sdev, static int cxlflash_disk_attach(struct scsi_device *sdev,
struct dk_cxlflash_attach *attach) struct dk_cxlflash_attach *attach)
{ {
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev; struct device *dev = &cfg->dev->dev;
struct afu *afu = cfg->afu; struct afu *afu = cfg->afu;
struct llun_info *lli = sdev->hostdata; struct llun_info *lli = sdev->hostdata;
@ -1287,6 +1294,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
int rc = 0; int rc = 0;
u32 perms; u32 perms;
int ctxid = -1; int ctxid = -1;
u64 flags = 0UL;
u64 rctxid = 0UL; u64 rctxid = 0UL;
struct file *file = NULL; struct file *file = NULL;
@ -1302,24 +1310,24 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
} }
if (gli->max_lba == 0) { if (gli->max_lba == 0) {
dev_dbg(dev, "%s: No capacity info for this LUN (%016llX)\n", dev_dbg(dev, "%s: No capacity info for LUN=%016llx\n",
__func__, lli->lun_id[sdev->channel]); __func__, lli->lun_id[sdev->channel]);
rc = read_cap16(sdev, lli); rc = read_cap16(sdev, lli);
if (rc) { if (rc) {
dev_err(dev, "%s: Invalid device! (%d)\n", dev_err(dev, "%s: Invalid device rc=%d\n",
__func__, rc); __func__, rc);
rc = -ENODEV; rc = -ENODEV;
goto out; goto out;
} }
dev_dbg(dev, "%s: LBA = %016llX\n", __func__, gli->max_lba); dev_dbg(dev, "%s: LBA = %016llx\n", __func__, gli->max_lba);
dev_dbg(dev, "%s: BLK_LEN = %08X\n", __func__, gli->blk_len); dev_dbg(dev, "%s: BLK_LEN = %08x\n", __func__, gli->blk_len);
} }
if (attach->hdr.flags & DK_CXLFLASH_ATTACH_REUSE_CONTEXT) { if (attach->hdr.flags & DK_CXLFLASH_ATTACH_REUSE_CONTEXT) {
rctxid = attach->context_id; rctxid = attach->context_id;
ctxi = get_context(cfg, rctxid, NULL, 0); ctxi = get_context(cfg, rctxid, NULL, 0);
if (!ctxi) { if (!ctxi) {
dev_dbg(dev, "%s: Bad context! (%016llX)\n", dev_dbg(dev, "%s: Bad context rctxid=%016llx\n",
__func__, rctxid); __func__, rctxid);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
@ -1327,7 +1335,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
list_for_each_entry(lun_access, &ctxi->luns, list) list_for_each_entry(lun_access, &ctxi->luns, list)
if (lun_access->lli == lli) { if (lun_access->lli == lli) {
dev_dbg(dev, "%s: Already attached!\n", dev_dbg(dev, "%s: Already attached\n",
__func__); __func__);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
@ -1336,13 +1344,13 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
rc = scsi_device_get(sdev); rc = scsi_device_get(sdev);
if (unlikely(rc)) { if (unlikely(rc)) {
dev_err(dev, "%s: Unable to get sdev reference!\n", __func__); dev_err(dev, "%s: Unable to get sdev reference\n", __func__);
goto out; goto out;
} }
lun_access = kzalloc(sizeof(*lun_access), GFP_KERNEL); lun_access = kzalloc(sizeof(*lun_access), GFP_KERNEL);
if (unlikely(!lun_access)) { if (unlikely(!lun_access)) {
dev_err(dev, "%s: Unable to allocate lun_access!\n", __func__); dev_err(dev, "%s: Unable to allocate lun_access\n", __func__);
rc = -ENOMEM; rc = -ENOMEM;
goto err; goto err;
} }
@ -1352,7 +1360,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
/* Non-NULL context indicates reuse (another context reference) */ /* Non-NULL context indicates reuse (another context reference) */
if (ctxi) { if (ctxi) {
dev_dbg(dev, "%s: Reusing context for LUN! (%016llX)\n", dev_dbg(dev, "%s: Reusing context for LUN rctxid=%016llx\n",
__func__, rctxid); __func__, rctxid);
kref_get(&ctxi->kref); kref_get(&ctxi->kref);
list_add(&lun_access->list, &ctxi->luns); list_add(&lun_access->list, &ctxi->luns);
@ -1361,7 +1369,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
ctxi = create_context(cfg); ctxi = create_context(cfg);
if (unlikely(!ctxi)) { if (unlikely(!ctxi)) {
dev_err(dev, "%s: Failed to create context! (%d)\n", dev_err(dev, "%s: Failed to create context ctxid=%d\n",
__func__, ctxid); __func__, ctxid);
goto err; goto err;
} }
@ -1387,7 +1395,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
ctxid = cxl_process_element(ctx); ctxid = cxl_process_element(ctx);
if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) { if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) {
dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid); dev_err(dev, "%s: ctxid=%d invalid\n", __func__, ctxid);
rc = -EPERM; rc = -EPERM;
goto err; goto err;
} }
@ -1426,10 +1434,11 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
out_attach: out_attach:
if (fd != -1) if (fd != -1)
attach->hdr.return_flags = DK_CXLFLASH_APP_CLOSE_ADAP_FD; flags |= DK_CXLFLASH_APP_CLOSE_ADAP_FD;
else if (afu_is_sq_cmd_mode(afu))
attach->hdr.return_flags = 0; flags |= DK_CXLFLASH_CONTEXT_SQ_CMD_MODE;
attach->hdr.return_flags = flags;
attach->context_id = ctxi->ctxid; attach->context_id = ctxi->ctxid;
attach->block_size = gli->blk_len; attach->block_size = gli->blk_len;
attach->mmio_size = sizeof(afu->afu_map->hosts[0].harea); attach->mmio_size = sizeof(afu->afu_map->hosts[0].harea);
@ -1520,7 +1529,7 @@ static int recover_context(struct cxlflash_cfg *cfg,
ctxid = cxl_process_element(ctx); ctxid = cxl_process_element(ctx);
if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) { if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) {
dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid); dev_err(dev, "%s: ctxid=%d invalid\n", __func__, ctxid);
rc = -EPERM; rc = -EPERM;
goto err2; goto err2;
} }
@ -1611,12 +1620,13 @@ err1:
static int cxlflash_afu_recover(struct scsi_device *sdev, static int cxlflash_afu_recover(struct scsi_device *sdev,
struct dk_cxlflash_recover_afu *recover) struct dk_cxlflash_recover_afu *recover)
{ {
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev; struct device *dev = &cfg->dev->dev;
struct llun_info *lli = sdev->hostdata; struct llun_info *lli = sdev->hostdata;
struct afu *afu = cfg->afu; struct afu *afu = cfg->afu;
struct ctx_info *ctxi = NULL; struct ctx_info *ctxi = NULL;
struct mutex *mutex = &cfg->ctx_recovery_mutex; struct mutex *mutex = &cfg->ctx_recovery_mutex;
u64 flags;
u64 ctxid = DECODE_CTXID(recover->context_id), u64 ctxid = DECODE_CTXID(recover->context_id),
rctxid = recover->context_id; rctxid = recover->context_id;
long reg; long reg;
@ -1632,19 +1642,19 @@ static int cxlflash_afu_recover(struct scsi_device *sdev,
goto out; goto out;
rc = check_state(cfg); rc = check_state(cfg);
if (rc) { if (rc) {
dev_err(dev, "%s: Failed state! rc=%d\n", __func__, rc); dev_err(dev, "%s: Failed state rc=%d\n", __func__, rc);
rc = -ENODEV; rc = -ENODEV;
goto out; goto out;
} }
dev_dbg(dev, "%s: reason 0x%016llX rctxid=%016llX\n", dev_dbg(dev, "%s: reason=%016llx rctxid=%016llx\n",
__func__, recover->reason, rctxid); __func__, recover->reason, rctxid);
retry: retry:
/* Ensure that this process is attached to the context */ /* Ensure that this process is attached to the context */
ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK); ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK);
if (unlikely(!ctxi)) { if (unlikely(!ctxi)) {
dev_dbg(dev, "%s: Bad context! (%llu)\n", __func__, ctxid); dev_dbg(dev, "%s: Bad context ctxid=%llu\n", __func__, ctxid);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
@ -1653,12 +1663,12 @@ retry:
retry_recover: retry_recover:
rc = recover_context(cfg, ctxi, &new_adap_fd); rc = recover_context(cfg, ctxi, &new_adap_fd);
if (unlikely(rc)) { if (unlikely(rc)) {
dev_err(dev, "%s: Recovery failed for context %llu (rc=%d)\n", dev_err(dev, "%s: Recovery failed ctxid=%llu rc=%d\n",
__func__, ctxid, rc); __func__, ctxid, rc);
if ((rc == -ENODEV) && if ((rc == -ENODEV) &&
((atomic_read(&cfg->recovery_threads) > 1) || ((atomic_read(&cfg->recovery_threads) > 1) ||
(lretry--))) { (lretry--))) {
dev_dbg(dev, "%s: Going to try again!\n", dev_dbg(dev, "%s: Going to try again\n",
__func__); __func__);
mutex_unlock(mutex); mutex_unlock(mutex);
msleep(100); msleep(100);
@ -1672,11 +1682,16 @@ retry_recover:
} }
ctxi->err_recovery_active = false; ctxi->err_recovery_active = false;
flags = DK_CXLFLASH_APP_CLOSE_ADAP_FD |
DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET;
if (afu_is_sq_cmd_mode(afu))
flags |= DK_CXLFLASH_CONTEXT_SQ_CMD_MODE;
recover->hdr.return_flags = flags;
recover->context_id = ctxi->ctxid; recover->context_id = ctxi->ctxid;
recover->adap_fd = new_adap_fd; recover->adap_fd = new_adap_fd;
recover->mmio_size = sizeof(afu->afu_map->hosts[0].harea); recover->mmio_size = sizeof(afu->afu_map->hosts[0].harea);
recover->hdr.return_flags = DK_CXLFLASH_APP_CLOSE_ADAP_FD |
DK_CXLFLASH_RECOVER_AFU_CONTEXT_RESET;
goto out; goto out;
} }
@ -1699,7 +1714,7 @@ retry_recover:
goto retry; goto retry;
} }
dev_dbg(dev, "%s: MMIO working, no recovery required!\n", __func__); dev_dbg(dev, "%s: MMIO working, no recovery required\n", __func__);
out: out:
if (likely(ctxi)) if (likely(ctxi))
put_context(ctxi); put_context(ctxi);
@ -1718,7 +1733,7 @@ out:
static int process_sense(struct scsi_device *sdev, static int process_sense(struct scsi_device *sdev,
struct dk_cxlflash_verify *verify) struct dk_cxlflash_verify *verify)
{ {
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev; struct device *dev = &cfg->dev->dev;
struct llun_info *lli = sdev->hostdata; struct llun_info *lli = sdev->hostdata;
struct glun_info *gli = lli->parent; struct glun_info *gli = lli->parent;
@ -1729,7 +1744,7 @@ static int process_sense(struct scsi_device *sdev,
rc = scsi_normalize_sense((const u8 *)&verify->sense_data, rc = scsi_normalize_sense((const u8 *)&verify->sense_data,
DK_CXLFLASH_VERIFY_SENSE_LEN, &sshdr); DK_CXLFLASH_VERIFY_SENSE_LEN, &sshdr);
if (!rc) { if (!rc) {
dev_err(dev, "%s: Failed to normalize sense data!\n", __func__); dev_err(dev, "%s: Failed to normalize sense data\n", __func__);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
@ -1785,7 +1800,7 @@ static int cxlflash_disk_verify(struct scsi_device *sdev,
{ {
int rc = 0; int rc = 0;
struct ctx_info *ctxi = NULL; struct ctx_info *ctxi = NULL;
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev; struct device *dev = &cfg->dev->dev;
struct llun_info *lli = sdev->hostdata; struct llun_info *lli = sdev->hostdata;
struct glun_info *gli = lli->parent; struct glun_info *gli = lli->parent;
@ -1795,20 +1810,20 @@ static int cxlflash_disk_verify(struct scsi_device *sdev,
rctxid = verify->context_id; rctxid = verify->context_id;
u64 last_lba = 0; u64 last_lba = 0;
dev_dbg(dev, "%s: ctxid=%llu rhndl=%016llX, hint=%016llX, " dev_dbg(dev, "%s: ctxid=%llu rhndl=%016llx, hint=%016llx, "
"flags=%016llX\n", __func__, ctxid, verify->rsrc_handle, "flags=%016llx\n", __func__, ctxid, verify->rsrc_handle,
verify->hint, verify->hdr.flags); verify->hint, verify->hdr.flags);
ctxi = get_context(cfg, rctxid, lli, 0); ctxi = get_context(cfg, rctxid, lli, 0);
if (unlikely(!ctxi)) { if (unlikely(!ctxi)) {
dev_dbg(dev, "%s: Bad context! (%llu)\n", __func__, ctxid); dev_dbg(dev, "%s: Bad context ctxid=%llu\n", __func__, ctxid);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
rhte = get_rhte(ctxi, rhndl, lli); rhte = get_rhte(ctxi, rhndl, lli);
if (unlikely(!rhte)) { if (unlikely(!rhte)) {
dev_dbg(dev, "%s: Bad resource handle! (%d)\n", dev_dbg(dev, "%s: Bad resource handle rhndl=%d\n",
__func__, rhndl); __func__, rhndl);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
@ -1855,7 +1870,7 @@ static int cxlflash_disk_verify(struct scsi_device *sdev,
out: out:
if (likely(ctxi)) if (likely(ctxi))
put_context(ctxi); put_context(ctxi);
dev_dbg(dev, "%s: returning rc=%d llba=%llX\n", dev_dbg(dev, "%s: returning rc=%d llba=%llx\n",
__func__, rc, verify->last_lba); __func__, rc, verify->last_lba);
return rc; return rc;
} }
@ -1907,7 +1922,7 @@ static char *decode_ioctl(int cmd)
*/ */
static int cxlflash_disk_direct_open(struct scsi_device *sdev, void *arg) static int cxlflash_disk_direct_open(struct scsi_device *sdev, void *arg)
{ {
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev; struct device *dev = &cfg->dev->dev;
struct afu *afu = cfg->afu; struct afu *afu = cfg->afu;
struct llun_info *lli = sdev->hostdata; struct llun_info *lli = sdev->hostdata;
@ -1927,25 +1942,25 @@ static int cxlflash_disk_direct_open(struct scsi_device *sdev, void *arg)
struct ctx_info *ctxi = NULL; struct ctx_info *ctxi = NULL;
struct sisl_rht_entry *rhte = NULL; struct sisl_rht_entry *rhte = NULL;
pr_debug("%s: ctxid=%llu ls=0x%llx\n", __func__, ctxid, lun_size); dev_dbg(dev, "%s: ctxid=%llu ls=%llu\n", __func__, ctxid, lun_size);
rc = cxlflash_lun_attach(gli, MODE_PHYSICAL, false); rc = cxlflash_lun_attach(gli, MODE_PHYSICAL, false);
if (unlikely(rc)) { if (unlikely(rc)) {
dev_dbg(dev, "%s: Failed to attach to LUN! (PHYSICAL)\n", dev_dbg(dev, "%s: Failed attach to LUN (PHYSICAL)\n", __func__);
__func__);
goto out; goto out;
} }
ctxi = get_context(cfg, rctxid, lli, 0); ctxi = get_context(cfg, rctxid, lli, 0);
if (unlikely(!ctxi)) { if (unlikely(!ctxi)) {
dev_dbg(dev, "%s: Bad context! (%llu)\n", __func__, ctxid); dev_dbg(dev, "%s: Bad context ctxid=%llu\n", __func__, ctxid);
rc = -EINVAL; rc = -EINVAL;
goto err1; goto err1;
} }
rhte = rhte_checkout(ctxi, lli); rhte = rhte_checkout(ctxi, lli);
if (unlikely(!rhte)) { if (unlikely(!rhte)) {
dev_dbg(dev, "%s: too many opens for this context\n", __func__); dev_dbg(dev, "%s: Too many opens ctxid=%lld\n",
__func__, ctxid);
rc = -EMFILE; /* too many opens */ rc = -EMFILE; /* too many opens */
goto err1; goto err1;
} }
@ -1963,7 +1978,7 @@ static int cxlflash_disk_direct_open(struct scsi_device *sdev, void *arg)
out: out:
if (likely(ctxi)) if (likely(ctxi))
put_context(ctxi); put_context(ctxi);
dev_dbg(dev, "%s: returning handle 0x%llx rc=%d llba %lld\n", dev_dbg(dev, "%s: returning handle=%llu rc=%d llba=%llu\n",
__func__, rsrc_handle, rc, last_lba); __func__, rsrc_handle, rc, last_lba);
return rc; return rc;
@ -1985,7 +2000,7 @@ err1:
*/ */
static int ioctl_common(struct scsi_device *sdev, int cmd) static int ioctl_common(struct scsi_device *sdev, int cmd)
{ {
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev; struct device *dev = &cfg->dev->dev;
struct llun_info *lli = sdev->hostdata; struct llun_info *lli = sdev->hostdata;
int rc = 0; int rc = 0;
@ -2002,7 +2017,7 @@ static int ioctl_common(struct scsi_device *sdev, int cmd)
case DK_CXLFLASH_VLUN_RESIZE: case DK_CXLFLASH_VLUN_RESIZE:
case DK_CXLFLASH_RELEASE: case DK_CXLFLASH_RELEASE:
case DK_CXLFLASH_DETACH: case DK_CXLFLASH_DETACH:
dev_dbg(dev, "%s: Command override! (%d)\n", dev_dbg(dev, "%s: Command override rc=%d\n",
__func__, rc); __func__, rc);
rc = 0; rc = 0;
break; break;
@ -2032,7 +2047,7 @@ int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
{ {
typedef int (*sioctl) (struct scsi_device *, void *); typedef int (*sioctl) (struct scsi_device *, void *);
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev; struct device *dev = &cfg->dev->dev;
struct afu *afu = cfg->afu; struct afu *afu = cfg->afu;
struct dk_cxlflash_hdr *hdr; struct dk_cxlflash_hdr *hdr;
@ -2111,7 +2126,7 @@ int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
} }
if (unlikely(copy_from_user(&buf, arg, size))) { if (unlikely(copy_from_user(&buf, arg, size))) {
dev_err(dev, "%s: copy_from_user() fail! " dev_err(dev, "%s: copy_from_user() fail "
"size=%lu cmd=%d (%s) arg=%p\n", "size=%lu cmd=%d (%s) arg=%p\n",
__func__, size, cmd, decode_ioctl(cmd), arg); __func__, size, cmd, decode_ioctl(cmd), arg);
rc = -EFAULT; rc = -EFAULT;
@ -2127,7 +2142,7 @@ int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
} }
if (hdr->rsvd[0] || hdr->rsvd[1] || hdr->rsvd[2] || hdr->return_flags) { if (hdr->rsvd[0] || hdr->rsvd[1] || hdr->rsvd[2] || hdr->return_flags) {
dev_dbg(dev, "%s: Reserved/rflags populated!\n", __func__); dev_dbg(dev, "%s: Reserved/rflags populated\n", __func__);
rc = -EINVAL; rc = -EINVAL;
goto cxlflash_ioctl_exit; goto cxlflash_ioctl_exit;
} }
@ -2135,7 +2150,7 @@ int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
rc = do_ioctl(sdev, (void *)&buf); rc = do_ioctl(sdev, (void *)&buf);
if (likely(!rc)) if (likely(!rc))
if (unlikely(copy_to_user(arg, &buf, size))) { if (unlikely(copy_to_user(arg, &buf, size))) {
dev_err(dev, "%s: copy_to_user() fail! " dev_err(dev, "%s: copy_to_user() fail "
"size=%lu cmd=%d (%s) arg=%p\n", "size=%lu cmd=%d (%s) arg=%p\n",
__func__, size, cmd, decode_ioctl(cmd), arg); __func__, size, cmd, decode_ioctl(cmd), arg);
rc = -EFAULT; rc = -EFAULT;

View File

@ -66,8 +66,8 @@ static int ba_init(struct ba_lun *ba_lun)
int last_word_underflow = 0; int last_word_underflow = 0;
u64 *lam; u64 *lam;
pr_debug("%s: Initializing LUN: lun_id = %llX, " pr_debug("%s: Initializing LUN: lun_id=%016llx "
"ba_lun->lsize = %lX, ba_lun->au_size = %lX\n", "ba_lun->lsize=%lx ba_lun->au_size=%lX\n",
__func__, ba_lun->lun_id, ba_lun->lsize, ba_lun->au_size); __func__, ba_lun->lun_id, ba_lun->lsize, ba_lun->au_size);
/* Calculate bit map size */ /* Calculate bit map size */
@ -80,7 +80,7 @@ static int ba_init(struct ba_lun *ba_lun)
/* Allocate lun information container */ /* Allocate lun information container */
bali = kzalloc(sizeof(struct ba_lun_info), GFP_KERNEL); bali = kzalloc(sizeof(struct ba_lun_info), GFP_KERNEL);
if (unlikely(!bali)) { if (unlikely(!bali)) {
pr_err("%s: Failed to allocate lun_info for lun_id %llX\n", pr_err("%s: Failed to allocate lun_info lun_id=%016llx\n",
__func__, ba_lun->lun_id); __func__, ba_lun->lun_id);
return -ENOMEM; return -ENOMEM;
} }
@ -96,7 +96,7 @@ static int ba_init(struct ba_lun *ba_lun)
GFP_KERNEL); GFP_KERNEL);
if (unlikely(!bali->lun_alloc_map)) { if (unlikely(!bali->lun_alloc_map)) {
pr_err("%s: Failed to allocate lun allocation map: " pr_err("%s: Failed to allocate lun allocation map: "
"lun_id = %llX\n", __func__, ba_lun->lun_id); "lun_id=%016llx\n", __func__, ba_lun->lun_id);
kfree(bali); kfree(bali);
return -ENOMEM; return -ENOMEM;
} }
@ -125,7 +125,7 @@ static int ba_init(struct ba_lun *ba_lun)
bali->aun_clone_map = kzalloc((bali->total_aus * sizeof(u8)), bali->aun_clone_map = kzalloc((bali->total_aus * sizeof(u8)),
GFP_KERNEL); GFP_KERNEL);
if (unlikely(!bali->aun_clone_map)) { if (unlikely(!bali->aun_clone_map)) {
pr_err("%s: Failed to allocate clone map: lun_id = %llX\n", pr_err("%s: Failed to allocate clone map: lun_id=%016llx\n",
__func__, ba_lun->lun_id); __func__, ba_lun->lun_id);
kfree(bali->lun_alloc_map); kfree(bali->lun_alloc_map);
kfree(bali); kfree(bali);
@ -136,7 +136,7 @@ static int ba_init(struct ba_lun *ba_lun)
ba_lun->ba_lun_handle = bali; ba_lun->ba_lun_handle = bali;
pr_debug("%s: Successfully initialized the LUN: " pr_debug("%s: Successfully initialized the LUN: "
"lun_id = %llX, bitmap size = %X, free_aun_cnt = %llX\n", "lun_id=%016llx bitmap size=%x, free_aun_cnt=%llx\n",
__func__, ba_lun->lun_id, bali->lun_bmap_size, __func__, ba_lun->lun_id, bali->lun_bmap_size,
bali->free_aun_cnt); bali->free_aun_cnt);
return 0; return 0;
@ -165,10 +165,9 @@ static int find_free_range(u32 low,
num_bits = (sizeof(*lam) * BITS_PER_BYTE); num_bits = (sizeof(*lam) * BITS_PER_BYTE);
bit_pos = find_first_bit(lam, num_bits); bit_pos = find_first_bit(lam, num_bits);
pr_devel("%s: Found free bit %llX in LUN " pr_devel("%s: Found free bit %llu in LUN "
"map entry %llX at bitmap index = %X\n", "map entry %016llx at bitmap index = %d\n",
__func__, bit_pos, bali->lun_alloc_map[i], __func__, bit_pos, bali->lun_alloc_map[i], i);
i);
*bit_word = i; *bit_word = i;
bali->free_aun_cnt--; bali->free_aun_cnt--;
@ -194,11 +193,11 @@ static u64 ba_alloc(struct ba_lun *ba_lun)
bali = ba_lun->ba_lun_handle; bali = ba_lun->ba_lun_handle;
pr_debug("%s: Received block allocation request: " pr_debug("%s: Received block allocation request: "
"lun_id = %llX, free_aun_cnt = %llX\n", "lun_id=%016llx free_aun_cnt=%llx\n",
__func__, ba_lun->lun_id, bali->free_aun_cnt); __func__, ba_lun->lun_id, bali->free_aun_cnt);
if (bali->free_aun_cnt == 0) { if (bali->free_aun_cnt == 0) {
pr_debug("%s: No space left on LUN: lun_id = %llX\n", pr_debug("%s: No space left on LUN: lun_id=%016llx\n",
__func__, ba_lun->lun_id); __func__, ba_lun->lun_id);
return -1ULL; return -1ULL;
} }
@ -212,7 +211,7 @@ static u64 ba_alloc(struct ba_lun *ba_lun)
bali, &bit_word); bali, &bit_word);
if (bit_pos == -1) { if (bit_pos == -1) {
pr_debug("%s: Could not find an allocation unit on LUN:" pr_debug("%s: Could not find an allocation unit on LUN:"
" lun_id = %llX\n", __func__, ba_lun->lun_id); " lun_id=%016llx\n", __func__, ba_lun->lun_id);
return -1ULL; return -1ULL;
} }
} }
@ -223,8 +222,8 @@ static u64 ba_alloc(struct ba_lun *ba_lun)
else else
bali->free_curr_idx = bit_word; bali->free_curr_idx = bit_word;
pr_debug("%s: Allocating AU number %llX, on lun_id %llX, " pr_debug("%s: Allocating AU number=%llx lun_id=%016llx "
"free_aun_cnt = %llX\n", __func__, "free_aun_cnt=%llx\n", __func__,
((bit_word * BITS_PER_LONG) + bit_pos), ba_lun->lun_id, ((bit_word * BITS_PER_LONG) + bit_pos), ba_lun->lun_id,
bali->free_aun_cnt); bali->free_aun_cnt);
@ -266,18 +265,18 @@ static int ba_free(struct ba_lun *ba_lun, u64 to_free)
bali = ba_lun->ba_lun_handle; bali = ba_lun->ba_lun_handle;
if (validate_alloc(bali, to_free)) { if (validate_alloc(bali, to_free)) {
pr_debug("%s: The AUN %llX is not allocated on lun_id %llX\n", pr_debug("%s: AUN %llx is not allocated on lun_id=%016llx\n",
__func__, to_free, ba_lun->lun_id); __func__, to_free, ba_lun->lun_id);
return -1; return -1;
} }
pr_debug("%s: Received a request to free AU %llX on lun_id %llX, " pr_debug("%s: Received a request to free AU=%llx lun_id=%016llx "
"free_aun_cnt = %llX\n", __func__, to_free, ba_lun->lun_id, "free_aun_cnt=%llx\n", __func__, to_free, ba_lun->lun_id,
bali->free_aun_cnt); bali->free_aun_cnt);
if (bali->aun_clone_map[to_free] > 0) { if (bali->aun_clone_map[to_free] > 0) {
pr_debug("%s: AUN %llX on lun_id %llX has been cloned. Clone " pr_debug("%s: AUN %llx lun_id=%016llx cloned. Clone count=%x\n",
"count = %X\n", __func__, to_free, ba_lun->lun_id, __func__, to_free, ba_lun->lun_id,
bali->aun_clone_map[to_free]); bali->aun_clone_map[to_free]);
bali->aun_clone_map[to_free]--; bali->aun_clone_map[to_free]--;
return 0; return 0;
@ -294,8 +293,8 @@ static int ba_free(struct ba_lun *ba_lun, u64 to_free)
else if (idx > bali->free_high_idx) else if (idx > bali->free_high_idx)
bali->free_high_idx = idx; bali->free_high_idx = idx;
pr_debug("%s: Successfully freed AU at bit_pos %X, bit map index %X on " pr_debug("%s: Successfully freed AU bit_pos=%x bit map index=%x "
"lun_id %llX, free_aun_cnt = %llX\n", __func__, bit_pos, idx, "lun_id=%016llx free_aun_cnt=%llx\n", __func__, bit_pos, idx,
ba_lun->lun_id, bali->free_aun_cnt); ba_lun->lun_id, bali->free_aun_cnt);
return 0; return 0;
@ -313,16 +312,16 @@ static int ba_clone(struct ba_lun *ba_lun, u64 to_clone)
struct ba_lun_info *bali = ba_lun->ba_lun_handle; struct ba_lun_info *bali = ba_lun->ba_lun_handle;
if (validate_alloc(bali, to_clone)) { if (validate_alloc(bali, to_clone)) {
pr_debug("%s: AUN %llX is not allocated on lun_id %llX\n", pr_debug("%s: AUN=%llx not allocated on lun_id=%016llx\n",
__func__, to_clone, ba_lun->lun_id); __func__, to_clone, ba_lun->lun_id);
return -1; return -1;
} }
pr_debug("%s: Received a request to clone AUN %llX on lun_id %llX\n", pr_debug("%s: Received a request to clone AUN %llx on lun_id=%016llx\n",
__func__, to_clone, ba_lun->lun_id); __func__, to_clone, ba_lun->lun_id);
if (bali->aun_clone_map[to_clone] == MAX_AUN_CLONE_CNT) { if (bali->aun_clone_map[to_clone] == MAX_AUN_CLONE_CNT) {
pr_debug("%s: AUN %llX on lun_id %llX hit max clones already\n", pr_debug("%s: AUN %llx on lun_id=%016llx hit max clones already\n",
__func__, to_clone, ba_lun->lun_id); __func__, to_clone, ba_lun->lun_id);
return -1; return -1;
} }
@ -433,7 +432,7 @@ static int write_same16(struct scsi_device *sdev,
u64 offset = lba; u64 offset = lba;
int left = nblks; int left = nblks;
u32 to = sdev->request_queue->rq_timeout; u32 to = sdev->request_queue->rq_timeout;
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev; struct device *dev = &cfg->dev->dev;
cmd_buf = kzalloc(CMD_BUFSIZE, GFP_KERNEL); cmd_buf = kzalloc(CMD_BUFSIZE, GFP_KERNEL);
@ -459,7 +458,7 @@ static int write_same16(struct scsi_device *sdev,
down_read(&cfg->ioctl_rwsem); down_read(&cfg->ioctl_rwsem);
rc = check_state(cfg); rc = check_state(cfg);
if (rc) { if (rc) {
dev_err(dev, "%s: Failed state! result=0x08%X\n", dev_err(dev, "%s: Failed state result=%08x\n",
__func__, result); __func__, result);
rc = -ENODEV; rc = -ENODEV;
goto out; goto out;
@ -467,7 +466,7 @@ static int write_same16(struct scsi_device *sdev,
if (result) { if (result) {
dev_err_ratelimited(dev, "%s: command failed for " dev_err_ratelimited(dev, "%s: command failed for "
"offset %lld result=0x%x\n", "offset=%lld result=%08x\n",
__func__, offset, result); __func__, offset, result);
rc = -EIO; rc = -EIO;
goto out; goto out;
@ -480,7 +479,7 @@ out:
kfree(cmd_buf); kfree(cmd_buf);
kfree(scsi_cmd); kfree(scsi_cmd);
kfree(sense_buf); kfree(sense_buf);
pr_debug("%s: returning rc=%d\n", __func__, rc); dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
return rc; return rc;
} }
@ -508,6 +507,8 @@ static int grow_lxt(struct afu *afu,
struct sisl_rht_entry *rhte, struct sisl_rht_entry *rhte,
u64 *new_size) u64 *new_size)
{ {
struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev;
struct sisl_lxt_entry *lxt = NULL, *lxt_old = NULL; struct sisl_lxt_entry *lxt = NULL, *lxt_old = NULL;
struct llun_info *lli = sdev->hostdata; struct llun_info *lli = sdev->hostdata;
struct glun_info *gli = lli->parent; struct glun_info *gli = lli->parent;
@ -527,7 +528,8 @@ static int grow_lxt(struct afu *afu,
mutex_lock(&blka->mutex); mutex_lock(&blka->mutex);
av_size = ba_space(&blka->ba_lun); av_size = ba_space(&blka->ba_lun);
if (unlikely(av_size <= 0)) { if (unlikely(av_size <= 0)) {
pr_debug("%s: ba_space error: av_size %d\n", __func__, av_size); dev_dbg(dev, "%s: ba_space error av_size=%d\n",
__func__, av_size);
mutex_unlock(&blka->mutex); mutex_unlock(&blka->mutex);
rc = -ENOSPC; rc = -ENOSPC;
goto out; goto out;
@ -568,8 +570,8 @@ static int grow_lxt(struct afu *afu,
*/ */
aun = ba_alloc(&blka->ba_lun); aun = ba_alloc(&blka->ba_lun);
if ((aun == -1ULL) || (aun >= blka->nchunk)) if ((aun == -1ULL) || (aun >= blka->nchunk))
pr_debug("%s: ba_alloc error: allocated chunk# %llX, " dev_dbg(dev, "%s: ba_alloc error allocated chunk=%llu "
"max %llX\n", __func__, aun, blka->nchunk - 1); "max=%llu\n", __func__, aun, blka->nchunk - 1);
/* select both ports, use r/w perms from RHT */ /* select both ports, use r/w perms from RHT */
lxt[i].rlba_base = ((aun << MC_CHUNK_SHIFT) | lxt[i].rlba_base = ((aun << MC_CHUNK_SHIFT) |
@ -599,7 +601,7 @@ static int grow_lxt(struct afu *afu,
kfree(lxt_old); kfree(lxt_old);
*new_size = my_new_size; *new_size = my_new_size;
out: out:
pr_debug("%s: returning rc=%d\n", __func__, rc); dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
return rc; return rc;
} }
@ -621,6 +623,8 @@ static int shrink_lxt(struct afu *afu,
struct ctx_info *ctxi, struct ctx_info *ctxi,
u64 *new_size) u64 *new_size)
{ {
struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev;
struct sisl_lxt_entry *lxt, *lxt_old; struct sisl_lxt_entry *lxt, *lxt_old;
struct llun_info *lli = sdev->hostdata; struct llun_info *lli = sdev->hostdata;
struct glun_info *gli = lli->parent; struct glun_info *gli = lli->parent;
@ -706,7 +710,7 @@ static int shrink_lxt(struct afu *afu,
kfree(lxt_old); kfree(lxt_old);
*new_size = my_new_size; *new_size = my_new_size;
out: out:
pr_debug("%s: returning rc=%d\n", __func__, rc); dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
return rc; return rc;
} }
@ -728,7 +732,8 @@ int _cxlflash_vlun_resize(struct scsi_device *sdev,
struct ctx_info *ctxi, struct ctx_info *ctxi,
struct dk_cxlflash_resize *resize) struct dk_cxlflash_resize *resize)
{ {
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev;
struct llun_info *lli = sdev->hostdata; struct llun_info *lli = sdev->hostdata;
struct glun_info *gli = lli->parent; struct glun_info *gli = lli->parent;
struct afu *afu = cfg->afu; struct afu *afu = cfg->afu;
@ -751,13 +756,13 @@ int _cxlflash_vlun_resize(struct scsi_device *sdev,
nsectors = (resize->req_size * CXLFLASH_BLOCK_SIZE) / gli->blk_len; nsectors = (resize->req_size * CXLFLASH_BLOCK_SIZE) / gli->blk_len;
new_size = DIV_ROUND_UP(nsectors, MC_CHUNK_SIZE); new_size = DIV_ROUND_UP(nsectors, MC_CHUNK_SIZE);
pr_debug("%s: ctxid=%llu rhndl=0x%llx, req_size=0x%llx," dev_dbg(dev, "%s: ctxid=%llu rhndl=%llu req_size=%llu new_size=%llu\n",
"new_size=%llx\n", __func__, ctxid, resize->rsrc_handle, __func__, ctxid, resize->rsrc_handle, resize->req_size,
resize->req_size, new_size); new_size);
if (unlikely(gli->mode != MODE_VIRTUAL)) { if (unlikely(gli->mode != MODE_VIRTUAL)) {
pr_debug("%s: LUN mode does not support resize! (%d)\n", dev_dbg(dev, "%s: LUN mode does not support resize mode=%d\n",
__func__, gli->mode); __func__, gli->mode);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
@ -766,7 +771,8 @@ int _cxlflash_vlun_resize(struct scsi_device *sdev,
if (!ctxi) { if (!ctxi) {
ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK); ctxi = get_context(cfg, rctxid, lli, CTX_CTRL_ERR_FALLBACK);
if (unlikely(!ctxi)) { if (unlikely(!ctxi)) {
pr_debug("%s: Bad context! (%llu)\n", __func__, ctxid); dev_dbg(dev, "%s: Bad context ctxid=%llu\n",
__func__, ctxid);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
@ -776,7 +782,8 @@ int _cxlflash_vlun_resize(struct scsi_device *sdev,
rhte = get_rhte(ctxi, rhndl, lli); rhte = get_rhte(ctxi, rhndl, lli);
if (unlikely(!rhte)) { if (unlikely(!rhte)) {
pr_debug("%s: Bad resource handle! (%u)\n", __func__, rhndl); dev_dbg(dev, "%s: Bad resource handle rhndl=%u\n",
__func__, rhndl);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
@ -794,8 +801,8 @@ int _cxlflash_vlun_resize(struct scsi_device *sdev,
out: out:
if (put_ctx) if (put_ctx)
put_context(ctxi); put_context(ctxi);
pr_debug("%s: resized to %lld returning rc=%d\n", dev_dbg(dev, "%s: resized to %llu returning rc=%d\n",
__func__, resize->last_lba, rc); __func__, resize->last_lba, rc);
return rc; return rc;
} }
@ -815,6 +822,7 @@ void cxlflash_restore_luntable(struct cxlflash_cfg *cfg)
u32 chan; u32 chan;
u32 lind; u32 lind;
struct afu *afu = cfg->afu; struct afu *afu = cfg->afu;
struct device *dev = &cfg->dev->dev;
struct sisl_global_map __iomem *agm = &afu->afu_map->global; struct sisl_global_map __iomem *agm = &afu->afu_map->global;
mutex_lock(&global.mutex); mutex_lock(&global.mutex);
@ -828,15 +836,15 @@ void cxlflash_restore_luntable(struct cxlflash_cfg *cfg)
if (lli->port_sel == BOTH_PORTS) { if (lli->port_sel == BOTH_PORTS) {
writeq_be(lli->lun_id[0], &agm->fc_port[0][lind]); writeq_be(lli->lun_id[0], &agm->fc_port[0][lind]);
writeq_be(lli->lun_id[1], &agm->fc_port[1][lind]); writeq_be(lli->lun_id[1], &agm->fc_port[1][lind]);
pr_debug("%s: Virtual LUN on slot %d id0=%llx, " dev_dbg(dev, "%s: Virtual LUN on slot %d id0=%llx "
"id1=%llx\n", __func__, lind, "id1=%llx\n", __func__, lind,
lli->lun_id[0], lli->lun_id[1]); lli->lun_id[0], lli->lun_id[1]);
} else { } else {
chan = PORT2CHAN(lli->port_sel); chan = PORT2CHAN(lli->port_sel);
writeq_be(lli->lun_id[chan], &agm->fc_port[chan][lind]); writeq_be(lli->lun_id[chan], &agm->fc_port[chan][lind]);
pr_debug("%s: Virtual LUN on slot %d chan=%d, " dev_dbg(dev, "%s: Virtual LUN on slot %d chan=%d "
"id=%llx\n", __func__, lind, chan, "id=%llx\n", __func__, lind, chan,
lli->lun_id[chan]); lli->lun_id[chan]);
} }
} }
@ -860,6 +868,7 @@ static int init_luntable(struct cxlflash_cfg *cfg, struct llun_info *lli)
u32 lind; u32 lind;
int rc = 0; int rc = 0;
struct afu *afu = cfg->afu; struct afu *afu = cfg->afu;
struct device *dev = &cfg->dev->dev;
struct sisl_global_map __iomem *agm = &afu->afu_map->global; struct sisl_global_map __iomem *agm = &afu->afu_map->global;
mutex_lock(&global.mutex); mutex_lock(&global.mutex);
@ -882,8 +891,8 @@ static int init_luntable(struct cxlflash_cfg *cfg, struct llun_info *lli)
writeq_be(lli->lun_id[0], &agm->fc_port[0][lind]); writeq_be(lli->lun_id[0], &agm->fc_port[0][lind]);
writeq_be(lli->lun_id[1], &agm->fc_port[1][lind]); writeq_be(lli->lun_id[1], &agm->fc_port[1][lind]);
cfg->promote_lun_index++; cfg->promote_lun_index++;
pr_debug("%s: Virtual LUN on slot %d id0=%llx, id1=%llx\n", dev_dbg(dev, "%s: Virtual LUN on slot %d id0=%llx id1=%llx\n",
__func__, lind, lli->lun_id[0], lli->lun_id[1]); __func__, lind, lli->lun_id[0], lli->lun_id[1]);
} else { } else {
/* /*
* If this LUN is visible only from one port, we will put * If this LUN is visible only from one port, we will put
@ -898,14 +907,14 @@ static int init_luntable(struct cxlflash_cfg *cfg, struct llun_info *lli)
lind = lli->lun_index = cfg->last_lun_index[chan]; lind = lli->lun_index = cfg->last_lun_index[chan];
writeq_be(lli->lun_id[chan], &agm->fc_port[chan][lind]); writeq_be(lli->lun_id[chan], &agm->fc_port[chan][lind]);
cfg->last_lun_index[chan]--; cfg->last_lun_index[chan]--;
pr_debug("%s: Virtual LUN on slot %d chan=%d, id=%llx\n", dev_dbg(dev, "%s: Virtual LUN on slot %d chan=%d id=%llx\n",
__func__, lind, chan, lli->lun_id[chan]); __func__, lind, chan, lli->lun_id[chan]);
} }
lli->in_table = true; lli->in_table = true;
out: out:
mutex_unlock(&global.mutex); mutex_unlock(&global.mutex);
pr_debug("%s: returning rc=%d\n", __func__, rc); dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
return rc; return rc;
} }
@ -923,7 +932,7 @@ out:
*/ */
int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg) int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg)
{ {
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev; struct device *dev = &cfg->dev->dev;
struct llun_info *lli = sdev->hostdata; struct llun_info *lli = sdev->hostdata;
struct glun_info *gli = lli->parent; struct glun_info *gli = lli->parent;
@ -942,14 +951,14 @@ int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg)
struct ctx_info *ctxi = NULL; struct ctx_info *ctxi = NULL;
struct sisl_rht_entry *rhte = NULL; struct sisl_rht_entry *rhte = NULL;
pr_debug("%s: ctxid=%llu ls=0x%llx\n", __func__, ctxid, lun_size); dev_dbg(dev, "%s: ctxid=%llu ls=%llu\n", __func__, ctxid, lun_size);
/* Setup the LUNs block allocator on first call */ /* Setup the LUNs block allocator on first call */
mutex_lock(&gli->mutex); mutex_lock(&gli->mutex);
if (gli->mode == MODE_NONE) { if (gli->mode == MODE_NONE) {
rc = init_vlun(lli); rc = init_vlun(lli);
if (rc) { if (rc) {
dev_err(dev, "%s: call to init_vlun failed rc=%d!\n", dev_err(dev, "%s: init_vlun failed rc=%d\n",
__func__, rc); __func__, rc);
rc = -ENOMEM; rc = -ENOMEM;
goto err0; goto err0;
@ -958,29 +967,28 @@ int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg)
rc = cxlflash_lun_attach(gli, MODE_VIRTUAL, true); rc = cxlflash_lun_attach(gli, MODE_VIRTUAL, true);
if (unlikely(rc)) { if (unlikely(rc)) {
dev_err(dev, "%s: Failed to attach to LUN! (VIRTUAL)\n", dev_err(dev, "%s: Failed attach to LUN (VIRTUAL)\n", __func__);
__func__);
goto err0; goto err0;
} }
mutex_unlock(&gli->mutex); mutex_unlock(&gli->mutex);
rc = init_luntable(cfg, lli); rc = init_luntable(cfg, lli);
if (rc) { if (rc) {
dev_err(dev, "%s: call to init_luntable failed rc=%d!\n", dev_err(dev, "%s: init_luntable failed rc=%d\n", __func__, rc);
__func__, rc);
goto err1; goto err1;
} }
ctxi = get_context(cfg, rctxid, lli, 0); ctxi = get_context(cfg, rctxid, lli, 0);
if (unlikely(!ctxi)) { if (unlikely(!ctxi)) {
dev_err(dev, "%s: Bad context! (%llu)\n", __func__, ctxid); dev_err(dev, "%s: Bad context ctxid=%llu\n", __func__, ctxid);
rc = -EINVAL; rc = -EINVAL;
goto err1; goto err1;
} }
rhte = rhte_checkout(ctxi, lli); rhte = rhte_checkout(ctxi, lli);
if (unlikely(!rhte)) { if (unlikely(!rhte)) {
dev_err(dev, "%s: too many opens for this context\n", __func__); dev_err(dev, "%s: too many opens ctxid=%llu\n",
__func__, ctxid);
rc = -EMFILE; /* too many opens */ rc = -EMFILE; /* too many opens */
goto err1; goto err1;
} }
@ -996,7 +1004,7 @@ int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg)
resize.rsrc_handle = rsrc_handle; resize.rsrc_handle = rsrc_handle;
rc = _cxlflash_vlun_resize(sdev, ctxi, &resize); rc = _cxlflash_vlun_resize(sdev, ctxi, &resize);
if (rc) { if (rc) {
dev_err(dev, "%s: resize failed rc %d\n", __func__, rc); dev_err(dev, "%s: resize failed rc=%d\n", __func__, rc);
goto err2; goto err2;
} }
last_lba = resize.last_lba; last_lba = resize.last_lba;
@ -1013,8 +1021,8 @@ int cxlflash_disk_virtual_open(struct scsi_device *sdev, void *arg)
out: out:
if (likely(ctxi)) if (likely(ctxi))
put_context(ctxi); put_context(ctxi);
pr_debug("%s: returning handle 0x%llx rc=%d llba %lld\n", dev_dbg(dev, "%s: returning handle=%llu rc=%d llba=%llu\n",
__func__, rsrc_handle, rc, last_lba); __func__, rsrc_handle, rc, last_lba);
return rc; return rc;
err2: err2:
@ -1047,6 +1055,8 @@ static int clone_lxt(struct afu *afu,
struct sisl_rht_entry *rhte, struct sisl_rht_entry *rhte,
struct sisl_rht_entry *rhte_src) struct sisl_rht_entry *rhte_src)
{ {
struct cxlflash_cfg *cfg = afu->parent;
struct device *dev = &cfg->dev->dev;
struct sisl_lxt_entry *lxt; struct sisl_lxt_entry *lxt;
u32 ngrps; u32 ngrps;
u64 aun; /* chunk# allocated by block allocator */ u64 aun; /* chunk# allocated by block allocator */
@ -1101,7 +1111,7 @@ static int clone_lxt(struct afu *afu,
cxlflash_afu_sync(afu, ctxid, rhndl, AFU_LW_SYNC); cxlflash_afu_sync(afu, ctxid, rhndl, AFU_LW_SYNC);
pr_debug("%s: returning\n", __func__); dev_dbg(dev, "%s: returning\n", __func__);
return 0; return 0;
} }
@ -1120,7 +1130,8 @@ static int clone_lxt(struct afu *afu,
int cxlflash_disk_clone(struct scsi_device *sdev, int cxlflash_disk_clone(struct scsi_device *sdev,
struct dk_cxlflash_clone *clone) struct dk_cxlflash_clone *clone)
{ {
struct cxlflash_cfg *cfg = (struct cxlflash_cfg *)sdev->host->hostdata; struct cxlflash_cfg *cfg = shost_priv(sdev->host);
struct device *dev = &cfg->dev->dev;
struct llun_info *lli = sdev->hostdata; struct llun_info *lli = sdev->hostdata;
struct glun_info *gli = lli->parent; struct glun_info *gli = lli->parent;
struct blka *blka = &gli->blka; struct blka *blka = &gli->blka;
@ -1140,8 +1151,8 @@ int cxlflash_disk_clone(struct scsi_device *sdev,
bool found; bool found;
LIST_HEAD(sidecar); LIST_HEAD(sidecar);
pr_debug("%s: ctxid_src=%llu ctxid_dst=%llu\n", dev_dbg(dev, "%s: ctxid_src=%llu ctxid_dst=%llu\n",
__func__, ctxid_src, ctxid_dst); __func__, ctxid_src, ctxid_dst);
/* Do not clone yourself */ /* Do not clone yourself */
if (unlikely(rctxid_src == rctxid_dst)) { if (unlikely(rctxid_src == rctxid_dst)) {
@ -1151,16 +1162,16 @@ int cxlflash_disk_clone(struct scsi_device *sdev,
if (unlikely(gli->mode != MODE_VIRTUAL)) { if (unlikely(gli->mode != MODE_VIRTUAL)) {
rc = -EINVAL; rc = -EINVAL;
pr_debug("%s: Clone not supported on physical LUNs! (%d)\n", dev_dbg(dev, "%s: Only supported on virtual LUNs mode=%u\n",
__func__, gli->mode); __func__, gli->mode);
goto out; goto out;
} }
ctxi_src = get_context(cfg, rctxid_src, lli, CTX_CTRL_CLONE); ctxi_src = get_context(cfg, rctxid_src, lli, CTX_CTRL_CLONE);
ctxi_dst = get_context(cfg, rctxid_dst, lli, 0); ctxi_dst = get_context(cfg, rctxid_dst, lli, 0);
if (unlikely(!ctxi_src || !ctxi_dst)) { if (unlikely(!ctxi_src || !ctxi_dst)) {
pr_debug("%s: Bad context! (%llu,%llu)\n", __func__, dev_dbg(dev, "%s: Bad context ctxid_src=%llu ctxid_dst=%llu\n",
ctxid_src, ctxid_dst); __func__, ctxid_src, ctxid_dst);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
@ -1185,8 +1196,8 @@ int cxlflash_disk_clone(struct scsi_device *sdev,
lun_access_dst = kzalloc(sizeof(*lun_access_dst), lun_access_dst = kzalloc(sizeof(*lun_access_dst),
GFP_KERNEL); GFP_KERNEL);
if (unlikely(!lun_access_dst)) { if (unlikely(!lun_access_dst)) {
pr_err("%s: Unable to allocate lun_access!\n", dev_err(dev, "%s: lun_access allocation fail\n",
__func__); __func__);
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto out;
} }
@ -1197,7 +1208,7 @@ int cxlflash_disk_clone(struct scsi_device *sdev,
} }
if (unlikely(!ctxi_src->rht_out)) { if (unlikely(!ctxi_src->rht_out)) {
pr_debug("%s: Nothing to clone!\n", __func__); dev_dbg(dev, "%s: Nothing to clone\n", __func__);
goto out_success; goto out_success;
} }
@ -1256,7 +1267,7 @@ out:
put_context(ctxi_src); put_context(ctxi_src);
if (ctxi_dst) if (ctxi_dst)
put_context(ctxi_dst); put_context(ctxi_dst);
pr_debug("%s: returning rc=%d\n", __func__, rc); dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
return rc; return rc;
err: err:

View File

@ -2768,16 +2768,12 @@ static int adpt_i2o_activate_hba(adpt_hba* pHba)
static int adpt_i2o_online_hba(adpt_hba* pHba) static int adpt_i2o_online_hba(adpt_hba* pHba)
{ {
if (adpt_i2o_systab_send(pHba) < 0) { if (adpt_i2o_systab_send(pHba) < 0)
adpt_i2o_delete_hba(pHba);
return -1; return -1;
}
/* In READY state */ /* In READY state */
if (adpt_i2o_enable_hba(pHba) < 0) { if (adpt_i2o_enable_hba(pHba) < 0)
adpt_i2o_delete_hba(pHba);
return -1; return -1;
}
/* In OPERATIONAL state */ /* In OPERATIONAL state */
return 0; return 0;

View File

@ -237,7 +237,7 @@ static void esas2r_claim_interrupts(struct esas2r_adapter *a)
flags |= IRQF_SHARED; flags |= IRQF_SHARED;
esas2r_log(ESAS2R_LOG_INFO, esas2r_log(ESAS2R_LOG_INFO,
"esas2r_claim_interrupts irq=%d (%p, %s, %x)", "esas2r_claim_interrupts irq=%d (%p, %s, %lx)",
a->pcid->irq, a, a->name, flags); a->pcid->irq, a, a->name, flags);
if (request_irq(a->pcid->irq, if (request_irq(a->pcid->irq,

View File

@ -1301,7 +1301,7 @@ int esas2r_ioctl_handler(void *hostdata, int cmd, void __user *arg)
ioctl = kzalloc(sizeof(struct atto_express_ioctl), GFP_KERNEL); ioctl = kzalloc(sizeof(struct atto_express_ioctl), GFP_KERNEL);
if (ioctl == NULL) { if (ioctl == NULL) {
esas2r_log(ESAS2R_LOG_WARN, esas2r_log(ESAS2R_LOG_WARN,
"ioctl_handler kzalloc failed for %d bytes", "ioctl_handler kzalloc failed for %zu bytes",
sizeof(struct atto_express_ioctl)); sizeof(struct atto_express_ioctl));
return -ENOMEM; return -ENOMEM;
} }

View File

@ -61,8 +61,8 @@ enum {
#endif #endif
}; };
int esas2r_log(const long level, const char *format, ...); __printf(2, 3) int esas2r_log(const long level, const char *format, ...);
int esas2r_log_dev(const long level, __printf(3, 4) int esas2r_log_dev(const long level,
const struct device *dev, const struct device *dev,
const char *format, const char *format,
...); ...);

View File

@ -198,7 +198,7 @@ static ssize_t write_hw(struct file *file, struct kobject *kobj,
GFP_KERNEL); GFP_KERNEL);
if (a->local_atto_ioctl == NULL) { if (a->local_atto_ioctl == NULL) {
esas2r_log(ESAS2R_LOG_WARN, esas2r_log(ESAS2R_LOG_WARN,
"write_hw kzalloc failed for %d bytes", "write_hw kzalloc failed for %zu bytes",
sizeof(struct atto_ioctl)); sizeof(struct atto_ioctl));
return -ENOMEM; return -ENOMEM;
} }
@ -1186,7 +1186,7 @@ retry:
} else { } else {
esas2r_log(ESAS2R_LOG_CRIT, esas2r_log(ESAS2R_LOG_CRIT,
"unable to allocate a request for a " "unable to allocate a request for a "
"device reset (%d:%d)!", "device reset (%d:%llu)!",
cmd->device->id, cmd->device->id,
cmd->device->lun); cmd->device->lun);
} }

View File

@ -277,6 +277,7 @@ static struct scsi_host_template fcoe_shost_template = {
.name = "FCoE Driver", .name = "FCoE Driver",
.proc_name = FCOE_NAME, .proc_name = FCOE_NAME,
.queuecommand = fc_queuecommand, .queuecommand = fc_queuecommand,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = fc_eh_abort, .eh_abort_handler = fc_eh_abort,
.eh_device_reset_handler = fc_eh_device_reset, .eh_device_reset_handler = fc_eh_device_reset,
.eh_host_reset_handler = fc_eh_host_reset, .eh_host_reset_handler = fc_eh_host_reset,

View File

@ -106,6 +106,7 @@ static struct scsi_host_template fnic_host_template = {
.module = THIS_MODULE, .module = THIS_MODULE,
.name = DRV_NAME, .name = DRV_NAME,
.queuecommand = fnic_queuecommand, .queuecommand = fnic_queuecommand,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = fnic_abort_cmd, .eh_abort_handler = fnic_abort_cmd,
.eh_device_reset_handler = fnic_device_reset, .eh_device_reset_handler = fnic_device_reset,
.eh_host_reset_handler = fnic_host_reset, .eh_host_reset_handler = fnic_host_reset,

View File

@ -26,14 +26,55 @@
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/module.h> #include <linux/module.h>
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
#include "g_NCR5380.h"
#include "NCR5380.h"
#include <linux/init.h> #include <linux/init.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/isa.h> #include <linux/isa.h>
#include <linux/pnp.h> #include <linux/pnp.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
/* Definitions for the core NCR5380 driver. */
#define NCR5380_read(reg) \
ioread8(hostdata->io + hostdata->offset + (reg))
#define NCR5380_write(reg, value) \
iowrite8(value, hostdata->io + hostdata->offset + (reg))
#define NCR5380_implementation_fields \
int offset; \
int c400_ctl_status; \
int c400_blk_cnt; \
int c400_host_buf; \
int io_width
#define NCR5380_dma_xfer_len generic_NCR5380_dma_xfer_len
#define NCR5380_dma_recv_setup generic_NCR5380_pread
#define NCR5380_dma_send_setup generic_NCR5380_pwrite
#define NCR5380_dma_residual NCR5380_dma_residual_none
#define NCR5380_intr generic_NCR5380_intr
#define NCR5380_queue_command generic_NCR5380_queue_command
#define NCR5380_abort generic_NCR5380_abort
#define NCR5380_bus_reset generic_NCR5380_bus_reset
#define NCR5380_info generic_NCR5380_info
#define NCR5380_io_delay(x) udelay(x)
#include "NCR5380.h"
#define DRV_MODULE_NAME "g_NCR5380"
#define NCR53C400_mem_base 0x3880
#define NCR53C400_host_buffer 0x3900
#define NCR53C400_region_size 0x3a00
#define BOARD_NCR5380 0
#define BOARD_NCR53C400 1
#define BOARD_NCR53C400A 2
#define BOARD_DTC3181E 3
#define BOARD_HP_C2502 4
#define IRQ_AUTO 254
#define MAX_CARDS 8 #define MAX_CARDS 8
/* old-style parameters for compatibility */ /* old-style parameters for compatibility */

View File

@ -1,56 +0,0 @@
/*
* Generic Generic NCR5380 driver defines
*
* Copyright 1993, Drew Eckhardt
* Visionary Computing
* (Unix and Linux consulting and custom programming)
* drew@colorado.edu
* +1 (303) 440-4894
*
* NCR53C400 extensions (c) 1994,1995,1996, Kevin Lentin
* K.Lentin@cs.monash.edu.au
*/
#ifndef GENERIC_NCR5380_H
#define GENERIC_NCR5380_H
#define DRV_MODULE_NAME "g_NCR5380"
#define NCR5380_read(reg) \
ioread8(hostdata->io + hostdata->offset + (reg))
#define NCR5380_write(reg, value) \
iowrite8(value, hostdata->io + hostdata->offset + (reg))
#define NCR5380_implementation_fields \
int offset; \
int c400_ctl_status; \
int c400_blk_cnt; \
int c400_host_buf; \
int io_width;
#define NCR53C400_mem_base 0x3880
#define NCR53C400_host_buffer 0x3900
#define NCR53C400_region_size 0x3a00
#define NCR5380_dma_xfer_len generic_NCR5380_dma_xfer_len
#define NCR5380_dma_recv_setup generic_NCR5380_pread
#define NCR5380_dma_send_setup generic_NCR5380_pwrite
#define NCR5380_dma_residual NCR5380_dma_residual_none
#define NCR5380_intr generic_NCR5380_intr
#define NCR5380_queue_command generic_NCR5380_queue_command
#define NCR5380_abort generic_NCR5380_abort
#define NCR5380_bus_reset generic_NCR5380_bus_reset
#define NCR5380_info generic_NCR5380_info
#define NCR5380_io_delay(x) udelay(x)
#define BOARD_NCR5380 0
#define BOARD_NCR53C400 1
#define BOARD_NCR53C400A 2
#define BOARD_DTC3181E 3
#define BOARD_HP_C2502 4
#define IRQ_AUTO 254
#endif /* GENERIC_NCR5380_H */

View File

@ -95,6 +95,7 @@ struct hisi_sas_port {
struct hisi_sas_cq { struct hisi_sas_cq {
struct hisi_hba *hisi_hba; struct hisi_hba *hisi_hba;
struct tasklet_struct tasklet;
int rd_point; int rd_point;
int id; int id;
}; };

View File

@ -71,6 +71,8 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
struct hisi_sas_slot *slot) struct hisi_sas_slot *slot)
{ {
struct device *dev = &hisi_hba->pdev->dev; struct device *dev = &hisi_hba->pdev->dev;
struct domain_device *device = task->dev;
struct hisi_sas_device *sas_dev = device->lldd_dev;
if (!slot->task) if (!slot->task)
return; return;
@ -97,6 +99,8 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
slot->task = NULL; slot->task = NULL;
slot->port = NULL; slot->port = NULL;
hisi_sas_slot_index_free(hisi_hba, slot->idx); hisi_sas_slot_index_free(hisi_hba, slot->idx);
if (sas_dev)
atomic64_dec(&sas_dev->running_req);
/* slot memory is fully zeroed when it is reused */ /* slot memory is fully zeroed when it is reused */
} }
EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free); EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free);
@ -141,11 +145,10 @@ static void hisi_sas_slot_abort(struct work_struct *work)
struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev); struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev);
struct scsi_cmnd *cmnd = task->uldd_task; struct scsi_cmnd *cmnd = task->uldd_task;
struct hisi_sas_tmf_task tmf_task; struct hisi_sas_tmf_task tmf_task;
struct domain_device *device = task->dev;
struct hisi_sas_device *sas_dev = device->lldd_dev;
struct scsi_lun lun; struct scsi_lun lun;
struct device *dev = &hisi_hba->pdev->dev; struct device *dev = &hisi_hba->pdev->dev;
int tag = abort_slot->idx; int tag = abort_slot->idx;
unsigned long flags;
if (!(task->task_proto & SAS_PROTOCOL_SSP)) { if (!(task->task_proto & SAS_PROTOCOL_SSP)) {
dev_err(dev, "cannot abort slot for non-ssp task\n"); dev_err(dev, "cannot abort slot for non-ssp task\n");
@ -159,11 +162,11 @@ static void hisi_sas_slot_abort(struct work_struct *work)
hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun, &tmf_task); hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun, &tmf_task);
out: out:
/* Do cleanup for this task */ /* Do cleanup for this task */
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_slot_task_free(hisi_hba, task, abort_slot); hisi_sas_slot_task_free(hisi_hba, task, abort_slot);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
if (task->task_done) if (task->task_done)
task->task_done(task); task->task_done(task);
if (sas_dev)
atomic64_dec(&sas_dev->running_req);
} }
static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba, static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
@ -1118,7 +1121,7 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
} }
exit: exit:
dev_info(dev, "internal task abort: task to dev %016llx task=%p " dev_dbg(dev, "internal task abort: task to dev %016llx task=%p "
"resp: 0x%x sts 0x%x\n", "resp: 0x%x sts 0x%x\n",
SAS_ADDR(device->sas_addr), SAS_ADDR(device->sas_addr),
task, task,
@ -1450,7 +1453,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
refclk = devm_clk_get(&pdev->dev, NULL); refclk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(refclk)) if (IS_ERR(refclk))
dev_info(dev, "no ref clk property\n"); dev_dbg(dev, "no ref clk property\n");
else else
hisi_hba->refclk_frequency_mhz = clk_get_rate(refclk) / 1000000; hisi_hba->refclk_frequency_mhz = clk_get_rate(refclk) / 1000000;
@ -1549,10 +1552,6 @@ int hisi_sas_probe(struct platform_device *pdev,
hisi_sas_init_add(hisi_hba); hisi_sas_init_add(hisi_hba);
rc = hisi_hba->hw->hw_init(hisi_hba);
if (rc)
goto err_out_ha;
rc = scsi_add_host(shost, &pdev->dev); rc = scsi_add_host(shost, &pdev->dev);
if (rc) if (rc)
goto err_out_ha; goto err_out_ha;
@ -1561,6 +1560,10 @@ int hisi_sas_probe(struct platform_device *pdev,
if (rc) if (rc)
goto err_out_register_ha; goto err_out_register_ha;
rc = hisi_hba->hw->hw_init(hisi_hba);
if (rc)
goto err_out_register_ha;
scsi_scan_host(shost); scsi_scan_host(shost);
return 0; return 0;

View File

@ -1596,6 +1596,7 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p)
hisi_hba->complete_hdr[queue]; hisi_hba->complete_hdr[queue];
u32 irq_value, rd_point = cq->rd_point, wr_point; u32 irq_value, rd_point = cq->rd_point, wr_point;
spin_lock(&hisi_hba->lock);
irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC); irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC);
hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue); hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
@ -1628,6 +1629,7 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p)
/* update rd_point */ /* update rd_point */
cq->rd_point = rd_point; cq->rd_point = rd_point;
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point); hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
spin_unlock(&hisi_hba->lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }

View File

@ -207,6 +207,8 @@
#define TXID_AUTO (PORT_BASE + 0xb8) #define TXID_AUTO (PORT_BASE + 0xb8)
#define TXID_AUTO_CT3_OFF 1 #define TXID_AUTO_CT3_OFF 1
#define TXID_AUTO_CT3_MSK (0x1 << TXID_AUTO_CT3_OFF) #define TXID_AUTO_CT3_MSK (0x1 << TXID_AUTO_CT3_OFF)
#define TX_HARDRST_OFF 2
#define TX_HARDRST_MSK (0x1 << TX_HARDRST_OFF)
#define RX_IDAF_DWORD0 (PORT_BASE + 0xc4) #define RX_IDAF_DWORD0 (PORT_BASE + 0xc4)
#define RX_IDAF_DWORD1 (PORT_BASE + 0xc8) #define RX_IDAF_DWORD1 (PORT_BASE + 0xc8)
#define RX_IDAF_DWORD2 (PORT_BASE + 0xcc) #define RX_IDAF_DWORD2 (PORT_BASE + 0xcc)
@ -215,6 +217,7 @@
#define RX_IDAF_DWORD5 (PORT_BASE + 0xd8) #define RX_IDAF_DWORD5 (PORT_BASE + 0xd8)
#define RX_IDAF_DWORD6 (PORT_BASE + 0xdc) #define RX_IDAF_DWORD6 (PORT_BASE + 0xdc)
#define RXOP_CHECK_CFG_H (PORT_BASE + 0xfc) #define RXOP_CHECK_CFG_H (PORT_BASE + 0xfc)
#define CON_CONTROL (PORT_BASE + 0x118)
#define DONE_RECEIVED_TIME (PORT_BASE + 0x11c) #define DONE_RECEIVED_TIME (PORT_BASE + 0x11c)
#define CHL_INT0 (PORT_BASE + 0x1b4) #define CHL_INT0 (PORT_BASE + 0x1b4)
#define CHL_INT0_HOTPLUG_TOUT_OFF 0 #define CHL_INT0_HOTPLUG_TOUT_OFF 0
@ -333,6 +336,11 @@
#define ITCT_HDR_MCR_MSK (0xf << ITCT_HDR_MCR_OFF) #define ITCT_HDR_MCR_MSK (0xf << ITCT_HDR_MCR_OFF)
#define ITCT_HDR_VLN_OFF 9 #define ITCT_HDR_VLN_OFF 9
#define ITCT_HDR_VLN_MSK (0xf << ITCT_HDR_VLN_OFF) #define ITCT_HDR_VLN_MSK (0xf << ITCT_HDR_VLN_OFF)
#define ITCT_HDR_SMP_TIMEOUT_OFF 16
#define ITCT_HDR_SMP_TIMEOUT_8US 1
#define ITCT_HDR_SMP_TIMEOUT (ITCT_HDR_SMP_TIMEOUT_8US * \
250) /* 2ms */
#define ITCT_HDR_AWT_CONTINUE_OFF 25
#define ITCT_HDR_PORT_ID_OFF 28 #define ITCT_HDR_PORT_ID_OFF 28
#define ITCT_HDR_PORT_ID_MSK (0xf << ITCT_HDR_PORT_ID_OFF) #define ITCT_HDR_PORT_ID_MSK (0xf << ITCT_HDR_PORT_ID_OFF)
/* qw2 */ /* qw2 */
@ -526,6 +534,8 @@ enum {
#define SATA_PROTOCOL_FPDMA 0x8 #define SATA_PROTOCOL_FPDMA 0x8
#define SATA_PROTOCOL_ATAPI 0x10 #define SATA_PROTOCOL_ATAPI 0x10
static void hisi_sas_link_timeout_disable_link(unsigned long data);
static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
{ {
void __iomem *regs = hisi_hba->regs + off; void __iomem *regs = hisi_hba->regs + off;
@ -693,6 +703,8 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
qw0 |= ((1 << ITCT_HDR_VALID_OFF) | qw0 |= ((1 << ITCT_HDR_VALID_OFF) |
(device->linkrate << ITCT_HDR_MCR_OFF) | (device->linkrate << ITCT_HDR_MCR_OFF) |
(1 << ITCT_HDR_VLN_OFF) | (1 << ITCT_HDR_VLN_OFF) |
(ITCT_HDR_SMP_TIMEOUT << ITCT_HDR_SMP_TIMEOUT_OFF) |
(1 << ITCT_HDR_AWT_CONTINUE_OFF) |
(port->id << ITCT_HDR_PORT_ID_OFF)); (port->id << ITCT_HDR_PORT_ID_OFF));
itct->qw0 = cpu_to_le64(qw0); itct->qw0 = cpu_to_le64(qw0);
@ -702,7 +714,7 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
/* qw2 */ /* qw2 */
if (!dev_is_sata(device)) if (!dev_is_sata(device))
itct->qw2 = cpu_to_le64((500ULL << ITCT_HDR_INLT_OFF) | itct->qw2 = cpu_to_le64((5000ULL << ITCT_HDR_INLT_OFF) |
(0x1ULL << ITCT_HDR_BITLT_OFF) | (0x1ULL << ITCT_HDR_BITLT_OFF) |
(0x32ULL << ITCT_HDR_MCTLT_OFF) | (0x32ULL << ITCT_HDR_MCTLT_OFF) |
(0x1ULL << ITCT_HDR_RTOLT_OFF)); (0x1ULL << ITCT_HDR_RTOLT_OFF));
@ -711,7 +723,7 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
static void free_device_v2_hw(struct hisi_hba *hisi_hba, static void free_device_v2_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_device *sas_dev) struct hisi_sas_device *sas_dev)
{ {
u64 qw0, dev_id = sas_dev->device_id; u64 dev_id = sas_dev->device_id;
struct device *dev = &hisi_hba->pdev->dev; struct device *dev = &hisi_hba->pdev->dev;
struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id]; struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3); u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
@ -735,8 +747,7 @@ static void free_device_v2_hw(struct hisi_hba *hisi_hba,
dev_dbg(dev, "got clear ITCT done interrupt\n"); dev_dbg(dev, "got clear ITCT done interrupt\n");
/* invalid the itct state*/ /* invalid the itct state*/
qw0 = cpu_to_le64(itct->qw0); memset(itct, 0, sizeof(struct hisi_sas_itct));
qw0 &= ~(1 << ITCT_HDR_VALID_OFF);
hisi_sas_write32(hisi_hba, ENT_INT_SRC3, hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
ENT_INT_SRC3_ITC_INT_MSK); ENT_INT_SRC3_ITC_INT_MSK);
@ -978,6 +989,50 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
upper_32_bits(hisi_hba->initial_fis_dma)); upper_32_bits(hisi_hba->initial_fis_dma));
} }
static void hisi_sas_link_timeout_enable_link(unsigned long data)
{
struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
int i, reg_val;
for (i = 0; i < hisi_hba->n_phy; i++) {
reg_val = hisi_sas_phy_read32(hisi_hba, i, CON_CONTROL);
if (!(reg_val & BIT(0))) {
hisi_sas_phy_write32(hisi_hba, i,
CON_CONTROL, 0x7);
break;
}
}
hisi_hba->timer.function = hisi_sas_link_timeout_disable_link;
mod_timer(&hisi_hba->timer, jiffies + msecs_to_jiffies(900));
}
static void hisi_sas_link_timeout_disable_link(unsigned long data)
{
struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
int i, reg_val;
reg_val = hisi_sas_read32(hisi_hba, PHY_STATE);
for (i = 0; i < hisi_hba->n_phy && reg_val; i++) {
if (reg_val & BIT(i)) {
hisi_sas_phy_write32(hisi_hba, i,
CON_CONTROL, 0x6);
break;
}
}
hisi_hba->timer.function = hisi_sas_link_timeout_enable_link;
mod_timer(&hisi_hba->timer, jiffies + msecs_to_jiffies(100));
}
static void set_link_timer_quirk(struct hisi_hba *hisi_hba)
{
hisi_hba->timer.data = (unsigned long)hisi_hba;
hisi_hba->timer.function = hisi_sas_link_timeout_disable_link;
hisi_hba->timer.expires = jiffies + msecs_to_jiffies(1000);
add_timer(&hisi_hba->timer);
}
static int hw_init_v2_hw(struct hisi_hba *hisi_hba) static int hw_init_v2_hw(struct hisi_hba *hisi_hba)
{ {
struct device *dev = &hisi_hba->pdev->dev; struct device *dev = &hisi_hba->pdev->dev;
@ -1025,14 +1080,21 @@ static void stop_phy_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
static void phy_hard_reset_v2_hw(struct hisi_hba *hisi_hba, int phy_no) static void phy_hard_reset_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
{ {
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
u32 txid_auto;
stop_phy_v2_hw(hisi_hba, phy_no); stop_phy_v2_hw(hisi_hba, phy_no);
if (phy->identify.device_type == SAS_END_DEVICE) {
txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO);
hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO,
txid_auto | TX_HARDRST_MSK);
}
msleep(100); msleep(100);
start_phy_v2_hw(hisi_hba, phy_no); start_phy_v2_hw(hisi_hba, phy_no);
} }
static void start_phys_v2_hw(unsigned long data) static void start_phys_v2_hw(struct hisi_hba *hisi_hba)
{ {
struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
int i; int i;
for (i = 0; i < hisi_hba->n_phy; i++) for (i = 0; i < hisi_hba->n_phy; i++)
@ -1041,10 +1103,7 @@ static void start_phys_v2_hw(unsigned long data)
static void phys_init_v2_hw(struct hisi_hba *hisi_hba) static void phys_init_v2_hw(struct hisi_hba *hisi_hba)
{ {
struct timer_list *timer = &hisi_hba->timer; start_phys_v2_hw(hisi_hba);
setup_timer(timer, start_phys_v2_hw, (unsigned long)hisi_hba);
mod_timer(timer, jiffies + HZ);
} }
static void sl_notify_v2_hw(struct hisi_hba *hisi_hba, int phy_no) static void sl_notify_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
@ -1771,8 +1830,6 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot,
} }
out: out:
if (sas_dev)
atomic64_dec(&sas_dev->running_req);
hisi_sas_slot_task_free(hisi_hba, task, slot); hisi_sas_slot_task_free(hisi_hba, task, slot);
sts = ts->stat; sts = ts->stat;
@ -2020,9 +2077,12 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
if (phy->identify.device_type == SAS_END_DEVICE) if (phy->identify.device_type == SAS_END_DEVICE)
phy->identify.target_port_protocols = phy->identify.target_port_protocols =
SAS_PROTOCOL_SSP; SAS_PROTOCOL_SSP;
else if (phy->identify.device_type != SAS_PHY_UNUSED) else if (phy->identify.device_type != SAS_PHY_UNUSED) {
phy->identify.target_port_protocols = phy->identify.target_port_protocols =
SAS_PROTOCOL_SMP; SAS_PROTOCOL_SMP;
if (!timer_pending(&hisi_hba->timer))
set_link_timer_quirk(hisi_hba);
}
queue_work(hisi_hba->wq, &phy->phyup_ws); queue_work(hisi_hba->wq, &phy->phyup_ws);
end: end:
@ -2033,10 +2093,23 @@ end:
return res; return res;
} }
static bool check_any_wideports_v2_hw(struct hisi_hba *hisi_hba)
{
u32 port_state;
port_state = hisi_sas_read32(hisi_hba, PORT_STATE);
if (port_state & 0x1ff)
return true;
return false;
}
static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba) static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
{ {
int res = 0; int res = 0;
u32 phy_state, sl_ctrl, txid_auto; u32 phy_state, sl_ctrl, txid_auto;
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
struct hisi_sas_port *port = phy->port;
hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1); hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1);
@ -2046,6 +2119,10 @@ static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
sl_ctrl = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL); sl_ctrl = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL);
hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL,
sl_ctrl & ~SL_CONTROL_CTA_MSK); sl_ctrl & ~SL_CONTROL_CTA_MSK);
if (port && !get_wideport_bitmap_v2_hw(hisi_hba, port->id))
if (!check_any_wideports_v2_hw(hisi_hba) &&
timer_pending(&hisi_hba->timer))
del_timer(&hisi_hba->timer);
txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO); txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO);
hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO, hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO,
@ -2481,21 +2558,19 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p) static void cq_tasklet_v2_hw(unsigned long val)
{ {
struct hisi_sas_cq *cq = p; struct hisi_sas_cq *cq = (struct hisi_sas_cq *)val;
struct hisi_hba *hisi_hba = cq->hisi_hba; struct hisi_hba *hisi_hba = cq->hisi_hba;
struct hisi_sas_slot *slot; struct hisi_sas_slot *slot;
struct hisi_sas_itct *itct; struct hisi_sas_itct *itct;
struct hisi_sas_complete_v2_hdr *complete_queue; struct hisi_sas_complete_v2_hdr *complete_queue;
u32 irq_value, rd_point = cq->rd_point, wr_point, dev_id; u32 rd_point = cq->rd_point, wr_point, dev_id;
int queue = cq->id; int queue = cq->id;
complete_queue = hisi_hba->complete_hdr[queue]; complete_queue = hisi_hba->complete_hdr[queue];
irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC);
hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
spin_lock(&hisi_hba->lock);
wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR + wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
(0x14 * queue)); (0x14 * queue));
@ -2545,6 +2620,19 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
/* update rd_point */ /* update rd_point */
cq->rd_point = rd_point; cq->rd_point = rd_point;
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point); hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
spin_unlock(&hisi_hba->lock);
}
static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
{
struct hisi_sas_cq *cq = p;
struct hisi_hba *hisi_hba = cq->hisi_hba;
int queue = cq->id;
hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
tasklet_schedule(&cq->tasklet);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -2726,6 +2814,8 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
for (i = 0; i < hisi_hba->queue_count; i++) { for (i = 0; i < hisi_hba->queue_count; i++) {
int idx = i + 96; /* First cq interrupt is irq96 */ int idx = i + 96; /* First cq interrupt is irq96 */
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
struct tasklet_struct *t = &cq->tasklet;
irq = irq_map[idx]; irq = irq_map[idx];
if (!irq) { if (!irq) {
@ -2742,6 +2832,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
irq, rc); irq, rc);
return -ENOENT; return -ENOENT;
} }
tasklet_init(t, cq_tasklet_v2_hw, (unsigned long)cq);
} }
return 0; return 0;
@ -2807,6 +2898,12 @@ static int hisi_sas_v2_probe(struct platform_device *pdev)
static int hisi_sas_v2_remove(struct platform_device *pdev) static int hisi_sas_v2_remove(struct platform_device *pdev)
{ {
struct sas_ha_struct *sha = platform_get_drvdata(pdev);
struct hisi_hba *hisi_hba = sha->lldd_ha;
if (timer_pending(&hisi_hba->timer))
del_timer(&hisi_hba->timer);
return hisi_sas_remove(pdev); return hisi_sas_remove(pdev);
} }

View File

@ -9263,13 +9263,9 @@ static int hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support)
access = SA5_ioaccel_mode1_access; access = SA5_ioaccel_mode1_access;
writel(10, &h->cfgtable->HostWrite.CoalIntDelay); writel(10, &h->cfgtable->HostWrite.CoalIntDelay);
writel(4, &h->cfgtable->HostWrite.CoalIntCount); writel(4, &h->cfgtable->HostWrite.CoalIntCount);
} else { } else
if (trans_support & CFGTBL_Trans_io_accel2) { if (trans_support & CFGTBL_Trans_io_accel2)
access = SA5_ioaccel_mode2_access; access = SA5_ioaccel_mode2_access;
writel(10, &h->cfgtable->HostWrite.CoalIntDelay);
writel(4, &h->cfgtable->HostWrite.CoalIntCount);
}
}
writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL); writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
if (hpsa_wait_for_mode_change_ack(h)) { if (hpsa_wait_for_mode_change_ack(h)) {
dev_err(&h->pdev->dev, dev_err(&h->pdev->dev,

View File

@ -578,38 +578,38 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q)
} }
static struct access_method SA5_access = { static struct access_method SA5_access = {
SA5_submit_command, .submit_command = SA5_submit_command,
SA5_intr_mask, .set_intr_mask = SA5_intr_mask,
SA5_intr_pending, .intr_pending = SA5_intr_pending,
SA5_completed, .command_completed = SA5_completed,
}; };
static struct access_method SA5_ioaccel_mode1_access = { static struct access_method SA5_ioaccel_mode1_access = {
SA5_submit_command, .submit_command = SA5_submit_command,
SA5_performant_intr_mask, .set_intr_mask = SA5_performant_intr_mask,
SA5_ioaccel_mode1_intr_pending, .intr_pending = SA5_ioaccel_mode1_intr_pending,
SA5_ioaccel_mode1_completed, .command_completed = SA5_ioaccel_mode1_completed,
}; };
static struct access_method SA5_ioaccel_mode2_access = { static struct access_method SA5_ioaccel_mode2_access = {
SA5_submit_command_ioaccel2, .submit_command = SA5_submit_command_ioaccel2,
SA5_performant_intr_mask, .set_intr_mask = SA5_performant_intr_mask,
SA5_performant_intr_pending, .intr_pending = SA5_performant_intr_pending,
SA5_performant_completed, .command_completed = SA5_performant_completed,
}; };
static struct access_method SA5_performant_access = { static struct access_method SA5_performant_access = {
SA5_submit_command, .submit_command = SA5_submit_command,
SA5_performant_intr_mask, .set_intr_mask = SA5_performant_intr_mask,
SA5_performant_intr_pending, .intr_pending = SA5_performant_intr_pending,
SA5_performant_completed, .command_completed = SA5_performant_completed,
}; };
static struct access_method SA5_performant_access_no_read = { static struct access_method SA5_performant_access_no_read = {
SA5_submit_command_no_read, .submit_command = SA5_submit_command_no_read,
SA5_performant_intr_mask, .set_intr_mask = SA5_performant_intr_mask,
SA5_performant_intr_pending, .intr_pending = SA5_performant_intr_pending,
SA5_performant_completed, .command_completed = SA5_performant_completed,
}; };
struct board_type { struct board_type {

View File

@ -3090,6 +3090,7 @@ static struct scsi_host_template driver_template = {
.name = "IBM POWER Virtual FC Adapter", .name = "IBM POWER Virtual FC Adapter",
.proc_name = IBMVFC_NAME, .proc_name = IBMVFC_NAME,
.queuecommand = ibmvfc_queuecommand, .queuecommand = ibmvfc_queuecommand,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = ibmvfc_eh_abort_handler, .eh_abort_handler = ibmvfc_eh_abort_handler,
.eh_device_reset_handler = ibmvfc_eh_device_reset_handler, .eh_device_reset_handler = ibmvfc_eh_device_reset_handler,
.eh_target_reset_handler = ibmvfc_eh_target_reset_handler, .eh_target_reset_handler = ibmvfc_eh_target_reset_handler,

View File

@ -2072,6 +2072,7 @@ static struct scsi_host_template driver_template = {
.name = "IBM POWER Virtual SCSI Adapter " IBMVSCSI_VERSION, .name = "IBM POWER Virtual SCSI Adapter " IBMVSCSI_VERSION,
.proc_name = "ibmvscsi", .proc_name = "ibmvscsi",
.queuecommand = ibmvscsi_queuecommand, .queuecommand = ibmvscsi_queuecommand,
.eh_timed_out = srp_timed_out,
.eh_abort_handler = ibmvscsi_eh_abort_handler, .eh_abort_handler = ibmvscsi_eh_abort_handler,
.eh_device_reset_handler = ibmvscsi_eh_device_reset_handler, .eh_device_reset_handler = ibmvscsi_eh_device_reset_handler,
.eh_host_reset_handler = ibmvscsi_eh_host_reset_handler, .eh_host_reset_handler = ibmvscsi_eh_host_reset_handler,

View File

@ -967,6 +967,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = {
.sg_tablesize = 4096, .sg_tablesize = 4096,
.max_sectors = 0xFFFF, .max_sectors = 0xFFFF,
.cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
.eh_timed_out = iscsi_eh_cmd_timed_out,
.eh_abort_handler = iscsi_eh_abort, .eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler= iscsi_eh_device_reset, .eh_device_reset_handler= iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_recover_target, .eh_target_reset_handler = iscsi_eh_recover_target,

View File

@ -1930,7 +1930,7 @@ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)
return 0; return 0;
} }
static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
{ {
enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED; enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
struct iscsi_task *task = NULL, *running_task; struct iscsi_task *task = NULL, *running_task;
@ -2063,6 +2063,7 @@ done:
"timer reset" : "nh"); "timer reset" : "nh");
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(iscsi_eh_cmd_timed_out);
static void iscsi_check_transport_timeouts(unsigned long data) static void iscsi_check_transport_timeouts(unsigned long data)
{ {
@ -2585,8 +2586,6 @@ int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev)
if (!shost->cmd_per_lun) if (!shost->cmd_per_lun)
shost->cmd_per_lun = ISCSI_DEF_CMD_PER_LUN; shost->cmd_per_lun = ISCSI_DEF_CMD_PER_LUN;
if (!shost->transportt->eh_timed_out)
shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
return scsi_add_host(shost, pdev); return scsi_add_host(shost, pdev);
} }
EXPORT_SYMBOL_GPL(iscsi_host_add); EXPORT_SYMBOL_GPL(iscsi_host_add);

View File

@ -560,7 +560,6 @@ sas_domain_attach_transport(struct sas_domain_function_template *dft)
i = to_sas_internal(stt); i = to_sas_internal(stt);
i->dft = dft; i->dft = dft;
stt->create_work_queue = 1; stt->create_work_queue = 1;
stt->eh_timed_out = sas_scsi_timed_out;
stt->eh_strategy_handler = sas_scsi_recover_host; stt->eh_strategy_handler = sas_scsi_recover_host;
return stt; return stt;

View File

@ -64,8 +64,6 @@ void sas_unregister_phys(struct sas_ha_struct *sas_ha);
int sas_register_ports(struct sas_ha_struct *sas_ha); int sas_register_ports(struct sas_ha_struct *sas_ha);
void sas_unregister_ports(struct sas_ha_struct *sas_ha); void sas_unregister_ports(struct sas_ha_struct *sas_ha);
enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *);
int sas_init_events(struct sas_ha_struct *sas_ha); int sas_init_events(struct sas_ha_struct *sas_ha);
void sas_disable_revalidation(struct sas_ha_struct *ha); void sas_disable_revalidation(struct sas_ha_struct *ha);
void sas_enable_revalidation(struct sas_ha_struct *ha); void sas_enable_revalidation(struct sas_ha_struct *ha);

View File

@ -803,13 +803,6 @@ out:
shost->host_failed, tries); shost->host_failed, tries);
} }
enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
{
scmd_dbg(cmd, "command %p timed out\n", cmd);
return BLK_EH_NOT_HANDLED;
}
int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
{ {
struct domain_device *dev = sdev_to_domain_dev(sdev); struct domain_device *dev = sdev_to_domain_dev(sdev);

View File

@ -727,7 +727,6 @@ struct lpfc_hba {
uint32_t cfg_fcp_io_channel; uint32_t cfg_fcp_io_channel;
uint32_t cfg_total_seg_cnt; uint32_t cfg_total_seg_cnt;
uint32_t cfg_sg_seg_cnt; uint32_t cfg_sg_seg_cnt;
uint32_t cfg_prot_sg_seg_cnt;
uint32_t cfg_sg_dma_buf_size; uint32_t cfg_sg_dma_buf_size;
uint64_t cfg_soft_wwnn; uint64_t cfg_soft_wwnn;
uint64_t cfg_soft_wwpn; uint64_t cfg_soft_wwpn;

View File

@ -2073,6 +2073,13 @@ lpfc_soft_wwn_enable_store(struct device *dev, struct device_attribute *attr,
return -EINVAL; return -EINVAL;
phba->soft_wwn_enable = 1; phba->soft_wwn_enable = 1;
dev_printk(KERN_WARNING, &phba->pcidev->dev,
"lpfc%d: soft_wwpn assignment has been enabled.\n",
phba->brd_no);
dev_printk(KERN_WARNING, &phba->pcidev->dev,
" The soft_wwpn feature is not supported by Broadcom.");
return count; return count;
} }
static DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL, static DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL,
@ -2143,7 +2150,7 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
phba->soft_wwn_enable = 0; phba->soft_wwn_enable = 0;
rc = lpfc_wwn_set(buf, cnt, wwpn); rc = lpfc_wwn_set(buf, cnt, wwpn);
if (!rc) { if (rc) {
/* not able to set wwpn, unlock it */ /* not able to set wwpn, unlock it */
phba->soft_wwn_enable = 1; phba->soft_wwn_enable = 1;
return rc; return rc;
@ -2224,7 +2231,7 @@ lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr,
return -EINVAL; return -EINVAL;
rc = lpfc_wwn_set(buf, cnt, wwnn); rc = lpfc_wwn_set(buf, cnt, wwnn);
if (!rc) { if (rc) {
/* Allow wwnn to be set many times, as long as the enable /* Allow wwnn to be set many times, as long as the enable
* is set. However, once the wwpn is set, everything locks. * is set. However, once the wwpn is set, everything locks.
*/ */
@ -2435,7 +2442,8 @@ lpfc_oas_vpt_store(struct device *dev, struct device_attribute *attr,
else else
phba->cfg_oas_flags &= ~OAS_FIND_ANY_VPORT; phba->cfg_oas_flags &= ~OAS_FIND_ANY_VPORT;
phba->cfg_oas_flags &= ~OAS_LUN_VALID; phba->cfg_oas_flags &= ~OAS_LUN_VALID;
phba->cfg_oas_priority = phba->cfg_XLanePriority; if (phba->cfg_oas_priority == 0)
phba->cfg_oas_priority = phba->cfg_XLanePriority;
phba->sli4_hba.oas_next_lun = FIND_FIRST_OAS_LUN; phba->sli4_hba.oas_next_lun = FIND_FIRST_OAS_LUN;
return count; return count;
} }
@ -2561,7 +2569,7 @@ lpfc_oas_lun_state_set(struct lpfc_hba *phba, uint8_t vpt_wwpn[],
rc = -ENOMEM; rc = -ENOMEM;
} else { } else {
lpfc_disable_oas_lun(phba, (struct lpfc_name *)vpt_wwpn, lpfc_disable_oas_lun(phba, (struct lpfc_name *)vpt_wwpn,
(struct lpfc_name *)tgt_wwpn, lun); (struct lpfc_name *)tgt_wwpn, lun, pri);
} }
return rc; return rc;
@ -2585,7 +2593,8 @@ lpfc_oas_lun_state_set(struct lpfc_hba *phba, uint8_t vpt_wwpn[],
*/ */
static uint64_t static uint64_t
lpfc_oas_lun_get_next(struct lpfc_hba *phba, uint8_t vpt_wwpn[], lpfc_oas_lun_get_next(struct lpfc_hba *phba, uint8_t vpt_wwpn[],
uint8_t tgt_wwpn[], uint32_t *lun_status) uint8_t tgt_wwpn[], uint32_t *lun_status,
uint32_t *lun_pri)
{ {
uint64_t found_lun; uint64_t found_lun;
@ -2598,7 +2607,7 @@ lpfc_oas_lun_get_next(struct lpfc_hba *phba, uint8_t vpt_wwpn[],
&phba->sli4_hba.oas_next_lun, &phba->sli4_hba.oas_next_lun,
(struct lpfc_name *)vpt_wwpn, (struct lpfc_name *)vpt_wwpn,
(struct lpfc_name *)tgt_wwpn, (struct lpfc_name *)tgt_wwpn,
&found_lun, lun_status)) &found_lun, lun_status, lun_pri))
return found_lun; return found_lun;
else else
return NOT_OAS_ENABLED_LUN; return NOT_OAS_ENABLED_LUN;
@ -2670,7 +2679,8 @@ lpfc_oas_lun_show(struct device *dev, struct device_attribute *attr,
oas_lun = lpfc_oas_lun_get_next(phba, phba->cfg_oas_vpt_wwpn, oas_lun = lpfc_oas_lun_get_next(phba, phba->cfg_oas_vpt_wwpn,
phba->cfg_oas_tgt_wwpn, phba->cfg_oas_tgt_wwpn,
&phba->cfg_oas_lun_status); &phba->cfg_oas_lun_status,
&phba->cfg_oas_priority);
if (oas_lun != NOT_OAS_ENABLED_LUN) if (oas_lun != NOT_OAS_ENABLED_LUN)
phba->cfg_oas_flags |= OAS_LUN_VALID; phba->cfg_oas_flags |= OAS_LUN_VALID;
@ -2701,6 +2711,7 @@ lpfc_oas_lun_store(struct device *dev, struct device_attribute *attr,
struct Scsi_Host *shost = class_to_shost(dev); struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
uint64_t scsi_lun; uint64_t scsi_lun;
uint32_t pri;
ssize_t rc; ssize_t rc;
if (!phba->cfg_fof) if (!phba->cfg_fof)
@ -2718,17 +2729,20 @@ lpfc_oas_lun_store(struct device *dev, struct device_attribute *attr,
if (sscanf(buf, "0x%llx", &scsi_lun) != 1) if (sscanf(buf, "0x%llx", &scsi_lun) != 1)
return -EINVAL; return -EINVAL;
pri = phba->cfg_oas_priority;
if (pri == 0)
pri = phba->cfg_XLanePriority;
lpfc_printf_log(phba, KERN_INFO, LOG_INIT, lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"3372 Try to set vport 0x%llx target 0x%llx lun:0x%llx " "3372 Try to set vport 0x%llx target 0x%llx lun:0x%llx "
"priority 0x%x with oas state %d\n", "priority 0x%x with oas state %d\n",
wwn_to_u64(phba->cfg_oas_vpt_wwpn), wwn_to_u64(phba->cfg_oas_vpt_wwpn),
wwn_to_u64(phba->cfg_oas_tgt_wwpn), scsi_lun, wwn_to_u64(phba->cfg_oas_tgt_wwpn), scsi_lun,
phba->cfg_oas_priority, phba->cfg_oas_lun_state); pri, phba->cfg_oas_lun_state);
rc = lpfc_oas_lun_state_change(phba, phba->cfg_oas_vpt_wwpn, rc = lpfc_oas_lun_state_change(phba, phba->cfg_oas_vpt_wwpn,
phba->cfg_oas_tgt_wwpn, scsi_lun, phba->cfg_oas_tgt_wwpn, scsi_lun,
phba->cfg_oas_lun_state, phba->cfg_oas_lun_state, pri);
phba->cfg_oas_priority);
if (rc) if (rc)
return rc; return rc;
@ -4669,14 +4683,6 @@ LPFC_ATTR(delay_discovery, 0, 0, 1,
LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_DEFAULT_SG_SEG_CNT, LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_DEFAULT_SG_SEG_CNT,
LPFC_MAX_SG_SEG_CNT, "Max Scatter Gather Segment Count"); LPFC_MAX_SG_SEG_CNT, "Max Scatter Gather Segment Count");
/*
* This parameter will be depricated, the driver cannot limit the
* protection data s/g list.
*/
LPFC_ATTR_R(prot_sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT,
LPFC_DEFAULT_SG_SEG_CNT, LPFC_MAX_SG_SEG_CNT,
"Max Protection Scatter Gather Segment Count");
/* /*
* lpfc_enable_mds_diags: Enable MDS Diagnostics * lpfc_enable_mds_diags: Enable MDS Diagnostics
* 0 = MDS Diagnostics disabled (default) * 0 = MDS Diagnostics disabled (default)
@ -4766,7 +4772,6 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_lpfc_sg_seg_cnt, &dev_attr_lpfc_sg_seg_cnt,
&dev_attr_lpfc_max_scsicmpl_time, &dev_attr_lpfc_max_scsicmpl_time,
&dev_attr_lpfc_stat_data_ctrl, &dev_attr_lpfc_stat_data_ctrl,
&dev_attr_lpfc_prot_sg_seg_cnt,
&dev_attr_lpfc_aer_support, &dev_attr_lpfc_aer_support,
&dev_attr_lpfc_aer_state_cleanup, &dev_attr_lpfc_aer_state_cleanup,
&dev_attr_lpfc_sriov_nr_virtfn, &dev_attr_lpfc_sriov_nr_virtfn,
@ -5060,6 +5065,19 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport)
* Dynamic FC Host Attributes Support * Dynamic FC Host Attributes Support
*/ */
/**
* lpfc_get_host_symbolic_name - Copy symbolic name into the scsi host
* @shost: kernel scsi host pointer.
**/
static void
lpfc_get_host_symbolic_name(struct Scsi_Host *shost)
{
struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
lpfc_vport_symbolic_node_name(vport, fc_host_symbolic_name(shost),
sizeof fc_host_symbolic_name(shost));
}
/** /**
* lpfc_get_host_port_id - Copy the vport DID into the scsi host port id * lpfc_get_host_port_id - Copy the vport DID into the scsi host port id
* @shost: kernel scsi host pointer. * @shost: kernel scsi host pointer.
@ -5597,6 +5615,8 @@ struct fc_function_template lpfc_transport_functions = {
.show_host_supported_fc4s = 1, .show_host_supported_fc4s = 1,
.show_host_supported_speeds = 1, .show_host_supported_speeds = 1,
.show_host_maxframe_size = 1, .show_host_maxframe_size = 1,
.get_host_symbolic_name = lpfc_get_host_symbolic_name,
.show_host_symbolic_name = 1, .show_host_symbolic_name = 1,
/* dynamic attributes the driver supports */ /* dynamic attributes the driver supports */
@ -5664,6 +5684,8 @@ struct fc_function_template lpfc_vport_transport_functions = {
.show_host_supported_fc4s = 1, .show_host_supported_fc4s = 1,
.show_host_supported_speeds = 1, .show_host_supported_speeds = 1,
.show_host_maxframe_size = 1, .show_host_maxframe_size = 1,
.get_host_symbolic_name = lpfc_get_host_symbolic_name,
.show_host_symbolic_name = 1, .show_host_symbolic_name = 1,
/* dynamic attributes the driver supports */ /* dynamic attributes the driver supports */
@ -5768,7 +5790,6 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
phba->cfg_soft_wwnn = 0L; phba->cfg_soft_wwnn = 0L;
phba->cfg_soft_wwpn = 0L; phba->cfg_soft_wwpn = 0L;
lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt); lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt);
lpfc_prot_sg_seg_cnt_init(phba, lpfc_prot_sg_seg_cnt);
lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth); lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);
lpfc_hba_log_verbose_init(phba, lpfc_log_verbose); lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);
lpfc_aer_support_init(phba, lpfc_aer_support); lpfc_aer_support_init(phba, lpfc_aer_support);

View File

@ -480,7 +480,7 @@ void lpfc_sli4_offline_eratt(struct lpfc_hba *);
struct lpfc_device_data *lpfc_create_device_data(struct lpfc_hba *, struct lpfc_device_data *lpfc_create_device_data(struct lpfc_hba *,
struct lpfc_name *, struct lpfc_name *,
struct lpfc_name *, struct lpfc_name *,
uint64_t, bool); uint64_t, uint32_t, bool);
void lpfc_delete_device_data(struct lpfc_hba *, struct lpfc_device_data*); void lpfc_delete_device_data(struct lpfc_hba *, struct lpfc_device_data*);
struct lpfc_device_data *__lpfc_get_device_data(struct lpfc_hba *, struct lpfc_device_data *__lpfc_get_device_data(struct lpfc_hba *,
struct list_head *list, struct list_head *list,
@ -489,9 +489,10 @@ struct lpfc_device_data *__lpfc_get_device_data(struct lpfc_hba *,
bool lpfc_enable_oas_lun(struct lpfc_hba *, struct lpfc_name *, bool lpfc_enable_oas_lun(struct lpfc_hba *, struct lpfc_name *,
struct lpfc_name *, uint64_t, uint8_t); struct lpfc_name *, uint64_t, uint8_t);
bool lpfc_disable_oas_lun(struct lpfc_hba *, struct lpfc_name *, bool lpfc_disable_oas_lun(struct lpfc_hba *, struct lpfc_name *,
struct lpfc_name *, uint64_t); struct lpfc_name *, uint64_t, uint8_t);
bool lpfc_find_next_oas_lun(struct lpfc_hba *, struct lpfc_name *, bool lpfc_find_next_oas_lun(struct lpfc_hba *, struct lpfc_name *,
struct lpfc_name *, uint64_t *, struct lpfc_name *, struct lpfc_name *, uint64_t *, struct lpfc_name *,
struct lpfc_name *, uint64_t *, uint32_t *); struct lpfc_name *, uint64_t *,
uint32_t *, uint32_t *);
int lpfc_sli4_dump_page_a0(struct lpfc_hba *phba, struct lpfcMboxq *mbox); int lpfc_sli4_dump_page_a0(struct lpfc_hba *phba, struct lpfcMboxq *mbox);
void lpfc_mbx_cmpl_rdp_page_a0(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb); void lpfc_mbx_cmpl_rdp_page_a0(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb);

View File

@ -1999,6 +1999,9 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
if (sp->cmn.fcphHigh < FC_PH3) if (sp->cmn.fcphHigh < FC_PH3)
sp->cmn.fcphHigh = FC_PH3; sp->cmn.fcphHigh = FC_PH3;
sp->cmn.valid_vendor_ver_level = 0;
memset(sp->vendorVersion, 0, sizeof(sp->vendorVersion));
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
"Issue PLOGI: did:x%x", "Issue PLOGI: did:x%x",
did, 0, 0); did, 0, 0);
@ -3990,6 +3993,9 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
} else { } else {
memcpy(pcmd, &vport->fc_sparam, memcpy(pcmd, &vport->fc_sparam,
sizeof(struct serv_parm)); sizeof(struct serv_parm));
sp->cmn.valid_vendor_ver_level = 0;
memset(sp->vendorVersion, 0, sizeof(sp->vendorVersion));
} }
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
@ -8851,8 +8857,7 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
{ {
struct ls_rjt stat; struct ls_rjt stat;
if ((cmdiocb->iocb_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC) BUG_ON((cmdiocb->iocb_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC);
BUG();
switch (rspiocb->iocb.ulpStatus) { switch (rspiocb->iocb.ulpStatus) {
case IOSTAT_NPORT_RJT: case IOSTAT_NPORT_RJT:

View File

@ -360,6 +360,12 @@ struct csp {
* Word 1 Bit 30 in PLOGI request is random offset * Word 1 Bit 30 in PLOGI request is random offset
*/ */
#define virtual_fabric_support randomOffset /* Word 1, bit 30 */ #define virtual_fabric_support randomOffset /* Word 1, bit 30 */
/*
* Word 1 Bit 29 in common service parameter is overloaded.
* Word 1 Bit 29 in FLOGI response is multiple NPort assignment
* Word 1 Bit 29 in FLOGI/PLOGI request is Valid Vendor Version Level
*/
#define valid_vendor_ver_level response_multiple_NPort /* Word 1, bit 29 */
#ifdef __BIG_ENDIAN_BITFIELD #ifdef __BIG_ENDIAN_BITFIELD
uint16_t request_multiple_Nport:1; /* FC Word 1, bit 31 */ uint16_t request_multiple_Nport:1; /* FC Word 1, bit 31 */
uint16_t randomOffset:1; /* FC Word 1, bit 30 */ uint16_t randomOffset:1; /* FC Word 1, bit 30 */

View File

@ -5452,7 +5452,9 @@ lpfc_slave_alloc(struct scsi_device *sdev)
device_data = lpfc_create_device_data(phba, device_data = lpfc_create_device_data(phba,
&vport->fc_portname, &vport->fc_portname,
&target_wwpn, &target_wwpn,
sdev->lun, true); sdev->lun,
phba->cfg_XLanePriority,
true);
if (!device_data) if (!device_data)
return -ENOMEM; return -ENOMEM;
spin_lock_irqsave(&phba->devicelock, flags); spin_lock_irqsave(&phba->devicelock, flags);
@ -5587,7 +5589,7 @@ lpfc_slave_destroy(struct scsi_device *sdev)
struct lpfc_device_data* struct lpfc_device_data*
lpfc_create_device_data(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, lpfc_create_device_data(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
struct lpfc_name *target_wwpn, uint64_t lun, struct lpfc_name *target_wwpn, uint64_t lun,
bool atomic_create) uint32_t pri, bool atomic_create)
{ {
struct lpfc_device_data *lun_info; struct lpfc_device_data *lun_info;
@ -5614,7 +5616,7 @@ lpfc_create_device_data(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
sizeof(struct lpfc_name)); sizeof(struct lpfc_name));
lun_info->device_id.lun = lun; lun_info->device_id.lun = lun;
lun_info->oas_enabled = false; lun_info->oas_enabled = false;
lun_info->priority = phba->cfg_XLanePriority; lun_info->priority = pri;
lun_info->available = false; lun_info->available = false;
return lun_info; return lun_info;
} }
@ -5716,7 +5718,8 @@ lpfc_find_next_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
struct lpfc_name *found_vport_wwpn, struct lpfc_name *found_vport_wwpn,
struct lpfc_name *found_target_wwpn, struct lpfc_name *found_target_wwpn,
uint64_t *found_lun, uint64_t *found_lun,
uint32_t *found_lun_status) uint32_t *found_lun_status,
uint32_t *found_lun_pri)
{ {
unsigned long flags; unsigned long flags;
@ -5763,6 +5766,7 @@ lpfc_find_next_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
OAS_LUN_STATUS_EXISTS; OAS_LUN_STATUS_EXISTS;
else else
*found_lun_status = 0; *found_lun_status = 0;
*found_lun_pri = lun_info->priority;
if (phba->cfg_oas_flags & OAS_FIND_ANY_VPORT) if (phba->cfg_oas_flags & OAS_FIND_ANY_VPORT)
memset(vport_wwpn, 0x0, memset(vport_wwpn, 0x0,
sizeof(struct lpfc_name)); sizeof(struct lpfc_name));
@ -5824,13 +5828,14 @@ lpfc_enable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
if (lun_info) { if (lun_info) {
if (!lun_info->oas_enabled) if (!lun_info->oas_enabled)
lun_info->oas_enabled = true; lun_info->oas_enabled = true;
lun_info->priority = pri;
spin_unlock_irqrestore(&phba->devicelock, flags); spin_unlock_irqrestore(&phba->devicelock, flags);
return true; return true;
} }
/* Create an lun info structure and add to list of luns */ /* Create an lun info structure and add to list of luns */
lun_info = lpfc_create_device_data(phba, vport_wwpn, target_wwpn, lun, lun_info = lpfc_create_device_data(phba, vport_wwpn, target_wwpn, lun,
false); pri, false);
if (lun_info) { if (lun_info) {
lun_info->oas_enabled = true; lun_info->oas_enabled = true;
lun_info->priority = pri; lun_info->priority = pri;
@ -5864,7 +5869,7 @@ lpfc_enable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
**/ **/
bool bool
lpfc_disable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, lpfc_disable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
struct lpfc_name *target_wwpn, uint64_t lun) struct lpfc_name *target_wwpn, uint64_t lun, uint8_t pri)
{ {
struct lpfc_device_data *lun_info; struct lpfc_device_data *lun_info;
@ -5882,6 +5887,7 @@ lpfc_disable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
target_wwpn, lun); target_wwpn, lun);
if (lun_info) { if (lun_info) {
lun_info->oas_enabled = false; lun_info->oas_enabled = false;
lun_info->priority = pri;
if (!lun_info->available) if (!lun_info->available)
lpfc_delete_device_data(phba, lun_info); lpfc_delete_device_data(phba, lun_info);
spin_unlock_irqrestore(&phba->devicelock, flags); spin_unlock_irqrestore(&phba->devicelock, flags);
@ -5923,6 +5929,7 @@ struct scsi_host_template lpfc_template = {
.proc_name = LPFC_DRIVER_NAME, .proc_name = LPFC_DRIVER_NAME,
.info = lpfc_info, .info = lpfc_info,
.queuecommand = lpfc_queuecommand, .queuecommand = lpfc_queuecommand,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = lpfc_abort_handler, .eh_abort_handler = lpfc_abort_handler,
.eh_device_reset_handler = lpfc_device_reset_handler, .eh_device_reset_handler = lpfc_device_reset_handler,
.eh_target_reset_handler = lpfc_target_reset_handler, .eh_target_reset_handler = lpfc_target_reset_handler,
@ -5949,6 +5956,7 @@ struct scsi_host_template lpfc_vport_template = {
.proc_name = LPFC_DRIVER_NAME, .proc_name = LPFC_DRIVER_NAME,
.info = lpfc_info, .info = lpfc_info,
.queuecommand = lpfc_queuecommand, .queuecommand = lpfc_queuecommand,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = lpfc_abort_handler, .eh_abort_handler = lpfc_abort_handler,
.eh_device_reset_handler = lpfc_device_reset_handler, .eh_device_reset_handler = lpfc_device_reset_handler,
.eh_target_reset_handler = lpfc_target_reset_handler, .eh_target_reset_handler = lpfc_target_reset_handler,

View File

@ -120,6 +120,8 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe)
if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED) if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED)
bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id); bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id);
lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size);
/* ensure WQE bcopy flushed before doorbell write */
wmb();
/* Update the host index before invoking device */ /* Update the host index before invoking device */
host_index = q->host_index; host_index = q->host_index;
@ -6313,7 +6315,8 @@ lpfc_set_host_data(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox)
LPFC_SLI4_MBX_EMBED); LPFC_SLI4_MBX_EMBED);
mbox->u.mqe.un.set_host_data.param_id = LPFC_SET_HOST_OS_DRIVER_VERSION; mbox->u.mqe.un.set_host_data.param_id = LPFC_SET_HOST_OS_DRIVER_VERSION;
mbox->u.mqe.un.set_host_data.param_len = 8; mbox->u.mqe.un.set_host_data.param_len =
LPFC_HOST_OS_DRIVER_VERSION_SIZE;
snprintf(mbox->u.mqe.un.set_host_data.data, snprintf(mbox->u.mqe.un.set_host_data.data,
LPFC_HOST_OS_DRIVER_VERSION_SIZE, LPFC_HOST_OS_DRIVER_VERSION_SIZE,
"Linux %s v"LPFC_DRIVER_VERSION, "Linux %s v"LPFC_DRIVER_VERSION,
@ -10035,6 +10038,7 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
iabt->ulpCommand = CMD_CLOSE_XRI_CN; iabt->ulpCommand = CMD_CLOSE_XRI_CN;
abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl; abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl;
abtsiocbp->vport = vport;
lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
"0339 Abort xri x%x, original iotag x%x, " "0339 Abort xri x%x, original iotag x%x, "
@ -17226,7 +17230,8 @@ lpfc_drain_txq(struct lpfc_hba *phba)
unsigned long iflags = 0; unsigned long iflags = 0;
char *fail_msg = NULL; char *fail_msg = NULL;
struct lpfc_sglq *sglq; struct lpfc_sglq *sglq;
union lpfc_wqe wqe; union lpfc_wqe128 wqe128;
union lpfc_wqe *wqe = (union lpfc_wqe *) &wqe128;
uint32_t txq_cnt = 0; uint32_t txq_cnt = 0;
spin_lock_irqsave(&pring->ring_lock, iflags); spin_lock_irqsave(&pring->ring_lock, iflags);
@ -17265,9 +17270,9 @@ lpfc_drain_txq(struct lpfc_hba *phba)
piocbq->sli4_xritag = sglq->sli4_xritag; piocbq->sli4_xritag = sglq->sli4_xritag;
if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocbq, sglq)) if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocbq, sglq))
fail_msg = "to convert bpl to sgl"; fail_msg = "to convert bpl to sgl";
else if (lpfc_sli4_iocb2wqe(phba, piocbq, &wqe)) else if (lpfc_sli4_iocb2wqe(phba, piocbq, wqe))
fail_msg = "to convert iocb to wqe"; fail_msg = "to convert iocb to wqe";
else if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe)) else if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, wqe))
fail_msg = " - Wq is full"; fail_msg = " - Wq is full";
else else
lpfc_sli_ringtxcmpl_put(phba, pring, piocbq); lpfc_sli_ringtxcmpl_put(phba, pring, piocbq);

View File

@ -18,7 +18,7 @@
* included with this package. * * included with this package. *
*******************************************************************/ *******************************************************************/
#define LPFC_DRIVER_VERSION "11.2.0.2" #define LPFC_DRIVER_VERSION "11.2.0.4"
#define LPFC_DRIVER_NAME "lpfc" #define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */ /* Used for SLI 2/3 */

View File

@ -537,6 +537,12 @@ enable_vport(struct fc_vport *fc_vport)
spin_lock_irq(shost->host_lock); spin_lock_irq(shost->host_lock);
vport->load_flag |= FC_LOADING; vport->load_flag |= FC_LOADING;
if (vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI) {
spin_unlock_irq(shost->host_lock);
lpfc_issue_init_vpi(vport);
goto out;
}
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
@ -557,6 +563,8 @@ enable_vport(struct fc_vport *fc_vport)
} else { } else {
lpfc_vport_set_state(vport, FC_VPORT_FAILED); lpfc_vport_set_state(vport, FC_VPORT_FAILED);
} }
out:
lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
"1827 Vport Enabled.\n"); "1827 Vport Enabled.\n");
return VPORT_OK; return VPORT_OK;

View File

@ -154,7 +154,7 @@ __asm__ __volatile__ \
static inline int macscsi_pread(struct NCR5380_hostdata *hostdata, static inline int macscsi_pread(struct NCR5380_hostdata *hostdata,
unsigned char *dst, int len) unsigned char *dst, int len)
{ {
unsigned char *s = hostdata->pdma_io + (INPUT_DATA_REG << 4); u8 __iomem *s = hostdata->pdma_io + (INPUT_DATA_REG << 4);
unsigned char *d = dst; unsigned char *d = dst;
int n = len; int n = len;
int transferred; int transferred;
@ -257,7 +257,7 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata,
unsigned char *src, int len) unsigned char *src, int len)
{ {
unsigned char *s = src; unsigned char *s = src;
unsigned char *d = hostdata->pdma_io + (OUTPUT_DATA_REG << 4); u8 __iomem *d = hostdata->pdma_io + (OUTPUT_DATA_REG << 4);
int n = len; int n = len;
int transferred; int transferred;
@ -381,10 +381,10 @@ static int __init mac_scsi_probe(struct platform_device *pdev)
hostdata = shost_priv(instance); hostdata = shost_priv(instance);
hostdata->base = pio_mem->start; hostdata->base = pio_mem->start;
hostdata->io = (void *)pio_mem->start; hostdata->io = (u8 __iomem *)pio_mem->start;
if (pdma_mem && setup_use_pdma) if (pdma_mem && setup_use_pdma)
hostdata->pdma_io = (void *)pdma_mem->start; hostdata->pdma_io = (u8 __iomem *)pdma_mem->start;
else else
host_flags |= FLAG_NO_PSEUDO_DMA; host_flags |= FLAG_NO_PSEUDO_DMA;

View File

@ -35,8 +35,8 @@
/* /*
* MegaRAID SAS Driver meta data * MegaRAID SAS Driver meta data
*/ */
#define MEGASAS_VERSION "06.812.07.00-rc1" #define MEGASAS_VERSION "07.701.16.00-rc1"
#define MEGASAS_RELDATE "August 22, 2016" #define MEGASAS_RELDATE "February 2, 2017"
/* /*
* Device IDs * Device IDs
@ -56,6 +56,11 @@
#define PCI_DEVICE_ID_LSI_INTRUDER_24 0x00cf #define PCI_DEVICE_ID_LSI_INTRUDER_24 0x00cf
#define PCI_DEVICE_ID_LSI_CUTLASS_52 0x0052 #define PCI_DEVICE_ID_LSI_CUTLASS_52 0x0052
#define PCI_DEVICE_ID_LSI_CUTLASS_53 0x0053 #define PCI_DEVICE_ID_LSI_CUTLASS_53 0x0053
#define PCI_DEVICE_ID_LSI_VENTURA 0x0014
#define PCI_DEVICE_ID_LSI_HARPOON 0x0016
#define PCI_DEVICE_ID_LSI_TOMCAT 0x0017
#define PCI_DEVICE_ID_LSI_VENTURA_4PORT 0x001B
#define PCI_DEVICE_ID_LSI_CRUSADER_4PORT 0x001C
/* /*
* Intel HBA SSDIDs * Intel HBA SSDIDs
@ -100,7 +105,7 @@
*/ */
/* /*
* MFI stands for MegaRAID SAS FW Interface. This is just a moniker for * MFI stands for MegaRAID SAS FW Interface. This is just a moniker for
* protocol between the software and firmware. Commands are issued using * protocol between the software and firmware. Commands are issued using
* "message frames" * "message frames"
*/ */
@ -690,6 +695,18 @@ struct MR_PD_INFO {
u8 reserved1[512-428]; u8 reserved1[512-428];
} __packed; } __packed;
/*
* Definition of structure used to expose attributes of VD or JBOD
* (this structure is to be filled by firmware when MR_DCMD_DRV_GET_TARGET_PROP
* is fired by driver)
*/
struct MR_TARGET_PROPERTIES {
u32 max_io_size_kb;
u32 device_qdepth;
u32 sector_size;
u8 reserved[500];
} __packed;
/* /*
* defines the physical drive address structure * defines the physical drive address structure
*/ */
@ -728,7 +745,6 @@ struct megasas_pd_list {
u16 tid; u16 tid;
u8 driveType; u8 driveType;
u8 driveState; u8 driveState;
u8 interface;
} __packed; } __packed;
/* /*
@ -1312,7 +1328,55 @@ struct megasas_ctrl_info {
#endif #endif
} adapterOperations3; } adapterOperations3;
u8 pad[0x800-0x7EC]; struct {
#if defined(__BIG_ENDIAN_BITFIELD)
u8 reserved:7;
/* Indicates whether the CPLD image is part of
* the package and stored in flash
*/
u8 cpld_in_flash:1;
#else
u8 cpld_in_flash:1;
u8 reserved:7;
#endif
u8 reserved1[3];
/* Null terminated string. Has the version
* information if cpld_in_flash = FALSE
*/
u8 userCodeDefinition[12];
} cpld; /* Valid only if upgradableCPLD is TRUE */
struct {
#if defined(__BIG_ENDIAN_BITFIELD)
u16 reserved:8;
u16 fw_swaps_bbu_vpd_info:1;
u16 support_pd_map_target_id:1;
u16 support_ses_ctrl_in_multipathcfg:1;
u16 image_upload_supported:1;
u16 support_encrypted_mfc:1;
u16 supported_enc_algo:1;
u16 support_ibutton_less:1;
u16 ctrl_info_ext_supported:1;
#else
u16 ctrl_info_ext_supported:1;
u16 support_ibutton_less:1;
u16 supported_enc_algo:1;
u16 support_encrypted_mfc:1;
u16 image_upload_supported:1;
/* FW supports LUN based association and target port based */
u16 support_ses_ctrl_in_multipathcfg:1;
/* association for the SES device connected in multipath mode */
/* FW defines Jbod target Id within MR_PD_CFG_SEQ */
u16 support_pd_map_target_id:1;
/* FW swaps relevant fields in MR_BBU_VPD_INFO_FIXED to
* provide the data in little endian order
*/
u16 fw_swaps_bbu_vpd_info:1;
u16 reserved:8;
#endif
} adapter_operations4;
u8 pad[0x800 - 0x7FE]; /* 0x7FE pad to 2K for expansion */
} __packed; } __packed;
/* /*
@ -1339,12 +1403,15 @@ struct megasas_ctrl_info {
#define MEGASAS_FW_BUSY 1 #define MEGASAS_FW_BUSY 1
#define VD_EXT_DEBUG 0 /* Driver's internal Logging levels*/
#define OCR_LOGS (1 << 0)
#define SCAN_PD_CHANNEL 0x1 #define SCAN_PD_CHANNEL 0x1
#define SCAN_VD_CHANNEL 0x2 #define SCAN_VD_CHANNEL 0x2
#define MEGASAS_KDUMP_QUEUE_DEPTH 100 #define MEGASAS_KDUMP_QUEUE_DEPTH 100
#define MR_LARGE_IO_MIN_SIZE (32 * 1024)
#define MR_R1_LDIO_PIGGYBACK_DEFAULT 4
enum MR_SCSI_CMD_TYPE { enum MR_SCSI_CMD_TYPE {
READ_WRITE_LDIO = 0, READ_WRITE_LDIO = 0,
@ -1391,7 +1458,7 @@ enum FW_BOOT_CONTEXT {
*/ */
#define MEGASAS_INT_CMDS 32 #define MEGASAS_INT_CMDS 32
#define MEGASAS_SKINNY_INT_CMDS 5 #define MEGASAS_SKINNY_INT_CMDS 5
#define MEGASAS_FUSION_INTERNAL_CMDS 5 #define MEGASAS_FUSION_INTERNAL_CMDS 8
#define MEGASAS_FUSION_IOCTL_CMDS 3 #define MEGASAS_FUSION_IOCTL_CMDS 3
#define MEGASAS_MFI_IOCTL_CMDS 27 #define MEGASAS_MFI_IOCTL_CMDS 27
@ -1429,13 +1496,19 @@ enum FW_BOOT_CONTEXT {
#define MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT 14 #define MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT 14
#define MR_MAX_MSIX_REG_ARRAY 16 #define MR_MAX_MSIX_REG_ARRAY 16
#define MR_RDPQ_MODE_OFFSET 0X00800000 #define MR_RDPQ_MODE_OFFSET 0X00800000
#define MR_MAX_RAID_MAP_SIZE_OFFSET_SHIFT 16
#define MR_MAX_RAID_MAP_SIZE_MASK 0x1FF
#define MR_MIN_MAP_SIZE 0x10000
/* 64k */
#define MR_CAN_HANDLE_SYNC_CACHE_OFFSET 0X01000000 #define MR_CAN_HANDLE_SYNC_CACHE_OFFSET 0X01000000
/* /*
* register set for both 1068 and 1078 controllers * register set for both 1068 and 1078 controllers
* structure extended for 1078 registers * structure extended for 1078 registers
*/ */
struct megasas_register_set { struct megasas_register_set {
u32 doorbell; /*0000h*/ u32 doorbell; /*0000h*/
u32 fusion_seq_offset; /*0004h*/ u32 fusion_seq_offset; /*0004h*/
@ -1471,14 +1544,14 @@ struct megasas_register_set {
u32 outbound_scratch_pad ; /*00B0h*/ u32 outbound_scratch_pad ; /*00B0h*/
u32 outbound_scratch_pad_2; /*00B4h*/ u32 outbound_scratch_pad_2; /*00B4h*/
u32 outbound_scratch_pad_3; /*00B8h*/ u32 outbound_scratch_pad_3; /*00B8h*/
u32 outbound_scratch_pad_4; /*00BCh*/
u32 reserved_4; /*00BCh*/
u32 inbound_low_queue_port ; /*00C0h*/ u32 inbound_low_queue_port ; /*00C0h*/
u32 inbound_high_queue_port ; /*00C4h*/ u32 inbound_high_queue_port ; /*00C4h*/
u32 reserved_5; /*00C8h*/ u32 inbound_single_queue_port; /*00C8h*/
u32 res_6[11]; /*CCh*/ u32 res_6[11]; /*CCh*/
u32 host_diag; u32 host_diag;
u32 seq_offset; u32 seq_offset;
@ -1544,33 +1617,35 @@ union megasas_sgl_frame {
typedef union _MFI_CAPABILITIES { typedef union _MFI_CAPABILITIES {
struct { struct {
#if defined(__BIG_ENDIAN_BITFIELD) #if defined(__BIG_ENDIAN_BITFIELD)
u32 reserved:20; u32 reserved:19;
u32 support_qd_throttling:1; u32 support_pd_map_target_id:1;
u32 support_fp_rlbypass:1; u32 support_qd_throttling:1;
u32 support_vfid_in_ioframe:1; u32 support_fp_rlbypass:1;
u32 support_ext_io_size:1; u32 support_vfid_in_ioframe:1;
u32 support_ext_queue_depth:1; u32 support_ext_io_size:1;
u32 security_protocol_cmds_fw:1; u32 support_ext_queue_depth:1;
u32 support_core_affinity:1; u32 security_protocol_cmds_fw:1;
u32 support_ndrive_r1_lb:1; u32 support_core_affinity:1;
u32 support_max_255lds:1; u32 support_ndrive_r1_lb:1;
u32 support_fastpath_wb:1; u32 support_max_255lds:1;
u32 support_additional_msix:1; u32 support_fastpath_wb:1;
u32 support_fp_remote_lun:1; u32 support_additional_msix:1;
u32 support_fp_remote_lun:1;
#else #else
u32 support_fp_remote_lun:1; u32 support_fp_remote_lun:1;
u32 support_additional_msix:1; u32 support_additional_msix:1;
u32 support_fastpath_wb:1; u32 support_fastpath_wb:1;
u32 support_max_255lds:1; u32 support_max_255lds:1;
u32 support_ndrive_r1_lb:1; u32 support_ndrive_r1_lb:1;
u32 support_core_affinity:1; u32 support_core_affinity:1;
u32 security_protocol_cmds_fw:1; u32 security_protocol_cmds_fw:1;
u32 support_ext_queue_depth:1; u32 support_ext_queue_depth:1;
u32 support_ext_io_size:1; u32 support_ext_io_size:1;
u32 support_vfid_in_ioframe:1; u32 support_vfid_in_ioframe:1;
u32 support_fp_rlbypass:1; u32 support_fp_rlbypass:1;
u32 support_qd_throttling:1; u32 support_qd_throttling:1;
u32 reserved:20; u32 support_pd_map_target_id:1;
u32 reserved:19;
#endif #endif
} mfi_capabilities; } mfi_capabilities;
__le32 reg; __le32 reg;
@ -1803,6 +1878,8 @@ union megasas_frame {
struct MR_PRIV_DEVICE { struct MR_PRIV_DEVICE {
bool is_tm_capable; bool is_tm_capable;
bool tm_busy; bool tm_busy;
atomic_t r1_ldio_hint;
u8 interface_type;
}; };
struct megasas_cmd; struct megasas_cmd;
@ -1994,17 +2071,24 @@ struct MR_DRV_SYSTEM_INFO {
}; };
enum MR_PD_TYPE { enum MR_PD_TYPE {
UNKNOWN_DRIVE = 0, UNKNOWN_DRIVE = 0,
PARALLEL_SCSI = 1, PARALLEL_SCSI = 1,
SAS_PD = 2, SAS_PD = 2,
SATA_PD = 3, SATA_PD = 3,
FC_PD = 4, FC_PD = 4,
NVME_PD = 5,
}; };
/* JBOD Queue depth definitions */ /* JBOD Queue depth definitions */
#define MEGASAS_SATA_QD 32 #define MEGASAS_SATA_QD 32
#define MEGASAS_SAS_QD 64 #define MEGASAS_SAS_QD 64
#define MEGASAS_DEFAULT_PD_QD 64 #define MEGASAS_DEFAULT_PD_QD 64
#define MEGASAS_NVME_QD 32
#define MR_DEFAULT_NVME_PAGE_SIZE 4096
#define MR_DEFAULT_NVME_PAGE_SHIFT 12
#define MR_DEFAULT_NVME_MDTS_KB 128
#define MR_NVME_PAGE_SIZE_MASK 0x000000FF
struct megasas_instance { struct megasas_instance {
@ -2022,6 +2106,8 @@ struct megasas_instance {
dma_addr_t hb_host_mem_h; dma_addr_t hb_host_mem_h;
struct MR_PD_INFO *pd_info; struct MR_PD_INFO *pd_info;
dma_addr_t pd_info_h; dma_addr_t pd_info_h;
struct MR_TARGET_PROPERTIES *tgt_prop;
dma_addr_t tgt_prop_h;
__le32 *reply_queue; __le32 *reply_queue;
dma_addr_t reply_queue_h; dma_addr_t reply_queue_h;
@ -2039,6 +2125,7 @@ struct megasas_instance {
u32 crash_dump_drv_support; u32 crash_dump_drv_support;
u32 crash_dump_app_support; u32 crash_dump_app_support;
u32 secure_jbod_support; u32 secure_jbod_support;
u32 support_morethan256jbod; /* FW support for more than 256 PD/JBOD */
bool use_seqnum_jbod_fp; /* Added for PD sequence */ bool use_seqnum_jbod_fp; /* Added for PD sequence */
spinlock_t crashdump_lock; spinlock_t crashdump_lock;
@ -2051,6 +2138,7 @@ struct megasas_instance {
u16 max_num_sge; u16 max_num_sge;
u16 max_fw_cmds; u16 max_fw_cmds;
u16 max_mpt_cmds;
u16 max_mfi_cmds; u16 max_mfi_cmds;
u16 max_scsi_cmds; u16 max_scsi_cmds;
u16 ldio_threshold; u16 ldio_threshold;
@ -2065,6 +2153,7 @@ struct megasas_instance {
/* used to sync fire the cmd to fw */ /* used to sync fire the cmd to fw */
spinlock_t hba_lock; spinlock_t hba_lock;
/* used to synch producer, consumer ptrs in dpc */ /* used to synch producer, consumer ptrs in dpc */
spinlock_t stream_lock;
spinlock_t completion_lock; spinlock_t completion_lock;
struct dma_pool *frame_dma_pool; struct dma_pool *frame_dma_pool;
struct dma_pool *sense_dma_pool; struct dma_pool *sense_dma_pool;
@ -2087,6 +2176,11 @@ struct megasas_instance {
atomic_t fw_outstanding; atomic_t fw_outstanding;
atomic_t ldio_outstanding; atomic_t ldio_outstanding;
atomic_t fw_reset_no_pci_access; atomic_t fw_reset_no_pci_access;
atomic_t ieee_sgl;
atomic_t prp_sgl;
atomic_t sge_holes_type1;
atomic_t sge_holes_type2;
atomic_t sge_holes_type3;
struct megasas_instance_template *instancet; struct megasas_instance_template *instancet;
struct tasklet_struct isr_tasklet; struct tasklet_struct isr_tasklet;
@ -2142,6 +2236,13 @@ struct megasas_instance {
u8 is_rdpq; u8 is_rdpq;
bool dev_handle; bool dev_handle;
bool fw_sync_cache_support; bool fw_sync_cache_support;
u32 mfi_frame_size;
bool is_ventura;
bool msix_combined;
u16 max_raid_mapsize;
/* preffered count to send as LDIO irrspective of FP capable.*/
u8 r1_ldio_hint_default;
u32 nvme_page_size;
}; };
struct MR_LD_VF_MAP { struct MR_LD_VF_MAP {
u32 size; u32 size;
@ -2230,12 +2331,12 @@ struct megasas_instance_template {
u32 (*init_adapter)(struct megasas_instance *); u32 (*init_adapter)(struct megasas_instance *);
u32 (*build_and_issue_cmd) (struct megasas_instance *, u32 (*build_and_issue_cmd) (struct megasas_instance *,
struct scsi_cmnd *); struct scsi_cmnd *);
int (*issue_dcmd)(struct megasas_instance *instance, void (*issue_dcmd)(struct megasas_instance *instance,
struct megasas_cmd *cmd); struct megasas_cmd *cmd);
}; };
#define MEGASAS_IS_LOGICAL(scp) \ #define MEGASAS_IS_LOGICAL(sdev) \
((scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1) ((sdev->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1)
#define MEGASAS_DEV_INDEX(scp) \ #define MEGASAS_DEV_INDEX(scp) \
(((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + \ (((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + \
@ -2346,7 +2447,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
struct IO_REQUEST_INFO *io_info, struct IO_REQUEST_INFO *io_info,
struct RAID_CONTEXT *pRAID_Context, struct RAID_CONTEXT *pRAID_Context,
struct MR_DRV_RAID_MAP_ALL *map, u8 **raidLUN); struct MR_DRV_RAID_MAP_ALL *map, u8 **raidLUN);
u8 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map); u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map);
struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_DRV_RAID_MAP_ALL *map); struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_DRV_RAID_MAP_ALL *map);
u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_DRV_RAID_MAP_ALL *map); u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_DRV_RAID_MAP_ALL *map);
u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_DRV_RAID_MAP_ALL *map); u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_DRV_RAID_MAP_ALL *map);
@ -2354,13 +2455,16 @@ __le16 MR_PdDevHandleGet(u32 pd, struct MR_DRV_RAID_MAP_ALL *map);
u16 MR_GetLDTgtId(u32 ld, struct MR_DRV_RAID_MAP_ALL *map); u16 MR_GetLDTgtId(u32 ld, struct MR_DRV_RAID_MAP_ALL *map);
__le16 get_updated_dev_handle(struct megasas_instance *instance, __le16 get_updated_dev_handle(struct megasas_instance *instance,
struct LD_LOAD_BALANCE_INFO *lbInfo, struct IO_REQUEST_INFO *in_info); struct LD_LOAD_BALANCE_INFO *lbInfo,
struct IO_REQUEST_INFO *in_info,
struct MR_DRV_RAID_MAP_ALL *drv_map);
void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map, void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *map,
struct LD_LOAD_BALANCE_INFO *lbInfo); struct LD_LOAD_BALANCE_INFO *lbInfo);
int megasas_get_ctrl_info(struct megasas_instance *instance); int megasas_get_ctrl_info(struct megasas_instance *instance);
/* PD sequence */ /* PD sequence */
int int
megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend); megasas_sync_pd_seq_num(struct megasas_instance *instance, bool pend);
void megasas_set_dynamic_target_properties(struct scsi_device *sdev);
int megasas_set_crash_dump_params(struct megasas_instance *instance, int megasas_set_crash_dump_params(struct megasas_instance *instance,
u8 crash_buf_state); u8 crash_buf_state);
void megasas_free_host_crash_buffer(struct megasas_instance *instance); void megasas_free_host_crash_buffer(struct megasas_instance *instance);
@ -2382,4 +2486,7 @@ void megasas_update_sdev_properties(struct scsi_device *sdev);
int megasas_reset_fusion(struct Scsi_Host *shost, int reason); int megasas_reset_fusion(struct Scsi_Host *shost, int reason);
int megasas_task_abort_fusion(struct scsi_cmnd *scmd); int megasas_task_abort_fusion(struct scsi_cmnd *scmd);
int megasas_reset_target_fusion(struct scsi_cmnd *scmd); int megasas_reset_target_fusion(struct scsi_cmnd *scmd);
u32 mega_mod64(u64 dividend, u32 divisor);
int megasas_alloc_fusion_context(struct megasas_instance *instance);
void megasas_free_fusion_context(struct megasas_instance *instance);
#endif /*LSI_MEGARAID_SAS_H */ #endif /*LSI_MEGARAID_SAS_H */

File diff suppressed because it is too large Load Diff

View File

@ -77,7 +77,6 @@ MODULE_PARM_DESC(lb_pending_cmds, "Change raid-1 load balancing outstanding "
#endif #endif
#define TRUE 1 #define TRUE 1
#define SPAN_DEBUG 0
#define SPAN_ROW_SIZE(map, ld, index_) (MR_LdSpanPtrGet(ld, index_, map)->spanRowSize) #define SPAN_ROW_SIZE(map, ld, index_) (MR_LdSpanPtrGet(ld, index_, map)->spanRowSize)
#define SPAN_ROW_DATA_SIZE(map_, ld, index_) (MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize) #define SPAN_ROW_DATA_SIZE(map_, ld, index_) (MR_LdSpanPtrGet(ld, index_, map)->spanRowDataSize)
#define SPAN_INVALID 0xff #define SPAN_INVALID 0xff
@ -155,12 +154,17 @@ __le16 MR_PdDevHandleGet(u32 pd, struct MR_DRV_RAID_MAP_ALL *map)
return map->raidMap.devHndlInfo[pd].curDevHdl; return map->raidMap.devHndlInfo[pd].curDevHdl;
} }
static u8 MR_PdInterfaceTypeGet(u32 pd, struct MR_DRV_RAID_MAP_ALL *map)
{
return map->raidMap.devHndlInfo[pd].interfaceType;
}
u16 MR_GetLDTgtId(u32 ld, struct MR_DRV_RAID_MAP_ALL *map) u16 MR_GetLDTgtId(u32 ld, struct MR_DRV_RAID_MAP_ALL *map)
{ {
return le16_to_cpu(map->raidMap.ldSpanMap[ld].ldRaid.targetId); return le16_to_cpu(map->raidMap.ldSpanMap[ld].ldRaid.targetId);
} }
u8 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map) u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map)
{ {
return map->raidMap.ldTgtIdToLd[ldTgtId]; return map->raidMap.ldTgtIdToLd[ldTgtId];
} }
@ -179,18 +183,108 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance)
struct fusion_context *fusion = instance->ctrl_context; struct fusion_context *fusion = instance->ctrl_context;
struct MR_FW_RAID_MAP_ALL *fw_map_old = NULL; struct MR_FW_RAID_MAP_ALL *fw_map_old = NULL;
struct MR_FW_RAID_MAP *pFwRaidMap = NULL; struct MR_FW_RAID_MAP *pFwRaidMap = NULL;
int i; int i, j;
u16 ld_count; u16 ld_count;
struct MR_FW_RAID_MAP_DYNAMIC *fw_map_dyn;
struct MR_FW_RAID_MAP_EXT *fw_map_ext;
struct MR_RAID_MAP_DESC_TABLE *desc_table;
struct MR_DRV_RAID_MAP_ALL *drv_map = struct MR_DRV_RAID_MAP_ALL *drv_map =
fusion->ld_drv_map[(instance->map_id & 1)]; fusion->ld_drv_map[(instance->map_id & 1)];
struct MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap; struct MR_DRV_RAID_MAP *pDrvRaidMap = &drv_map->raidMap;
void *raid_map_data = NULL;
memset(drv_map, 0, fusion->drv_map_sz);
memset(pDrvRaidMap->ldTgtIdToLd,
0xff, (sizeof(u16) * MAX_LOGICAL_DRIVES_DYN));
if (instance->max_raid_mapsize) {
fw_map_dyn = fusion->ld_map[(instance->map_id & 1)];
desc_table =
(struct MR_RAID_MAP_DESC_TABLE *)((void *)fw_map_dyn + le32_to_cpu(fw_map_dyn->desc_table_offset));
if (desc_table != fw_map_dyn->raid_map_desc_table)
dev_dbg(&instance->pdev->dev, "offsets of desc table are not matching desc %p original %p\n",
desc_table, fw_map_dyn->raid_map_desc_table);
ld_count = (u16)le16_to_cpu(fw_map_dyn->ld_count);
pDrvRaidMap->ldCount = (__le16)cpu_to_le16(ld_count);
pDrvRaidMap->fpPdIoTimeoutSec =
fw_map_dyn->fp_pd_io_timeout_sec;
pDrvRaidMap->totalSize =
cpu_to_le32(sizeof(struct MR_DRV_RAID_MAP_ALL));
/* point to actual data starting point*/
raid_map_data = (void *)fw_map_dyn +
le32_to_cpu(fw_map_dyn->desc_table_offset) +
le32_to_cpu(fw_map_dyn->desc_table_size);
for (i = 0; i < le32_to_cpu(fw_map_dyn->desc_table_num_elements); ++i) {
switch (le32_to_cpu(desc_table->raid_map_desc_type)) {
case RAID_MAP_DESC_TYPE_DEVHDL_INFO:
fw_map_dyn->dev_hndl_info =
(struct MR_DEV_HANDLE_INFO *)(raid_map_data + le32_to_cpu(desc_table->raid_map_desc_offset));
memcpy(pDrvRaidMap->devHndlInfo,
fw_map_dyn->dev_hndl_info,
sizeof(struct MR_DEV_HANDLE_INFO) *
le32_to_cpu(desc_table->raid_map_desc_elements));
break;
case RAID_MAP_DESC_TYPE_TGTID_INFO:
fw_map_dyn->ld_tgt_id_to_ld =
(u16 *)(raid_map_data +
le32_to_cpu(desc_table->raid_map_desc_offset));
for (j = 0; j < le32_to_cpu(desc_table->raid_map_desc_elements); j++) {
pDrvRaidMap->ldTgtIdToLd[j] =
le16_to_cpu(fw_map_dyn->ld_tgt_id_to_ld[j]);
}
break;
case RAID_MAP_DESC_TYPE_ARRAY_INFO:
fw_map_dyn->ar_map_info =
(struct MR_ARRAY_INFO *)
(raid_map_data + le32_to_cpu(desc_table->raid_map_desc_offset));
memcpy(pDrvRaidMap->arMapInfo,
fw_map_dyn->ar_map_info,
sizeof(struct MR_ARRAY_INFO) *
le32_to_cpu(desc_table->raid_map_desc_elements));
break;
case RAID_MAP_DESC_TYPE_SPAN_INFO:
fw_map_dyn->ld_span_map =
(struct MR_LD_SPAN_MAP *)
(raid_map_data +
le32_to_cpu(desc_table->raid_map_desc_offset));
memcpy(pDrvRaidMap->ldSpanMap,
fw_map_dyn->ld_span_map,
sizeof(struct MR_LD_SPAN_MAP) *
le32_to_cpu(desc_table->raid_map_desc_elements));
break;
default:
dev_dbg(&instance->pdev->dev, "wrong number of desctableElements %d\n",
fw_map_dyn->desc_table_num_elements);
}
++desc_table;
}
} else if (instance->supportmax256vd) {
fw_map_ext =
(struct MR_FW_RAID_MAP_EXT *)fusion->ld_map[(instance->map_id & 1)];
ld_count = (u16)le16_to_cpu(fw_map_ext->ldCount);
if (ld_count > MAX_LOGICAL_DRIVES_EXT) {
dev_dbg(&instance->pdev->dev, "megaraid_sas: LD count exposed in RAID map in not valid\n");
return;
}
pDrvRaidMap->ldCount = (__le16)cpu_to_le16(ld_count);
pDrvRaidMap->fpPdIoTimeoutSec = fw_map_ext->fpPdIoTimeoutSec;
for (i = 0; i < (MAX_LOGICAL_DRIVES_EXT); i++)
pDrvRaidMap->ldTgtIdToLd[i] =
(u16)fw_map_ext->ldTgtIdToLd[i];
memcpy(pDrvRaidMap->ldSpanMap, fw_map_ext->ldSpanMap,
sizeof(struct MR_LD_SPAN_MAP) * ld_count);
memcpy(pDrvRaidMap->arMapInfo, fw_map_ext->arMapInfo,
sizeof(struct MR_ARRAY_INFO) * MAX_API_ARRAYS_EXT);
memcpy(pDrvRaidMap->devHndlInfo, fw_map_ext->devHndlInfo,
sizeof(struct MR_DEV_HANDLE_INFO) *
MAX_RAIDMAP_PHYSICAL_DEVICES);
if (instance->supportmax256vd) {
memcpy(fusion->ld_drv_map[instance->map_id & 1],
fusion->ld_map[instance->map_id & 1],
fusion->current_map_sz);
/* New Raid map will not set totalSize, so keep expected value /* New Raid map will not set totalSize, so keep expected value
* for legacy code in ValidateMapInfo * for legacy code in ValidateMapInfo
*/ */
@ -201,50 +295,14 @@ void MR_PopulateDrvRaidMap(struct megasas_instance *instance)
fusion->ld_map[(instance->map_id & 1)]; fusion->ld_map[(instance->map_id & 1)];
pFwRaidMap = &fw_map_old->raidMap; pFwRaidMap = &fw_map_old->raidMap;
ld_count = (u16)le32_to_cpu(pFwRaidMap->ldCount); ld_count = (u16)le32_to_cpu(pFwRaidMap->ldCount);
#if VD_EXT_DEBUG
for (i = 0; i < ld_count; i++) {
dev_dbg(&instance->pdev->dev, "(%d) :Index 0x%x "
"Target Id 0x%x Seq Num 0x%x Size 0/%llx\n",
instance->unique_id, i,
fw_map_old->raidMap.ldSpanMap[i].ldRaid.targetId,
fw_map_old->raidMap.ldSpanMap[i].ldRaid.seqNum,
fw_map_old->raidMap.ldSpanMap[i].ldRaid.size);
}
#endif
memset(drv_map, 0, fusion->drv_map_sz);
pDrvRaidMap->totalSize = pFwRaidMap->totalSize; pDrvRaidMap->totalSize = pFwRaidMap->totalSize;
pDrvRaidMap->ldCount = (__le16)cpu_to_le16(ld_count); pDrvRaidMap->ldCount = (__le16)cpu_to_le16(ld_count);
pDrvRaidMap->fpPdIoTimeoutSec = pFwRaidMap->fpPdIoTimeoutSec; pDrvRaidMap->fpPdIoTimeoutSec = pFwRaidMap->fpPdIoTimeoutSec;
for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++) for (i = 0; i < MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS; i++)
pDrvRaidMap->ldTgtIdToLd[i] = pDrvRaidMap->ldTgtIdToLd[i] =
(u8)pFwRaidMap->ldTgtIdToLd[i]; (u8)pFwRaidMap->ldTgtIdToLd[i];
for (i = (MAX_RAIDMAP_LOGICAL_DRIVES + MAX_RAIDMAP_VIEWS);
i < MAX_LOGICAL_DRIVES_EXT; i++)
pDrvRaidMap->ldTgtIdToLd[i] = 0xff;
for (i = 0; i < ld_count; i++) { for (i = 0; i < ld_count; i++) {
pDrvRaidMap->ldSpanMap[i] = pFwRaidMap->ldSpanMap[i]; pDrvRaidMap->ldSpanMap[i] = pFwRaidMap->ldSpanMap[i];
#if VD_EXT_DEBUG
dev_dbg(&instance->pdev->dev,
"pFwRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x "
"pFwRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x "
"size 0x%x\n", i, i,
pFwRaidMap->ldSpanMap[i].ldRaid.targetId,
pFwRaidMap->ldSpanMap[i].ldRaid.seqNum,
(u32)pFwRaidMap->ldSpanMap[i].ldRaid.rowSize);
dev_dbg(&instance->pdev->dev,
"pDrvRaidMap->ldSpanMap[%d].ldRaid.targetId 0x%x "
"pDrvRaidMap->ldSpanMap[%d].ldRaid.seqNum 0x%x "
"size 0x%x\n", i, i,
pDrvRaidMap->ldSpanMap[i].ldRaid.targetId,
pDrvRaidMap->ldSpanMap[i].ldRaid.seqNum,
(u32)pDrvRaidMap->ldSpanMap[i].ldRaid.rowSize);
dev_dbg(&instance->pdev->dev, "Driver raid map all %p "
"raid map %p LD RAID MAP %p/%p\n", drv_map,
pDrvRaidMap, &pFwRaidMap->ldSpanMap[i].ldRaid,
&pDrvRaidMap->ldSpanMap[i].ldRaid);
#endif
} }
memcpy(pDrvRaidMap->arMapInfo, pFwRaidMap->arMapInfo, memcpy(pDrvRaidMap->arMapInfo, pFwRaidMap->arMapInfo,
sizeof(struct MR_ARRAY_INFO) * MAX_RAIDMAP_ARRAYS); sizeof(struct MR_ARRAY_INFO) * MAX_RAIDMAP_ARRAYS);
@ -265,7 +323,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance)
struct LD_LOAD_BALANCE_INFO *lbInfo; struct LD_LOAD_BALANCE_INFO *lbInfo;
PLD_SPAN_INFO ldSpanInfo; PLD_SPAN_INFO ldSpanInfo;
struct MR_LD_RAID *raid; struct MR_LD_RAID *raid;
u16 ldCount, num_lds; u16 num_lds, i;
u16 ld; u16 ld;
u32 expected_size; u32 expected_size;
@ -279,7 +337,9 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance)
lbInfo = fusion->load_balance_info; lbInfo = fusion->load_balance_info;
ldSpanInfo = fusion->log_to_span; ldSpanInfo = fusion->log_to_span;
if (instance->supportmax256vd) if (instance->max_raid_mapsize)
expected_size = sizeof(struct MR_DRV_RAID_MAP_ALL);
else if (instance->supportmax256vd)
expected_size = sizeof(struct MR_FW_RAID_MAP_EXT); expected_size = sizeof(struct MR_FW_RAID_MAP_EXT);
else else
expected_size = expected_size =
@ -287,8 +347,10 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance)
(sizeof(struct MR_LD_SPAN_MAP) * le16_to_cpu(pDrvRaidMap->ldCount))); (sizeof(struct MR_LD_SPAN_MAP) * le16_to_cpu(pDrvRaidMap->ldCount)));
if (le32_to_cpu(pDrvRaidMap->totalSize) != expected_size) { if (le32_to_cpu(pDrvRaidMap->totalSize) != expected_size) {
dev_err(&instance->pdev->dev, "map info structure size 0x%x is not matching with ld count\n", dev_dbg(&instance->pdev->dev, "megasas: map info structure size 0x%x",
(unsigned int) expected_size); le32_to_cpu(pDrvRaidMap->totalSize));
dev_dbg(&instance->pdev->dev, "is not matching expected size 0x%x\n",
(unsigned int)expected_size);
dev_err(&instance->pdev->dev, "megasas: span map %x, pDrvRaidMap->totalSize : %x\n", dev_err(&instance->pdev->dev, "megasas: span map %x, pDrvRaidMap->totalSize : %x\n",
(unsigned int)sizeof(struct MR_LD_SPAN_MAP), (unsigned int)sizeof(struct MR_LD_SPAN_MAP),
le32_to_cpu(pDrvRaidMap->totalSize)); le32_to_cpu(pDrvRaidMap->totalSize));
@ -298,15 +360,23 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance)
if (instance->UnevenSpanSupport) if (instance->UnevenSpanSupport)
mr_update_span_set(drv_map, ldSpanInfo); mr_update_span_set(drv_map, ldSpanInfo);
mr_update_load_balance_params(drv_map, lbInfo); if (lbInfo)
mr_update_load_balance_params(drv_map, lbInfo);
num_lds = le16_to_cpu(drv_map->raidMap.ldCount); num_lds = le16_to_cpu(drv_map->raidMap.ldCount);
/*Convert Raid capability values to CPU arch */ /*Convert Raid capability values to CPU arch */
for (ldCount = 0; ldCount < num_lds; ldCount++) { for (i = 0; (num_lds > 0) && (i < MAX_LOGICAL_DRIVES_EXT); i++) {
ld = MR_TargetIdToLdGet(ldCount, drv_map); ld = MR_TargetIdToLdGet(i, drv_map);
/* For non existing VDs, iterate to next VD*/
if (ld >= (MAX_LOGICAL_DRIVES_EXT - 1))
continue;
raid = MR_LdRaidGet(ld, drv_map); raid = MR_LdRaidGet(ld, drv_map);
le32_to_cpus((u32 *)&raid->capability); le32_to_cpus((u32 *)&raid->capability);
num_lds--;
} }
return 1; return 1;
@ -345,91 +415,6 @@ u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
return SPAN_INVALID; return SPAN_INVALID;
} }
/*
******************************************************************************
*
* Function to print info about span set created in driver from FW raid map
*
* Inputs :
* map - LD map
* ldSpanInfo - ldSpanInfo per HBA instance
*/
#if SPAN_DEBUG
static int getSpanInfo(struct MR_DRV_RAID_MAP_ALL *map,
PLD_SPAN_INFO ldSpanInfo)
{
u8 span;
u32 element;
struct MR_LD_RAID *raid;
LD_SPAN_SET *span_set;
struct MR_QUAD_ELEMENT *quad;
int ldCount;
u16 ld;
for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES_EXT; ldCount++) {
ld = MR_TargetIdToLdGet(ldCount, map);
if (ld >= (MAX_LOGICAL_DRIVES_EXT - 1))
continue;
raid = MR_LdRaidGet(ld, map);
dev_dbg(&instance->pdev->dev, "LD %x: span_depth=%x\n",
ld, raid->spanDepth);
for (span = 0; span < raid->spanDepth; span++)
dev_dbg(&instance->pdev->dev, "Span=%x,"
" number of quads=%x\n", span,
le32_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span].
block_span_info.noElements));
for (element = 0; element < MAX_QUAD_DEPTH; element++) {
span_set = &(ldSpanInfo[ld].span_set[element]);
if (span_set->span_row_data_width == 0)
break;
dev_dbg(&instance->pdev->dev, "Span Set %x:"
"width=%x, diff=%x\n", element,
(unsigned int)span_set->span_row_data_width,
(unsigned int)span_set->diff);
dev_dbg(&instance->pdev->dev, "logical LBA"
"start=0x%08lx, end=0x%08lx\n",
(long unsigned int)span_set->log_start_lba,
(long unsigned int)span_set->log_end_lba);
dev_dbg(&instance->pdev->dev, "span row start=0x%08lx,"
" end=0x%08lx\n",
(long unsigned int)span_set->span_row_start,
(long unsigned int)span_set->span_row_end);
dev_dbg(&instance->pdev->dev, "data row start=0x%08lx,"
" end=0x%08lx\n",
(long unsigned int)span_set->data_row_start,
(long unsigned int)span_set->data_row_end);
dev_dbg(&instance->pdev->dev, "data strip start=0x%08lx,"
" end=0x%08lx\n",
(long unsigned int)span_set->data_strip_start,
(long unsigned int)span_set->data_strip_end);
for (span = 0; span < raid->spanDepth; span++) {
if (le32_to_cpu(map->raidMap.ldSpanMap[ld].spanBlock[span].
block_span_info.noElements) >=
element + 1) {
quad = &map->raidMap.ldSpanMap[ld].
spanBlock[span].block_span_info.
quad[element];
dev_dbg(&instance->pdev->dev, "Span=%x,"
"Quad=%x, diff=%x\n", span,
element, le32_to_cpu(quad->diff));
dev_dbg(&instance->pdev->dev,
"offset_in_span=0x%08lx\n",
(long unsigned int)le64_to_cpu(quad->offsetInSpan));
dev_dbg(&instance->pdev->dev,
"logical start=0x%08lx, end=0x%08lx\n",
(long unsigned int)le64_to_cpu(quad->logStart),
(long unsigned int)le64_to_cpu(quad->logEnd));
}
}
}
}
return 0;
}
#endif
/* /*
****************************************************************************** ******************************************************************************
* *
@ -543,19 +528,7 @@ static u64 get_row_from_strip(struct megasas_instance *instance,
else else
break; break;
} }
#if SPAN_DEBUG
dev_info(&instance->pdev->dev, "Strip 0x%llx,"
"span_set_Strip 0x%llx, span_set_Row 0x%llx"
"data width 0x%llx span offset 0x%x\n", strip,
(unsigned long long)span_set_Strip,
(unsigned long long)span_set_Row,
(unsigned long long)span_set->span_row_data_width,
span_offset);
dev_info(&instance->pdev->dev, "For strip 0x%llx"
"row is 0x%llx\n", strip,
(unsigned long long) span_set->data_row_start +
(unsigned long long) span_set_Row + (span_offset - 1));
#endif
retval = (span_set->data_row_start + span_set_Row + retval = (span_set->data_row_start + span_set_Row +
(span_offset - 1)); (span_offset - 1));
return retval; return retval;
@ -672,11 +645,7 @@ static u32 get_arm_from_strip(struct megasas_instance *instance,
else else
break; break;
} }
#if SPAN_DEBUG
dev_info(&instance->pdev->dev, "get_arm_from_strip:"
"for ld=0x%x strip=0x%lx arm is 0x%x\n", ld,
(long unsigned int)strip, (strip_offset - span_offset));
#endif
retval = (strip_offset - span_offset); retval = (strip_offset - span_offset);
return retval; return retval;
} }
@ -737,16 +706,18 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
struct MR_DRV_RAID_MAP_ALL *map) struct MR_DRV_RAID_MAP_ALL *map)
{ {
struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
u32 pd, arRef; u32 pd, arRef, r1_alt_pd;
u8 physArm, span; u8 physArm, span;
u64 row; u64 row;
u8 retval = TRUE; u8 retval = TRUE;
u64 *pdBlock = &io_info->pdBlock; u64 *pdBlock = &io_info->pdBlock;
__le16 *pDevHandle = &io_info->devHandle; __le16 *pDevHandle = &io_info->devHandle;
u8 *pPdInterface = &io_info->pd_interface;
u32 logArm, rowMod, armQ, arm; u32 logArm, rowMod, armQ, arm;
struct fusion_context *fusion; struct fusion_context *fusion;
fusion = instance->ctrl_context; fusion = instance->ctrl_context;
*pDevHandle = cpu_to_le16(MR_DEVHANDLE_INVALID);
/*Get row and span from io_info for Uneven Span IO.*/ /*Get row and span from io_info for Uneven Span IO.*/
row = io_info->start_row; row = io_info->start_row;
@ -772,27 +743,46 @@ static u8 mr_spanset_get_phy_params(struct megasas_instance *instance, u32 ld,
arRef = MR_LdSpanArrayGet(ld, span, map); arRef = MR_LdSpanArrayGet(ld, span, map);
pd = MR_ArPdGet(arRef, physArm, map); pd = MR_ArPdGet(arRef, physArm, map);
if (pd != MR_PD_INVALID) if (pd != MR_PD_INVALID) {
*pDevHandle = MR_PdDevHandleGet(pd, map); *pDevHandle = MR_PdDevHandleGet(pd, map);
else { *pPdInterface = MR_PdInterfaceTypeGet(pd, map);
*pDevHandle = cpu_to_le16(MR_PD_INVALID); /* get second pd also for raid 1/10 fast path writes*/
if (instance->is_ventura &&
(raid->level == 1) &&
!io_info->isRead) {
r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map);
if (r1_alt_pd != MR_PD_INVALID)
io_info->r1_alt_dev_handle =
MR_PdDevHandleGet(r1_alt_pd, map);
}
} else {
if ((raid->level >= 5) && if ((raid->level >= 5) &&
((fusion->adapter_type == THUNDERBOLT_SERIES) || ((fusion->adapter_type == THUNDERBOLT_SERIES) ||
((fusion->adapter_type == INVADER_SERIES) && ((fusion->adapter_type == INVADER_SERIES) &&
(raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))) (raid->regTypeReqOnRead != REGION_TYPE_UNUSED))))
pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; pRAID_Context->reg_lock_flags = REGION_TYPE_EXCLUSIVE;
else if (raid->level == 1) { else if (raid->level == 1) {
physArm = physArm + 1; physArm = physArm + 1;
pd = MR_ArPdGet(arRef, physArm, map); pd = MR_ArPdGet(arRef, physArm, map);
if (pd != MR_PD_INVALID) if (pd != MR_PD_INVALID) {
*pDevHandle = MR_PdDevHandleGet(pd, map); *pDevHandle = MR_PdDevHandleGet(pd, map);
*pPdInterface = MR_PdInterfaceTypeGet(pd, map);
}
} }
} }
*pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk); *pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk);
pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | if (instance->is_ventura) {
physArm; ((struct RAID_CONTEXT_G35 *)pRAID_Context)->span_arm =
io_info->span_arm = pRAID_Context->spanArm; (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm;
io_info->span_arm =
(span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm;
} else {
pRAID_Context->span_arm =
(span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm;
io_info->span_arm = pRAID_Context->span_arm;
}
io_info->pd_after_lb = pd;
return retval; return retval;
} }
@ -819,16 +809,17 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
struct MR_DRV_RAID_MAP_ALL *map) struct MR_DRV_RAID_MAP_ALL *map)
{ {
struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
u32 pd, arRef; u32 pd, arRef, r1_alt_pd;
u8 physArm, span; u8 physArm, span;
u64 row; u64 row;
u8 retval = TRUE; u8 retval = TRUE;
u64 *pdBlock = &io_info->pdBlock; u64 *pdBlock = &io_info->pdBlock;
__le16 *pDevHandle = &io_info->devHandle; __le16 *pDevHandle = &io_info->devHandle;
u8 *pPdInterface = &io_info->pd_interface;
struct fusion_context *fusion; struct fusion_context *fusion;
fusion = instance->ctrl_context; fusion = instance->ctrl_context;
*pDevHandle = cpu_to_le16(MR_DEVHANDLE_INVALID);
row = mega_div64_32(stripRow, raid->rowDataSize); row = mega_div64_32(stripRow, raid->rowDataSize);
@ -867,31 +858,49 @@ u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
arRef = MR_LdSpanArrayGet(ld, span, map); arRef = MR_LdSpanArrayGet(ld, span, map);
pd = MR_ArPdGet(arRef, physArm, map); /* Get the pd */ pd = MR_ArPdGet(arRef, physArm, map); /* Get the pd */
if (pd != MR_PD_INVALID) if (pd != MR_PD_INVALID) {
/* Get dev handle from Pd. */ /* Get dev handle from Pd. */
*pDevHandle = MR_PdDevHandleGet(pd, map); *pDevHandle = MR_PdDevHandleGet(pd, map);
else { *pPdInterface = MR_PdInterfaceTypeGet(pd, map);
/* set dev handle as invalid. */ /* get second pd also for raid 1/10 fast path writes*/
*pDevHandle = cpu_to_le16(MR_PD_INVALID); if (instance->is_ventura &&
(raid->level == 1) &&
!io_info->isRead) {
r1_alt_pd = MR_ArPdGet(arRef, physArm + 1, map);
if (r1_alt_pd != MR_PD_INVALID)
io_info->r1_alt_dev_handle =
MR_PdDevHandleGet(r1_alt_pd, map);
}
} else {
if ((raid->level >= 5) && if ((raid->level >= 5) &&
((fusion->adapter_type == THUNDERBOLT_SERIES) || ((fusion->adapter_type == THUNDERBOLT_SERIES) ||
((fusion->adapter_type == INVADER_SERIES) && ((fusion->adapter_type == INVADER_SERIES) &&
(raid->regTypeReqOnRead != REGION_TYPE_UNUSED)))) (raid->regTypeReqOnRead != REGION_TYPE_UNUSED))))
pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; pRAID_Context->reg_lock_flags = REGION_TYPE_EXCLUSIVE;
else if (raid->level == 1) { else if (raid->level == 1) {
/* Get alternate Pd. */ /* Get alternate Pd. */
physArm = physArm + 1; physArm = physArm + 1;
pd = MR_ArPdGet(arRef, physArm, map); pd = MR_ArPdGet(arRef, physArm, map);
if (pd != MR_PD_INVALID) if (pd != MR_PD_INVALID) {
/* Get dev handle from Pd */ /* Get dev handle from Pd */
*pDevHandle = MR_PdDevHandleGet(pd, map); *pDevHandle = MR_PdDevHandleGet(pd, map);
*pPdInterface = MR_PdInterfaceTypeGet(pd, map);
}
} }
} }
*pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk); *pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk);
pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | if (instance->is_ventura) {
physArm; ((struct RAID_CONTEXT_G35 *)pRAID_Context)->span_arm =
io_info->span_arm = pRAID_Context->spanArm; (span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm;
io_info->span_arm =
(span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm;
} else {
pRAID_Context->span_arm =
(span << RAID_CTX_SPANARM_SPAN_SHIFT) | physArm;
io_info->span_arm = pRAID_Context->span_arm;
}
io_info->pd_after_lb = pd;
return retval; return retval;
} }
@ -912,7 +921,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
{ {
struct fusion_context *fusion; struct fusion_context *fusion;
struct MR_LD_RAID *raid; struct MR_LD_RAID *raid;
u32 ld, stripSize, stripe_mask; u32 stripSize, stripe_mask;
u64 endLba, endStrip, endRow, start_row, start_strip; u64 endLba, endStrip, endRow, start_row, start_strip;
u64 regStart; u64 regStart;
u32 regSize; u32 regSize;
@ -924,6 +933,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
u8 retval = 0; u8 retval = 0;
u8 startlba_span = SPAN_INVALID; u8 startlba_span = SPAN_INVALID;
u64 *pdBlock = &io_info->pdBlock; u64 *pdBlock = &io_info->pdBlock;
u16 ld;
ldStartBlock = io_info->ldStartBlock; ldStartBlock = io_info->ldStartBlock;
numBlocks = io_info->numBlocks; numBlocks = io_info->numBlocks;
@ -935,6 +945,8 @@ MR_BuildRaidContext(struct megasas_instance *instance,
ld = MR_TargetIdToLdGet(ldTgtId, map); ld = MR_TargetIdToLdGet(ldTgtId, map);
raid = MR_LdRaidGet(ld, map); raid = MR_LdRaidGet(ld, map);
/*check read ahead bit*/
io_info->ra_capable = raid->capability.ra_capable;
/* /*
* if rowDataSize @RAID map and spanRowDataSize @SPAN INFO are zero * if rowDataSize @RAID map and spanRowDataSize @SPAN INFO are zero
@ -996,17 +1008,6 @@ MR_BuildRaidContext(struct megasas_instance *instance,
} }
io_info->start_span = startlba_span; io_info->start_span = startlba_span;
io_info->start_row = start_row; io_info->start_row = start_row;
#if SPAN_DEBUG
dev_dbg(&instance->pdev->dev, "Check Span number from %s %d"
"for row 0x%llx, start strip 0x%llx end strip 0x%llx"
" span 0x%x\n", __func__, __LINE__,
(unsigned long long)start_row,
(unsigned long long)start_strip,
(unsigned long long)endStrip, startlba_span);
dev_dbg(&instance->pdev->dev, "start_row 0x%llx endRow 0x%llx"
"Start span 0x%x\n", (unsigned long long)start_row,
(unsigned long long)endRow, startlba_span);
#endif
} else { } else {
start_row = mega_div64_32(start_strip, raid->rowDataSize); start_row = mega_div64_32(start_strip, raid->rowDataSize);
endRow = mega_div64_32(endStrip, raid->rowDataSize); endRow = mega_div64_32(endStrip, raid->rowDataSize);
@ -1093,20 +1094,20 @@ MR_BuildRaidContext(struct megasas_instance *instance,
regSize += stripSize; regSize += stripSize;
} }
pRAID_Context->timeoutValue = pRAID_Context->timeout_value =
cpu_to_le16(raid->fpIoTimeoutForLd ? cpu_to_le16(raid->fpIoTimeoutForLd ?
raid->fpIoTimeoutForLd : raid->fpIoTimeoutForLd :
map->raidMap.fpPdIoTimeoutSec); map->raidMap.fpPdIoTimeoutSec);
if (fusion->adapter_type == INVADER_SERIES) if (fusion->adapter_type == INVADER_SERIES)
pRAID_Context->regLockFlags = (isRead) ? pRAID_Context->reg_lock_flags = (isRead) ?
raid->regTypeReqOnRead : raid->regTypeReqOnWrite; raid->regTypeReqOnRead : raid->regTypeReqOnWrite;
else else if (!instance->is_ventura)
pRAID_Context->regLockFlags = (isRead) ? pRAID_Context->reg_lock_flags = (isRead) ?
REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite; REGION_TYPE_SHARED_READ : raid->regTypeReqOnWrite;
pRAID_Context->VirtualDiskTgtId = raid->targetId; pRAID_Context->virtual_disk_tgt_id = raid->targetId;
pRAID_Context->regLockRowLBA = cpu_to_le64(regStart); pRAID_Context->reg_lock_row_lba = cpu_to_le64(regStart);
pRAID_Context->regLockLength = cpu_to_le32(regSize); pRAID_Context->reg_lock_length = cpu_to_le32(regSize);
pRAID_Context->configSeqNum = raid->seqNum; pRAID_Context->config_seq_num = raid->seqNum;
/* save pointer to raid->LUN array */ /* save pointer to raid->LUN array */
*raidLUN = raid->LUN; *raidLUN = raid->LUN;
@ -1122,7 +1123,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
ref_in_start_stripe, io_info, ref_in_start_stripe, io_info,
pRAID_Context, map); pRAID_Context, map);
/* If IO on an invalid Pd, then FP is not possible.*/ /* If IO on an invalid Pd, then FP is not possible.*/
if (io_info->devHandle == cpu_to_le16(MR_PD_INVALID)) if (io_info->devHandle == MR_DEVHANDLE_INVALID)
io_info->fpOkForIo = FALSE; io_info->fpOkForIo = FALSE;
return retval; return retval;
} else if (isRead) { } else if (isRead) {
@ -1140,12 +1141,6 @@ MR_BuildRaidContext(struct megasas_instance *instance,
return TRUE; return TRUE;
} }
} }
#if SPAN_DEBUG
/* Just for testing what arm we get for strip.*/
if (io_info->IoforUnevenSpan)
get_arm_from_strip(instance, ld, start_strip, map);
#endif
return TRUE; return TRUE;
} }
@ -1259,10 +1254,6 @@ void mr_update_span_set(struct MR_DRV_RAID_MAP_ALL *map,
break; break;
} }
} }
#if SPAN_DEBUG
getSpanInfo(map, ldSpanInfo);
#endif
} }
void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *drv_map, void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *drv_map,
@ -1293,11 +1284,12 @@ void mr_update_load_balance_params(struct MR_DRV_RAID_MAP_ALL *drv_map,
} }
u8 megasas_get_best_arm_pd(struct megasas_instance *instance, u8 megasas_get_best_arm_pd(struct megasas_instance *instance,
struct LD_LOAD_BALANCE_INFO *lbInfo, struct IO_REQUEST_INFO *io_info) struct LD_LOAD_BALANCE_INFO *lbInfo,
struct IO_REQUEST_INFO *io_info,
struct MR_DRV_RAID_MAP_ALL *drv_map)
{ {
struct fusion_context *fusion;
struct MR_LD_RAID *raid; struct MR_LD_RAID *raid;
struct MR_DRV_RAID_MAP_ALL *drv_map; u16 pd1_dev_handle;
u16 pend0, pend1, ld; u16 pend0, pend1, ld;
u64 diff0, diff1; u64 diff0, diff1;
u8 bestArm, pd0, pd1, span, arm; u8 bestArm, pd0, pd1, span, arm;
@ -1310,9 +1302,6 @@ u8 megasas_get_best_arm_pd(struct megasas_instance *instance,
>> RAID_CTX_SPANARM_SPAN_SHIFT); >> RAID_CTX_SPANARM_SPAN_SHIFT);
arm = (io_info->span_arm & RAID_CTX_SPANARM_ARM_MASK); arm = (io_info->span_arm & RAID_CTX_SPANARM_ARM_MASK);
fusion = instance->ctrl_context;
drv_map = fusion->ld_drv_map[(instance->map_id & 1)];
ld = MR_TargetIdToLdGet(io_info->ldTgtId, drv_map); ld = MR_TargetIdToLdGet(io_info->ldTgtId, drv_map);
raid = MR_LdRaidGet(ld, drv_map); raid = MR_LdRaidGet(ld, drv_map);
span_row_size = instance->UnevenSpanSupport ? span_row_size = instance->UnevenSpanSupport ?
@ -1323,47 +1312,52 @@ u8 megasas_get_best_arm_pd(struct megasas_instance *instance,
pd1 = MR_ArPdGet(arRef, (arm + 1) >= span_row_size ? pd1 = MR_ArPdGet(arRef, (arm + 1) >= span_row_size ?
(arm + 1 - span_row_size) : arm + 1, drv_map); (arm + 1 - span_row_size) : arm + 1, drv_map);
/* get the pending cmds for the data and mirror arms */ /* Get PD1 Dev Handle */
pend0 = atomic_read(&lbInfo->scsi_pending_cmds[pd0]);
pend1 = atomic_read(&lbInfo->scsi_pending_cmds[pd1]);
/* Determine the disk whose head is nearer to the req. block */ pd1_dev_handle = MR_PdDevHandleGet(pd1, drv_map);
diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[pd0]);
diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[pd1]);
bestArm = (diff0 <= diff1 ? arm : arm ^ 1);
if ((bestArm == arm && pend0 > pend1 + lb_pending_cmds) || if (pd1_dev_handle == MR_DEVHANDLE_INVALID) {
(bestArm != arm && pend1 > pend0 + lb_pending_cmds)) bestArm = arm;
bestArm ^= 1; } else {
/* get the pending cmds for the data and mirror arms */
pend0 = atomic_read(&lbInfo->scsi_pending_cmds[pd0]);
pend1 = atomic_read(&lbInfo->scsi_pending_cmds[pd1]);
/* Determine the disk whose head is nearer to the req. block */
diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[pd0]);
diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[pd1]);
bestArm = (diff0 <= diff1 ? arm : arm ^ 1);
/* Make balance count from 16 to 4 to
* keep driver in sync with Firmware
*/
if ((bestArm == arm && pend0 > pend1 + lb_pending_cmds) ||
(bestArm != arm && pend1 > pend0 + lb_pending_cmds))
bestArm ^= 1;
/* Update the last accessed block on the correct pd */
io_info->span_arm =
(span << RAID_CTX_SPANARM_SPAN_SHIFT) | bestArm;
io_info->pd_after_lb = (bestArm == arm) ? pd0 : pd1;
}
/* Update the last accessed block on the correct pd */
io_info->pd_after_lb = (bestArm == arm) ? pd0 : pd1;
lbInfo->last_accessed_block[io_info->pd_after_lb] = block + count - 1; lbInfo->last_accessed_block[io_info->pd_after_lb] = block + count - 1;
io_info->span_arm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | bestArm;
#if SPAN_DEBUG
if (arm != bestArm)
dev_dbg(&instance->pdev->dev, "LSI Debug R1 Load balance "
"occur - span 0x%x arm 0x%x bestArm 0x%x "
"io_info->span_arm 0x%x\n",
span, arm, bestArm, io_info->span_arm);
#endif
return io_info->pd_after_lb; return io_info->pd_after_lb;
} }
__le16 get_updated_dev_handle(struct megasas_instance *instance, __le16 get_updated_dev_handle(struct megasas_instance *instance,
struct LD_LOAD_BALANCE_INFO *lbInfo, struct IO_REQUEST_INFO *io_info) struct LD_LOAD_BALANCE_INFO *lbInfo,
struct IO_REQUEST_INFO *io_info,
struct MR_DRV_RAID_MAP_ALL *drv_map)
{ {
u8 arm_pd; u8 arm_pd;
__le16 devHandle; __le16 devHandle;
struct fusion_context *fusion;
struct MR_DRV_RAID_MAP_ALL *drv_map;
fusion = instance->ctrl_context;
drv_map = fusion->ld_drv_map[(instance->map_id & 1)];
/* get best new arm (PD ID) */ /* get best new arm (PD ID) */
arm_pd = megasas_get_best_arm_pd(instance, lbInfo, io_info); arm_pd = megasas_get_best_arm_pd(instance, lbInfo, io_info, drv_map);
devHandle = MR_PdDevHandleGet(arm_pd, drv_map); devHandle = MR_PdDevHandleGet(arm_pd, drv_map);
io_info->pd_interface = MR_PdInterfaceTypeGet(arm_pd, drv_map);
atomic_inc(&lbInfo->scsi_pending_cmds[arm_pd]); atomic_inc(&lbInfo->scsi_pending_cmds[arm_pd]);
return devHandle; return devHandle;
} }

File diff suppressed because it is too large Load Diff

View File

@ -59,6 +59,8 @@
#define MR_RL_FLAGS_GRANT_DESTINATION_CPU1 0x10 #define MR_RL_FLAGS_GRANT_DESTINATION_CPU1 0x10
#define MR_RL_FLAGS_GRANT_DESTINATION_CUDA 0x80 #define MR_RL_FLAGS_GRANT_DESTINATION_CUDA 0x80
#define MR_RL_FLAGS_SEQ_NUM_ENABLE 0x8 #define MR_RL_FLAGS_SEQ_NUM_ENABLE 0x8
#define MR_RL_WRITE_THROUGH_MODE 0x00
#define MR_RL_WRITE_BACK_MODE 0x01
/* T10 PI defines */ /* T10 PI defines */
#define MR_PROT_INFO_TYPE_CONTROLLER 0x8 #define MR_PROT_INFO_TYPE_CONTROLLER 0x8
@ -81,6 +83,11 @@
enum MR_RAID_FLAGS_IO_SUB_TYPE { enum MR_RAID_FLAGS_IO_SUB_TYPE {
MR_RAID_FLAGS_IO_SUB_TYPE_NONE = 0, MR_RAID_FLAGS_IO_SUB_TYPE_NONE = 0,
MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD = 1, MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD = 1,
MR_RAID_FLAGS_IO_SUB_TYPE_RMW_DATA = 2,
MR_RAID_FLAGS_IO_SUB_TYPE_RMW_P = 3,
MR_RAID_FLAGS_IO_SUB_TYPE_RMW_Q = 4,
MR_RAID_FLAGS_IO_SUB_TYPE_CACHE_BYPASS = 6,
MR_RAID_FLAGS_IO_SUB_TYPE_LDIO_BW_LIMIT = 7
}; };
/* /*
@ -94,11 +101,13 @@ enum MR_RAID_FLAGS_IO_SUB_TYPE {
#define MEGASAS_FP_CMD_LEN 16 #define MEGASAS_FP_CMD_LEN 16
#define MEGASAS_FUSION_IN_RESET 0 #define MEGASAS_FUSION_IN_RESET 0
#define THRESHOLD_REPLY_COUNT 50 #define THRESHOLD_REPLY_COUNT 50
#define RAID_1_PEER_CMDS 2
#define JBOD_MAPS_COUNT 2 #define JBOD_MAPS_COUNT 2
enum MR_FUSION_ADAPTER_TYPE { enum MR_FUSION_ADAPTER_TYPE {
THUNDERBOLT_SERIES = 0, THUNDERBOLT_SERIES = 0,
INVADER_SERIES = 1, INVADER_SERIES = 1,
VENTURA_SERIES = 2,
}; };
/* /*
@ -108,29 +117,133 @@ enum MR_FUSION_ADAPTER_TYPE {
struct RAID_CONTEXT { struct RAID_CONTEXT {
#if defined(__BIG_ENDIAN_BITFIELD) #if defined(__BIG_ENDIAN_BITFIELD)
u8 nseg:4; u8 nseg:4;
u8 Type:4; u8 type:4;
#else #else
u8 Type:4; u8 type:4;
u8 nseg:4; u8 nseg:4;
#endif #endif
u8 resvd0; u8 resvd0;
__le16 timeoutValue; __le16 timeout_value;
u8 regLockFlags; u8 reg_lock_flags;
u8 resvd1; u8 resvd1;
__le16 VirtualDiskTgtId; __le16 virtual_disk_tgt_id;
__le64 regLockRowLBA; __le64 reg_lock_row_lba;
__le32 regLockLength; __le32 reg_lock_length;
__le16 nextLMId; __le16 next_lmid;
u8 exStatus; u8 ex_status;
u8 status; u8 status;
u8 RAIDFlags; u8 raid_flags;
u8 numSGE; u8 num_sge;
__le16 configSeqNum; __le16 config_seq_num;
u8 spanArm; u8 span_arm;
u8 priority; u8 priority;
u8 numSGEExt; u8 num_sge_ext;
u8 resvd2; u8 resvd2;
};
/*
* Raid Context structure which describes ventura MegaRAID specific
* IO Paramenters ,This resides at offset 0x60 where the SGL normally
* starts in MPT IO Frames
*/
struct RAID_CONTEXT_G35 {
#define RAID_CONTEXT_NSEG_MASK 0x00F0
#define RAID_CONTEXT_NSEG_SHIFT 4
#define RAID_CONTEXT_TYPE_MASK 0x000F
#define RAID_CONTEXT_TYPE_SHIFT 0
u16 nseg_type;
u16 timeout_value; /* 0x02 -0x03 */
u16 routing_flags; // 0x04 -0x05 routing flags
u16 virtual_disk_tgt_id; /* 0x06 -0x07 */
u64 reg_lock_row_lba; /* 0x08 - 0x0F */
u32 reg_lock_length; /* 0x10 - 0x13 */
union {
u16 next_lmid; /* 0x14 - 0x15 */
u16 peer_smid; /* used for the raid 1/10 fp writes */
} smid;
u8 ex_status; /* 0x16 : OUT */
u8 status; /* 0x17 status */
u8 raid_flags; /* 0x18 resvd[7:6], ioSubType[5:4],
* resvd[3:1], preferredCpu[0]
*/
u8 span_arm; /* 0x1C span[7:5], arm[4:0] */
u16 config_seq_num; /* 0x1A -0x1B */
union {
/*
* Bit format:
* ---------------------------------
* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
* ---------------------------------
* Byte0 | numSGE[7]- numSGE[0] |
* ---------------------------------
* Byte1 |SD | resvd | numSGE 8-11 |
* --------------------------------
*/
#define NUM_SGE_MASK_LOWER 0xFF
#define NUM_SGE_MASK_UPPER 0x0F
#define NUM_SGE_SHIFT_UPPER 8
#define STREAM_DETECT_SHIFT 7
#define STREAM_DETECT_MASK 0x80
struct {
#if defined(__BIG_ENDIAN_BITFIELD) /* 0x1C - 0x1D */
u16 stream_detected:1;
u16 reserved:3;
u16 num_sge:12;
#else
u16 num_sge:12;
u16 reserved:3;
u16 stream_detected:1;
#endif
} bits;
u8 bytes[2];
} u;
u8 resvd2[2]; /* 0x1E-0x1F */
};
#define MR_RAID_CTX_ROUTINGFLAGS_SLD_SHIFT 1
#define MR_RAID_CTX_ROUTINGFLAGS_C2D_SHIFT 2
#define MR_RAID_CTX_ROUTINGFLAGS_FWD_SHIFT 3
#define MR_RAID_CTX_ROUTINGFLAGS_SQN_SHIFT 4
#define MR_RAID_CTX_ROUTINGFLAGS_SBS_SHIFT 5
#define MR_RAID_CTX_ROUTINGFLAGS_RW_SHIFT 6
#define MR_RAID_CTX_ROUTINGFLAGS_LOG_SHIFT 7
#define MR_RAID_CTX_ROUTINGFLAGS_CPUSEL_SHIFT 8
#define MR_RAID_CTX_ROUTINGFLAGS_CPUSEL_MASK 0x0F00
#define MR_RAID_CTX_ROUTINGFLAGS_SETDIVERT_SHIFT 12
#define MR_RAID_CTX_ROUTINGFLAGS_SETDIVERT_MASK 0xF000
static inline void set_num_sge(struct RAID_CONTEXT_G35 *rctx_g35,
u16 sge_count)
{
rctx_g35->u.bytes[0] = (u8)(sge_count & NUM_SGE_MASK_LOWER);
rctx_g35->u.bytes[1] |= (u8)((sge_count >> NUM_SGE_SHIFT_UPPER)
& NUM_SGE_MASK_UPPER);
}
static inline u16 get_num_sge(struct RAID_CONTEXT_G35 *rctx_g35)
{
u16 sge_count;
sge_count = (u16)(((rctx_g35->u.bytes[1] & NUM_SGE_MASK_UPPER)
<< NUM_SGE_SHIFT_UPPER) | (rctx_g35->u.bytes[0]));
return sge_count;
}
#define SET_STREAM_DETECTED(rctx_g35) \
(rctx_g35.u.bytes[1] |= STREAM_DETECT_MASK)
#define CLEAR_STREAM_DETECTED(rctx_g35) \
(rctx_g35.u.bytes[1] &= ~(STREAM_DETECT_MASK))
static inline bool is_stream_detected(struct RAID_CONTEXT_G35 *rctx_g35)
{
return ((rctx_g35->u.bytes[1] & STREAM_DETECT_MASK));
}
union RAID_CONTEXT_UNION {
struct RAID_CONTEXT raid_context;
struct RAID_CONTEXT_G35 raid_context_g35;
}; };
#define RAID_CTX_SPANARM_ARM_SHIFT (0) #define RAID_CTX_SPANARM_ARM_SHIFT (0)
@ -139,6 +252,14 @@ struct RAID_CONTEXT {
#define RAID_CTX_SPANARM_SPAN_SHIFT (5) #define RAID_CTX_SPANARM_SPAN_SHIFT (5)
#define RAID_CTX_SPANARM_SPAN_MASK (0xE0) #define RAID_CTX_SPANARM_SPAN_MASK (0xE0)
/* number of bits per index in U32 TrackStream */
#define BITS_PER_INDEX_STREAM 4
#define INVALID_STREAM_NUM 16
#define MR_STREAM_BITMAP 0x76543210
#define STREAM_MASK ((1 << BITS_PER_INDEX_STREAM) - 1)
#define ZERO_LAST_STREAM 0x0fffffff
#define MAX_STREAMS_TRACKED 8
/* /*
* define region lock types * define region lock types
*/ */
@ -175,6 +296,8 @@ enum REGION_TYPE {
#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200) #define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200)
#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100) #define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100)
#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004) #define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004)
/* EEDP escape mode */
#define MPI25_SCSIIO_EEDPFLAGS_DO_NOT_DISABLE_MODE (0x0040)
#define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */ #define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */
#define MPI2_FUNCTION_SCSI_TASK_MGMT (0x01) #define MPI2_FUNCTION_SCSI_TASK_MGMT (0x01)
#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x03) #define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x03)
@ -407,7 +530,7 @@ struct MPI2_RAID_SCSI_IO_REQUEST {
u8 LUN[8]; /* 0x34 */ u8 LUN[8]; /* 0x34 */
__le32 Control; /* 0x3C */ __le32 Control; /* 0x3C */
union MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */ union MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */
struct RAID_CONTEXT RaidContext; /* 0x60 */ union RAID_CONTEXT_UNION RaidContext; /* 0x60 */
union MPI2_SGE_IO_UNION SGL; /* 0x80 */ union MPI2_SGE_IO_UNION SGL; /* 0x80 */
}; };
@ -563,7 +686,7 @@ struct MPI2_IOC_INIT_REQUEST {
__le16 HeaderVersion; /* 0x0E */ __le16 HeaderVersion; /* 0x0E */
u32 Reserved5; /* 0x10 */ u32 Reserved5; /* 0x10 */
__le16 Reserved6; /* 0x14 */ __le16 Reserved6; /* 0x14 */
u8 Reserved7; /* 0x16 */ u8 HostPageSize; /* 0x16 */
u8 HostMSIxVectors; /* 0x17 */ u8 HostMSIxVectors; /* 0x17 */
__le16 Reserved8; /* 0x18 */ __le16 Reserved8; /* 0x18 */
__le16 SystemRequestFrameSize; /* 0x1A */ __le16 SystemRequestFrameSize; /* 0x1A */
@ -579,6 +702,7 @@ struct MPI2_IOC_INIT_REQUEST {
/* mrpriv defines */ /* mrpriv defines */
#define MR_PD_INVALID 0xFFFF #define MR_PD_INVALID 0xFFFF
#define MR_DEVHANDLE_INVALID 0xFFFF
#define MAX_SPAN_DEPTH 8 #define MAX_SPAN_DEPTH 8
#define MAX_QUAD_DEPTH MAX_SPAN_DEPTH #define MAX_QUAD_DEPTH MAX_SPAN_DEPTH
#define MAX_RAIDMAP_SPAN_DEPTH (MAX_SPAN_DEPTH) #define MAX_RAIDMAP_SPAN_DEPTH (MAX_SPAN_DEPTH)
@ -586,16 +710,20 @@ struct MPI2_IOC_INIT_REQUEST {
#define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE) #define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE)
#define MAX_LOGICAL_DRIVES 64 #define MAX_LOGICAL_DRIVES 64
#define MAX_LOGICAL_DRIVES_EXT 256 #define MAX_LOGICAL_DRIVES_EXT 256
#define MAX_LOGICAL_DRIVES_DYN 512
#define MAX_RAIDMAP_LOGICAL_DRIVES (MAX_LOGICAL_DRIVES) #define MAX_RAIDMAP_LOGICAL_DRIVES (MAX_LOGICAL_DRIVES)
#define MAX_RAIDMAP_VIEWS (MAX_LOGICAL_DRIVES) #define MAX_RAIDMAP_VIEWS (MAX_LOGICAL_DRIVES)
#define MAX_ARRAYS 128 #define MAX_ARRAYS 128
#define MAX_RAIDMAP_ARRAYS (MAX_ARRAYS) #define MAX_RAIDMAP_ARRAYS (MAX_ARRAYS)
#define MAX_ARRAYS_EXT 256 #define MAX_ARRAYS_EXT 256
#define MAX_API_ARRAYS_EXT (MAX_ARRAYS_EXT) #define MAX_API_ARRAYS_EXT (MAX_ARRAYS_EXT)
#define MAX_API_ARRAYS_DYN 512
#define MAX_PHYSICAL_DEVICES 256 #define MAX_PHYSICAL_DEVICES 256
#define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES) #define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES)
#define MAX_RAIDMAP_PHYSICAL_DEVICES_DYN 512
#define MR_DCMD_LD_MAP_GET_INFO 0x0300e101 #define MR_DCMD_LD_MAP_GET_INFO 0x0300e101
#define MR_DCMD_SYSTEM_PD_MAP_GET_INFO 0x0200e102 #define MR_DCMD_SYSTEM_PD_MAP_GET_INFO 0x0200e102
#define MR_DCMD_DRV_GET_TARGET_PROP 0x0200e103
#define MR_DCMD_CTRL_SHARED_HOST_MEM_ALLOC 0x010e8485 /* SR-IOV HB alloc*/ #define MR_DCMD_CTRL_SHARED_HOST_MEM_ALLOC 0x010e8485 /* SR-IOV HB alloc*/
#define MR_DCMD_LD_VF_MAP_GET_ALL_LDS_111 0x03200200 #define MR_DCMD_LD_VF_MAP_GET_ALL_LDS_111 0x03200200
#define MR_DCMD_LD_VF_MAP_GET_ALL_LDS 0x03150200 #define MR_DCMD_LD_VF_MAP_GET_ALL_LDS 0x03150200
@ -603,7 +731,7 @@ struct MPI2_IOC_INIT_REQUEST {
struct MR_DEV_HANDLE_INFO { struct MR_DEV_HANDLE_INFO {
__le16 curDevHdl; __le16 curDevHdl;
u8 validHandles; u8 validHandles;
u8 reserved; u8 interfaceType;
__le16 devHandle[2]; __le16 devHandle[2];
}; };
@ -640,10 +768,56 @@ struct MR_SPAN_BLOCK_INFO {
struct MR_SPAN_INFO block_span_info; struct MR_SPAN_INFO block_span_info;
}; };
#define MR_RAID_CTX_CPUSEL_0 0
#define MR_RAID_CTX_CPUSEL_1 1
#define MR_RAID_CTX_CPUSEL_2 2
#define MR_RAID_CTX_CPUSEL_3 3
#define MR_RAID_CTX_CPUSEL_FCFS 0xF
struct MR_CPU_AFFINITY_MASK {
union {
struct {
#ifndef MFI_BIG_ENDIAN
u8 hw_path:1;
u8 cpu0:1;
u8 cpu1:1;
u8 cpu2:1;
u8 cpu3:1;
u8 reserved:3;
#else
u8 reserved:3;
u8 cpu3:1;
u8 cpu2:1;
u8 cpu1:1;
u8 cpu0:1;
u8 hw_path:1;
#endif
};
u8 core_mask;
};
};
struct MR_IO_AFFINITY {
union {
struct {
struct MR_CPU_AFFINITY_MASK pdRead;
struct MR_CPU_AFFINITY_MASK pdWrite;
struct MR_CPU_AFFINITY_MASK ldRead;
struct MR_CPU_AFFINITY_MASK ldWrite;
};
u32 word;
};
u8 maxCores; /* Total cores + HW Path in ROC */
u8 reserved[3];
};
struct MR_LD_RAID { struct MR_LD_RAID {
struct { struct {
#if defined(__BIG_ENDIAN_BITFIELD) #if defined(__BIG_ENDIAN_BITFIELD)
u32 reserved4:5; u32 reserved4:2;
u32 fp_cache_bypass_capable:1;
u32 fp_rmw_capable:1;
u32 disable_coalescing:1;
u32 fpBypassRegionLock:1; u32 fpBypassRegionLock:1;
u32 tmCapable:1; u32 tmCapable:1;
u32 fpNonRWCapable:1; u32 fpNonRWCapable:1;
@ -654,11 +828,13 @@ struct MR_LD_RAID {
u32 encryptionType:8; u32 encryptionType:8;
u32 pdPiMode:4; u32 pdPiMode:4;
u32 ldPiMode:4; u32 ldPiMode:4;
u32 reserved5:3; u32 reserved5:2;
u32 ra_capable:1;
u32 fpCapable:1; u32 fpCapable:1;
#else #else
u32 fpCapable:1; u32 fpCapable:1;
u32 reserved5:3; u32 ra_capable:1;
u32 reserved5:2;
u32 ldPiMode:4; u32 ldPiMode:4;
u32 pdPiMode:4; u32 pdPiMode:4;
u32 encryptionType:8; u32 encryptionType:8;
@ -669,7 +845,10 @@ struct MR_LD_RAID {
u32 fpNonRWCapable:1; u32 fpNonRWCapable:1;
u32 tmCapable:1; u32 tmCapable:1;
u32 fpBypassRegionLock:1; u32 fpBypassRegionLock:1;
u32 reserved4:5; u32 disable_coalescing:1;
u32 fp_rmw_capable:1;
u32 fp_cache_bypass_capable:1;
u32 reserved4:2;
#endif #endif
} capability; } capability;
__le32 reserved6; __le32 reserved6;
@ -696,7 +875,36 @@ struct MR_LD_RAID {
u8 LUN[8]; /* 0x24 8 byte LUN field used for SCSI IO's */ u8 LUN[8]; /* 0x24 8 byte LUN field used for SCSI IO's */
u8 fpIoTimeoutForLd;/*0x2C timeout value used by driver in FP IO*/ u8 fpIoTimeoutForLd;/*0x2C timeout value used by driver in FP IO*/
u8 reserved3[0x80-0x2D]; /* 0x2D */ /* Ox2D This LD accept priority boost of this type */
u8 ld_accept_priority_type;
u8 reserved2[2]; /* 0x2E - 0x2F */
/* 0x30 - 0x33, Logical block size for the LD */
u32 logical_block_length;
struct {
#ifndef MFI_BIG_ENDIAN
/* 0x34, P_I_EXPONENT from READ CAPACITY 16 */
u32 ld_pi_exp:4;
/* 0x34, LOGICAL BLOCKS PER PHYSICAL
* BLOCK EXPONENT from READ CAPACITY 16
*/
u32 ld_logical_block_exp:4;
u32 reserved1:24; /* 0x34 */
#else
u32 reserved1:24; /* 0x34 */
/* 0x34, LOGICAL BLOCKS PER PHYSICAL
* BLOCK EXPONENT from READ CAPACITY 16
*/
u32 ld_logical_block_exp:4;
/* 0x34, P_I_EXPONENT from READ CAPACITY 16 */
u32 ld_pi_exp:4;
#endif
}; /* 0x34 - 0x37 */
/* 0x38 - 0x3f, This will determine which
* core will process LD IO and PD IO.
*/
struct MR_IO_AFFINITY cpuAffinity;
/* Bit definiations are specified by MR_IO_AFFINITY */
u8 reserved3[0x80 - 0x40]; /* 0x40 - 0x7f */
}; };
struct MR_LD_SPAN_MAP { struct MR_LD_SPAN_MAP {
@ -735,6 +943,7 @@ struct IO_REQUEST_INFO {
u16 ldTgtId; u16 ldTgtId;
u8 isRead; u8 isRead;
__le16 devHandle; __le16 devHandle;
u8 pd_interface;
u64 pdBlock; u64 pdBlock;
u8 fpOkForIo; u8 fpOkForIo;
u8 IoforUnevenSpan; u8 IoforUnevenSpan;
@ -743,6 +952,8 @@ struct IO_REQUEST_INFO {
u64 start_row; u64 start_row;
u8 span_arm; /* span[7:5], arm[4:0] */ u8 span_arm; /* span[7:5], arm[4:0] */
u8 pd_after_lb; u8 pd_after_lb;
u16 r1_alt_dev_handle; /* raid 1/10 only */
bool ra_capable;
}; };
struct MR_LD_TARGET_SYNC { struct MR_LD_TARGET_SYNC {
@ -751,6 +962,91 @@ struct MR_LD_TARGET_SYNC {
__le16 seqNum; __le16 seqNum;
}; };
/*
* RAID Map descriptor Types.
* Each element should uniquely idetify one data structure in the RAID map
*/
enum MR_RAID_MAP_DESC_TYPE {
/* MR_DEV_HANDLE_INFO data */
RAID_MAP_DESC_TYPE_DEVHDL_INFO = 0x0,
/* target to Ld num Index map */
RAID_MAP_DESC_TYPE_TGTID_INFO = 0x1,
/* MR_ARRAY_INFO data */
RAID_MAP_DESC_TYPE_ARRAY_INFO = 0x2,
/* MR_LD_SPAN_MAP data */
RAID_MAP_DESC_TYPE_SPAN_INFO = 0x3,
RAID_MAP_DESC_TYPE_COUNT,
};
/*
* This table defines the offset, size and num elements of each descriptor
* type in the RAID Map buffer
*/
struct MR_RAID_MAP_DESC_TABLE {
/* Raid map descriptor type */
u32 raid_map_desc_type;
/* Offset into the RAID map buffer where
* descriptor data is saved
*/
u32 raid_map_desc_offset;
/* total size of the
* descriptor buffer
*/
u32 raid_map_desc_buffer_size;
/* Number of elements contained in the
* descriptor buffer
*/
u32 raid_map_desc_elements;
};
/*
* Dynamic Raid Map Structure.
*/
struct MR_FW_RAID_MAP_DYNAMIC {
u32 raid_map_size; /* total size of RAID Map structure */
u32 desc_table_offset;/* Offset of desc table into RAID map*/
u32 desc_table_size; /* Total Size of desc table */
/* Total Number of elements in the desc table */
u32 desc_table_num_elements;
u64 reserved1;
u32 reserved2[3]; /*future use */
/* timeout value used by driver in FP IOs */
u8 fp_pd_io_timeout_sec;
u8 reserved3[3];
/* when this seqNum increments, driver needs to
* release RMW buffers asap
*/
u32 rmw_fp_seq_num;
u16 ld_count; /* count of lds. */
u16 ar_count; /* count of arrays */
u16 span_count; /* count of spans */
u16 reserved4[3];
/*
* The below structure of pointers is only to be used by the driver.
* This is added in the ,API to reduce the amount of code changes
* needed in the driver to support dynamic RAID map Firmware should
* not update these pointers while preparing the raid map
*/
union {
struct {
struct MR_DEV_HANDLE_INFO *dev_hndl_info;
u16 *ld_tgt_id_to_ld;
struct MR_ARRAY_INFO *ar_map_info;
struct MR_LD_SPAN_MAP *ld_span_map;
};
u64 ptr_structure_size[RAID_MAP_DESC_TYPE_COUNT];
};
/*
* RAID Map descriptor table defines the layout of data in the RAID Map.
* The size of the descriptor table itself could change.
*/
/* Variable Size descriptor Table. */
struct MR_RAID_MAP_DESC_TABLE
raid_map_desc_table[RAID_MAP_DESC_TYPE_COUNT];
/* Variable Size buffer containing all data */
u32 raid_map_desc_data[1];
}; /* Dynamicaly sized RAID MAp structure */
#define IEEE_SGE_FLAGS_ADDR_MASK (0x03) #define IEEE_SGE_FLAGS_ADDR_MASK (0x03)
#define IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00) #define IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00)
#define IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01) #define IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01)
@ -759,6 +1055,16 @@ struct MR_LD_TARGET_SYNC {
#define IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80) #define IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80)
#define IEEE_SGE_FLAGS_END_OF_LIST (0x40) #define IEEE_SGE_FLAGS_END_OF_LIST (0x40)
#define MPI2_SGE_FLAGS_SHIFT (0x02)
#define IEEE_SGE_FLAGS_FORMAT_MASK (0xC0)
#define IEEE_SGE_FLAGS_FORMAT_IEEE (0x00)
#define IEEE_SGE_FLAGS_FORMAT_NVME (0x02)
#define MPI26_IEEE_SGE_FLAGS_NSF_MASK (0x1C)
#define MPI26_IEEE_SGE_FLAGS_NSF_MPI_IEEE (0x00)
#define MPI26_IEEE_SGE_FLAGS_NSF_NVME_PRP (0x08)
#define MPI26_IEEE_SGE_FLAGS_NSF_NVME_SGL (0x10)
struct megasas_register_set; struct megasas_register_set;
struct megasas_instance; struct megasas_instance;
@ -795,6 +1101,10 @@ struct megasas_cmd_fusion {
u32 index; u32 index;
u8 pd_r1_lb; u8 pd_r1_lb;
struct completion done; struct completion done;
u8 pd_interface;
u16 r1_alt_dev_handle; /* raid 1/10 only*/
bool cmd_completed; /* raid 1/10 fp writes status holder */
}; };
struct LD_LOAD_BALANCE_INFO { struct LD_LOAD_BALANCE_INFO {
@ -856,9 +1166,10 @@ struct MR_DRV_RAID_MAP {
__le16 spanCount; __le16 spanCount;
__le16 reserve3; __le16 reserve3;
struct MR_DEV_HANDLE_INFO devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES]; struct MR_DEV_HANDLE_INFO
u8 ldTgtIdToLd[MAX_LOGICAL_DRIVES_EXT]; devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES_DYN];
struct MR_ARRAY_INFO arMapInfo[MAX_API_ARRAYS_EXT]; u16 ldTgtIdToLd[MAX_LOGICAL_DRIVES_DYN];
struct MR_ARRAY_INFO arMapInfo[MAX_API_ARRAYS_DYN];
struct MR_LD_SPAN_MAP ldSpanMap[1]; struct MR_LD_SPAN_MAP ldSpanMap[1];
}; };
@ -870,7 +1181,7 @@ struct MR_DRV_RAID_MAP {
struct MR_DRV_RAID_MAP_ALL { struct MR_DRV_RAID_MAP_ALL {
struct MR_DRV_RAID_MAP raidMap; struct MR_DRV_RAID_MAP raidMap;
struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_EXT - 1]; struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_DYN - 1];
} __packed; } __packed;
@ -919,7 +1230,8 @@ struct MR_PD_CFG_SEQ {
u8 reserved:7; u8 reserved:7;
#endif #endif
} capability; } capability;
u8 reserved[3]; u8 reserved;
u16 pd_target_id;
} __packed; } __packed;
struct MR_PD_CFG_SEQ_NUM_SYNC { struct MR_PD_CFG_SEQ_NUM_SYNC {
@ -928,6 +1240,30 @@ struct MR_PD_CFG_SEQ_NUM_SYNC {
struct MR_PD_CFG_SEQ seq[1]; struct MR_PD_CFG_SEQ seq[1];
} __packed; } __packed;
/* stream detection */
struct STREAM_DETECT {
u64 next_seq_lba; /* next LBA to match sequential access */
struct megasas_cmd_fusion *first_cmd_fusion; /* first cmd in group */
struct megasas_cmd_fusion *last_cmd_fusion; /* last cmd in group */
u32 count_cmds_in_stream; /* count of host commands in this stream */
u16 num_sges_in_group; /* total number of SGEs in grouped IOs */
u8 is_read; /* SCSI OpCode for this stream */
u8 group_depth; /* total number of host commands in group */
/* TRUE if cannot add any more commands to this group */
bool group_flush;
u8 reserved[7]; /* pad to 64-bit alignment */
};
struct LD_STREAM_DETECT {
bool write_back; /* TRUE if WB, FALSE if WT */
bool fp_write_enabled;
bool members_ssds;
bool fp_cache_bypass_capable;
u32 mru_bit_map; /* bitmap used to track MRU and LRU stream indicies */
/* this is the array of stream detect structures (one per stream) */
struct STREAM_DETECT stream_track[MAX_STREAMS_TRACKED];
};
struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY { struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY {
u64 RDPQBaseAddress; u64 RDPQBaseAddress;
u32 Reserved1; u32 Reserved1;
@ -965,7 +1301,7 @@ struct fusion_context {
u8 chain_offset_io_request; u8 chain_offset_io_request;
u8 chain_offset_mfi_pthru; u8 chain_offset_mfi_pthru;
struct MR_FW_RAID_MAP_ALL *ld_map[2]; struct MR_FW_RAID_MAP_DYNAMIC *ld_map[2];
dma_addr_t ld_map_phys[2]; dma_addr_t ld_map_phys[2];
/*Non dma-able memory. Driver local copy.*/ /*Non dma-able memory. Driver local copy.*/
@ -973,14 +1309,18 @@ struct fusion_context {
u32 max_map_sz; u32 max_map_sz;
u32 current_map_sz; u32 current_map_sz;
u32 old_map_sz;
u32 new_map_sz;
u32 drv_map_sz; u32 drv_map_sz;
u32 drv_map_pages; u32 drv_map_pages;
struct MR_PD_CFG_SEQ_NUM_SYNC *pd_seq_sync[JBOD_MAPS_COUNT]; struct MR_PD_CFG_SEQ_NUM_SYNC *pd_seq_sync[JBOD_MAPS_COUNT];
dma_addr_t pd_seq_phys[JBOD_MAPS_COUNT]; dma_addr_t pd_seq_phys[JBOD_MAPS_COUNT];
u8 fast_path_io; u8 fast_path_io;
struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES_EXT]; struct LD_LOAD_BALANCE_INFO *load_balance_info;
u32 load_balance_info_pages;
LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT]; LD_SPAN_INFO log_to_span[MAX_LOGICAL_DRIVES_EXT];
u8 adapter_type; u8 adapter_type;
struct LD_STREAM_DETECT **stream_detect_by_ld;
}; };
union desc_value { union desc_value {

View File

@ -624,6 +624,8 @@ typedef struct _MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT {
/* defines for ReasonCode field */ /* defines for ReasonCode field */
#define MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER (0x00) #define MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER (0x00)
#define MPI26_EVENT_ACTIVE_CABLE_PRESENT (0x01)
#define MPI26_EVENT_ACTIVE_CABLE_DEGRADED (0x02)
/*Hard Reset Received Event data */ /*Hard Reset Received Event data */

View File

@ -1040,6 +1040,25 @@ _base_interrupt(int irq, void *bus_id)
reply_q->reply_post_free[reply_q->reply_post_host_index]. reply_q->reply_post_free[reply_q->reply_post_host_index].
Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
completed_cmds++; completed_cmds++;
/* Update the reply post host index after continuously
* processing the threshold number of Reply Descriptors.
* So that FW can find enough entries to post the Reply
* Descriptors in the reply descriptor post queue.
*/
if (completed_cmds > ioc->hba_queue_depth/3) {
if (ioc->combined_reply_queue) {
writel(reply_q->reply_post_host_index |
((msix_index & 7) <<
MPI2_RPHI_MSIX_INDEX_SHIFT),
ioc->replyPostRegisterIndex[msix_index/8]);
} else {
writel(reply_q->reply_post_host_index |
(msix_index <<
MPI2_RPHI_MSIX_INDEX_SHIFT),
&ioc->chip->ReplyPostHostIndex);
}
completed_cmds = 1;
}
if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
goto out; goto out;
if (!reply_q->reply_post_host_index) if (!reply_q->reply_post_host_index)
@ -5522,6 +5541,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
goto out_free_resources; goto out_free_resources;
ioc->non_operational_loop = 0; ioc->non_operational_loop = 0;
ioc->got_task_abort_from_ioctl = 0;
return 0; return 0;
out_free_resources: out_free_resources:

View File

@ -73,9 +73,9 @@
#define MPT3SAS_DRIVER_NAME "mpt3sas" #define MPT3SAS_DRIVER_NAME "mpt3sas"
#define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>" #define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>"
#define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" #define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver"
#define MPT3SAS_DRIVER_VERSION "14.101.00.00" #define MPT3SAS_DRIVER_VERSION "15.100.00.00"
#define MPT3SAS_MAJOR_VERSION 14 #define MPT3SAS_MAJOR_VERSION 15
#define MPT3SAS_MINOR_VERSION 101 #define MPT3SAS_MINOR_VERSION 100
#define MPT3SAS_BUILD_VERSION 0 #define MPT3SAS_BUILD_VERSION 0
#define MPT3SAS_RELEASE_VERSION 00 #define MPT3SAS_RELEASE_VERSION 00
@ -1000,6 +1000,7 @@ struct MPT3SAS_ADAPTER {
u8 broadcast_aen_busy; u8 broadcast_aen_busy;
u16 broadcast_aen_pending; u16 broadcast_aen_pending;
u8 shost_recovery; u8 shost_recovery;
u8 got_task_abort_from_ioctl;
struct mutex reset_in_progress_mutex; struct mutex reset_in_progress_mutex;
spinlock_t ioc_reset_in_progress_lock; spinlock_t ioc_reset_in_progress_lock;

View File

@ -826,16 +826,18 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
"TASK_MGMT: handle(0x%04x), task_type(0x%02x)\n", "TASK_MGMT: handle(0x%04x), task_type(0x%02x)\n",
ioc->name, ioc->name,
le16_to_cpu(tm_request->DevHandle), tm_request->TaskType)); le16_to_cpu(tm_request->DevHandle), tm_request->TaskType));
ioc->got_task_abort_from_ioctl = 1;
if (tm_request->TaskType == if (tm_request->TaskType ==
MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK || MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK ||
tm_request->TaskType == tm_request->TaskType ==
MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) { MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) {
if (_ctl_set_task_mid(ioc, &karg, tm_request)) { if (_ctl_set_task_mid(ioc, &karg, tm_request)) {
mpt3sas_base_free_smid(ioc, smid); mpt3sas_base_free_smid(ioc, smid);
ioc->got_task_abort_from_ioctl = 0;
goto out; goto out;
} }
} }
ioc->got_task_abort_from_ioctl = 0;
if (test_bit(device_handle, ioc->device_remove_in_progress)) { if (test_bit(device_handle, ioc->device_remove_in_progress)) {
dtmprintk(ioc, pr_info(MPT3SAS_FMT dtmprintk(ioc, pr_info(MPT3SAS_FMT

View File

@ -1074,6 +1074,26 @@ _scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid)
return ioc->scsi_lookup[smid - 1].scmd; return ioc->scsi_lookup[smid - 1].scmd;
} }
/**
* __scsih_scsi_lookup_get_clear - returns scmd entry without
* holding any lock.
* @ioc: per adapter object
* @smid: system request message index
*
* Returns the smid stored scmd pointer.
* Then will dereference the stored scmd pointer.
*/
static inline struct scsi_cmnd *
__scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER *ioc,
u16 smid)
{
struct scsi_cmnd *scmd = NULL;
swap(scmd, ioc->scsi_lookup[smid - 1].scmd);
return scmd;
}
/** /**
* _scsih_scsi_lookup_get_clear - returns scmd entry * _scsih_scsi_lookup_get_clear - returns scmd entry
* @ioc: per adapter object * @ioc: per adapter object
@ -1089,8 +1109,7 @@ _scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER *ioc, u16 smid)
struct scsi_cmnd *scmd; struct scsi_cmnd *scmd;
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
scmd = ioc->scsi_lookup[smid - 1].scmd; scmd = __scsih_scsi_lookup_get_clear(ioc, smid);
ioc->scsi_lookup[smid - 1].scmd = NULL;
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
return scmd; return scmd;
@ -4661,7 +4680,13 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
unsigned int sector_sz; unsigned int sector_sz;
mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
if (ioc->broadcast_aen_busy || ioc->pci_error_recovery ||
ioc->got_task_abort_from_ioctl)
scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
else
scmd = __scsih_scsi_lookup_get_clear(ioc, smid);
if (scmd == NULL) if (scmd == NULL)
return 1; return 1;
@ -8044,15 +8069,24 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION: case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION:
ActiveCableEventData = ActiveCableEventData =
(Mpi26EventDataActiveCableExcept_t *) mpi_reply->EventData; (Mpi26EventDataActiveCableExcept_t *) mpi_reply->EventData;
if (ActiveCableEventData->ReasonCode == switch (ActiveCableEventData->ReasonCode) {
MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER) { case MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER:
pr_info(MPT3SAS_FMT "Currently an active cable with ReceptacleID %d", pr_notice(MPT3SAS_FMT "Receptacle ID %d: This active cable"
ioc->name, ActiveCableEventData->ReceptacleID); " requires %d mW of power\n", ioc->name,
pr_info("cannot be powered and devices connected to this active cable"); ActiveCableEventData->ReceptacleID,
pr_info("will not be seen. This active cable"); ActiveCableEventData->ActiveCablePowerRequirement);
pr_info("requires %d mW of power", pr_notice(MPT3SAS_FMT "Receptacle ID %d: Devices connected"
ActiveCableEventData->ActiveCablePowerRequirement); " to this active cable will not be seen\n",
ioc->name, ActiveCableEventData->ReceptacleID);
break;
case MPI26_EVENT_ACTIVE_CABLE_DEGRADED:
pr_notice(MPT3SAS_FMT "ReceptacleID %d: This cable",
ioc->name, ActiveCableEventData->ReceptacleID);
pr_notice(" is not running at an optimal speed(12 Gb/s)\n");
break;
} }
break; break;
default: /* ignore the rest */ default: /* ignore the rest */

View File

@ -2225,15 +2225,12 @@ static struct scsi_host_template mvumi_template = {
.name = "Marvell Storage Controller", .name = "Marvell Storage Controller",
.slave_configure = mvumi_slave_configure, .slave_configure = mvumi_slave_configure,
.queuecommand = mvumi_queue_command, .queuecommand = mvumi_queue_command,
.eh_timed_out = mvumi_timed_out,
.eh_host_reset_handler = mvumi_host_reset, .eh_host_reset_handler = mvumi_host_reset,
.bios_param = mvumi_bios_param, .bios_param = mvumi_bios_param,
.this_id = -1, .this_id = -1,
}; };
static struct scsi_transport_template mvumi_transport_template = {
.eh_timed_out = mvumi_timed_out,
};
static int mvumi_cfg_hw_reg(struct mvumi_hba *mhba) static int mvumi_cfg_hw_reg(struct mvumi_hba *mhba)
{ {
void *base = NULL; void *base = NULL;
@ -2451,7 +2448,6 @@ static int mvumi_io_attach(struct mvumi_hba *mhba)
host->cmd_per_lun = (mhba->max_io - 1) ? (mhba->max_io - 1) : 1; host->cmd_per_lun = (mhba->max_io - 1) ? (mhba->max_io - 1) : 1;
host->max_id = mhba->max_target_id; host->max_id = mhba->max_target_id;
host->max_cmd_len = MAX_COMMAND_SIZE; host->max_cmd_len = MAX_COMMAND_SIZE;
host->transportt = &mvumi_transport_template;
ret = scsi_add_host(host, &mhba->pdev->dev); ret = scsi_add_host(host, &mhba->pdev->dev);
if (ret) { if (ret) {

View File

@ -888,7 +888,6 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
u32 i = 0, j = 0; u32 i = 0, j = 0;
u32 number_of_intr; u32 number_of_intr;
int flag = 0; int flag = 0;
u32 max_entry;
int rc; int rc;
static char intr_drvname[PM8001_MAX_MSIX_VEC][sizeof(DRV_NAME)+3]; static char intr_drvname[PM8001_MAX_MSIX_VEC][sizeof(DRV_NAME)+3];
@ -900,18 +899,14 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
flag &= ~IRQF_SHARED; flag &= ~IRQF_SHARED;
} }
max_entry = sizeof(pm8001_ha->msix_entries) / rc = pci_alloc_irq_vectors(pm8001_ha->pdev, number_of_intr,
sizeof(pm8001_ha->msix_entries[0]); number_of_intr, PCI_IRQ_MSIX);
for (i = 0; i < max_entry ; i++) if (rc < 0)
pm8001_ha->msix_entries[i].entry = i;
rc = pci_enable_msix_exact(pm8001_ha->pdev, pm8001_ha->msix_entries,
number_of_intr);
pm8001_ha->number_of_intr = number_of_intr;
if (rc)
return rc; return rc;
pm8001_ha->number_of_intr = number_of_intr;
PM8001_INIT_DBG(pm8001_ha, pm8001_printk( PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
"pci_enable_msix_exact request ret:%d no of intr %d\n", "pci_alloc_irq_vectors request ret:%d no of intr %d\n",
rc, pm8001_ha->number_of_intr)); rc, pm8001_ha->number_of_intr));
for (i = 0; i < number_of_intr; i++) { for (i = 0; i < number_of_intr; i++) {
@ -920,15 +915,15 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->irq_vector[i].irq_id = i; pm8001_ha->irq_vector[i].irq_id = i;
pm8001_ha->irq_vector[i].drv_inst = pm8001_ha; pm8001_ha->irq_vector[i].drv_inst = pm8001_ha;
rc = request_irq(pm8001_ha->msix_entries[i].vector, rc = request_irq(pci_irq_vector(pm8001_ha->pdev, i),
pm8001_interrupt_handler_msix, flag, pm8001_interrupt_handler_msix, flag,
intr_drvname[i], &(pm8001_ha->irq_vector[i])); intr_drvname[i], &(pm8001_ha->irq_vector[i]));
if (rc) { if (rc) {
for (j = 0; j < i; j++) { for (j = 0; j < i; j++) {
free_irq(pm8001_ha->msix_entries[j].vector, free_irq(pci_irq_vector(pm8001_ha->pdev, i),
&(pm8001_ha->irq_vector[i])); &(pm8001_ha->irq_vector[i]));
} }
pci_disable_msix(pm8001_ha->pdev); pci_free_irq_vectors(pm8001_ha->pdev);
break; break;
} }
} }
@ -1102,11 +1097,10 @@ static void pm8001_pci_remove(struct pci_dev *pdev)
#ifdef PM8001_USE_MSIX #ifdef PM8001_USE_MSIX
for (i = 0; i < pm8001_ha->number_of_intr; i++) for (i = 0; i < pm8001_ha->number_of_intr; i++)
synchronize_irq(pm8001_ha->msix_entries[i].vector); synchronize_irq(pci_irq_vector(pdev, i));
for (i = 0; i < pm8001_ha->number_of_intr; i++) for (i = 0; i < pm8001_ha->number_of_intr; i++)
free_irq(pm8001_ha->msix_entries[i].vector, free_irq(pci_irq_vector(pdev, i), &pm8001_ha->irq_vector[i]);
&(pm8001_ha->irq_vector[i])); pci_free_irq_vectors(pdev);
pci_disable_msix(pdev);
#else #else
free_irq(pm8001_ha->irq, sha); free_irq(pm8001_ha->irq, sha);
#endif #endif
@ -1152,11 +1146,10 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
#ifdef PM8001_USE_MSIX #ifdef PM8001_USE_MSIX
for (i = 0; i < pm8001_ha->number_of_intr; i++) for (i = 0; i < pm8001_ha->number_of_intr; i++)
synchronize_irq(pm8001_ha->msix_entries[i].vector); synchronize_irq(pci_irq_vector(pdev, i));
for (i = 0; i < pm8001_ha->number_of_intr; i++) for (i = 0; i < pm8001_ha->number_of_intr; i++)
free_irq(pm8001_ha->msix_entries[i].vector, free_irq(pci_irq_vector(pdev, i), &pm8001_ha->irq_vector[i]);
&(pm8001_ha->irq_vector[i])); pci_free_irq_vectors(pdev);
pci_disable_msix(pdev);
#else #else
free_irq(pm8001_ha->irq, sha); free_irq(pm8001_ha->irq, sha);
#endif #endif

View File

@ -521,8 +521,6 @@ struct pm8001_hba_info {
struct pm8001_device *devices; struct pm8001_device *devices;
struct pm8001_ccb_info *ccb_info; struct pm8001_ccb_info *ccb_info;
#ifdef PM8001_USE_MSIX #ifdef PM8001_USE_MSIX
struct msix_entry msix_entries[PM8001_MAX_MSIX_VEC];
/*for msi-x interrupt*/
int number_of_intr;/*will be used in remove()*/ int number_of_intr;/*will be used in remove()*/
#endif #endif
#ifdef PM8001_USE_TASKLET #ifdef PM8001_USE_TASKLET

View File

@ -4587,16 +4587,14 @@ static void pmcraid_tasklet_function(unsigned long instance)
static static
void pmcraid_unregister_interrupt_handler(struct pmcraid_instance *pinstance) void pmcraid_unregister_interrupt_handler(struct pmcraid_instance *pinstance)
{ {
struct pci_dev *pdev = pinstance->pdev;
int i; int i;
for (i = 0; i < pinstance->num_hrrq; i++) for (i = 0; i < pinstance->num_hrrq; i++)
free_irq(pinstance->hrrq_vector[i].vector, free_irq(pci_irq_vector(pdev, i), &pinstance->hrrq_vector[i]);
&(pinstance->hrrq_vector[i]));
if (pinstance->interrupt_mode) { pinstance->interrupt_mode = 0;
pci_disable_msix(pinstance->pdev); pci_free_irq_vectors(pdev);
pinstance->interrupt_mode = 0;
}
} }
/** /**
@ -4609,60 +4607,52 @@ void pmcraid_unregister_interrupt_handler(struct pmcraid_instance *pinstance)
static int static int
pmcraid_register_interrupt_handler(struct pmcraid_instance *pinstance) pmcraid_register_interrupt_handler(struct pmcraid_instance *pinstance)
{ {
int rc;
struct pci_dev *pdev = pinstance->pdev; struct pci_dev *pdev = pinstance->pdev;
unsigned int irq_flag = PCI_IRQ_LEGACY, flag;
int num_hrrq, rc, i;
irq_handler_t isr;
if ((pmcraid_enable_msix) && if (pmcraid_enable_msix)
(pci_find_capability(pdev, PCI_CAP_ID_MSIX))) { irq_flag |= PCI_IRQ_MSIX;
int num_hrrq = PMCRAID_NUM_MSIX_VECTORS;
struct msix_entry entries[PMCRAID_NUM_MSIX_VECTORS];
int i;
for (i = 0; i < PMCRAID_NUM_MSIX_VECTORS; i++)
entries[i].entry = i;
num_hrrq = pci_enable_msix_range(pdev, entries, 1, num_hrrq); num_hrrq = pci_alloc_irq_vectors(pdev, 1, PMCRAID_NUM_MSIX_VECTORS,
if (num_hrrq < 0) irq_flag);
goto pmcraid_isr_legacy; if (num_hrrq < 0)
return num_hrrq;
for (i = 0; i < num_hrrq; i++) { if (pdev->msix_enabled) {
pinstance->hrrq_vector[i].hrrq_id = i; flag = 0;
pinstance->hrrq_vector[i].drv_inst = pinstance; isr = pmcraid_isr_msix;
pinstance->hrrq_vector[i].vector = entries[i].vector; } else {
rc = request_irq(pinstance->hrrq_vector[i].vector, flag = IRQF_SHARED;
pmcraid_isr_msix, 0, isr = pmcraid_isr;
PMCRAID_DRIVER_NAME, }
&(pinstance->hrrq_vector[i]));
if (rc) { for (i = 0; i < num_hrrq; i++) {
int j; struct pmcraid_isr_param *vec = &pinstance->hrrq_vector[i];
for (j = 0; j < i; j++)
free_irq(entries[j].vector,
&(pinstance->hrrq_vector[j]));
pci_disable_msix(pdev);
goto pmcraid_isr_legacy;
}
}
pinstance->num_hrrq = num_hrrq; vec->hrrq_id = i;
vec->drv_inst = pinstance;
rc = request_irq(pci_irq_vector(pdev, i), isr, flag,
PMCRAID_DRIVER_NAME, vec);
if (rc)
goto out_unwind;
}
pinstance->num_hrrq = num_hrrq;
if (pdev->msix_enabled) {
pinstance->interrupt_mode = 1; pinstance->interrupt_mode = 1;
iowrite32(DOORBELL_INTR_MODE_MSIX, iowrite32(DOORBELL_INTR_MODE_MSIX,
pinstance->int_regs.host_ioa_interrupt_reg); pinstance->int_regs.host_ioa_interrupt_reg);
ioread32(pinstance->int_regs.host_ioa_interrupt_reg); ioread32(pinstance->int_regs.host_ioa_interrupt_reg);
goto pmcraid_isr_out;
} }
pmcraid_isr_legacy: return 0;
/* If MSI-X registration failed fallback to legacy mode, where
* only one hrrq entry will be used
*/
pinstance->hrrq_vector[0].hrrq_id = 0;
pinstance->hrrq_vector[0].drv_inst = pinstance;
pinstance->hrrq_vector[0].vector = pdev->irq;
pinstance->num_hrrq = 1;
rc = request_irq(pdev->irq, pmcraid_isr, IRQF_SHARED, out_unwind:
PMCRAID_DRIVER_NAME, &pinstance->hrrq_vector[0]); while (--i > 0)
pmcraid_isr_out: free_irq(pci_irq_vector(pdev, i), &pinstance->hrrq_vector[i]);
pci_free_irq_vectors(pdev);
return rc; return rc;
} }

View File

@ -628,7 +628,6 @@ struct pmcraid_interrupts {
/* ISR parameters LLD allocates (one for each MSI-X if enabled) vectors */ /* ISR parameters LLD allocates (one for each MSI-X if enabled) vectors */
struct pmcraid_isr_param { struct pmcraid_isr_param {
struct pmcraid_instance *drv_inst; struct pmcraid_instance *drv_inst;
u16 vector; /* allocated msi-x vector */
u8 hrrq_id; /* hrrq entry index */ u8 hrrq_id; /* hrrq entry index */
}; };

View File

@ -52,7 +52,7 @@ qedi_dbg_warn(struct qedi_dbg_ctx *qedi, const char *func, u32 line,
vaf.va = &va; vaf.va = &va;
if (!(qedi_dbg_log & QEDI_LOG_WARN)) if (!(qedi_dbg_log & QEDI_LOG_WARN))
return; goto ret;
if (likely(qedi) && likely(qedi->pdev)) if (likely(qedi) && likely(qedi->pdev))
pr_warn("[%s]:[%s:%d]:%d: %pV", dev_name(&qedi->pdev->dev), pr_warn("[%s]:[%s:%d]:%d: %pV", dev_name(&qedi->pdev->dev),
@ -60,6 +60,7 @@ qedi_dbg_warn(struct qedi_dbg_ctx *qedi, const char *func, u32 line,
else else
pr_warn("[0000:00:00.0]:[%s:%d]: %pV", nfunc, line, &vaf); pr_warn("[0000:00:00.0]:[%s:%d]: %pV", nfunc, line, &vaf);
ret:
va_end(va); va_end(va);
} }
@ -80,7 +81,7 @@ qedi_dbg_notice(struct qedi_dbg_ctx *qedi, const char *func, u32 line,
vaf.va = &va; vaf.va = &va;
if (!(qedi_dbg_log & QEDI_LOG_NOTICE)) if (!(qedi_dbg_log & QEDI_LOG_NOTICE))
return; goto ret;
if (likely(qedi) && likely(qedi->pdev)) if (likely(qedi) && likely(qedi->pdev))
pr_notice("[%s]:[%s:%d]:%d: %pV", pr_notice("[%s]:[%s:%d]:%d: %pV",
@ -89,6 +90,7 @@ qedi_dbg_notice(struct qedi_dbg_ctx *qedi, const char *func, u32 line,
else else
pr_notice("[0000:00:00.0]:[%s:%d]: %pV", nfunc, line, &vaf); pr_notice("[0000:00:00.0]:[%s:%d]: %pV", nfunc, line, &vaf);
ret:
va_end(va); va_end(va);
} }
@ -109,7 +111,7 @@ qedi_dbg_info(struct qedi_dbg_ctx *qedi, const char *func, u32 line,
vaf.va = &va; vaf.va = &va;
if (!(qedi_dbg_log & level)) if (!(qedi_dbg_log & level))
return; goto ret;
if (likely(qedi) && likely(qedi->pdev)) if (likely(qedi) && likely(qedi->pdev))
pr_info("[%s]:[%s:%d]:%d: %pV", dev_name(&qedi->pdev->dev), pr_info("[%s]:[%s:%d]:%d: %pV", dev_name(&qedi->pdev->dev),
@ -117,6 +119,7 @@ qedi_dbg_info(struct qedi_dbg_ctx *qedi, const char *func, u32 line,
else else
pr_info("[0000:00:00.0]:[%s:%d]: %pV", nfunc, line, &vaf); pr_info("[0000:00:00.0]:[%s:%d]: %pV", nfunc, line, &vaf);
ret:
va_end(va); va_end(va);
} }

View File

@ -48,6 +48,7 @@ struct scsi_host_template qedi_host_template = {
.name = "QLogic QEDI 25/40/100Gb iSCSI Initiator Driver", .name = "QLogic QEDI 25/40/100Gb iSCSI Initiator Driver",
.proc_name = QEDI_MODULE_NAME, .proc_name = QEDI_MODULE_NAME,
.queuecommand = iscsi_queuecommand, .queuecommand = iscsi_queuecommand,
.eh_timed_out = iscsi_eh_cmd_timed_out,
.eh_abort_handler = iscsi_eh_abort, .eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler = iscsi_eh_device_reset, .eh_device_reset_handler = iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_recover_target, .eh_target_reset_handler = iscsi_eh_recover_target,
@ -453,13 +454,9 @@ static int qedi_iscsi_update_conn(struct qedi_ctx *qedi,
if (rval) { if (rval) {
rval = -ENXIO; rval = -ENXIO;
QEDI_ERR(&qedi->dbg_ctx, "Could not update connection\n"); QEDI_ERR(&qedi->dbg_ctx, "Could not update connection\n");
goto update_conn_err;
} }
kfree(conn_info); kfree(conn_info);
rval = 0;
update_conn_err:
return rval; return rval;
} }

View File

@ -2248,7 +2248,7 @@ struct ct_fdmiv2_hba_attr {
uint32_t num_ports; uint32_t num_ports;
uint8_t fabric_name[WWN_SIZE]; uint8_t fabric_name[WWN_SIZE];
uint8_t bios_name[32]; uint8_t bios_name[32];
uint8_t vendor_indentifer[8]; uint8_t vendor_identifier[8];
} a; } a;
}; };
@ -2423,7 +2423,7 @@ struct ct_sns_req {
} rsnn_nn; } rsnn_nn;
struct { struct {
uint8_t hba_indentifier[8]; uint8_t hba_identifier[8];
} ghat; } ghat;
struct { struct {

View File

@ -1939,15 +1939,15 @@ qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha)
/* Vendor Identifier */ /* Vendor Identifier */
eiter = entries + size; eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_TYPE_VENDOR_IDENTIFIER); eiter->type = cpu_to_be16(FDMI_HBA_TYPE_VENDOR_IDENTIFIER);
snprintf(eiter->a.vendor_indentifer, sizeof(eiter->a.vendor_indentifer), snprintf(eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier),
"%s", "QLGC"); "%s", "QLGC");
alen = strlen(eiter->a.vendor_indentifer); alen = strlen(eiter->a.vendor_identifier);
alen += 4 - (alen & 3); alen += 4 - (alen & 3);
eiter->len = cpu_to_be16(4 + alen); eiter->len = cpu_to_be16(4 + alen);
size += 4 + alen; size += 4 + alen;
ql_dbg(ql_dbg_disc, vha, 0x20b1, ql_dbg(ql_dbg_disc, vha, 0x20b1,
"Vendor Identifier = %s.\n", eiter->a.vendor_indentifer); "Vendor Identifier = %s.\n", eiter->a.vendor_identifier);
/* Update MS request size. */ /* Update MS request size. */
qla2x00_update_ms_fdmi_iocb(vha, size + 16); qla2x00_update_ms_fdmi_iocb(vha, size + 16);

View File

@ -2997,14 +2997,14 @@ struct qla_init_msix_entry {
irq_handler_t handler; irq_handler_t handler;
}; };
static struct qla_init_msix_entry msix_entries[] = { static const struct qla_init_msix_entry msix_entries[] = {
{ "qla2xxx (default)", qla24xx_msix_default }, { "qla2xxx (default)", qla24xx_msix_default },
{ "qla2xxx (rsp_q)", qla24xx_msix_rsp_q }, { "qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
{ "qla2xxx (atio_q)", qla83xx_msix_atio_q }, { "qla2xxx (atio_q)", qla83xx_msix_atio_q },
{ "qla2xxx (qpair_multiq)", qla2xxx_msix_rsp_q }, { "qla2xxx (qpair_multiq)", qla2xxx_msix_rsp_q },
}; };
static struct qla_init_msix_entry qla82xx_msix_entries[] = { static const struct qla_init_msix_entry qla82xx_msix_entries[] = {
{ "qla2xxx (default)", qla82xx_msix_default }, { "qla2xxx (default)", qla82xx_msix_default },
{ "qla2xxx (rsp_q)", qla82xx_msix_rsp_q }, { "qla2xxx (rsp_q)", qla82xx_msix_rsp_q },
}; };
@ -3078,7 +3078,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
qentry->handle = rsp; qentry->handle = rsp;
rsp->msix = qentry; rsp->msix = qentry;
scnprintf(qentry->name, sizeof(qentry->name), scnprintf(qentry->name, sizeof(qentry->name),
msix_entries[i].name); "%s", msix_entries[i].name);
if (IS_P3P_TYPE(ha)) if (IS_P3P_TYPE(ha))
ret = request_irq(qentry->vector, ret = request_irq(qentry->vector,
qla82xx_msix_entries[i].handler, qla82xx_msix_entries[i].handler,
@ -3102,7 +3102,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
rsp->msix = qentry; rsp->msix = qentry;
qentry->handle = rsp; qentry->handle = rsp;
scnprintf(qentry->name, sizeof(qentry->name), scnprintf(qentry->name, sizeof(qentry->name),
msix_entries[QLA_ATIO_VECTOR].name); "%s", msix_entries[QLA_ATIO_VECTOR].name);
qentry->in_use = 1; qentry->in_use = 1;
ret = request_irq(qentry->vector, ret = request_irq(qentry->vector,
msix_entries[QLA_ATIO_VECTOR].handler, msix_entries[QLA_ATIO_VECTOR].handler,
@ -3271,7 +3271,7 @@ free_irqs:
int qla25xx_request_irq(struct qla_hw_data *ha, struct qla_qpair *qpair, int qla25xx_request_irq(struct qla_hw_data *ha, struct qla_qpair *qpair,
struct qla_msix_entry *msix, int vector_type) struct qla_msix_entry *msix, int vector_type)
{ {
struct qla_init_msix_entry *intr = &msix_entries[vector_type]; const struct qla_init_msix_entry *intr = &msix_entries[vector_type];
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
int ret; int ret;

View File

@ -262,6 +262,7 @@ struct scsi_host_template qla2xxx_driver_template = {
.name = QLA2XXX_DRIVER_NAME, .name = QLA2XXX_DRIVER_NAME,
.queuecommand = qla2xxx_queuecommand, .queuecommand = qla2xxx_queuecommand,
.eh_timed_out = fc_eh_timed_out,
.eh_abort_handler = qla2xxx_eh_abort, .eh_abort_handler = qla2xxx_eh_abort,
.eh_device_reset_handler = qla2xxx_eh_device_reset, .eh_device_reset_handler = qla2xxx_eh_device_reset,
.eh_target_reset_handler = qla2xxx_eh_target_reset, .eh_target_reset_handler = qla2xxx_eh_target_reset,

Some files were not shown because too many files have changed in this diff Show More