SCSI misc on 20160315

This pull includes driver updates from the usual suspects (stex, hpsa,
 ncr5380, scsi_dh, qla2xxx, be2iscsi, hisi_sas, cxlflash, aacraid,
 mp3sas, megaraid_sas, ibmvscsi, ufs) plus an assortment of
 miscellaneous fixes.  The major user visible change of this pull is
 that we've moved from monotonically increasing host number to an ida
 allocated one (meaning the numbers get re-used) because someone
 managed to wrap the count in an iscsi system.  We don't believe there
 will be any adverse consequences of this.
 
 Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQEcBAABAgAGBQJW6I3XAAoJEDeqqVYsXL0MyHoH+wWPbgLhMwjLL2KXwOrx73i7
 HF3JttnYCbOGHlAz01mGnOdQF2bD9EqChQk1blsu0lVX0agbZ20CbXiEhwM4Iphn
 45fIKpVbTSEfTQOnPHs8gcVx6ToidHkpQ224wB9LPtkrQtEldmmPlqBNvpEg8m1s
 382YPZ7Nn1p9Ci92L9RpztHuC9luUnfndOAgIrtEWBKWkIPeSaJ9iElY5bOf+gJ/
 t8ft3SGcljj1i73z0LNEvoQyggUb0yEW9iyi72Cmn2DeGnKbKOWlP1oV77aq3MuO
 8TYxG6qaUn1zOoZDwOnl25MpT7FWuG1RvBcoCrOTPuoXGVgk9MAJi5w+YG/5LFk=
 =xX0G
 -----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 pull includes driver updates from the usual suspects (stex, hpsa,
  ncr5380, scsi_dh, qla2xxx, be2iscsi, hisi_sas, cxlflash, aacraid,
  mp3sas, megaraid_sas, ibmvscsi, ufs) plus an assortment of
  miscellaneous fixes.

  The major user visible change of this pull is that we've moved from
  monotonically increasing host number to an ida allocated one (meaning
  the numbers get re-used) because someone managed to wrap the count in
  an iscsi system.  We don't believe there will be any adverse
  consequences of this"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (230 commits)
  MAINTAINERS: use new email address for James Bottomley
  mpt3sas: Remove unnecessary synchronize_irq() before free_irq()
  sg: fix dxferp in from_to case
  cxlflash: Increase cmd_per_lun for better throughput
  cxlflash: Fix to avoid unnecessary scan with internal LUNs
  cxlflash: Reorder user context initialization
  cxlflash: Simplify attach path error cleanup
  cxlflash: Split out context initialization
  cxlflash: Unmap problem state area before detaching master context
  cxlflash: Simplify PCI registration
  scsi: storvsc: fix SRB_STATUS_ABORTED handling
  be2iscsi: set the boot_kset pointer to NULL in case of failure
  sd: Fix discard granularity when LBPRZ=1
  be2iscsi: Remove unnecessary synchronize_irq() before free_irq()
  scsi_sysfs: call 'device_add' after attaching device handler
  scsi_dh_emc: update 'access_state' field
  scsi_dh_rdac: update 'access_state' field
  scsi_dh_alua: update 'access_state' field
  scsi_dh_alua: use common definitions for ALUA state
  scsi: Add 'access_state' and 'preferred_path' attribute
  ...
This commit is contained in:
Linus Torvalds 2016-03-16 17:16:22 -07:00
commit cae8da047b
120 changed files with 9230 additions and 3218 deletions

View File

@ -5,6 +5,7 @@ The HiSilicon SAS controller supports SAS/SATA.
Main node required properties:
- compatible : value should be as follows:
(a) "hisilicon,hip05-sas-v1" for v1 hw in hip05 chipset
(b) "hisilicon,hip06-sas-v2" for v2 hw in hip06 chipset
- sas-addr : array of 8 bytes for host SAS address
- reg : Address and length of the SAS register
- hisilicon,sas-syscon: phandle of syscon used for sas control
@ -13,7 +14,7 @@ Main node required properties:
- ctrl-clock-ena-reg : offset to controller clock enable register in ctrl reg
- queue-count : number of delivery and completion queues in the controller
- phy-count : number of phys accessible by the controller
- interrupts : Interrupts for phys, completion queues, and fatal
- interrupts : For v1 hw: Interrupts for phys, completion queues, and fatal
sources; the interrupts are ordered in 3 groups, as follows:
- Phy interrupts
- Completion queue interrupts
@ -30,6 +31,24 @@ Main node required properties:
Fatal interrupts : the fatal interrupts are ordered as follows:
- ECC
- AXI bus
For v2 hw: Interrupts for phys, Sata, and completion queues;
the interrupts are ordered in 3 groups, as follows:
- Phy interrupts
- Sata interrupts
- Completion queue interrupts
Phy interrupts : Each controller has 2 phy interrupts:
- phy up/down
- channel interrupt
Sata interrupts : Each phy on the controller has 1 Sata
interrupt. The interrupts are ordered in increasing
order.
Completion queue interrupts : each completion queue has 1
interrupt source. The interrupts are ordered in
increasing order.
Optional main node properties:
- hip06-sas-v2-quirk-amt : when set, indicates that the v2 controller has the
"am-max-transmissions" limitation.
Example:
sas0: sas@c1000000 {

View File

@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
The driver is currently maintained by Kai Mäkisara (email
Kai.Makisara@kolumbus.fi)
Last modified: Sun Aug 29 18:25:47 2010 by kai.makisara
Last modified: Tue Feb 9 21:54:16 2016 by kai.makisara
BASICS
@ -408,10 +408,15 @@ MTSETPART Moves the tape to the partition given by the argument at the
specified by MTSEEK. MTSETPART is inactive unless
MT_ST_CAN_PARTITIONS set.
MTMKPART Formats the tape with one partition (argument zero) or two
partitions (the argument gives in megabytes the size of
partition 1 that is physically the first partition of the
tape). The drive has to support partitions with size specified
by the initiator. Inactive unless MT_ST_CAN_PARTITIONS set.
partitions (argument non-zero). If the argument is positive,
it specifies the size of partition 1 in megabytes. For DDS
drives and several early drives this is the physically first
partition of the tape. If the argument is negative, its absolute
value specifies the size of partition 0 in megabytes. This is
the physically first partition of many later drives, like the
LTO drives from LTO-5 upwards. The drive has to support partitions
with size specified by the initiator. Inactive unless
MT_ST_CAN_PARTITIONS set.
MTSETDRVBUFFER
Is used for several purposes. The command is obtained from count
with mask MT_SET_OPTIONS, the low order bits are used as argument.

View File

@ -5007,9 +5007,9 @@ F: Documentation/blockdev/cpqarray.txt
F: drivers/block/cpqarray.*
HEWLETT-PACKARD SMART ARRAY RAID DRIVER (hpsa)
M: Don Brace <don.brace@pmcs.com>
M: Don Brace <don.brace@microsemi.com>
L: iss_storagedev@hp.com
L: storagedev@pmcs.com
L: esc.storagedev@microsemi.com
L: linux-scsi@vger.kernel.org
S: Supported
F: Documentation/scsi/hpsa.txt
@ -6682,13 +6682,12 @@ S: Maintained
F: arch/arm/mach-lpc32xx/
LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
M: Nagalakshmi Nandigama <nagalakshmi.nandigama@avagotech.com>
M: Praveen Krishnamoorthy <praveen.krishnamoorthy@avagotech.com>
M: Sreekanth Reddy <sreekanth.reddy@avagotech.com>
M: Abhijit Mahajan <abhijit.mahajan@avagotech.com>
L: MPT-FusionLinux.pdl@avagotech.com
M: Sathya Prakash <sathya.prakash@broadcom.com>
M: Chaitra P B <chaitra.basappa@broadcom.com>
M: Suganath Prabu Subramani <suganath-prabu.subramani@broadcom.com>
L: MPT-FusionLinux.pdl@broadcom.com
L: linux-scsi@vger.kernel.org
W: http://www.lsilogic.com/support
W: http://www.avagotech.com/support/
S: Supported
F: drivers/message/fusion/
F: drivers/scsi/mpt2sas/
@ -9691,7 +9690,7 @@ F: drivers/scsi/sg.c
F: include/scsi/sg.h
SCSI SUBSYSTEM
M: "James E.J. Bottomley" <JBottomley@odin.com>
M: "James E.J. Bottomley" <jejb@linux.vnet.ibm.com>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git
M: "Martin K. Petersen" <martin.petersen@oracle.com>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git

View File

@ -1801,8 +1801,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->pcidev = pdev;
if (mpt_mapresources(ioc)) {
kfree(ioc);
return r;
goto out_free_ioc;
}
/*
@ -1871,9 +1870,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
if (!ioc->reset_work_q) {
printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
ioc->name);
pci_release_selected_regions(pdev, ioc->bars);
kfree(ioc);
return -ENOMEM;
r = -ENOMEM;
goto out_unmap_resources;
}
dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n",
@ -1995,16 +1993,27 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
spin_lock_init(&ioc->fw_event_lock);
snprintf(ioc->fw_event_q_name, MPT_KOBJ_NAME_LEN, "mpt/%d", ioc->id);
ioc->fw_event_q = create_singlethread_workqueue(ioc->fw_event_q_name);
if (!ioc->fw_event_q) {
printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
ioc->name);
r = -ENOMEM;
goto out_remove_ioc;
}
if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
CAN_SLEEP)) != 0){
printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n",
ioc->name, r);
destroy_workqueue(ioc->fw_event_q);
ioc->fw_event_q = NULL;
list_del(&ioc->list);
if (ioc->alt_ioc)
ioc->alt_ioc->alt_ioc = NULL;
iounmap(ioc->memmap);
if (pci_is_enabled(pdev))
pci_disable_device(pdev);
if (r != -5)
pci_release_selected_regions(pdev, ioc->bars);
@ -2012,7 +2021,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->reset_work_q = NULL;
kfree(ioc);
pci_set_drvdata(pdev, NULL);
return r;
}
@ -2040,6 +2048,24 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
msecs_to_jiffies(MPT_POLLING_INTERVAL));
return 0;
out_remove_ioc:
list_del(&ioc->list);
if (ioc->alt_ioc)
ioc->alt_ioc->alt_ioc = NULL;
destroy_workqueue(ioc->reset_work_q);
ioc->reset_work_q = NULL;
out_unmap_resources:
iounmap(ioc->memmap);
pci_disable_device(pdev);
pci_release_selected_regions(pdev, ioc->bars);
out_free_ioc:
kfree(ioc);
return r;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@ -6229,7 +6255,7 @@ mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc)
memcpy(ioc->board_assembly, pbuf->BoardAssembly, sizeof(ioc->board_assembly));
memcpy(ioc->board_tracer, pbuf->BoardTracerNumber, sizeof(ioc->board_tracer));
out:
out:
if (pbuf)
pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma);
@ -6848,6 +6874,7 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int sh
*size = y;
}
#ifdef CONFIG_PROC_FS
static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan)
{
char expVer[32];
@ -6879,6 +6906,7 @@ static void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int
seq_putc(m, '\n');
}
#endif
/**
* mpt_set_taskmgmt_in_progress_flag - set flags associated with task management

View File

@ -596,6 +596,7 @@ config XEN_SCSI_FRONTEND
config HYPERV_STORAGE
tristate "Microsoft Hyper-V virtual storage driver"
depends on SCSI && HYPERV
depends on m || SCSI_FC_ATTRS != m
default HYPERV
help
Select this option to enable the Hyper-V virtual storage driver.

View File

@ -760,7 +760,7 @@ static struct scsi_cmnd *dequeue_next_cmd(struct Scsi_Host *instance)
struct NCR5380_cmd *ncmd;
struct scsi_cmnd *cmd;
if (list_empty(&hostdata->autosense)) {
if (hostdata->sensing || list_empty(&hostdata->autosense)) {
list_for_each_entry(ncmd, &hostdata->unissued, list) {
cmd = NCR5380_to_scmd(ncmd);
dsprintk(NDEBUG_QUEUES, instance, "dequeue: cmd=%p target=%d busy=0x%02x lun=%llu\n",
@ -793,7 +793,7 @@ static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
struct NCR5380_hostdata *hostdata = shost_priv(instance);
struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
if (hostdata->sensing) {
if (hostdata->sensing == cmd) {
scsi_eh_restore_cmnd(cmd, &hostdata->ses);
list_add(&ncmd->list, &hostdata->autosense);
hostdata->sensing = NULL;
@ -815,15 +815,17 @@ static void NCR5380_main(struct work_struct *work)
struct NCR5380_hostdata *hostdata =
container_of(work, struct NCR5380_hostdata, main_task);
struct Scsi_Host *instance = hostdata->host;
struct scsi_cmnd *cmd;
int done;
do {
done = 1;
spin_lock_irq(&hostdata->lock);
while (!hostdata->connected &&
(cmd = dequeue_next_cmd(instance))) {
while (!hostdata->connected && !hostdata->selecting) {
struct scsi_cmnd *cmd = dequeue_next_cmd(instance);
if (!cmd)
break;
dsprintk(NDEBUG_MAIN, instance, "main: dequeued %p\n", cmd);
@ -840,8 +842,7 @@ static void NCR5380_main(struct work_struct *work)
* entire unit.
*/
cmd = NCR5380_select(instance, cmd);
if (!cmd) {
if (!NCR5380_select(instance, cmd)) {
dsprintk(NDEBUG_MAIN, instance, "main: select complete\n");
} else {
dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance,
@ -1056,6 +1057,11 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
/* Reselection interrupt */
goto out;
}
if (!hostdata->selecting) {
/* Command was aborted */
NCR5380_write(MODE_REG, MR_BASE);
goto out;
}
if (err < 0) {
NCR5380_write(MODE_REG, MR_BASE);
shost_printk(KERN_ERR, instance,
@ -1759,9 +1765,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
unsigned char msgout = NOP;
int sink = 0;
int len;
#if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL)
int transfersize;
#endif
unsigned char *data;
unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
struct scsi_cmnd *cmd;
@ -1798,6 +1802,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
do_abort(instance);
cmd->result = DID_ERROR << 16;
complete_cmd(instance, cmd);
hostdata->connected = NULL;
return;
#endif
case PHASE_DATAIN:
@ -1847,20 +1852,23 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
sink = 1;
do_abort(instance);
cmd->result = DID_ERROR << 16;
complete_cmd(instance, cmd);
/* XXX - need to source or sink data here, as appropriate */
} else
cmd->SCp.this_residual -= transfersize - len;
} else
#endif /* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */
{
spin_unlock_irq(&hostdata->lock);
NCR5380_transfer_pio(instance, &phase,
(int *)&cmd->SCp.this_residual,
/* Break up transfer into 3 ms chunks,
* presuming 6 accesses per handshake.
*/
transfersize = min((unsigned long)cmd->SCp.this_residual,
hostdata->accesses_per_ms / 2);
len = transfersize;
NCR5380_transfer_pio(instance, &phase, &len,
(unsigned char **)&cmd->SCp.ptr);
spin_lock_irq(&hostdata->lock);
cmd->SCp.this_residual -= transfersize - len;
}
break;
return;
case PHASE_MSGIN:
len = 1;
data = &tmp;
@ -2292,14 +2300,17 @@ static bool list_del_cmd(struct list_head *haystack,
* [disconnected -> connected ->]...
* [autosense -> connected ->] done
*
* If cmd is unissued then just remove it.
* If cmd is disconnected, try to select the target.
* If cmd is connected, try to send an abort message.
* If cmd is waiting for autosense, give it a chance to complete but check
* that it isn't left connected.
* If cmd was not found at all then presumably it has already been completed,
* in which case return SUCCESS to try to avoid further EH measures.
*
* If the command has not completed yet, we must not fail to find it.
* We have no option but to forget the aborted command (even if it still
* lacks sense data). The mid-layer may re-issue a command that is in error
* recovery (see scsi_send_eh_cmnd), but the logic and data structures in
* this driver are such that a command can appear on one queue only.
*
* The lock protects driver data structures, but EH handlers also use it
* to serialize their own execution and prevent their own re-entry.
*/
static int NCR5380_abort(struct scsi_cmnd *cmd)
@ -2322,6 +2333,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd)
"abort: removed %p from issue queue\n", cmd);
cmd->result = DID_ABORT << 16;
cmd->scsi_done(cmd); /* No tag or busy flag to worry about */
goto out;
}
if (hostdata->selecting == cmd) {
@ -2336,19 +2348,21 @@ static int NCR5380_abort(struct scsi_cmnd *cmd)
if (list_del_cmd(&hostdata->disconnected, cmd)) {
dsprintk(NDEBUG_ABORT, instance,
"abort: removed %p from disconnected list\n", cmd);
cmd->result = DID_ERROR << 16;
if (!hostdata->connected)
NCR5380_select(instance, cmd);
if (hostdata->connected != cmd) {
complete_cmd(instance, cmd);
result = FAILED;
goto out;
}
/* Can't call NCR5380_select() and send ABORT because that
* means releasing the lock. Need a bus reset.
*/
set_host_byte(cmd, DID_ERROR);
complete_cmd(instance, cmd);
result = FAILED;
goto out;
}
if (hostdata->connected == cmd) {
dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd);
hostdata->connected = NULL;
#ifdef REAL_DMA
hostdata->dma_len = 0;
#endif
if (do_abort(instance)) {
set_host_byte(cmd, DID_ERROR);
complete_cmd(instance, cmd);
@ -2356,48 +2370,14 @@ static int NCR5380_abort(struct scsi_cmnd *cmd)
goto out;
}
set_host_byte(cmd, DID_ABORT);
#ifdef REAL_DMA
hostdata->dma_len = 0;
#endif
if (cmd->cmnd[0] == REQUEST_SENSE)
complete_cmd(instance, cmd);
else {
struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
/* Perform autosense for this command */
list_add(&ncmd->list, &hostdata->autosense);
}
complete_cmd(instance, cmd);
goto out;
}
if (list_find_cmd(&hostdata->autosense, cmd)) {
if (list_del_cmd(&hostdata->autosense, cmd)) {
dsprintk(NDEBUG_ABORT, instance,
"abort: found %p on sense queue\n", cmd);
spin_unlock_irqrestore(&hostdata->lock, flags);
queue_work(hostdata->work_q, &hostdata->main_task);
msleep(1000);
spin_lock_irqsave(&hostdata->lock, flags);
if (list_del_cmd(&hostdata->autosense, cmd)) {
dsprintk(NDEBUG_ABORT, instance,
"abort: removed %p from sense queue\n", cmd);
set_host_byte(cmd, DID_ABORT);
complete_cmd(instance, cmd);
goto out;
}
}
if (hostdata->connected == cmd) {
dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd);
hostdata->connected = NULL;
if (do_abort(instance)) {
set_host_byte(cmd, DID_ERROR);
complete_cmd(instance, cmd);
result = FAILED;
goto out;
}
set_host_byte(cmd, DID_ABORT);
#ifdef REAL_DMA
hostdata->dma_len = 0;
#endif
"abort: removed %p from sense queue\n", cmd);
set_host_byte(cmd, DID_ERROR);
complete_cmd(instance, cmd);
}
@ -2450,7 +2430,16 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
* commands!
*/
hostdata->selecting = NULL;
if (list_del_cmd(&hostdata->unissued, cmd)) {
cmd->result = DID_RESET << 16;
cmd->scsi_done(cmd);
}
if (hostdata->selecting) {
hostdata->selecting->result = DID_RESET << 16;
complete_cmd(instance, hostdata->selecting);
hostdata->selecting = NULL;
}
list_for_each_entry(ncmd, &hostdata->disconnected, list) {
struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
@ -2458,6 +2447,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
set_host_byte(cmd, DID_RESET);
cmd->scsi_done(cmd);
}
INIT_LIST_HEAD(&hostdata->disconnected);
list_for_each_entry(ncmd, &hostdata->autosense, list) {
struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
@ -2465,6 +2455,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
set_host_byte(cmd, DID_RESET);
cmd->scsi_done(cmd);
}
INIT_LIST_HEAD(&hostdata->autosense);
if (hostdata->connected) {
set_host_byte(hostdata->connected, DID_RESET);
@ -2472,12 +2463,6 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
hostdata->connected = NULL;
}
if (hostdata->sensing) {
set_host_byte(hostdata->connected, DID_RESET);
complete_cmd(instance, hostdata->sensing);
hostdata->sensing = NULL;
}
for (i = 0; i < 8; ++i)
hostdata->busy[i] = 0;
#ifdef REAL_DMA

View File

@ -323,7 +323,6 @@ static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
if (unlikely(!scsicmd || !scsicmd->scsi_done)) {
dprintk((KERN_WARNING "aac_valid_context: scsi command corrupt\n"));
aac_fib_complete(fibptr);
aac_fib_free(fibptr);
return 0;
}
scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
@ -331,7 +330,6 @@ static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
if (unlikely(!device || !scsi_device_online(device))) {
dprintk((KERN_WARNING "aac_valid_context: scsi device corrupt\n"));
aac_fib_complete(fibptr);
aac_fib_free(fibptr);
return 0;
}
return 1;
@ -541,7 +539,6 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
aac_fib_complete(fibptr);
aac_fib_free(fibptr);
scsicmd->scsi_done(scsicmd);
}
@ -557,7 +554,8 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd)
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
if (!(cmd_fibcontext = aac_fib_alloc(dev)))
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
if (!cmd_fibcontext)
return -ENOMEM;
aac_fib_init(cmd_fibcontext);
@ -586,7 +584,6 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd)
printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status);
aac_fib_complete(cmd_fibcontext);
aac_fib_free(cmd_fibcontext);
return -1;
}
@ -1024,7 +1021,6 @@ static void get_container_serial_callback(void *context, struct fib * fibptr)
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
aac_fib_complete(fibptr);
aac_fib_free(fibptr);
scsicmd->scsi_done(scsicmd);
}
@ -1040,7 +1036,8 @@ static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
if (!(cmd_fibcontext = aac_fib_alloc(dev)))
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
if (!cmd_fibcontext)
return -ENOMEM;
aac_fib_init(cmd_fibcontext);
@ -1068,7 +1065,6 @@ static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
printk(KERN_WARNING "aac_get_container_serial: aac_fib_send failed with status: %d.\n", status);
aac_fib_complete(cmd_fibcontext);
aac_fib_free(cmd_fibcontext);
return -1;
}
@ -1869,7 +1865,6 @@ static void io_callback(void *context, struct fib * fibptr)
break;
}
aac_fib_complete(fibptr);
aac_fib_free(fibptr);
scsicmd->scsi_done(scsicmd);
}
@ -1954,7 +1949,8 @@ static int aac_read(struct scsi_cmnd * scsicmd)
/*
* Alocate and initialize a Fib
*/
if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
if (!cmd_fibcontext) {
printk(KERN_WARNING "aac_read: fib allocation failed\n");
return -1;
}
@ -2051,7 +2047,8 @@ static int aac_write(struct scsi_cmnd * scsicmd)
/*
* Allocate and initialize a Fib then setup a BlockWrite command
*/
if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
if (!cmd_fibcontext) {
/* FIB temporarily unavailable,not catastrophic failure */
/* scsicmd->result = DID_ERROR << 16;
@ -2285,7 +2282,7 @@ static int aac_start_stop(struct scsi_cmnd *scsicmd)
/*
* Allocate and initialize a Fib
*/
cmd_fibcontext = aac_fib_alloc(aac);
cmd_fibcontext = aac_fib_alloc_tag(aac, scsicmd);
if (!cmd_fibcontext)
return SCSI_MLQUEUE_HOST_BUSY;
@ -3157,7 +3154,6 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
scsicmd->result |= le32_to_cpu(srbreply->scsi_status);
aac_fib_complete(fibptr);
aac_fib_free(fibptr);
scsicmd->scsi_done(scsicmd);
}
@ -3187,9 +3183,10 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
/*
* Allocate and initialize a Fib then setup a BlockWrite command
*/
if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
if (!cmd_fibcontext)
return -1;
}
status = aac_adapter_scsi(cmd_fibcontext, scsicmd);
/*

View File

@ -62,7 +62,7 @@ enum {
#define PMC_GLOBAL_INT_BIT0 0x00000001
#ifndef AAC_DRIVER_BUILD
# define AAC_DRIVER_BUILD 41010
# define AAC_DRIVER_BUILD 41052
# define AAC_DRIVER_BRANCH "-ms"
#endif
#define MAXIMUM_NUM_CONTAINERS 32
@ -94,6 +94,13 @@ enum {
#define aac_phys_to_logical(x) ((x)+1)
#define aac_logical_to_phys(x) ((x)?(x)-1:0)
/*
* These macros are for keeping track of
* character device state.
*/
#define AAC_CHARDEV_UNREGISTERED (-1)
#define AAC_CHARDEV_NEEDS_REINIT (-2)
/* #define AAC_DETAILED_STATUS_INFO */
struct diskparm
@ -944,6 +951,7 @@ struct fib {
*/
struct list_head fiblink;
void *data;
u32 vector_no;
struct hw_fib *hw_fib_va; /* Actual shared object */
dma_addr_t hw_fib_pa; /* physical address of hw_fib*/
};
@ -1123,6 +1131,7 @@ struct aac_dev
struct fib *free_fib;
spinlock_t fib_lock;
struct mutex ioctl_mutex;
struct aac_queue_block *queues;
/*
* The user API will use an IOCTL to register itself to receive
@ -1234,6 +1243,7 @@ struct aac_dev
struct msix_entry msixentry[AAC_MAX_MSIX];
struct aac_msix_ctx aac_msix[AAC_MAX_MSIX]; /* context */
u8 adapter_shutdown;
u32 handle_pci_error;
};
#define aac_adapter_interrupt(dev) \
@ -2113,7 +2123,9 @@ static inline unsigned int cap_to_cyls(sector_t capacity, unsigned divisor)
int aac_acquire_irq(struct aac_dev *dev);
void aac_free_irq(struct aac_dev *dev);
const char *aac_driverinfo(struct Scsi_Host *);
void aac_fib_vector_assign(struct aac_dev *dev);
struct fib *aac_fib_alloc(struct aac_dev *dev);
struct fib *aac_fib_alloc_tag(struct aac_dev *dev, struct scsi_cmnd *scmd);
int aac_fib_setup(struct aac_dev *dev);
void aac_fib_map_free(struct aac_dev *dev);
void aac_fib_free(struct fib * context);

View File

@ -855,13 +855,20 @@ int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg)
{
int status;
mutex_lock(&dev->ioctl_mutex);
if (dev->adapter_shutdown) {
status = -EACCES;
goto cleanup;
}
/*
* HBA gets first crack
*/
status = aac_dev_ioctl(dev, cmd, arg);
if (status != -ENOTTY)
return status;
goto cleanup;
switch (cmd) {
case FSACTL_MINIPORT_REV_CHECK:
@ -890,6 +897,10 @@ int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg)
status = -ENOTTY;
break;
}
cleanup:
mutex_unlock(&dev->ioctl_mutex);
return status;
}

View File

@ -212,8 +212,11 @@ int aac_send_shutdown(struct aac_dev * dev)
return -ENOMEM;
aac_fib_init(fibctx);
cmd = (struct aac_close *) fib_data(fibctx);
mutex_lock(&dev->ioctl_mutex);
dev->adapter_shutdown = 1;
mutex_unlock(&dev->ioctl_mutex);
cmd = (struct aac_close *) fib_data(fibctx);
cmd->command = cpu_to_le32(VM_CloseAll);
cmd->cid = cpu_to_le32(0xfffffffe);
@ -229,7 +232,6 @@ int aac_send_shutdown(struct aac_dev * dev)
/* FIB should be freed only after getting the response from the F/W */
if (status != -ERESTARTSYS)
aac_fib_free(fibctx);
dev->adapter_shutdown = 1;
if ((dev->pdev->device == PMC_DEVICE_S7 ||
dev->pdev->device == PMC_DEVICE_S8 ||
dev->pdev->device == PMC_DEVICE_S9) &&

View File

@ -83,13 +83,38 @@ static int fib_map_alloc(struct aac_dev *dev)
void aac_fib_map_free(struct aac_dev *dev)
{
pci_free_consistent(dev->pdev,
dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB),
dev->hw_fib_va, dev->hw_fib_pa);
if (dev->hw_fib_va && dev->max_fib_size) {
pci_free_consistent(dev->pdev,
(dev->max_fib_size *
(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)),
dev->hw_fib_va, dev->hw_fib_pa);
}
dev->hw_fib_va = NULL;
dev->hw_fib_pa = 0;
}
void aac_fib_vector_assign(struct aac_dev *dev)
{
u32 i = 0;
u32 vector = 1;
struct fib *fibptr = NULL;
for (i = 0, fibptr = &dev->fibs[i];
i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB);
i++, fibptr++) {
if ((dev->max_msix == 1) ||
(i > ((dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB - 1)
- dev->vector_cap))) {
fibptr->vector_no = 0;
} else {
fibptr->vector_no = vector;
vector++;
if (vector == dev->max_msix)
vector = 1;
}
}
}
/**
* aac_fib_setup - setup the fibs
* @dev: Adapter to set up
@ -137,6 +162,7 @@ int aac_fib_setup(struct aac_dev * dev)
i++, fibptr++)
{
fibptr->flags = 0;
fibptr->size = sizeof(struct fib);
fibptr->dev = dev;
fibptr->hw_fib_va = hw_fib;
fibptr->data = (void *) fibptr->hw_fib_va->data;
@ -151,17 +177,48 @@ int aac_fib_setup(struct aac_dev * dev)
hw_fib_pa = hw_fib_pa +
dev->max_fib_size + sizeof(struct aac_fib_xporthdr);
}
/*
*Assign vector numbers to fibs
*/
aac_fib_vector_assign(dev);
/*
* Add the fib chain to the free list
*/
dev->fibs[dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB - 1].next = NULL;
/*
* Enable this to debug out of queue space
*/
dev->free_fib = &dev->fibs[0];
* Set 8 fibs aside for management tools
*/
dev->free_fib = &dev->fibs[dev->scsi_host_ptr->can_queue];
return 0;
}
/**
* aac_fib_alloc_tag-allocate a fib using tags
* @dev: Adapter to allocate the fib for
*
* Allocate a fib from the adapter fib pool using tags
* from the blk layer.
*/
struct fib *aac_fib_alloc_tag(struct aac_dev *dev, struct scsi_cmnd *scmd)
{
struct fib *fibptr;
fibptr = &dev->fibs[scmd->request->tag];
/*
* Null out fields that depend on being zero at the start of
* each I/O
*/
fibptr->hw_fib_va->header.XferState = 0;
fibptr->type = FSAFS_NTC_FIB_CONTEXT;
fibptr->callback_data = NULL;
fibptr->callback = NULL;
return fibptr;
}
/**
* aac_fib_alloc - allocate a fib
* @dev: Adapter to allocate the fib for

View File

@ -394,7 +394,6 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index,
fib->callback(fib->callback_data, fib);
} else {
aac_fib_complete(fib);
aac_fib_free(fib);
}
} else {
unsigned long flagv;
@ -416,7 +415,6 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index,
fib->done = 0;
spin_unlock_irqrestore(&fib->event_lock, flagv);
aac_fib_complete(fib);
aac_fib_free(fib);
}
}

View File

@ -38,6 +38,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <linux/aer.h>
#include <linux/pci-aspm.h>
#include <linux/slab.h>
#include <linux/mutex.h>
@ -79,7 +80,7 @@ MODULE_VERSION(AAC_DRIVER_FULL_VERSION);
static DEFINE_MUTEX(aac_mutex);
static LIST_HEAD(aac_devices);
static int aac_cfg_major = -1;
static int aac_cfg_major = AAC_CHARDEV_UNREGISTERED;
char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
/*
@ -454,6 +455,8 @@ static int aac_slave_configure(struct scsi_device *sdev)
} else
scsi_change_queue_depth(sdev, 1);
sdev->tagged_supported = 1;
return 0;
}
@ -700,23 +703,18 @@ static int aac_cfg_open(struct inode *inode, struct file *file)
static long aac_cfg_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
int ret;
struct aac_dev *aac;
aac = (struct aac_dev *)file->private_data;
if (!capable(CAP_SYS_RAWIO) || aac->adapter_shutdown)
return -EPERM;
mutex_lock(&aac_mutex);
ret = aac_do_ioctl(file->private_data, cmd, (void __user *)arg);
mutex_unlock(&aac_mutex);
struct aac_dev *aac = (struct aac_dev *)file->private_data;
return ret;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
return aac_do_ioctl(aac, cmd, (void __user *)arg);
}
#ifdef CONFIG_COMPAT
static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long arg)
{
long ret;
mutex_lock(&aac_mutex);
switch (cmd) {
case FSACTL_MINIPORT_REV_CHECK:
case FSACTL_SENDFIB:
@ -750,7 +748,6 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
ret = -ENOIOCTLCMD;
break;
}
mutex_unlock(&aac_mutex);
return ret;
}
@ -1075,6 +1072,8 @@ static void __aac_shutdown(struct aac_dev * aac)
int i;
int cpu;
aac_send_shutdown(aac);
if (aac->aif_thread) {
int i;
/* Clear out events first */
@ -1086,7 +1085,6 @@ static void __aac_shutdown(struct aac_dev * aac)
}
kthread_stop(aac->thread);
}
aac_send_shutdown(aac);
aac_adapter_disable_int(aac);
cpu = cpumask_first(cpu_online_mask);
if (aac->pdev->device == PMC_DEVICE_S6 ||
@ -1120,6 +1118,13 @@ static void __aac_shutdown(struct aac_dev * aac)
else if (aac->max_msix > 1)
pci_disable_msix(aac->pdev);
}
static void aac_init_char(void)
{
aac_cfg_major = register_chrdev(0, "aac", &aac_cfg_fops);
if (aac_cfg_major < 0) {
pr_err("aacraid: unable to register \"aac\" device.\n");
}
}
static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
@ -1132,6 +1137,12 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
u64 dmamask;
extern int aac_sync_mode;
/*
* Only series 7 needs freset.
*/
if (pdev->device == PMC_DEVICE_S7)
pdev->needs_freset = 1;
list_for_each_entry(aac, &aac_devices, entry) {
if (aac->id > unique_id)
break;
@ -1171,6 +1182,9 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
shost->max_cmd_len = 16;
shost->use_cmd_list = 1;
if (aac_cfg_major == AAC_CHARDEV_NEEDS_REINIT)
aac_init_char();
aac = (struct aac_dev *)shost->hostdata;
aac->base_start = pci_resource_start(pdev, 0);
aac->scsi_host_ptr = shost;
@ -1185,6 +1199,7 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_free_host;
spin_lock_init(&aac->fib_lock);
mutex_init(&aac->ioctl_mutex);
/*
* Map in the registers from the adapter.
*/
@ -1296,6 +1311,9 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_deinit;
scsi_scan_host(shost);
pci_enable_pcie_error_reporting(pdev);
pci_save_state(pdev);
return 0;
out_deinit:
@ -1317,7 +1335,6 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
return error;
}
#if (defined(CONFIG_PM))
static void aac_release_resources(struct aac_dev *aac)
{
int i;
@ -1404,14 +1421,26 @@ static int aac_acquire_resources(struct aac_dev *dev)
aac_adapter_enable_int(dev);
if (!dev->sync_mode)
/*max msix may change after EEH
* Re-assign vectors to fibs
*/
aac_fib_vector_assign(dev);
if (!dev->sync_mode) {
/* After EEH recovery or suspend resume, max_msix count
* may change, therfore updating in init as well.
*/
aac_adapter_start(dev);
dev->init->Sa_MSIXVectors = cpu_to_le32(dev->max_msix);
}
return 0;
error_iounmap:
return -1;
}
#if (defined(CONFIG_PM))
static int aac_suspend(struct pci_dev *pdev, pm_message_t state)
{
@ -1495,10 +1524,142 @@ static void aac_remove_one(struct pci_dev *pdev)
pci_disable_device(pdev);
if (list_empty(&aac_devices)) {
unregister_chrdev(aac_cfg_major, "aac");
aac_cfg_major = -1;
aac_cfg_major = AAC_CHARDEV_NEEDS_REINIT;
}
}
static void aac_flush_ios(struct aac_dev *aac)
{
int i;
struct scsi_cmnd *cmd;
for (i = 0; i < aac->scsi_host_ptr->can_queue; i++) {
cmd = (struct scsi_cmnd *)aac->fibs[i].callback_data;
if (cmd && (cmd->SCp.phase == AAC_OWNER_FIRMWARE)) {
scsi_dma_unmap(cmd);
if (aac->handle_pci_error)
cmd->result = DID_NO_CONNECT << 16;
else
cmd->result = DID_RESET << 16;
cmd->scsi_done(cmd);
}
}
}
static pci_ers_result_t aac_pci_error_detected(struct pci_dev *pdev,
enum pci_channel_state error)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct aac_dev *aac = shost_priv(shost);
dev_err(&pdev->dev, "aacraid: PCI error detected %x\n", error);
switch (error) {
case pci_channel_io_normal:
return PCI_ERS_RESULT_CAN_RECOVER;
case pci_channel_io_frozen:
aac->handle_pci_error = 1;
scsi_block_requests(aac->scsi_host_ptr);
aac_flush_ios(aac);
aac_release_resources(aac);
pci_disable_pcie_error_reporting(pdev);
aac_adapter_ioremap(aac, 0);
return PCI_ERS_RESULT_NEED_RESET;
case pci_channel_io_perm_failure:
aac->handle_pci_error = 1;
aac_flush_ios(aac);
return PCI_ERS_RESULT_DISCONNECT;
}
return PCI_ERS_RESULT_NEED_RESET;
}
static pci_ers_result_t aac_pci_mmio_enabled(struct pci_dev *pdev)
{
dev_err(&pdev->dev, "aacraid: PCI error - mmio enabled\n");
return PCI_ERS_RESULT_NEED_RESET;
}
static pci_ers_result_t aac_pci_slot_reset(struct pci_dev *pdev)
{
dev_err(&pdev->dev, "aacraid: PCI error - slot reset\n");
pci_restore_state(pdev);
if (pci_enable_device(pdev)) {
dev_warn(&pdev->dev,
"aacraid: failed to enable slave\n");
goto fail_device;
}
pci_set_master(pdev);
if (pci_enable_device_mem(pdev)) {
dev_err(&pdev->dev, "pci_enable_device_mem failed\n");
goto fail_device;
}
return PCI_ERS_RESULT_RECOVERED;
fail_device:
dev_err(&pdev->dev, "aacraid: PCI error - slot reset failed\n");
return PCI_ERS_RESULT_DISCONNECT;
}
static void aac_pci_resume(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct scsi_device *sdev = NULL;
struct aac_dev *aac = (struct aac_dev *)shost_priv(shost);
pci_cleanup_aer_uncorrect_error_status(pdev);
if (aac_adapter_ioremap(aac, aac->base_size)) {
dev_err(&pdev->dev, "aacraid: ioremap failed\n");
/* remap failed, go back ... */
aac->comm_interface = AAC_COMM_PRODUCER;
if (aac_adapter_ioremap(aac, AAC_MIN_FOOTPRINT_SIZE)) {
dev_warn(&pdev->dev,
"aacraid: unable to map adapter.\n");
return;
}
}
msleep(10000);
aac_acquire_resources(aac);
/*
* reset this flag to unblock ioctl() as it was set
* at aac_send_shutdown() to block ioctls from upperlayer
*/
aac->adapter_shutdown = 0;
aac->handle_pci_error = 0;
shost_for_each_device(sdev, shost)
if (sdev->sdev_state == SDEV_OFFLINE)
sdev->sdev_state = SDEV_RUNNING;
scsi_unblock_requests(aac->scsi_host_ptr);
scsi_scan_host(aac->scsi_host_ptr);
pci_save_state(pdev);
dev_err(&pdev->dev, "aacraid: PCI error - resume\n");
}
static struct pci_error_handlers aac_pci_err_handler = {
.error_detected = aac_pci_error_detected,
.mmio_enabled = aac_pci_mmio_enabled,
.slot_reset = aac_pci_slot_reset,
.resume = aac_pci_resume,
};
static struct pci_driver aac_pci_driver = {
.name = AAC_DRIVERNAME,
.id_table = aac_pci_tbl,
@ -1509,6 +1670,7 @@ static struct pci_driver aac_pci_driver = {
.resume = aac_resume,
#endif
.shutdown = aac_shutdown,
.err_handler = &aac_pci_err_handler,
};
static int __init aac_init(void)
@ -1522,11 +1684,8 @@ static int __init aac_init(void)
if (error < 0)
return error;
aac_cfg_major = register_chrdev( 0, "aac", &aac_cfg_fops);
if (aac_cfg_major < 0) {
printk(KERN_WARNING
"aacraid: unable to register \"aac\" device.\n");
}
aac_init_char();
return 0;
}

View File

@ -156,8 +156,8 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
break;
if (dev->msi_enabled && dev->max_msix > 1)
atomic_dec(&dev->rrq_outstanding[vector_no]);
aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL);
dev->host_rrq[index++] = 0;
aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL);
if (index == (vector_no + 1) * dev->vector_cap)
index = vector_no * dev->vector_cap;
dev->host_rrq_idx[vector_no] = index;
@ -452,36 +452,20 @@ static int aac_src_deliver_message(struct fib *fib)
#endif
u16 hdr_size = le16_to_cpu(fib->hw_fib_va->header.Size);
u16 vector_no;
atomic_inc(&q->numpending);
if (dev->msi_enabled && fib->hw_fib_va->header.Command != AifRequest &&
dev->max_msix > 1) {
u_int16_t vector_no, first_choice = 0xffff;
vector_no = dev->fibs_pushed_no % dev->max_msix;
do {
vector_no += 1;
if (vector_no == dev->max_msix)
vector_no = 1;
if (atomic_read(&dev->rrq_outstanding[vector_no]) <
dev->vector_cap)
break;
if (0xffff == first_choice)
first_choice = vector_no;
else if (vector_no == first_choice)
break;
} while (1);
if (vector_no == first_choice)
vector_no = 0;
atomic_inc(&dev->rrq_outstanding[vector_no]);
if (dev->fibs_pushed_no == 0xffffffff)
dev->fibs_pushed_no = 0;
else
dev->fibs_pushed_no++;
vector_no = fib->vector_no;
fib->hw_fib_va->header.Handle += (vector_no << 16);
} else {
vector_no = 0;
}
atomic_inc(&dev->rrq_outstanding[vector_no]);
if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) {
/* Calculate the amount to the fibsize bits */
fibsize = (hdr_size + 127) / 128 - 1;

View File

@ -403,6 +403,9 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
cptr = kmalloc(sizeof(*cptr) * sg_count, GFP_KERNEL | GFP_DMA);
if (!cptr)
return SCSI_MLQUEUE_HOST_BUSY;
} else {
sg_count = 0;
cptr = NULL;
}
/* Use the outgoing mailboxes in a round-robin fashion, because this

View File

@ -1336,6 +1336,7 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev,
case AHC_DEV_Q_TAGGED:
scsi_change_queue_depth(sdev,
dev->openings + dev->active);
break;
default:
/*
* We allow the OS to queue 2 untagged transactions to

View File

@ -677,7 +677,8 @@ int round_period(unsigned int period)
* Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting
*/
static
unsigned char calc_sync_xfer(unsigned int period, unsigned int offset)
unsigned char __maybe_unused calc_sync_xfer(unsigned int period,
unsigned int offset)
{
return sync_xfer_table[round_period(period)].reg_value |
((offset < SDTR_SIZE) ? offset : SDTR_SIZE);

View File

@ -98,6 +98,7 @@ static int level_mask = LOG_ERROR;
module_param(level_mask, int, 0644);
#ifndef MODULE
static int __init fas216_log_setup(char *str)
{
char *s;
@ -138,6 +139,7 @@ static int __init fas216_log_setup(char *str)
}
__setup("fas216_logging=", fas216_log_setup);
#endif
static inline unsigned char fas216_readb(FAS216_Info *info, unsigned int reg)
{

View File

@ -862,7 +862,7 @@ static struct scsi_cmnd *dequeue_next_cmd(struct Scsi_Host *instance)
struct NCR5380_cmd *ncmd;
struct scsi_cmnd *cmd;
if (list_empty(&hostdata->autosense)) {
if (hostdata->sensing || list_empty(&hostdata->autosense)) {
list_for_each_entry(ncmd, &hostdata->unissued, list) {
cmd = NCR5380_to_scmd(ncmd);
dsprintk(NDEBUG_QUEUES, instance, "dequeue: cmd=%p target=%d busy=0x%02x lun=%llu\n",
@ -901,7 +901,7 @@ static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
struct NCR5380_hostdata *hostdata = shost_priv(instance);
struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
if (hostdata->sensing) {
if (hostdata->sensing == cmd) {
scsi_eh_restore_cmnd(cmd, &hostdata->ses);
list_add(&ncmd->list, &hostdata->autosense);
hostdata->sensing = NULL;
@ -923,7 +923,6 @@ static void NCR5380_main(struct work_struct *work)
struct NCR5380_hostdata *hostdata =
container_of(work, struct NCR5380_hostdata, main_task);
struct Scsi_Host *instance = hostdata->host;
struct scsi_cmnd *cmd;
int done;
/*
@ -936,8 +935,11 @@ static void NCR5380_main(struct work_struct *work)
done = 1;
spin_lock_irq(&hostdata->lock);
while (!hostdata->connected &&
(cmd = dequeue_next_cmd(instance))) {
while (!hostdata->connected && !hostdata->selecting) {
struct scsi_cmnd *cmd = dequeue_next_cmd(instance);
if (!cmd)
break;
dsprintk(NDEBUG_MAIN, instance, "main: dequeued %p\n", cmd);
@ -960,8 +962,7 @@ static void NCR5380_main(struct work_struct *work)
#ifdef SUPPORT_TAGS
cmd_get_tag(cmd, cmd->cmnd[0] != REQUEST_SENSE);
#endif
cmd = NCR5380_select(instance, cmd);
if (!cmd) {
if (!NCR5380_select(instance, cmd)) {
dsprintk(NDEBUG_MAIN, instance, "main: select complete\n");
maybe_release_dma_irq(instance);
} else {
@ -1257,6 +1258,11 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance,
/* Reselection interrupt */
goto out;
}
if (!hostdata->selecting) {
/* Command was aborted */
NCR5380_write(MODE_REG, MR_BASE);
goto out;
}
if (err < 0) {
NCR5380_write(MODE_REG, MR_BASE);
shost_printk(KERN_ERR, instance,
@ -1838,9 +1844,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
unsigned char msgout = NOP;
int sink = 0;
int len;
#if defined(REAL_DMA)
int transfersize;
#endif
unsigned char *data;
unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
struct scsi_cmnd *cmd;
@ -1909,6 +1913,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
do_abort(instance);
cmd->result = DID_ERROR << 16;
complete_cmd(instance, cmd);
hostdata->connected = NULL;
return;
#endif
case PHASE_DATAIN:
@ -1966,7 +1971,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
sink = 1;
do_abort(instance);
cmd->result = DID_ERROR << 16;
complete_cmd(instance, cmd);
/* XXX - need to source or sink data here, as appropriate */
} else {
#ifdef REAL_DMA
@ -1983,18 +1987,22 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
} else
#endif /* defined(REAL_DMA) */
{
spin_unlock_irq(&hostdata->lock);
NCR5380_transfer_pio(instance, &phase,
(int *)&cmd->SCp.this_residual,
/* Break up transfer into 3 ms chunks,
* presuming 6 accesses per handshake.
*/
transfersize = min((unsigned long)cmd->SCp.this_residual,
hostdata->accesses_per_ms / 2);
len = transfersize;
NCR5380_transfer_pio(instance, &phase, &len,
(unsigned char **)&cmd->SCp.ptr);
spin_lock_irq(&hostdata->lock);
cmd->SCp.this_residual -= transfersize - len;
}
#if defined(CONFIG_SUN3) && defined(REAL_DMA)
/* if we had intended to dma that command clear it */
if (sun3_dma_setup_done == cmd)
sun3_dma_setup_done = NULL;
#endif
break;
return;
case PHASE_MSGIN:
len = 1;
data = &tmp;
@ -2487,14 +2495,17 @@ static bool list_del_cmd(struct list_head *haystack,
* [disconnected -> connected ->]...
* [autosense -> connected ->] done
*
* If cmd is unissued then just remove it.
* If cmd is disconnected, try to select the target.
* If cmd is connected, try to send an abort message.
* If cmd is waiting for autosense, give it a chance to complete but check
* that it isn't left connected.
* If cmd was not found at all then presumably it has already been completed,
* in which case return SUCCESS to try to avoid further EH measures.
*
* If the command has not completed yet, we must not fail to find it.
* We have no option but to forget the aborted command (even if it still
* lacks sense data). The mid-layer may re-issue a command that is in error
* recovery (see scsi_send_eh_cmnd), but the logic and data structures in
* this driver are such that a command can appear on one queue only.
*
* The lock protects driver data structures, but EH handlers also use it
* to serialize their own execution and prevent their own re-entry.
*/
static int NCR5380_abort(struct scsi_cmnd *cmd)
@ -2517,6 +2528,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd)
"abort: removed %p from issue queue\n", cmd);
cmd->result = DID_ABORT << 16;
cmd->scsi_done(cmd); /* No tag or busy flag to worry about */
goto out;
}
if (hostdata->selecting == cmd) {
@ -2531,19 +2543,21 @@ static int NCR5380_abort(struct scsi_cmnd *cmd)
if (list_del_cmd(&hostdata->disconnected, cmd)) {
dsprintk(NDEBUG_ABORT, instance,
"abort: removed %p from disconnected list\n", cmd);
cmd->result = DID_ERROR << 16;
if (!hostdata->connected)
NCR5380_select(instance, cmd);
if (hostdata->connected != cmd) {
complete_cmd(instance, cmd);
result = FAILED;
goto out;
}
/* Can't call NCR5380_select() and send ABORT because that
* means releasing the lock. Need a bus reset.
*/
set_host_byte(cmd, DID_ERROR);
complete_cmd(instance, cmd);
result = FAILED;
goto out;
}
if (hostdata->connected == cmd) {
dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd);
hostdata->connected = NULL;
#ifdef REAL_DMA
hostdata->dma_len = 0;
#endif
if (do_abort(instance)) {
set_host_byte(cmd, DID_ERROR);
complete_cmd(instance, cmd);
@ -2551,48 +2565,14 @@ static int NCR5380_abort(struct scsi_cmnd *cmd)
goto out;
}
set_host_byte(cmd, DID_ABORT);
#ifdef REAL_DMA
hostdata->dma_len = 0;
#endif
if (cmd->cmnd[0] == REQUEST_SENSE)
complete_cmd(instance, cmd);
else {
struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd);
/* Perform autosense for this command */
list_add(&ncmd->list, &hostdata->autosense);
}
complete_cmd(instance, cmd);
goto out;
}
if (list_find_cmd(&hostdata->autosense, cmd)) {
if (list_del_cmd(&hostdata->autosense, cmd)) {
dsprintk(NDEBUG_ABORT, instance,
"abort: found %p on sense queue\n", cmd);
spin_unlock_irqrestore(&hostdata->lock, flags);
queue_work(hostdata->work_q, &hostdata->main_task);
msleep(1000);
spin_lock_irqsave(&hostdata->lock, flags);
if (list_del_cmd(&hostdata->autosense, cmd)) {
dsprintk(NDEBUG_ABORT, instance,
"abort: removed %p from sense queue\n", cmd);
set_host_byte(cmd, DID_ABORT);
complete_cmd(instance, cmd);
goto out;
}
}
if (hostdata->connected == cmd) {
dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd);
hostdata->connected = NULL;
if (do_abort(instance)) {
set_host_byte(cmd, DID_ERROR);
complete_cmd(instance, cmd);
result = FAILED;
goto out;
}
set_host_byte(cmd, DID_ABORT);
#ifdef REAL_DMA
hostdata->dma_len = 0;
#endif
"abort: removed %p from sense queue\n", cmd);
set_host_byte(cmd, DID_ERROR);
complete_cmd(instance, cmd);
}
@ -2646,7 +2626,16 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
* commands!
*/
hostdata->selecting = NULL;
if (list_del_cmd(&hostdata->unissued, cmd)) {
cmd->result = DID_RESET << 16;
cmd->scsi_done(cmd);
}
if (hostdata->selecting) {
hostdata->selecting->result = DID_RESET << 16;
complete_cmd(instance, hostdata->selecting);
hostdata->selecting = NULL;
}
list_for_each_entry(ncmd, &hostdata->disconnected, list) {
struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
@ -2654,6 +2643,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
set_host_byte(cmd, DID_RESET);
cmd->scsi_done(cmd);
}
INIT_LIST_HEAD(&hostdata->disconnected);
list_for_each_entry(ncmd, &hostdata->autosense, list) {
struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
@ -2661,6 +2651,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
set_host_byte(cmd, DID_RESET);
cmd->scsi_done(cmd);
}
INIT_LIST_HEAD(&hostdata->autosense);
if (hostdata->connected) {
set_host_byte(hostdata->connected, DID_RESET);
@ -2668,12 +2659,6 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd)
hostdata->connected = NULL;
}
if (hostdata->sensing) {
set_host_byte(hostdata->connected, DID_RESET);
complete_cmd(instance, hostdata->sensing);
hostdata->sensing = NULL;
}
#ifdef SUPPORT_TAGS
free_all_tags(hostdata);
#endif

View File

@ -42,7 +42,7 @@ struct be_queue_info {
u16 id;
u16 tail, head;
bool created;
atomic_t used; /* Number of valid elements in the queue */
u16 used; /* Number of valid elements in the queue */
};
static inline u32 MODULO(u16 val, u16 limit)
@ -110,10 +110,9 @@ struct be_mcc_obj {
};
struct beiscsi_mcc_tag_state {
#define MCC_TAG_STATE_COMPLETED 0x00
#define MCC_TAG_STATE_RUNNING 0x01
#define MCC_TAG_STATE_TIMEOUT 0x02
uint8_t tag_state;
unsigned long tag_state;
#define MCC_TAG_STATE_RUNNING 1
#define MCC_TAG_STATE_TIMEOUT 2
struct be_dma_mem tag_mem_state;
};
@ -124,7 +123,7 @@ struct be_ctrl_info {
struct pci_dev *pdev;
/* Mbox used for cmd request/response */
spinlock_t mbox_lock; /* For serializing mbox cmds to BE card */
struct mutex mbox_lock; /* For serializing mbox cmds to BE card */
struct be_dma_mem mbox_mem;
/* Mbox mem is adjusted to align to 16 bytes. The allocated addr
* is stored for freeing purpose */
@ -133,11 +132,10 @@ struct be_ctrl_info {
/* MCC Rings */
struct be_mcc_obj mcc_obj;
spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */
spinlock_t mcc_cq_lock;
wait_queue_head_t mcc_wait[MAX_MCC_CMD + 1];
unsigned int mcc_tag[MAX_MCC_CMD];
unsigned int mcc_numtag[MAX_MCC_CMD + 1];
unsigned int mcc_tag_status[MAX_MCC_CMD + 1];
unsigned short mcc_alloc_index;
unsigned short mcc_free_index;
unsigned int mcc_tag_available;
@ -147,6 +145,12 @@ struct be_ctrl_info {
#include "be_cmds.h"
/* WRB index mask for MCC_Q_LEN queue entries */
#define MCC_Q_WRB_IDX_MASK CQE_STATUS_WRB_MASK
#define MCC_Q_WRB_IDX_SHIFT CQE_STATUS_WRB_SHIFT
/* TAG is from 1...MAX_MCC_CMD, MASK includes MAX_MCC_CMD */
#define MCC_Q_CMD_TAG_MASK ((MAX_MCC_CMD << 1) - 1)
#define PAGE_SHIFT_4K 12
#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
#define mcc_timeout 120000 /* 12s timeout */

File diff suppressed because it is too large Load Diff

View File

@ -58,15 +58,16 @@ struct be_mcc_wrb {
#define MCC_STATUS_ILLEGAL_FIELD 0x3
#define MCC_STATUS_INSUFFICIENT_BUFFER 0x4
#define CQE_STATUS_COMPL_MASK 0xFFFF
#define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */
#define CQE_STATUS_EXTD_MASK 0xFFFF
#define CQE_STATUS_EXTD_SHIFT 16 /* bits 0 - 15 */
#define CQE_STATUS_COMPL_MASK 0xFFFF
#define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */
#define CQE_STATUS_EXTD_MASK 0xFFFF
#define CQE_STATUS_EXTD_SHIFT 16 /* bits 31 - 16 */
#define CQE_STATUS_ADDL_MASK 0xFF00
#define CQE_STATUS_MASK 0xFF
#define CQE_STATUS_ADDL_SHIFT 0x08
#define CQE_STATUS_ADDL_SHIFT 8
#define CQE_STATUS_MASK 0xFF
#define CQE_STATUS_WRB_MASK 0xFF0000
#define CQE_STATUS_WRB_SHIFT 16
#define BEISCSI_HOST_MBX_TIMEOUT (110 * 1000)
#define BEISCSI_FW_MBX_TIMEOUT 100
@ -119,13 +120,22 @@ struct be_mcc_compl {
#define ASYNC_TRAILER_EVENT_CODE_MASK 0xFF
#define ASYNC_EVENT_CODE_LINK_STATE 0x1
#define ASYNC_EVENT_CODE_ISCSI 0x4
#define ASYNC_EVENT_CODE_SLI 0x11
#define ASYNC_TRAILER_EVENT_TYPE_SHIFT 16 /* bits 16 - 23 */
#define ASYNC_TRAILER_EVENT_TYPE_MASK 0xF
#define ASYNC_TRAILER_EVENT_TYPE_MASK 0xFF
/* iSCSI events */
#define ASYNC_EVENT_NEW_ISCSI_TGT_DISC 0x4
#define ASYNC_EVENT_NEW_ISCSI_CONN 0x5
#define ASYNC_EVENT_NEW_TCP_CONN 0x7
/* SLI events */
#define ASYNC_SLI_EVENT_TYPE_MISCONFIGURED 0x9
#define ASYNC_SLI_LINK_EFFECT_VALID(le) (le & 0x80)
#define ASYNC_SLI_LINK_EFFECT_SEV(le) ((le >> 1) & 0x03)
#define ASYNC_SLI_LINK_EFFECT_STATE(le) (le & 0x01)
struct be_async_event_trailer {
u32 code;
};
@ -133,7 +143,6 @@ struct be_async_event_trailer {
enum {
ASYNC_EVENT_LINK_DOWN = 0x0,
ASYNC_EVENT_LINK_UP = 0x1,
ASYNC_EVENT_LOGICAL = 0x2
};
/**
@ -143,16 +152,39 @@ enum {
struct be_async_event_link_state {
u8 physical_port;
u8 port_link_status;
/**
* ASYNC_EVENT_LINK_DOWN 0x0
* ASYNC_EVENT_LINK_UP 0x1
* ASYNC_EVENT_LINK_LOGICAL_DOWN 0x2
* ASYNC_EVENT_LINK_LOGICAL_UP 0x3
*/
#define BE_ASYNC_LINK_UP_MASK 0x01
u8 port_duplex;
u8 port_speed;
#define BEISCSI_PHY_LINK_FAULT_NONE 0x00
#define BEISCSI_PHY_LINK_FAULT_LOCAL 0x01
#define BEISCSI_PHY_LINK_FAULT_REMOTE 0x02
/* BE2ISCSI_LINK_SPEED_ZERO 0x00 - no link */
#define BE2ISCSI_LINK_SPEED_10MBPS 0x01
#define BE2ISCSI_LINK_SPEED_100MBPS 0x02
#define BE2ISCSI_LINK_SPEED_1GBPS 0x03
#define BE2ISCSI_LINK_SPEED_10GBPS 0x04
#define BE2ISCSI_LINK_SPEED_25GBPS 0x06
#define BE2ISCSI_LINK_SPEED_40GBPS 0x07
u8 port_fault;
u8 rsvd0[7];
u8 event_reason;
u16 qos_link_speed;
u32 event_tag;
struct be_async_event_trailer trailer;
} __packed;
/**
* When async-trailer is SLI event, mcc_compl is interpreted as
*/
struct be_async_event_sli {
u32 event_data1;
u32 event_data2;
u32 reserved;
u32 trailer;
} __packed;
struct be_mcc_mailbox {
struct be_mcc_wrb wrb;
struct be_mcc_compl compl;
@ -172,6 +204,7 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_CQ_CREATE 12
#define OPCODE_COMMON_EQ_CREATE 13
#define OPCODE_COMMON_MCC_CREATE 21
#define OPCODE_COMMON_MCC_CREATE_EXT 90
#define OPCODE_COMMON_ADD_TEMPLATE_HEADER_BUFFERS 24
#define OPCODE_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS 25
#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES 32
@ -183,6 +216,7 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_EQ_DESTROY 55
#define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58
#define OPCODE_COMMON_FUNCTION_RESET 61
#define OPCODE_COMMON_GET_PORT_NAME 77
/**
* LIST of opcodes that are common between Initiator and Target
@ -587,10 +621,11 @@ struct amap_mcc_context {
u8 rsvd2[32];
} __packed;
struct be_cmd_req_mcc_create {
struct be_cmd_req_mcc_create_ext {
struct be_cmd_req_hdr hdr;
u16 num_pages;
u16 rsvd0;
u32 async_evt_bitmap;
u8 context[sizeof(struct amap_mcc_context) / 8];
struct phys_addr pages[8];
} __packed;
@ -653,20 +688,6 @@ struct be_cmd_req_modify_eq_delay {
/******************** Get MAC ADDR *******************/
#define ETH_ALEN 6
struct be_cmd_get_nic_conf_req {
struct be_cmd_req_hdr hdr;
u32 nic_port_count;
u32 speed;
u32 max_speed;
u32 link_state;
u32 max_frame_size;
u16 size_of_structure;
u8 mac_address[ETH_ALEN];
u32 rsvd[23];
};
struct be_cmd_get_nic_conf_resp {
struct be_cmd_resp_hdr hdr;
u32 nic_port_count;
@ -675,9 +696,8 @@ struct be_cmd_get_nic_conf_resp {
u32 link_state;
u32 max_frame_size;
u16 size_of_structure;
u8 mac_address[6];
u32 rsvd[23];
};
u8 mac_address[ETH_ALEN];
} __packed;
#define BEISCSI_ALIAS_LEN 32
@ -689,29 +709,6 @@ struct be_cmd_hba_name {
u8 initiator_alias[BEISCSI_ALIAS_LEN];
} __packed;
struct be_cmd_ntwk_link_status_req {
struct be_cmd_req_hdr hdr;
u32 rsvd0;
} __packed;
/*** Port Speed Values ***/
#define BE2ISCSI_LINK_SPEED_ZERO 0x00
#define BE2ISCSI_LINK_SPEED_10MBPS 0x01
#define BE2ISCSI_LINK_SPEED_100MBPS 0x02
#define BE2ISCSI_LINK_SPEED_1GBPS 0x03
#define BE2ISCSI_LINK_SPEED_10GBPS 0x04
struct be_cmd_ntwk_link_status_resp {
struct be_cmd_resp_hdr hdr;
u8 phys_port;
u8 mac_duplex;
u8 mac_speed;
u8 mac_fault;
u8 mgmt_mac_duplex;
u8 mgmt_mac_speed;
u16 qos_link_speed;
u32 logical_link_speed;
} __packed;
int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl,
struct be_queue_info *eq, int eq_delay);
@ -730,28 +727,28 @@ int be_poll_mcc(struct be_ctrl_info *ctrl);
int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
struct beiscsi_hba *phba);
unsigned int be_cmd_get_initname(struct beiscsi_hba *phba);
unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba);
void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag);
void free_mcc_wrb(struct be_ctrl_info *ctrl, unsigned int tag);
int be_cmd_modify_eq_delay(struct beiscsi_hba *phba, struct be_set_eqd *,
int num);
int beiscsi_mccq_compl(struct beiscsi_hba *phba,
uint32_t tag, struct be_mcc_wrb **wrb,
struct be_dma_mem *mbx_cmd_mem);
int beiscsi_mccq_compl_wait(struct beiscsi_hba *phba,
uint32_t tag, struct be_mcc_wrb **wrb,
struct be_dma_mem *mbx_cmd_mem);
/*ISCSI Functuions */
int be_cmd_fw_initialize(struct be_ctrl_info *ctrl);
int be_cmd_fw_uninit(struct be_ctrl_info *ctrl);
struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem);
struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba);
int be_mcc_notify_wait(struct beiscsi_hba *phba);
void be_mcc_notify(struct beiscsi_hba *phba);
unsigned int alloc_mcc_tag(struct beiscsi_hba *phba);
void beiscsi_async_link_state_process(struct beiscsi_hba *phba,
struct be_async_event_link_state *evt);
int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl,
struct be_mcc_compl *compl);
int be_mcc_compl_poll(struct beiscsi_hba *phba, unsigned int tag);
void be_mcc_notify(struct beiscsi_hba *phba, unsigned int tag);
struct be_mcc_wrb *alloc_mcc_wrb(struct beiscsi_hba *phba,
unsigned int *ref_tag);
void beiscsi_process_async_event(struct beiscsi_hba *phba,
struct be_mcc_compl *compl);
int beiscsi_process_mcc_compl(struct be_ctrl_info *ctrl,
struct be_mcc_compl *compl);
int be_mbox_notify(struct be_ctrl_info *ctrl);
@ -777,8 +774,6 @@ int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem,
struct hwi_wrb_context *pwrb_context,
uint8_t ulp_num);
bool is_link_state_evt(u32 trailer);
/* Configuration Functions */
int be_cmd_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag);
@ -1137,6 +1132,21 @@ struct be_cmd_get_all_if_id_req {
u32 if_hndl_list[1];
} __packed;
struct be_cmd_get_port_name {
union {
struct be_cmd_req_hdr req_hdr;
struct be_cmd_resp_hdr resp_hdr;
} h;
union {
struct {
u32 reserved;
} req;
struct {
u32 port_names;
} resp;
} p;
} __packed;
#define ISCSI_OPCODE_SCSI_DATA_OUT 5
#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY 5
#define OPCODE_COMMON_MODIFY_EQ_DELAY 41
@ -1367,5 +1377,5 @@ void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
u8 subsystem, u8 opcode, int cmd_len);
void be2iscsi_fail_session(struct iscsi_cls_session *cls_session);
void beiscsi_fail_session(struct iscsi_cls_session *cls_session);
#endif /* !BEISCSI_CMDS_H */

View File

@ -367,13 +367,14 @@ beiscsi_set_vlan_tag(struct Scsi_Host *shost,
struct iscsi_iface_param_info *iface_param)
{
struct beiscsi_hba *phba = iscsi_host_priv(shost);
int ret = 0;
int ret;
/* Get the Interface Handle */
if (mgmt_get_all_if_id(phba)) {
ret = mgmt_get_all_if_id(phba);
if (ret) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : Getting Interface Handle Failed\n");
return -EIO;
return ret;
}
switch (iface_param->param) {
@ -465,6 +466,10 @@ beiscsi_set_ipv6(struct Scsi_Host *shost,
ret = mgmt_set_ip(phba, iface_param, NULL,
ISCSI_BOOTPROTO_STATIC);
break;
case ISCSI_NET_PARAM_VLAN_ENABLED:
case ISCSI_NET_PARAM_VLAN_TAG:
ret = beiscsi_set_vlan_tag(shost, iface_param);
break;
default:
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : Param %d not supported\n",
@ -730,7 +735,7 @@ static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba)
return -EBUSY;
}
rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
rc = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL);
if (rc) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
@ -753,7 +758,7 @@ static void beiscsi_get_port_state(struct Scsi_Host *shost)
struct beiscsi_hba *phba = iscsi_host_priv(shost);
struct iscsi_cls_host *ihost = shost->shost_data;
ihost->port_state = (phba->state == BE_ADAPTER_LINK_UP) ?
ihost->port_state = (phba->state & BE_ADAPTER_LINK_UP) ?
ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN;
}
@ -761,34 +766,13 @@ static void beiscsi_get_port_state(struct Scsi_Host *shost)
* beiscsi_get_port_speed - Get the Port Speed from Adapter
* @shost : pointer to scsi_host structure
*
* returns Success/Failure
*/
static int beiscsi_get_port_speed(struct Scsi_Host *shost)
static void beiscsi_get_port_speed(struct Scsi_Host *shost)
{
int rc;
unsigned int tag;
struct be_mcc_wrb *wrb;
struct be_cmd_ntwk_link_status_resp *resp;
struct beiscsi_hba *phba = iscsi_host_priv(shost);
struct iscsi_cls_host *ihost = shost->shost_data;
tag = be_cmd_get_port_speed(phba);
if (!tag) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : Getting Port Speed Failed\n");
return -EBUSY;
}
rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
if (rc) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BS_%d : Port Speed MBX Failed\n");
return rc;
}
resp = embedded_payload(wrb);
switch (resp->mac_speed) {
switch (phba->port_speed) {
case BE2ISCSI_LINK_SPEED_10MBPS:
ihost->port_speed = ISCSI_PORT_SPEED_10MBPS;
break;
@ -801,10 +785,15 @@ static int beiscsi_get_port_speed(struct Scsi_Host *shost)
case BE2ISCSI_LINK_SPEED_10GBPS:
ihost->port_speed = ISCSI_PORT_SPEED_10GBPS;
break;
case BE2ISCSI_LINK_SPEED_25GBPS:
ihost->port_speed = ISCSI_PORT_SPEED_25GBPS;
break;
case BE2ISCSI_LINK_SPEED_40GBPS:
ihost->port_speed = ISCSI_PORT_SPEED_40GBPS;
break;
default:
ihost->port_speed = ISCSI_PORT_SPEED_UNKNOWN;
}
return 0;
}
/**
@ -854,12 +843,7 @@ int beiscsi_get_host_param(struct Scsi_Host *shost,
status = sprintf(buf, "%s\n", iscsi_get_port_state_name(shost));
break;
case ISCSI_HOST_PARAM_PORT_SPEED:
status = beiscsi_get_port_speed(shost);
if (status) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : Retreiving Port Speed Failed\n");
return status;
}
beiscsi_get_port_speed(shost);
status = sprintf(buf, "%s\n", iscsi_get_port_speed_name(shost));
break;
default:
@ -1159,7 +1143,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
return -EAGAIN;
}
ret = beiscsi_mccq_compl(phba, tag, NULL, &nonemb_cmd);
ret = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd);
if (ret) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
@ -1293,7 +1277,7 @@ static void beiscsi_flush_cq(struct beiscsi_hba *phba)
for (i = 0; i < phba->num_cpus; i++) {
pbe_eq = &phwi_context->be_eq[i];
irq_poll_disable(&pbe_eq->iopoll);
beiscsi_process_cq(pbe_eq);
beiscsi_process_cq(pbe_eq, BE2_MAX_NUM_CQ_PROC);
irq_poll_enable(&pbe_eq->iopoll);
}
}
@ -1318,7 +1302,7 @@ static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag)
ret = -EAGAIN;
}
ret = beiscsi_mccq_compl(phba, tag, NULL, NULL);
ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
/* Flush the CQ entries */
beiscsi_flush_cq(phba);
@ -1393,7 +1377,7 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
beiscsi_ep->ep_cid);
}
beiscsi_mccq_compl(phba, tag, NULL, NULL);
beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
beiscsi_close_conn(beiscsi_ep, tcp_upload_flag);
free_ep:
msleep(BEISCSI_LOGOUT_SYNC_DELAY);

View File

@ -29,6 +29,7 @@
#include <linux/iscsi_boot_sysfs.h>
#include <linux/module.h>
#include <linux/bsg-lib.h>
#include <linux/irq_poll.h>
#include <scsi/libiscsi.h>
#include <scsi/scsi_bsg_iscsi.h>
@ -285,7 +286,7 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
return FAILED;
}
rc = beiscsi_mccq_compl(phba, tag, NULL, &nonemb_cmd);
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);
@ -366,7 +367,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
return FAILED;
}
rc = beiscsi_mccq_compl(phba, tag, NULL, &nonemb_cmd);
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);
@ -727,9 +728,8 @@ static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev)
mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16);
mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
spin_lock_init(&ctrl->mbox_lock);
mutex_init(&ctrl->mbox_lock);
spin_lock_init(&phba->ctrl.mcc_lock);
spin_lock_init(&phba->ctrl.mcc_cq_lock);
return status;
}
@ -895,31 +895,17 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id)
static irqreturn_t be_isr_msix(int irq, void *dev_id)
{
struct beiscsi_hba *phba;
struct be_eq_entry *eqe = NULL;
struct be_queue_info *eq;
struct be_queue_info *cq;
unsigned int num_eq_processed;
struct be_eq_obj *pbe_eq;
pbe_eq = dev_id;
eq = &pbe_eq->q;
cq = pbe_eq->cq;
eqe = queue_tail_node(eq);
phba = pbe_eq->phba;
num_eq_processed = 0;
while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32]
& EQE_VALID_MASK) {
irq_poll_sched(&pbe_eq->iopoll);
AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
queue_tail_inc(eq);
eqe = queue_tail_node(eq);
num_eq_processed++;
}
if (num_eq_processed)
hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1);
/* disable interrupt till iopoll completes */
hwi_ring_eq_db(phba, eq->id, 1, 0, 0, 1);
irq_poll_sched(&pbe_eq->iopoll);
return IRQ_HANDLED;
}
@ -996,6 +982,7 @@ static irqreturn_t be_isr(int irq, void *dev_id)
return IRQ_NONE;
}
static int beiscsi_init_irqs(struct beiscsi_hba *phba)
{
struct pci_dev *pcidev = phba->pcidev;
@ -1070,7 +1057,7 @@ free_msix_irqs:
void hwi_ring_cq_db(struct beiscsi_hba *phba,
unsigned int id, unsigned int num_processed,
unsigned char rearm, unsigned char event)
unsigned char rearm)
{
u32 val = 0;
@ -1145,6 +1132,7 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba)
{
struct sgl_handle *psgl_handle;
spin_lock_bh(&phba->io_sgl_lock);
if (phba->io_sgl_hndl_avbl) {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO,
"BM_%d : In alloc_io_sgl_handle,"
@ -1162,12 +1150,14 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba)
phba->io_sgl_alloc_index++;
} else
psgl_handle = NULL;
spin_unlock_bh(&phba->io_sgl_lock);
return psgl_handle;
}
static void
free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
{
spin_lock_bh(&phba->io_sgl_lock);
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO,
"BM_%d : In free_,io_sgl_free_index=%d\n",
phba->io_sgl_free_index);
@ -1182,6 +1172,7 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
"value there=%p\n", phba->io_sgl_free_index,
phba->io_sgl_hndl_base
[phba->io_sgl_free_index]);
spin_unlock_bh(&phba->io_sgl_lock);
return;
}
phba->io_sgl_hndl_base[phba->io_sgl_free_index] = psgl_handle;
@ -1190,6 +1181,25 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
phba->io_sgl_free_index = 0;
else
phba->io_sgl_free_index++;
spin_unlock_bh(&phba->io_sgl_lock);
}
static inline struct wrb_handle *
beiscsi_get_wrb_handle(struct hwi_wrb_context *pwrb_context,
unsigned int wrbs_per_cxn)
{
struct wrb_handle *pwrb_handle;
spin_lock_bh(&pwrb_context->wrb_lock);
pwrb_handle = pwrb_context->pwrb_handle_base[pwrb_context->alloc_index];
pwrb_context->wrb_handles_available--;
if (pwrb_context->alloc_index == (wrbs_per_cxn - 1))
pwrb_context->alloc_index = 0;
else
pwrb_context->alloc_index++;
spin_unlock_bh(&pwrb_context->wrb_lock);
return pwrb_handle;
}
/**
@ -1201,30 +1211,32 @@ free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
* This happens under session_lock until submission to chip
*/
struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid,
struct hwi_wrb_context **pcontext)
struct hwi_wrb_context **pcontext)
{
struct hwi_wrb_context *pwrb_context;
struct hwi_controller *phwi_ctrlr;
struct wrb_handle *pwrb_handle;
uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
phwi_ctrlr = phba->phwi_ctrlr;
pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
if (pwrb_context->wrb_handles_available >= 2) {
pwrb_handle = pwrb_context->pwrb_handle_base[
pwrb_context->alloc_index];
pwrb_context->wrb_handles_available--;
if (pwrb_context->alloc_index ==
(phba->params.wrbs_per_cxn - 1))
pwrb_context->alloc_index = 0;
else
pwrb_context->alloc_index++;
/* return the context address */
*pcontext = pwrb_context;
return beiscsi_get_wrb_handle(pwrb_context, phba->params.wrbs_per_cxn);
}
/* Return the context address */
*pcontext = pwrb_context;
} else
pwrb_handle = NULL;
return pwrb_handle;
static inline void
beiscsi_put_wrb_handle(struct hwi_wrb_context *pwrb_context,
struct wrb_handle *pwrb_handle,
unsigned int wrbs_per_cxn)
{
spin_lock_bh(&pwrb_context->wrb_lock);
pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle;
pwrb_context->wrb_handles_available++;
if (pwrb_context->free_index == (wrbs_per_cxn - 1))
pwrb_context->free_index = 0;
else
pwrb_context->free_index++;
spin_unlock_bh(&pwrb_context->wrb_lock);
}
/**
@ -1239,13 +1251,9 @@ static void
free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context,
struct wrb_handle *pwrb_handle)
{
pwrb_context->pwrb_handle_base[pwrb_context->free_index] = pwrb_handle;
pwrb_context->wrb_handles_available++;
if (pwrb_context->free_index == (phba->params.wrbs_per_cxn - 1))
pwrb_context->free_index = 0;
else
pwrb_context->free_index++;
beiscsi_put_wrb_handle(pwrb_context,
pwrb_handle,
phba->params.wrbs_per_cxn);
beiscsi_log(phba, KERN_INFO,
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
"BM_%d : FREE WRB: pwrb_handle=%p free_index=0x%x"
@ -1258,6 +1266,7 @@ static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba)
{
struct sgl_handle *psgl_handle;
spin_lock_bh(&phba->mgmt_sgl_lock);
if (phba->eh_sgl_hndl_avbl) {
psgl_handle = phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index];
phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index] = NULL;
@ -1275,13 +1284,14 @@ static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba)
phba->eh_sgl_alloc_index++;
} else
psgl_handle = NULL;
spin_unlock_bh(&phba->mgmt_sgl_lock);
return psgl_handle;
}
void
free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
{
spin_lock_bh(&phba->mgmt_sgl_lock);
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
"BM_%d : In free_mgmt_sgl_handle,"
"eh_sgl_free_index=%d\n",
@ -1296,6 +1306,7 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
"BM_%d : Double Free in eh SGL ,"
"eh_sgl_free_index=%d\n",
phba->eh_sgl_free_index);
spin_unlock_bh(&phba->mgmt_sgl_lock);
return;
}
phba->eh_sgl_hndl_base[phba->eh_sgl_free_index] = psgl_handle;
@ -1305,6 +1316,7 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)
phba->eh_sgl_free_index = 0;
else
phba->eh_sgl_free_index++;
spin_unlock_bh(&phba->mgmt_sgl_lock);
}
static void
@ -2029,7 +2041,7 @@ static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn,
phwi_ctrlr, cri_index));
}
static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba)
void beiscsi_process_mcc_cq(struct beiscsi_hba *phba)
{
struct be_queue_info *mcc_cq;
struct be_mcc_compl *mcc_compl;
@ -2039,31 +2051,15 @@ static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba)
mcc_compl = queue_tail_node(mcc_cq);
mcc_compl->flags = le32_to_cpu(mcc_compl->flags);
while (mcc_compl->flags & CQE_FLAGS_VALID_MASK) {
if (num_processed >= 32) {
hwi_ring_cq_db(phba, mcc_cq->id,
num_processed, 0, 0);
num_processed, 0);
num_processed = 0;
}
if (mcc_compl->flags & CQE_FLAGS_ASYNC_MASK) {
/* Interpret flags as an async trailer */
if (is_link_state_evt(mcc_compl->flags))
/* Interpret compl as a async link evt */
beiscsi_async_link_state_process(phba,
(struct be_async_event_link_state *) mcc_compl);
else {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_MBOX,
"BM_%d : Unsupported Async Event, flags"
" = 0x%08x\n",
mcc_compl->flags);
if (phba->state & BE_ADAPTER_LINK_UP) {
phba->state |= BE_ADAPTER_CHECK_BOOT;
phba->get_boot = BE_GET_BOOT_RETRIES;
}
}
beiscsi_process_async_event(phba, mcc_compl);
} else if (mcc_compl->flags & CQE_FLAGS_COMPLETED_MASK) {
be_mcc_compl_process_isr(&phba->ctrl, mcc_compl);
atomic_dec(&phba->ctrl.mcc_obj.q.used);
beiscsi_process_mcc_compl(&phba->ctrl, mcc_compl);
}
mcc_compl->flags = 0;
@ -2074,24 +2070,24 @@ static void beiscsi_process_mcc_isr(struct beiscsi_hba *phba)
}
if (num_processed > 0)
hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1, 0);
hwi_ring_cq_db(phba, mcc_cq->id, num_processed, 1);
}
/**
* beiscsi_process_cq()- Process the Completion Queue
* @pbe_eq: Event Q on which the Completion has come
* @budget: Max number of events to processed
*
* return
* Number of Completion Entries processed.
**/
unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq, int budget)
{
struct be_queue_info *cq;
struct sol_cqe *sol;
struct dmsg_cqe *dmsg;
unsigned int total = 0;
unsigned int num_processed = 0;
unsigned int tot_nump = 0;
unsigned short code = 0, cid = 0;
uint16_t cri_index = 0;
struct beiscsi_conn *beiscsi_conn;
@ -2142,12 +2138,12 @@ unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
beiscsi_ep = ep->dd_data;
beiscsi_conn = beiscsi_ep->conn;
if (num_processed >= 32) {
hwi_ring_cq_db(phba, cq->id,
num_processed, 0, 0);
tot_nump += num_processed;
/* replenish cq */
if (num_processed == 32) {
hwi_ring_cq_db(phba, cq->id, 32, 0);
num_processed = 0;
}
total++;
switch (code) {
case SOL_CMD_COMPLETE:
@ -2192,7 +2188,13 @@ unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
"BM_%d : Ignoring %s[%d] on CID : %d\n",
cqe_desc[code], code, cid);
break;
case CXN_KILLED_HDR_DIGEST_ERR:
case SOL_CMD_KILLED_DATA_DIGEST_ERR:
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
"BM_%d : Cmd Notification %s[%d] on CID : %d\n",
cqe_desc[code], code, cid);
break;
case CMD_KILLED_INVALID_STATSN_RCVD:
case CMD_KILLED_INVALID_R2T_RCVD:
case CMD_CXN_KILLED_LUN_INVALID:
@ -2218,7 +2220,6 @@ unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
case CXN_KILLED_PDU_SIZE_EXCEEDS_DSL:
case CXN_KILLED_BURST_LEN_MISMATCH:
case CXN_KILLED_AHS_RCVD:
case CXN_KILLED_HDR_DIGEST_ERR:
case CXN_KILLED_UNKNOWN_HDR:
case CXN_KILLED_STALE_ITT_TTT_RCVD:
case CXN_KILLED_INVALID_ITT_TTT_RCVD:
@ -2253,13 +2254,12 @@ proc_next_cqe:
queue_tail_inc(cq);
sol = queue_tail_node(cq);
num_processed++;
if (total == budget)
break;
}
if (num_processed > 0) {
tot_nump += num_processed;
hwi_ring_cq_db(phba, cq->id, num_processed, 1, 0);
}
return tot_nump;
hwi_ring_cq_db(phba, cq->id, num_processed, 1);
return total;
}
void beiscsi_process_all_cqs(struct work_struct *work)
@ -2279,14 +2279,14 @@ void beiscsi_process_all_cqs(struct work_struct *work)
spin_lock_irqsave(&phba->isr_lock, flags);
pbe_eq->todo_mcc_cq = false;
spin_unlock_irqrestore(&phba->isr_lock, flags);
beiscsi_process_mcc_isr(phba);
beiscsi_process_mcc_cq(phba);
}
if (pbe_eq->todo_cq) {
spin_lock_irqsave(&phba->isr_lock, flags);
pbe_eq->todo_cq = false;
spin_unlock_irqrestore(&phba->isr_lock, flags);
beiscsi_process_cq(pbe_eq);
beiscsi_process_cq(pbe_eq, BE2_MAX_NUM_CQ_PROC);
}
/* rearm EQ for further interrupts */
@ -2295,20 +2295,36 @@ void beiscsi_process_all_cqs(struct work_struct *work)
static int be_iopoll(struct irq_poll *iop, int budget)
{
unsigned int ret;
unsigned int ret, num_eq_processed;
struct beiscsi_hba *phba;
struct be_eq_obj *pbe_eq;
struct be_eq_entry *eqe = NULL;
struct be_queue_info *eq;
num_eq_processed = 0;
pbe_eq = container_of(iop, struct be_eq_obj, iopoll);
ret = beiscsi_process_cq(pbe_eq);
phba = pbe_eq->phba;
eq = &pbe_eq->q;
eqe = queue_tail_node(eq);
while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] &
EQE_VALID_MASK) {
AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0);
queue_tail_inc(eq);
eqe = queue_tail_node(eq);
num_eq_processed++;
}
hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 0, 1);
ret = beiscsi_process_cq(pbe_eq, budget);
pbe_eq->cq_count += ret;
if (ret < budget) {
phba = pbe_eq->phba;
irq_poll_complete(iop);
beiscsi_log(phba, KERN_INFO,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
"BM_%d : rearm pbe_eq->q.id =%d\n",
pbe_eq->q.id);
"BM_%d : rearm pbe_eq->q.id =%d ret %d\n",
pbe_eq->q.id, ret);
hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1);
}
return ret;
@ -2502,7 +2518,7 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,
* @pwrb: ptr to the WRB entry
* @task: iscsi task which is to be executed
**/
static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
static int hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
{
struct iscsi_sge *psgl;
struct beiscsi_io_task *io_task = task->dd_data;
@ -2534,6 +2550,9 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
task->data,
task->data_count,
PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(phba->pcidev,
io_task->mtask_addr))
return -ENOMEM;
io_task->mtask_data_count = task->data_count;
} else
io_task->mtask_addr = 0;
@ -2578,6 +2597,7 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)
AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0x106);
}
AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1);
return 0;
}
/**
@ -2706,8 +2726,10 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba)
phwi_ctrlr->wrb_context = kzalloc(sizeof(struct hwi_wrb_context) *
phba->params.cxns_per_ctrl,
GFP_KERNEL);
if (!phwi_ctrlr->wrb_context)
if (!phwi_ctrlr->wrb_context) {
kfree(phba->phwi_ctrlr);
return -ENOMEM;
}
phba->init_mem = kcalloc(SE_MEM_MAX, sizeof(*mem_descr),
GFP_KERNEL);
@ -2904,6 +2926,7 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
}
num_cxn_wrbh--;
}
spin_lock_init(&pwrb_context->wrb_lock);
}
idx = 0;
for (index = 0; index < phba->params.cxns_per_ctrl; index++) {
@ -3866,6 +3889,8 @@ static int hwi_init_port(struct beiscsi_hba *phba)
phwi_context->min_eqd = 0;
phwi_context->cur_eqd = 0;
be_cmd_fw_initialize(&phba->ctrl);
/* set optic state to unknown */
phba->optic_state = 0xff;
status = beiscsi_create_eqs(phba, phwi_context);
if (status != 0) {
@ -4384,7 +4409,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba)
goto boot_freemem;
}
ret = beiscsi_mccq_compl(phba, tag, NULL, &nonemb_cmd);
ret = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd);
if (ret) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
@ -4468,6 +4493,7 @@ put_shost:
scsi_host_put(phba->shost);
free_kset:
iscsi_boot_destroy_kset(phba->boot_kset);
phba->boot_kset = NULL;
return -ENOMEM;
}
@ -4607,11 +4633,9 @@ beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn,
}
if (io_task->psgl_handle) {
spin_lock_bh(&phba->mgmt_sgl_lock);
free_mgmt_sgl_handle(phba,
io_task->psgl_handle);
io_task->psgl_handle = NULL;
spin_unlock_bh(&phba->mgmt_sgl_lock);
}
if (io_task->mtask_addr) {
@ -4657,9 +4681,7 @@ static void beiscsi_cleanup_task(struct iscsi_task *task)
}
if (io_task->psgl_handle) {
spin_lock(&phba->io_sgl_lock);
free_io_sgl_handle(phba, io_task->psgl_handle);
spin_unlock(&phba->io_sgl_lock);
io_task->psgl_handle = NULL;
}
@ -4714,6 +4736,20 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,
doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT;
iowrite32(doorbell, phba->db_va +
beiscsi_conn->doorbell_offset);
/*
* There is no completion for CONTEXT_UPDATE. The completion of next
* WRB posted guarantees FW's processing and DMA'ing of it.
* Use beiscsi_put_wrb_handle to put it back in the pool which makes
* sure zero'ing or reuse of the WRB only after wrbs_per_cxn.
*/
beiscsi_put_wrb_handle(pwrb_context, pwrb_handle,
phba->params.wrbs_per_cxn);
beiscsi_log(phba, KERN_INFO,
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
"BM_%d : put CONTEXT_UPDATE pwrb_handle=%p free_index=0x%x wrb_handles_available=%d\n",
pwrb_handle, pwrb_context->free_index,
pwrb_context->wrb_handles_available);
}
static void beiscsi_parse_pdu(struct iscsi_conn *conn, itt_t itt,
@ -4761,9 +4797,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
io_task->pwrb_handle = NULL;
if (task->sc) {
spin_lock(&phba->io_sgl_lock);
io_task->psgl_handle = alloc_io_sgl_handle(phba);
spin_unlock(&phba->io_sgl_lock);
if (!io_task->psgl_handle) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
@ -4788,10 +4822,8 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) {
beiscsi_conn->task = task;
if (!beiscsi_conn->login_in_progress) {
spin_lock(&phba->mgmt_sgl_lock);
io_task->psgl_handle = (struct sgl_handle *)
alloc_mgmt_sgl_handle(phba);
spin_unlock(&phba->mgmt_sgl_lock);
if (!io_task->psgl_handle) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO |
@ -4830,9 +4862,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
beiscsi_conn->plogin_wrb_handle;
}
} else {
spin_lock(&phba->mgmt_sgl_lock);
io_task->psgl_handle = alloc_mgmt_sgl_handle(phba);
spin_unlock(&phba->mgmt_sgl_lock);
if (!io_task->psgl_handle) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO |
@ -4867,15 +4897,11 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
return 0;
free_io_hndls:
spin_lock(&phba->io_sgl_lock);
free_io_sgl_handle(phba, io_task->psgl_handle);
spin_unlock(&phba->io_sgl_lock);
goto free_hndls;
free_mgmt_hndls:
spin_lock(&phba->mgmt_sgl_lock);
free_mgmt_sgl_handle(phba, io_task->psgl_handle);
io_task->psgl_handle = NULL;
spin_unlock(&phba->mgmt_sgl_lock);
free_hndls:
phwi_ctrlr = phba->phwi_ctrlr;
cri_index = BE_GET_CRI_FROM_CID(
@ -4903,7 +4929,6 @@ int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg,
pwrb = io_task->pwrb_handle->pwrb;
io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0;
io_task->bhs_len = sizeof(struct be_cmd_bhs);
if (writedir) {
@ -4964,7 +4989,6 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,
unsigned int doorbell = 0;
pwrb = io_task->pwrb_handle->pwrb;
io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0;
io_task->bhs_len = sizeof(struct be_cmd_bhs);
if (writedir) {
@ -5023,6 +5047,7 @@ static int beiscsi_mtask(struct iscsi_task *task)
unsigned int doorbell = 0;
unsigned int cid;
unsigned int pwrb_typeoffset = 0;
int ret = 0;
cid = beiscsi_conn->beiscsi_conn_cid;
pwrb = io_task->pwrb_handle->pwrb;
@ -5071,7 +5096,7 @@ static int beiscsi_mtask(struct iscsi_task *task)
case ISCSI_OP_LOGIN:
AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 1);
ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset);
hwi_write_buffer(pwrb, task);
ret = hwi_write_buffer(pwrb, task);
break;
case ISCSI_OP_NOOP_OUT:
if (task->hdr->ttt != ISCSI_RESERVED_TAG) {
@ -5091,19 +5116,19 @@ static int beiscsi_mtask(struct iscsi_task *task)
AMAP_SET_BITS(struct amap_iscsi_wrb_v2,
dmsg, pwrb, 0);
}
hwi_write_buffer(pwrb, task);
ret = hwi_write_buffer(pwrb, task);
break;
case ISCSI_OP_TEXT:
ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset);
hwi_write_buffer(pwrb, task);
ret = hwi_write_buffer(pwrb, task);
break;
case ISCSI_OP_SCSI_TMFUNC:
ADAPTER_SET_WRB_TYPE(pwrb, INI_TMF_CMD, pwrb_typeoffset);
hwi_write_buffer(pwrb, task);
ret = hwi_write_buffer(pwrb, task);
break;
case ISCSI_OP_LOGOUT:
ADAPTER_SET_WRB_TYPE(pwrb, HWH_TYPE_LOGOUT, pwrb_typeoffset);
hwi_write_buffer(pwrb, task);
ret = hwi_write_buffer(pwrb, task);
break;
default:
@ -5114,6 +5139,9 @@ static int beiscsi_mtask(struct iscsi_task *task)
return -EINVAL;
}
if (ret)
return ret;
/* Set the task type */
io_task->wrb_type = (is_chip_be2_be3r(phba)) ?
AMAP_GET_BITS(struct amap_iscsi_wrb, type, pwrb) :
@ -5132,23 +5160,21 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
{
struct beiscsi_io_task *io_task = task->dd_data;
struct scsi_cmnd *sc = task->sc;
struct beiscsi_hba *phba = NULL;
struct beiscsi_hba *phba;
struct scatterlist *sg;
int num_sg;
unsigned int writedir = 0, xferlen = 0;
phba = ((struct beiscsi_conn *)task->conn->dd_data)->phba;
if (!io_task->conn->login_in_progress)
task->hdr->exp_statsn = 0;
if (!sc)
return beiscsi_mtask(task);
io_task->scsi_cmnd = sc;
num_sg = scsi_dma_map(sc);
phba = io_task->conn->phba;
if (num_sg < 0) {
struct iscsi_conn *conn = task->conn;
struct beiscsi_hba *phba = NULL;
phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO | BEISCSI_LOG_ISCSI,
"BM_%d : scsi_dma_map Failed "
@ -5211,12 +5237,13 @@ static int beiscsi_bsg_request(struct bsg_job *job)
rc = wait_event_interruptible_timeout(
phba->ctrl.mcc_wait[tag],
phba->ctrl.mcc_numtag[tag],
phba->ctrl.mcc_tag_status[tag],
msecs_to_jiffies(
BEISCSI_HOST_MBX_TIMEOUT));
extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
free_mcc_tag(&phba->ctrl, tag);
extd_status = (phba->ctrl.mcc_tag_status[tag] &
CQE_STATUS_ADDL_MASK) >> CQE_STATUS_ADDL_SHIFT;
status = phba->ctrl.mcc_tag_status[tag] & CQE_STATUS_MASK;
free_mcc_wrb(&phba->ctrl, tag);
resp = (struct be_cmd_resp_hdr *)nonemb_cmd.va;
sg_copy_from_buffer(job->reply_payload.sg_list,
job->reply_payload.sg_cnt,
@ -5277,15 +5304,12 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba,
if (phba->msix_enabled) {
for (i = 0; i <= phba->num_cpus; i++) {
msix_vec = phba->msix_entries[i].vector;
synchronize_irq(msix_vec);
free_irq(msix_vec, &phwi_context->be_eq[i]);
kfree(phba->msi_name[i]);
}
} else
if (phba->pcidev->irq) {
synchronize_irq(phba->pcidev->irq);
if (phba->pcidev->irq)
free_irq(phba->pcidev->irq, phba);
}
pci_disable_msix(phba->pcidev);
cancel_delayed_work_sync(&phba->beiscsi_hw_check_task);
@ -5313,7 +5337,6 @@ static void beiscsi_quiesce(struct beiscsi_hba *phba,
static void beiscsi_remove(struct pci_dev *pcidev)
{
struct beiscsi_hba *phba = NULL;
phba = pci_get_drvdata(pcidev);
@ -5323,9 +5346,9 @@ static void beiscsi_remove(struct pci_dev *pcidev)
}
beiscsi_destroy_def_ifaces(phba);
beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD);
iscsi_boot_destroy_kset(phba->boot_kset);
iscsi_host_remove(phba->shost);
beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD);
pci_dev_put(phba->pcidev);
iscsi_host_free(phba->shost);
pci_disable_pcie_error_reporting(pcidev);
@ -5334,23 +5357,6 @@ static void beiscsi_remove(struct pci_dev *pcidev)
pci_disable_device(pcidev);
}
static void beiscsi_shutdown(struct pci_dev *pcidev)
{
struct beiscsi_hba *phba = NULL;
phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev);
if (!phba) {
dev_err(&pcidev->dev, "beiscsi_shutdown called with no phba\n");
return;
}
phba->state = BE_ADAPTER_STATE_SHUTDOWN;
iscsi_host_for_each_session(phba->shost, be2iscsi_fail_session);
beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD);
pci_disable_device(pcidev);
}
static void beiscsi_msix_enable(struct beiscsi_hba *phba)
{
int i, status;
@ -5413,7 +5419,7 @@ static void be_eqd_update(struct beiscsi_hba *phba)
if (num) {
tag = be_cmd_modify_eq_delay(phba, set_eqd, num);
if (tag)
beiscsi_mccq_compl(phba, tag, NULL, NULL);
beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
}
}
@ -5564,11 +5570,17 @@ static void beiscsi_eeh_resume(struct pci_dev *pdev)
phba->shost->max_id = phba->params.cxns_per_ctrl;
phba->shost->can_queue = phba->params.ios_per_ctrl;
ret = hwi_init_controller(phba);
if (ret) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : beiscsi_eeh_resume -"
"Failed to initialize beiscsi_hba.\n");
goto ret_err;
}
for (i = 0; i < MAX_MCC_CMD; i++) {
init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]);
phba->ctrl.mcc_tag[i] = i + 1;
phba->ctrl.mcc_numtag[i + 1] = 0;
phba->ctrl.mcc_tag_status[i + 1] = 0;
phba->ctrl.mcc_tag_available++;
}
@ -5670,6 +5682,9 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
goto hba_free;
}
/*
* FUNCTION_RESET should clean up any stale info in FW for this fn
*/
ret = beiscsi_cmd_reset_function(phba);
if (ret) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
@ -5693,6 +5708,8 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
"BM_%d : Error getting fw config\n");
goto free_port;
}
mgmt_get_port_name(&phba->ctrl, phba);
beiscsi_get_params(phba);
if (enable_msix)
find_num_cpus(phba);
@ -5710,7 +5727,6 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
}
phba->shost->max_id = phba->params.cxns_per_ctrl;
beiscsi_get_params(phba);
phba->shost->can_queue = phba->params.ios_per_ctrl;
ret = beiscsi_init_port(phba);
if (ret < 0) {
@ -5723,7 +5739,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
for (i = 0; i < MAX_MCC_CMD; i++) {
init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]);
phba->ctrl.mcc_tag[i] = i + 1;
phba->ctrl.mcc_numtag[i + 1] = 0;
phba->ctrl.mcc_tag_status[i + 1] = 0;
phba->ctrl.mcc_tag_available++;
memset(&phba->ctrl.ptag_state[i].tag_mem_state, 0,
sizeof(struct be_dma_mem));
@ -5857,7 +5873,6 @@ static struct pci_driver beiscsi_pci_driver = {
.name = DRV_NAME,
.probe = beiscsi_dev_probe,
.remove = beiscsi_remove,
.shutdown = beiscsi_shutdown,
.id_table = beiscsi_pci_id_table,
.err_handler = &beiscsi_eeh_handlers
};

View File

@ -36,7 +36,7 @@
#include <scsi/scsi_transport_iscsi.h>
#define DRV_NAME "be2iscsi"
#define BUILD_STR "10.6.0.1"
#define BUILD_STR "11.0.0.0"
#define BE_NAME "Emulex OneConnect" \
"Open-iSCSI Driver version" BUILD_STR
#define DRV_DESC BE_NAME " " "Driver"
@ -63,6 +63,7 @@
#define BE2_SGE 32
#define BE2_DEFPDU_HDR_SZ 64
#define BE2_DEFPDU_DATA_SZ 8192
#define BE2_MAX_NUM_CQ_PROC 512
#define MAX_CPUS 64
#define BEISCSI_MAX_NUM_CPUS 7
@ -103,8 +104,7 @@
#define BE_ADAPTER_LINK_UP 0x001
#define BE_ADAPTER_LINK_DOWN 0x002
#define BE_ADAPTER_PCI_ERR 0x004
#define BE_ADAPTER_STATE_SHUTDOWN 0x008
#define BE_ADAPTER_CHECK_BOOT 0x010
#define BE_ADAPTER_CHECK_BOOT 0x008
#define BEISCSI_CLEAN_UNLOAD 0x01
@ -304,6 +304,7 @@ struct invalidate_command_table {
#define BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, cri) \
(phwi_ctrlr->wrb_context[cri].ulp_num)
struct hwi_wrb_context {
spinlock_t wrb_lock;
struct list_head wrb_handle_list;
struct list_head wrb_handle_drvr_list;
struct wrb_handle **pwrb_handle_base;
@ -398,7 +399,9 @@ struct beiscsi_hba {
* group together since they are used most frequently
* for cid to cri conversion
*/
#define BEISCSI_PHYS_PORT_MAX 4
unsigned int phys_port;
/* valid values of phys_port id are 0, 1, 2, 3 */
unsigned int eqid_count;
unsigned int cqid_count;
unsigned int iscsi_cid_start[BEISCSI_ULP_COUNT];
@ -416,6 +419,7 @@ struct beiscsi_hba {
} fw_config;
unsigned int state;
u8 optic_state;
int get_boot;
bool fw_timeout;
bool ue_detected;
@ -423,6 +427,8 @@ struct beiscsi_hba {
bool mac_addr_set;
u8 mac_address[ETH_ALEN];
u8 port_name;
u8 port_speed;
char fw_ver_str[BEISCSI_VER_STRLEN];
char wq_name[20];
struct workqueue_struct *wq; /* The actuak work queue */
@ -845,9 +851,10 @@ void beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn,
void hwi_ring_cq_db(struct beiscsi_hba *phba,
unsigned int id, unsigned int num_processed,
unsigned char rearm, unsigned char event);
unsigned char rearm);
unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq);
unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq, int budget);
void beiscsi_process_mcc_cq(struct beiscsi_hba *phba);
static inline bool beiscsi_error(struct beiscsi_hba *phba)
{
@ -1074,12 +1081,14 @@ struct hwi_context_memory {
#define BEISCSI_LOG_CONFIG 0x0020 /* CONFIG Code Path */
#define BEISCSI_LOG_ISCSI 0x0040 /* SCSI/iSCSI Protocol related Logs */
#define __beiscsi_log(phba, level, fmt, arg...) \
shost_printk(level, phba->shost, fmt, __LINE__, ##arg)
#define beiscsi_log(phba, level, mask, fmt, arg...) \
do { \
uint32_t log_value = phba->attr_log_enable; \
if (((mask) & log_value) || (level[1] <= '3')) \
shost_printk(level, phba->shost, \
fmt, __LINE__, ##arg); \
} while (0)
__beiscsi_log(phba, level, fmt, ##arg); \
} while (0);
#endif

View File

@ -161,20 +161,17 @@ int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb;
struct be_cmd_req_modify_eq_delay *req;
unsigned int tag = 0;
unsigned int tag;
int i;
spin_lock(&ctrl->mbox_lock);
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
return tag;
mutex_lock(&ctrl->mbox_lock);
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
return 0;
}
wrb = wrb_from_mccq(phba);
req = embedded_payload(wrb);
wrb->tag0 |= tag;
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req));
@ -187,8 +184,8 @@ int be_cmd_modify_eq_delay(struct beiscsi_hba *phba,
cpu_to_le32(set_eqd[i].delay_multiplier);
}
be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock);
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
return tag;
}
@ -209,22 +206,20 @@ unsigned int mgmt_reopen_session(struct beiscsi_hba *phba,
struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb;
struct be_cmd_reopen_session_req *req;
unsigned int tag = 0;
unsigned int tag;
beiscsi_log(phba, KERN_INFO,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BG_%d : In bescsi_get_boot_target\n");
spin_lock(&ctrl->mbox_lock);
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
return tag;
mutex_lock(&ctrl->mbox_lock);
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
return 0;
}
wrb = wrb_from_mccq(phba);
req = embedded_payload(wrb);
wrb->tag0 |= tag;
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
OPCODE_ISCSI_INI_DRIVER_REOPEN_ALL_SESSIONS,
@ -234,8 +229,8 @@ unsigned int mgmt_reopen_session(struct beiscsi_hba *phba,
req->reopen_type = reopen_type;
req->session_handle = sess_handle;
be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock);
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
return tag;
}
@ -244,29 +239,27 @@ unsigned int mgmt_get_boot_target(struct beiscsi_hba *phba)
struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb;
struct be_cmd_get_boot_target_req *req;
unsigned int tag = 0;
unsigned int tag;
beiscsi_log(phba, KERN_INFO,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BG_%d : In bescsi_get_boot_target\n");
spin_lock(&ctrl->mbox_lock);
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
return tag;
mutex_lock(&ctrl->mbox_lock);
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
return 0;
}
wrb = wrb_from_mccq(phba);
req = embedded_payload(wrb);
wrb->tag0 |= tag;
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET,
sizeof(struct be_cmd_get_boot_target_resp));
be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock);
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
return tag;
}
@ -276,7 +269,7 @@ unsigned int mgmt_get_session_info(struct beiscsi_hba *phba,
{
struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb;
unsigned int tag = 0;
unsigned int tag;
struct be_cmd_get_session_req *req;
struct be_cmd_get_session_resp *resp;
struct be_sge *sge;
@ -285,22 +278,17 @@ unsigned int mgmt_get_session_info(struct beiscsi_hba *phba,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BG_%d : In beiscsi_get_session_info\n");
spin_lock(&ctrl->mbox_lock);
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
return tag;
mutex_lock(&ctrl->mbox_lock);
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
return 0;
}
nonemb_cmd->size = sizeof(*resp);
req = nonemb_cmd->va;
memset(req, 0, sizeof(*req));
wrb = wrb_from_mccq(phba);
sge = nonembedded_sgl(wrb);
wrb->tag0 |= tag;
wrb->tag0 |= tag;
be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
OPCODE_ISCSI_INI_SESSION_GET_A_SESSION,
@ -310,11 +298,53 @@ unsigned int mgmt_get_session_info(struct beiscsi_hba *phba,
sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
sge->len = cpu_to_le32(nonemb_cmd->size);
be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock);
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
return tag;
}
/**
* mgmt_get_port_name()- Get port name for the function
* @ctrl: ptr to Ctrl Info
* @phba: ptr to the dev priv structure
*
* Get the alphanumeric character for port
*
**/
int mgmt_get_port_name(struct be_ctrl_info *ctrl,
struct beiscsi_hba *phba)
{
int ret = 0;
struct be_mcc_wrb *wrb;
struct be_cmd_get_port_name *ioctl;
mutex_lock(&ctrl->mbox_lock);
wrb = wrb_from_mbox(&ctrl->mbox_mem);
memset(wrb, 0, sizeof(*wrb));
ioctl = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*ioctl), true, 0);
be_cmd_hdr_prepare(&ioctl->h.req_hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_GET_PORT_NAME,
EMBED_MBX_MAX_PAYLOAD_SIZE);
ret = be_mbox_notify(ctrl);
phba->port_name = 0;
if (!ret) {
phba->port_name = ioctl->p.resp.port_names >>
(phba->fw_config.phys_port * 8) & 0xff;
} else {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
"BG_%d : GET_PORT_NAME ret 0x%x status 0x%x\n",
ret, ioctl->h.resp_hdr.status);
}
if (phba->port_name == 0)
phba->port_name = '?';
mutex_unlock(&ctrl->mbox_lock);
return ret;
}
/**
* mgmt_get_fw_config()- Get the FW config for the function
* @ctrl: ptr to Ctrl Info
@ -331,91 +361,147 @@ int mgmt_get_fw_config(struct be_ctrl_info *ctrl,
struct beiscsi_hba *phba)
{
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
struct be_fw_cfg *req = embedded_payload(wrb);
int status = 0;
struct be_fw_cfg *pfw_cfg = embedded_payload(wrb);
uint32_t cid_count, icd_count;
int status = -EINVAL;
uint8_t ulp_num = 0;
spin_lock(&ctrl->mbox_lock);
mutex_lock(&ctrl->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*pfw_cfg), true, 0);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
be_cmd_hdr_prepare(&pfw_cfg->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
EMBED_MBX_MAX_PAYLOAD_SIZE);
status = be_mbox_notify(ctrl);
if (!status) {
uint8_t ulp_num = 0;
struct be_fw_cfg *pfw_cfg;
pfw_cfg = req;
if (!is_chip_be2_be3r(phba)) {
phba->fw_config.eqid_count = pfw_cfg->eqid_count;
phba->fw_config.cqid_count = pfw_cfg->cqid_count;
beiscsi_log(phba, KERN_INFO,
BEISCSI_LOG_INIT,
"BG_%d : EQ_Count : %d CQ_Count : %d\n",
phba->fw_config.eqid_count,
phba->fw_config.cqid_count);
}
for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++)
if (pfw_cfg->ulp[ulp_num].ulp_mode &
BEISCSI_ULP_ISCSI_INI_MODE)
set_bit(ulp_num,
&phba->fw_config.ulp_supported);
phba->fw_config.phys_port = pfw_cfg->phys_port;
for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {
if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) {
phba->fw_config.iscsi_cid_start[ulp_num] =
pfw_cfg->ulp[ulp_num].sq_base;
phba->fw_config.iscsi_cid_count[ulp_num] =
pfw_cfg->ulp[ulp_num].sq_count;
phba->fw_config.iscsi_icd_start[ulp_num] =
pfw_cfg->ulp[ulp_num].icd_base;
phba->fw_config.iscsi_icd_count[ulp_num] =
pfw_cfg->ulp[ulp_num].icd_count;
phba->fw_config.iscsi_chain_start[ulp_num] =
pfw_cfg->chain_icd[ulp_num].chain_base;
phba->fw_config.iscsi_chain_count[ulp_num] =
pfw_cfg->chain_icd[ulp_num].chain_count;
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
"BG_%d : Function loaded on ULP : %d\n"
"\tiscsi_cid_count : %d\n"
"\tiscsi_cid_start : %d\n"
"\t iscsi_icd_count : %d\n"
"\t iscsi_icd_start : %d\n",
ulp_num,
phba->fw_config.
iscsi_cid_count[ulp_num],
phba->fw_config.
iscsi_cid_start[ulp_num],
phba->fw_config.
iscsi_icd_count[ulp_num],
phba->fw_config.
iscsi_icd_start[ulp_num]);
}
}
phba->fw_config.dual_ulp_aware = (pfw_cfg->function_mode &
BEISCSI_FUNC_DUA_MODE);
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
"BG_%d : DUA Mode : 0x%x\n",
phba->fw_config.dual_ulp_aware);
} else {
if (be_mbox_notify(ctrl)) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BG_%d : Failed in mgmt_get_fw_config\n");
status = -EINVAL;
goto fail_init;
}
spin_unlock(&ctrl->mbox_lock);
/* FW response formats depend on port id */
phba->fw_config.phys_port = pfw_cfg->phys_port;
if (phba->fw_config.phys_port >= BEISCSI_PHYS_PORT_MAX) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BG_%d : invalid physical port id %d\n",
phba->fw_config.phys_port);
goto fail_init;
}
/* populate and check FW config against min and max values */
if (!is_chip_be2_be3r(phba)) {
phba->fw_config.eqid_count = pfw_cfg->eqid_count;
phba->fw_config.cqid_count = pfw_cfg->cqid_count;
if (phba->fw_config.eqid_count == 0 ||
phba->fw_config.eqid_count > 2048) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BG_%d : invalid EQ count %d\n",
phba->fw_config.eqid_count);
goto fail_init;
}
if (phba->fw_config.cqid_count == 0 ||
phba->fw_config.cqid_count > 4096) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BG_%d : invalid CQ count %d\n",
phba->fw_config.cqid_count);
goto fail_init;
}
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
"BG_%d : EQ_Count : %d CQ_Count : %d\n",
phba->fw_config.eqid_count,
phba->fw_config.cqid_count);
}
/**
* Check on which all ULP iSCSI Protocol is loaded.
* Set the Bit for those ULP. This set flag is used
* at all places in the code to check on which ULP
* iSCSi Protocol is loaded
**/
for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {
if (pfw_cfg->ulp[ulp_num].ulp_mode &
BEISCSI_ULP_ISCSI_INI_MODE) {
set_bit(ulp_num, &phba->fw_config.ulp_supported);
/* Get the CID, ICD and Chain count for each ULP */
phba->fw_config.iscsi_cid_start[ulp_num] =
pfw_cfg->ulp[ulp_num].sq_base;
phba->fw_config.iscsi_cid_count[ulp_num] =
pfw_cfg->ulp[ulp_num].sq_count;
phba->fw_config.iscsi_icd_start[ulp_num] =
pfw_cfg->ulp[ulp_num].icd_base;
phba->fw_config.iscsi_icd_count[ulp_num] =
pfw_cfg->ulp[ulp_num].icd_count;
phba->fw_config.iscsi_chain_start[ulp_num] =
pfw_cfg->chain_icd[ulp_num].chain_base;
phba->fw_config.iscsi_chain_count[ulp_num] =
pfw_cfg->chain_icd[ulp_num].chain_count;
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
"BG_%d : Function loaded on ULP : %d\n"
"\tiscsi_cid_count : %d\n"
"\tiscsi_cid_start : %d\n"
"\t iscsi_icd_count : %d\n"
"\t iscsi_icd_start : %d\n",
ulp_num,
phba->fw_config.
iscsi_cid_count[ulp_num],
phba->fw_config.
iscsi_cid_start[ulp_num],
phba->fw_config.
iscsi_icd_count[ulp_num],
phba->fw_config.
iscsi_icd_start[ulp_num]);
}
}
if (phba->fw_config.ulp_supported == 0) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BG_%d : iSCSI initiator mode not set: ULP0 %x ULP1 %x\n",
pfw_cfg->ulp[BEISCSI_ULP0].ulp_mode,
pfw_cfg->ulp[BEISCSI_ULP1].ulp_mode);
goto fail_init;
}
/**
* ICD is shared among ULPs. Use icd_count of any one loaded ULP
**/
for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++)
if (test_bit(ulp_num, &phba->fw_config.ulp_supported))
break;
icd_count = phba->fw_config.iscsi_icd_count[ulp_num];
if (icd_count == 0 || icd_count > 65536) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BG_%d: invalid ICD count %d\n", icd_count);
goto fail_init;
}
cid_count = BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP0) +
BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP1);
if (cid_count == 0 || cid_count > 4096) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BG_%d: invalid CID count %d\n", cid_count);
goto fail_init;
}
/**
* Check FW is dual ULP aware i.e. can handle either
* of the protocols.
*/
phba->fw_config.dual_ulp_aware = (pfw_cfg->function_mode &
BEISCSI_FUNC_DUA_MODE);
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT,
"BG_%d : DUA Mode : 0x%x\n",
phba->fw_config.dual_ulp_aware);
/* all set, continue using this FW config */
status = 0;
fail_init:
mutex_unlock(&ctrl->mbox_lock);
return status;
}
@ -440,7 +526,7 @@ int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes);
req = nonemb_cmd.va;
memset(req, 0, sizeof(*req));
spin_lock(&ctrl->mbox_lock);
mutex_lock(&ctrl->mbox_lock);
memset(wrb, 0, sizeof(*wrb));
be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
@ -470,7 +556,7 @@ int mgmt_check_supported_fw(struct be_ctrl_info *ctrl,
} else
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BG_%d : Failed in mgmt_check_supported_fw\n");
spin_unlock(&ctrl->mbox_lock);
mutex_unlock(&ctrl->mbox_lock);
if (nonemb_cmd.va)
pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
@ -501,8 +587,9 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
req->region = region;
req->sector = sector;
req->offset = offset;
spin_lock(&ctrl->mbox_lock);
if (mutex_lock_interruptible(&ctrl->mbox_lock))
return 0;
switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) {
case BEISCSI_WRITE_FLASH:
offset = sector * sector_size + offset;
@ -521,28 +608,26 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
"BG_%d : Unsupported cmd = 0x%x\n\n",
bsg_req->rqst_data.h_vendor.vendor_cmd[0]);
spin_unlock(&ctrl->mbox_lock);
mutex_unlock(&ctrl->mbox_lock);
return -ENOSYS;
}
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
return tag;
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
return 0;
}
wrb = wrb_from_mccq(phba);
mcc_sge = nonembedded_sgl(wrb);
be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false,
job->request_payload.sg_cnt);
mcc_sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
mcc_sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
mcc_sge->len = cpu_to_le32(nonemb_cmd->size);
wrb->tag0 |= tag;
be_mcc_notify(phba);
be_mcc_notify(phba, tag);
spin_unlock(&ctrl->mbox_lock);
mutex_unlock(&ctrl->mbox_lock);
return tag;
}
@ -558,12 +643,19 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short ulp_num)
{
struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb = wrb_from_mccq(phba);
struct iscsi_cleanup_req *req = embedded_payload(wrb);
int status = 0;
struct be_mcc_wrb *wrb;
struct iscsi_cleanup_req *req;
unsigned int tag;
int status;
spin_lock(&ctrl->mbox_lock);
mutex_lock(&ctrl->mbox_lock);
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
return -EBUSY;
}
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));
@ -572,11 +664,12 @@ int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short ulp_num)
req->hdr_ring_id = cpu_to_le16(HWI_GET_DEF_HDRQ_ID(phba, ulp_num));
req->data_ring_id = cpu_to_le16(HWI_GET_DEF_BUFQ_ID(phba, ulp_num));
status = be_mcc_notify_wait(phba);
be_mcc_notify(phba, tag);
status = be_mcc_compl_poll(phba, tag);
if (status)
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT,
"BG_%d : mgmt_epfw_cleanup , FAILED\n");
spin_unlock(&ctrl->mbox_lock);
mutex_unlock(&ctrl->mbox_lock);
return status;
}
@ -590,20 +683,18 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
struct be_mcc_wrb *wrb;
struct be_sge *sge;
struct invalidate_commands_params_in *req;
unsigned int i, tag = 0;
unsigned int i, tag;
spin_lock(&ctrl->mbox_lock);
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
return 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));
wrb = wrb_from_mccq(phba);
sge = nonembedded_sgl(wrb);
wrb->tag0 |= tag;
be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
@ -621,8 +712,8 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
sge->len = cpu_to_le32(nonemb_cmd->size);
be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock);
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
return tag;
}
@ -637,16 +728,14 @@ unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba,
struct iscsi_invalidate_connection_params_in *req;
unsigned int tag = 0;
spin_lock(&ctrl->mbox_lock);
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
return tag;
mutex_lock(&ctrl->mbox_lock);
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
return 0;
}
wrb = wrb_from_mccq(phba);
wrb->tag0 |= tag;
req = embedded_payload(wrb);
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION,
@ -658,8 +747,8 @@ unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba,
else
req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE;
req->save_cfg = savecfg_flag;
be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock);
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
return tag;
}
@ -669,25 +758,23 @@ unsigned int mgmt_upload_connection(struct beiscsi_hba *phba,
struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb;
struct tcp_upload_params_in *req;
unsigned int tag = 0;
unsigned int tag;
spin_lock(&ctrl->mbox_lock);
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
return tag;
mutex_lock(&ctrl->mbox_lock);
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
return 0;
}
wrb = wrb_from_mccq(phba);
req = embedded_payload(wrb);
wrb->tag0 |= tag;
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD,
OPCODE_COMMON_TCP_UPLOAD, sizeof(*req));
req->id = (unsigned short)cid;
req->upload_type = (unsigned char)upload_flag;
be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock);
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
return tag;
}
@ -722,6 +809,13 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
unsigned short cid = beiscsi_ep->ep_cid;
struct be_sge *sge;
if (dst_addr->sa_family != PF_INET && dst_addr->sa_family != PF_INET6) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BG_%d : unknown addr family %d\n",
dst_addr->sa_family);
return -EINVAL;
}
phwi_ctrlr = phba->phwi_ctrlr;
phwi_context = phwi_ctrlr->phwi_ctxt;
@ -732,18 +826,17 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
ptemplate_address = &template_address;
ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address);
spin_lock(&ctrl->mbox_lock);
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
return tag;
if (mutex_lock_interruptible(&ctrl->mbox_lock))
return 0;
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
return 0;
}
wrb = wrb_from_mccq(phba);
sge = nonembedded_sgl(wrb);
sge = nonembedded_sgl(wrb);
req = nonemb_cmd->va;
memset(req, 0, sizeof(*req));
wrb->tag0 |= tag;
be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
@ -760,7 +853,8 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr;
beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port);
beiscsi_ep->ip_type = BE2_IPV4;
} else if (dst_addr->sa_family == PF_INET6) {
} else {
/* else its PF_INET6 family */
req->ip_address.ip_type = BE2_IPV6;
memcpy(&req->ip_address.addr,
&daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
@ -769,14 +863,6 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
memcpy(&beiscsi_ep->dst6_addr,
&daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
beiscsi_ep->ip_type = BE2_IPV6;
} else{
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BG_%d : unknown addr family %d\n",
dst_addr->sa_family);
spin_unlock(&ctrl->mbox_lock);
free_mcc_tag(&phba->ctrl, tag);
return -EINVAL;
}
req->cid = cid;
i = phba->nxt_cqid++;
@ -801,35 +887,45 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
req->tcp_window_scale_count = 2;
}
be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock);
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
return tag;
}
unsigned int mgmt_get_all_if_id(struct beiscsi_hba *phba)
{
struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
struct be_cmd_get_all_if_id_req *req = embedded_payload(wrb);
struct be_cmd_get_all_if_id_req *pbe_allid = req;
struct be_mcc_wrb *wrb;
struct be_cmd_get_all_if_id_req *req;
struct be_cmd_get_all_if_id_req *pbe_allid;
unsigned int tag;
int status = 0;
memset(wrb, 0, sizeof(*wrb));
spin_lock(&ctrl->mbox_lock);
if (mutex_lock_interruptible(&ctrl->mbox_lock))
return -EINTR;
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
return -ENOMEM;
}
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_NTWK_GET_ALL_IF_ID,
sizeof(*req));
status = be_mbox_notify(ctrl);
if (!status)
phba->interface_handle = pbe_allid->if_hndl_list[0];
else {
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
status = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL);
if (status) {
beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
"BG_%d : Failed in mgmt_get_all_if_id\n");
return -EBUSY;
}
spin_unlock(&ctrl->mbox_lock);
pbe_allid = embedded_payload(wrb);
phba->interface_handle = pbe_allid->if_hndl_list[0];
return status;
}
@ -852,27 +948,24 @@ static int mgmt_exec_nonemb_cmd(struct beiscsi_hba *phba,
unsigned int tag;
int rc = 0;
spin_lock(&ctrl->mbox_lock);
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
mutex_lock(&ctrl->mbox_lock);
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
rc = -ENOMEM;
goto free_cmd;
}
wrb = wrb_from_mccq(phba);
wrb->tag0 |= tag;
sge = nonembedded_sgl(wrb);
be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1);
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);
spin_unlock(&ctrl->mbox_lock);
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
rc = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd);
rc = beiscsi_mccq_compl_wait(phba, tag, NULL, nonemb_cmd);
if (resp_buf)
memcpy(resp_buf, nonemb_cmd->va, resp_buf_len);
@ -1003,8 +1096,9 @@ int mgmt_set_ip(struct beiscsi_hba *phba,
uint32_t ip_type;
int rc;
if (mgmt_get_all_if_id(phba))
return -EIO;
rc = mgmt_get_all_if_id(phba);
if (rc)
return rc;
ip_type = (ip_param->param == ISCSI_NET_PARAM_IPV6_ADDR) ?
BE2_IPV6 : BE2_IPV4 ;
@ -1173,8 +1267,9 @@ int mgmt_get_if_info(struct beiscsi_hba *phba, int ip_type,
uint32_t ioctl_size = sizeof(struct be_cmd_get_if_info_resp);
int rc;
if (mgmt_get_all_if_id(phba))
return -EIO;
rc = mgmt_get_all_if_id(phba);
if (rc)
return rc;
do {
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
@ -1245,55 +1340,27 @@ int mgmt_get_nic_conf(struct beiscsi_hba *phba,
unsigned int be_cmd_get_initname(struct beiscsi_hba *phba)
{
unsigned int tag = 0;
unsigned int tag;
struct be_mcc_wrb *wrb;
struct be_cmd_hba_name *req;
struct be_ctrl_info *ctrl = &phba->ctrl;
spin_lock(&ctrl->mbox_lock);
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
return tag;
if (mutex_lock_interruptible(&ctrl->mbox_lock))
return 0;
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
return 0;
}
wrb = wrb_from_mccq(phba);
req = embedded_payload(wrb);
wrb->tag0 |= tag;
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
OPCODE_ISCSI_INI_CFG_GET_HBA_NAME,
sizeof(*req));
be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock);
return tag;
}
unsigned int be_cmd_get_port_speed(struct beiscsi_hba *phba)
{
unsigned int tag = 0;
struct be_mcc_wrb *wrb;
struct be_cmd_ntwk_link_status_req *req;
struct be_ctrl_info *ctrl = &phba->ctrl;
spin_lock(&ctrl->mbox_lock);
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
return tag;
}
wrb = wrb_from_mccq(phba);
req = embedded_payload(wrb);
wrb->tag0 |= tag;
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_NTWK_LINK_STATUS_QUERY,
sizeof(*req));
be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock);
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
return tag;
}
@ -1330,7 +1397,7 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba,
return -EAGAIN;
}
rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
rc = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL);
if (rc) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
@ -1364,7 +1431,7 @@ int be_mgmt_get_boot_shandle(struct beiscsi_hba *phba,
return -EAGAIN;
}
rc = beiscsi_mccq_compl(phba, tag, NULL, NULL);
rc = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
if (rc) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,
@ -1406,7 +1473,7 @@ int mgmt_set_vlan(struct beiscsi_hba *phba,
return -EBUSY;
}
rc = beiscsi_mccq_compl(phba, tag, NULL, NULL);
rc = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
if (rc) {
beiscsi_log(phba, KERN_ERR,
(BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX),
@ -1749,19 +1816,17 @@ int beiscsi_logout_fw_sess(struct beiscsi_hba *phba,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BG_%d : In bescsi_logout_fwboot_sess\n");
spin_lock(&ctrl->mbox_lock);
tag = alloc_mcc_tag(phba);
if (!tag) {
spin_unlock(&ctrl->mbox_lock);
mutex_lock(&ctrl->mbox_lock);
wrb = alloc_mcc_wrb(phba, &tag);
if (!wrb) {
mutex_unlock(&ctrl->mbox_lock);
beiscsi_log(phba, KERN_INFO,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
"BG_%d : MBX Tag Failure\n");
return -EINVAL;
}
wrb = wrb_from_mccq(phba);
req = embedded_payload(wrb);
wrb->tag0 |= tag;
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI,
OPCODE_ISCSI_INI_SESSION_LOGOUT_TARGET,
@ -1769,10 +1834,10 @@ int beiscsi_logout_fw_sess(struct beiscsi_hba *phba,
/* Set the session handle */
req->session_handle = fw_sess_handle;
be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock);
be_mcc_notify(phba, tag);
mutex_unlock(&ctrl->mbox_lock);
rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
rc = beiscsi_mccq_compl_wait(phba, tag, &wrb, NULL);
if (rc) {
beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG,

View File

@ -268,6 +268,8 @@ struct beiscsi_endpoint {
int mgmt_get_fw_config(struct be_ctrl_info *ctrl,
struct beiscsi_hba *phba);
int mgmt_get_port_name(struct be_ctrl_info *ctrl,
struct beiscsi_hba *phba);
unsigned int mgmt_invalidate_connection(struct beiscsi_hba *phba,
struct beiscsi_endpoint *beiscsi_ep,

View File

@ -91,6 +91,25 @@ static bfa_ioc_mbox_mcfunc_t bfa_mbox_isrs[BFI_MC_MAX] = {
void
__bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)
{
int tail = trcm->tail;
struct bfa_trc_s *trc = &trcm->trc[tail];
if (trcm->stopped)
return;
trc->fileno = (u16) fileno;
trc->line = (u16) line;
trc->data.u64 = data;
trc->timestamp = BFA_TRC_TS(trcm);
trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
if (trcm->tail == trcm->head)
trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
}
static void
bfa_com_port_attach(struct bfa_s *bfa)
{

View File

@ -108,44 +108,11 @@ bfa_trc_stop(struct bfa_trc_mod_s *trcm)
trcm->stopped = 1;
}
static inline void
__bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data)
{
int tail = trcm->tail;
struct bfa_trc_s *trc = &trcm->trc[tail];
void
__bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data);
if (trcm->stopped)
return;
trc->fileno = (u16) fileno;
trc->line = (u16) line;
trc->data.u64 = data;
trc->timestamp = BFA_TRC_TS(trcm);
trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
if (trcm->tail == trcm->head)
trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
}
static inline void
__bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data)
{
int tail = trcm->tail;
struct bfa_trc_s *trc = &trcm->trc[tail];
if (trcm->stopped)
return;
trc->fileno = (u16) fileno;
trc->line = (u16) line;
trc->data.u32.u32 = data;
trc->timestamp = BFA_TRC_TS(trcm);
trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1);
if (trcm->tail == trcm->head)
trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1);
}
void
__bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data);
#define bfa_sm_fault(__mod, __event) do { \
bfa_trc(__mod, (((u32)0xDEAD << 16) | __event)); \

View File

@ -2803,7 +2803,7 @@ void
bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc, char *manufacturer)
{
memset((void *)manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
strncpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
}
void

View File

@ -97,6 +97,15 @@ static void __exit bnx2fc_mod_exit(void);
unsigned int bnx2fc_debug_level;
module_param_named(debug_logging, bnx2fc_debug_level, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(debug_logging,
"Option to enable extended logging,\n"
"\t\tDefault is 0 - no logging.\n"
"\t\t0x01 - SCSI cmd error, cleanup.\n"
"\t\t0x02 - Session setup, cleanup, etc.\n"
"\t\t0x04 - lport events, link, mtu, etc.\n"
"\t\t0x08 - ELS logs.\n"
"\t\t0x10 - fcoe L2 fame related logs.\n"
"\t\t0xff - LOG all messages.");
static int bnx2fc_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu);

View File

@ -1104,8 +1104,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
struct bnx2fc_cmd *io_req;
struct fc_lport *lport;
struct bnx2fc_rport *tgt;
int rc = FAILED;
int rc;
rc = fc_block_scsi_eh(sc_cmd);
if (rc)
@ -1114,7 +1113,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
lport = shost_priv(sc_cmd->device->host);
if ((lport->state != LPORT_ST_READY) || !(lport->link_up)) {
printk(KERN_ERR PFX "eh_abort: link not ready\n");
return rc;
return FAILED;
}
tgt = (struct bnx2fc_rport *)&rp[1];

View File

@ -34,7 +34,6 @@ extern const struct file_operations cxlflash_cxl_fops;
sectors
*/
#define NUM_RRQ_ENTRY 16 /* for master issued cmds */
#define MAX_RHT_PER_CONTEXT (PAGE_SIZE / sizeof(struct sisl_rht_entry))
/* AFU command retry limit */
@ -48,9 +47,12 @@ extern const struct file_operations cxlflash_cxl_fops;
index derivation
*/
#define CXLFLASH_MAX_CMDS 16
#define CXLFLASH_MAX_CMDS 256
#define CXLFLASH_MAX_CMDS_PER_LUN CXLFLASH_MAX_CMDS
/* RRQ for master issued cmds */
#define NUM_RRQ_ENTRY CXLFLASH_MAX_CMDS
static inline void check_sizes(void)
{
@ -149,7 +151,7 @@ struct afu_cmd {
struct afu {
/* Stuff requiring alignment go first. */
u64 rrq_entry[NUM_RRQ_ENTRY]; /* 128B RRQ */
u64 rrq_entry[NUM_RRQ_ENTRY]; /* 2K RRQ */
/*
* Command & data for AFU commands.
*/

View File

@ -726,11 +726,11 @@ static void term_mc(struct cxlflash_cfg *cfg, enum undo_level level)
*/
static void term_afu(struct cxlflash_cfg *cfg)
{
term_mc(cfg, UNDO_START);
if (cfg->afu)
stop_afu(cfg);
term_mc(cfg, UNDO_START);
pr_debug("%s: returning\n", __func__);
}
@ -767,7 +767,6 @@ static void cxlflash_remove(struct pci_dev *pdev)
cancel_work_sync(&cfg->work_q);
term_afu(cfg);
case INIT_STATE_PCI:
pci_release_regions(cfg->dev);
pci_disable_device(pdev);
case INIT_STATE_NONE:
free_mem(cfg);
@ -840,15 +839,6 @@ static int init_pci(struct cxlflash_cfg *cfg)
struct pci_dev *pdev = cfg->dev;
int rc = 0;
cfg->cxlflash_regs_pci = pci_resource_start(pdev, 0);
rc = pci_request_regions(pdev, CXLFLASH_NAME);
if (rc < 0) {
dev_err(&pdev->dev,
"%s: Couldn't register memory range of registers\n",
__func__);
goto out;
}
rc = pci_enable_device(pdev);
if (rc || pci_channel_offline(pdev)) {
if (pci_channel_offline(pdev)) {
@ -860,55 +850,13 @@ static int init_pci(struct cxlflash_cfg *cfg)
dev_err(&pdev->dev, "%s: Cannot enable adapter\n",
__func__);
cxlflash_wait_for_pci_err_recovery(cfg);
goto out_release_regions;
goto out;
}
}
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
if (rc < 0) {
dev_dbg(&pdev->dev, "%s: Failed to set 64 bit PCI DMA mask\n",
__func__);
rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
}
if (rc < 0) {
dev_err(&pdev->dev, "%s: Failed to set PCI DMA mask\n",
__func__);
goto out_disable;
}
pci_set_master(pdev);
if (pci_channel_offline(pdev)) {
cxlflash_wait_for_pci_err_recovery(cfg);
if (pci_channel_offline(pdev)) {
rc = -EIO;
goto out_msi_disable;
}
}
rc = pci_save_state(pdev);
if (rc != PCIBIOS_SUCCESSFUL) {
dev_err(&pdev->dev, "%s: Failed to save PCI config space\n",
__func__);
rc = -EIO;
goto cleanup_nolog;
}
out:
pr_debug("%s: returning rc=%d\n", __func__, rc);
return rc;
cleanup_nolog:
out_msi_disable:
cxlflash_wait_for_pci_err_recovery(cfg);
out_disable:
pci_disable_device(pdev);
out_release_regions:
pci_release_regions(pdev);
goto out;
}
/**
@ -2149,6 +2097,16 @@ static ssize_t lun_mode_store(struct device *dev,
rc = kstrtouint(buf, 10, &lun_mode);
if (!rc && (lun_mode < 5) && (lun_mode != afu->internal_lun)) {
afu->internal_lun = lun_mode;
/*
* When configured for internal LUN, there is only one channel,
* channel number 0, else there will be 2 (default).
*/
if (afu->internal_lun)
shost->max_channel = 0;
else
shost->max_channel = NUM_FC_PORTS - 1;
afu_reset(cfg);
scsi_scan_host(cfg->host);
}
@ -2295,7 +2253,7 @@ static struct scsi_host_template driver_template = {
.eh_device_reset_handler = cxlflash_eh_device_reset_handler,
.eh_host_reset_handler = cxlflash_eh_host_reset_handler,
.change_queue_depth = cxlflash_change_queue_depth,
.cmd_per_lun = 16,
.cmd_per_lun = CXLFLASH_MAX_CMDS_PER_LUN,
.can_queue = CXLFLASH_MAX_CMDS,
.this_id = -1,
.sg_tablesize = SG_NONE, /* No scatter gather support */
@ -2544,8 +2502,8 @@ static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev,
if (unlikely(rc))
dev_err(dev, "%s: Failed to mark user contexts!(%d)\n",
__func__, rc);
term_mc(cfg, UNDO_START);
stop_afu(cfg);
term_mc(cfg, UNDO_START);
return PCI_ERS_RESULT_NEED_RESET;
case pci_channel_io_perm_failure:
cfg->state = STATE_FAILTERM;

View File

@ -709,27 +709,32 @@ int cxlflash_disk_release(struct scsi_device *sdev,
* @cfg: Internal structure associated with the host.
* @ctxi: Context to release.
*
* Note that the rht_lun member of the context was cut from a single
* allocation when the context was created and therefore does not need
* to be explicitly freed. Also note that we conditionally check for the
* existence of the context control map before clearing the RHT registers
* and context capabilities because it is possible to destroy a context
* while the context is in the error state (previous mapping was removed
* [so we don't have to worry about clearing] and context is waiting for
* a new mapping).
* This routine is safe to be called with a a non-initialized context
* and is tolerant of being called with the context's mutex held (it
* will be unlocked if necessary before freeing). Also note that the
* routine conditionally checks for the existence of the context control
* map before clearing the RHT registers and context capabilities because
* it is possible to destroy a context while the context is in the error
* state (previous mapping was removed [so there is no need to worry about
* clearing] and context is waiting for a new mapping).
*/
static void destroy_context(struct cxlflash_cfg *cfg,
struct ctx_info *ctxi)
{
struct afu *afu = cfg->afu;
WARN_ON(!list_empty(&ctxi->luns));
if (ctxi->initialized) {
WARN_ON(!list_empty(&ctxi->luns));
/* Clear RHT registers and drop all capabilities for this context */
if (afu->afu_map && ctxi->ctrl_map) {
writeq_be(0, &ctxi->ctrl_map->rht_start);
writeq_be(0, &ctxi->ctrl_map->rht_cnt_id);
writeq_be(0, &ctxi->ctrl_map->ctx_cap);
/* Clear RHT registers and drop all capabilities for context */
if (afu->afu_map && ctxi->ctrl_map) {
writeq_be(0, &ctxi->ctrl_map->rht_start);
writeq_be(0, &ctxi->ctrl_map->rht_cnt_id);
writeq_be(0, &ctxi->ctrl_map->ctx_cap);
}
if (mutex_is_locked(&ctxi->mutex))
mutex_unlock(&ctxi->mutex);
}
/* Free memory associated with context */
@ -742,23 +747,12 @@ static void destroy_context(struct cxlflash_cfg *cfg,
/**
* create_context() - allocates and initializes a context
* @cfg: Internal structure associated with the host.
* @ctx: Previously obtained CXL context reference.
* @ctxid: Previously obtained process element associated with CXL context.
* @adap_fd: Previously obtained adapter fd associated with CXL context.
* @file: Previously obtained file associated with CXL context.
* @perms: User-specified permissions.
*
* The context's mutex is locked when an allocated context is returned.
*
* Return: Allocated context on success, NULL on failure
*/
static struct ctx_info *create_context(struct cxlflash_cfg *cfg,
struct cxl_context *ctx, int ctxid,
int adap_fd, struct file *file,
u32 perms)
static struct ctx_info *create_context(struct cxlflash_cfg *cfg)
{
struct device *dev = &cfg->dev->dev;
struct afu *afu = cfg->afu;
struct ctx_info *ctxi = NULL;
struct llun_info **lli = NULL;
u8 *ws = NULL;
@ -781,19 +775,6 @@ static struct ctx_info *create_context(struct cxlflash_cfg *cfg,
ctxi->rht_lun = lli;
ctxi->rht_needs_ws = ws;
ctxi->rht_start = rhte;
ctxi->rht_perms = perms;
ctxi->ctrl_map = &afu->afu_map->ctrls[ctxid].ctrl;
ctxi->ctxid = ENCODE_CTXID(ctxi, ctxid);
ctxi->lfd = adap_fd;
ctxi->pid = current->tgid; /* tgid = pid */
ctxi->ctx = ctx;
ctxi->file = file;
mutex_init(&ctxi->mutex);
INIT_LIST_HEAD(&ctxi->luns);
INIT_LIST_HEAD(&ctxi->list); /* initialize for list_empty() */
mutex_lock(&ctxi->mutex);
out:
return ctxi;
@ -805,6 +786,40 @@ err:
goto out;
}
/**
* init_context() - initializes a previously allocated context
* @ctxi: Previously allocated context
* @cfg: Internal structure associated with the host.
* @ctx: Previously obtained CXL context reference.
* @ctxid: Previously obtained process element associated with CXL context.
* @adap_fd: Previously obtained adapter fd associated with CXL context.
* @file: Previously obtained file associated with CXL context.
* @perms: User-specified permissions.
*
* Upon return, the context is marked as initialized and the context's mutex
* is locked.
*/
static void init_context(struct ctx_info *ctxi, struct cxlflash_cfg *cfg,
struct cxl_context *ctx, int ctxid, int adap_fd,
struct file *file, u32 perms)
{
struct afu *afu = cfg->afu;
ctxi->rht_perms = perms;
ctxi->ctrl_map = &afu->afu_map->ctrls[ctxid].ctrl;
ctxi->ctxid = ENCODE_CTXID(ctxi, ctxid);
ctxi->lfd = adap_fd;
ctxi->pid = current->tgid; /* tgid = pid */
ctxi->ctx = ctx;
ctxi->file = file;
ctxi->initialized = true;
mutex_init(&ctxi->mutex);
INIT_LIST_HEAD(&ctxi->luns);
INIT_LIST_HEAD(&ctxi->list); /* initialize for list_empty() */
mutex_lock(&ctxi->mutex);
}
/**
* _cxlflash_disk_detach() - detaches a LUN from a context
* @sdev: SCSI device associated with LUN.
@ -1300,9 +1315,9 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
u32 perms;
int ctxid = -1;
u64 rctxid = 0UL;
struct file *file;
struct file *file = NULL;
struct cxl_context *ctx;
struct cxl_context *ctx = NULL;
int fd = -1;
@ -1356,7 +1371,7 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
if (unlikely(!lun_access)) {
dev_err(dev, "%s: Unable to allocate lun_access!\n", __func__);
rc = -ENOMEM;
goto err0;
goto err;
}
lun_access->lli = lli;
@ -1371,36 +1386,19 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
goto out_attach;
}
ctxi = create_context(cfg);
if (unlikely(!ctxi)) {
dev_err(dev, "%s: Failed to create context! (%d)\n",
__func__, ctxid);
goto err;
}
ctx = cxl_dev_context_init(cfg->dev);
if (IS_ERR_OR_NULL(ctx)) {
dev_err(dev, "%s: Could not initialize context %p\n",
__func__, ctx);
rc = -ENODEV;
goto err1;
}
ctxid = cxl_process_element(ctx);
if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) {
dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid);
rc = -EPERM;
goto err2;
}
file = cxl_get_fd(ctx, &cfg->cxl_fops, &fd);
if (unlikely(fd < 0)) {
rc = -ENODEV;
dev_err(dev, "%s: Could not get file descriptor\n", __func__);
goto err2;
}
/* Translate read/write O_* flags from fcntl.h to AFU permission bits */
perms = SISL_RHT_PERM(attach->hdr.flags + 1);
ctxi = create_context(cfg, ctx, ctxid, fd, file, perms);
if (unlikely(!ctxi)) {
dev_err(dev, "%s: Failed to create context! (%d)\n",
__func__, ctxid);
goto err3;
goto err;
}
work = &ctxi->work;
@ -1411,13 +1409,33 @@ static int cxlflash_disk_attach(struct scsi_device *sdev,
if (unlikely(rc)) {
dev_dbg(dev, "%s: Could not start context rc=%d\n",
__func__, rc);
goto err4;
goto err;
}
ctxid = cxl_process_element(ctx);
if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) {
dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid);
rc = -EPERM;
goto err;
}
file = cxl_get_fd(ctx, &cfg->cxl_fops, &fd);
if (unlikely(fd < 0)) {
rc = -ENODEV;
dev_err(dev, "%s: Could not get file descriptor\n", __func__);
goto err;
}
/* Translate read/write O_* flags from fcntl.h to AFU permission bits */
perms = SISL_RHT_PERM(attach->hdr.flags + 1);
/* Context mutex is locked upon return */
init_context(ctxi, cfg, ctx, ctxid, fd, file, perms);
rc = afu_attach(cfg, ctxi);
if (unlikely(rc)) {
dev_err(dev, "%s: Could not attach AFU rc %d\n", __func__, rc);
goto err5;
goto err;
}
/*
@ -1453,13 +1471,14 @@ out:
__func__, ctxid, fd, attach->block_size, rc, attach->last_lba);
return rc;
err5:
cxl_stop_context(ctx);
err4:
put_context(ctxi);
destroy_context(cfg, ctxi);
ctxi = NULL;
err3:
err:
/* Cleanup CXL context; okay to 'stop' even if it was not started */
if (!IS_ERR_OR_NULL(ctx)) {
cxl_stop_context(ctx);
cxl_release_context(ctx);
ctx = NULL;
}
/*
* Here, we're overriding the fops with a dummy all-NULL fops because
* fput() calls the release fop, which will cause us to mistakenly
@ -1467,15 +1486,21 @@ err3:
* to that routine (cxlflash_cxl_release) we should try to fix the
* issue here.
*/
file->f_op = &null_fops;
fput(file);
put_unused_fd(fd);
fd = -1;
err2:
cxl_release_context(ctx);
err1:
if (fd > 0) {
file->f_op = &null_fops;
fput(file);
put_unused_fd(fd);
fd = -1;
file = NULL;
}
/* Cleanup our context; safe to call even with mutex locked */
if (ctxi) {
destroy_context(cfg, ctxi);
ctxi = NULL;
}
kfree(lun_access);
err0:
scsi_device_put(sdev);
goto out;
}
@ -1507,24 +1532,24 @@ static int recover_context(struct cxlflash_cfg *cfg, struct ctx_info *ctxi)
goto out;
}
rc = cxl_start_work(ctx, &ctxi->work);
if (unlikely(rc)) {
dev_dbg(dev, "%s: Could not start context rc=%d\n",
__func__, rc);
goto err1;
}
ctxid = cxl_process_element(ctx);
if (unlikely((ctxid >= MAX_CONTEXT) || (ctxid < 0))) {
dev_err(dev, "%s: ctxid (%d) invalid!\n", __func__, ctxid);
rc = -EPERM;
goto err1;
goto err2;
}
file = cxl_get_fd(ctx, &cfg->cxl_fops, &fd);
if (unlikely(fd < 0)) {
rc = -ENODEV;
dev_err(dev, "%s: Could not get file descriptor\n", __func__);
goto err1;
}
rc = cxl_start_work(ctx, &ctxi->work);
if (unlikely(rc)) {
dev_dbg(dev, "%s: Could not start context rc=%d\n",
__func__, rc);
goto err2;
}
@ -1569,10 +1594,10 @@ out:
return rc;
err3:
cxl_stop_context(ctx);
err2:
fput(file);
put_unused_fd(fd);
err2:
cxl_stop_context(ctx);
err1:
cxl_release_context(ctx);
goto out;

View File

@ -102,6 +102,7 @@ struct ctx_info {
u64 ctxid;
int lfd;
pid_t pid;
bool initialized;
bool unavail;
bool err_recovery_active;
struct mutex mutex; /* Context protection */

View File

@ -13,13 +13,13 @@ menuconfig SCSI_DH
config SCSI_DH_RDAC
tristate "LSI RDAC Device Handler"
depends on SCSI_DH
depends on SCSI_DH && SCSI
help
If you have a LSI RDAC select y. Otherwise, say N.
config SCSI_DH_HP_SW
tristate "HP/COMPAQ MSA Device Handler"
depends on SCSI_DH
depends on SCSI_DH && SCSI
help
If you have a HP/COMPAQ MSA device that requires START_STOP to
be sent to start it and cannot upgrade the firmware then select y.
@ -27,13 +27,13 @@ config SCSI_DH_HP_SW
config SCSI_DH_EMC
tristate "EMC CLARiiON Device Handler"
depends on SCSI_DH
depends on SCSI_DH && SCSI
help
If you have a EMC CLARiiON select y. Otherwise, say N.
config SCSI_DH_ALUA
tristate "SPC-3 ALUA Device Handler"
depends on SCSI_DH
depends on SCSI_DH && SCSI
help
SCSI Device handler for generic SPC-3 Asymmetric Logical Unit
Access (ALUA).

File diff suppressed because it is too large Load Diff

View File

@ -199,7 +199,12 @@ static int parse_sp_info_reply(struct scsi_device *sdev,
csdev->lun_state = csdev->buffer[4];
csdev->current_sp = csdev->buffer[8];
csdev->port = csdev->buffer[7];
if (csdev->lun_state == CLARIION_LUN_OWNED)
sdev->access_state = SCSI_ACCESS_STATE_OPTIMAL;
else
sdev->access_state = SCSI_ACCESS_STATE_STANDBY;
if (csdev->default_sp == csdev->current_sp)
sdev->access_state |= SCSI_ACCESS_STATE_PREFERRED;
out:
return err;
}

View File

@ -165,6 +165,7 @@ struct rdac_controller {
struct work_struct ms_work;
struct scsi_device *ms_sdev;
struct list_head ms_head;
struct list_head dh_list;
};
struct c2_inquiry {
@ -181,7 +182,9 @@ struct c2_inquiry {
};
struct rdac_dh_data {
struct list_head node;
struct rdac_controller *ctlr;
struct scsi_device *sdev;
#define UNINITIALIZED_LUN (1 << 8)
unsigned lun;
@ -392,6 +395,7 @@ static struct rdac_controller *get_controller(int index, char *array_name,
INIT_WORK(&ctlr->ms_work, send_mode_select);
INIT_LIST_HEAD(&ctlr->ms_head);
list_add(&ctlr->node, &ctlr_list);
INIT_LIST_HEAD(&ctlr->dh_list);
return ctlr;
}
@ -455,7 +459,8 @@ static int get_lun_info(struct scsi_device *sdev, struct rdac_dh_data *h,
static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h)
{
int err;
int err, access_state;
struct rdac_dh_data *tmp;
struct c9_inquiry *inqp;
h->state = RDAC_STATE_ACTIVE;
@ -471,19 +476,31 @@ static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h)
h->mode = RDAC_MODE; /* LUN in RDAC mode */
/* Update ownership */
if (inqp->avte_cvp & 0x1)
if (inqp->avte_cvp & 0x1) {
h->lun_state = RDAC_LUN_OWNED;
else {
access_state = SCSI_ACCESS_STATE_OPTIMAL;
} else {
h->lun_state = RDAC_LUN_UNOWNED;
if (h->mode == RDAC_MODE)
if (h->mode == RDAC_MODE) {
h->state = RDAC_STATE_PASSIVE;
access_state = SCSI_ACCESS_STATE_STANDBY;
} else
access_state = SCSI_ACCESS_STATE_ACTIVE;
}
/* Update path prio*/
if (inqp->path_prio & 0x1)
if (inqp->path_prio & 0x1) {
h->preferred = RDAC_PREFERRED;
else
access_state |= SCSI_ACCESS_STATE_PREFERRED;
} else
h->preferred = RDAC_NON_PREFERRED;
rcu_read_lock();
list_for_each_entry_rcu(tmp, &h->ctlr->dh_list, node) {
/* h->sdev should always be valid */
BUG_ON(!tmp->sdev);
tmp->sdev->access_state = access_state;
}
rcu_read_unlock();
}
return err;
@ -508,6 +525,10 @@ static int initialize_controller(struct scsi_device *sdev,
h->ctlr = get_controller(index, array_name, array_id, sdev);
if (!h->ctlr)
err = SCSI_DH_RES_TEMP_UNAVAIL;
else {
list_add_rcu(&h->node, &h->ctlr->dh_list);
h->sdev = sdev;
}
spin_unlock(&list_lock);
}
return err;
@ -829,8 +850,11 @@ static void rdac_bus_detach( struct scsi_device *sdev )
flush_workqueue(kmpath_rdacd);
spin_lock(&list_lock);
if (h->ctlr)
if (h->ctlr) {
list_del_rcu(&h->node);
h->sdev = NULL;
kref_put(&h->ctlr->kref, release_controller);
}
spin_unlock(&list_lock);
sdev->handler_data = NULL;
kfree(h);

View File

@ -180,11 +180,14 @@ static u8 adpt_read_blink_led(adpt_hba* host)
*============================================================================
*/
#ifdef MODULE
static struct pci_device_id dptids[] = {
{ PCI_DPT_VENDOR_ID, PCI_DPT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{ PCI_DPT_VENDOR_ID, PCI_DPT_RAPTOR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{ 0, }
};
#endif
MODULE_DEVICE_TABLE(pci,dptids);
static int adpt_detect(struct scsi_host_template* sht)

View File

@ -1360,14 +1360,15 @@ int esas2r_ioctl_handler(void *hostdata, int cmd, void __user *arg)
if (ioctl->header.channel == 0xFF) {
a = (struct esas2r_adapter *)hostdata;
} else {
a = esas2r_adapters[ioctl->header.channel];
if (ioctl->header.channel >= MAX_ADAPTERS || (a == NULL)) {
if (ioctl->header.channel >= MAX_ADAPTERS ||
esas2r_adapters[ioctl->header.channel] == NULL) {
ioctl->header.return_code = IOCTL_BAD_CHANNEL;
esas2r_log(ESAS2R_LOG_WARN, "bad channel value");
kfree(ioctl);
return -ENOTSUPP;
}
a = esas2r_adapters[ioctl->header.channel];
}
switch (cmd) {

View File

@ -1118,7 +1118,8 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
* If this is the first validated FCF, note the time and
* set a timer to trigger selection.
*/
if (mtu_valid && !fip->sel_fcf && fcoe_ctlr_fcf_usable(fcf)) {
if (mtu_valid && !fip->sel_fcf && !fip->sel_time &&
fcoe_ctlr_fcf_usable(fcf)) {
fip->sel_time = jiffies +
msecs_to_jiffies(FCOE_CTLR_START_DELAY);
if (!timer_pending(&fip->timer) ||

View File

@ -1768,7 +1768,7 @@ struct scsi_host_template fdomain_driver_template = {
};
#ifndef PCMCIA
#ifdef CONFIG_PCI
#if defined(CONFIG_PCI) && defined(MODULE)
static struct pci_device_id fdomain_pci_tbl[] = {
{ PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70,

View File

@ -2838,7 +2838,6 @@ static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, u16 source,
u16 idx, gdth_evt_data *evt)
{
gdth_evt_str *e;
struct timeval tv;
/* no GDTH_LOCK_HA() ! */
TRACE2(("gdth_store_event() source %d idx %d\n", source, idx));
@ -2854,8 +2853,7 @@ static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, u16 source,
!strcmp((char *)&ebuffer[elastidx].event_data.event_string,
(char *)&evt->event_string)))) {
e = &ebuffer[elastidx];
do_gettimeofday(&tv);
e->last_stamp = tv.tv_sec;
e->last_stamp = (u32)ktime_get_real_seconds();
++e->same_count;
} else {
if (ebuffer[elastidx].event_source != 0) { /* entry not free ? */
@ -2871,8 +2869,7 @@ static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, u16 source,
e = &ebuffer[elastidx];
e->event_source = source;
e->event_idx = idx;
do_gettimeofday(&tv);
e->first_stamp = e->last_stamp = tv.tv_sec;
e->first_stamp = e->last_stamp = (u32)ktime_get_real_seconds();
e->same_count = 1;
e->event_data = *evt;
e->application = 0;

View File

@ -148,7 +148,6 @@ int gdth_show_info(struct seq_file *m, struct Scsi_Host *host)
gdth_cmd_str *gdtcmd;
gdth_evt_str *estr;
char hrec[161];
struct timeval tv;
char *buf;
gdth_dskstat_str *pds;
@ -540,8 +539,14 @@ int gdth_show_info(struct seq_file *m, struct Scsi_Host *host)
if (estr->event_data.eu.driver.ionode == ha->hanum &&
estr->event_source == ES_ASYNC) {
gdth_log_event(&estr->event_data, hrec);
do_gettimeofday(&tv);
sec = (int)(tv.tv_sec - estr->first_stamp);
/*
* Elapsed seconds subtraction with unsigned operands is
* safe from wrap around in year 2106. Executes as:
* operand a + (2's complement operand b) + 1
*/
sec = (int)((u32)ktime_get_real_seconds() - estr->first_stamp);
if (sec < 0) sec = 0;
seq_printf(m," date- %02d:%02d:%02d\t%s\n",
sec/3600, sec%3600/60, sec%60, hrec);

View File

@ -1,2 +1,2 @@
obj-$(CONFIG_SCSI_HISI_SAS) += hisi_sas_main.o
obj-$(CONFIG_SCSI_HISI_SAS) += hisi_sas_v1_hw.o
obj-$(CONFIG_SCSI_HISI_SAS) += hisi_sas_v1_hw.o hisi_sas_v2_hw.o

View File

@ -12,22 +12,24 @@
#ifndef _HISI_SAS_H_
#define _HISI_SAS_H_
#include <linux/acpi.h>
#include <linux/dmapool.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <scsi/sas_ata.h>
#include <scsi/libsas.h>
#define DRV_VERSION "v1.0"
#define DRV_VERSION "v1.3"
#define HISI_SAS_MAX_PHYS 9
#define HISI_SAS_MAX_QUEUES 32
#define HISI_SAS_QUEUE_SLOTS 512
#define HISI_SAS_MAX_ITCT_ENTRIES 4096
#define HISI_SAS_MAX_ITCT_ENTRIES 2048
#define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES
#define HISI_SAS_COMMAND_ENTRIES 8192
#define HISI_SAS_STATUS_BUF_SZ \
(sizeof(struct hisi_sas_err_record) + 1024)
@ -36,6 +38,11 @@
#define HISI_SAS_MAX_SSP_RESP_SZ (sizeof(struct ssp_frame_hdr) + 1024)
#define HISI_SAS_MAX_SMP_RESP_SZ 1028
#define HISI_SAS_MAX_STP_RESP_SZ 28
#define DEV_IS_EXPANDER(type) \
((type == SAS_EDGE_EXPANDER_DEVICE) || \
(type == SAS_FANOUT_EXPANDER_DEVICE))
struct hisi_hba;
@ -105,6 +112,7 @@ struct hisi_sas_slot {
int cmplt_queue;
int cmplt_queue_slot;
int idx;
int abort;
void *cmd_hdr;
dma_addr_t cmd_hdr_dma;
void *status_buffer;
@ -113,6 +121,7 @@ struct hisi_sas_slot {
dma_addr_t command_table_dma;
struct hisi_sas_sge_page *sge_page;
dma_addr_t sge_page_dma;
struct work_struct abort_slot;
};
struct hisi_sas_tmf_task {
@ -132,6 +141,8 @@ struct hisi_sas_hw {
struct hisi_sas_tmf_task *tmf);
int (*prep_smp)(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot);
int (*prep_stp)(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot);
int (*slot_complete)(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot, int abort);
void (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no);
@ -140,6 +151,7 @@ struct hisi_sas_hw {
void (*free_device)(struct hisi_hba *hisi_hba,
struct hisi_sas_device *dev);
int (*get_wideport_bitmap)(struct hisi_hba *hisi_hba, int port_id);
int max_command_entries;
int complete_hdr_size;
};
@ -244,18 +256,7 @@ struct hisi_sas_itct {
__le64 sas_addr;
__le64 qw2;
__le64 qw3;
__le64 qw4;
__le64 qw_sata_ncq0_3;
__le64 qw_sata_ncq7_4;
__le64 qw_sata_ncq11_8;
__le64 qw_sata_ncq15_12;
__le64 qw_sata_ncq19_16;
__le64 qw_sata_ncq23_20;
__le64 qw_sata_ncq27_24;
__le64 qw_sata_ncq31_28;
__le64 qw_non_ncq_iptt;
__le64 qw_rsvd0;
__le64 qw_rsvd1;
__le64 qw4_15[12];
};
struct hisi_sas_iost {
@ -266,17 +267,7 @@ struct hisi_sas_iost {
};
struct hisi_sas_err_record {
/* dw0 */
__le32 dma_err_type;
/* dw1 */
__le32 trans_tx_fail_type;
/* dw2 */
__le32 trans_rx_fail_type;
/* dw3 */
u32 rsvd;
u32 data[4];
};
struct hisi_sas_initial_fis {

View File

@ -12,13 +12,12 @@
#include "hisi_sas.h"
#define DRV_NAME "hisi_sas"
#define DEV_IS_EXPANDER(type) \
((type == SAS_EDGE_EXPANDER_DEVICE) || \
(type == SAS_FANOUT_EXPANDER_DEVICE))
#define DEV_IS_GONE(dev) \
((!dev) || (dev->dev_type == SAS_PHY_UNUSED))
static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device,
u8 *lun, struct hisi_sas_tmf_task *tmf);
static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device)
{
return device->port->ha->lldd_ha;
@ -111,6 +110,50 @@ static int hisi_sas_task_prep_ssp(struct hisi_hba *hisi_hba,
return hisi_hba->hw->prep_ssp(hisi_hba, slot, is_tmf, tmf);
}
static int hisi_sas_task_prep_ata(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot)
{
return hisi_hba->hw->prep_stp(hisi_hba, slot);
}
/*
* This function will issue an abort TMF regardless of whether the
* task is in the sdev or not. Then it will do the task complete
* cleanup and callbacks.
*/
static void hisi_sas_slot_abort(struct work_struct *work)
{
struct hisi_sas_slot *abort_slot =
container_of(work, struct hisi_sas_slot, abort_slot);
struct sas_task *task = abort_slot->task;
struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev);
struct scsi_cmnd *cmnd = task->uldd_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 device *dev = &hisi_hba->pdev->dev;
int tag = abort_slot->idx;
if (!(task->task_proto & SAS_PROTOCOL_SSP)) {
dev_err(dev, "cannot abort slot for non-ssp task\n");
goto out;
}
int_to_scsilun(cmnd->device->lun, &lun);
tmf_task.tmf = TMF_ABORT_TASK;
tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag);
hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun, &tmf_task);
out:
/* Do cleanup for this task */
hisi_sas_slot_task_free(hisi_hba, task, abort_slot);
if (task->task_done)
task->task_done(task);
if (sas_dev && sas_dev->running_req)
sas_dev->running_req--;
}
static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
int is_tmf, struct hisi_sas_tmf_task *tmf,
int *pass)
@ -204,6 +247,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
slot->task = task;
slot->port = port;
task->lldd_task = slot;
INIT_WORK(&slot->abort_slot, hisi_sas_slot_abort);
slot->status_buffer = dma_pool_alloc(hisi_hba->status_buffer_pool,
GFP_ATOMIC,
@ -234,6 +278,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
case SAS_PROTOCOL_SATA:
case SAS_PROTOCOL_STP:
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
rc = hisi_sas_task_prep_ata(hisi_hba, slot);
break;
default:
dev_err(dev, "task prep: unknown/unsupported proto (0x%x)\n",
task->task_proto);
@ -407,6 +453,19 @@ static int hisi_sas_dev_found(struct domain_device *device)
return 0;
}
static int hisi_sas_slave_configure(struct scsi_device *sdev)
{
struct domain_device *dev = sdev_to_domain_dev(sdev);
int ret = sas_slave_configure(sdev);
if (ret)
return ret;
if (!dev_is_sata(dev))
sas_change_queue_depth(sdev, 64);
return 0;
}
static void hisi_sas_scan_start(struct Scsi_Host *shost)
{
struct hisi_hba *hisi_hba = shost_priv(shost);
@ -657,7 +716,7 @@ static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,
}
if (task->task_status.resp == SAS_TASK_COMPLETE &&
task->task_status.stat == SAM_STAT_GOOD) {
task->task_status.stat == TMF_RESP_FUNC_COMPLETE) {
res = TMF_RESP_FUNC_COMPLETE;
break;
}
@ -944,7 +1003,7 @@ static struct scsi_host_template hisi_sas_sht = {
.name = DRV_NAME,
.queuecommand = sas_queuecommand,
.target_alloc = sas_target_alloc,
.slave_configure = sas_slave_configure,
.slave_configure = hisi_sas_slave_configure,
.scan_finished = hisi_sas_scan_finished,
.scan_start = hisi_sas_scan_start,
.change_queue_depth = sas_change_queue_depth,
@ -977,9 +1036,9 @@ static struct sas_domain_function_template hisi_sas_transport_ops = {
static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
{
int i, s;
struct platform_device *pdev = hisi_hba->pdev;
struct device *dev = &pdev->dev;
int i, s, max_command_entries = hisi_hba->hw->max_command_entries;
spin_lock_init(&hisi_hba->lock);
for (i = 0; i < hisi_hba->n_phy; i++) {
@ -1039,13 +1098,13 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
memset(hisi_hba->itct, 0, s);
hisi_hba->slot_info = devm_kcalloc(dev, HISI_SAS_COMMAND_ENTRIES,
hisi_hba->slot_info = devm_kcalloc(dev, max_command_entries,
sizeof(struct hisi_sas_slot),
GFP_KERNEL);
if (!hisi_hba->slot_info)
goto err_out;
s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_iost);
s = max_command_entries * sizeof(struct hisi_sas_iost);
hisi_hba->iost = dma_alloc_coherent(dev, s, &hisi_hba->iost_dma,
GFP_KERNEL);
if (!hisi_hba->iost)
@ -1053,7 +1112,7 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
memset(hisi_hba->iost, 0, s);
s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint);
s = max_command_entries * sizeof(struct hisi_sas_breakpoint);
hisi_hba->breakpoint = dma_alloc_coherent(dev, s,
&hisi_hba->breakpoint_dma, GFP_KERNEL);
if (!hisi_hba->breakpoint)
@ -1061,7 +1120,7 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
memset(hisi_hba->breakpoint, 0, s);
hisi_hba->slot_index_count = HISI_SAS_COMMAND_ENTRIES;
hisi_hba->slot_index_count = max_command_entries;
s = hisi_hba->slot_index_count / sizeof(unsigned long);
hisi_hba->slot_index_tags = devm_kzalloc(dev, s, GFP_KERNEL);
if (!hisi_hba->slot_index_tags)
@ -1079,7 +1138,7 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
goto err_out;
memset(hisi_hba->initial_fis, 0, s);
s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint) * 2;
s = max_command_entries * sizeof(struct hisi_sas_breakpoint) * 2;
hisi_hba->sata_breakpoint = dma_alloc_coherent(dev, s,
&hisi_hba->sata_breakpoint_dma, GFP_KERNEL);
if (!hisi_hba->sata_breakpoint)
@ -1102,7 +1161,7 @@ err_out:
static void hisi_sas_free(struct hisi_hba *hisi_hba)
{
struct device *dev = &hisi_hba->pdev->dev;
int i, s;
int i, s, max_command_entries = hisi_hba->hw->max_command_entries;
for (i = 0; i < hisi_hba->queue_count; i++) {
s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
@ -1127,12 +1186,12 @@ static void hisi_sas_free(struct hisi_hba *hisi_hba)
dma_free_coherent(dev, s,
hisi_hba->itct, hisi_hba->itct_dma);
s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_iost);
s = max_command_entries * sizeof(struct hisi_sas_iost);
if (hisi_hba->iost)
dma_free_coherent(dev, s,
hisi_hba->iost, hisi_hba->iost_dma);
s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint);
s = max_command_entries * sizeof(struct hisi_sas_breakpoint);
if (hisi_hba->breakpoint)
dma_free_coherent(dev, s,
hisi_hba->breakpoint,
@ -1145,7 +1204,7 @@ static void hisi_sas_free(struct hisi_hba *hisi_hba)
hisi_hba->initial_fis,
hisi_hba->initial_fis_dma);
s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint) * 2;
s = max_command_entries * sizeof(struct hisi_sas_breakpoint) * 2;
if (hisi_hba->sata_breakpoint)
dma_free_coherent(dev, s,
hisi_hba->sata_breakpoint,
@ -1163,7 +1222,6 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
struct hisi_hba *hisi_hba;
struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
struct property *sas_addr_prop;
shost = scsi_host_alloc(&hisi_sas_sht, sizeof(*hisi_hba));
if (!shost)
@ -1177,27 +1235,34 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
init_timer(&hisi_hba->timer);
sas_addr_prop = of_find_property(np, "sas-addr", NULL);
if (!sas_addr_prop || (sas_addr_prop->length != SAS_ADDR_SIZE))
goto err_out;
memcpy(hisi_hba->sas_addr, sas_addr_prop->value, SAS_ADDR_SIZE);
if (of_property_read_u32(np, "ctrl-reset-reg",
&hisi_hba->ctrl_reset_reg))
if (device_property_read_u8_array(dev, "sas-addr", hisi_hba->sas_addr,
SAS_ADDR_SIZE))
goto err_out;
if (of_property_read_u32(np, "ctrl-reset-sts-reg",
&hisi_hba->ctrl_reset_sts_reg))
if (np) {
hisi_hba->ctrl = syscon_regmap_lookup_by_phandle(np,
"hisilicon,sas-syscon");
if (IS_ERR(hisi_hba->ctrl))
goto err_out;
if (device_property_read_u32(dev, "ctrl-reset-reg",
&hisi_hba->ctrl_reset_reg))
goto err_out;
if (device_property_read_u32(dev, "ctrl-reset-sts-reg",
&hisi_hba->ctrl_reset_sts_reg))
goto err_out;
if (device_property_read_u32(dev, "ctrl-clock-ena-reg",
&hisi_hba->ctrl_clock_ena_reg))
goto err_out;
}
if (device_property_read_u32(dev, "phy-count", &hisi_hba->n_phy))
goto err_out;
if (of_property_read_u32(np, "ctrl-clock-ena-reg",
&hisi_hba->ctrl_clock_ena_reg))
goto err_out;
if (of_property_read_u32(np, "phy-count", &hisi_hba->n_phy))
goto err_out;
if (of_property_read_u32(np, "queue-count", &hisi_hba->queue_count))
if (device_property_read_u32(dev, "queue-count",
&hisi_hba->queue_count))
goto err_out;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -1205,11 +1270,6 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
if (IS_ERR(hisi_hba->regs))
goto err_out;
hisi_hba->ctrl = syscon_regmap_lookup_by_phandle(
np, "hisilicon,sas-syscon");
if (IS_ERR(hisi_hba->ctrl))
goto err_out;
if (hisi_sas_alloc(hisi_hba, shost)) {
hisi_sas_free(hisi_hba);
goto err_out;
@ -1277,8 +1337,8 @@ int hisi_sas_probe(struct platform_device *pdev,
shost->max_channel = 1;
shost->max_cmd_len = 16;
shost->sg_tablesize = min_t(u16, SG_ALL, HISI_SAS_SGE_PAGE_CNT);
shost->can_queue = HISI_SAS_COMMAND_ENTRIES;
shost->cmd_per_lun = HISI_SAS_COMMAND_ENTRIES;
shost->can_queue = hisi_hba->hw->max_command_entries;
shost->cmd_per_lun = hisi_hba->hw->max_command_entries;
sha->sas_ha_name = DRV_NAME;
sha->dev = &hisi_hba->pdev->dev;

View File

@ -288,6 +288,20 @@ struct hisi_sas_complete_v1_hdr {
__le32 data;
};
struct hisi_sas_err_record_v1 {
/* dw0 */
__le32 dma_err_type;
/* dw1 */
__le32 trans_tx_fail_type;
/* dw2 */
__le32 trans_rx_fail_type;
/* dw3 */
u32 rsvd;
};
enum {
HISI_SAS_PHY_BCAST_ACK = 0,
HISI_SAS_PHY_SL_PHY_ENABLED,
@ -392,6 +406,8 @@ enum {
TRANS_RX_SMP_RESP_TIMEOUT_ERR, /* 0x31a */
};
#define HISI_SAS_COMMAND_ENTRIES_V1_HW 8192
#define HISI_SAS_PHY_MAX_INT_NR (HISI_SAS_PHY_INT_NR * HISI_SAS_MAX_PHYS)
#define HISI_SAS_CQ_MAX_INT_NR (HISI_SAS_MAX_QUEUES)
#define HISI_SAS_FATAL_INT_NR (2)
@ -607,31 +623,42 @@ static int reset_hw_v1_hw(struct hisi_hba *hisi_hba)
return -EIO;
}
/* Apply reset and disable clock */
/* clk disable reg is offset by +4 bytes from clk enable reg */
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg,
RESET_VALUE);
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg + 4,
RESET_VALUE);
msleep(1);
regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg, &val);
if (RESET_VALUE != (val & RESET_VALUE)) {
dev_err(dev, "Reset failed\n");
return -EIO;
}
if (ACPI_HANDLE(dev)) {
acpi_status s;
/* De-reset and enable clock */
/* deassert rst reg is offset by +4 bytes from assert reg */
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg + 4,
RESET_VALUE);
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg,
RESET_VALUE);
msleep(1);
regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg, &val);
if (val & RESET_VALUE) {
dev_err(dev, "De-reset failed\n");
return -EIO;
}
s = acpi_evaluate_object(ACPI_HANDLE(dev), "_RST", NULL, NULL);
if (ACPI_FAILURE(s)) {
dev_err(dev, "Reset failed\n");
return -EIO;
}
} else if (hisi_hba->ctrl) {
/* Apply reset and disable clock */
/* clk disable reg is offset by +4 bytes from clk enable reg */
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg,
RESET_VALUE);
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg + 4,
RESET_VALUE);
msleep(1);
regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg, &val);
if (RESET_VALUE != (val & RESET_VALUE)) {
dev_err(dev, "Reset failed\n");
return -EIO;
}
/* De-reset and enable clock */
/* deassert rst reg is offset by +4 bytes from assert reg */
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg + 4,
RESET_VALUE);
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg,
RESET_VALUE);
msleep(1);
regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg, &val);
if (val & RESET_VALUE) {
dev_err(dev, "De-reset failed\n");
return -EIO;
}
} else
dev_warn(dev, "no reset method\n");
return 0;
}
@ -1096,7 +1123,7 @@ static void slot_err_v1_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot)
{
struct task_status_struct *ts = &task->task_status;
struct hisi_sas_err_record *err_record = slot->status_buffer;
struct hisi_sas_err_record_v1 *err_record = slot->status_buffer;
struct device *dev = &hisi_hba->pdev->dev;
switch (task->task_proto) {
@ -1185,6 +1212,14 @@ static void slot_err_v1_hw(struct hisi_hba *hisi_hba,
ts->stat = SAS_NAK_R_ERR;
break;
}
case TRANS_TX_CREDIT_TIMEOUT_ERR:
case TRANS_TX_CLOSE_NORMAL_ERR:
{
/* This will request a retry */
ts->stat = SAS_QUEUE_FULL;
slot->abort = 1;
break;
}
default:
{
ts->stat = SAM_STAT_CHECK_CONDITION;
@ -1220,7 +1255,6 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba,
struct domain_device *device;
enum exec_status sts;
struct hisi_sas_complete_v1_hdr *complete_queue =
(struct hisi_sas_complete_v1_hdr *)
hisi_hba->complete_hdr[slot->cmplt_queue];
struct hisi_sas_complete_v1_hdr *complete_hdr;
u32 cmplt_hdr_data;
@ -1293,6 +1327,11 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba,
!(cmplt_hdr_data & CMPLT_HDR_RSPNS_XFRD_MSK)) {
slot_err_v1_hw(hisi_hba, task, slot);
if (unlikely(slot->abort)) {
queue_work(hisi_hba->wq, &slot->abort_slot);
/* immediately return and do not complete */
return ts->stat;
}
goto out;
}
@ -1796,6 +1835,7 @@ static const struct hisi_sas_hw hisi_sas_v1_hw = {
.phy_disable = disable_phy_v1_hw,
.phy_hard_reset = phy_hard_reset_v1_hw,
.get_wideport_bitmap = get_wideport_bitmap_v1_hw,
.max_command_entries = HISI_SAS_COMMAND_ENTRIES_V1_HW,
.complete_hdr_size = sizeof(struct hisi_sas_complete_v1_hdr),
};
@ -1815,12 +1855,20 @@ static const struct of_device_id sas_v1_of_match[] = {
};
MODULE_DEVICE_TABLE(of, sas_v1_of_match);
static const struct acpi_device_id sas_v1_acpi_match[] = {
{ "HISI0161", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, sas_v1_acpi_match);
static struct platform_driver hisi_sas_v1_driver = {
.probe = hisi_sas_v1_probe,
.remove = hisi_sas_v1_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = sas_v1_of_match,
.acpi_match_table = ACPI_PTR(sas_v1_acpi_match),
},
};

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,7 @@
#include <linux/transport_class.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/idr.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
@ -42,7 +42,7 @@
#include "scsi_logging.h"
static atomic_t scsi_host_next_hn = ATOMIC_INIT(0); /* host_no for next new host */
static DEFINE_IDA(host_index_ida);
static void scsi_host_cls_release(struct device *dev)
@ -355,6 +355,8 @@ static void scsi_host_dev_release(struct device *dev)
kfree(shost->shost_data);
ida_simple_remove(&host_index_ida, shost->host_no);
if (parent)
put_device(parent);
kfree(shost);
@ -388,6 +390,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
{
struct Scsi_Host *shost;
gfp_t gfp_mask = GFP_KERNEL;
int index;
if (sht->unchecked_isa_dma && privsize)
gfp_mask |= __GFP_DMA;
@ -406,11 +409,11 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
init_waitqueue_head(&shost->host_wait);
mutex_init(&shost->scan_mutex);
/*
* subtract one because we increment first then return, but we need to
* know what the next host number was before increment
*/
shost->host_no = atomic_inc_return(&scsi_host_next_hn) - 1;
index = ida_simple_get(&host_index_ida, 0, 0, GFP_KERNEL);
if (index < 0)
goto fail_kfree;
shost->host_no = index;
shost->dma_channel = 0xff;
/* These three are default values which can be overridden */
@ -495,7 +498,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
shost_printk(KERN_WARNING, shost,
"error handler thread failed to spawn, error = %ld\n",
PTR_ERR(shost->ehandler));
goto fail_kfree;
goto fail_index_remove;
}
shost->tmf_work_q = alloc_workqueue("scsi_tmf_%d",
@ -511,6 +514,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
fail_kthread:
kthread_stop(shost->ehandler);
fail_index_remove:
ida_simple_remove(&host_index_ida, shost->host_no);
fail_kfree:
kfree(shost);
return NULL;
@ -606,6 +611,7 @@ int scsi_init_hosts(void)
void scsi_exit_hosts(void)
{
class_unregister(&shost_class);
ida_destroy(&host_index_ida);
}
int scsi_is_host_device(const struct device *dev)

View File

@ -1,5 +1,6 @@
/*
* Disk Array driver for HP Smart Array SAS controllers
* Copyright 2016 Microsemi Corporation
* Copyright 2014-2015 PMC-Sierra, Inc.
* Copyright 2000,2009-2015 Hewlett-Packard Development Company, L.P.
*
@ -12,7 +13,7 @@
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more details.
*
* Questions/Comments/Bugfixes to storagedev@pmcs.com
* Questions/Comments/Bugfixes to esc.storagedev@microsemi.com
*
*/
@ -809,7 +810,8 @@ static ssize_t path_info_show(struct device *dev,
PAGE_SIZE - output_len,
"PORT: %.2s ",
phys_connector);
if (hdev->devtype == TYPE_DISK && hdev->expose_device) {
if ((hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC) &&
hdev->expose_device) {
if (box == 0 || box == 0xFF) {
output_len += scnprintf(buf + output_len,
PAGE_SIZE - output_len,
@ -1166,6 +1168,7 @@ static void hpsa_show_dev_msg(const char *level, struct ctlr_info *h,
snprintf(label, LABEL_SIZE, "enclosure");
break;
case TYPE_DISK:
case TYPE_ZBC:
if (dev->external)
snprintf(label, LABEL_SIZE, "external");
else if (!is_logical_dev_addr_mode(dev->scsi3addr))
@ -1636,6 +1639,8 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h,
continue;
if (dev[j]->devtype != TYPE_DISK)
continue;
if (dev[j]->devtype != TYPE_ZBC)
continue;
if (is_logical_device(dev[j]))
continue;
if (dev[j]->ioaccel_handle != dd[i].ioaccel_handle)
@ -1681,6 +1686,8 @@ static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h,
continue;
if (dev[i]->devtype != TYPE_DISK)
continue;
if (dev[i]->devtype != TYPE_ZBC)
continue;
if (!is_logical_device(dev[i]))
continue;
@ -3208,8 +3215,10 @@ static void hpsa_get_enclosure_info(struct ctlr_info *h,
bmic_device_index = GET_BMIC_DRIVE_NUMBER(&rle->lunid[0]);
if (bmic_device_index == 0xFF00)
if (bmic_device_index == 0xFF00 || MASKED_DEVICE(&rle->lunid[0])) {
rc = IO_OK;
goto out;
}
bssbp = kzalloc(sizeof(*bssbp), GFP_KERNEL);
if (!bssbp)
@ -3657,18 +3666,6 @@ static int hpsa_device_supports_aborts(struct ctlr_info *h,
return rc;
}
static void sanitize_inquiry_string(unsigned char *s, int len)
{
bool terminated = false;
for (; len > 0; (--len, ++s)) {
if (*s == 0)
terminated = true;
if (terminated || *s < 0x20 || *s > 0x7e)
*s = ' ';
}
}
static int hpsa_update_device_info(struct ctlr_info *h,
unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device,
unsigned char *is_OBDR_device)
@ -3699,8 +3696,8 @@ static int hpsa_update_device_info(struct ctlr_info *h,
goto bail_out;
}
sanitize_inquiry_string(&inq_buff[8], 8);
sanitize_inquiry_string(&inq_buff[16], 16);
scsi_sanitize_inquiry_string(&inq_buff[8], 8);
scsi_sanitize_inquiry_string(&inq_buff[16], 16);
this_device->devtype = (inq_buff[0] & 0x1f);
memcpy(this_device->scsi3addr, scsi3addr, 8);
@ -3713,7 +3710,8 @@ static int hpsa_update_device_info(struct ctlr_info *h,
hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8,
sizeof(this_device->device_id));
if (this_device->devtype == TYPE_DISK &&
if ((this_device->devtype == TYPE_DISK ||
this_device->devtype == TYPE_ZBC) &&
is_logical_dev_addr_mode(scsi3addr)) {
int volume_offline;
@ -4181,6 +4179,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
ncurrent++;
break;
case TYPE_DISK:
case TYPE_ZBC:
if (this_device->physical_device) {
/* The disk is in HBA mode. */
/* Never use RAID mapper in HBA mode. */
@ -4197,7 +4196,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
ncurrent++;
break;
case TYPE_ENCLOSURE:
hpsa_get_enclosure_info(h, lunaddrbytes,
if (!this_device->external)
hpsa_get_enclosure_info(h, lunaddrbytes,
physdev_list, phys_dev_index,
this_device);
ncurrent++;
@ -4970,6 +4970,8 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h,
return IO_ACCEL_INELIGIBLE;
c->phys_disk = dev->phys_disk[map_index];
if (!c->phys_disk)
return IO_ACCEL_INELIGIBLE;
disk_handle = dd[map_index].ioaccel_handle;
disk_block = le64_to_cpu(map->disk_starting_blk) +
@ -5835,7 +5837,7 @@ static int hpsa_send_abort_ioaccel2(struct ctlr_info *h,
}
static int hpsa_send_abort_both_ways(struct ctlr_info *h,
unsigned char *scsi3addr, struct CommandList *abort, int reply_queue)
struct hpsa_scsi_dev_t *dev, struct CommandList *abort, int reply_queue)
{
/*
* ioccelerator mode 2 commands should be aborted via the
@ -5844,14 +5846,16 @@ static int hpsa_send_abort_both_ways(struct ctlr_info *h,
* Change abort to physical device reset when abort TMF is unsupported.
*/
if (abort->cmd_type == CMD_IOACCEL2) {
if (HPSATMF_IOACCEL_ENABLED & h->TMFSupportFlags)
if ((HPSATMF_IOACCEL_ENABLED & h->TMFSupportFlags) ||
dev->physical_device)
return hpsa_send_abort_ioaccel2(h, abort,
reply_queue);
else
return hpsa_send_reset_as_abort_ioaccel2(h, scsi3addr,
return hpsa_send_reset_as_abort_ioaccel2(h,
dev->scsi3addr,
abort, reply_queue);
}
return hpsa_send_abort(h, scsi3addr, abort, reply_queue);
return hpsa_send_abort(h, dev->scsi3addr, abort, reply_queue);
}
/* Find out which reply queue a command was meant to return on */
@ -5989,7 +5993,7 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
cmd_free(h, abort);
return FAILED;
}
rc = hpsa_send_abort_both_ways(h, dev->scsi3addr, abort, reply_queue);
rc = hpsa_send_abort_both_ways(h, dev, abort, reply_queue);
atomic_inc(&h->abort_cmds_available);
wake_up_all(&h->abort_cmd_wait_queue);
if (rc != 0) {

View File

@ -1,5 +1,6 @@
/*
* Disk Array driver for HP Smart Array SAS controllers
* Copyright 2016 Microsemi Corporation
* Copyright 2014-2015 PMC-Sierra, Inc.
* Copyright 2000,2009-2015 Hewlett-Packard Development Company, L.P.
*
@ -12,7 +13,7 @@
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more details.
*
* Questions/Comments/Bugfixes to storagedev@pmcs.com
* Questions/Comments/Bugfixes to esc.storagedev@microsemi.com
*
*/
#ifndef HPSA_H

View File

@ -1,5 +1,6 @@
/*
* Disk Array driver for HP Smart Array SAS controllers
* Copyright 2016 Microsemi Corporation
* Copyright 2014-2015 PMC-Sierra, Inc.
* Copyright 2000,2009-2015 Hewlett-Packard Development Company, L.P.
*
@ -12,7 +13,7 @@
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
* NON INFRINGEMENT. See the GNU General Public License for more details.
*
* Questions/Comments/Bugfixes to storagedev@pmcs.com
* Questions/Comments/Bugfixes to esc.storagedev@microsemi.com
*
*/
#ifndef HPSA_CMD_H
@ -289,7 +290,7 @@ struct SenseSubsystem_info {
#define BMIC_IDENTIFY_CONTROLLER 0x11
#define BMIC_SET_DIAG_OPTIONS 0xF4
#define BMIC_SENSE_DIAG_OPTIONS 0xF5
#define HPSA_DIAG_OPTS_DISABLE_RLD_CACHING 0x40000000
#define HPSA_DIAG_OPTS_DISABLE_RLD_CACHING 0x80000000
#define BMIC_SENSE_SUBSYSTEM_INFORMATION 0x66
#define BMIC_SENSE_STORAGE_BOX_PARAMS 0x65

View File

@ -2636,7 +2636,8 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
struct ibmvfc_target *tgt;
ibmvfc_log(vhost, desc->log_level, "%s event received. scsi_id: %llx, wwpn: %llx,"
" node_name: %llx%s\n", desc->desc, crq->scsi_id, crq->wwpn, crq->node_name,
" node_name: %llx%s\n", desc->desc, be64_to_cpu(crq->scsi_id),
be64_to_cpu(crq->wwpn), be64_to_cpu(crq->node_name),
ibmvfc_get_link_state(crq->link_state));
switch (be64_to_cpu(crq->event)) {

View File

@ -182,7 +182,7 @@ static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue)
spin_lock_irqsave(&queue->lock, flags);
crq = &queue->msgs[queue->cur];
if (crq->valid & 0x80) {
if (crq->valid != VIOSRP_CRQ_FREE) {
if (++queue->cur == queue->size)
queue->cur = 0;
@ -231,7 +231,7 @@ static void ibmvscsi_task(void *data)
/* Pull all the valid messages off the CRQ */
while ((crq = crq_queue_next_crq(&hostdata->queue)) != NULL) {
ibmvscsi_handle_crq(crq, hostdata);
crq->valid = 0x00;
crq->valid = VIOSRP_CRQ_FREE;
}
vio_enable_interrupts(vdev);
@ -239,7 +239,7 @@ static void ibmvscsi_task(void *data)
if (crq != NULL) {
vio_disable_interrupts(vdev);
ibmvscsi_handle_crq(crq, hostdata);
crq->valid = 0x00;
crq->valid = VIOSRP_CRQ_FREE;
} else {
done = 1;
}
@ -248,25 +248,23 @@ static void ibmvscsi_task(void *data)
static void gather_partition_info(void)
{
struct device_node *rootdn;
const char *ppartition_name;
const __be32 *p_number_ptr;
/* Retrieve information about this partition */
rootdn = of_find_node_by_path("/");
if (!rootdn) {
if (!of_root)
return;
}
ppartition_name = of_get_property(rootdn, "ibm,partition-name", NULL);
of_node_get(of_root);
ppartition_name = of_get_property(of_root, "ibm,partition-name", NULL);
if (ppartition_name)
strncpy(partition_name, ppartition_name,
sizeof(partition_name));
p_number_ptr = of_get_property(rootdn, "ibm,partition-no", NULL);
p_number_ptr = of_get_property(of_root, "ibm,partition-no", NULL);
if (p_number_ptr)
partition_number = of_read_number(p_number_ptr, 1);
of_node_put(rootdn);
of_node_put(of_root);
}
static void set_adapter_info(struct ibmvscsi_host_data *hostdata)
@ -283,8 +281,8 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata)
hostdata->madapter_info.partition_number =
cpu_to_be32(partition_number);
hostdata->madapter_info.mad_version = cpu_to_be32(1);
hostdata->madapter_info.os_type = cpu_to_be32(2);
hostdata->madapter_info.mad_version = cpu_to_be32(SRP_MAD_VERSION_1);
hostdata->madapter_info.os_type = cpu_to_be32(SRP_MAD_OS_LINUX);
}
/**
@ -316,7 +314,7 @@ static int ibmvscsi_reset_crq_queue(struct crq_queue *queue,
rc = plpar_hcall_norets(H_REG_CRQ,
vdev->unit_address,
queue->msg_token, PAGE_SIZE);
if (rc == 2) {
if (rc == H_CLOSED) {
/* Adapter is good, but other end is not ready */
dev_warn(hostdata->dev, "Partner adapter not ready\n");
} else if (rc != 0) {
@ -366,7 +364,7 @@ static int ibmvscsi_init_crq_queue(struct crq_queue *queue,
rc = ibmvscsi_reset_crq_queue(queue,
hostdata);
if (rc == 2) {
if (rc == H_CLOSED) {
/* Adapter is good, but other end is not ready */
dev_warn(hostdata->dev, "Partner adapter not ready\n");
retrc = 0;
@ -474,7 +472,7 @@ static int initialize_event_pool(struct event_pool *pool,
struct srp_event_struct *evt = &pool->events[i];
memset(&evt->crq, 0x00, sizeof(evt->crq));
atomic_set(&evt->free, 1);
evt->crq.valid = 0x80;
evt->crq.valid = VIOSRP_CRQ_CMD_RSP;
evt->crq.IU_length = cpu_to_be16(sizeof(*evt->xfer_iu));
evt->crq.IU_data_ptr = cpu_to_be64(pool->iu_token +
sizeof(*evt->xfer_iu) * i);
@ -1398,7 +1396,7 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct)
hostdata->host->max_sectors =
be32_to_cpu(hostdata->madapter_info.port_max_txu[0]) >> 9;
if (be32_to_cpu(hostdata->madapter_info.os_type) == 3 &&
if (be32_to_cpu(hostdata->madapter_info.os_type) == SRP_MAD_OS_AIX &&
strcmp(hostdata->madapter_info.srp_version, "1.6a") <= 0) {
dev_err(hostdata->dev, "host (Ver. %s) doesn't support large transfers\n",
hostdata->madapter_info.srp_version);
@ -1407,7 +1405,7 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct)
hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS;
}
if (be32_to_cpu(hostdata->madapter_info.os_type) == 3) {
if (be32_to_cpu(hostdata->madapter_info.os_type) == SRP_MAD_OS_AIX) {
enable_fast_fail(hostdata);
return;
}
@ -1767,9 +1765,9 @@ static void ibmvscsi_handle_crq(struct viosrp_crq *crq,
struct srp_event_struct *evt_struct =
(__force struct srp_event_struct *)crq->IU_data_ptr;
switch (crq->valid) {
case 0xC0: /* initialization */
case VIOSRP_CRQ_INIT_RSP: /* initialization */
switch (crq->format) {
case 0x01: /* Initialization message */
case VIOSRP_CRQ_INIT: /* Initialization message */
dev_info(hostdata->dev, "partner initialized\n");
/* Send back a response */
rc = ibmvscsi_send_crq(hostdata, 0xC002000000000000LL, 0);
@ -1781,7 +1779,7 @@ static void ibmvscsi_handle_crq(struct viosrp_crq *crq,
}
break;
case 0x02: /* Initialization response */
case VIOSRP_CRQ_INIT_COMPLETE: /* Initialization response */
dev_info(hostdata->dev, "partner initialization complete\n");
/* Now login */
@ -1791,7 +1789,7 @@ static void ibmvscsi_handle_crq(struct viosrp_crq *crq,
dev_err(hostdata->dev, "unknown crq message type: %d\n", crq->format);
}
return;
case 0xFF: /* Hypervisor telling us the connection is closed */
case VIOSRP_CRQ_XPORT_EVENT: /* Hypervisor telling us the connection is closed */
scsi_block_requests(hostdata->host);
atomic_set(&hostdata->request_limit, 0);
if (crq->format == 0x06) {
@ -1807,7 +1805,7 @@ static void ibmvscsi_handle_crq(struct viosrp_crq *crq,
ibmvscsi_reset_host(hostdata);
}
return;
case 0x80: /* real payload */
case VIOSRP_CRQ_CMD_RSP: /* real payload */
break;
default:
dev_err(hostdata->dev, "got an invalid message type 0x%02x\n",
@ -1854,62 +1852,6 @@ static void ibmvscsi_handle_crq(struct viosrp_crq *crq,
spin_unlock_irqrestore(evt_struct->hostdata->host->host_lock, flags);
}
/**
* ibmvscsi_get_host_config: Send the command to the server to get host
* configuration data. The data is opaque to us.
*/
static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
unsigned char *buffer, int length)
{
struct viosrp_host_config *host_config;
struct srp_event_struct *evt_struct;
unsigned long flags;
dma_addr_t addr;
int rc;
evt_struct = get_event_struct(&hostdata->pool);
if (!evt_struct) {
dev_err(hostdata->dev, "couldn't allocate event for HOST_CONFIG!\n");
return -1;
}
init_event_struct(evt_struct,
sync_completion,
VIOSRP_MAD_FORMAT,
info_timeout);
host_config = &evt_struct->iu.mad.host_config;
/* The transport length field is only 16-bit */
length = min(0xffff, length);
/* Set up a lun reset SRP command */
memset(host_config, 0x00, sizeof(*host_config));
host_config->common.type = cpu_to_be32(VIOSRP_HOST_CONFIG_TYPE);
host_config->common.length = cpu_to_be16(length);
addr = dma_map_single(hostdata->dev, buffer, length, DMA_BIDIRECTIONAL);
if (dma_mapping_error(hostdata->dev, addr)) {
if (!firmware_has_feature(FW_FEATURE_CMO))
dev_err(hostdata->dev,
"dma_mapping error getting host config\n");
free_event_struct(&hostdata->pool, evt_struct);
return -1;
}
host_config->buffer = cpu_to_be64(addr);
init_completion(&evt_struct->comp);
spin_lock_irqsave(hostdata->host->host_lock, flags);
rc = ibmvscsi_send_srp_event(evt_struct, hostdata, info_timeout * 2);
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
if (rc == 0)
wait_for_completion(&evt_struct->comp);
dma_unmap_single(hostdata->dev, addr, length, DMA_BIDIRECTIONAL);
return rc;
}
/**
* ibmvscsi_slave_configure: Set the "allow_restart" flag for each disk.
* @sdev: struct scsi_device device to configure
@ -2041,7 +1983,7 @@ static ssize_t show_host_partition_number(struct device *dev,
int len;
len = snprintf(buf, PAGE_SIZE, "%d\n",
hostdata->madapter_info.partition_number);
be32_to_cpu(hostdata->madapter_info.partition_number));
return len;
}
@ -2061,7 +2003,7 @@ static ssize_t show_host_mad_version(struct device *dev,
int len;
len = snprintf(buf, PAGE_SIZE, "%d\n",
hostdata->madapter_info.mad_version);
be32_to_cpu(hostdata->madapter_info.mad_version));
return len;
}
@ -2080,7 +2022,8 @@ static ssize_t show_host_os_type(struct device *dev,
struct ibmvscsi_host_data *hostdata = shost_priv(shost);
int len;
len = snprintf(buf, PAGE_SIZE, "%d\n", hostdata->madapter_info.os_type);
len = snprintf(buf, PAGE_SIZE, "%d\n",
be32_to_cpu(hostdata->madapter_info.os_type));
return len;
}
@ -2095,21 +2038,14 @@ static struct device_attribute ibmvscsi_host_os_type = {
static ssize_t show_host_config(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct ibmvscsi_host_data *hostdata = shost_priv(shost);
/* returns null-terminated host config data */
if (ibmvscsi_do_host_config(hostdata, buf, PAGE_SIZE) == 0)
return strlen(buf);
else
return 0;
return 0;
}
static struct device_attribute ibmvscsi_host_config = {
.attr = {
.name = "config",
.mode = S_IRUGO,
},
.name = "config",
.mode = S_IRUGO,
},
.show = show_host_config,
};

View File

@ -51,13 +51,25 @@ union srp_iu {
u8 reserved[SRP_MAX_IU_LEN];
};
enum viosrp_crq_headers {
VIOSRP_CRQ_FREE = 0x00,
VIOSRP_CRQ_CMD_RSP = 0x80,
VIOSRP_CRQ_INIT_RSP = 0xC0,
VIOSRP_CRQ_XPORT_EVENT = 0xFF
};
enum viosrp_crq_init_formats {
VIOSRP_CRQ_INIT = 0x01,
VIOSRP_CRQ_INIT_COMPLETE = 0x02
};
enum viosrp_crq_formats {
VIOSRP_SRP_FORMAT = 0x01,
VIOSRP_MAD_FORMAT = 0x02,
VIOSRP_OS400_FORMAT = 0x03,
VIOSRP_AIX_FORMAT = 0x04,
VIOSRP_LINUX_FORMAT = 0x06,
VIOSRP_INLINE_FORMAT = 0x07
VIOSRP_LINUX_FORMAT = 0x05,
VIOSRP_INLINE_FORMAT = 0x06
};
enum viosrp_crq_status {
@ -87,7 +99,6 @@ enum viosrp_mad_types {
VIOSRP_EMPTY_IU_TYPE = 0x01,
VIOSRP_ERROR_LOG_TYPE = 0x02,
VIOSRP_ADAPTER_INFO_TYPE = 0x03,
VIOSRP_HOST_CONFIG_TYPE = 0x04,
VIOSRP_CAPABILITIES_TYPE = 0x05,
VIOSRP_ENABLE_FAST_FAIL = 0x08,
};
@ -153,11 +164,6 @@ struct viosrp_adapter_info {
__be64 buffer;
};
struct viosrp_host_config {
struct mad_common common;
__be64 buffer;
};
struct viosrp_fast_fail {
struct mad_common common;
};
@ -195,7 +201,6 @@ union mad_iu {
struct viosrp_empty_iu empty_iu;
struct viosrp_error_log error_log;
struct viosrp_adapter_info adapter_info;
struct viosrp_host_config host_config;
struct viosrp_fast_fail fast_fail;
struct viosrp_capabilities capabilities;
};
@ -209,7 +214,10 @@ struct mad_adapter_info_data {
char srp_version[8];
char partition_name[96];
__be32 partition_number;
#define SRP_MAD_VERSION_1 1
__be32 mad_version;
#define SRP_MAD_OS_LINUX 2
#define SRP_MAD_OS_AIX 3
__be32 os_type;
__be32 port_max_txu[8]; /* per-port maximum transfer */
};

View File

@ -77,9 +77,10 @@ static void imm_wakeup(void *ref)
spin_lock_irqsave(&arbitration_lock, flags);
if (dev->wanted) {
parport_claim(dev->dev);
got_it(dev);
dev->wanted = 0;
if (parport_claim(dev->dev) == 0) {
got_it(dev);
dev->wanted = 0;
}
}
spin_unlock_irqrestore(&arbitration_lock, flags);
}

View File

@ -1054,11 +1054,11 @@ lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf,
{
struct dentry *dent = file->f_path.dentry;
struct lpfc_hba *phba = file->private_data;
char dstbuf[32];
char dstbuf[33];
uint64_t tmp = 0;
int size;
memset(dstbuf, 0, 32);
memset(dstbuf, 0, 33);
size = (nbytes < 32) ? nbytes : 32;
if (copy_from_user(dstbuf, buf, size))
return 0;

View File

@ -25,6 +25,7 @@
#include <linux/pci.h>
#include <linux/kthread.h>
#include <linux/interrupt.h>
#include <linux/lockdep.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
@ -1314,6 +1315,8 @@ __lpfc_update_fcf_record_pri(struct lpfc_hba *phba, uint16_t fcf_index,
{
struct lpfc_fcf_pri *fcf_pri;
lockdep_assert_held(&phba->hbalock);
fcf_pri = &phba->fcf.fcf_pri[fcf_index];
fcf_pri->fcf_rec.fcf_index = fcf_index;
/* FCF record priority */
@ -1398,6 +1401,8 @@ __lpfc_update_fcf_record(struct lpfc_hba *phba, struct lpfc_fcf_rec *fcf_rec,
struct fcf_record *new_fcf_record, uint32_t addr_mode,
uint16_t vlan_id, uint32_t flag)
{
lockdep_assert_held(&phba->hbalock);
/* Copy the fields from the HBA's FCF record */
lpfc_copy_fcf_record(fcf_rec, new_fcf_record);
/* Update other fields of driver FCF record */

View File

@ -4139,23 +4139,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
/* The sdev is not guaranteed to be valid post scsi_done upcall. */
cmd->scsi_done(cmd);
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
spin_lock_irqsave(&phba->hbalock, flags);
lpfc_cmd->pCmd = NULL;
spin_unlock_irqrestore(&phba->hbalock, flags);
/*
* If there is a thread waiting for command completion
* wake up the thread.
*/
spin_lock_irqsave(shost->host_lock, flags);
if (lpfc_cmd->waitq)
wake_up(lpfc_cmd->waitq);
spin_unlock_irqrestore(shost->host_lock, flags);
lpfc_release_scsi_buf(phba, lpfc_cmd);
return;
}
spin_lock_irqsave(&phba->hbalock, flags);
lpfc_cmd->pCmd = NULL;
spin_unlock_irqrestore(&phba->hbalock, flags);

View File

@ -24,6 +24,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/lockdep.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@ -576,6 +577,8 @@ __lpfc_sli_get_iocbq(struct lpfc_hba *phba)
struct list_head *lpfc_iocb_list = &phba->lpfc_iocb_list;
struct lpfc_iocbq * iocbq = NULL;
lockdep_assert_held(&phba->hbalock);
list_remove_head(lpfc_iocb_list, iocbq, struct lpfc_iocbq, list);
if (iocbq)
phba->iocb_cnt++;
@ -797,6 +800,7 @@ int
lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
uint16_t xritag)
{
lockdep_assert_held(&phba->hbalock);
if (!ndlp)
return 0;
if (!ndlp->active_rrqs_xri_bitmap)
@ -914,6 +918,8 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq)
struct lpfc_nodelist *ndlp;
int found = 0;
lockdep_assert_held(&phba->hbalock);
if (piocbq->iocb_flag & LPFC_IO_FCP) {
lpfc_cmd = (struct lpfc_scsi_buf *) piocbq->context1;
ndlp = lpfc_cmd->rdata->pnode;
@ -1003,6 +1009,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
unsigned long iflag = 0;
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
lockdep_assert_held(&phba->hbalock);
if (iocbq->sli4_xritag == NO_XRI)
sglq = NULL;
else
@ -1058,6 +1066,7 @@ __lpfc_sli_release_iocbq_s3(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{
size_t start_clean = offsetof(struct lpfc_iocbq, iocb);
lockdep_assert_held(&phba->hbalock);
/*
* Clean all volatile data fields, preserve iotag and node struct.
@ -1080,6 +1089,8 @@ __lpfc_sli_release_iocbq_s3(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
static void
__lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{
lockdep_assert_held(&phba->hbalock);
phba->__lpfc_sli_release_iocbq(phba, iocbq);
phba->iocb_cnt--;
}
@ -1310,6 +1321,8 @@ static int
lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb)
{
lockdep_assert_held(&phba->hbalock);
list_add_tail(&piocb->list, &pring->txcmplq);
piocb->iocb_flag |= LPFC_IO_ON_TXCMPLQ;
@ -1344,6 +1357,8 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
struct lpfc_iocbq *cmd_iocb;
lockdep_assert_held(&phba->hbalock);
list_remove_head((&pring->txq), cmd_iocb, struct lpfc_iocbq, list);
return cmd_iocb;
}
@ -1367,6 +1382,9 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
struct lpfc_pgp *pgp = &phba->port_gp[pring->ringno];
uint32_t max_cmd_idx = pring->sli.sli3.numCiocb;
lockdep_assert_held(&phba->hbalock);
if ((pring->sli.sli3.next_cmdidx == pring->sli.sli3.cmdidx) &&
(++pring->sli.sli3.next_cmdidx >= max_cmd_idx))
pring->sli.sli3.next_cmdidx = 0;
@ -1497,6 +1515,7 @@ static void
lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
IOCB_t *iocb, struct lpfc_iocbq *nextiocb)
{
lockdep_assert_held(&phba->hbalock);
/*
* Set up an iotag
*/
@ -1606,6 +1625,8 @@ lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
IOCB_t *iocb;
struct lpfc_iocbq *nextiocb;
lockdep_assert_held(&phba->hbalock);
/*
* Check to see if:
* (a) there is anything on the txq to send
@ -1647,6 +1668,8 @@ lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno)
{
struct hbq_s *hbqp = &phba->hbqs[hbqno];
lockdep_assert_held(&phba->hbalock);
if (hbqp->next_hbqPutIdx == hbqp->hbqPutIdx &&
++hbqp->next_hbqPutIdx >= hbqp->entry_count)
hbqp->next_hbqPutIdx = 0;
@ -1747,6 +1770,7 @@ static int
lpfc_sli_hbq_to_firmware(struct lpfc_hba *phba, uint32_t hbqno,
struct hbq_dmabuf *hbq_buf)
{
lockdep_assert_held(&phba->hbalock);
return phba->lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buf);
}
@ -1768,6 +1792,7 @@ lpfc_sli_hbq_to_firmware_s3(struct lpfc_hba *phba, uint32_t hbqno,
struct lpfc_hbq_entry *hbqe;
dma_addr_t physaddr = hbq_buf->dbuf.phys;
lockdep_assert_held(&phba->hbalock);
/* Get next HBQ entry slot to use */
hbqe = lpfc_sli_next_hbq_slot(phba, hbqno);
if (hbqe) {
@ -1808,6 +1833,7 @@ lpfc_sli_hbq_to_firmware_s4(struct lpfc_hba *phba, uint32_t hbqno,
struct lpfc_rqe hrqe;
struct lpfc_rqe drqe;
lockdep_assert_held(&phba->hbalock);
hrqe.address_lo = putPaddrLow(hbq_buf->hbuf.phys);
hrqe.address_hi = putPaddrHigh(hbq_buf->hbuf.phys);
drqe.address_lo = putPaddrLow(hbq_buf->dbuf.phys);
@ -1986,6 +2012,8 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag)
struct hbq_dmabuf *hbq_buf;
uint32_t hbqno;
lockdep_assert_held(&phba->hbalock);
hbqno = tag >> 16;
if (hbqno >= LPFC_MAX_HBQS)
return NULL;
@ -2647,6 +2675,7 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
{
struct lpfc_iocbq *cmd_iocb = NULL;
uint16_t iotag;
lockdep_assert_held(&phba->hbalock);
iotag = prspiocb->iocb.ulpIoTag;
@ -2685,6 +2714,7 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba,
{
struct lpfc_iocbq *cmd_iocb;
lockdep_assert_held(&phba->hbalock);
if (iotag != 0 && iotag <= phba->sli.last_iotag) {
cmd_iocb = phba->sli.iocbq_lookup[iotag];
if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) {
@ -3799,6 +3829,8 @@ void lpfc_reset_barrier(struct lpfc_hba *phba)
int i;
uint8_t hdrtype;
lockdep_assert_held(&phba->hbalock);
pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);
if (hdrtype != 0x80 ||
(FC_JEDEC_ID(phba->vpd.rev.biuRev) != HELIOS_JEDEC_ID &&
@ -7861,6 +7893,7 @@ void
__lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb)
{
lockdep_assert_held(&phba->hbalock);
/* Insert the caller's iocb in the txq tail for later processing. */
list_add_tail(&piocb->list, &pring->txq);
}
@ -7888,6 +7921,8 @@ lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
{
struct lpfc_iocbq * nextiocb;
lockdep_assert_held(&phba->hbalock);
nextiocb = lpfc_sli_ringtx_get(phba, pring);
if (!nextiocb) {
nextiocb = *piocb;
@ -7927,6 +7962,8 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number,
IOCB_t *iocb;
struct lpfc_sli_ring *pring = &phba->sli.ring[ring_number];
lockdep_assert_held(&phba->hbalock);
if (piocb->iocb_cmpl && (!piocb->vport) &&
(piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) &&
(piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) {
@ -8642,6 +8679,8 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
struct lpfc_queue *wq;
struct lpfc_sli_ring *pring = &phba->sli.ring[ring_number];
lockdep_assert_held(&phba->hbalock);
if (piocb->sli4_xritag == NO_XRI) {
if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
@ -9752,6 +9791,8 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
int retval;
unsigned long iflags;
lockdep_assert_held(&phba->hbalock);
/*
* There are certain command types we don't want to abort. And we
* don't want to abort commands that are already in the process of
@ -9854,6 +9895,8 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
int retval = IOCB_ERROR;
IOCB_t *icmd = NULL;
lockdep_assert_held(&phba->hbalock);
/*
* There are certain command types we don't want to abort. And we
* don't want to abort commands that are already in the process of

View File

@ -35,8 +35,8 @@
/*
* MegaRAID SAS Driver meta data
*/
#define MEGASAS_VERSION "06.808.16.00-rc1"
#define MEGASAS_RELDATE "Oct. 8, 2015"
#define MEGASAS_VERSION "06.810.09.00-rc1"
#define MEGASAS_RELDATE "Jan. 28, 2016"
/*
* Device IDs
@ -152,6 +152,7 @@
#define MFI_RESET_FLAGS MFI_INIT_READY| \
MFI_INIT_MFIMODE| \
MFI_INIT_ABORT
#define MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE (0x01)
/*
* MFI frame flags
@ -170,6 +171,7 @@
/* Driver internal */
#define DRV_DCMD_POLLED_MODE 0x1
#define DRV_DCMD_SKIP_REFIRE 0x2
/*
* Definition for cmd_status
@ -214,6 +216,7 @@
#define MR_DCMD_CTRL_SET_CRASH_DUMP_PARAMS 0x01190100
#define MR_DRIVER_SET_APP_CRASHDUMP_MODE (0xF0010000 | 0x0600)
#define MR_DCMD_PD_GET_INFO 0x02020000
/*
* Global functions
@ -390,6 +393,7 @@ enum MR_EVT_ARGS {
#define SGE_BUFFER_SIZE 4096
#define MEGASAS_CLUSTER_ID_SIZE 16
/*
* define constants for device list query options
*/
@ -434,6 +438,257 @@ enum MR_PD_STATE {
MR_PD_STATE_SYSTEM = 0x40,
};
union MR_PD_REF {
struct {
u16 deviceId;
u16 seqNum;
} mrPdRef;
u32 ref;
};
/*
* define the DDF Type bit structure
*/
union MR_PD_DDF_TYPE {
struct {
union {
struct {
#ifndef __BIG_ENDIAN_BITFIELD
u16 forcedPDGUID:1;
u16 inVD:1;
u16 isGlobalSpare:1;
u16 isSpare:1;
u16 isForeign:1;
u16 reserved:7;
u16 intf:4;
#else
u16 intf:4;
u16 reserved:7;
u16 isForeign:1;
u16 isSpare:1;
u16 isGlobalSpare:1;
u16 inVD:1;
u16 forcedPDGUID:1;
#endif
} pdType;
u16 type;
};
u16 reserved;
} ddf;
struct {
u32 reserved;
} nonDisk;
u32 type;
} __packed;
/*
* defines the progress structure
*/
union MR_PROGRESS {
struct {
u16 progress;
union {
u16 elapsedSecs;
u16 elapsedSecsForLastPercent;
};
} mrProgress;
u32 w;
} __packed;
/*
* defines the physical drive progress structure
*/
struct MR_PD_PROGRESS {
struct {
#ifndef MFI_BIG_ENDIAN
u32 rbld:1;
u32 patrol:1;
u32 clear:1;
u32 copyBack:1;
u32 erase:1;
u32 locate:1;
u32 reserved:26;
#else
u32 reserved:26;
u32 locate:1;
u32 erase:1;
u32 copyBack:1;
u32 clear:1;
u32 patrol:1;
u32 rbld:1;
#endif
} active;
union MR_PROGRESS rbld;
union MR_PROGRESS patrol;
union {
union MR_PROGRESS clear;
union MR_PROGRESS erase;
};
struct {
#ifndef MFI_BIG_ENDIAN
u32 rbld:1;
u32 patrol:1;
u32 clear:1;
u32 copyBack:1;
u32 erase:1;
u32 reserved:27;
#else
u32 reserved:27;
u32 erase:1;
u32 copyBack:1;
u32 clear:1;
u32 patrol:1;
u32 rbld:1;
#endif
} pause;
union MR_PROGRESS reserved[3];
} __packed;
struct MR_PD_INFO {
union MR_PD_REF ref;
u8 inquiryData[96];
u8 vpdPage83[64];
u8 notSupported;
u8 scsiDevType;
union {
u8 connectedPortBitmap;
u8 connectedPortNumbers;
};
u8 deviceSpeed;
u32 mediaErrCount;
u32 otherErrCount;
u32 predFailCount;
u32 lastPredFailEventSeqNum;
u16 fwState;
u8 disabledForRemoval;
u8 linkSpeed;
union MR_PD_DDF_TYPE state;
struct {
u8 count;
#ifndef __BIG_ENDIAN_BITFIELD
u8 isPathBroken:4;
u8 reserved3:3;
u8 widePortCapable:1;
#else
u8 widePortCapable:1;
u8 reserved3:3;
u8 isPathBroken:4;
#endif
u8 connectorIndex[2];
u8 reserved[4];
u64 sasAddr[2];
u8 reserved2[16];
} pathInfo;
u64 rawSize;
u64 nonCoercedSize;
u64 coercedSize;
u16 enclDeviceId;
u8 enclIndex;
union {
u8 slotNumber;
u8 enclConnectorIndex;
};
struct MR_PD_PROGRESS progInfo;
u8 badBlockTableFull;
u8 unusableInCurrentConfig;
u8 vpdPage83Ext[64];
u8 powerState;
u8 enclPosition;
u32 allowedOps;
u16 copyBackPartnerId;
u16 enclPartnerDeviceId;
struct {
#ifndef __BIG_ENDIAN_BITFIELD
u16 fdeCapable:1;
u16 fdeEnabled:1;
u16 secured:1;
u16 locked:1;
u16 foreign:1;
u16 needsEKM:1;
u16 reserved:10;
#else
u16 reserved:10;
u16 needsEKM:1;
u16 foreign:1;
u16 locked:1;
u16 secured:1;
u16 fdeEnabled:1;
u16 fdeCapable:1;
#endif
} security;
u8 mediaType;
u8 notCertified;
u8 bridgeVendor[8];
u8 bridgeProductIdentification[16];
u8 bridgeProductRevisionLevel[4];
u8 satBridgeExists;
u8 interfaceType;
u8 temperature;
u8 emulatedBlockSize;
u16 userDataBlockSize;
u16 reserved2;
struct {
#ifndef __BIG_ENDIAN_BITFIELD
u32 piType:3;
u32 piFormatted:1;
u32 piEligible:1;
u32 NCQ:1;
u32 WCE:1;
u32 commissionedSpare:1;
u32 emergencySpare:1;
u32 ineligibleForSSCD:1;
u32 ineligibleForLd:1;
u32 useSSEraseType:1;
u32 wceUnchanged:1;
u32 supportScsiUnmap:1;
u32 reserved:18;
#else
u32 reserved:18;
u32 supportScsiUnmap:1;
u32 wceUnchanged:1;
u32 useSSEraseType:1;
u32 ineligibleForLd:1;
u32 ineligibleForSSCD:1;
u32 emergencySpare:1;
u32 commissionedSpare:1;
u32 WCE:1;
u32 NCQ:1;
u32 piEligible:1;
u32 piFormatted:1;
u32 piType:3;
#endif
} properties;
u64 shieldDiagCompletionTime;
u8 shieldCounter;
u8 linkSpeedOther;
u8 reserved4[2];
struct {
#ifndef __BIG_ENDIAN_BITFIELD
u32 bbmErrCountSupported:1;
u32 bbmErrCount:31;
#else
u32 bbmErrCount:31;
u32 bbmErrCountSupported:1;
#endif
} bbmErr;
u8 reserved1[512-428];
} __packed;
/*
* defines the physical drive address structure
@ -473,6 +728,7 @@ struct megasas_pd_list {
u16 tid;
u8 driveType;
u8 driveState;
u8 interface;
} __packed;
/*
@ -972,7 +1228,8 @@ struct megasas_ctrl_info {
*/
struct {
#if defined(__BIG_ENDIAN_BITFIELD)
u32 reserved:26;
u32 reserved:25;
u32 passive:1;
u32 premiumFeatureMismatch:1;
u32 ctrlPropIncompatible:1;
u32 fwVersionMismatch:1;
@ -986,11 +1243,12 @@ struct megasas_ctrl_info {
u32 fwVersionMismatch:1;
u32 ctrlPropIncompatible:1;
u32 premiumFeatureMismatch:1;
u32 reserved:26;
u32 passive:1;
u32 reserved:25;
#endif
} cluster;
char clusterId[16]; /*7D4h */
char clusterId[MEGASAS_CLUSTER_ID_SIZE]; /*0x7D4 */
struct {
u8 maxVFsSupported; /*0x7E4*/
u8 numVFsEnabled; /*0x7E5*/
@ -1083,6 +1341,8 @@ struct megasas_ctrl_info {
#define VD_EXT_DEBUG 0
#define SCAN_PD_CHANNEL 0x1
#define SCAN_VD_CHANNEL 0x2
enum MR_SCSI_CMD_TYPE {
READ_WRITE_LDIO = 0,
@ -1091,6 +1351,17 @@ enum MR_SCSI_CMD_TYPE {
NON_READ_WRITE_SYSPDIO = 3,
};
enum DCMD_TIMEOUT_ACTION {
INITIATE_OCR = 0,
KILL_ADAPTER = 1,
IGNORE_TIMEOUT = 2,
};
enum FW_BOOT_CONTEXT {
PROBE_CONTEXT = 0,
OCR_CONTEXT = 1,
};
/* Frame Type */
#define IO_FRAME 0
#define PTHRU_FRAME 1
@ -1137,6 +1408,7 @@ enum MR_SCSI_CMD_TYPE {
#define MFI_OB_INTR_STATUS_MASK 0x00000002
#define MFI_POLL_TIMEOUT_SECS 60
#define MFI_IO_TIMEOUT_SECS 180
#define MEGASAS_SRIOV_HEARTBEAT_INTERVAL_VF (5 * HZ)
#define MEGASAS_OCR_SETTLE_TIME_VF (1000 * 30)
#define MEGASAS_ROUTINE_WAIT_TIME_VF 300
@ -1154,6 +1426,7 @@ enum MR_SCSI_CMD_TYPE {
#define MR_MAX_REPLY_QUEUES_EXT_OFFSET 0X003FC000
#define MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT 14
#define MR_MAX_MSIX_REG_ARRAY 16
#define MR_RDPQ_MODE_OFFSET 0X00800000
/*
* register set for both 1068 and 1078 controllers
* structure extended for 1078 registers
@ -1193,8 +1466,9 @@ struct megasas_register_set {
u32 outbound_scratch_pad ; /*00B0h*/
u32 outbound_scratch_pad_2; /*00B4h*/
u32 outbound_scratch_pad_3; /*00B8h*/
u32 reserved_4[2]; /*00B8h*/
u32 reserved_4; /*00BCh*/
u32 inbound_low_queue_port ; /*00C0h*/
@ -1266,7 +1540,10 @@ union megasas_sgl_frame {
typedef union _MFI_CAPABILITIES {
struct {
#if defined(__BIG_ENDIAN_BITFIELD)
u32 reserved:23;
u32 reserved:20;
u32 support_qd_throttling:1;
u32 support_fp_rlbypass:1;
u32 support_vfid_in_ioframe:1;
u32 support_ext_io_size:1;
u32 support_ext_queue_depth:1;
u32 security_protocol_cmds_fw:1;
@ -1286,7 +1563,10 @@ typedef union _MFI_CAPABILITIES {
u32 security_protocol_cmds_fw:1;
u32 support_ext_queue_depth:1;
u32 support_ext_io_size:1;
u32 reserved:23;
u32 support_vfid_in_ioframe:1;
u32 support_fp_rlbypass:1;
u32 support_qd_throttling:1;
u32 reserved:20;
#endif
} mfi_capabilities;
__le32 reg;
@ -1511,6 +1791,15 @@ union megasas_frame {
u8 raw_bytes[64];
};
/**
* struct MR_PRIV_DEVICE - sdev private hostdata
* @is_tm_capable: firmware managed tm_capable flag
* @tm_busy: TM request is in progress
*/
struct MR_PRIV_DEVICE {
bool is_tm_capable;
bool tm_busy;
};
struct megasas_cmd;
union megasas_evt_class_locale {
@ -1700,6 +1989,19 @@ struct MR_DRV_SYSTEM_INFO {
u8 reserved[1980];
};
enum MR_PD_TYPE {
UNKNOWN_DRIVE = 0,
PARALLEL_SCSI = 1,
SAS_PD = 2,
SATA_PD = 3,
FC_PD = 4,
};
/* JBOD Queue depth definitions */
#define MEGASAS_SATA_QD 32
#define MEGASAS_SAS_QD 64
#define MEGASAS_DEFAULT_PD_QD 64
struct megasas_instance {
__le32 *producer;
@ -1714,6 +2016,8 @@ struct megasas_instance {
dma_addr_t vf_affiliation_111_h;
struct MR_CTRL_HB_HOST_MEM *hb_host_mem;
dma_addr_t hb_host_mem_h;
struct MR_PD_INFO *pd_info;
dma_addr_t pd_info_h;
__le32 *reply_queue;
dma_addr_t reply_queue_h;
@ -1745,6 +2049,8 @@ struct megasas_instance {
u16 max_fw_cmds;
u16 max_mfi_cmds;
u16 max_scsi_cmds;
u16 ldio_threshold;
u16 cur_can_queue;
u32 max_sectors_per_req;
struct megasas_aen_event *ev;
@ -1762,7 +2068,7 @@ struct megasas_instance {
struct megasas_evt_detail *evt_detail;
dma_addr_t evt_detail_h;
struct megasas_cmd *aen_cmd;
struct mutex aen_mutex;
struct mutex hba_mutex;
struct semaphore ioctl_sem;
struct Scsi_Host *host;
@ -1775,6 +2081,7 @@ struct megasas_instance {
u32 fw_support_ieee;
atomic_t fw_outstanding;
atomic_t ldio_outstanding;
atomic_t fw_reset_no_pci_access;
struct megasas_instance_template *instancet;
@ -1797,7 +2104,7 @@ struct megasas_instance {
u16 drv_supported_vd_count;
u16 drv_supported_pd_count;
u8 adprecovery;
atomic_t adprecovery;
unsigned long last_time;
u32 mfiStatus;
u32 last_seq_num;
@ -1822,11 +2129,14 @@ struct megasas_instance {
char skip_heartbeat_timer_del;
u8 requestorId;
char PlasmaFW111;
char mpio;
char clusterId[MEGASAS_CLUSTER_ID_SIZE];
u8 peerIsPresent;
u8 passive;
u16 throttlequeuedepth;
u8 mask_interrupts;
u16 max_chain_frame_sz;
u8 is_imr;
u8 is_rdpq;
bool dev_handle;
};
struct MR_LD_VF_MAP {
@ -1916,7 +2226,7 @@ struct megasas_instance_template {
u32 (*init_adapter)(struct megasas_instance *);
u32 (*build_and_issue_cmd) (struct megasas_instance *,
struct scsi_cmnd *);
void (*issue_dcmd) (struct megasas_instance *instance,
int (*issue_dcmd)(struct megasas_instance *instance,
struct megasas_cmd *cmd);
};
@ -2014,6 +2324,19 @@ struct megasas_mgmt_info {
int max_index;
};
enum MEGASAS_OCR_CAUSE {
FW_FAULT_OCR = 0,
SCSIIO_TIMEOUT_OCR = 1,
MFI_IO_TIMEOUT_OCR = 2,
};
enum DCMD_RETURN_STATUS {
DCMD_SUCCESS = 0,
DCMD_TIMEOUT = 1,
DCMD_FAILED = 2,
DCMD_NOT_FIRED = 3,
};
u8
MR_BuildRaidContext(struct megasas_instance *instance,
struct IO_REQUEST_INFO *io_info,
@ -2051,4 +2374,8 @@ void megasas_return_mfi_mpt_pthr(struct megasas_instance *instance,
int megasas_cmd_type(struct scsi_cmnd *cmd);
void megasas_setup_jbod_map(struct megasas_instance *instance);
void megasas_update_sdev_properties(struct scsi_device *sdev);
int megasas_reset_fusion(struct Scsi_Host *shost, int reason);
int megasas_task_abort_fusion(struct scsi_cmnd *scmd);
int megasas_reset_target_fusion(struct scsi_cmnd *scmd);
#endif /*LSI_MEGARAID_SAS_H */

File diff suppressed because it is too large Load Diff

View File

@ -1020,6 +1020,8 @@ MR_BuildRaidContext(struct megasas_instance *instance,
/* assume this IO needs the full row - we'll adjust if not true */
regSize = stripSize;
io_info->do_fp_rlbypass = raid->capability.fpBypassRegionLock;
/* Check if we can send this I/O via FastPath */
if (raid->capability.fpCapable) {
if (isRead)

File diff suppressed because it is too large Load Diff

View File

@ -176,7 +176,9 @@ enum REGION_TYPE {
#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100)
#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004)
#define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */
#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06)
#define MPI2_FUNCTION_SCSI_TASK_MGMT (0x01)
#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x03)
#define MPI2_REQ_DESCRIPT_FLAGS_FP_IO (0x06)
#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00)
#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02)
#define MPI2_SCSIIO_CONTROL_WRITE (0x01000000)
@ -277,6 +279,100 @@ union MPI2_SCSI_IO_CDB_UNION {
struct MPI2_SGE_SIMPLE_UNION SGE;
};
/****************************************************************************
* SCSI Task Management messages
****************************************************************************/
/*SCSI Task Management Request Message */
struct MPI2_SCSI_TASK_MANAGE_REQUEST {
u16 DevHandle; /*0x00 */
u8 ChainOffset; /*0x02 */
u8 Function; /*0x03 */
u8 Reserved1; /*0x04 */
u8 TaskType; /*0x05 */
u8 Reserved2; /*0x06 */
u8 MsgFlags; /*0x07 */
u8 VP_ID; /*0x08 */
u8 VF_ID; /*0x09 */
u16 Reserved3; /*0x0A */
u8 LUN[8]; /*0x0C */
u32 Reserved4[7]; /*0x14 */
u16 TaskMID; /*0x30 */
u16 Reserved5; /*0x32 */
};
/*SCSI Task Management Reply Message */
struct MPI2_SCSI_TASK_MANAGE_REPLY {
u16 DevHandle; /*0x00 */
u8 MsgLength; /*0x02 */
u8 Function; /*0x03 */
u8 ResponseCode; /*0x04 */
u8 TaskType; /*0x05 */
u8 Reserved1; /*0x06 */
u8 MsgFlags; /*0x07 */
u8 VP_ID; /*0x08 */
u8 VF_ID; /*0x09 */
u16 Reserved2; /*0x0A */
u16 Reserved3; /*0x0C */
u16 IOCStatus; /*0x0E */
u32 IOCLogInfo; /*0x10 */
u32 TerminationCount; /*0x14 */
u32 ResponseInfo; /*0x18 */
};
struct MR_TM_REQUEST {
char request[128];
};
struct MR_TM_REPLY {
char reply[128];
};
/* SCSI Task Management Request Message */
struct MR_TASK_MANAGE_REQUEST {
/*To be type casted to struct MPI2_SCSI_TASK_MANAGE_REQUEST */
struct MR_TM_REQUEST TmRequest;
union {
struct {
#if defined(__BIG_ENDIAN_BITFIELD)
u32 reserved1:30;
u32 isTMForPD:1;
u32 isTMForLD:1;
#else
u32 isTMForLD:1;
u32 isTMForPD:1;
u32 reserved1:30;
#endif
u32 reserved2;
} tmReqFlags;
struct MR_TM_REPLY TMReply;
};
};
/* TaskType values */
#define MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01)
#define MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET (0x02)
#define MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03)
#define MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05)
#define MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06)
#define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07)
#define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08)
#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET (0x09)
#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT (0x0A)
/* ResponseCode values */
#define MPI2_SCSITASKMGMT_RSP_TM_COMPLETE (0x00)
#define MPI2_SCSITASKMGMT_RSP_INVALID_FRAME (0x02)
#define MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED (0x04)
#define MPI2_SCSITASKMGMT_RSP_TM_FAILED (0x05)
#define MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED (0x08)
#define MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN (0x09)
#define MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG (0x0A)
#define MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC (0x80)
/*
* RAID SCSI IO Request Message
* Total SGE count will be one less than _MPI2_SCSI_IO_REQUEST
@ -547,7 +643,9 @@ struct MR_SPAN_BLOCK_INFO {
struct MR_LD_RAID {
struct {
#if defined(__BIG_ENDIAN_BITFIELD)
u32 reserved4:7;
u32 reserved4:5;
u32 fpBypassRegionLock:1;
u32 tmCapable:1;
u32 fpNonRWCapable:1;
u32 fpReadAcrossStripe:1;
u32 fpWriteAcrossStripe:1;
@ -569,7 +667,9 @@ struct MR_LD_RAID {
u32 fpWriteAcrossStripe:1;
u32 fpReadAcrossStripe:1;
u32 fpNonRWCapable:1;
u32 reserved4:7;
u32 tmCapable:1;
u32 fpBypassRegionLock:1;
u32 reserved4:5;
#endif
} capability;
__le32 reserved6;
@ -639,7 +739,7 @@ struct IO_REQUEST_INFO {
u8 fpOkForIo;
u8 IoforUnevenSpan;
u8 start_span;
u8 reserved;
u8 do_fp_rlbypass;
u64 start_row;
u8 span_arm; /* span[7:5], arm[4:0] */
u8 pd_after_lb;
@ -694,6 +794,7 @@ struct megasas_cmd_fusion {
u32 sync_cmd_idx;
u32 index;
u8 pd_r1_lb;
struct completion done;
};
struct LD_LOAD_BALANCE_INFO {
@ -807,9 +908,18 @@ struct MR_FW_RAID_MAP_EXT {
* * define MR_PD_CFG_SEQ structure for system PDs
* */
struct MR_PD_CFG_SEQ {
__le16 seqNum;
__le16 devHandle;
u8 reserved[4];
u16 seqNum;
u16 devHandle;
struct {
#if defined(__BIG_ENDIAN_BITFIELD)
u8 reserved:7;
u8 tmCapable:1;
#else
u8 tmCapable:1;
u8 reserved:7;
#endif
} capability;
u8 reserved[3];
} __packed;
struct MR_PD_CFG_SEQ_NUM_SYNC {
@ -818,6 +928,12 @@ struct MR_PD_CFG_SEQ_NUM_SYNC {
struct MR_PD_CFG_SEQ seq[1];
} __packed;
struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY {
u64 RDPQBaseAddress;
u32 Reserved1;
u32 Reserved2;
};
struct fusion_context {
struct megasas_cmd_fusion **cmd_list;
dma_addr_t req_frames_desc_phys;
@ -830,8 +946,8 @@ struct fusion_context {
struct dma_pool *sg_dma_pool;
struct dma_pool *sense_dma_pool;
dma_addr_t reply_frames_desc_phys;
union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc;
dma_addr_t reply_frames_desc_phys[MAX_MSIX_QUEUES_FUSION];
union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc[MAX_MSIX_QUEUES_FUSION];
struct dma_pool *reply_frames_desc_pool;
u16 last_reply_idx[MAX_MSIX_QUEUES_FUSION];
@ -841,6 +957,8 @@ struct fusion_context {
u32 reply_alloc_sz;
u32 io_frames_alloc_sz;
struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY *rdpq_virt;
dma_addr_t rdpq_phys;
u16 max_sge_in_main_msg;
u16 max_sge_in_chain;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2014 LSI Corporation.
* Copyright 2000-2015 Avago Technologies. All rights reserved.
*
*
* Name: mpi2.h
@ -8,7 +8,7 @@
* scatter/gather formats.
* Creation Date: June 21, 2006
*
* mpi2.h Version: 02.00.35
* mpi2.h Version: 02.00.39
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@ -92,6 +92,14 @@
* 12-05-13 02.00.33 Bumped MPI2_HEADER_VERSION_UNIT.
* 01-08-14 02.00.34 Bumped MPI2_HEADER_VERSION_UNIT
* 06-13-14 02.00.35 Bumped MPI2_HEADER_VERSION_UNIT.
* 11-18-14 02.00.36 Updated copyright information.
* Bumped MPI2_HEADER_VERSION_UNIT.
* 03-16-15 02.00.37 Bumped MPI2_HEADER_VERSION_UNIT.
* Added Scratchpad registers to
* MPI2_SYSTEM_INTERFACE_REGS.
* Added MPI2_DIAG_SBR_RELOAD.
* 03-19-15 02.00.38 Bumped MPI2_HEADER_VERSION_UNIT.
* 05-25-15 02.00.39 Bumped MPI2_HEADER_VERSION_UNIT.
* --------------------------------------------------------------------------
*/
@ -124,8 +132,14 @@
MPI25_VERSION_MINOR)
#define MPI2_VERSION_02_05 (0x0205)
/*minor version for MPI v2.6 compatible products */
#define MPI26_VERSION_MINOR (0x06)
#define MPI26_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \
MPI26_VERSION_MINOR)
#define MPI2_VERSION_02_06 (0x0206)
/*Unit and Dev versioning for this MPI header set */
#define MPI2_HEADER_VERSION_UNIT (0x23)
#define MPI2_HEADER_VERSION_UNIT (0x27)
#define MPI2_HEADER_VERSION_DEV (0x00)
#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
@ -179,10 +193,12 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS {
U32 HCBSize; /*0x74 */
U32 HCBAddressLow; /*0x78 */
U32 HCBAddressHigh; /*0x7C */
U32 Reserved6[16]; /*0x80 */
U32 Reserved6[12]; /*0x80 */
U32 Scratchpad[4]; /*0xB0 */
U32 RequestDescriptorPostLow; /*0xC0 */
U32 RequestDescriptorPostHigh; /*0xC4 */
U32 Reserved7[14]; /*0xC8 */
U32 AtomicRequestDescriptorPost;/*0xC8 */
U32 Reserved7[13]; /*0xCC */
} MPI2_SYSTEM_INTERFACE_REGS,
*PTR_MPI2_SYSTEM_INTERFACE_REGS,
Mpi2SystemInterfaceRegs_t,
@ -224,6 +240,8 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS {
*/
#define MPI2_HOST_DIAGNOSTIC_OFFSET (0x00000008)
#define MPI2_DIAG_SBR_RELOAD (0x00002000)
#define MPI2_DIAG_BOOT_DEVICE_SELECT_MASK (0x00001800)
#define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT (0x00000000)
#define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW (0x00000800)
@ -298,10 +316,19 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS {
#define MPI2_HCB_ADDRESS_HIGH_OFFSET (0x0000007C)
/*
*Offsets for the Request Queue
*Offsets for the Scratchpad registers
*/
#define MPI26_SCRATCHPAD0_OFFSET (0x000000B0)
#define MPI26_SCRATCHPAD1_OFFSET (0x000000B4)
#define MPI26_SCRATCHPAD2_OFFSET (0x000000B8)
#define MPI26_SCRATCHPAD3_OFFSET (0x000000BC)
/*
*Offsets for the Request Descriptor Post Queue
*/
#define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET (0x000000C0)
#define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET (0x000000C4)
#define MPI26_ATOMIC_REQUEST_DESCRIPTOR_POST_OFFSET (0x000000C8)
/*Hard Reset delay timings */
#define MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC (50000)
@ -329,7 +356,8 @@ typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR {
*pMpi2DefaultRequestDescriptor_t;
/*defines for the RequestFlags field */
#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E)
#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x1E)
#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_RSHIFT (1)
#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00)
#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET (0x02)
#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06)
@ -337,7 +365,7 @@ typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR {
#define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR (0x0A)
#define MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO (0x0C)
#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01)
#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01)
/*High Priority Request Descriptor */
typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR {
@ -408,6 +436,33 @@ typedef union _MPI2_REQUEST_DESCRIPTOR_UNION {
Mpi2RequestDescriptorUnion_t,
*pMpi2RequestDescriptorUnion_t;
/*Atomic Request Descriptors */
/*
* All Atomic Request Descriptors have the same format, so the following
* structure is used for all Atomic Request Descriptors:
* Atomic Default Request Descriptor
* Atomic High Priority Request Descriptor
* Atomic SCSI IO Request Descriptor
* Atomic SCSI Target Request Descriptor
* Atomic RAID Accelerator Request Descriptor
* Atomic Fast Path SCSI IO Request Descriptor
*/
/*Atomic Request Descriptor */
typedef struct _MPI26_ATOMIC_REQUEST_DESCRIPTOR {
U8 RequestFlags; /* 0x00 */
U8 MSIxIndex; /* 0x01 */
U16 SMID; /* 0x02 */
} MPI26_ATOMIC_REQUEST_DESCRIPTOR,
*PTR_MPI26_ATOMIC_REQUEST_DESCRIPTOR,
Mpi26AtomicRequestDescriptor_t,
*pMpi26AtomicRequestDescriptor_t;
/*for the RequestFlags field, use the same
*defines as MPI2_DEFAULT_REQUEST_DESCRIPTOR
*/
/*Reply Descriptors */
/*Default Reply Descriptor */
@ -548,6 +603,7 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION {
#define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18)
#define MPI2_FUNCTION_SMP_PASSTHROUGH (0x1A)
#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B)
#define MPI2_FUNCTION_IO_UNIT_CONTROL (0x1B)
#define MPI2_FUNCTION_SATA_PASSTHROUGH (0x1C)
#define MPI2_FUNCTION_DIAG_BUFFER_POST (0x1D)
#define MPI2_FUNCTION_DIAG_RELEASE (0x1E)
@ -587,6 +643,7 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION {
#define MPI2_IOCSTATUS_INVALID_FIELD (0x0007)
#define MPI2_IOCSTATUS_INVALID_STATE (0x0008)
#define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED (0x0009)
#define MPI2_IOCSTATUS_INSUFFICIENT_POWER (0x000A)
/****************************************************************************
* Config IOCStatus values
@ -1045,7 +1102,7 @@ typedef union _MPI2_IEEE_SGE_CHAIN_UNION {
Mpi2IeeeSgeChainUnion_t,
*pMpi2IeeeSgeChainUnion_t;
/*MPI25_IEEE_SGE_CHAIN64 is for MPI v2.5 products only */
/*MPI25_IEEE_SGE_CHAIN64 is for MPI v2.5 and later */
typedef struct _MPI25_IEEE_SGE_CHAIN64 {
U64 Address;
U32 Length;
@ -1098,6 +1155,11 @@ typedef union _MPI25_SGE_IO_UNION {
#define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT (0x00)
#define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80)
/*Next Segment Format */
#define MPI26_IEEE_SGE_FLAGS_NSF_MASK (0x1C)
#define MPI26_IEEE_SGE_FLAGS_NSF_MPI_IEEE (0x00)
/*Data Location Address Space */
#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK (0x03)
@ -1108,6 +1170,7 @@ typedef union _MPI25_SGE_IO_UNION {
#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR (0x03)
#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR \
(MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR)
#define MPI26_IEEE_SGE_FLAGS_IOCCTL_ADDR (0x02)
/****************************************************************************
* IEEE SGE operation Macros
@ -1166,6 +1229,7 @@ typedef union _MPI2_SGE_IO_UNION {
#define MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE (0x00)
#define MPI2_SGLFLAGS_IOCDDR_ADDRESS_SPACE (0x04)
#define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE (0x08)
#define MPI26_SGLFLAGS_IOCPLB_ADDRESS_SPACE (0x08)
#define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE (0x0C)
/*values for SGL Type subfield */
#define MPI2_SGLFLAGS_SGL_TYPE_MASK (0x03)

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2000-2014 LSI Corporation.
* Copyright 2000-2015 Avago Technologies. All rights reserved.
*
*
* Name: mpi2_cnfg.h
* Title: MPI Configuration messages and pages
* Creation Date: November 10, 2006
*
* mpi2_cnfg.h Version: 02.00.29
* mpi2_cnfg.h Version: 02.00.33
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@ -178,7 +178,14 @@
* 01-08-14 02.00.28 Added more defines for the BiosOptions field of
* MPI2_CONFIG_PAGE_BIOS_1.
* 06-13-14 02.00.29 Added SSUTimeout field to MPI2_CONFIG_PAGE_BIOS_1, and
* more defines for the BiosOptions field..
* more defines for the BiosOptions field.
* 11-18-14 02.00.30 Updated copyright information.
* Added MPI2_BIOSPAGE1_OPTIONS_ADVANCED_CONFIG.
* Added AdapterOrderAux fields to BIOS Page 3.
* 03-16-15 02.00.31 Updated for MPI v2.6.
* Added new SAS Phy Event codes
* 05-25-15 02.00.33 Added more defines for the BiosOptions field of
* MPI2_CONFIG_PAGE_BIOS_1.
* --------------------------------------------------------------------------
*/
@ -355,7 +362,6 @@ typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION {
#define MPI2_ETHERNET_PGAD_IF_NUMBER_MASK (0x000000FF)
/****************************************************************************
* Configuration messages
****************************************************************************/
@ -457,8 +463,17 @@ typedef struct _MPI2_CONFIG_REPLY {
#define MPI25_MFGPAGE_DEVID_SAS3108_5 (0x0094)
#define MPI25_MFGPAGE_DEVID_SAS3108_6 (0x0095)
/* MPI v2.6 SAS Products */
#define MPI26_MFGPAGE_DEVID_SAS3216 (0x00C9)
#define MPI26_MFGPAGE_DEVID_SAS3224 (0x00C4)
#define MPI26_MFGPAGE_DEVID_SAS3316_1 (0x00C5)
#define MPI26_MFGPAGE_DEVID_SAS3316_2 (0x00C6)
#define MPI26_MFGPAGE_DEVID_SAS3316_3 (0x00C7)
#define MPI26_MFGPAGE_DEVID_SAS3316_4 (0x00C8)
#define MPI26_MFGPAGE_DEVID_SAS3324_1 (0x00C0)
#define MPI26_MFGPAGE_DEVID_SAS3324_2 (0x00C1)
#define MPI26_MFGPAGE_DEVID_SAS3324_3 (0x00C2)
#define MPI26_MFGPAGE_DEVID_SAS3324_4 (0x00C3)
/*Manufacturing Page 0 */
@ -941,8 +956,8 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 {
U8
BoardTemperatureUnits; /*0x16 */
U8 Reserved3; /*0x17 */
U32 Reserved4; /* 0x18 */
U32 Reserved5; /* 0x1C */
U32 BoardPowerRequirement; /*0x18 */
U32 PCISlotPowerAllocation; /*0x1C */
U32 Reserved6; /* 0x20 */
U32 Reserved7; /* 0x24 */
} MPI2_CONFIG_PAGE_IO_UNIT_7,
@ -1151,6 +1166,62 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 {
#define MPI2_IOUNITPAGE10_PAGEVERSION (0x01)
/* IO Unit Page 11 (for MPI v2.6 and later) */
typedef struct _MPI26_IOUNIT11_SPINUP_GROUP {
U8 MaxTargetSpinup; /* 0x00 */
U8 SpinupDelay; /* 0x01 */
U8 SpinupFlags; /* 0x02 */
U8 Reserved1; /* 0x03 */
} MPI26_IOUNIT11_SPINUP_GROUP,
*PTR_MPI26_IOUNIT11_SPINUP_GROUP,
Mpi26IOUnit11SpinupGroup_t,
*pMpi26IOUnit11SpinupGroup_t;
/* defines for IO Unit Page 11 SpinupFlags */
#define MPI26_IOUNITPAGE11_SPINUP_DISABLE_FLAG (0x01)
/*
* Host code (drivers, BIOS, utilities, etc.) should leave this define set to
* four and check the value returned for NumPhys at runtime.
*/
#ifndef MPI26_IOUNITPAGE11_PHY_MAX
#define MPI26_IOUNITPAGE11_PHY_MAX (4)
#endif
typedef struct _MPI26_CONFIG_PAGE_IO_UNIT_11 {
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
U32 Reserved1; /*0x04 */
MPI26_IOUNIT11_SPINUP_GROUP SpinupGroupParameters[4]; /*0x08 */
U32 Reserved2; /*0x18 */
U32 Reserved3; /*0x1C */
U32 Reserved4; /*0x20 */
U8 BootDeviceWaitTime; /*0x24 */
U8 Reserved5; /*0x25 */
U16 Reserved6; /*0x26 */
U8 NumPhys; /*0x28 */
U8 PEInitialSpinupDelay; /*0x29 */
U8 PEReplyDelay; /*0x2A */
U8 Flags; /*0x2B */
U8 PHY[MPI26_IOUNITPAGE11_PHY_MAX];/*0x2C */
} MPI26_CONFIG_PAGE_IO_UNIT_11,
*PTR_MPI26_CONFIG_PAGE_IO_UNIT_11,
Mpi26IOUnitPage11_t,
*pMpi26IOUnitPage11_t;
#define MPI26_IOUNITPAGE11_PAGEVERSION (0x00)
/* defines for Flags field */
#define MPI26_IOUNITPAGE11_FLAGS_AUTO_PORTENABLE (0x01)
/* defines for PHY field */
#define MPI26_IOUNITPAGE11_PHY_SPINUP_GROUP_MASK (0x03)
/****************************************************************************
* IOC Config Pages
@ -1343,6 +1414,10 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_1 {
#define MPI2_BIOSPAGE1_PAGEVERSION (0x07)
/*values for BIOS Page 1 BiosOptions field */
#define MPI2_BIOSPAGE1_OPTIONS_BOOT_LIST_ADD_ALT_BOOT_DEVICE (0x00008000)
#define MPI2_BIOSPAGE1_OPTIONS_ADVANCED_CONFIG (0x00004000)
#define MPI2_BIOSPAGE1_OPTIONS_PNS_MASK (0x00003800)
#define MPI2_BIOSPAGE1_OPTIONS_PNS_MASK (0x00003800)
#define MPI2_BIOSPAGE1_OPTIONS_PNS_PBDHL (0x00000000)
#define MPI2_BIOSPAGE1_OPTIONS_PNS_ENCSLOSURE (0x00000800)
@ -1492,6 +1567,8 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_2 {
/*BIOS Page 3 */
#define MPI2_BIOSPAGE3_NUM_ADAPTER (4)
typedef struct _MPI2_ADAPTER_INFO {
U8 PciBusNumber; /*0x00 */
U8 PciDeviceAndFunctionNumber; /*0x01 */
@ -1502,17 +1579,26 @@ typedef struct _MPI2_ADAPTER_INFO {
#define MPI2_ADAPTER_INFO_FLAGS_EMBEDDED (0x0001)
#define MPI2_ADAPTER_INFO_FLAGS_INIT_STATUS (0x0002)
typedef struct _MPI2_ADAPTER_ORDER_AUX {
U64 WWID; /* 0x00 */
U32 Reserved1; /* 0x08 */
U32 Reserved2; /* 0x0C */
} MPI2_ADAPTER_ORDER_AUX, *PTR_MPI2_ADAPTER_ORDER_AUX,
Mpi2AdapterOrderAux_t, *pMpi2AdapterOrderAux_t;
typedef struct _MPI2_CONFIG_PAGE_BIOS_3 {
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
U32 GlobalFlags; /*0x04 */
U32 BiosVersion; /*0x08 */
MPI2_ADAPTER_INFO AdapterOrder[4]; /*0x0C */
MPI2_ADAPTER_INFO AdapterOrder[MPI2_BIOSPAGE3_NUM_ADAPTER];
U32 Reserved1; /*0x1C */
MPI2_ADAPTER_ORDER_AUX AdapterOrderAux[MPI2_BIOSPAGE3_NUM_ADAPTER];
} MPI2_CONFIG_PAGE_BIOS_3,
*PTR_MPI2_CONFIG_PAGE_BIOS_3,
Mpi2BiosPage3_t, *pMpi2BiosPage3_t;
#define MPI2_BIOSPAGE3_PAGEVERSION (0x00)
#define MPI2_BIOSPAGE3_PAGEVERSION (0x01)
/*values for BIOS Page 3 GlobalFlags */
#define MPI2_BIOSPAGE3_FLAGS_PAUSE_ON_ERROR (0x00000002)
@ -2006,6 +2092,8 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0 {
#define MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG (0x01)
/*values for SAS IO Unit Page 0 PhyFlags */
#define MPI2_SASIOUNIT0_PHYFLAGS_INIT_PERSIST_CONNECT (0x40)
#define MPI2_SASIOUNIT0_PHYFLAGS_TARG_PERSIST_CONNECT (0x20)
#define MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED (0x10)
#define MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08)
@ -2108,6 +2196,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 {
#define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
/*values for SAS IO Unit Page 1 AdditionalControlFlags */
#define MPI2_SASIOUNIT1_ACONTROL_DA_PERSIST_CONNECT (0x0100)
#define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080)
#define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040)
#define MPI2_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION (0x0020)
@ -2125,6 +2214,8 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 {
#define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
/*values for SAS IO Unit Page 1 PhyFlags */
#define MPI2_SASIOUNIT1_PHYFLAGS_INIT_PERSIST_CONNECT (0x40)
#define MPI2_SASIOUNIT1_PHYFLAGS_TARG_PERSIST_CONNECT (0x20)
#define MPI2_SASIOUNIT1_PHYFLAGS_ZONING_ENABLE (0x10)
#define MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08)
@ -2144,7 +2235,7 @@ typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 {
*SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
/*SAS IO Unit Page 4 */
/*SAS IO Unit Page 4 (for MPI v2.5 and earlier) */
typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP {
U8 MaxTargetSpinup; /*0x00 */
@ -2715,6 +2806,7 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0 {
#define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020)
#define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010)
#define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008)
#define MPI2_SAS_DEVICE0_FLAGS_PERSIST_CAPABLE (0x0004)
#define MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID (0x0002)
#define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001)
@ -2922,6 +3014,19 @@ typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG {
#define MPI2_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE (0xD1)
#define MPI2_SASPHY3_EVENT_CODE_RX_AIP (0xD2)
/*Following codes are product specific and in MPI v2.6 and later */
#define MPI2_SASPHY3_EVENT_CODE_LCARB_WAIT_TIME (0xD3)
#define MPI2_SASPHY3_EVENT_CODE_RCVD_CONN_RESP_WAIT_TIME (0xD4)
#define MPI2_SASPHY3_EVENT_CODE_LCCONN_TIME (0xD5)
#define MPI2_SASPHY3_EVENT_CODE_SSP_TX_START_TRANSMIT (0xD6)
#define MPI2_SASPHY3_EVENT_CODE_SATA_TX_START (0xD7)
#define MPI2_SASPHY3_EVENT_CODE_SMP_TX_START_TRANSMT (0xD8)
#define MPI2_SASPHY3_EVENT_CODE_TX_SMP_BREAK_CONN (0xD9)
#define MPI2_SASPHY3_EVENT_CODE_SSP_RX_START_RECEIVE (0xDA)
#define MPI2_SASPHY3_EVENT_CODE_SATA_RX_START_RECEIVE (0xDB)
#define MPI2_SASPHY3_EVENT_CODE_SMP_RX_START_RECEIVE (0xDC)
/*values for the CounterType field */
#define MPI2_SASPHY3_COUNTER_TYPE_WRAPPING (0x00)
#define MPI2_SASPHY3_COUNTER_TYPE_SATURATING (0x01)

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2000-2014 LSI Corporation.
* Copyright 2000-2015 Avago Technologies. All rights reserved.
*
*
* Name: mpi2_init.h
* Title: MPI SCSI initiator mode messages and structures
* Creation Date: June 23, 2006
*
* mpi2_init.h Version: 02.00.15
* mpi2_init.h Version: 02.00.17
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@ -46,6 +46,11 @@
* 07-10-12 02.00.14 Added MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION.
* 04-09-13 02.00.15 Added SCSIStatusQualifier field to MPI2_SCSI_IO_REPLY,
* replacing the Reserved4 field.
* 11-18-14 02.00.16 Updated copyright information.
* 03-16-15 02.00.17 Updated for MPI v2.6.
* Added MPI26_SCSIIO_IOFLAGS_ESCAPE_PASSTHROUGH.
* Added MPI2_SEP_REQ_SLOTSTATUS_DEV_OFF and
* MPI2_SEP_REPLY_SLOTSTATUS_DEV_OFF.
* --------------------------------------------------------------------------
*/
@ -128,6 +133,7 @@ typedef struct _MPI2_SCSI_IO_REQUEST {
#define MPI2_SCSIIO_MSGFLAGS_IOCDDR_SENSE_ADDR (0x04)
#define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR (0x08)
#define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR (0x0C)
#define MPI26_SCSIIO_MSGFLAGS_IOCCTL_SENSE_ADDR (0x08)
/*SCSI IO SGLFlags bits */
@ -228,7 +234,7 @@ typedef union _MPI25_SCSI_IO_CDB_UNION {
} MPI25_SCSI_IO_CDB_UNION, *PTR_MPI25_SCSI_IO_CDB_UNION,
Mpi25ScsiIoCdb_t, *pMpi25ScsiIoCdb_t;
/*MPI v2.5 SCSI IO Request Message */
/*MPI v2.5/2.6 SCSI IO Request Message */
typedef struct _MPI25_SCSI_IO_REQUEST {
U16 DevHandle; /*0x00 */
U8 ChainOffset; /*0x02 */
@ -302,12 +308,14 @@ typedef struct _MPI25_SCSI_IO_REQUEST {
#define MPI25_SCSIIO_NUM_SGLOFFSETS (4)
/*defines for the IoFlags field */
#define MPI25_SCSIIO_IOFLAGS_IO_PATH_MASK (0xC000)
#define MPI25_SCSIIO_IOFLAGS_NORMAL_PATH (0x0000)
#define MPI25_SCSIIO_IOFLAGS_FAST_PATH (0x4000)
#define MPI25_SCSIIO_IOFLAGS_IO_PATH_MASK (0xC000)
#define MPI25_SCSIIO_IOFLAGS_NORMAL_PATH (0x0000)
#define MPI25_SCSIIO_IOFLAGS_FAST_PATH (0x4000)
#define MPI26_SCSIIO_IOFLAGS_ESCAPE_PASSTHROUGH (0x2000)
#define MPI25_SCSIIO_IOFLAGS_LARGE_CDB (0x1000)
#define MPI25_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800)
#define MPI26_SCSIIO_IOFLAGS_PORT_REQUEST (0x0400)
#define MPI25_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF)
/*MPI v2.5 defines for the EEDPFlags bits */
@ -512,6 +520,7 @@ typedef struct _MPI2_SEP_REQUEST {
#define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01)
/*SlotStatus defines */
#define MPI2_SEP_REQ_SLOTSTATUS_DEV_OFF (0x00080000)
#define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000)
#define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000)
#define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200)
@ -547,6 +556,7 @@ typedef struct _MPI2_SEP_REPLY {
Mpi2SepReply_t, *pMpi2SepReply_t;
/*SlotStatus defines */
#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_OFF (0x00080000)
#define MPI2_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000)
#define MPI2_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000)
#define MPI2_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200)

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2000-2014 LSI Corporation.
* Copyright 2000-2015 Avago Technologies. All rights reserved.
*
*
* Name: mpi2_ioc.h
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: October 11, 2006
*
* mpi2_ioc.h Version: 02.00.24
* mpi2_ioc.h Version: 02.00.26
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@ -133,6 +133,10 @@
* Added MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY.
* Added Encrypted Hash Extended Image.
* 12-05-13 02.00.24 Added MPI25_HASH_IMAGE_TYPE_BIOS.
* 11-18-14 02.00.25 Updated copyright information.
* 03-16-15 02.00.26 Added MPI26_FW_HEADER_PID_FAMILY_3324_SAS and
* MPI26_FW_HEADER_PID_FAMILY_3516_SAS.
* Added MPI26_CTRL_OP_SHUTDOWN.
* --------------------------------------------------------------------------
*/
@ -165,7 +169,7 @@ typedef struct _MPI2_IOC_INIT_REQUEST {
U16 HeaderVersion; /*0x0E */
U32 Reserved5; /*0x10 */
U16 Reserved6; /*0x14 */
U8 Reserved7; /*0x16 */
U8 HostPageSize; /*0x16 */
U8 HostMSIxVectors; /*0x17 */
U16 Reserved8; /*0x18 */
U16 SystemRequestFrameSize; /*0x1A */
@ -289,7 +293,8 @@ typedef struct _MPI2_IOC_FACTS_REPLY {
U16 MaxDevHandle; /*0x38 */
U16 MaxPersistentEntries; /*0x3A */
U16 MinDevHandle; /*0x3C */
U16 Reserved4; /*0x3E */
U8 CurrentHostPageSize; /* 0x3E */
U8 Reserved4; /* 0x3F */
} MPI2_IOC_FACTS_REPLY, *PTR_MPI2_IOC_FACTS_REPLY,
Mpi2IOCFactsReply_t, *pMpi2IOCFactsReply_t;
@ -326,6 +331,7 @@ typedef struct _MPI2_IOC_FACTS_REPLY {
/*ProductID field uses MPI2_FW_HEADER_PID_ */
/*IOCCapabilities */
#define MPI26_IOCFACTS_CAPABILITY_ATOMIC_REQ (0x00080000)
#define MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE (0x00040000)
#define MPI25_IOCFACTS_CAPABILITY_FAST_PATH_CAPABLE (0x00020000)
#define MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY (0x00010000)
@ -343,8 +349,8 @@ typedef struct _MPI2_IOC_FACTS_REPLY {
#define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004)
/*ProtocolFlags */
#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001)
#define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002)
#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001)
/****************************************************************************
* PortFacts message
@ -1247,6 +1253,7 @@ typedef struct _MPI2_FW_UPLOAD_REQUEST {
#define MPI2_FW_UPLOAD_ITYPE_MEGARAID (0x09)
#define MPI2_FW_UPLOAD_ITYPE_COMPLETE (0x0A)
#define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
#define MPI2_FW_UPLOAD_ITYPE_CBB_BACKUP (0x0D)
/*MPI v2.0 FWUpload TransactionContext Element */
typedef struct _MPI2_FW_UPLOAD_TCSGE {
@ -1328,7 +1335,7 @@ typedef struct _MPI2_FW_IMAGE_HEADER {
U32 Reserved54; /*0x54 */
U32 Reserved58; /*0x58 */
U32 Reserved5C; /*0x5C */
U32 Reserved60; /*0x60 */
U32 BootFlags; /*0x60 */
U32 FirmwareVersionNameWhat; /*0x64 */
U8 FirmwareVersionName[32]; /*0x68 */
U32 VendorNameWhat; /*0x88 */
@ -1354,18 +1361,22 @@ typedef struct _MPI2_FW_IMAGE_HEADER {
#define MPI2_FW_HEADER_SIGNATURE_OFFSET (0x00)
#define MPI2_FW_HEADER_SIGNATURE_MASK (0xFF000000)
#define MPI2_FW_HEADER_SIGNATURE (0xEA000000)
#define MPI26_FW_HEADER_SIGNATURE (0xEB000000)
/*Signature0 field */
#define MPI2_FW_HEADER_SIGNATURE0_OFFSET (0x04)
#define MPI2_FW_HEADER_SIGNATURE0 (0x5AFAA55A)
#define MPI26_FW_HEADER_SIGNATURE0 (0x5AEAA55A)
/*Signature1 field */
#define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08)
#define MPI2_FW_HEADER_SIGNATURE1 (0xA55AFAA5)
#define MPI26_FW_HEADER_SIGNATURE1 (0xA55AEAA5)
/*Signature2 field */
#define MPI2_FW_HEADER_SIGNATURE2_OFFSET (0x0C)
#define MPI2_FW_HEADER_SIGNATURE2 (0x5AA55AFA)
#define MPI26_FW_HEADER_SIGNATURE2 (0x5AA55AEA)
/*defines for using the ProductID field */
#define MPI2_FW_HEADER_PID_TYPE_MASK (0xF000)
@ -1381,6 +1392,8 @@ typedef struct _MPI2_FW_IMAGE_HEADER {
#define MPI2_FW_HEADER_PID_FAMILY_2108_SAS (0x0013)
#define MPI2_FW_HEADER_PID_FAMILY_2208_SAS (0x0014)
#define MPI25_FW_HEADER_PID_FAMILY_3108_SAS (0x0021)
#define MPI26_FW_HEADER_PID_FAMILY_3324_SAS (0x0028)
#define MPI26_FW_HEADER_PID_FAMILY_3516_SAS (0x0031)
/*use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */
@ -1388,6 +1401,7 @@ typedef struct _MPI2_FW_IMAGE_HEADER {
#define MPI2_FW_HEADER_IMAGESIZE_OFFSET (0x2C)
#define MPI2_FW_HEADER_NEXTIMAGE_OFFSET (0x30)
#define MPI26_FW_HEADER_BOOTFLAGS_OFFSET (0x60)
#define MPI2_FW_HEADER_VERNMHWAT_OFFSET (0x64)
#define MPI2_FW_HEADER_WHAT_SIGNATURE (0x29232840)
@ -1493,7 +1507,9 @@ typedef struct _MPI2_FLASH_LAYOUT_DATA {
#define MPI2_FLASH_REGION_CONFIG_1 (0x07)
#define MPI2_FLASH_REGION_CONFIG_2 (0x08)
#define MPI2_FLASH_REGION_MEGARAID (0x09)
#define MPI2_FLASH_REGION_INIT (0x0A)
#define MPI2_FLASH_REGION_COMMON_BOOT_BLOCK (0x0A)
#define MPI2_FLASH_REGION_INIT (MPI2_FLASH_REGION_COMMON_BOOT_BLOCK)
#define MPI2_FLASH_REGION_CBB_BACKUP (0x0D)
/*ImageRevision */
#define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00)
@ -1619,7 +1635,6 @@ typedef struct _MPI25_ENCRYPTED_HASH_DATA {
Mpi25EncryptedHashData_t, *pMpi25EncryptedHashData_t;
/****************************************************************************
* PowerManagementControl message
****************************************************************************/
@ -1726,4 +1741,90 @@ typedef struct _MPI2_PWR_MGMT_CONTROL_REPLY {
} MPI2_PWR_MGMT_CONTROL_REPLY, *PTR_MPI2_PWR_MGMT_CONTROL_REPLY,
Mpi2PwrMgmtControlReply_t, *pMpi2PwrMgmtControlReply_t;
/****************************************************************************
* IO Unit Control messages (MPI v2.6 and later only.)
****************************************************************************/
/* IO Unit Control Request Message */
typedef struct _MPI26_IOUNIT_CONTROL_REQUEST {
U8 Operation; /* 0x00 */
U8 Reserved1; /* 0x01 */
U8 ChainOffset; /* 0x02 */
U8 Function; /* 0x03 */
U16 DevHandle; /* 0x04 */
U8 IOCParameter; /* 0x06 */
U8 MsgFlags; /* 0x07 */
U8 VP_ID; /* 0x08 */
U8 VF_ID; /* 0x09 */
U16 Reserved3; /* 0x0A */
U16 Reserved4; /* 0x0C */
U8 PhyNum; /* 0x0E */
U8 PrimFlags; /* 0x0F */
U32 Primitive; /* 0x10 */
U8 LookupMethod; /* 0x14 */
U8 Reserved5; /* 0x15 */
U16 SlotNumber; /* 0x16 */
U64 LookupAddress; /* 0x18 */
U32 IOCParameterValue; /* 0x20 */
U32 Reserved7; /* 0x24 */
U32 Reserved8; /* 0x28 */
} MPI26_IOUNIT_CONTROL_REQUEST,
*PTR_MPI26_IOUNIT_CONTROL_REQUEST,
Mpi26IoUnitControlRequest_t,
*pMpi26IoUnitControlRequest_t;
/* values for the Operation field */
#define MPI26_CTRL_OP_CLEAR_ALL_PERSISTENT (0x02)
#define MPI26_CTRL_OP_SAS_PHY_LINK_RESET (0x06)
#define MPI26_CTRL_OP_SAS_PHY_HARD_RESET (0x07)
#define MPI26_CTRL_OP_PHY_CLEAR_ERROR_LOG (0x08)
#define MPI26_CTRL_OP_SAS_SEND_PRIMITIVE (0x0A)
#define MPI26_CTRL_OP_FORCE_FULL_DISCOVERY (0x0B)
#define MPI26_CTRL_OP_REMOVE_DEVICE (0x0D)
#define MPI26_CTRL_OP_LOOKUP_MAPPING (0x0E)
#define MPI26_CTRL_OP_SET_IOC_PARAMETER (0x0F)
#define MPI26_CTRL_OP_ENABLE_FP_DEVICE (0x10)
#define MPI26_CTRL_OP_DISABLE_FP_DEVICE (0x11)
#define MPI26_CTRL_OP_ENABLE_FP_ALL (0x12)
#define MPI26_CTRL_OP_DISABLE_FP_ALL (0x13)
#define MPI26_CTRL_OP_DEV_ENABLE_NCQ (0x14)
#define MPI26_CTRL_OP_DEV_DISABLE_NCQ (0x15)
#define MPI26_CTRL_OP_SHUTDOWN (0x16)
#define MPI26_CTRL_OP_DEV_ENABLE_PERSIST_CONNECTION (0x17)
#define MPI26_CTRL_OP_DEV_DISABLE_PERSIST_CONNECTION (0x18)
#define MPI26_CTRL_OP_DEV_CLOSE_PERSIST_CONNECTION (0x19)
#define MPI26_CTRL_OP_PRODUCT_SPECIFIC_MIN (0x80)
/* values for the PrimFlags field */
#define MPI26_CTRL_PRIMFLAGS_SINGLE (0x08)
#define MPI26_CTRL_PRIMFLAGS_TRIPLE (0x02)
#define MPI26_CTRL_PRIMFLAGS_REDUNDANT (0x01)
/* values for the LookupMethod field */
#define MPI26_CTRL_LOOKUP_METHOD_WWID_ADDRESS (0x01)
#define MPI26_CTRL_LOOKUP_METHOD_ENCLOSURE_SLOT (0x02)
#define MPI26_CTRL_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03)
/* IO Unit Control Reply Message */
typedef struct _MPI26_IOUNIT_CONTROL_REPLY {
U8 Operation; /* 0x00 */
U8 Reserved1; /* 0x01 */
U8 MsgLength; /* 0x02 */
U8 Function; /* 0x03 */
U16 DevHandle; /* 0x04 */
U8 IOCParameter; /* 0x06 */
U8 MsgFlags; /* 0x07 */
U8 VP_ID; /* 0x08 */
U8 VF_ID; /* 0x09 */
U16 Reserved3; /* 0x0A */
U16 Reserved4; /* 0x0C */
U16 IOCStatus; /* 0x0E */
U32 IOCLogInfo; /* 0x10 */
} MPI26_IOUNIT_CONTROL_REPLY,
*PTR_MPI26_IOUNIT_CONTROL_REPLY,
Mpi26IoUnitControlReply_t,
*pMpi26IoUnitControlReply_t;
#endif

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2000-2014 LSI Corporation.
* Copyright 2000-2014 Avago Technologies. All rights reserved.
*
*
* Name: mpi2_raid.h
* Title: MPI Integrated RAID messages and structures
* Creation Date: April 26, 2007
*
* mpi2_raid.h Version: 02.00.10
* mpi2_raid.h Version: 02.00.11
*
* Version History
* ---------------
@ -31,6 +31,7 @@
* 07-26-12 02.00.09 Added ElapsedSeconds field to MPI2_RAID_VOL_INDICATOR.
* Added MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID define.
* 04-17-13 02.00.10 Added MPI25_RAID_ACTION_ADATA_ALLOW_PI.
* 11-18-14 02.00.11 Updated copyright information.
* --------------------------------------------------------------------------
*/

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2000-2014 LSI Corporation.
* Copyright 2000-2015 Avago Technologies. All rights reserved.
*
*
* Name: mpi2_sas.h
* Title: MPI Serial Attached SCSI structures and definitions
* Creation Date: February 9, 2007
*
* mpi2_sas.h Version: 02.00.08
* mpi2_sas.h Version: 02.00.10
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@ -32,6 +32,9 @@
* Passthrough Request message.
* 08-19-13 02.00.08 Made MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL obsolete
* for anything newer than MPI v2.0.
* 11-18-14 02.00.09 Updated copyright information.
* 03-16-15 02.00.10 Updated for MPI v2.6.
* Added MPI2_SATA_PT_REQ_PT_FLAGS_FPDMA.
* --------------------------------------------------------------------------
*/
@ -183,6 +186,7 @@ typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST {
/*values for PassthroughFlags field */
#define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100)
#define MPI2_SATA_PT_REQ_PT_FLAGS_FPDMA (0x0040)
#define MPI2_SATA_PT_REQ_PT_FLAGS_DMA (0x0020)
#define MPI2_SATA_PT_REQ_PT_FLAGS_PIO (0x0010)
#define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004)
@ -216,6 +220,8 @@ typedef struct _MPI2_SATA_PASSTHROUGH_REPLY {
/****************************************************************************
* SAS IO Unit Control messages
* (MPI v2.5 and earlier only.
* Replaced by IO Unit Control messages in MPI v2.6 and later.)
****************************************************************************/
/*SAS IO Unit Control Request Message */

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2000-2014 LSI Corporation.
* Copyright 2000-2014 Avago Technologies. All rights reserved.
*
*
* Name: mpi2_tool.h
* Title: MPI diagnostic tool structures and definitions
* Creation Date: March 26, 2007
*
* mpi2_tool.h Version: 02.00.12
* mpi2_tool.h Version: 02.00.13
*
* Version History
* ---------------
@ -34,6 +34,7 @@
* it uses MPI Chain SGE as well as MPI Simple SGE.
* 08-19-13 02.00.11 Added MPI2_TOOLBOX_TEXT_DISPLAY_TOOL and related info.
* 01-08-14 02.00.12 Added MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC.
* 11-18-14 02.00.13 Updated copyright information.
* --------------------------------------------------------------------------
*/

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2000-2014 LSI Corporation.
* Copyright 2000-2014 Avago Technologies. All rights reserved.
*
*
* Name: mpi2_type.h
* Title: MPI basic type definitions
* Creation Date: August 16, 2006
*
* mpi2_type.h Version: 02.00.00
* mpi2_type.h Version: 02.00.01
*
* Version History
* ---------------
@ -14,6 +14,7 @@
* Date Version Description
* -------- -------- ------------------------------------------------------
* 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
* 11-18-14 02.00.01 Updated copyright information.
* --------------------------------------------------------------------------
*/

View File

@ -83,6 +83,10 @@ static int msix_disable = -1;
module_param(msix_disable, int, 0);
MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
static int smp_affinity_enable = 1;
module_param(smp_affinity_enable, int, S_IRUGO);
MODULE_PARM_DESC(smp_affinity_enable, "SMP affinity feature enable/disbale Default: enable(1)");
static int max_msix_vectors = -1;
module_param(max_msix_vectors, int, 0);
MODULE_PARM_DESC(max_msix_vectors,
@ -395,6 +399,9 @@ _base_sas_ioc_info(struct MPT3SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
desc = "insufficient resources";
break;
case MPI2_IOCSTATUS_INSUFFICIENT_POWER:
desc = "insufficient power";
break;
case MPI2_IOCSTATUS_INVALID_FIELD:
desc = "invalid field";
break;
@ -772,7 +779,7 @@ mpt3sas_base_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK)
return 1;
return mpt3sas_check_for_pending_internal_cmds(ioc, smid);
if (ioc->base_cmds.status == MPT3_CMD_NOT_USED)
return 1;
@ -803,6 +810,7 @@ _base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply)
Mpi2EventNotificationReply_t *mpi_reply;
Mpi2EventAckRequest_t *ack_request;
u16 smid;
struct _event_ack_list *delayed_event_ack;
mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
if (!mpi_reply)
@ -816,8 +824,18 @@ _base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply)
goto out;
smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
if (!smid) {
pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
ioc->name, __func__);
delayed_event_ack = kzalloc(sizeof(*delayed_event_ack),
GFP_ATOMIC);
if (!delayed_event_ack)
goto out;
INIT_LIST_HEAD(&delayed_event_ack->list);
delayed_event_ack->Event = mpi_reply->Event;
delayed_event_ack->EventContext = mpi_reply->EventContext;
list_add_tail(&delayed_event_ack->list,
&ioc->delayed_event_ack_list);
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"DELAYED: EVENT ACK: event (0x%04x)\n",
ioc->name, le16_to_cpu(mpi_reply->Event)));
goto out;
}
@ -1348,6 +1366,7 @@ _base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr)
u8 sgl_flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR |
MPI25_IEEE_SGE_FLAGS_END_OF_LIST);
_base_add_sg_single_ieee(paddr, sgl_flags, 0, 0, -1);
}
@ -1797,9 +1816,10 @@ _base_free_irq(struct MPT3SAS_ADAPTER *ioc)
list_for_each_entry_safe(reply_q, next, &ioc->reply_queue_list, list) {
list_del(&reply_q->list);
irq_set_affinity_hint(reply_q->vector, NULL);
free_cpumask_var(reply_q->affinity_hint);
synchronize_irq(reply_q->vector);
if (smp_affinity_enable) {
irq_set_affinity_hint(reply_q->vector, NULL);
free_cpumask_var(reply_q->affinity_hint);
}
free_irq(reply_q->vector, reply_q);
kfree(reply_q);
}
@ -1829,9 +1849,12 @@ _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index, u32 vector)
reply_q->msix_index = index;
reply_q->vector = vector;
if (!alloc_cpumask_var(&reply_q->affinity_hint, GFP_KERNEL))
return -ENOMEM;
cpumask_clear(reply_q->affinity_hint);
if (smp_affinity_enable) {
if (!zalloc_cpumask_var(&reply_q->affinity_hint, GFP_KERNEL)) {
kfree(reply_q);
return -ENOMEM;
}
}
atomic_set(&reply_q->busy, 0);
if (ioc->msix_enable)
@ -1845,6 +1868,7 @@ _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index, u32 vector)
if (r) {
pr_err(MPT3SAS_FMT "unable to allocate interrupt %d!\n",
reply_q->name, vector);
free_cpumask_var(reply_q->affinity_hint);
kfree(reply_q);
return -EBUSY;
}
@ -1894,16 +1918,17 @@ _base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc)
for (i = 0 ; i < group ; i++) {
ioc->cpu_msix_table[cpu] = index;
cpumask_or(reply_q->affinity_hint,
if (smp_affinity_enable)
cpumask_or(reply_q->affinity_hint,
reply_q->affinity_hint, get_cpu_mask(cpu));
cpu = cpumask_next(cpu, cpu_online_mask);
}
if (irq_set_affinity_hint(reply_q->vector,
if (smp_affinity_enable)
if (irq_set_affinity_hint(reply_q->vector,
reply_q->affinity_hint))
dinitprintk(ioc, pr_info(MPT3SAS_FMT
"error setting affinity hint for irq vector %d\n",
ioc->name, reply_q->vector));
dinitprintk(ioc, pr_info(MPT3SAS_FMT
"Err setting affinity hint to irq vector %d\n",
ioc->name, reply_q->vector));
index++;
}
}
@ -1961,6 +1986,9 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc)
} else if (max_msix_vectors == 0)
goto try_ioapic;
if (ioc->msix_vector_count < ioc->cpu_count)
smp_affinity_enable = 0;
entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry),
GFP_KERNEL);
if (!entries) {
@ -2231,6 +2259,12 @@ mpt3sas_base_get_reply_virt_addr(struct MPT3SAS_ADAPTER *ioc, u32 phys_addr)
return ioc->reply + (phys_addr - (u32)ioc->reply_dma);
}
static inline u8
_base_get_msix_index(struct MPT3SAS_ADAPTER *ioc)
{
return ioc->cpu_msix_table[raw_smp_processor_id()];
}
/**
* mpt3sas_base_get_smid - obtain a free smid from internal queue
* @ioc: per adapter object
@ -2291,6 +2325,7 @@ mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx,
request->scmd = scmd;
request->cb_idx = cb_idx;
smid = request->smid;
request->msix_io = _base_get_msix_index(ioc);
list_del(&request->tracker_list);
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
return smid;
@ -2413,12 +2448,6 @@ _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock)
}
#endif
static inline u8
_base_get_msix_index(struct MPT3SAS_ADAPTER *ioc)
{
return ioc->cpu_msix_table[raw_smp_processor_id()];
}
/**
* mpt3sas_base_put_smid_scsi_io - send SCSI_IO request to firmware
* @ioc: per adapter object
@ -2472,18 +2501,19 @@ mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid,
* mpt3sas_base_put_smid_hi_priority - send Task Managment request to firmware
* @ioc: per adapter object
* @smid: system request message index
*
* @msix_task: msix_task will be same as msix of IO incase of task abort else 0.
* Return nothing.
*/
void
mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid)
mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid,
u16 msix_task)
{
Mpi2RequestDescriptorUnion_t descriptor;
u64 *request = (u64 *)&descriptor;
descriptor.HighPriority.RequestFlags =
MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
descriptor.HighPriority.MSIxIndex = 0;
descriptor.HighPriority.MSIxIndex = msix_task;
descriptor.HighPriority.SMID = cpu_to_le16(smid);
descriptor.HighPriority.LMID = 0;
descriptor.HighPriority.Reserved1 = 0;
@ -3185,20 +3215,35 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
}
ioc->shost->sg_tablesize = sg_tablesize;
ioc->hi_priority_depth = facts->HighPriorityCredit;
ioc->internal_depth = ioc->hi_priority_depth + (5);
ioc->internal_depth = min_t(int, (facts->HighPriorityCredit + (5)),
(facts->RequestCredit / 4));
if (ioc->internal_depth < INTERNAL_CMDS_COUNT) {
if (facts->RequestCredit <= (INTERNAL_CMDS_COUNT +
INTERNAL_SCSIIO_CMDS_COUNT)) {
pr_err(MPT3SAS_FMT "IOC doesn't have enough Request \
Credits, it has just %d number of credits\n",
ioc->name, facts->RequestCredit);
return -ENOMEM;
}
ioc->internal_depth = 10;
}
ioc->hi_priority_depth = ioc->internal_depth - (5);
/* command line tunables for max controller queue depth */
if (max_queue_depth != -1 && max_queue_depth != 0) {
max_request_credit = min_t(u16, max_queue_depth +
ioc->hi_priority_depth + ioc->internal_depth,
facts->RequestCredit);
ioc->internal_depth, facts->RequestCredit);
if (max_request_credit > MAX_HBA_QUEUE_DEPTH)
max_request_credit = MAX_HBA_QUEUE_DEPTH;
} else
max_request_credit = min_t(u16, facts->RequestCredit,
MAX_HBA_QUEUE_DEPTH);
ioc->hba_queue_depth = max_request_credit;
/* Firmware maintains additional facts->HighPriorityCredit number of
* credits for HiPriprity Request messages, so hba queue depth will be
* sum of max_request_credit and high priority queue depth.
*/
ioc->hba_queue_depth = max_request_credit + ioc->hi_priority_depth;
/* request frame size */
ioc->request_sz = facts->IOCRequestFrameSize * 4;
@ -3206,6 +3251,19 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
/* reply frame size */
ioc->reply_sz = facts->ReplyFrameSize * 4;
/* chain segment size */
if (ioc->hba_mpi_version_belonged != MPI2_VERSION) {
if (facts->IOCMaxChainSegmentSize)
ioc->chain_segment_sz =
facts->IOCMaxChainSegmentSize *
MAX_CHAIN_ELEMT_SZ;
else
/* set to 128 bytes size if IOCMaxChainSegmentSize is zero */
ioc->chain_segment_sz = DEFAULT_NUM_FWCHAIN_ELEMTS *
MAX_CHAIN_ELEMT_SZ;
} else
ioc->chain_segment_sz = ioc->request_sz;
/* calculate the max scatter element size */
sge_size = max_t(u16, ioc->sge_size, ioc->sge_size_ieee);
@ -3217,7 +3275,7 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
ioc->max_sges_in_main_message = max_sge_elements/sge_size;
/* now do the same for a chain buffer */
max_sge_elements = ioc->request_sz - sge_size;
max_sge_elements = ioc->chain_segment_sz - sge_size;
ioc->max_sges_in_chain_message = max_sge_elements/sge_size;
/*
@ -3245,7 +3303,6 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
ioc->reply_post_queue_depth += 16 -
(ioc->reply_post_queue_depth % 16);
if (ioc->reply_post_queue_depth >
facts->MaxReplyDescriptorPostQueueDepth) {
ioc->reply_post_queue_depth =
@ -3327,7 +3384,7 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
/* set the scsi host can_queue depth
* with some internal commands that could be outstanding
*/
ioc->shost->can_queue = ioc->scsiio_depth;
ioc->shost->can_queue = ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT;
dinitprintk(ioc, pr_info(MPT3SAS_FMT
"scsi host: can_queue depth (%d)\n",
ioc->name, ioc->shost->can_queue));
@ -3354,8 +3411,9 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
if (ioc->scsiio_depth < MPT3SAS_SAS_QUEUE_DEPTH)
goto out;
retry_sz += 64;
ioc->hba_queue_depth = max_request_credit - retry_sz;
retry_sz = 64;
ioc->hba_queue_depth -= retry_sz;
_base_release_memory_pools(ioc);
goto retry_allocation;
}
@ -3410,7 +3468,7 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
goto out;
}
ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev,
ioc->request_sz, 16, 0);
ioc->chain_segment_sz, 16, 0);
if (!ioc->chain_dma_pool) {
pr_err(MPT3SAS_FMT "chain_dma_pool: pci_pool_create failed\n",
ioc->name);
@ -3424,13 +3482,13 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
ioc->chain_depth = i;
goto chain_done;
}
total_sz += ioc->request_sz;
total_sz += ioc->chain_segment_sz;
}
chain_done:
dinitprintk(ioc, pr_info(MPT3SAS_FMT
"chain pool depth(%d), frame_size(%d), pool_size(%d kB)\n",
ioc->name, ioc->chain_depth, ioc->request_sz,
((ioc->chain_depth * ioc->request_sz))/1024));
ioc->name, ioc->chain_depth, ioc->chain_segment_sz,
((ioc->chain_depth * ioc->chain_segment_sz))/1024));
/* initialize hi-priority queue smid's */
ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth,
@ -4291,6 +4349,10 @@ _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word);
facts->IOCRequestFrameSize =
le16_to_cpu(mpi_reply.IOCRequestFrameSize);
if (ioc->hba_mpi_version_belonged != MPI2_VERSION) {
facts->IOCMaxChainSegmentSize =
le16_to_cpu(mpi_reply.IOCMaxChainSegmentSize);
}
facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators);
facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets);
ioc->shost->max_id = -1;
@ -4973,6 +5035,8 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
u32 reply_address;
u16 smid;
struct _tr_list *delayed_tr, *delayed_tr_next;
struct _sc_list *delayed_sc, *delayed_sc_next;
struct _event_ack_list *delayed_event_ack, *delayed_event_ack_next;
u8 hide_flag;
struct adapter_reply_queue *reply_q;
long reply_post_free;
@ -4995,6 +5059,18 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
kfree(delayed_tr);
}
list_for_each_entry_safe(delayed_sc, delayed_sc_next,
&ioc->delayed_sc_list, list) {
list_del(&delayed_sc->list);
kfree(delayed_sc);
}
list_for_each_entry_safe(delayed_event_ack, delayed_event_ack_next,
&ioc->delayed_event_ack_list, list) {
list_del(&delayed_event_ack->list);
kfree(delayed_event_ack);
}
/* initialize the scsi lookup free list */
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
INIT_LIST_HEAD(&ioc->free_list);
@ -5226,6 +5302,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
ioc->build_zero_len_sge = &_base_build_zero_len_sge;
break;
case MPI25_VERSION:
case MPI26_VERSION:
/*
* In SAS3.0,
* SCSI_IO, SMP_PASSTHRU, SATA_PASSTHRU, Target Assist, and

View File

@ -73,9 +73,9 @@
#define MPT3SAS_DRIVER_NAME "mpt3sas"
#define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>"
#define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver"
#define MPT3SAS_DRIVER_VERSION "09.102.00.00"
#define MPT3SAS_MAJOR_VERSION 9
#define MPT3SAS_MINOR_VERSION 102
#define MPT3SAS_DRIVER_VERSION "12.100.00.00"
#define MPT3SAS_MAJOR_VERSION 12
#define MPT3SAS_MINOR_VERSION 100
#define MPT3SAS_BUILD_VERSION 0
#define MPT3SAS_RELEASE_VERSION 00
@ -122,11 +122,16 @@
#define NO_SLEEP 0
#define INTERNAL_CMDS_COUNT 10 /* reserved cmds */
/* reserved for issuing internally framed scsi io cmds */
#define INTERNAL_SCSIIO_CMDS_COUNT 3
#define MPI3_HIM_MASK 0xFFFFFFFF /* mask every bit*/
#define MPT3SAS_INVALID_DEVICE_HANDLE 0xFFFF
#define MAX_CHAIN_ELEMT_SZ 16
#define DEFAULT_NUM_FWCHAIN_ELEMTS 8
/*
* reset phases
*/
@ -398,6 +403,7 @@ struct MPT3SAS_DEVICE {
u8 configured_lun;
u8 block;
u8 tlr_snoop_check;
u8 ignore_delay_remove;
};
#define MPT3_CMD_NOT_USED 0x8000 /* free */
@ -643,6 +649,7 @@ struct chain_tracker {
* @cb_idx: callback index
* @direct_io: To indicate whether I/O is direct (WARPDRIVE)
* @tracker_list: list of free request (ioc->free_list)
* @msix_io: IO's msix
*/
struct scsiio_tracker {
u16 smid;
@ -651,6 +658,7 @@ struct scsiio_tracker {
u8 direct_io;
struct list_head chain_list;
struct list_head tracker_list;
u16 msix_io;
};
/**
@ -676,6 +684,25 @@ struct _tr_list {
u16 state;
};
/**
* struct _sc_list - delayed SAS_IO_UNIT_CONTROL message list
* @handle: device handle
*/
struct _sc_list {
struct list_head list;
u16 handle;
};
/**
* struct _event_ack_list - delayed event acknowledgment list
* @Event: Event ID
* @EventContext: used to track the event uniquely
*/
struct _event_ack_list {
struct list_head list;
u16 Event;
u32 EventContext;
};
/**
* struct adapter_reply_queue - the reply queue struct
@ -737,7 +764,7 @@ struct mpt3sas_facts {
u32 IOCCapabilities;
union mpi3_version_union FWVersion;
u16 IOCRequestFrameSize;
u16 Reserved3;
u16 IOCMaxChainSegmentSize;
u16 MaxInitiators;
u16 MaxTargets;
u16 MaxSasExpanders;
@ -884,6 +911,8 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
* @max_sges_in_chain_message: number sg elements per chain
* @chains_needed_per_io: max chains per io
* @chain_depth: total chains allocated
* @chain_segment_sz: gives the max number of
* SGEs accommodate on single chain buffer
* @hi_priority_smid:
* @hi_priority:
* @hi_priority_dma:
@ -921,6 +950,8 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
* @replyPostRegisterIndex: index of next position in Reply Desc Post Queue
* @delayed_tr_list: target reset link list
* @delayed_tr_volume_list: volume target reset link list
* @delayed_sc_list:
* @delayed_event_ack_list:
* @temp_sensors_count: flag to carry the number of temperature sensors
* @pci_access_mutex: Mutex to synchronize ioctl,sysfs show path and
* pci resource handling. PCI resource freeing will lead to free
@ -1089,6 +1120,7 @@ struct MPT3SAS_ADAPTER {
u16 max_sges_in_chain_message;
u16 chains_needed_per_io;
u32 chain_depth;
u16 chain_segment_sz;
/* hi-priority queue */
u16 hi_priority_smid;
@ -1142,6 +1174,8 @@ struct MPT3SAS_ADAPTER {
struct list_head delayed_tr_list;
struct list_head delayed_tr_volume_list;
struct list_head delayed_sc_list;
struct list_head delayed_event_ack_list;
u8 temp_sensors_count;
struct mutex pci_access_mutex;
@ -1213,7 +1247,8 @@ void mpt3sas_base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid,
u16 handle);
void mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid,
u16 handle);
void mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid);
void mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc,
u16 smid, u16 msix_task);
void mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid);
void mpt3sas_base_initialize_callback_handler(void);
u8 mpt3sas_base_register_callback_handler(MPT_CALLBACK cb_func);
@ -1259,6 +1294,8 @@ void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
void mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
void mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
u64 sas_address);
u8 mpt3sas_check_for_pending_internal_cmds(struct MPT3SAS_ADAPTER *ioc,
u16 smid);
struct _sas_node *mpt3sas_scsih_expander_find_by_handle(
struct MPT3SAS_ADAPTER *ioc, u16 handle);

View File

@ -401,7 +401,8 @@ mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
Mpi2EventNotificationReply_t *mpi_reply;
mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
mpt3sas_ctl_add_to_event_log(ioc, mpi_reply);
if (mpi_reply)
mpt3sas_ctl_add_to_event_log(ioc, mpi_reply);
return 1;
}
@ -410,7 +411,7 @@ mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
* @ioc: per adapter object
* @iocpp: The ioc pointer is returned in this.
* @mpi_version: will be MPI2_VERSION for mpt2ctl ioctl device &
* MPI25_VERSION for mpt3ctl ioctl device.
* MPI25_VERSION | MPI26_VERSION for mpt3ctl ioctl device.
*
* Return (-1) means error, else ioc_number.
*/
@ -419,6 +420,7 @@ _ctl_verify_adapter(int ioc_number, struct MPT3SAS_ADAPTER **iocpp,
int mpi_version)
{
struct MPT3SAS_ADAPTER *ioc;
int version = 0;
/* global ioc lock to protect controller on list operations */
spin_lock(&gioc_lock);
list_for_each_entry(ioc, &mpt3sas_ioc_list, list) {
@ -427,8 +429,21 @@ _ctl_verify_adapter(int ioc_number, struct MPT3SAS_ADAPTER **iocpp,
/* Check whether this ioctl command is from right
* ioctl device or not, if not continue the search.
*/
if (ioc->hba_mpi_version_belonged != mpi_version)
continue;
version = ioc->hba_mpi_version_belonged;
/* MPI25_VERSION and MPI26_VERSION uses same ioctl
* device.
*/
if (mpi_version == (MPI25_VERSION | MPI26_VERSION)) {
if ((version == MPI25_VERSION) ||
(version == MPI26_VERSION))
goto out;
else
continue;
} else {
if (version != mpi_version)
continue;
}
out:
spin_unlock(&gioc_lock);
*iocpp = ioc;
return ioc_number;
@ -817,7 +832,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
tm_request->DevHandle));
ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
data_in_dma, data_in_sz);
mpt3sas_base_put_smid_hi_priority(ioc, smid);
mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
break;
}
case MPI2_FUNCTION_SMP_PASSTHROUGH:
@ -1053,6 +1068,7 @@ _ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg)
strcat(karg.driver_version, MPT2SAS_DRIVER_VERSION);
break;
case MPI25_VERSION:
case MPI26_VERSION:
karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS3;
strcat(karg.driver_version, MPT3SAS_DRIVER_VERSION);
break;
@ -2203,7 +2219,7 @@ _ctl_compat_mpt_command(struct MPT3SAS_ADAPTER *ioc, unsigned cmd,
* @arg - user space data buffer
* @compat - handles 32 bit applications in 64bit os
* @mpi_version: will be MPI2_VERSION for mpt2ctl ioctl device &
* MPI25_VERSION for mpt3ctl ioctl device.
* MPI25_VERSION | MPI26_VERSION for mpt3ctl ioctl device.
*/
static long
_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg,
@ -2341,10 +2357,12 @@ _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret;
/* pass MPI25_VERSION value, to indicate that this ioctl cmd
/* pass MPI25_VERSION | MPI26_VERSION value,
* to indicate that this ioctl cmd
* came from mpt3ctl ioctl device.
*/
ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0, MPI25_VERSION);
ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0,
MPI25_VERSION | MPI26_VERSION);
return ret;
}
@ -2379,7 +2397,8 @@ _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
{
long ret;
ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1, MPI25_VERSION);
ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1,
MPI25_VERSION | MPI26_VERSION);
return ret;
}

View File

@ -1589,10 +1589,16 @@ scsih_get_resync(struct device *dev)
percent_complete = 0;
out:
if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
switch (ioc->hba_mpi_version_belonged) {
case MPI2_VERSION:
raid_set_resync(mpt2sas_raid_template, dev, percent_complete);
if (ioc->hba_mpi_version_belonged == MPI25_VERSION)
break;
case MPI25_VERSION:
case MPI26_VERSION:
raid_set_resync(mpt3sas_raid_template, dev, percent_complete);
break;
}
}
/**
@ -1650,10 +1656,15 @@ scsih_get_state(struct device *dev)
break;
}
out:
if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
switch (ioc->hba_mpi_version_belonged) {
case MPI2_VERSION:
raid_set_state(mpt2sas_raid_template, dev, state);
if (ioc->hba_mpi_version_belonged == MPI25_VERSION)
break;
case MPI25_VERSION:
case MPI26_VERSION:
raid_set_state(mpt3sas_raid_template, dev, state);
break;
}
}
/**
@ -1682,12 +1693,17 @@ _scsih_set_level(struct MPT3SAS_ADAPTER *ioc,
break;
}
if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
switch (ioc->hba_mpi_version_belonged) {
case MPI2_VERSION:
raid_set_level(mpt2sas_raid_template,
&sdev->sdev_gendev, level);
if (ioc->hba_mpi_version_belonged == MPI25_VERSION)
&sdev->sdev_gendev, level);
break;
case MPI25_VERSION:
case MPI26_VERSION:
raid_set_level(mpt3sas_raid_template,
&sdev->sdev_gendev, level);
&sdev->sdev_gendev, level);
break;
}
}
@ -1937,7 +1953,15 @@ scsih_slave_configure(struct scsi_device *sdev)
if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
ssp_target = 1;
ds = "SSP";
if (sas_device->device_info &
MPI2_SAS_DEVICE_INFO_SEP) {
sdev_printk(KERN_WARNING, sdev,
"set ignore_delay_remove for handle(0x%04x)\n",
sas_device_priv_data->sas_target->handle);
sas_device_priv_data->ignore_delay_remove = 1;
ds = "SES";
} else
ds = "SSP";
} else {
qdepth = MPT3SAS_SATA_QUEUE_DEPTH;
if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
@ -2193,6 +2217,7 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel,
unsigned long timeleft;
struct scsiio_tracker *scsi_lookup = NULL;
int rc;
u16 msix_task = 0;
if (m_type == TM_MUTEX_ON)
mutex_lock(&ioc->tm_cmds.mutex);
@ -2256,7 +2281,12 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel,
int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
mpt3sas_scsih_set_tm_flag(ioc, handle);
init_completion(&ioc->tm_cmds.done);
mpt3sas_base_put_smid_hi_priority(ioc, smid);
if ((type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) &&
(scsi_lookup->msix_io < ioc->reply_queue_count))
msix_task = scsi_lookup->msix_io;
else
msix_task = 0;
mpt3sas_base_put_smid_hi_priority(ioc, smid, msix_task);
timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) {
pr_err(MPT3SAS_FMT "%s: timeout\n",
@ -2383,7 +2413,7 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
(unsigned long long)
sas_device->enclosure_logical_id,
sas_device->slot);
if (sas_device->connector_name)
if (sas_device->connector_name[0] != '\0')
starget_printk(KERN_INFO, starget,
"enclosure level(0x%04x),connector name(%s)\n",
sas_device->enclosure_level,
@ -2927,6 +2957,12 @@ _scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc)
continue;
if (sas_device_priv_data->block)
continue;
if (sas_device_priv_data->ignore_delay_remove) {
sdev_printk(KERN_INFO, sdev,
"%s skip device_block for SES handle(0x%04x)\n",
__func__, sas_device_priv_data->sas_target->handle);
continue;
}
_scsih_internal_device_block(sdev, sas_device_priv_data);
}
}
@ -2959,6 +2995,12 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
continue;
if (sas_device->pend_sas_rphy_add)
continue;
if (sas_device_priv_data->ignore_delay_remove) {
sdev_printk(KERN_INFO, sdev,
"%s skip device_block for SES handle(0x%04x)\n",
__func__, sas_device_priv_data->sas_target->handle);
continue;
}
_scsih_internal_device_block(sdev, sas_device_priv_data);
}
@ -3118,7 +3160,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
" slot(%d)\n", ioc->name, (unsigned long long)
sas_device->enclosure_logical_id,
sas_device->slot));
if (sas_device->connector_name)
if (sas_device->connector_name[0] != '\0')
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"setting delete flag: enclosure level(0x%04x),"
" connector name( %s)\n", ioc->name,
@ -3151,7 +3193,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
mpi_request->DevHandle = cpu_to_le16(handle);
mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
mpt3sas_base_put_smid_hi_priority(ioc, smid);
mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL);
out:
@ -3186,6 +3228,7 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
Mpi2SasIoUnitControlRequest_t *mpi_request;
u16 smid_sas_ctrl;
u32 ioc_state;
struct _sc_list *delayed_sc;
if (ioc->remove_host) {
dewtprintk(ioc, pr_info(MPT3SAS_FMT
@ -3228,9 +3271,16 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
smid_sas_ctrl = mpt3sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx);
if (!smid_sas_ctrl) {
pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
ioc->name, __func__);
return 1;
delayed_sc = kzalloc(sizeof(*delayed_sc), GFP_ATOMIC);
if (!delayed_sc)
return _scsih_check_for_pending_tm(ioc, smid);
INIT_LIST_HEAD(&delayed_sc->list);
delayed_sc->handle = mpi_request_tm->DevHandle;
list_add_tail(&delayed_sc->list, &ioc->delayed_sc_list);
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"DELAYED:sc:handle(0x%04x), (open)\n",
ioc->name, handle));
return _scsih_check_for_pending_tm(ioc, smid);
}
dewtprintk(ioc, pr_info(MPT3SAS_FMT
@ -3281,7 +3331,7 @@ _scsih_sas_control_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
}
return 1;
return mpt3sas_check_for_pending_internal_cmds(ioc, smid);
}
/**
@ -3332,7 +3382,7 @@ _scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
mpi_request->DevHandle = cpu_to_le16(handle);
mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
mpt3sas_base_put_smid_hi_priority(ioc, smid);
mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
}
/**
@ -3388,6 +3438,142 @@ _scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
return _scsih_check_for_pending_tm(ioc, smid);
}
/**
* _scsih_issue_delayed_event_ack - issue delayed Event ACK messages
* @ioc: per adapter object
* @smid: system request message index
* @event: Event ID
* @event_context: used to track events uniquely
*
* Context - processed in interrupt context.
*/
void
_scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 event,
u32 event_context)
{
Mpi2EventAckRequest_t *ack_request;
int i = smid - ioc->internal_smid;
unsigned long flags;
/* Without releasing the smid just update the
* call back index and reuse the same smid for
* processing this delayed request
*/
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
ioc->internal_lookup[i].cb_idx = ioc->base_cb_idx;
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"EVENT ACK: event(0x%04x), smid(%d), cb(%d)\n",
ioc->name, le16_to_cpu(event), smid,
ioc->base_cb_idx));
ack_request = mpt3sas_base_get_msg_frame(ioc, smid);
memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t));
ack_request->Function = MPI2_FUNCTION_EVENT_ACK;
ack_request->Event = event;
ack_request->EventContext = event_context;
ack_request->VF_ID = 0; /* TODO */
ack_request->VP_ID = 0;
mpt3sas_base_put_smid_default(ioc, smid);
}
/**
* _scsih_issue_delayed_sas_io_unit_ctrl - issue delayed
* sas_io_unit_ctrl messages
* @ioc: per adapter object
* @smid: system request message index
* @handle: device handle
*
* Context - processed in interrupt context.
*/
void
_scsih_issue_delayed_sas_io_unit_ctrl(struct MPT3SAS_ADAPTER *ioc,
u16 smid, u16 handle)
{
Mpi2SasIoUnitControlRequest_t *mpi_request;
u32 ioc_state;
int i = smid - ioc->internal_smid;
unsigned long flags;
if (ioc->remove_host) {
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"%s: host has been removed\n",
__func__, ioc->name));
return;
} else if (ioc->pci_error_recovery) {
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"%s: host in pci error recovery\n",
__func__, ioc->name));
return;
}
ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"%s: host is not operational\n",
__func__, ioc->name));
return;
}
/* Without releasing the smid just update the
* call back index and reuse the same smid for
* processing this delayed request
*/
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
ioc->internal_lookup[i].cb_idx = ioc->tm_sas_control_cb_idx;
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"sc_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
ioc->name, le16_to_cpu(handle), smid,
ioc->tm_sas_control_cb_idx));
mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
mpi_request->DevHandle = handle;
mpt3sas_base_put_smid_default(ioc, smid);
}
/**
* _scsih_check_for_pending_internal_cmds - check for pending internal messages
* @ioc: per adapter object
* @smid: system request message index
*
* Context: Executed in interrupt context
*
* This will check delayed internal messages list, and process the
* next request.
*
* Return 1 meaning mf should be freed from _base_interrupt
* 0 means the mf is freed from this function.
*/
u8
mpt3sas_check_for_pending_internal_cmds(struct MPT3SAS_ADAPTER *ioc, u16 smid)
{
struct _sc_list *delayed_sc;
struct _event_ack_list *delayed_event_ack;
if (!list_empty(&ioc->delayed_event_ack_list)) {
delayed_event_ack = list_entry(ioc->delayed_event_ack_list.next,
struct _event_ack_list, list);
_scsih_issue_delayed_event_ack(ioc, smid,
delayed_event_ack->Event, delayed_event_ack->EventContext);
list_del(&delayed_event_ack->list);
kfree(delayed_event_ack);
return 0;
}
if (!list_empty(&ioc->delayed_sc_list)) {
delayed_sc = list_entry(ioc->delayed_sc_list.next,
struct _sc_list, list);
_scsih_issue_delayed_sas_io_unit_ctrl(ioc, smid,
delayed_sc->handle);
list_del(&delayed_sc->list);
kfree(delayed_sc);
return 0;
}
return 1;
}
/**
* _scsih_check_for_pending_tm - check for pending task management
@ -4084,6 +4270,9 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
desc_ioc_state = "eedp app tag error";
break;
case MPI2_IOCSTATUS_INSUFFICIENT_POWER:
desc_ioc_state = "insufficient power";
break;
default:
desc_ioc_state = "unknown";
break;
@ -4609,6 +4798,7 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
case MPI2_IOCSTATUS_INVALID_STATE:
case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
case MPI2_IOCSTATUS_INSUFFICIENT_POWER:
default:
scmd->result = DID_SOFT_ERROR << 16;
break;
@ -8391,7 +8581,8 @@ static struct raid_function_template mpt3sas_raid_functions = {
* @pdev: PCI device struct
*
* return MPI2_VERSION for SAS 2.0 HBA devices,
* MPI25_VERSION for SAS 3.0 HBA devices.
* MPI25_VERSION for SAS 3.0 HBA devices, and
* MPI26 VERSION for Cutlass & Invader SAS 3.0 HBA devices
*/
u16
_scsih_determine_hba_mpi_version(struct pci_dev *pdev)
@ -8423,6 +8614,17 @@ _scsih_determine_hba_mpi_version(struct pci_dev *pdev)
case MPI25_MFGPAGE_DEVID_SAS3108_5:
case MPI25_MFGPAGE_DEVID_SAS3108_6:
return MPI25_VERSION;
case MPI26_MFGPAGE_DEVID_SAS3216:
case MPI26_MFGPAGE_DEVID_SAS3224:
case MPI26_MFGPAGE_DEVID_SAS3316_1:
case MPI26_MFGPAGE_DEVID_SAS3316_2:
case MPI26_MFGPAGE_DEVID_SAS3316_3:
case MPI26_MFGPAGE_DEVID_SAS3316_4:
case MPI26_MFGPAGE_DEVID_SAS3324_1:
case MPI26_MFGPAGE_DEVID_SAS3324_2:
case MPI26_MFGPAGE_DEVID_SAS3324_3:
case MPI26_MFGPAGE_DEVID_SAS3324_4:
return MPI26_VERSION;
}
return 0;
}
@ -8456,7 +8658,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* Enumerate only SAS 3.0 HBA's if hbas_to_enumerate is two,
* for other generation HBA's return with -ENODEV
*/
if ((hbas_to_enumerate == 2) && (hba_mpi_version != MPI25_VERSION))
if ((hbas_to_enumerate == 2) && (!(hba_mpi_version == MPI25_VERSION
|| hba_mpi_version == MPI26_VERSION)))
return -ENODEV;
switch (hba_mpi_version) {
@ -8478,6 +8681,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
break;
case MPI25_VERSION:
case MPI26_VERSION:
/* Use mpt3sas driver host template for SAS 3.0 HBA's */
shost = scsi_host_alloc(&mpt3sas_driver_template,
sizeof(struct MPT3SAS_ADAPTER));
@ -8488,7 +8692,9 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->hba_mpi_version_belonged = hba_mpi_version;
ioc->id = mpt3_ids++;
sprintf(ioc->driver_name, "%s", MPT3SAS_DRIVER_NAME);
if (pdev->revision >= SAS3_PCI_DEVICE_C0_REVISION)
if ((ioc->hba_mpi_version_belonged == MPI25_VERSION &&
pdev->revision >= SAS3_PCI_DEVICE_C0_REVISION) ||
(ioc->hba_mpi_version_belonged == MPI26_VERSION))
ioc->msix96_vector = 1;
break;
default:
@ -8533,6 +8739,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_LIST_HEAD(&ioc->raid_device_list);
INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list);
INIT_LIST_HEAD(&ioc->delayed_tr_list);
INIT_LIST_HEAD(&ioc->delayed_sc_list);
INIT_LIST_HEAD(&ioc->delayed_event_ack_list);
INIT_LIST_HEAD(&ioc->delayed_tr_volume_list);
INIT_LIST_HEAD(&ioc->reply_queue_list);
@ -8866,6 +9074,28 @@ static const struct pci_device_id mpt3sas_pci_table[] = {
PCI_ANY_ID, PCI_ANY_ID },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6,
PCI_ANY_ID, PCI_ANY_ID },
/* Cutlass ~ 3216 and 3224 */
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3216,
PCI_ANY_ID, PCI_ANY_ID },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3224,
PCI_ANY_ID, PCI_ANY_ID },
/* Intruder ~ 3316 and 3324 */
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_1,
PCI_ANY_ID, PCI_ANY_ID },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_2,
PCI_ANY_ID, PCI_ANY_ID },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_3,
PCI_ANY_ID, PCI_ANY_ID },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_4,
PCI_ANY_ID, PCI_ANY_ID },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_1,
PCI_ANY_ID, PCI_ANY_ID },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_2,
PCI_ANY_ID, PCI_ANY_ID },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_3,
PCI_ANY_ID, PCI_ANY_ID },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_4,
PCI_ANY_ID, PCI_ANY_ID },
{0} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, mpt3sas_pci_table);

View File

@ -1418,7 +1418,6 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc,
u32 ioc_state;
unsigned long timeleft;
void *psge;
u32 sgl_flags;
u8 issue_reset = 0;
void *data_out = NULL;
dma_addr_t data_out_dma;
@ -1507,24 +1506,10 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc,
cpu_to_le16(sizeof(struct phy_error_log_request));
psge = &mpi_request->SGL;
/* WRITE sgel first */
sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
ioc->base_add_sg_single(psge, sgl_flags |
sizeof(struct phy_control_request), data_out_dma);
/* incr sgel */
psge += ioc->sge_size;
/* READ sgel last */
sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
MPI2_SGE_FLAGS_END_OF_LIST);
sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
ioc->base_add_sg_single(psge, sgl_flags |
sizeof(struct phy_control_reply), data_out_dma +
sizeof(struct phy_control_request));
ioc->build_sg(ioc, psge, data_out_dma,
sizeof(struct phy_control_request),
data_out_dma + sizeof(struct phy_control_request),
sizeof(struct phy_control_reply));
dtransportprintk(ioc, pr_info(MPT3SAS_FMT
"phy_control - send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n",
@ -1615,7 +1600,7 @@ _transport_phy_reset(struct sas_phy *phy, int hard_reset)
SMP_PHY_CONTROL_LINK_RESET);
/* handle hba phys */
memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
mpi_request.Operation = hard_reset ?
MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;

View File

@ -2629,7 +2629,7 @@ static void mvumi_shutdown(struct pci_dev *pdev)
mvumi_flush_cache(mhba);
}
static int mvumi_suspend(struct pci_dev *pdev, pm_message_t state)
static int __maybe_unused mvumi_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct mvumi_hba *mhba = NULL;
@ -2648,7 +2648,7 @@ static int mvumi_suspend(struct pci_dev *pdev, pm_message_t state)
return 0;
}
static int mvumi_resume(struct pci_dev *pdev)
static int __maybe_unused mvumi_resume(struct pci_dev *pdev)
{
int ret;
struct mvumi_hba *mhba = NULL;

View File

@ -2006,9 +2006,8 @@ EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
*/
void osd_set_caps(struct osd_cdb *cdb, const void *caps)
{
bool is_ver1 = true;
/* NOTE: They start at same address */
memcpy(&cdb->v1.caps, caps, is_ver1 ? OSDv1_CAP_LEN : OSD_CAP_LEN);
memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN);
}
bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms __unused)

View File

@ -37,6 +37,7 @@ typedef struct {
unsigned long recon_tmo; /* How many usecs to wait for reconnection (6th bit) */
unsigned int failed:1; /* Failure flag */
unsigned wanted:1; /* Parport sharing busy flag */
unsigned int dev_no; /* Device number */
wait_queue_head_t *waiting;
struct Scsi_Host *host;
struct list_head list;
@ -985,15 +986,40 @@ static struct scsi_host_template ppa_template = {
static LIST_HEAD(ppa_hosts);
/*
* Finds the first available device number that can be alloted to the
* new ppa device and returns the address of the previous node so that
* we can add to the tail and have a list in the ascending order.
*/
static inline ppa_struct *find_parent(void)
{
ppa_struct *dev, *par = NULL;
unsigned int cnt = 0;
if (list_empty(&ppa_hosts))
return NULL;
list_for_each_entry(dev, &ppa_hosts, list) {
if (dev->dev_no != cnt)
return par;
cnt++;
par = dev;
}
return par;
}
static int __ppa_attach(struct parport *pb)
{
struct Scsi_Host *host;
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waiting);
DEFINE_WAIT(wait);
ppa_struct *dev;
ppa_struct *dev, *temp;
int ports;
int modes, ppb, ppb_hi;
int err = -ENOMEM;
struct pardev_cb ppa_cb;
dev = kzalloc(sizeof(ppa_struct), GFP_KERNEL);
if (!dev)
@ -1002,8 +1028,15 @@ static int __ppa_attach(struct parport *pb)
dev->mode = PPA_AUTODETECT;
dev->recon_tmo = PPA_RECON_TMO;
init_waitqueue_head(&waiting);
dev->dev = parport_register_device(pb, "ppa", NULL, ppa_wakeup,
NULL, 0, dev);
temp = find_parent();
if (temp)
dev->dev_no = temp->dev_no + 1;
memset(&ppa_cb, 0, sizeof(ppa_cb));
ppa_cb.private = dev;
ppa_cb.wakeup = ppa_wakeup;
dev->dev = parport_register_dev_model(pb, "ppa", &ppa_cb, dev->dev_no);
if (!dev->dev)
goto out;
@ -1110,9 +1143,10 @@ static void ppa_detach(struct parport *pb)
}
static struct parport_driver ppa_driver = {
.name = "ppa",
.attach = ppa_attach,
.detach = ppa_detach,
.name = "ppa",
.match_port = ppa_attach,
.detach = ppa_detach,
.devmodel = true,
};
static int __init ppa_driver_init(void)

View File

@ -272,8 +272,8 @@ qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj,
iter = (uint32_t *)buf;
chksum = 0;
for (cnt = 0; cnt < ((count >> 2) - 1); cnt++)
chksum += le32_to_cpu(*iter++);
for (cnt = 0; cnt < ((count >> 2) - 1); cnt++, iter++)
chksum += le32_to_cpu(*iter);
chksum = ~chksum + 1;
*iter = cpu_to_le32(chksum);
} else {
@ -562,6 +562,7 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj,
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
struct qla_hw_data *ha = vha->hw;
uint32_t faddr;
if (unlikely(pci_channel_offline(ha->pdev)))
return -EAGAIN;
@ -569,9 +570,16 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN))
return -EINVAL;
if (IS_NOCACHE_VPD_TYPE(ha))
ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2,
if (IS_NOCACHE_VPD_TYPE(ha)) {
faddr = ha->flt_region_vpd << 2;
if (IS_QLA27XX(ha) &&
qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
faddr = ha->flt_region_vpd_sec << 2;
ha->isp_ops->read_optrom(vha, ha->vpd, faddr,
ha->vpd_size);
}
return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size);
}
@ -1909,7 +1917,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
if (qla2x00_reset_active(vha))
goto done;
stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma);
stats = dma_alloc_coherent(&ha->pdev->dev,
sizeof(struct link_statistics), &stats_dma, GFP_KERNEL);
if (stats == NULL) {
ql_log(ql_log_warn, vha, 0x707d,
"Failed to allocate memory for stats.\n");
@ -1957,7 +1966,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
do_div(pfc_host_stat->seconds_since_last_reset, HZ);
done_free:
dma_pool_free(ha->s_dma_pool, stats, stats_dma);
dma_free_coherent(&ha->pdev->dev, sizeof(struct link_statistics),
stats, stats_dma);
done:
return pfc_host_stat;
}

View File

@ -2106,6 +2106,195 @@ qla8044_serdes_op(struct fc_bsg_job *bsg_job)
return 0;
}
static int
qla27xx_get_flash_upd_cap(struct fc_bsg_job *bsg_job)
{
struct Scsi_Host *host = bsg_job->shost;
scsi_qla_host_t *vha = shost_priv(host);
struct qla_hw_data *ha = vha->hw;
struct qla_flash_update_caps cap;
if (!(IS_QLA27XX(ha)))
return -EPERM;
memset(&cap, 0, sizeof(cap));
cap.capabilities = (uint64_t)ha->fw_attributes_ext[1] << 48 |
(uint64_t)ha->fw_attributes_ext[0] << 32 |
(uint64_t)ha->fw_attributes_h << 16 |
(uint64_t)ha->fw_attributes;
sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
bsg_job->reply_payload.sg_cnt, &cap, sizeof(cap));
bsg_job->reply->reply_payload_rcv_len = sizeof(cap);
bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
EXT_STATUS_OK;
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
bsg_job->reply->result = DID_OK << 16;
bsg_job->job_done(bsg_job);
return 0;
}
static int
qla27xx_set_flash_upd_cap(struct fc_bsg_job *bsg_job)
{
struct Scsi_Host *host = bsg_job->shost;
scsi_qla_host_t *vha = shost_priv(host);
struct qla_hw_data *ha = vha->hw;
uint64_t online_fw_attr = 0;
struct qla_flash_update_caps cap;
if (!(IS_QLA27XX(ha)))
return -EPERM;
memset(&cap, 0, sizeof(cap));
sg_copy_to_buffer(bsg_job->request_payload.sg_list,
bsg_job->request_payload.sg_cnt, &cap, sizeof(cap));
online_fw_attr = (uint64_t)ha->fw_attributes_ext[1] << 48 |
(uint64_t)ha->fw_attributes_ext[0] << 32 |
(uint64_t)ha->fw_attributes_h << 16 |
(uint64_t)ha->fw_attributes;
if (online_fw_attr != cap.capabilities) {
bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
EXT_STATUS_INVALID_PARAM;
return -EINVAL;
}
if (cap.outage_duration < MAX_LOOP_TIMEOUT) {
bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
EXT_STATUS_INVALID_PARAM;
return -EINVAL;
}
bsg_job->reply->reply_payload_rcv_len = 0;
bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
EXT_STATUS_OK;
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
bsg_job->reply->result = DID_OK << 16;
bsg_job->job_done(bsg_job);
return 0;
}
static int
qla27xx_get_bbcr_data(struct fc_bsg_job *bsg_job)
{
struct Scsi_Host *host = bsg_job->shost;
scsi_qla_host_t *vha = shost_priv(host);
struct qla_hw_data *ha = vha->hw;
struct qla_bbcr_data bbcr;
uint16_t loop_id, topo, sw_cap;
uint8_t domain, area, al_pa, state;
int rval;
if (!(IS_QLA27XX(ha)))
return -EPERM;
memset(&bbcr, 0, sizeof(bbcr));
if (vha->flags.bbcr_enable)
bbcr.status = QLA_BBCR_STATUS_ENABLED;
else
bbcr.status = QLA_BBCR_STATUS_DISABLED;
if (bbcr.status == QLA_BBCR_STATUS_ENABLED) {
rval = qla2x00_get_adapter_id(vha, &loop_id, &al_pa,
&area, &domain, &topo, &sw_cap);
if (rval != QLA_SUCCESS) {
bbcr.status = QLA_BBCR_STATUS_UNKNOWN;
bbcr.state = QLA_BBCR_STATE_OFFLINE;
bbcr.mbx1 = loop_id;
goto done;
}
state = (vha->bbcr >> 12) & 0x1;
if (state) {
bbcr.state = QLA_BBCR_STATE_OFFLINE;
bbcr.offline_reason_code = QLA_BBCR_REASON_LOGIN_REJECT;
} else {
bbcr.state = QLA_BBCR_STATE_ONLINE;
bbcr.negotiated_bbscn = (vha->bbcr >> 8) & 0xf;
}
bbcr.configured_bbscn = vha->bbcr & 0xf;
}
done:
sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
bsg_job->reply_payload.sg_cnt, &bbcr, sizeof(bbcr));
bsg_job->reply->reply_payload_rcv_len = sizeof(bbcr);
bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
bsg_job->reply->result = DID_OK << 16;
bsg_job->job_done(bsg_job);
return 0;
}
static int
qla2x00_get_priv_stats(struct fc_bsg_job *bsg_job)
{
struct Scsi_Host *host = bsg_job->shost;
scsi_qla_host_t *vha = shost_priv(host);
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
struct link_statistics *stats = NULL;
dma_addr_t stats_dma;
int rval = QLA_FUNCTION_FAILED;
if (test_bit(UNLOADING, &vha->dpc_flags))
goto done;
if (unlikely(pci_channel_offline(ha->pdev)))
goto done;
if (qla2x00_reset_active(vha))
goto done;
if (!IS_FWI2_CAPABLE(ha))
goto done;
stats = dma_alloc_coherent(&ha->pdev->dev,
sizeof(struct link_statistics), &stats_dma, GFP_KERNEL);
if (!stats) {
ql_log(ql_log_warn, vha, 0x70e2,
"Failed to allocate memory for stats.\n");
goto done;
}
memset(stats, 0, sizeof(struct link_statistics));
rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma);
if (rval != QLA_SUCCESS)
goto done_free;
ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e3,
(uint8_t *)stats, sizeof(struct link_statistics));
sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
bsg_job->reply_payload.sg_cnt, stats, sizeof(struct link_statistics));
bsg_job->reply->reply_payload_rcv_len = sizeof(struct link_statistics);
bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
bsg_job->reply->result = DID_OK << 16;
bsg_job->job_done(bsg_job);
done_free:
dma_free_coherent(&ha->pdev->dev, sizeof(struct link_statistics),
stats, stats_dma);
done:
return rval;
}
static int
qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
{
@ -2161,6 +2350,18 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
case QL_VND_SERDES_OP_EX:
return qla8044_serdes_op(bsg_job);
case QL_VND_GET_FLASH_UPDATE_CAPS:
return qla27xx_get_flash_upd_cap(bsg_job);
case QL_VND_SET_FLASH_UPDATE_CAPS:
return qla27xx_set_flash_upd_cap(bsg_job);
case QL_VND_GET_BBCR_DATA:
return qla27xx_get_bbcr_data(bsg_job);
case QL_VND_GET_PRIV_STATS:
return qla2x00_get_priv_stats(bsg_job);
default:
return -ENOSYS;
}

View File

@ -25,6 +25,10 @@
#define QL_VND_FX00_MGMT_CMD 0x12
#define QL_VND_SERDES_OP 0x13
#define QL_VND_SERDES_OP_EX 0x14
#define QL_VND_GET_FLASH_UPDATE_CAPS 0x15
#define QL_VND_SET_FLASH_UPDATE_CAPS 0x16
#define QL_VND_GET_BBCR_DATA 0x17
#define QL_VND_GET_PRIV_STATS 0x18
/* BSG Vendor specific subcode returns */
#define EXT_STATUS_OK 0
@ -232,4 +236,34 @@ struct qla_serdes_reg_ex {
uint32_t val;
} __packed;
struct qla_flash_update_caps {
uint64_t capabilities;
uint32_t outage_duration;
uint8_t reserved[20];
} __packed;
/* BB_CR Status */
#define QLA_BBCR_STATUS_DISABLED 0
#define QLA_BBCR_STATUS_ENABLED 1
#define QLA_BBCR_STATUS_UNKNOWN 2
/* BB_CR State */
#define QLA_BBCR_STATE_OFFLINE 0
#define QLA_BBCR_STATE_ONLINE 1
/* BB_CR Offline Reason Code */
#define QLA_BBCR_REASON_PORT_SPEED 1
#define QLA_BBCR_REASON_PEER_PORT 2
#define QLA_BBCR_REASON_SWITCH 3
#define QLA_BBCR_REASON_LOGIN_REJECT 4
struct qla_bbcr_data {
uint8_t status; /* 1 - enabled, 0 - Disabled */
uint8_t state; /* 1 - online, 0 - offline */
uint8_t configured_bbscn; /* 0-15 */
uint8_t negotiated_bbscn; /* 0-15 */
uint8_t offline_reason_code;
uint16_t mbx1; /* Port state */
uint8_t reserved[9];
} __packed;
#endif

View File

@ -11,7 +11,7 @@
* ----------------------------------------------------------------------
* | Level | Last Value Used | Holes |
* ----------------------------------------------------------------------
* | Module Init and Probe | 0x017f | 0x0146 |
* | Module Init and Probe | 0x018f | 0x0146 |
* | | | 0x015b-0x0160 |
* | | | 0x016e-0x0170 |
* | Mailbox commands | 0x1192 | |
@ -27,11 +27,12 @@
* | | | 0x303a |
* | DPC Thread | 0x4023 | 0x4002,0x4013 |
* | Async Events | 0x5089 | 0x502b-0x502f |
* | | | 0x505e |
* | | | 0x5084,0x5075 |
* | | | 0x503d,0x5044 |
* | | | 0x507b,0x505f |
* | Timer Routines | 0x6012 | |
* | User Space Interactions | 0x70e65 | 0x7018,0x702e |
* | User Space Interactions | 0x70e3 | 0x7018,0x702e |
* | | | 0x7020,0x7024 |
* | | | 0x7039,0x7045 |
* | | | 0x7073-0x7075 |
@ -293,8 +294,8 @@ qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase,
WRT_REG_DWORD(&reg->iobase_addr, iobase);
dmp_reg = &reg->iobase_window;
while (count--)
*buf++ = htonl(RD_REG_DWORD(dmp_reg++));
for ( ; count--; dmp_reg++)
*buf++ = htonl(RD_REG_DWORD(dmp_reg));
return buf;
}
@ -456,8 +457,8 @@ qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count,
{
uint16_t __iomem *dmp_reg = &reg->u.isp2300.fb_cmd;
while (count--)
*buf++ = htons(RD_REG_WORD(dmp_reg++));
for ( ; count--; dmp_reg++)
*buf++ = htons(RD_REG_WORD(dmp_reg));
}
static inline void *
@ -732,16 +733,18 @@ qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
if (rval == QLA_SUCCESS) {
dmp_reg = &reg->flash_address;
for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++, dmp_reg++)
fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
dmp_reg = &reg->u.isp2300.req_q_in;
for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++)
fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2;
cnt++, dmp_reg++)
fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
dmp_reg = &reg->u.isp2300.mailbox0;
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2;
cnt++, dmp_reg++)
fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
WRT_REG_WORD(&reg->ctrl_status, 0x40);
qla2xxx_read_window(reg, 32, fw->resp_dma_reg);
@ -751,8 +754,9 @@ qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
WRT_REG_WORD(&reg->ctrl_status, 0x00);
dmp_reg = &reg->risc_hw;
for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2;
cnt++, dmp_reg++)
fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
WRT_REG_WORD(&reg->pcr, 0x2000);
qla2xxx_read_window(reg, 16, fw->risc_gp0_reg);
@ -895,25 +899,25 @@ qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
}
if (rval == QLA_SUCCESS) {
dmp_reg = &reg->flash_address;
for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++, dmp_reg++)
fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
dmp_reg = &reg->u.isp2100.mailbox0;
for (cnt = 0; cnt < ha->mbx_count; cnt++) {
for (cnt = 0; cnt < ha->mbx_count; cnt++, dmp_reg++) {
if (cnt == 8)
dmp_reg = &reg->u_end.isp2200.mailbox8;
fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
}
dmp_reg = &reg->u.isp2100.unused_2[0];
for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++)
fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++, dmp_reg++)
fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
WRT_REG_WORD(&reg->ctrl_status, 0x00);
dmp_reg = &reg->risc_hw;
for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++, dmp_reg++)
fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
WRT_REG_WORD(&reg->pcr, 0x2000);
qla2xxx_read_window(reg, 16, fw->risc_gp0_reg);
@ -1095,8 +1099,8 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
/* Host interface registers. */
dmp_reg = &reg->flash_addr;
for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++)
fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg));
/* Disable interrupts. */
WRT_REG_DWORD(&reg->ictrl, 0);
@ -1128,8 +1132,8 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
/* Mailbox registers. */
mbx_reg = &reg->mailbox0;
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, dmp_reg++)
fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg));
/* Transfer sequence registers. */
iter_reg = fw->xseq_gp_reg;
@ -1167,20 +1171,20 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
iter_reg = fw->req0_dma_reg;
iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
dmp_reg = &reg->iobase_q;
for (cnt = 0; cnt < 7; cnt++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
iter_reg = fw->resp0_dma_reg;
iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
dmp_reg = &reg->iobase_q;
for (cnt = 0; cnt < 7; cnt++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
iter_reg = fw->req1_dma_reg;
iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
dmp_reg = &reg->iobase_q;
for (cnt = 0; cnt < 7; cnt++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
/* Transmit DMA registers. */
iter_reg = fw->xmt0_dma_reg;
@ -1358,8 +1362,10 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
RD_REG_DWORD(&reg->iobase_addr);
WRT_REG_DWORD(&reg->iobase_window, 0x01);
dmp_reg = &reg->iobase_c4;
fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++));
fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++));
fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg));
dmp_reg++;
fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg));
dmp_reg++;
fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg));
fw->pcie_regs[3] = htonl(RD_REG_DWORD(&reg->iobase_window));
@ -1368,8 +1374,8 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
/* Host interface registers. */
dmp_reg = &reg->flash_addr;
for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++)
fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg));
/* Disable interrupts. */
WRT_REG_DWORD(&reg->ictrl, 0);
@ -1417,8 +1423,8 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
/* Mailbox registers. */
mbx_reg = &reg->mailbox0;
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++)
fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg));
/* Transfer sequence registers. */
iter_reg = fw->xseq_gp_reg;
@ -1481,20 +1487,20 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
iter_reg = fw->req0_dma_reg;
iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
dmp_reg = &reg->iobase_q;
for (cnt = 0; cnt < 7; cnt++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
iter_reg = fw->resp0_dma_reg;
iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
dmp_reg = &reg->iobase_q;
for (cnt = 0; cnt < 7; cnt++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
iter_reg = fw->req1_dma_reg;
iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
dmp_reg = &reg->iobase_q;
for (cnt = 0; cnt < 7; cnt++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
/* Transmit DMA registers. */
iter_reg = fw->xmt0_dma_reg;
@ -1679,8 +1685,10 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
RD_REG_DWORD(&reg->iobase_addr);
WRT_REG_DWORD(&reg->iobase_window, 0x01);
dmp_reg = &reg->iobase_c4;
fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++));
fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++));
fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg));
dmp_reg++;
fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg));
dmp_reg++;
fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg));
fw->pcie_regs[3] = htonl(RD_REG_DWORD(&reg->iobase_window));
@ -1689,8 +1697,8 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
/* Host interface registers. */
dmp_reg = &reg->flash_addr;
for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++)
fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg));
/* Disable interrupts. */
WRT_REG_DWORD(&reg->ictrl, 0);
@ -1738,8 +1746,8 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
/* Mailbox registers. */
mbx_reg = &reg->mailbox0;
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++)
fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg));
/* Transfer sequence registers. */
iter_reg = fw->xseq_gp_reg;
@ -1802,20 +1810,20 @@ qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
iter_reg = fw->req0_dma_reg;
iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
dmp_reg = &reg->iobase_q;
for (cnt = 0; cnt < 7; cnt++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
iter_reg = fw->resp0_dma_reg;
iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
dmp_reg = &reg->iobase_q;
for (cnt = 0; cnt < 7; cnt++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
iter_reg = fw->req1_dma_reg;
iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
dmp_reg = &reg->iobase_q;
for (cnt = 0; cnt < 7; cnt++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
/* Transmit DMA registers. */
iter_reg = fw->xmt0_dma_reg;
@ -2022,8 +2030,10 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
RD_REG_DWORD(&reg->iobase_addr);
WRT_REG_DWORD(&reg->iobase_window, 0x01);
dmp_reg = &reg->iobase_c4;
fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++));
fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++));
fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg));
dmp_reg++;
fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg));
dmp_reg++;
fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg));
fw->pcie_regs[3] = htonl(RD_REG_DWORD(&reg->iobase_window));
@ -2032,8 +2042,8 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
/* Host interface registers. */
dmp_reg = &reg->flash_addr;
for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++)
fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg));
/* Disable interrupts. */
WRT_REG_DWORD(&reg->ictrl, 0);
@ -2081,8 +2091,8 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
/* Mailbox registers. */
mbx_reg = &reg->mailbox0;
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, dmp_reg++)
fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg));
/* Transfer sequence registers. */
iter_reg = fw->xseq_gp_reg;
@ -2177,20 +2187,20 @@ qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
iter_reg = fw->req0_dma_reg;
iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
dmp_reg = &reg->iobase_q;
for (cnt = 0; cnt < 7; cnt++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
iter_reg = fw->resp0_dma_reg;
iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
dmp_reg = &reg->iobase_q;
for (cnt = 0; cnt < 7; cnt++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
iter_reg = fw->req1_dma_reg;
iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
dmp_reg = &reg->iobase_q;
for (cnt = 0; cnt < 7; cnt++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
/* Transmit DMA registers. */
iter_reg = fw->xmt0_dma_reg;

View File

@ -1060,6 +1060,12 @@ struct mbx_cmd_32 {
#define FSTATE_FATAL_ERROR 4
#define FSTATE_LOOP_BACK_CONN 5
#define QLA27XX_IMG_STATUS_VER_MAJOR 0x01
#define QLA27XX_IMG_STATUS_VER_MINOR 0x00
#define QLA27XX_IMG_STATUS_SIGN 0xFACEFADE
#define QLA27XX_PRIMARY_IMAGE 1
#define QLA27XX_SECONDARY_IMAGE 2
/*
* Port Database structure definition
* Little endian except where noted.
@ -1248,13 +1254,41 @@ struct link_statistics {
uint32_t inval_xmit_word_cnt;
uint32_t inval_crc_cnt;
uint32_t lip_cnt;
uint32_t unused1[0x1a];
uint32_t link_up_cnt;
uint32_t link_down_loop_init_tmo;
uint32_t link_down_los;
uint32_t link_down_loss_rcv_clk;
uint32_t reserved0[5];
uint32_t port_cfg_chg;
uint32_t reserved1[11];
uint32_t rsp_q_full;
uint32_t atio_q_full;
uint32_t drop_ae;
uint32_t els_proto_err;
uint32_t reserved2;
uint32_t tx_frames;
uint32_t rx_frames;
uint32_t discarded_frames;
uint32_t dropped_frames;
uint32_t unused2[1];
uint32_t reserved3;
uint32_t nos_rcvd;
uint32_t reserved4[4];
uint32_t tx_prjt;
uint32_t rcv_exfail;
uint32_t rcv_abts;
uint32_t seq_frm_miss;
uint32_t corr_err;
uint32_t mb_rqst;
uint32_t nport_full;
uint32_t eofa;
uint32_t reserved5;
uint32_t fpm_recv_word_cnt_lo;
uint32_t fpm_recv_word_cnt_hi;
uint32_t fpm_disc_word_cnt_lo;
uint32_t fpm_disc_word_cnt_hi;
uint32_t fpm_xmit_word_cnt_lo;
uint32_t fpm_xmit_word_cnt_hi;
uint32_t reserved6[70];
};
/*
@ -3433,14 +3467,20 @@ struct qla_hw_data {
uint32_t flt_region_flt;
uint32_t flt_region_fdt;
uint32_t flt_region_boot;
uint32_t flt_region_boot_sec;
uint32_t flt_region_fw;
uint32_t flt_region_fw_sec;
uint32_t flt_region_vpd_nvram;
uint32_t flt_region_vpd;
uint32_t flt_region_vpd_sec;
uint32_t flt_region_nvram;
uint32_t flt_region_npiv_conf;
uint32_t flt_region_gold_fw;
uint32_t flt_region_fcp_prio;
uint32_t flt_region_bootload;
uint32_t flt_region_img_status_pri;
uint32_t flt_region_img_status_sec;
uint8_t active_image;
/* Needed for BEACON */
uint16_t beacon_blink_led;
@ -3571,6 +3611,7 @@ typedef struct scsi_qla_host {
uint32_t delete_progress:1;
uint32_t fw_tgt_reported:1;
uint32_t bbcr_enable:1;
} flags;
atomic_t loop_state;
@ -3703,8 +3744,19 @@ typedef struct scsi_qla_host {
atomic_t vref_count;
struct qla8044_reset_template reset_tmplt;
struct qla_tgt_counters tgt_counters;
uint16_t bbcr;
} scsi_qla_host_t;
struct qla27xx_image_status {
uint8_t image_status_mask;
uint16_t generation_number;
uint8_t reserved[3];
uint8_t ver_minor;
uint8_t ver_major;
uint32_t checksum;
uint32_t signature;
} __packed;
#define SET_VP_IDX 1
#define SET_AL_PA 2
#define RESET_VP_IDX 3

View File

@ -1288,7 +1288,9 @@ struct vp_rpt_id_entry_24xx {
uint8_t vp_idx_map[16];
uint8_t reserved_4[32];
uint8_t reserved_4[28];
uint16_t bbcr;
uint8_t reserved_5[6];
};
#define VF_EVFP_IOCB_TYPE 0x26 /* Exchange Virtual Fabric Parameters entry. */
@ -1393,6 +1395,16 @@ struct qla_flt_header {
#define FLT_REG_FCOE_NVRAM_0 0xAA
#define FLT_REG_FCOE_NVRAM_1 0xAC
/* 27xx */
#define FLT_REG_IMG_PRI_27XX 0x95
#define FLT_REG_IMG_SEC_27XX 0x96
#define FLT_REG_FW_SEC_27XX 0x02
#define FLT_REG_BOOTLOAD_SEC_27XX 0x9
#define FLT_REG_VPD_SEC_27XX_0 0x50
#define FLT_REG_VPD_SEC_27XX_1 0x52
#define FLT_REG_VPD_SEC_27XX_2 0xD8
#define FLT_REG_VPD_SEC_27XX_3 0xDA
struct qla_flt_region {
uint32_t code;
uint32_t size;

View File

@ -90,6 +90,7 @@ extern int qla2xxx_mctp_dump(scsi_qla_host_t *);
extern int
qla2x00_alloc_outstanding_cmds(struct qla_hw_data *, struct req_que *);
extern int qla2x00_init_rings(scsi_qla_host_t *);
extern uint8_t qla27xx_find_valid_image(struct scsi_qla_host *);
/*
* Global Data in qla_os.c source file.
@ -121,6 +122,7 @@ extern int ql2xmdcapmask;
extern int ql2xmdenable;
extern int ql2xexlogins;
extern int ql2xexchoffld;
extern int ql2xfwholdabts;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);

View File

@ -157,8 +157,12 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
lio->u.logio.flags |= SRB_LOGIN_RETRIED;
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS)
if (rval != QLA_SUCCESS) {
fcport->flags &= ~FCF_ASYNC_SENT;
fcport->flags |= FCF_LOGIN_NEEDED;
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
goto done_free_sp;
}
ql_dbg(ql_dbg_disc, vha, 0x2072,
"Async-login - hdl=%x, loopid=%x portid=%02x%02x%02x "
@ -2062,6 +2066,10 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
if (IS_P3P_TYPE(ha))
return;
/* Hold status IOCBs until ABTS response received. */
if (ql2xfwholdabts)
ha->fw_options[3] |= BIT_12;
/* Update Serial Link options. */
if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)
return;
@ -2844,7 +2852,6 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
if (nv->login_timeout < 4)
nv->login_timeout = 4;
ha->login_timeout = nv->login_timeout;
icb->login_timeout = nv->login_timeout;
/* Set minimum RATOV to 100 tenths of a second. */
ha->r_a_tov = 100;
@ -5122,8 +5129,8 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
dptr = (uint32_t *)nv;
ha->isp_ops->read_nvram(vha, (uint8_t *)dptr, ha->nvram_base,
ha->nvram_size);
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++)
chksum += le32_to_cpu(*dptr++);
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++)
chksum += le32_to_cpu(*dptr);
ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x006a,
"Contents of NVRAM\n");
@ -5274,7 +5281,6 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
if (le16_to_cpu(nv->login_timeout) < 4)
nv->login_timeout = cpu_to_le16(4);
ha->login_timeout = le16_to_cpu(nv->login_timeout);
icb->login_timeout = nv->login_timeout;
/* Set minimum RATOV to 100 tenths of a second. */
ha->r_a_tov = 100;
@ -5346,6 +5352,93 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
return (rval);
}
uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha)
{
struct qla27xx_image_status pri_image_status, sec_image_status;
uint8_t valid_pri_image, valid_sec_image;
uint32_t *wptr;
uint32_t cnt, chksum, size;
struct qla_hw_data *ha = vha->hw;
valid_pri_image = valid_sec_image = 1;
ha->active_image = 0;
size = sizeof(struct qla27xx_image_status) / sizeof(uint32_t);
if (!ha->flt_region_img_status_pri) {
valid_pri_image = 0;
goto check_sec_image;
}
qla24xx_read_flash_data(vha, (uint32_t *)(&pri_image_status),
ha->flt_region_img_status_pri, size);
if (pri_image_status.signature != QLA27XX_IMG_STATUS_SIGN) {
ql_dbg(ql_dbg_init, vha, 0x018b,
"Primary image signature (0x%x) not valid\n",
pri_image_status.signature);
valid_pri_image = 0;
goto check_sec_image;
}
wptr = (uint32_t *)(&pri_image_status);
cnt = size;
for (chksum = 0; cnt--; wptr++)
chksum += le32_to_cpu(*wptr);
if (chksum) {
ql_dbg(ql_dbg_init, vha, 0x018c,
"Checksum validation failed for primary image (0x%x)\n",
chksum);
valid_pri_image = 0;
}
check_sec_image:
if (!ha->flt_region_img_status_sec) {
valid_sec_image = 0;
goto check_valid_image;
}
qla24xx_read_flash_data(vha, (uint32_t *)(&sec_image_status),
ha->flt_region_img_status_sec, size);
if (sec_image_status.signature != QLA27XX_IMG_STATUS_SIGN) {
ql_dbg(ql_dbg_init, vha, 0x018d,
"Secondary image signature(0x%x) not valid\n",
sec_image_status.signature);
valid_sec_image = 0;
goto check_valid_image;
}
wptr = (uint32_t *)(&sec_image_status);
cnt = size;
for (chksum = 0; cnt--; wptr++)
chksum += le32_to_cpu(*wptr);
if (chksum) {
ql_dbg(ql_dbg_init, vha, 0x018e,
"Checksum validation failed for secondary image (0x%x)\n",
chksum);
valid_sec_image = 0;
}
check_valid_image:
if (valid_pri_image && (pri_image_status.image_status_mask & 0x1))
ha->active_image = QLA27XX_PRIMARY_IMAGE;
if (valid_sec_image && (sec_image_status.image_status_mask & 0x1)) {
if (!ha->active_image ||
pri_image_status.generation_number <
sec_image_status.generation_number)
ha->active_image = QLA27XX_SECONDARY_IMAGE;
}
ql_dbg(ql_dbg_init, vha, 0x018f, "%s image\n",
ha->active_image == 0 ? "default bootld and fw" :
ha->active_image == 1 ? "primary" :
ha->active_image == 2 ? "secondary" :
"Invalid");
return ha->active_image;
}
static int
qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
uint32_t faddr)
@ -5368,6 +5461,10 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
dcode = (uint32_t *)req->ring;
*srisc_addr = 0;
if (IS_QLA27XX(ha) &&
qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
faddr = ha->flt_region_fw_sec;
/* Validate firmware image by checking version. */
qla24xx_read_flash_data(vha, dcode, faddr + 4, 4);
for (i = 0; i < 4; i++)
@ -6068,8 +6165,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2,
ha->nvram_size);
dptr = (uint32_t *)nv;
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++)
chksum += le32_to_cpu(*dptr++);
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++)
chksum += le32_to_cpu(*dptr);
ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0111,
"Contents of NVRAM:\n");
@ -6231,7 +6328,6 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
if (le16_to_cpu(nv->login_timeout) < 4)
nv->login_timeout = cpu_to_le16(4);
ha->login_timeout = le16_to_cpu(nv->login_timeout);
icb->login_timeout = nv->login_timeout;
/* Set minimum RATOV to 100 tenths of a second. */
ha->r_a_tov = 100;
@ -6413,12 +6509,17 @@ qla81xx_update_fw_options(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
/* Hold status IOCBs until ABTS response received. */
if (ql2xfwholdabts)
ha->fw_options[3] |= BIT_12;
if (!ql2xetsenable)
return;
goto out;
/* Enable ETS Burst. */
memset(ha->fw_options, 0, sizeof(ha->fw_options));
ha->fw_options[2] |= BIT_9;
out:
qla2x00_set_fw_options(vha, ha->fw_options);
}

View File

@ -87,8 +87,8 @@ host_to_adap(uint8_t *src, uint8_t *dst, uint32_t bsize)
__le32 *odest = (__le32 *) dst;
uint32_t iter = bsize >> 2;
for (; iter ; iter--)
*odest++ = cpu_to_le32(*isrc++);
for ( ; iter--; isrc++)
*odest++ = cpu_to_le32(*isrc);
}
static inline void

View File

@ -934,10 +934,6 @@ skip_rio:
break;
global_port_update:
/* Port unavailable. */
ql_log(ql_log_warn, vha, 0x505e,
"Link is offline.\n");
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
atomic_set(&vha->loop_state, LOOP_DOWN);
atomic_set(&vha->loop_down_timer,

View File

@ -1349,6 +1349,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
if (IS_FWI2_CAPABLE(vha->hw))
mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16;
if (IS_QLA27XX(vha->hw))
mcp->in_mb |= MBX_15;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
@ -1400,6 +1402,9 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
wwn_to_u64(vha->port_name));
}
}
if (IS_QLA27XX(vha->hw))
vha->bbcr = mcp->mb[15];
}
return rval;
@ -2754,7 +2759,7 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
uint32_t *siter, *diter, dwords;
uint32_t *iter, dwords;
struct qla_hw_data *ha = vha->hw;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1084,
@ -2794,10 +2799,11 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
/* Copy over data -- firmware data is LE. */
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1086,
"Done %s.\n", __func__);
dwords = offsetof(struct link_statistics, unused1) / 4;
siter = diter = &stats->link_fail_cnt;
while (dwords--)
*diter++ = le32_to_cpu(*siter++);
dwords = offsetof(struct link_statistics,
link_up_cnt) / 4;
iter = &stats->link_fail_cnt;
for ( ; dwords--; iter++)
le32_to_cpus(iter);
}
} else {
/* Failed. */
@ -2814,7 +2820,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
uint32_t *siter, *diter, dwords;
uint32_t *iter, dwords;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1088,
"Entered %s.\n", __func__);
@ -2843,9 +2849,9 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
"Done %s.\n", __func__);
/* Copy over data -- firmware data is LE. */
dwords = sizeof(struct link_statistics) / 4;
siter = diter = &stats->link_fail_cnt;
while (dwords--)
*diter++ = le32_to_cpu(*siter++);
iter = &stats->link_fail_cnt;
for ( ; dwords--; iter++)
le32_to_cpus(iter);
}
} else {
/* Failed. */
@ -3612,6 +3618,9 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
rptid_entry->port_id[2], rptid_entry->port_id[1],
rptid_entry->port_id[0]);
/* buffer to buffer credit flag */
vha->flags.bbcr_enable = (rptid_entry->bbcr & 0xf) != 0;
/* FA-WWN is only for physical port */
if (!vp_idx) {
void *wwpn = ha->init_cb->port_name;

View File

@ -233,6 +233,13 @@ MODULE_PARM_DESC(ql2xexchoffld,
"Number of exchanges to offload. "
"0 (Default)- Disabled.");
int ql2xfwholdabts = 0;
module_param(ql2xfwholdabts, int, S_IRUGO);
MODULE_PARM_DESC(ql2xfwholdabts,
"Allow FW to hold status IOCB until ABTS rsp received. "
"0 (Default) Do not set fw option. "
"1 - Set fw option to hold ABTS.");
/*
* SCSI host template entry points
*/
@ -2216,6 +2223,7 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
ha->device_type |= DT_ZIO_SUPPORTED;
ha->device_type |= DT_FWI2;
ha->device_type |= DT_IIDMA;
ha->device_type |= DT_T10_PI;
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
break;
case PCI_DEVICE_ID_QLOGIC_ISP2271:
@ -2223,6 +2231,7 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
ha->device_type |= DT_ZIO_SUPPORTED;
ha->device_type |= DT_FWI2;
ha->device_type |= DT_IIDMA;
ha->device_type |= DT_T10_PI;
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
break;
case PCI_DEVICE_ID_QLOGIC_ISP2261:
@ -2230,6 +2239,7 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
ha->device_type |= DT_ZIO_SUPPORTED;
ha->device_type |= DT_FWI2;
ha->device_type |= DT_IIDMA;
ha->device_type |= DT_T10_PI;
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
break;
}

View File

@ -610,8 +610,8 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start)
wptr = (uint16_t *)req->ring;
cnt = sizeof(struct qla_flt_location) >> 1;
for (chksum = 0; cnt; cnt--)
chksum += le16_to_cpu(*wptr++);
for (chksum = 0; cnt--; wptr++)
chksum += le16_to_cpu(*wptr);
if (chksum) {
ql_log(ql_log_fatal, vha, 0x0045,
"Inconsistent FLTL detected: checksum=0x%x.\n", chksum);
@ -702,8 +702,8 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
}
cnt = (sizeof(struct qla_flt_header) + le16_to_cpu(flt->length)) >> 1;
for (chksum = 0; cnt; cnt--)
chksum += le16_to_cpu(*wptr++);
for (chksum = 0; cnt--; wptr++)
chksum += le16_to_cpu(*wptr);
if (chksum) {
ql_log(ql_log_fatal, vha, 0x0048,
"Inconsistent FLT detected: version=0x%x length=0x%x checksum=0x%x.\n",
@ -846,6 +846,38 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
if (ha->port_no == 1)
ha->flt_region_nvram = start;
break;
case FLT_REG_IMG_PRI_27XX:
if (IS_QLA27XX(ha))
ha->flt_region_img_status_pri = start;
break;
case FLT_REG_IMG_SEC_27XX:
if (IS_QLA27XX(ha))
ha->flt_region_img_status_sec = start;
break;
case FLT_REG_FW_SEC_27XX:
if (IS_QLA27XX(ha))
ha->flt_region_fw_sec = start;
break;
case FLT_REG_BOOTLOAD_SEC_27XX:
if (IS_QLA27XX(ha))
ha->flt_region_boot_sec = start;
break;
case FLT_REG_VPD_SEC_27XX_0:
if (IS_QLA27XX(ha))
ha->flt_region_vpd_sec = start;
break;
case FLT_REG_VPD_SEC_27XX_1:
if (IS_QLA27XX(ha))
ha->flt_region_vpd_sec = start;
break;
case FLT_REG_VPD_SEC_27XX_2:
if (IS_QLA27XX(ha))
ha->flt_region_vpd_sec = start;
break;
case FLT_REG_VPD_SEC_27XX_3:
if (IS_QLA27XX(ha))
ha->flt_region_vpd_sec = start;
break;
}
}
goto done;
@ -898,9 +930,8 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha)
fdt->sig[3] != 'D')
goto no_flash_data;
for (cnt = 0, chksum = 0; cnt < sizeof(struct qla_fdt_layout) >> 1;
cnt++)
chksum += le16_to_cpu(*wptr++);
for (cnt = 0, chksum = 0; cnt < sizeof(*fdt) >> 1; cnt++, wptr++)
chksum += le16_to_cpu(*wptr);
if (chksum) {
ql_dbg(ql_dbg_init, vha, 0x004c,
"Inconsistent FDT detected:"
@ -995,7 +1026,8 @@ qla2xxx_get_idc_param(scsi_qla_host_t *vha)
ha->fcoe_dev_init_timeout = QLA82XX_ROM_DEV_INIT_TIMEOUT;
ha->fcoe_reset_timeout = QLA82XX_ROM_DRV_RESET_ACK_TIMEOUT;
} else {
ha->fcoe_dev_init_timeout = le32_to_cpu(*wptr++);
ha->fcoe_dev_init_timeout = le32_to_cpu(*wptr);
wptr++;
ha->fcoe_reset_timeout = le32_to_cpu(*wptr);
}
ql_dbg(ql_dbg_init, vha, 0x004e,
@ -1072,10 +1104,9 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
ha->isp_ops->read_optrom(vha, (uint8_t *)data,
ha->flt_region_npiv_conf << 2, NPIV_CONFIG_SIZE);
cnt = (sizeof(struct qla_npiv_header) + le16_to_cpu(hdr.entries) *
sizeof(struct qla_npiv_entry)) >> 1;
for (wptr = data, chksum = 0; cnt; cnt--)
chksum += le16_to_cpu(*wptr++);
cnt = (sizeof(hdr) + le16_to_cpu(hdr.entries) * sizeof(*entry)) >> 1;
for (wptr = data, chksum = 0; cnt--; wptr++)
chksum += le16_to_cpu(*wptr);
if (chksum) {
ql_dbg(ql_dbg_user, vha, 0x7092,
"Inconsistent NPIV-Config "
@ -2989,6 +3020,9 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
uint8_t code_type, last_image;
int i;
struct qla_hw_data *ha = vha->hw;
uint32_t faddr = 0;
pcihdr = pcids = 0;
if (IS_P3P_TYPE(ha))
return ret;
@ -3002,9 +3036,11 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
dcode = mbuf;
/* Begin with first PCI expansion ROM header. */
pcihdr = ha->flt_region_boot << 2;
if (IS_QLA27XX(ha) &&
qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
pcihdr = ha->flt_region_boot_sec << 2;
last_image = 1;
do {
/* Verify PCI expansion ROM header. */
@ -3077,8 +3113,12 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
/* Read firmware image information. */
memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
dcode = mbuf;
faddr = ha->flt_region_fw;
if (IS_QLA27XX(ha) &&
qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
faddr = ha->flt_region_fw_sec;
qla24xx_read_flash_data(vha, dcode, ha->flt_region_fw + 4, 4);
qla24xx_read_flash_data(vha, dcode, faddr + 4, 4);
for (i = 0; i < 4; i++)
dcode[i] = be32_to_cpu(dcode[i]);

View File

@ -7,7 +7,7 @@
/*
* Driver version
*/
#define QLA2XXX_VERSION "8.07.00.26-k"
#define QLA2XXX_VERSION "8.07.00.33-k"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 7

View File

@ -46,11 +46,13 @@ int qla4_83xx_rd_reg_indirect(struct scsi_qla_host *ha, uint32_t addr,
ret_val = qla4_83xx_set_win_base(ha, addr);
if (ret_val == QLA_SUCCESS)
if (ret_val == QLA_SUCCESS) {
*data = qla4_83xx_rd_reg(ha, QLA83XX_WILDCARD);
else
} else {
*data = 0xffffffff;
ql4_printk(KERN_ERR, ha, "%s: failed read of addr 0x%x!\n",
__func__, addr);
}
return ret_val;
}

View File

@ -710,7 +710,7 @@ static int qpti_map_regs(struct qlogicpti *qpti)
"PTI Qlogic/ISP");
if (!qpti->qregs) {
printk("PTI: Qlogic/ISP registers are unmappable\n");
return -1;
return -ENODEV;
}
if (qpti->is_pti) {
qpti->sreg = of_ioremap(&op->resource[0], (16 * 4096),
@ -718,7 +718,7 @@ static int qpti_map_regs(struct qlogicpti *qpti)
"PTI Qlogic/ISP statreg");
if (!qpti->sreg) {
printk("PTI: Qlogic/ISP status register is unmappable\n");
return -1;
return -ENODEV;
}
}
return 0;

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