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:
commit
cdc194705d
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
...);
|
...);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
@ -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
|
@ -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 {
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue