Update Linux to v5.10.109
Sourced from [1]
[1] https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.109.tar.xz
Change-Id: I19bca9fc6762d4e63bcf3e4cba88bbe560d9c76c
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/drivers/scsi/.gitignore b/drivers/scsi/.gitignore
index e295674..5f65cb7 100644
--- a/drivers/scsi/.gitignore
+++ b/drivers/scsi/.gitignore
@@ -1,2 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
53c700_d.h
scsi_devinfo_tbl.c
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 2b1e0d5..fb6444d 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1049,9 +1049,7 @@
static const struct file_operations tw_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = tw_chrdev_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = tw_chrdev_ioctl,
-#endif
+ .compat_ioctl = compat_ptr_ioctl,
.open = tw_chrdev_open,
.release = NULL,
.llseek = noop_llseek,
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 0068963..3242ff6 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -116,9 +116,9 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/device.h>
+#include <linux/pgtable.h>
#include <asm/dma.h>
#include <asm/io.h>
-#include <asm/pgtable.h>
#include <asm/byteorder.h>
#include <scsi/scsi.h>
@@ -269,6 +269,27 @@
spi_period(SDp->sdev_target));
}
+static inline dma_addr_t virt_to_dma(struct NCR_700_Host_Parameters *h, void *p)
+{
+ return h->pScript + ((uintptr_t)p - (uintptr_t)h->script);
+}
+
+static inline void dma_sync_to_dev(struct NCR_700_Host_Parameters *h,
+ void *addr, size_t size)
+{
+ if (h->noncoherent)
+ dma_sync_single_for_device(h->dev, virt_to_dma(h, addr),
+ size, DMA_BIDIRECTIONAL);
+}
+
+static inline void dma_sync_from_dev(struct NCR_700_Host_Parameters *h,
+ void *addr, size_t size)
+{
+ if (h->noncoherent)
+ dma_sync_single_for_device(h->dev, virt_to_dma(h, addr), size,
+ DMA_BIDIRECTIONAL);
+}
+
struct Scsi_Host *
NCR_700_detect(struct scsi_host_template *tpnt,
struct NCR_700_Host_Parameters *hostdata, struct device *dev)
@@ -283,9 +304,13 @@
if(tpnt->sdev_attrs == NULL)
tpnt->sdev_attrs = NCR_700_dev_attrs;
- memory = dma_alloc_attrs(dev, TOTAL_MEM_SIZE, &pScript,
- GFP_KERNEL, DMA_ATTR_NON_CONSISTENT);
- if(memory == NULL) {
+ memory = dma_alloc_coherent(dev, TOTAL_MEM_SIZE, &pScript, GFP_KERNEL);
+ if (!memory) {
+ hostdata->noncoherent = 1;
+ memory = dma_alloc_noncoherent(dev, TOTAL_MEM_SIZE, &pScript,
+ DMA_BIDIRECTIONAL, GFP_KERNEL);
+ }
+ if (!memory) {
printk(KERN_ERR "53c700: Failed to allocate memory for driver, detaching\n");
return NULL;
}
@@ -339,11 +364,11 @@
for (j = 0; j < PATCHES; j++)
script[LABELPATCHES[j]] = bS_to_host(pScript + SCRIPT[LABELPATCHES[j]]);
/* now patch up fixed addresses. */
- script_patch_32(hostdata->dev, script, MessageLocation,
+ script_patch_32(hostdata, script, MessageLocation,
pScript + MSGOUT_OFFSET);
- script_patch_32(hostdata->dev, script, StatusAddress,
+ script_patch_32(hostdata, script, StatusAddress,
pScript + STATUS_OFFSET);
- script_patch_32(hostdata->dev, script, ReceiveMsgAddress,
+ script_patch_32(hostdata, script, ReceiveMsgAddress,
pScript + MSGIN_OFFSET);
hostdata->script = script;
@@ -395,8 +420,13 @@
struct NCR_700_Host_Parameters *hostdata =
(struct NCR_700_Host_Parameters *)host->hostdata[0];
- dma_free_attrs(hostdata->dev, TOTAL_MEM_SIZE, hostdata->script,
- hostdata->pScript, DMA_ATTR_NON_CONSISTENT);
+ if (hostdata->noncoherent)
+ dma_free_noncoherent(hostdata->dev, TOTAL_MEM_SIZE,
+ hostdata->script, hostdata->pScript,
+ DMA_BIDIRECTIONAL);
+ else
+ dma_free_coherent(hostdata->dev, TOTAL_MEM_SIZE,
+ hostdata->script, hostdata->pScript);
return 1;
}
@@ -804,8 +834,8 @@
shost_printk(KERN_WARNING, host,
"Unexpected SDTR msg\n");
hostdata->msgout[0] = A_REJECT_MSG;
- dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE);
- script_patch_16(hostdata->dev, hostdata->script,
+ dma_sync_to_dev(hostdata, hostdata->msgout, 1);
+ script_patch_16(hostdata, hostdata->script,
MessageCount, 1);
/* SendMsgOut returns, so set up the return
* address */
@@ -817,9 +847,8 @@
printk(KERN_INFO "scsi%d: (%d:%d), Unsolicited WDTR after CMD, Rejecting\n",
host->host_no, pun, lun);
hostdata->msgout[0] = A_REJECT_MSG;
- dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE);
- script_patch_16(hostdata->dev, hostdata->script, MessageCount,
- 1);
+ dma_sync_to_dev(hostdata, hostdata->msgout, 1);
+ script_patch_16(hostdata, hostdata->script, MessageCount, 1);
resume_offset = hostdata->pScript + Ent_SendMessageWithATN;
break;
@@ -832,9 +861,8 @@
printk("\n");
/* just reject it */
hostdata->msgout[0] = A_REJECT_MSG;
- dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE);
- script_patch_16(hostdata->dev, hostdata->script, MessageCount,
- 1);
+ dma_sync_to_dev(hostdata, hostdata->msgout, 1);
+ script_patch_16(hostdata, hostdata->script, MessageCount, 1);
/* SendMsgOut returns, so set up the return
* address */
resume_offset = hostdata->pScript + Ent_SendMessageWithATN;
@@ -917,9 +945,8 @@
printk("\n");
/* just reject it */
hostdata->msgout[0] = A_REJECT_MSG;
- dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE);
- script_patch_16(hostdata->dev, hostdata->script, MessageCount,
- 1);
+ dma_sync_to_dev(hostdata, hostdata->msgout, 1);
+ script_patch_16(hostdata, hostdata->script, MessageCount, 1);
/* SendMsgOut returns, so set up the return
* address */
resume_offset = hostdata->pScript + Ent_SendMessageWithATN;
@@ -928,7 +955,7 @@
}
NCR_700_writel(temp, host, TEMP_REG);
/* set us up to receive another message */
- dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE);
+ dma_sync_from_dev(hostdata, hostdata->msgin, MSG_ARRAY_SIZE);
return resume_offset;
}
@@ -1008,8 +1035,8 @@
slot->SG[1].ins = bS_to_host(SCRIPT_RETURN);
slot->SG[1].pAddr = 0;
slot->resume_offset = hostdata->pScript;
- dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG[0])*2, DMA_TO_DEVICE);
- dma_cache_sync(hostdata->dev, SCp->sense_buffer, SCSI_SENSE_BUFFERSIZE, DMA_FROM_DEVICE);
+ dma_sync_to_dev(hostdata, slot->SG, sizeof(slot->SG[0])*2);
+ dma_sync_from_dev(hostdata, SCp->sense_buffer, SCSI_SENSE_BUFFERSIZE);
/* queue the command for reissue */
slot->state = NCR_700_SLOT_QUEUED;
@@ -1129,11 +1156,11 @@
hostdata->cmd = slot->cmnd;
/* re-patch for this command */
- script_patch_32_abs(hostdata->dev, hostdata->script,
+ script_patch_32_abs(hostdata, hostdata->script,
CommandAddress, slot->pCmd);
- script_patch_16(hostdata->dev, hostdata->script,
+ script_patch_16(hostdata, hostdata->script,
CommandCount, slot->cmnd->cmd_len);
- script_patch_32_abs(hostdata->dev, hostdata->script,
+ script_patch_32_abs(hostdata, hostdata->script,
SGScriptStartAddress,
to32bit(&slot->pSG[0].ins));
@@ -1144,14 +1171,14 @@
* should therefore always clear ACK */
NCR_700_writeb(NCR_700_get_SXFER(hostdata->cmd->device),
host, SXFER_REG);
- dma_cache_sync(hostdata->dev, hostdata->msgin,
- MSG_ARRAY_SIZE, DMA_FROM_DEVICE);
- dma_cache_sync(hostdata->dev, hostdata->msgout,
- MSG_ARRAY_SIZE, DMA_TO_DEVICE);
+ dma_sync_from_dev(hostdata, hostdata->msgin,
+ MSG_ARRAY_SIZE);
+ dma_sync_to_dev(hostdata, hostdata->msgout,
+ MSG_ARRAY_SIZE);
/* I'm just being paranoid here, the command should
* already have been flushed from the cache */
- dma_cache_sync(hostdata->dev, slot->cmnd->cmnd,
- slot->cmnd->cmd_len, DMA_TO_DEVICE);
+ dma_sync_to_dev(hostdata, slot->cmnd->cmnd,
+ slot->cmnd->cmd_len);
@@ -1214,8 +1241,7 @@
hostdata->reselection_id = reselection_id;
/* just in case we have a stale simple tag message, clear it */
hostdata->msgin[1] = 0;
- dma_cache_sync(hostdata->dev, hostdata->msgin,
- MSG_ARRAY_SIZE, DMA_BIDIRECTIONAL);
+ dma_sync_to_dev(hostdata, hostdata->msgin, MSG_ARRAY_SIZE);
if(hostdata->tag_negotiated & (1<<reselection_id)) {
resume_offset = hostdata->pScript + Ent_GetReselectionWithTag;
} else {
@@ -1329,8 +1355,7 @@
hostdata->cmd = NULL;
/* clear any stale simple tag message */
hostdata->msgin[1] = 0;
- dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE,
- DMA_BIDIRECTIONAL);
+ dma_sync_to_dev(hostdata, hostdata->msgin, MSG_ARRAY_SIZE);
if(id == 0xff) {
/* Selected as target, Ignore */
@@ -1427,30 +1452,26 @@
NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION);
}
- script_patch_16(hostdata->dev, hostdata->script, MessageCount, count);
+ script_patch_16(hostdata, hostdata->script, MessageCount, count);
+ script_patch_ID(hostdata, hostdata->script, Device_ID, 1<<scmd_id(SCp));
- script_patch_ID(hostdata->dev, hostdata->script,
- Device_ID, 1<<scmd_id(SCp));
-
- script_patch_32_abs(hostdata->dev, hostdata->script, CommandAddress,
+ script_patch_32_abs(hostdata, hostdata->script, CommandAddress,
slot->pCmd);
- script_patch_16(hostdata->dev, hostdata->script, CommandCount,
- SCp->cmd_len);
+ script_patch_16(hostdata, hostdata->script, CommandCount, SCp->cmd_len);
/* finally plumb the beginning of the SG list into the script
* */
- script_patch_32_abs(hostdata->dev, hostdata->script,
+ script_patch_32_abs(hostdata, hostdata->script,
SGScriptStartAddress, to32bit(&slot->pSG[0].ins));
NCR_700_clear_fifo(SCp->device->host);
if(slot->resume_offset == 0)
slot->resume_offset = hostdata->pScript;
/* now perform all the writebacks and invalidates */
- dma_cache_sync(hostdata->dev, hostdata->msgout, count, DMA_TO_DEVICE);
- dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE,
- DMA_FROM_DEVICE);
- dma_cache_sync(hostdata->dev, SCp->cmnd, SCp->cmd_len, DMA_TO_DEVICE);
- dma_cache_sync(hostdata->dev, hostdata->status, 1, DMA_FROM_DEVICE);
+ dma_sync_to_dev(hostdata, hostdata->msgout, count);
+ dma_sync_from_dev(hostdata, hostdata->msgin, MSG_ARRAY_SIZE);
+ dma_sync_to_dev(hostdata, SCp->cmnd, SCp->cmd_len);
+ dma_sync_from_dev(hostdata, hostdata->status, 1);
/* set the synchronous period/offset */
NCR_700_writeb(NCR_700_get_SXFER(SCp->device),
@@ -1485,10 +1506,8 @@
__u8 sstat0 = 0, dstat = 0;
__u32 dsp;
struct scsi_cmnd *SCp = hostdata->cmd;
- enum NCR_700_Host_State state;
handled = 1;
- state = hostdata->state;
SCp = hostdata->cmd;
if(istat & SCSI_INT_PENDING) {
@@ -1626,7 +1645,7 @@
slot->SG[i].ins = bS_to_host(SCRIPT_NOP);
slot->SG[i].pAddr = 0;
}
- dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG), DMA_TO_DEVICE);
+ dma_sync_to_dev(hostdata, slot->SG, sizeof(slot->SG));
/* and pretend we disconnected after
* the command phase */
resume_offset = hostdata->pScript + Ent_MsgInDuringData;
@@ -1739,7 +1758,6 @@
struct NCR_700_Host_Parameters *hostdata =
(struct NCR_700_Host_Parameters *)SCp->device->host->hostdata[0];
__u32 move_ins;
- enum dma_data_direction direction;
struct NCR_700_command_slot *slot;
if(hostdata->command_slot_count >= NCR_700_COMMAND_SLOTS_PER_HOST) {
@@ -1832,7 +1850,7 @@
case REQUEST_SENSE:
/* clear the internal sense magic */
SCp->cmnd[6] = 0;
- /* fall through */
+ fallthrough;
default:
/* OK, get it from the command */
switch(SCp->sc_data_direction) {
@@ -1856,7 +1874,6 @@
}
/* now build the scatter gather list */
- direction = SCp->sc_data_direction;
if(move_ins != 0) {
int i;
int sg_count;
@@ -1878,7 +1895,7 @@
}
slot->SG[i].ins = bS_to_host(SCRIPT_RETURN);
slot->SG[i].pAddr = 0;
- dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG), DMA_TO_DEVICE);
+ dma_sync_to_dev(hostdata, slot->SG, sizeof(slot->SG));
DEBUG((" SETTING %p to %x\n",
(&slot->pSG[i].ins),
slot->SG[i].ins));
diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
index 05fe439..c9f8c49 100644
--- a/drivers/scsi/53c700.h
+++ b/drivers/scsi/53c700.h
@@ -209,6 +209,7 @@
#endif
__u32 chip710:1; /* set if really a 710 not 700 */
__u32 burst_length:4; /* set to 0 to disable 710 bursting */
+ __u32 noncoherent:1; /* needs to use non-coherent DMA */
/* NOTHING BELOW HERE NEEDS ALTERING */
__u32 fast:1; /* if we can alter the SCSI bus clock
@@ -422,33 +423,33 @@
#define NCR_710_MIN_XFERP 0
#define NCR_700_MIN_PERIOD 25 /* for SDTR message, 100ns */
-#define script_patch_32(dev, script, symbol, value) \
+#define script_patch_32(h, script, symbol, value) \
{ \
int i; \
dma_addr_t da = value; \
for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \
__u32 val = bS_to_cpu((script)[A_##symbol##_used[i]]) + da; \
(script)[A_##symbol##_used[i]] = bS_to_host(val); \
- dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \
+ dma_sync_to_dev((h), &(script)[A_##symbol##_used[i]], 4); \
DEBUG((" script, patching %s at %d to %pad\n", \
#symbol, A_##symbol##_used[i], &da)); \
} \
}
-#define script_patch_32_abs(dev, script, symbol, value) \
+#define script_patch_32_abs(h, script, symbol, value) \
{ \
int i; \
dma_addr_t da = value; \
for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \
(script)[A_##symbol##_used[i]] = bS_to_host(da); \
- dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \
+ dma_sync_to_dev((h), &(script)[A_##symbol##_used[i]], 4); \
DEBUG((" script, patching %s at %d to %pad\n", \
#symbol, A_##symbol##_used[i], &da)); \
} \
}
/* Used for patching the SCSI ID in the SELECT instruction */
-#define script_patch_ID(dev, script, symbol, value) \
+#define script_patch_ID(h, script, symbol, value) \
{ \
int i; \
for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \
@@ -456,13 +457,13 @@
val &= 0xff00ffff; \
val |= ((value) & 0xff) << 16; \
(script)[A_##symbol##_used[i]] = bS_to_host(val); \
- dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \
+ dma_sync_to_dev((h), &(script)[A_##symbol##_used[i]], 4); \
DEBUG((" script, patching ID field %s at %d to 0x%x\n", \
#symbol, A_##symbol##_used[i], val)); \
} \
}
-#define script_patch_16(dev, script, symbol, value) \
+#define script_patch_16(h, script, symbol, value) \
{ \
int i; \
for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \
@@ -470,7 +471,7 @@
val &= 0xffff0000; \
val |= ((value) & 0xffff); \
(script)[A_##symbol##_used[i]] = bS_to_host(val); \
- dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \
+ dma_sync_to_dev((h), &(script)[A_##symbol##_used[i]], 4); \
DEBUG((" script, patching short field %s at %d to 0x%x\n", \
#symbol, A_##symbol##_used[i], val)); \
} \
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 6a54556..39ef074 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -36,6 +36,7 @@
#include <linux/jiffies.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
+#include <linux/msdos_partition.h>
#include <scsi/scsicam.h>
#include <asm/dma.h>
@@ -134,7 +135,7 @@
static void blogic_announce_drvr(struct blogic_adapter *adapter)
{
blogic_announce("***** BusLogic SCSI Driver Version " blogic_drvr_version " of " blogic_drvr_date " *****\n", adapter);
- blogic_announce("Copyright 1995-1998 by Leonard N. Zubkoff " "<lnz@dandelion.com>\n", adapter);
+ blogic_announce("Copyright 1995-1998 by Leonard N. Zubkoff <lnz@dandelion.com>\n", adapter);
}
@@ -440,7 +441,7 @@
goto done;
}
if (blogic_global_options.trace_config)
- blogic_notice("blogic_cmd(%02X) Status = %02X: " "(Modify I/O Address)\n", adapter, opcode, statusreg.all);
+ blogic_notice("blogic_cmd(%02X) Status = %02X: (Modify I/O Address)\n", adapter, opcode, statusreg.all);
result = 0;
goto done;
}
@@ -716,23 +717,23 @@
pci_addr = base_addr1 = pci_resource_start(pci_device, 1);
if (pci_resource_flags(pci_device, 0) & IORESOURCE_MEM) {
- blogic_err("BusLogic: Base Address0 0x%X not I/O for " "MultiMaster Host Adapter\n", NULL, base_addr0);
- blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
+ blogic_err("BusLogic: Base Address0 0x%lX not I/O for MultiMaster Host Adapter\n", NULL, base_addr0);
+ blogic_err("at PCI Bus %d Device %d I/O Address 0x%lX\n", NULL, bus, device, io_addr);
continue;
}
if (pci_resource_flags(pci_device, 1) & IORESOURCE_IO) {
- blogic_err("BusLogic: Base Address1 0x%X not Memory for " "MultiMaster Host Adapter\n", NULL, base_addr1);
- blogic_err("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, bus, device, pci_addr);
+ blogic_err("BusLogic: Base Address1 0x%lX not Memory for MultiMaster Host Adapter\n", NULL, base_addr1);
+ blogic_err("at PCI Bus %d Device %d PCI Address 0x%lX\n", NULL, bus, device, pci_addr);
continue;
}
if (irq_ch == 0) {
- blogic_err("BusLogic: IRQ Channel %d invalid for " "MultiMaster Host Adapter\n", NULL, irq_ch);
- blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
+ blogic_err("BusLogic: IRQ Channel %d invalid for MultiMaster Host Adapter\n", NULL, irq_ch);
+ blogic_err("at PCI Bus %d Device %d I/O Address 0x%lX\n", NULL, bus, device, io_addr);
continue;
}
if (blogic_global_options.trace_probe) {
- blogic_notice("BusLogic: PCI MultiMaster Host Adapter " "detected at\n", NULL);
- blogic_notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, bus, device, io_addr, pci_addr);
+ blogic_notice("BusLogic: PCI MultiMaster Host Adapter detected at\n", NULL);
+ blogic_notice("BusLogic: PCI Bus %d Device %d I/O Address 0x%lX PCI Address 0x%lX\n", NULL, bus, device, io_addr, pci_addr);
}
/*
Issue the Inquire PCI Host Adapter Information command to determine
@@ -818,7 +819,7 @@
nonpr_mmcount++;
mmcount++;
} else
- blogic_warn("BusLogic: Too many Host Adapters " "detected\n", NULL);
+ blogic_warn("BusLogic: Too many Host Adapters detected\n", NULL);
}
/*
If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq."
@@ -956,23 +957,23 @@
pci_addr = base_addr1 = pci_resource_start(pci_device, 1);
#ifdef CONFIG_SCSI_FLASHPOINT
if (pci_resource_flags(pci_device, 0) & IORESOURCE_MEM) {
- blogic_err("BusLogic: Base Address0 0x%X not I/O for " "FlashPoint Host Adapter\n", NULL, base_addr0);
- blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
+ blogic_err("BusLogic: Base Address0 0x%lX not I/O for FlashPoint Host Adapter\n", NULL, base_addr0);
+ blogic_err("at PCI Bus %d Device %d I/O Address 0x%lX\n", NULL, bus, device, io_addr);
continue;
}
if (pci_resource_flags(pci_device, 1) & IORESOURCE_IO) {
- blogic_err("BusLogic: Base Address1 0x%X not Memory for " "FlashPoint Host Adapter\n", NULL, base_addr1);
- blogic_err("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, bus, device, pci_addr);
+ blogic_err("BusLogic: Base Address1 0x%lX not Memory for FlashPoint Host Adapter\n", NULL, base_addr1);
+ blogic_err("at PCI Bus %d Device %d PCI Address 0x%lX\n", NULL, bus, device, pci_addr);
continue;
}
if (irq_ch == 0) {
- blogic_err("BusLogic: IRQ Channel %d invalid for " "FlashPoint Host Adapter\n", NULL, irq_ch);
- blogic_err("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, bus, device, io_addr);
+ blogic_err("BusLogic: IRQ Channel %d invalid for FlashPoint Host Adapter\n", NULL, irq_ch);
+ blogic_err("at PCI Bus %d Device %d I/O Address 0x%lX\n", NULL, bus, device, io_addr);
continue;
}
if (blogic_global_options.trace_probe) {
- blogic_notice("BusLogic: FlashPoint Host Adapter " "detected at\n", NULL);
- blogic_notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, bus, device, io_addr, pci_addr);
+ blogic_notice("BusLogic: FlashPoint Host Adapter detected at\n", NULL);
+ blogic_notice("BusLogic: PCI Bus %d Device %d I/O Address 0x%lX PCI Address 0x%lX\n", NULL, bus, device, io_addr, pci_addr);
}
if (blogic_probeinfo_count < BLOGIC_MAX_ADAPTERS) {
struct blogic_probeinfo *probeinfo =
@@ -987,11 +988,11 @@
probeinfo->pci_device = pci_dev_get(pci_device);
fpcount++;
} else
- blogic_warn("BusLogic: Too many Host Adapters " "detected\n", NULL);
+ blogic_warn("BusLogic: Too many Host Adapters detected\n", NULL);
#else
- blogic_err("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", NULL, bus, device);
- blogic_err("BusLogic: I/O Address 0x%X PCI Address 0x%X, irq %d, " "but FlashPoint\n", NULL, io_addr, pci_addr, irq_ch);
- blogic_err("BusLogic: support was omitted in this kernel " "configuration.\n", NULL);
+ blogic_err("BusLogic: FlashPoint Host Adapter detected at PCI Bus %d Device %d\n", NULL, bus, device);
+ blogic_err("BusLogic: I/O Address 0x%lX PCI Address 0x%lX, irq %d, but FlashPoint\n", NULL, io_addr, pci_addr, irq_ch);
+ blogic_err("BusLogic: support was omitted in this kernel configuration.\n", NULL);
#endif
}
/*
@@ -1099,9 +1100,9 @@
if (adapter->adapter_bus_type == BLOGIC_PCI_BUS) {
blogic_err("While configuring BusLogic PCI Host Adapter at\n",
adapter);
- blogic_err("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n", adapter, adapter->bus, adapter->dev, adapter->io_addr, adapter->pci_addr);
+ blogic_err("Bus %d Device %d I/O Address 0x%lX PCI Address 0x%lX:\n", adapter, adapter->bus, adapter->dev, adapter->io_addr, adapter->pci_addr);
} else
- blogic_err("While configuring BusLogic Host Adapter at " "I/O Address 0x%X:\n", adapter, adapter->io_addr);
+ blogic_err("While configuring BusLogic Host Adapter at I/O Address 0x%lX:\n", adapter, adapter->io_addr);
blogic_err("%s FAILED - DETACHING\n", adapter, msg);
if (blogic_cmd_failure_reason != NULL)
blogic_err("ADDITIONAL FAILURE INFO - %s\n", adapter,
@@ -1129,13 +1130,13 @@
fpinfo->present = false;
if (!(FlashPoint_ProbeHostAdapter(fpinfo) == 0 &&
fpinfo->present)) {
- blogic_err("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", adapter, adapter->bus, adapter->dev);
- blogic_err("BusLogic: I/O Address 0x%X PCI Address 0x%X, " "but FlashPoint\n", adapter, adapter->io_addr, adapter->pci_addr);
+ blogic_err("BusLogic: FlashPoint Host Adapter detected at PCI Bus %d Device %d\n", adapter, adapter->bus, adapter->dev);
+ blogic_err("BusLogic: I/O Address 0x%lX PCI Address 0x%lX, but FlashPoint\n", adapter, adapter->io_addr, adapter->pci_addr);
blogic_err("BusLogic: Probe Function failed to validate it.\n", adapter);
return false;
}
if (blogic_global_options.trace_probe)
- blogic_notice("BusLogic_Probe(0x%X): FlashPoint Found\n", adapter, adapter->io_addr);
+ blogic_notice("BusLogic_Probe(0x%lX): FlashPoint Found\n", adapter, adapter->io_addr);
/*
Indicate the Host Adapter Probe completed successfully.
*/
@@ -1152,7 +1153,7 @@
intreg.all = blogic_rdint(adapter);
georeg.all = blogic_rdgeom(adapter);
if (blogic_global_options.trace_probe)
- blogic_notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, " "Geometry 0x%02X\n", adapter, adapter->io_addr, statusreg.all, intreg.all, georeg.all);
+ blogic_notice("BusLogic_Probe(0x%lX): Status 0x%02X, Interrupt 0x%02X, Geometry 0x%02X\n", adapter, adapter->io_addr, statusreg.all, intreg.all, georeg.all);
if (statusreg.all == 0 || statusreg.sr.diag_active ||
statusreg.sr.cmd_param_busy || statusreg.sr.rsvd ||
statusreg.sr.cmd_invalid || intreg.ir.rsvd != 0)
@@ -1231,7 +1232,7 @@
udelay(100);
}
if (blogic_global_options.trace_hw_reset)
- blogic_notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, " "Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
+ blogic_notice("BusLogic_HardwareReset(0x%lX): Diagnostic Active, Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
if (timeout < 0)
return false;
/*
@@ -1251,7 +1252,7 @@
udelay(100);
}
if (blogic_global_options.trace_hw_reset)
- blogic_notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, " "Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
+ blogic_notice("BusLogic_HardwareReset(0x%lX): Diagnostic Completed, Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
if (timeout < 0)
return false;
/*
@@ -1267,7 +1268,7 @@
udelay(100);
}
if (blogic_global_options.trace_hw_reset)
- blogic_notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, " "Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
+ blogic_notice("BusLogic_HardwareReset(0x%lX): Host Adapter Ready, Status 0x%02X\n", adapter, adapter->io_addr, statusreg.all);
if (timeout < 0)
return false;
/*
@@ -1323,7 +1324,7 @@
Provide tracing information if requested and return.
*/
if (blogic_global_options.trace_probe)
- blogic_notice("BusLogic_Check(0x%X): MultiMaster %s\n", adapter,
+ blogic_notice("BusLogic_Check(0x%lX): MultiMaster %s\n", adapter,
adapter->io_addr,
(result ? "Found" : "Not Found"));
return result;
@@ -1836,7 +1837,7 @@
int tgt_id;
blogic_info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n", adapter, adapter->model, blogic_adapter_busnames[adapter->adapter_bus_type], (adapter->wide ? " Wide" : ""), (adapter->differential ? " Differential" : ""), (adapter->ultra ? " Ultra" : ""));
- blogic_info(" Firmware Version: %s, I/O Address: 0x%X, " "IRQ Channel: %d/%s\n", adapter, adapter->fw_ver, adapter->io_addr, adapter->irq_ch, (adapter->level_int ? "Level" : "Edge"));
+ blogic_info(" Firmware Version: %s, I/O Address: 0x%lX, IRQ Channel: %d/%s\n", adapter, adapter->fw_ver, adapter->io_addr, adapter->irq_ch, (adapter->level_int ? "Level" : "Edge"));
if (adapter->adapter_bus_type != BLOGIC_PCI_BUS) {
blogic_info(" DMA Channel: ", adapter);
if (adapter->dma_ch > 0)
@@ -1852,7 +1853,7 @@
blogic_info(" PCI Bus: %d, Device: %d, Address: ", adapter,
adapter->bus, adapter->dev);
if (adapter->pci_addr > 0)
- blogic_info("0x%X, ", adapter, adapter->pci_addr);
+ blogic_info("0x%lX, ", adapter, adapter->pci_addr);
else
blogic_info("Unassigned, ", adapter);
}
@@ -1932,10 +1933,10 @@
blogic_info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n", adapter,
discon_msg, tagq_msg);
if (blogic_multimaster_type(adapter)) {
- blogic_info(" Scatter/Gather Limit: %d of %d segments, " "Mailboxes: %d\n", adapter, adapter->drvr_sglimit, adapter->adapter_sglimit, adapter->mbox_count);
- blogic_info(" Driver Queue Depth: %d, " "Host Adapter Queue Depth: %d\n", adapter, adapter->drvr_qdepth, adapter->adapter_qdepth);
+ blogic_info(" Scatter/Gather Limit: %d of %d segments, Mailboxes: %d\n", adapter, adapter->drvr_sglimit, adapter->adapter_sglimit, adapter->mbox_count);
+ blogic_info(" Driver Queue Depth: %d, Host Adapter Queue Depth: %d\n", adapter, adapter->drvr_qdepth, adapter->adapter_qdepth);
} else
- blogic_info(" Driver Queue Depth: %d, " "Scatter/Gather Limit: %d segments\n", adapter, adapter->drvr_qdepth, adapter->drvr_sglimit);
+ blogic_info(" Driver Queue Depth: %d, Scatter/Gather Limit: %d segments\n", adapter, adapter->drvr_qdepth, adapter->drvr_sglimit);
blogic_info(" Tagged Queue Depth: ", adapter);
common_tagq_depth = true;
for (tgt_id = 1; tgt_id < adapter->maxdev; tgt_id++)
@@ -2236,7 +2237,7 @@
"INQUIRE INSTALLED DEVICES ID 0 TO 7");
for (tgt_id = 0; tgt_id < 8; tgt_id++)
adapter->tgt_flags[tgt_id].tgt_exists =
- (installed_devs0to7[tgt_id] != 0 ? true : false);
+ installed_devs0to7[tgt_id] != 0;
}
/*
Issue the Inquire Setup Information command.
@@ -2634,7 +2635,7 @@
case BLOGIC_BAD_CMD_PARAM:
blogic_warn("BusLogic Driver Protocol Error 0x%02X\n",
adapter, adapter_status);
- /* fall through */
+ fallthrough;
case BLOGIC_DATA_UNDERRUN:
case BLOGIC_DATA_OVERRUN:
case BLOGIC_NOEXPECT_BUSFREE:
@@ -2717,7 +2718,7 @@
then there is most likely a bug in
the Host Adapter firmware.
*/
- blogic_warn("Illegal CCB #%ld status %d in " "Incoming Mailbox\n", adapter, ccb->serial, ccb->status);
+ blogic_warn("Illegal CCB #%ld status %d in Incoming Mailbox\n", adapter, ccb->serial, ccb->status);
}
}
next_inbox->comp_code = BLOGIC_INBOX_FREE;
@@ -2752,7 +2753,7 @@
if (ccb->opcode == BLOGIC_BDR) {
int tgt_id = ccb->tgt_id;
- blogic_warn("Bus Device Reset CCB #%ld to Target " "%d Completed\n", adapter, ccb->serial, tgt_id);
+ blogic_warn("Bus Device Reset CCB #%ld to Target %d Completed\n", adapter, ccb->serial, tgt_id);
blogic_inc_count(&adapter->tgt_stats[tgt_id].bdr_done);
adapter->tgt_flags[tgt_id].tagq_active = false;
adapter->cmds_since_rst[tgt_id] = 0;
@@ -2829,7 +2830,7 @@
if (blogic_global_options.trace_err) {
int i;
blogic_notice("CCB #%ld Target %d: Result %X Host "
- "Adapter Status %02X " "Target Status %02X\n", adapter, ccb->serial, ccb->tgt_id, command->result, ccb->adapter_status, ccb->tgt_status);
+ "Adapter Status %02X Target Status %02X\n", adapter, ccb->serial, ccb->tgt_id, command->result, ccb->adapter_status, ccb->tgt_status);
blogic_notice("CDB ", adapter);
for (i = 0; i < ccb->cdblen; i++)
blogic_notice(" %02X", adapter, ccb->cdb[i]);
@@ -3203,12 +3204,12 @@
*/
if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START, ccb)) {
spin_unlock_irq(adapter->scsi_host->host_lock);
- blogic_warn("Unable to write Outgoing Mailbox - " "Pausing for 1 second\n", adapter);
+ blogic_warn("Unable to write Outgoing Mailbox - Pausing for 1 second\n", adapter);
blogic_delay(1);
spin_lock_irq(adapter->scsi_host->host_lock);
if (!blogic_write_outbox(adapter, BLOGIC_MBOX_START,
ccb)) {
- blogic_warn("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", adapter);
+ blogic_warn("Still unable to write Outgoing Mailbox - Host Adapter Dead?\n", adapter);
blogic_dealloc_ccb(ccb, 1);
command->result = DID_ERROR << 16;
command->scsi_done(command);
@@ -3410,9 +3411,10 @@
a partition table entry whose end_head matches one of the
standard BusLogic geometry translations (64/32, 128/32, or 255/63).
*/
- if (*(unsigned short *) (buf + 64) == 0xAA55) {
- struct partition *part1_entry = (struct partition *) buf;
- struct partition *part_entry = part1_entry;
+ if (*(unsigned short *) (buf + 64) == MSDOS_LABEL_MAGIC) {
+ struct msdos_partition *part1_entry =
+ (struct msdos_partition *)buf;
+ struct msdos_partition *part_entry = part1_entry;
int saved_cyl = diskparam->cylinders, part_no;
unsigned char part_end_head = 0, part_end_sector = 0;
@@ -3443,8 +3445,8 @@
if (diskparam->cylinders != saved_cyl)
blogic_warn("Adopting Geometry %d/%d from Partition Table\n", adapter, diskparam->heads, diskparam->sectors);
} else if (part_end_head > 0 || part_end_sector > 0) {
- blogic_warn("Warning: Partition Table appears to " "have Geometry %d/%d which is\n", adapter, part_end_head + 1, part_end_sector);
- blogic_warn("not compatible with current BusLogic " "Host Adapter Geometry %d/%d\n", adapter, diskparam->heads, diskparam->sectors);
+ blogic_warn("Warning: Partition Table appears to have Geometry %d/%d which is\n", adapter, part_end_head + 1, part_end_sector);
+ blogic_warn("not compatible with current BusLogic Host Adapter Geometry %d/%d\n", adapter, diskparam->heads, diskparam->sectors);
}
}
kfree(buf);
@@ -3652,7 +3654,7 @@
selected host adapter.
The BusLogic Driver Probing Options are described in
- <file:Documentation/scsi/BusLogic.txt>.
+ <file:Documentation/scsi/BusLogic.rst>.
*/
static int __init blogic_parseopts(char *options)
@@ -3689,7 +3691,7 @@
blogic_probe_options.probe134 = true;
break;
default:
- blogic_err("BusLogic: Invalid Driver Options " "(invalid I/O Address 0x%X)\n", NULL, io_addr);
+ blogic_err("BusLogic: Invalid Driver Options (invalid I/O Address 0x%lX)\n", NULL, io_addr);
return 0;
}
} else if (blogic_parse(&options, "NoProbeISA"))
@@ -3710,7 +3712,7 @@
for (tgt_id = 0; tgt_id < BLOGIC_MAXDEV; tgt_id++) {
unsigned short qdepth = simple_strtoul(options, &options, 0);
if (qdepth > BLOGIC_MAX_TAG_DEPTH) {
- blogic_err("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, qdepth);
+ blogic_err("BusLogic: Invalid Driver Options (invalid Queue Depth %d)\n", NULL, qdepth);
return 0;
}
drvr_opts->qdepth[tgt_id] = qdepth;
@@ -3719,12 +3721,12 @@
else if (*options == ']')
break;
else {
- blogic_err("BusLogic: Invalid Driver Options " "(',' or ']' expected at '%s')\n", NULL, options);
+ blogic_err("BusLogic: Invalid Driver Options (',' or ']' expected at '%s')\n", NULL, options);
return 0;
}
}
if (*options != ']') {
- blogic_err("BusLogic: Invalid Driver Options " "(']' expected at '%s')\n", NULL, options);
+ blogic_err("BusLogic: Invalid Driver Options (']' expected at '%s')\n", NULL, options);
return 0;
} else
options++;
@@ -3732,7 +3734,7 @@
unsigned short qdepth = simple_strtoul(options, &options, 0);
if (qdepth == 0 ||
qdepth > BLOGIC_MAX_TAG_DEPTH) {
- blogic_err("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, qdepth);
+ blogic_err("BusLogic: Invalid Driver Options (invalid Queue Depth %d)\n", NULL, qdepth);
return 0;
}
drvr_opts->common_qdepth = qdepth;
@@ -3778,7 +3780,7 @@
unsigned short bus_settle_time =
simple_strtoul(options, &options, 0);
if (bus_settle_time > 5 * 60) {
- blogic_err("BusLogic: Invalid Driver Options " "(invalid Bus Settle Time %d)\n", NULL, bus_settle_time);
+ blogic_err("BusLogic: Invalid Driver Options (invalid Bus Settle Time %d)\n", NULL, bus_settle_time);
return 0;
}
drvr_opts->bus_settle_time = bus_settle_time;
@@ -3803,14 +3805,14 @@
if (*options == ',')
options++;
else if (*options != ';' && *options != '\0') {
- blogic_err("BusLogic: Unexpected Driver Option '%s' " "ignored\n", NULL, options);
+ blogic_err("BusLogic: Unexpected Driver Option '%s' ignored\n", NULL, options);
*options = '\0';
}
}
if (!(blogic_drvr_options_count == 0 ||
blogic_probeinfo_count == 0 ||
blogic_drvr_options_count == blogic_probeinfo_count)) {
- blogic_err("BusLogic: Invalid Driver Options " "(all or no I/O Addresses must be specified)\n", NULL);
+ blogic_err("BusLogic: Invalid Driver Options (all or no I/O Addresses must be specified)\n", NULL);
return 0;
}
/*
@@ -3864,7 +3866,7 @@
(void) get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] != 0) {
- blogic_err("BusLogic: Obsolete Command Line Entry " "Format Ignored\n", NULL);
+ blogic_err("BusLogic: Obsolete Command Line Entry Format Ignored\n", NULL);
return 0;
}
if (str == NULL || *str == '\0')
diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c
index 3b15fb2..ec8a621 100644
--- a/drivers/scsi/FlashPoint.c
+++ b/drivers/scsi/FlashPoint.c
@@ -1034,11 +1034,14 @@
temp6 >>= 1;
switch (temp & 0x3) {
case AUTO_RATE_20: /* Synchronous, 20 mega-transfers/second */
- temp6 |= 0x8000; /* Fall through */
+ temp6 |= 0x8000;
+ fallthrough;
case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */
- temp5 |= 0x8000; /* Fall through */
+ temp5 |= 0x8000;
+ fallthrough;
case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */
- temp2 |= 0x8000; /* Fall through */
+ temp2 |= 0x8000;
+ fallthrough;
case AUTO_RATE_00: /* Asynchronous */
break;
}
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 9ea30fc..701b61e 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -11,7 +11,7 @@
default n
depends on BLOCK
depends on SCSI_MOD
- ---help---
+ help
Provides RAID
config SCSI
@@ -20,7 +20,7 @@
select SCSI_DMA if HAS_DMA
select SG_POOL
select BLK_SCSI_REQUEST
- ---help---
+ help
If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or
any other SCSI device under Linux, say Y and make sure that you know
the name of your SCSI host adapter (the card inside your computer
@@ -33,7 +33,7 @@
Channel, and FireWire storage.
To compile this driver as a module, choose M here and read
- <file:Documentation/scsi/scsi.txt>.
+ <file:Documentation/scsi/scsi.rst>.
The module will be called scsi_mod.
However, do not compile this as a module if your root file system
@@ -55,7 +55,7 @@
bool "legacy /proc/scsi/ support"
depends on SCSI && PROC_FS
default y
- ---help---
+ help
This option enables support for the various files in
/proc/scsi. In Linux 2.6 this has been superseded by
files in sysfs but many legacy applications rely on this.
@@ -68,7 +68,8 @@
config BLK_DEV_SD
tristate "SCSI disk support"
depends on SCSI
- ---help---
+ select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY
+ help
If you want to use SCSI hard disks, Fibre Channel disks,
Serial ATA (SATA) or Parallel ATA (PATA) hard disks,
USB storage or the SCSI or parallel port version of
@@ -78,7 +79,7 @@
CD-ROMs.
To compile this driver as a module, choose M here and read
- <file:Documentation/scsi/scsi.txt>.
+ <file:Documentation/scsi/scsi.rst>.
The module will be called sd_mod.
Do not compile this driver as a module if your root file system
@@ -89,21 +90,21 @@
config CHR_DEV_ST
tristate "SCSI tape support"
depends on SCSI
- ---help---
+ help
If you want to use a SCSI tape drive under Linux, say Y and read the
SCSI-HOWTO, available from
<http://www.tldp.org/docs.html#howto>, and
- <file:Documentation/scsi/st.txt> in the kernel source. This is NOT
+ <file:Documentation/scsi/st.rst> in the kernel source. This is NOT
for SCSI CD-ROMs.
To compile this driver as a module, choose M here and read
- <file:Documentation/scsi/scsi.txt>. The module will be called st.
+ <file:Documentation/scsi/scsi.rst>. The module will be called st.
config BLK_DEV_SR
tristate "SCSI CDROM support"
depends on SCSI && BLK_DEV
select CDROM
- ---help---
+ help
If you want to use a CD or DVD drive attached to your computer
by SCSI, FireWire, USB or ATAPI, say Y and read the SCSI-HOWTO
and the CDROM-HOWTO at <http://www.tldp.org/docs.html#howto>.
@@ -111,13 +112,13 @@
Make sure to say Y or M to "ISO 9660 CD-ROM file system support".
To compile this driver as a module, choose M here and read
- <file:Documentation/scsi/scsi.txt>.
+ <file:Documentation/scsi/scsi.rst>.
The module will be called sr_mod.
config CHR_DEV_SG
tristate "SCSI generic support"
depends on SCSI
- ---help---
+ help
If you want to use SCSI scanners, synthesizers or CD-writers or just
about anything having "SCSI" in its name other than hard disks,
CD-ROMs or tapes, say Y here. These won't be supported by the kernel
@@ -126,34 +127,34 @@
For scanners, look at SANE (<http://www.sane-project.org/>). For CD
writer software look at Cdrtools
- (<http://cdrecord.berlios.de/private/cdrecord.html>)
+ (<http://cdrtools.sourceforge.net/>)
and for burning a "disk at once": CDRDAO
(<http://cdrdao.sourceforge.net/>). Cdparanoia is a high
quality digital reader of audio CDs (<http://www.xiph.org/paranoia/>).
For other devices, it's possible that you'll have to write the
driver software yourself. Please read the file
- <file:Documentation/scsi/scsi-generic.txt> for more information.
+ <file:Documentation/scsi/scsi-generic.rst> for more information.
To compile this driver as a module, choose M here and read
- <file:Documentation/scsi/scsi.txt>. The module will be called sg.
+ <file:Documentation/scsi/scsi.rst>. The module will be called sg.
If unsure, say N.
config CHR_DEV_SCH
tristate "SCSI media changer support"
depends on SCSI
- ---help---
+ help
This is a driver for SCSI media changers. Most common devices are
tape libraries and MOD/CDROM jukeboxes. *Real* jukeboxes, you
don't need this for those tiny 6-slot cdrom changers. Media
changers are listed as "Type: Medium Changer" in /proc/scsi/scsi.
If you have such hardware and want to use it with linux, say Y
- here. Check <file:Documentation/scsi/scsi-changer.txt> for details.
+ here. Check <file:Documentation/scsi/scsi-changer.rst> for details.
If you want to compile this as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/kbuild/modules.rst> and
- <file:Documentation/scsi/scsi.txt>. The module will be called ch.o.
+ <file:Documentation/scsi/scsi.rst>. The module will be called ch.o.
If unsure, say N.
config SCSI_ENCLOSURE
@@ -177,7 +178,7 @@
config SCSI_LOGGING
bool "SCSI logging facility"
depends on SCSI
- ---help---
+ help
This turns on a logging facility that can be used to debug a number
of SCSI related problems.
@@ -375,14 +376,14 @@
depends on ISA && SCSI
select SCSI_SPI_ATTRS
select CHECK_SIGNATURE
- ---help---
+ help
This is a driver for the AHA-1510, AHA-1520, AHA-1522, and AHA-2825
SCSI host adapters. It also works for the AVA-1505, but the IRQ etc.
must be manually specified in this case.
It is explained in section 3.3 of the SCSI-HOWTO, available from
<http://www.tldp.org/docs.html#howto>. You might also want to
- read the file <file:Documentation/scsi/aha152x.txt>.
+ read the file <file:Documentation/scsi/aha152x.rst>.
To compile this driver as a module, choose M here: the
module will be called aha152x.
@@ -390,7 +391,7 @@
config SCSI_AHA1542
tristate "Adaptec AHA1542 support"
depends on ISA && SCSI && ISA_DMA_API
- ---help---
+ help
This is support for a SCSI host adapter. It is explained in section
3.4 of the SCSI-HOWTO, available from
<http://www.tldp.org/docs.html#howto>. Note that Trantor was
@@ -404,7 +405,7 @@
config SCSI_AHA1740
tristate "Adaptec AHA1740 support"
depends on EISA && SCSI
- ---help---
+ help
This is support for a SCSI host adapter. It is explained in section
3.5 of the SCSI-HOWTO, available from
<http://www.tldp.org/docs.html#howto>. If it doesn't work out
@@ -420,7 +421,7 @@
help
This driver supports a variety of Dell, HP, Adaptec, IBM and
ICP storage products. For a list of supported products, refer
- to <file:Documentation/scsi/aacraid.txt>.
+ to <file:Documentation/scsi/aacraid.rst>.
To compile this driver as a module, choose M here: the module
will be called aacraid.
@@ -447,7 +448,7 @@
help
This driver supports all of Adaptec's I2O based RAID controllers as
well as the DPT SmartRaid V cards. This is an Adaptec maintained
- driver by Deanna Bonds. See <file:Documentation/scsi/dpti.txt>.
+ driver by Deanna Bonds. See <file:Documentation/scsi/dpti.rst>.
To compile this driver as a module, choose M here: the
module will be called dpt_i2o.
@@ -497,12 +498,12 @@
config SCSI_BUSLOGIC
tristate "BusLogic SCSI support"
depends on (PCI || ISA) && SCSI && ISA_DMA_API && VIRT_TO_BUS
- ---help---
+ help
This is support for BusLogic MultiMaster and FlashPoint SCSI Host
Adapters. Consult the SCSI-HOWTO, available from
<http://www.tldp.org/docs.html#howto>, and the files
- <file:Documentation/scsi/BusLogic.txt> and
- <file:Documentation/scsi/FlashPoint.txt> for more information.
+ <file:Documentation/scsi/BusLogic.rst> and
+ <file:Documentation/scsi/FlashPoint.rst> for more information.
Note that support for FlashPoint is only available for 32-bit
x86 configurations.
@@ -579,20 +580,20 @@
tristate "LibFC module"
depends on SCSI_FC_ATTRS
select CRC32
- ---help---
+ help
Fibre Channel library module
config LIBFCOE
tristate "LibFCoE module"
depends on LIBFC
- ---help---
+ help
Library for Fibre Channel over Ethernet module
config FCOE
tristate "FCoE module"
depends on PCI
depends on LIBFCOE
- ---help---
+ help
Fibre Channel over Ethernet module
config FCOE_FNIC
@@ -603,7 +604,7 @@
This is support for the Cisco PCI-Express FCoE HBA.
To compile this driver as a module, choose M here and read
- <file:Documentation/scsi/scsi.txt>.
+ <file:Documentation/scsi/scsi.rst>.
The module will be called fnic.
config SCSI_SNIC
@@ -613,7 +614,7 @@
This is support for the Cisco PCI-Express SCSI HBA.
To compile this driver as a module, choose M here and read
- <file:Documentation/scsi/scsi.txt>.
+ <file:Documentation/scsi/scsi.rst>.
The module will be called snic.
config SCSI_SNIC_DEBUG_FS
@@ -671,7 +672,7 @@
config SCSI_GDTH
tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support"
depends on PCI && SCSI
- ---help---
+ help
Formerly called GDT SCSI Disk Array Controller Support.
This is a driver for RAID/SCSI Disk Array Controllers (EISA/ISA/PCI)
@@ -687,7 +688,7 @@
depends on PCI && SCSI
depends on X86
select SCSI_SAS_LIBSAS
- ---help---
+ help
This driver supports the 6Gb/s SAS capabilities of the storage
control unit found in the Intel(R) C600 series chipset.
@@ -695,7 +696,7 @@
tristate "Generic NCR5380/53c400 SCSI ISA card support"
depends on ISA && SCSI && HAS_IOPORT_MAP
select SCSI_SPI_ATTRS
- ---help---
+ help
This is a driver for old ISA card SCSI controllers based on a
NCR 5380, 53C80, 53C400, 53C400A, or DTC 436 device.
Most boards such as the Trantor T130 fit this category, as do
@@ -707,7 +708,7 @@
config SCSI_IPS
tristate "IBM ServeRAID support"
depends on PCI && SCSI
- ---help---
+ help
This is support for the IBM ServeRAID hardware RAID controllers.
See <http://www.developer.ibm.com/welcome/netfinity/serveraid.html>
and <http://www-947.ibm.com/support/entry/portal/docdisplay?brand=5000008&lndocid=SERV-RAID>
@@ -789,7 +790,7 @@
config SCSI_PPA
tristate "IOMEGA parallel port (ppa - older drives)"
depends on SCSI && PARPORT_PC
- ---help---
+ help
This driver supports older versions of IOMEGA's parallel port ZIP
drive (a 100 MB removable media device).
@@ -803,7 +804,7 @@
newer drives)", below.
For more information about this driver and how to use it you should
- read the file <file:Documentation/scsi/ppa.txt>. You should also read
+ read the file <file:Documentation/scsi/ppa.rst>. You should also read
the SCSI-HOWTO, which is available from
<http://www.tldp.org/docs.html#howto>. If you use this driver,
you will still be able to use the parallel port for other tasks,
@@ -816,7 +817,7 @@
config SCSI_IMM
tristate "IOMEGA parallel port (imm - newer drives)"
depends on SCSI && PARPORT_PC
- ---help---
+ help
This driver supports newer versions of IOMEGA's parallel port ZIP
drive (a 100 MB removable media device).
@@ -830,7 +831,7 @@
here and Y to "IOMEGA Parallel Port (ppa - older drives)", above.
For more information about this driver and how to use it you should
- read the file <file:Documentation/scsi/ppa.txt>. You should also read
+ read the file <file:Documentation/scsi/ppa.rst>. You should also read
the SCSI-HOWTO, which is available from
<http://www.tldp.org/docs.html#howto>. If you use this driver,
you will still be able to use the parallel port for other tasks,
@@ -843,7 +844,7 @@
config SCSI_IZIP_EPP16
bool "ppa/imm option - Use slow (but safe) EPP-16"
depends on SCSI_PPA || SCSI_IMM
- ---help---
+ help
EPP (Enhanced Parallel Port) is a standard for parallel ports which
allows them to act as expansion buses that can handle up to 64
peripheral devices.
@@ -895,7 +896,7 @@
config SCSI_STEX
tristate "Promise SuperTrak EX Series support"
depends on PCI && SCSI
- ---help---
+ help
This driver supports Promise SuperTrak EX series storage controllers.
Promise provides Linux RAID configuration utility for these
@@ -913,21 +914,21 @@
tristate "SYM53C8XX Version 2 SCSI support"
depends on PCI && SCSI
select SCSI_SPI_ATTRS
- ---help---
+ help
This driver supports the whole NCR53C8XX/SYM53C8XX family of
PCI-SCSI controllers. It also supports the subset of LSI53C10XX
Ultra-160 controllers that are based on the SYM53C8XX SCRIPTS
language. It does not support LSI53C10XX Ultra-320 PCI-X SCSI
controllers; you need to use the Fusion MPT driver for that.
- Please read <file:Documentation/scsi/sym53c8xx_2.txt> for more
+ Please read <file:Documentation/scsi/sym53c8xx_2.rst> for more
information.
config SCSI_SYM53C8XX_DMA_ADDRESSING_MODE
int "DMA addressing mode"
depends on SCSI_SYM53C8XX_2
default "1"
- ---help---
+ help
This option only applies to PCI-SCSI chips that are PCI DAC
capable (875A, 895A, 896, 1010-33, 1010-66, 1000).
@@ -979,10 +980,11 @@
config SCSI_IPR
tristate "IBM Power Linux RAID adapter support"
depends on PCI && SCSI && ATA
+ select SATA_HOST
select FW_LOADER
select IRQ_POLL
select SGL_ALLOC
- ---help---
+ help
This driver supports the IBM Power Linux family RAID adapters.
This includes IBM pSeries 5712, 5703, 5709, and 570A, as well
as IBM iSeries 5702, 5703, 5709, and 570A.
@@ -1020,7 +1022,7 @@
int "default tagged command queue depth"
depends on SCSI_ZALON
default "8"
- ---help---
+ help
"Tagged command queuing" is a feature of SCSI-2 which improves
performance: the host adapter can send several SCSI commands to a
device's queue even if previous commands haven't finished yet.
@@ -1046,7 +1048,7 @@
int "maximum number of queued commands"
depends on SCSI_ZALON
default "32"
- ---help---
+ help
This option allows you to specify the maximum number of commands
that can be queued to any device, when tagged command queuing is
possible. The default value is 32. Minimum is 2, maximum is 64.
@@ -1063,7 +1065,7 @@
int "synchronous transfers frequency in MHz"
depends on SCSI_ZALON
default "20"
- ---help---
+ help
The SCSI Parallel Interface-2 Standard defines 5 classes of transfer
rates: FAST-5, FAST-10, FAST-20, FAST-40 and FAST-80. The numbers
are respectively the maximum data transfer rates in mega-transfers
@@ -1106,7 +1108,7 @@
config SCSI_QLOGIC_FAS
tristate "Qlogic FAS SCSI support"
depends on ISA && SCSI
- ---help---
+ help
This is a driver for the ISA, VLB, and PCMCIA versions of the Qlogic
FastSCSI! cards as well as any other card based on the FASXX chip
(including the Control Concepts SCSI/IDE/SIO/PIO/FDC cards).
@@ -1116,7 +1118,7 @@
SCSI support"), below.
Information about this driver is contained in
- <file:Documentation/scsi/qlogicfas.txt>. You should also read the
+ <file:Documentation/scsi/qlogicfas.rst>. You should also read the
SCSI-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
@@ -1152,18 +1154,19 @@
config SCSI_LPFC
tristate "Emulex LightPulse Fibre Channel Support"
depends on PCI && SCSI
+ depends on CPU_FREQ
depends on SCSI_FC_ATTRS
depends on NVME_TARGET_FC || NVME_TARGET_FC=n
depends on NVME_FC || NVME_FC=n
select CRC_T10DIF
- ---help---
+ help
This lpfc driver supports the Emulex LightPulse
Family of Fibre Channel PCI host adapters.
config SCSI_LPFC_DEBUG_FS
bool "Emulex LightPulse Fibre Channel debugfs Support"
depends on SCSI_LPFC && DEBUG_FS
- ---help---
+ help
This makes debugging information from the lpfc driver
available via the debugfs filesystem.
@@ -1171,7 +1174,7 @@
tristate "Simple 53c710 SCSI support (Compaq, NCR machines)"
depends on EISA && SCSI
select SCSI_SPI_ATTRS
- ---help---
+ help
This driver is for NCR53c710 based SCSI host adapters.
It currently supports Compaq EISA cards.
@@ -1179,14 +1182,14 @@
config SCSI_DC395x
tristate "Tekram DC395(U/UW/F) and DC315(U) SCSI support"
depends on PCI && SCSI
- ---help---
+ help
This driver supports PCI SCSI host adapters based on the ASIC
TRM-S1040 chip, e.g Tekram DC395(U/UW/F) and DC315(U) variants.
This driver works, but is still in experimental status. So better
have a bootable disk and a backup in case of emergency.
- Documentation can be found in <file:Documentation/scsi/dc395x.txt>.
+ Documentation can be found in <file:Documentation/scsi/dc395x.rst>.
To compile this driver as a module, choose M here: the
module will be called dc395x.
@@ -1195,7 +1198,7 @@
tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)"
depends on PCI && SCSI
select SCSI_SPI_ATTRS
- ---help---
+ help
This driver supports PCI SCSI host adapters based on the Am53C974A
chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
PCscsi/PCnet (Am53/79C974) solutions.
@@ -1222,7 +1225,7 @@
tristate "Western Digital WD7193/7197/7296 support"
depends on PCI && SCSI
select EEPROM_93CX6
- ---help---
+ help
This is a driver for Western Digital WD7193, WD7197 and WD7296 PCI
SCSI controllers (based on WD33C296A chip).
@@ -1316,7 +1319,7 @@
config GVP11_SCSI
tristate "GVP Series II WD33C93A support"
depends on ZORRO && SCSI
- ---help---
+ help
If you have a Great Valley Products Series II SCSI controller,
answer Y. Also say Y if you have a later model of GVP SCSI
controller (such as the GVP A4008 or a Combo board). Otherwise,
@@ -1372,7 +1375,7 @@
tristate "Atari native SCSI support"
depends on ATARI && SCSI
select SCSI_SPI_ATTRS
- ---help---
+ help
If you have an Atari with built-in NCR5380 SCSI controller (TT,
Falcon, ...) say Y to get it supported. Of course also, if you have
a compatible SCSI controller (e.g. for Medusa).
@@ -1467,14 +1470,19 @@
module will be called sun_esp.
config ZFCP
- tristate "FCP host bus adapter driver for IBM eServer zSeries"
+ tristate "FCP host bus adapter driver for IBM mainframes"
depends on S390 && QDIO && SCSI
depends on SCSI_FC_ATTRS
help
- If you want to access SCSI devices attached to your IBM eServer
- zSeries by means of Fibre Channel interfaces say Y.
- For details please refer to the documentation provided by IBM at
- <http://oss.software.ibm.com/developerworks/opensource/linux390>
+ If you want to access SCSI devices attached to your IBM mainframe by
+ means of Fibre Channel Protocol host bus adapters say Y.
+
+ Supported HBAs include different models of the FICON Express and FCP
+ Express I/O cards.
+
+ For a more complete list, and for more details about setup and
+ operation refer to the IBM publication "Device Drivers, Features, and
+ Commands", SC33-8411.
This driver is also available as a module. This module will be
called zfcp. If you want to compile it as a module, say M here
@@ -1484,7 +1492,7 @@
tristate "PMC SIERRA Linux MaxRAID adapter support"
depends on PCI && SCSI && NET
select SGL_ALLOC
- ---help---
+ help
This driver supports the PMC SIERRA MaxRAID adapters.
config SCSI_PM8001
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index d4401c7..d654a6c 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -175,6 +175,19 @@
}
}
+static inline void set_resid_from_SCp(struct scsi_cmnd *cmd)
+{
+ int resid = cmd->SCp.this_residual;
+ struct scatterlist *s = cmd->SCp.buffer;
+
+ if (s)
+ while (!sg_is_last(s)) {
+ s = sg_next(s);
+ resid += s->length;
+ }
+ scsi_set_resid(cmd, resid);
+}
+
/**
* NCR5380_poll_politely2 - wait for two chip register values
* @hostdata: host private data
@@ -1383,7 +1396,7 @@
* MESSAGE OUT phase and sending an ABORT message.
* @instance: relevant scsi host instance
*
- * Returns 0 on success, -1 on failure.
+ * Returns 0 on success, negative error code on failure.
*/
static int do_abort(struct Scsi_Host *instance)
@@ -1408,7 +1421,7 @@
rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ);
if (rc < 0)
- goto timeout;
+ goto out;
tmp = NCR5380_read(STATUS_REG) & PHASE_MASK;
@@ -1419,7 +1432,7 @@
ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, 0, 3 * HZ);
if (rc < 0)
- goto timeout;
+ goto out;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
}
@@ -1428,17 +1441,17 @@
len = 1;
phase = PHASE_MSGOUT;
NCR5380_transfer_pio(instance, &phase, &len, &msgptr);
+ if (len)
+ rc = -ENXIO;
/*
* If we got here, and the command completed successfully,
* we're about to go into bus free state.
*/
- return len ? -1 : 0;
-
-timeout:
+out:
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- return -1;
+ return rc;
}
/*
@@ -1807,6 +1820,8 @@
cmd->result |= cmd->SCp.Status;
cmd->result |= cmd->SCp.Message << 8;
+ set_resid_from_SCp(cmd);
+
if (cmd->cmnd[0] == REQUEST_SENSE)
complete_cmd(instance, cmd);
else {
@@ -1928,7 +1943,7 @@
return;
/* Reject message */
- /* Fall through */
+ fallthrough;
default:
/*
* If we get something weird that we aren't expecting,
@@ -2268,7 +2283,7 @@
dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd);
hostdata->connected = NULL;
hostdata->dma_len = 0;
- if (do_abort(instance)) {
+ if (do_abort(instance) < 0) {
set_host_byte(cmd, DID_ERROR);
complete_cmd(instance, cmd);
result = FAILED;
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index 564b354..5853db3 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -9,7 +9,6 @@
#include <linux/module.h>
#include <asm/page.h>
-#include <asm/pgtable.h>
#include <asm/amigaints.h>
#include <asm/amigahw.h>
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index 222c77c..86f1da2 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -10,7 +10,6 @@
#include <linux/module.h>
#include <asm/page.h>
-#include <asm/pgtable.h>
#include <asm/amigaints.h>
#include <asm/amigahw.h>
@@ -39,7 +38,7 @@
spin_unlock_irqrestore(instance->host_lock, flags);
return IRQ_HANDLED;
}
- pr_warning("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status);
+ pr_warn("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status);
return IRQ_NONE;
}
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 2388143..31233f6 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -242,7 +242,7 @@
int startup_timeout = 180;
int aif_timeout = 120;
int aac_sync_mode; /* Only Sync. transfer - disabled */
-int aac_convert_sgl = 1; /* convert non-conformable s/g list - enabled */
+static int aac_convert_sgl = 1; /* convert non-conformable s/g list - enabled */
module_param(aac_sync_mode, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(aac_sync_mode, "Force sync. transfer mode"
@@ -290,7 +290,7 @@
" blocks (FIB) allocated. Valid values are 512 and down. Default is"
" to use suggestion from Firmware.");
-int acbsize = -1;
+static int acbsize = -1;
module_param(acbsize, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB)"
" size. Valid values are 512, 2048, 4096 and 8192. Default is to use"
@@ -321,7 +321,7 @@
module_param_named(reset_devices, aac_reset_devices, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(reset_devices, "Force an adapter reset at initialization.");
-int aac_wwn = 1;
+static int aac_wwn = 1;
module_param_named(wwn, aac_wwn, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(wwn, "Select a WWN type for the arrays:\n"
"\t0 - Disable\n"
@@ -350,7 +350,8 @@
/**
* aac_get_config_status - check the adapter configuration
- * @common: adapter to query
+ * @dev: aac driver data
+ * @commit_flag: force sending CT_COMMIT_CONFIG
*
* Query config status, and commit the configuration if needed.
*/
@@ -442,7 +443,7 @@
/**
* aac_get_containers - list containers
- * @common: adapter to probe
+ * @dev: aac driver data
*
* Make a list of all containers on this controller
*/
@@ -535,7 +536,7 @@
if ((le32_to_cpu(get_name_reply->status) == CT_OK)
&& (get_name_reply->data[0] != '\0')) {
char *sp = get_name_reply->data;
- int data_size = FIELD_SIZEOF(struct aac_get_name_resp, data);
+ int data_size = sizeof_field(struct aac_get_name_resp, data);
sp[data_size - 1] = '\0';
while (*sp == ' ')
@@ -561,7 +562,7 @@
scsicmd->scsi_done(scsicmd);
}
-/**
+/*
* aac_get_container_name - get container name, none blocking.
*/
static int aac_get_container_name(struct scsi_cmnd * scsicmd)
@@ -574,7 +575,7 @@
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
- data_size = FIELD_SIZEOF(struct aac_get_name_resp, data);
+ data_size = sizeof_field(struct aac_get_name_resp, data);
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
@@ -786,8 +787,7 @@
/**
* aac_probe_container - query a logical volume
- * @dev: device to query
- * @cid: container identifier
+ * @scsicmd: the scsi command block
*
* Queries the controller about the given volume. The volume information
* is updated in the struct fsa_dev_info structure rather than returned.
@@ -798,6 +798,11 @@
return 0;
}
+static void aac_probe_container_scsi_done(struct scsi_cmnd *scsi_cmnd)
+{
+ aac_probe_container_callback1(scsi_cmnd);
+}
+
int aac_probe_container(struct aac_dev *dev, int cid)
{
struct scsi_cmnd *scsicmd = kmalloc(sizeof(*scsicmd), GFP_KERNEL);
@@ -809,8 +814,7 @@
kfree(scsidev);
return -ENOMEM;
}
- scsicmd->list.next = NULL;
- scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))aac_probe_container_callback1;
+ scsicmd->scsi_done = aac_probe_container_scsi_done;
scsicmd->device = scsidev;
scsidev->sdev_state = 0;
@@ -1094,7 +1098,7 @@
scsicmd->scsi_done(scsicmd);
}
-/**
+/*
* aac_get_container_serial - get container serial, none blocking.
*/
static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
@@ -1477,6 +1481,7 @@
struct aac_srb * srbcmd;
u32 flag;
u32 timeout;
+ struct aac_dev *dev = fib->dev;
aac_fib_init(fib);
switch(cmd->sc_data_direction){
@@ -1503,7 +1508,7 @@
srbcmd->flags = cpu_to_le32(flag);
timeout = cmd->request->timeout/HZ;
if (timeout == 0)
- timeout = 1;
+ timeout = (dev->sa_firmware ? AAC_SA_TIMEOUT : AAC_ARC_TIMEOUT);
srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds
srbcmd->retry_limit = 0; /* Obsolete parameter */
srbcmd->cdb_size = cpu_to_le32(cmd->cmd_len);
@@ -1947,8 +1952,6 @@
/**
* aac_set_safw_attr_all_targets- update current hba map with data from FW
* @dev: aac_dev structure
- * @phys_luns: FW information from report phys luns
- * @rescan: Indicates scan type
*
* Update our hba map with the information gathered from the FW
*/
@@ -2226,10 +2229,10 @@
}
if (dev->dac_support) {
- if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(64))) {
+ if (!dma_set_mask(&dev->pdev->dev, DMA_BIT_MASK(64))) {
if (!dev->in_reset)
dev_info(&dev->pdev->dev, "64 Bit DAC enabled\n");
- } else if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(32))) {
+ } else if (!dma_set_mask(&dev->pdev->dev, DMA_BIT_MASK(32))) {
dev_info(&dev->pdev->dev, "DMA mask set failed, 64 Bit DAC disabled\n");
dev->dac_support = 0;
} else {
@@ -2600,9 +2603,7 @@
static void synchronize_callback(void *context, struct fib *fibptr)
{
struct aac_synchronize_reply *synchronizereply;
- struct scsi_cmnd *cmd;
-
- cmd = context;
+ struct scsi_cmnd *cmd = context;
if (!aac_valid_context(cmd, fibptr))
return;
@@ -2643,77 +2644,8 @@
int status;
struct fib *cmd_fibcontext;
struct aac_synchronize *synchronizecmd;
- struct scsi_cmnd *cmd;
struct scsi_device *sdev = scsicmd->device;
- int active = 0;
struct aac_dev *aac;
- u64 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) |
- (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
- u32 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
- unsigned long flags;
-
- /*
- * Wait for all outstanding queued commands to complete to this
- * specific target (block).
- */
- spin_lock_irqsave(&sdev->list_lock, flags);
- list_for_each_entry(cmd, &sdev->cmd_list, list)
- if (cmd->SCp.phase == AAC_OWNER_FIRMWARE) {
- u64 cmnd_lba;
- u32 cmnd_count;
-
- if (cmd->cmnd[0] == WRITE_6) {
- cmnd_lba = ((cmd->cmnd[1] & 0x1F) << 16) |
- (cmd->cmnd[2] << 8) |
- cmd->cmnd[3];
- cmnd_count = cmd->cmnd[4];
- if (cmnd_count == 0)
- cmnd_count = 256;
- } else if (cmd->cmnd[0] == WRITE_16) {
- cmnd_lba = ((u64)cmd->cmnd[2] << 56) |
- ((u64)cmd->cmnd[3] << 48) |
- ((u64)cmd->cmnd[4] << 40) |
- ((u64)cmd->cmnd[5] << 32) |
- ((u64)cmd->cmnd[6] << 24) |
- (cmd->cmnd[7] << 16) |
- (cmd->cmnd[8] << 8) |
- cmd->cmnd[9];
- cmnd_count = (cmd->cmnd[10] << 24) |
- (cmd->cmnd[11] << 16) |
- (cmd->cmnd[12] << 8) |
- cmd->cmnd[13];
- } else if (cmd->cmnd[0] == WRITE_12) {
- cmnd_lba = ((u64)cmd->cmnd[2] << 24) |
- (cmd->cmnd[3] << 16) |
- (cmd->cmnd[4] << 8) |
- cmd->cmnd[5];
- cmnd_count = (cmd->cmnd[6] << 24) |
- (cmd->cmnd[7] << 16) |
- (cmd->cmnd[8] << 8) |
- cmd->cmnd[9];
- } else if (cmd->cmnd[0] == WRITE_10) {
- cmnd_lba = ((u64)cmd->cmnd[2] << 24) |
- (cmd->cmnd[3] << 16) |
- (cmd->cmnd[4] << 8) |
- cmd->cmnd[5];
- cmnd_count = (cmd->cmnd[7] << 8) |
- cmd->cmnd[8];
- } else
- continue;
- if (((cmnd_lba + cmnd_count) < lba) ||
- (count && ((lba + count) < cmnd_lba)))
- continue;
- ++active;
- break;
- }
-
- spin_unlock_irqrestore(&sdev->list_lock, flags);
-
- /*
- * Yield the processor (requeue for later)
- */
- if (active)
- return SCSI_MLQUEUE_DEVICE_BUSY;
aac = (struct aac_dev *)sdev->host->hostdata;
if (aac->in_reset)
@@ -2722,8 +2654,7 @@
/*
* Allocate and initialize a Fib
*/
- if (!(cmd_fibcontext = aac_fib_alloc(aac)))
- return SCSI_MLQUEUE_HOST_BUSY;
+ cmd_fibcontext = aac_fib_alloc_tag(aac, scsicmd);
aac_fib_init(cmd_fibcontext);
@@ -2878,7 +2809,7 @@
!(dev->raw_io_64) ||
((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
break;
- /* fall through */
+ fallthrough;
case INQUIRY:
case READ_CAPACITY:
case TEST_UNIT_READY:
@@ -2953,7 +2884,7 @@
/* Issue FIB to tell Firmware to flush it's cache */
if ((aac_cache & 6) != 2)
return aac_synchronize(scsicmd);
- /* fall through */
+ fallthrough;
case INQUIRY:
{
struct inquiry_data inq_data;
@@ -3309,7 +3240,7 @@
SCSI_SENSE_BUFFERSIZE));
break;
}
- /* fall through */
+ fallthrough;
case RESERVE:
case RELEASE:
case REZERO_UNIT:
@@ -3322,7 +3253,6 @@
case START_STOP:
return aac_start_stop(scsicmd);
- /* FALLTHRU */
default:
/*
* Unhandled commands
@@ -3458,15 +3388,12 @@
}
/**
- *
* aac_srb_callback
* @context: the context set in the fib - here it is scsi cmd
* @fibptr: pointer to the fib
*
* Handles the completion of a scsi command to a non dasd device
- *
*/
-
static void aac_srb_callback(void *context, struct fib * fibptr)
{
struct aac_srb_reply *srbreply;
@@ -3751,13 +3678,11 @@
}
/**
- *
* aac_hba_callback
* @context: the context set in the fib - here it is scsi cmd
* @fibptr: pointer to the fib
*
* Handles the completion of a native HBA scsi command
- *
*/
void aac_hba_callback(void *context, struct fib *fibptr)
{
@@ -3816,14 +3741,12 @@
}
/**
- *
* aac_send_srb_fib
* @scsicmd: the scsi command block
*
* This routine will form a FIB and fill in the aac_srb from the
* scsicmd passed in.
*/
-
static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
{
struct fib* cmd_fibcontext;
@@ -3859,7 +3782,6 @@
}
/**
- *
* aac_send_hba_fib
* @scsicmd: the scsi command block
*
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 3fa0323..e3e4ecb 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -85,7 +85,7 @@
#define PMC_GLOBAL_INT_BIT0 0x00000001
#ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 50877
+# define AAC_DRIVER_BUILD 50983
# define AAC_DRIVER_BRANCH "-custom"
#endif
#define MAXIMUM_NUM_CONTAINERS 32
@@ -108,6 +108,8 @@
#define AAC_BUS_TARGET_LOOP (AAC_MAX_BUSES * AAC_MAX_TARGETS)
#define AAC_MAX_NATIVE_SIZE 2048
#define FW_ERROR_BUFFER_SIZE 512
+#define AAC_SA_TIMEOUT 180
+#define AAC_ARC_TIMEOUT 60
#define get_bus_number(x) (x/AAC_MAX_TARGETS)
#define get_target_number(x) (x%AAC_MAX_TARGETS)
@@ -1328,7 +1330,7 @@
#define AAC_DEVTYPE_ARC_RAW 2
#define AAC_DEVTYPE_NATIVE_RAW 3
-#define AAC_SAFW_RESCAN_DELAY (10 * HZ)
+#define AAC_RESCAN_DELAY (10 * HZ)
struct aac_hba_map_info {
__le32 rmw_nexus; /* nexus for native HBA devices */
@@ -1601,6 +1603,7 @@
struct fsa_dev_info *fsa_dev;
struct task_struct *thread;
struct delayed_work safw_rescan_work;
+ struct delayed_work src_reinit_aif_worker;
int cardtype;
/*
*This lock will protect the two 32-bit
@@ -1673,6 +1676,7 @@
u8 adapter_shutdown;
u32 handle_pci_error;
bool init_reset;
+ u8 soft_reset_support;
};
#define aac_adapter_interrupt(dev) \
@@ -2644,7 +2648,12 @@
static inline void aac_schedule_safw_scan_worker(struct aac_dev *dev)
{
- schedule_delayed_work(&dev->safw_rescan_work, AAC_SAFW_RESCAN_DELAY);
+ schedule_delayed_work(&dev->safw_rescan_work, AAC_RESCAN_DELAY);
+}
+
+static inline void aac_schedule_src_reinit_aif_worker(struct aac_dev *dev)
+{
+ schedule_delayed_work(&dev->src_reinit_aif_worker, AAC_RESCAN_DELAY);
}
static inline void aac_safw_rescan_worker(struct work_struct *work)
@@ -2658,10 +2667,10 @@
aac_scan_host(dev);
}
-static inline void aac_cancel_safw_rescan_worker(struct aac_dev *dev)
+static inline void aac_cancel_rescan_worker(struct aac_dev *dev)
{
- if (dev->sa_firmware)
- cancel_delayed_work_sync(&dev->safw_rescan_work);
+ cancel_delayed_work_sync(&dev->safw_rescan_work);
+ cancel_delayed_work_sync(&dev->src_reinit_aif_worker);
}
/* SCp.phase values */
@@ -2671,6 +2680,7 @@
#define AAC_OWNER_FIRMWARE 0x106
void aac_safw_rescan_worker(struct work_struct *work);
+void aac_src_reinit_aif_worker(struct work_struct *work);
int aac_acquire_irq(struct aac_dev *dev);
void aac_free_irq(struct aac_dev *dev);
int aac_setup_safw_adapter(struct aac_dev *dev);
@@ -2728,6 +2738,7 @@
int _aac_rx_init(struct aac_dev *dev);
int aac_rx_select_comm(struct aac_dev *dev, int comm);
int aac_rx_deliver_producer(struct fib * fib);
+void aac_reinit_aif(struct aac_dev *aac, unsigned int index);
static inline int aac_is_src(struct aac_dev *dev)
{
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index ffe41bc..1b1da16 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -25,6 +25,7 @@
#include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/blkdev.h>
+#include <linux/compat.h>
#include <linux/delay.h> /* ssleep prototype */
#include <linux/kthread.h>
#include <linux/uaccess.h>
@@ -32,6 +33,8 @@
#include "aacraid.h"
+# define AAC_DEBUG_PREAMBLE KERN_INFO
+# define AAC_DEBUG_POSTAMBLE
/**
* ioctl_send_fib - send a FIB from userspace
* @dev: adapter is being processed
@@ -40,9 +43,6 @@
* This routine sends a fib to the adapter on behalf of a user level
* program.
*/
-# define AAC_DEBUG_PREAMBLE KERN_INFO
-# define AAC_DEBUG_POSTAMBLE
-
static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
{
struct hw_fib * kfib;
@@ -158,11 +158,12 @@
/**
* open_getadapter_fib - Get the next fib
+ * @dev: adapter is being processed
+ * @arg: arguments to the open call
*
* This routine will get the next Fib, if available, from the AdapterFibContext
* passed in from the user.
*/
-
static int open_getadapter_fib(struct aac_dev * dev, void __user *arg)
{
struct aac_fib_context * fibctx;
@@ -226,6 +227,12 @@
return status;
}
+struct compat_fib_ioctl {
+ u32 fibctx;
+ s32 wait;
+ compat_uptr_t fib;
+};
+
/**
* next_getadapter_fib - get the next fib
* @dev: adapter to use
@@ -234,7 +241,6 @@
* This routine will get the next Fib, if available, from the AdapterFibContext
* passed in from the user.
*/
-
static int next_getadapter_fib(struct aac_dev * dev, void __user *arg)
{
struct fib_ioctl f;
@@ -244,8 +250,19 @@
struct list_head * entry;
unsigned long flags;
- if(copy_from_user((void *)&f, arg, sizeof(struct fib_ioctl)))
- return -EFAULT;
+ if (in_compat_syscall()) {
+ struct compat_fib_ioctl cf;
+
+ if (copy_from_user(&cf, arg, sizeof(struct compat_fib_ioctl)))
+ return -EFAULT;
+
+ f.fibctx = cf.fibctx;
+ f.wait = cf.wait;
+ f.fib = compat_ptr(cf.fib);
+ } else {
+ if (copy_from_user(&f, arg, sizeof(struct fib_ioctl)))
+ return -EFAULT;
+ }
/*
* Verify that the HANDLE passed in was a valid AdapterFibContext
*
@@ -455,11 +472,10 @@
/**
- *
* aac_send_raw_scb
- *
+ * @dev: adapter is being processed
+ * @arg: arguments to the send call
*/
-
static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
{
struct fib* srbfib;
@@ -513,15 +529,10 @@
goto cleanup;
}
- user_srbcmd = kmalloc(fibsize, GFP_KERNEL);
- if (!user_srbcmd) {
- dprintk((KERN_DEBUG"aacraid: Could not make a copy of the srb\n"));
- rcode = -ENOMEM;
- goto cleanup;
- }
- if(copy_from_user(user_srbcmd, user_srb,fibsize)){
- dprintk((KERN_DEBUG"aacraid: Could not copy srb from user\n"));
- rcode = -EFAULT;
+ user_srbcmd = memdup_user(user_srb, fibsize);
+ if (IS_ERR(user_srbcmd)) {
+ rcode = PTR_ERR(user_srbcmd);
+ user_srbcmd = NULL;
goto cleanup;
}
@@ -677,8 +688,8 @@
goto cleanup;
}
}
- addr = pci_map_single(dev->pdev, p, sg_count[i],
- data_dir);
+ addr = dma_map_single(&dev->pdev->dev, p, sg_count[i],
+ data_dir);
hbacmd->sge[i].addr_hi = cpu_to_le32((u32)(addr>>32));
hbacmd->sge[i].addr_lo = cpu_to_le32(
(u32)(addr & 0xffffffff));
@@ -739,8 +750,8 @@
goto cleanup;
}
}
- addr = pci_map_single(dev->pdev, p,
- sg_count[i], data_dir);
+ addr = dma_map_single(&dev->pdev->dev, p,
+ sg_count[i], data_dir);
psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
@@ -795,8 +806,8 @@
goto cleanup;
}
}
- addr = pci_map_single(dev->pdev, p,
- sg_count[i], data_dir);
+ addr = dma_map_single(&dev->pdev->dev, p,
+ sg_count[i], data_dir);
psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
@@ -851,7 +862,9 @@
goto cleanup;
}
}
- addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
+ addr = dma_map_single(&dev->pdev->dev, p,
+ usg->sg[i].count,
+ data_dir);
psg->sg[i].addr = cpu_to_le32(addr & 0xffffffff);
byte_count += usg->sg[i].count;
@@ -890,8 +903,8 @@
goto cleanup;
}
}
- addr = pci_map_single(dev->pdev, p,
- sg_count[i], data_dir);
+ addr = dma_map_single(&dev->pdev->dev, p,
+ sg_count[i], data_dir);
psg->sg[i].addr = cpu_to_le32(addr);
byte_count += sg_count[i];
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index d4fcfa1..355b16f 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -272,36 +272,35 @@
q->entries = qsize;
}
+static bool wait_for_io_iter(struct scsi_cmnd *cmd, void *data, bool rsvd)
+{
+ int *active = data;
+
+ if (cmd->SCp.phase == AAC_OWNER_FIRMWARE)
+ *active = *active + 1;
+ return true;
+}
static void aac_wait_for_io_completion(struct aac_dev *aac)
{
- unsigned long flagv = 0;
- int i = 0;
+ int i = 0, active;
for (i = 60; i; --i) {
- struct scsi_device *dev;
- struct scsi_cmnd *command;
- int active = 0;
- __shost_for_each_device(dev, aac->scsi_host_ptr) {
- spin_lock_irqsave(&dev->list_lock, flagv);
- list_for_each_entry(command, &dev->cmd_list, list) {
- if (command->SCp.phase == AAC_OWNER_FIRMWARE) {
- active++;
- break;
- }
- }
- spin_unlock_irqrestore(&dev->list_lock, flagv);
- if (active)
- break;
-
- }
+ active = 0;
+ scsi_host_busy_iter(aac->scsi_host_ptr,
+ wait_for_io_iter, &active);
/*
* We can exit If all the commands are complete
*/
if (active == 0)
break;
+ dev_info(&aac->pdev->dev,
+ "Wait for %d commands to complete\n", active);
ssleep(1);
}
+ if (active)
+ dev_err(&aac->pdev->dev,
+ "%d outstanding commands during shutdown\n", active);
}
/**
@@ -571,6 +570,11 @@
else
dev->sa_firmware = 0;
+ if (status[4] & le32_to_cpu(AAC_EXTOPT_SOFT_RESET))
+ dev->soft_reset_support = 1;
+ else
+ dev->soft_reset_support = 0;
+
if ((dev->comm_interface == AAC_COMM_MESSAGE) &&
(status[2] > dev->base_size)) {
aac_adapter_ioremap(dev, 0);
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 90fb17c..b99ca1b 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -214,6 +214,7 @@
/**
* aac_fib_alloc_tag-allocate a fib using tags
* @dev: Adapter to allocate the fib for
+ * @scmd: SCSI command
*
* Allocate a fib from the adapter fib pool using tags
* from the blk layer.
@@ -232,6 +233,7 @@
fibptr->type = FSAFS_NTC_FIB_CONTEXT;
fibptr->callback_data = NULL;
fibptr->callback = NULL;
+ fibptr->flags = 0;
return fibptr;
}
@@ -404,8 +406,8 @@
* aac_queue_get - get the next free QE
* @dev: Adapter
* @index: Returned index
- * @priority: Priority of fib
- * @fib: Fib to associate with the queue entry
+ * @qid: Queue number
+ * @hw_fib: Fib to associate with the queue entry
* @wait: Wait if queue full
* @fibptr: Driver fib object to go with fib
* @nonotify: Don't notify the adapter
@@ -933,7 +935,7 @@
/**
* aac_fib_complete - fib completion handler
- * @fib: FIB to complete
+ * @fibptr: FIB to complete
*
* Will do all necessary work to complete a FIB.
*/
@@ -1048,6 +1050,7 @@
}
}
+#define AIF_SNIFF_TIMEOUT (500*HZ)
/**
* aac_handle_aif - Handle a message from the firmware
* @dev: Which adapter this fib is from
@@ -1056,8 +1059,6 @@
* This routine handles a driver notify fib from the adapter and
* dispatches it to the appropriate routine for handling.
*/
-
-#define AIF_SNIFF_TIMEOUT (500*HZ)
static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
{
struct hw_fib * hw_fib = fibptr->hw_fib_va;
@@ -1430,7 +1431,7 @@
"enclosure services event");
scsi_device_set_state(device, SDEV_RUNNING);
}
- /* FALLTHRU */
+ fallthrough;
case CHANGE:
if ((channel == CONTAINER_CHANNEL)
&& (!dev->fsa_dev[container].valid)) {
@@ -1463,14 +1464,19 @@
}
}
+static void aac_schedule_bus_scan(struct aac_dev *aac)
+{
+ if (aac->sa_firmware)
+ aac_schedule_safw_scan_worker(aac);
+ else
+ aac_schedule_src_reinit_aif_worker(aac);
+}
+
static int _aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type)
{
int index, quirks;
int retval;
- struct Scsi_Host *host;
- struct scsi_device *dev;
- struct scsi_cmnd *command;
- struct scsi_cmnd *command_list;
+ struct Scsi_Host *host = aac->scsi_host_ptr;
int jafo = 0;
int bled;
u64 dmamask;
@@ -1486,8 +1492,6 @@
* - The card is dead, or will be very shortly ;-/ so no new
* commands are completing in the interrupt service.
*/
- host = aac->scsi_host_ptr;
- scsi_block_requests(host);
aac_adapter_disable_int(aac);
if (aac->thread && aac->thread->pid != current->pid) {
spin_unlock_irq(host->host_lock);
@@ -1547,6 +1551,7 @@
aac_fib_map_free(aac);
dma_free_coherent(&aac->pdev->dev, aac->comm_size, aac->comm_addr,
aac->comm_phys);
+ aac_adapter_ioremap(aac, 0);
aac->comm_addr = NULL;
aac->comm_phys = 0;
kfree(aac->queues);
@@ -1557,15 +1562,15 @@
dmamask = DMA_BIT_MASK(32);
quirks = aac_get_driver_ident(index)->quirks;
if (quirks & AAC_QUIRK_31BIT)
- retval = pci_set_dma_mask(aac->pdev, dmamask);
+ retval = dma_set_mask(&aac->pdev->dev, dmamask);
else if (!(quirks & AAC_QUIRK_SRC))
- retval = pci_set_dma_mask(aac->pdev, dmamask);
+ retval = dma_set_mask(&aac->pdev->dev, dmamask);
else
- retval = pci_set_consistent_dma_mask(aac->pdev, dmamask);
+ retval = dma_set_coherent_mask(&aac->pdev->dev, dmamask);
if (quirks & AAC_QUIRK_31BIT && !retval) {
dmamask = DMA_BIT_MASK(31);
- retval = pci_set_consistent_dma_mask(aac->pdev, dmamask);
+ retval = dma_set_coherent_mask(&aac->pdev->dev, dmamask);
}
if (retval)
@@ -1598,39 +1603,11 @@
* This is where the assumption that the Adapter is quiesced
* is important.
*/
- command_list = NULL;
- __shost_for_each_device(dev, host) {
- unsigned long flags;
- spin_lock_irqsave(&dev->list_lock, flags);
- list_for_each_entry(command, &dev->cmd_list, list)
- if (command->SCp.phase == AAC_OWNER_FIRMWARE) {
- command->SCp.buffer = (struct scatterlist *)command_list;
- command_list = command;
- }
- spin_unlock_irqrestore(&dev->list_lock, flags);
- }
- while ((command = command_list)) {
- command_list = (struct scsi_cmnd *)command->SCp.buffer;
- command->SCp.buffer = NULL;
- command->result = DID_OK << 16
- | COMMAND_COMPLETE << 8
- | SAM_STAT_TASK_SET_FULL;
- command->SCp.phase = AAC_OWNER_ERROR_HANDLER;
- command->scsi_done(command);
- }
- /*
- * Any Device that was already marked offline needs to be marked
- * running
- */
- __shost_for_each_device(dev, host) {
- if (!scsi_device_online(dev))
- scsi_device_set_state(dev, SDEV_RUNNING);
- }
- retval = 0;
+ scsi_host_complete_all_commands(host, DID_RESET);
+ retval = 0;
out:
aac->in_reset = 0;
- scsi_unblock_requests(host);
/*
* Issue bus rescan to catch any configuration that might have
@@ -1638,7 +1615,7 @@
*/
if (!retval && !is_kdump_kernel()) {
dev_info(&aac->pdev->dev, "Scheduling bus rescan\n");
- aac_schedule_safw_scan_worker(aac);
+ aac_schedule_bus_scan(aac);
}
if (jafo) {
@@ -1650,8 +1627,8 @@
int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type)
{
unsigned long flagv = 0;
- int retval;
- struct Scsi_Host * host;
+ int retval, unblock_retval;
+ struct Scsi_Host *host = aac->scsi_host_ptr;
int bled;
if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0)
@@ -1669,8 +1646,7 @@
* target (block maximum 60 seconds). Although not necessary,
* it does make us a good storage citizen.
*/
- host = aac->scsi_host_ptr;
- scsi_block_requests(host);
+ scsi_host_block(host);
/* Quiesce build, flush cache, write through mode */
if (forced < 2)
@@ -1681,6 +1657,9 @@
retval = _aac_reset_adapter(aac, bled, reset_type);
spin_unlock_irqrestore(host->host_lock, flagv);
+ unblock_retval = scsi_host_unblock(host, SDEV_RUNNING);
+ if (!retval)
+ retval = unblock_retval;
if ((forced < 2) && (retval == -ENODEV)) {
/* Unwind aac_send_shutdown() IOP_RESET unsupported/disabled */
struct fib * fibctx = aac_fib_alloc(aac);
@@ -1959,6 +1938,16 @@
return rcode;
}
+void aac_src_reinit_aif_worker(struct work_struct *work)
+{
+ struct aac_dev *dev = container_of(to_delayed_work(work),
+ struct aac_dev, src_reinit_aif_worker);
+
+ wait_event(dev->scsi_host_ptr->host_wait,
+ !scsi_host_in_recovery(dev->scsi_host_ptr));
+ aac_reinit_aif(dev, dev->cardtype);
+}
+
/**
* aac_handle_sa_aif Handle a message from the firmware
* @dev: Which adapter this fib is from
@@ -2363,7 +2352,7 @@
goto out;
}
-int aac_send_safw_hostttime(struct aac_dev *dev, struct timespec64 *now)
+static int aac_send_safw_hostttime(struct aac_dev *dev, struct timespec64 *now)
{
struct tm cur_tm;
char wellness_str[] = "<HW>TD\010\0\0\0\0\0\0\0\0\0DW\0\0ZZ";
@@ -2392,7 +2381,7 @@
return ret;
}
-int aac_send_hosttime(struct aac_dev *dev, struct timespec64 *now)
+static int aac_send_hosttime(struct aac_dev *dev, struct timespec64 *now)
{
int ret = -ENOMEM;
struct fib *fibptr;
@@ -2428,7 +2417,7 @@
/**
* aac_command_thread - command processing thread
- * @dev: Adapter to monitor
+ * @data: Adapter to monitor
*
* Waits on the commandready event in it's queue. When the event gets set
* it will pull FIBs off it's queue. It will continue to pull FIBs off
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index a557aa6..fbe334c 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -99,10 +99,11 @@
}
if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected | Async))
{
- if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected))
+ if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected)) {
FIB_COUNTER_INCREMENT(aac_config.NoResponseRecved);
- else
+ } else {
FIB_COUNTER_INCREMENT(aac_config.AsyncRecved);
+ }
/*
* NOTE: we cannot touch the fib after this
* call, because it may have been deallocated.
@@ -229,7 +230,6 @@
struct fib *fibctx;
struct aac_dev *dev;
struct aac_aifcmd *cmd;
- int status;
fibctx = (struct fib *)context;
BUG_ON(fibptr == NULL);
@@ -249,7 +249,7 @@
cmd = (struct aac_aifcmd *) fib_data(fibctx);
cmd->command = cpu_to_le32(AifReqEvent);
- status = aac_fib_send(AifRequest,
+ aac_fib_send(AifRequest,
fibctx,
sizeof(struct hw_fib)-sizeof(struct aac_fibhdr),
FsaNormal,
@@ -258,7 +258,7 @@
}
-/**
+/*
* aac_intr_normal - Handle command replies
* @dev: Device
* @index: completion reference
@@ -403,12 +403,13 @@
if (hwfib->header.XferState &
cpu_to_le32(NoResponseExpected | Async)) {
if (hwfib->header.XferState & cpu_to_le32(
- NoResponseExpected))
+ NoResponseExpected)) {
FIB_COUNTER_INCREMENT(
aac_config.NoResponseRecved);
- else
+ } else {
FIB_COUNTER_INCREMENT(
aac_config.AsyncRecved);
+ }
start_callback = 1;
} else {
unsigned long flagv;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 1035f94..0a82afa 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -33,6 +33,7 @@
#include <linux/syscalls.h>
#include <linux/delay.h>
#include <linux/kthread.h>
+#include <linux/msdos_partition.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -229,8 +230,8 @@
/**
* aac_queuecommand - queue a SCSI command
+ * @shost: Scsi host to queue command on
* @cmd: SCSI command to queue
- * @done: Function to call on command completion
*
* Queues a command for execution by the associated Host Adapter.
*
@@ -328,9 +329,9 @@
buf = scsi_bios_ptable(bdev);
if (!buf)
return 0;
- if(*(__le16 *)(buf + 0x40) == cpu_to_le16(0xaa55)) {
- struct partition *first = (struct partition * )buf;
- struct partition *entry = first;
+ if (*(__le16 *)(buf + 0x40) == cpu_to_le16(MSDOS_LABEL_MAGIC)) {
+ struct msdos_partition *first = (struct msdos_partition *)buf;
+ struct msdos_partition *entry = first;
int saved_cylinders = param->cylinders;
int num;
unsigned char end_head, end_sec;
@@ -362,9 +363,10 @@
param->cylinders = cap_to_cyls(capacity, param->heads * param->sectors);
if (num < 4 && end_sec == param->sectors) {
- if (param->cylinders != saved_cylinders)
+ if (param->cylinders != saved_cylinders) {
dprintk((KERN_DEBUG "Adopting geometry: heads=%d, sectors=%d from partition table %d.\n",
param->heads, param->sectors, num));
+ }
} else if (end_head > 0 || end_sec > 0) {
dprintk((KERN_DEBUG "Strange geometry: heads=%d, sectors=%d in partition table %d.\n",
end_head + 1, end_sec, num));
@@ -391,6 +393,7 @@
int chn, tid;
unsigned int depth = 0;
unsigned int set_timeout = 0;
+ int timeout = 0;
bool set_qd_dev_type = false;
u8 devtype = 0;
@@ -483,10 +486,13 @@
/*
* Firmware has an individual device recovery time typically
- * of 35 seconds, give us a margin.
+ * of 35 seconds, give us a margin. Thor devices can take longer in
+ * error recovery, hence different value.
*/
- if (set_timeout && sdev->request_queue->rq_timeout < (45 * HZ))
- blk_queue_rq_timeout(sdev->request_queue, 45*HZ);
+ if (set_timeout) {
+ timeout = aac->sa_firmware ? AAC_SA_TIMEOUT : AAC_ARC_TIMEOUT;
+ blk_queue_rq_timeout(sdev->request_queue, timeout * HZ);
+ }
if (depth > 256)
depth = 256;
@@ -608,60 +614,66 @@
static int aac_ioctl(struct scsi_device *sdev, unsigned int cmd,
void __user *arg)
{
+ int retval;
struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
+ retval = aac_adapter_check_health(dev);
+ if (retval)
+ return -EBUSY;
return aac_do_ioctl(dev, cmd, arg);
}
+struct fib_count_data {
+ int mlcnt;
+ int llcnt;
+ int ehcnt;
+ int fwcnt;
+ int krlcnt;
+};
+
+static bool fib_count_iter(struct scsi_cmnd *scmnd, void *data, bool reserved)
+{
+ struct fib_count_data *fib_count = data;
+
+ switch (scmnd->SCp.phase) {
+ case AAC_OWNER_FIRMWARE:
+ fib_count->fwcnt++;
+ break;
+ case AAC_OWNER_ERROR_HANDLER:
+ fib_count->ehcnt++;
+ break;
+ case AAC_OWNER_LOWLEVEL:
+ fib_count->llcnt++;
+ break;
+ case AAC_OWNER_MIDLEVEL:
+ fib_count->mlcnt++;
+ break;
+ default:
+ fib_count->krlcnt++;
+ break;
+ }
+ return true;
+}
+
+/* Called during SCSI EH, so we don't need to block requests */
static int get_num_of_incomplete_fibs(struct aac_dev *aac)
{
-
- unsigned long flags;
- struct scsi_device *sdev = NULL;
struct Scsi_Host *shost = aac->scsi_host_ptr;
- struct scsi_cmnd *scmnd = NULL;
struct device *ctrl_dev;
+ struct fib_count_data fcnt = { };
- int mlcnt = 0;
- int llcnt = 0;
- int ehcnt = 0;
- int fwcnt = 0;
- int krlcnt = 0;
-
- __shost_for_each_device(sdev, shost) {
- spin_lock_irqsave(&sdev->list_lock, flags);
- list_for_each_entry(scmnd, &sdev->cmd_list, list) {
- switch (scmnd->SCp.phase) {
- case AAC_OWNER_FIRMWARE:
- fwcnt++;
- break;
- case AAC_OWNER_ERROR_HANDLER:
- ehcnt++;
- break;
- case AAC_OWNER_LOWLEVEL:
- llcnt++;
- break;
- case AAC_OWNER_MIDLEVEL:
- mlcnt++;
- break;
- default:
- krlcnt++;
- break;
- }
- }
- spin_unlock_irqrestore(&sdev->list_lock, flags);
- }
+ scsi_host_busy_iter(shost, fib_count_iter, &fcnt);
ctrl_dev = &aac->pdev->dev;
- dev_info(ctrl_dev, "outstanding cmd: midlevel-%d\n", mlcnt);
- dev_info(ctrl_dev, "outstanding cmd: lowlevel-%d\n", llcnt);
- dev_info(ctrl_dev, "outstanding cmd: error handler-%d\n", ehcnt);
- dev_info(ctrl_dev, "outstanding cmd: firmware-%d\n", fwcnt);
- dev_info(ctrl_dev, "outstanding cmd: kernel-%d\n", krlcnt);
+ dev_info(ctrl_dev, "outstanding cmd: midlevel-%d\n", fcnt.mlcnt);
+ dev_info(ctrl_dev, "outstanding cmd: lowlevel-%d\n", fcnt.llcnt);
+ dev_info(ctrl_dev, "outstanding cmd: error handler-%d\n", fcnt.ehcnt);
+ dev_info(ctrl_dev, "outstanding cmd: firmware-%d\n", fcnt.fwcnt);
+ dev_info(ctrl_dev, "outstanding cmd: kernel-%d\n", fcnt.krlcnt);
- return mlcnt + llcnt + ehcnt + fwcnt;
+ return fcnt.mlcnt + fcnt.llcnt + fcnt.ehcnt + fcnt.fwcnt;
}
static int aac_eh_abort(struct scsi_cmnd* cmd)
@@ -753,7 +765,7 @@
!(aac->raw_io_64) ||
((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
break;
- /* fall through */
+ fallthrough;
case INQUIRY:
case READ_CAPACITY:
/*
@@ -853,7 +865,7 @@
return HBA_IU_TYPE_SATA_REQ;
}
-void aac_tmf_callback(void *context, struct fib *fibptr)
+static void aac_tmf_callback(void *context, struct fib *fibptr)
{
struct aac_hba_resp *err =
&((struct aac_native_hba *)fibptr->hw_fib_va)->resp.err;
@@ -1067,7 +1079,7 @@
* @scsi_cmd: SCSI command block causing the reset
*
*/
-int aac_eh_host_reset(struct scsi_cmnd *cmd)
+static int aac_eh_host_reset(struct scsi_cmnd *cmd)
{
struct scsi_device * dev = cmd->device;
struct Scsi_Host * host = dev->host;
@@ -1148,7 +1160,6 @@
/**
* aac_cfg_ioctl - AAC configuration request
- * @inode: inode of device
* @file: file handle
* @cmd: ioctl command code
* @arg: argument
@@ -1171,63 +1182,6 @@
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;
- switch (cmd) {
- case FSACTL_MINIPORT_REV_CHECK:
- case FSACTL_SENDFIB:
- case FSACTL_OPEN_GET_ADAPTER_FIB:
- case FSACTL_CLOSE_GET_ADAPTER_FIB:
- case FSACTL_SEND_RAW_SRB:
- case FSACTL_GET_PCI_INFO:
- case FSACTL_QUERY_DISK:
- case FSACTL_DELETE_DISK:
- case FSACTL_FORCE_DELETE_DISK:
- case FSACTL_GET_CONTAINERS:
- case FSACTL_SEND_LARGE_FIB:
- ret = aac_do_ioctl(dev, cmd, (void __user *)arg);
- break;
-
- case FSACTL_GET_NEXT_ADAPTER_FIB: {
- struct fib_ioctl __user *f;
-
- f = compat_alloc_user_space(sizeof(*f));
- ret = 0;
- if (clear_user(f, sizeof(*f)))
- ret = -EFAULT;
- if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32)))
- ret = -EFAULT;
- if (!ret)
- ret = aac_do_ioctl(dev, cmd, f);
- break;
- }
-
- default:
- ret = -ENOIOCTLCMD;
- break;
- }
- return ret;
-}
-
-static int aac_compat_ioctl(struct scsi_device *sdev, unsigned int cmd,
- void __user *arg)
-{
- struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg);
-}
-
-static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long arg)
-{
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- return aac_compat_do_ioctl(file->private_data, cmd, arg);
-}
-#endif
-
static ssize_t aac_show_model(struct device *device,
struct device_attribute *attr, char *buf)
{
@@ -1277,20 +1231,21 @@
if (nblank(dprintk(x)))
len = snprintf(buf, PAGE_SIZE, "dprintk\n");
#ifdef AAC_DETAILED_STATUS_INFO
- len += snprintf(buf + len, PAGE_SIZE - len,
- "AAC_DETAILED_STATUS_INFO\n");
+ len += scnprintf(buf + len, PAGE_SIZE - len,
+ "AAC_DETAILED_STATUS_INFO\n");
#endif
if (dev->raw_io_interface && dev->raw_io_64)
- len += snprintf(buf + len, PAGE_SIZE - len,
- "SAI_READ_CAPACITY_16\n");
+ len += scnprintf(buf + len, PAGE_SIZE - len,
+ "SAI_READ_CAPACITY_16\n");
if (dev->jbod)
- len += snprintf(buf + len, PAGE_SIZE - len, "SUPPORTED_JBOD\n");
+ len += scnprintf(buf + len, PAGE_SIZE - len,
+ "SUPPORTED_JBOD\n");
if (dev->supplement_adapter_info.supported_options2 &
AAC_OPTION_POWER_MANAGEMENT)
- len += snprintf(buf + len, PAGE_SIZE - len,
- "SUPPORTED_POWER_MANAGEMENT\n");
+ len += scnprintf(buf + len, PAGE_SIZE - len,
+ "SUPPORTED_POWER_MANAGEMENT\n");
if (dev->msi)
- len += snprintf(buf + len, PAGE_SIZE - len, "PCI_HAS_MSI\n");
+ len += scnprintf(buf + len, PAGE_SIZE - len, "PCI_HAS_MSI\n");
return len;
}
@@ -1511,7 +1466,7 @@
.owner = THIS_MODULE,
.unlocked_ioctl = aac_cfg_ioctl,
#ifdef CONFIG_COMPAT
- .compat_ioctl = aac_compat_cfg_ioctl,
+ .compat_ioctl = aac_cfg_ioctl,
#endif
.open = aac_cfg_open,
.llseek = noop_llseek,
@@ -1524,7 +1479,7 @@
.info = aac_info,
.ioctl = aac_ioctl,
#ifdef CONFIG_COMPAT
- .compat_ioctl = aac_compat_ioctl,
+ .compat_ioctl = aac_ioctl,
#endif
.queuecommand = aac_queuecommand,
.bios_param = aac_biosparm,
@@ -1601,6 +1556,19 @@
}
}
+void aac_reinit_aif(struct aac_dev *aac, unsigned int index)
+{
+ /*
+ * Firmware may send a AIF messages very early and the Driver may have
+ * ignored as it is not fully ready to process the messages. Send
+ * AIF to firmware so that if there are any unprocessed events they
+ * can be processed now.
+ */
+ if (aac_drivers[index].quirks & AAC_QUIRK_SRC)
+ aac_intr_normal(aac, 0, 2, 0, NULL);
+
+}
+
static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
unsigned index = id->driver_data;
@@ -1634,7 +1602,7 @@
goto out;
if (!(aac_drivers[index].quirks & AAC_QUIRK_SRC)) {
- error = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ error = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
if (error) {
dev_err(&pdev->dev, "PCI 32 BIT dma mask set failed");
goto out_disable_pdev;
@@ -1653,7 +1621,7 @@
mask_bits = 32;
}
- error = pci_set_consistent_dma_mask(pdev, dmamask);
+ error = dma_set_coherent_mask(&pdev->dev, dmamask);
if (error) {
dev_err(&pdev->dev, "PCI %d B consistent dma mask set failed\n"
, mask_bits);
@@ -1671,7 +1639,6 @@
shost->irq = pdev->irq;
shost->unique_id = unique_id;
shost->max_cmd_len = 16;
- shost->use_cmd_list = 1;
if (aac_cfg_major == AAC_CHARDEV_NEEDS_REINIT)
aac_init_char();
@@ -1702,6 +1669,8 @@
mutex_init(&aac->scan_mutex);
INIT_DELAYED_WORK(&aac->safw_rescan_work, aac_safw_rescan_worker);
+ INIT_DELAYED_WORK(&aac->src_reinit_aif_worker,
+ aac_src_reinit_aif_worker);
/*
* Map in the registers from the adapter.
*/
@@ -1891,8 +1860,8 @@
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
- scsi_block_requests(shost);
- aac_cancel_safw_rescan_worker(aac);
+ scsi_host_block(shost);
+ aac_cancel_rescan_worker(aac);
aac_send_shutdown(aac);
aac_release_resources(aac);
@@ -1927,7 +1896,7 @@
* aac_send_shutdown() to block ioctls from upperlayer
*/
aac->adapter_shutdown = 0;
- scsi_unblock_requests(shost);
+ scsi_host_unblock(shost, SDEV_RUNNING);
return 0;
@@ -1942,7 +1911,8 @@
static void aac_shutdown(struct pci_dev *dev)
{
struct Scsi_Host *shost = pci_get_drvdata(dev);
- scsi_block_requests(shost);
+
+ scsi_host_block(shost);
__aac_shutdown((struct aac_dev *)shost->hostdata);
}
@@ -1951,7 +1921,7 @@
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
- aac_cancel_safw_rescan_worker(aac);
+ aac_cancel_rescan_worker(aac);
scsi_remove_host(shost);
__aac_shutdown(aac);
@@ -1974,28 +1944,8 @@
}
}
-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)
+ pci_channel_state_t error)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct aac_dev *aac = shost_priv(shost);
@@ -2008,9 +1958,9 @@
case pci_channel_io_frozen:
aac->handle_pci_error = 1;
- scsi_block_requests(aac->scsi_host_ptr);
- aac_cancel_safw_rescan_worker(aac);
- aac_flush_ios(aac);
+ scsi_host_block(shost);
+ aac_cancel_rescan_worker(aac);
+ scsi_host_complete_all_commands(shost, DID_NO_CONNECT);
aac_release_resources(aac);
pci_disable_pcie_error_reporting(pdev);
@@ -2020,7 +1970,7 @@
case pci_channel_io_perm_failure:
aac->handle_pci_error = 1;
- aac_flush_ios(aac);
+ scsi_host_complete_all_commands(shost, DID_NO_CONNECT);
return PCI_ERS_RESULT_DISCONNECT;
}
@@ -2061,7 +2011,6 @@
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);
if (aac_adapter_ioremap(aac, aac->base_size)) {
@@ -2088,10 +2037,7 @@
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_host_unblock(shost, SDEV_RUNNING);
aac_scan_host(aac);
pci_save_state(pdev);
diff --git a/drivers/scsi/aacraid/nark.c b/drivers/scsi/aacraid/nark.c
index b5d6b24..4745a99 100644
--- a/drivers/scsi/aacraid/nark.c
+++ b/drivers/scsi/aacraid/nark.c
@@ -24,6 +24,7 @@
/**
* aac_nark_ioremap
+ * @dev: device to ioremap
* @size: mapping resize request
*
*/
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index 5f2cede..8ebc67e 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -57,6 +57,7 @@
/**
* aac_rkt_ioremap
+ * @dev: device to ioremap
* @size: mapping resize request
*
*/
@@ -77,8 +78,8 @@
* aac_rkt_init - initialize an i960 based AAC card
* @dev: device to configure
*
- * Allocate and set up resources for the i960 based AAC variants. The
- * device_interface in the commregion will be allocated and linked
+ * Allocate and set up resources for the i960 based AAC variants. The
+ * device_interface in the commregion will be allocated and linked
* to the comm region.
*/
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 3dea348..cdccf9a 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -144,7 +144,16 @@
* @dev: Adapter
* @command: Command to execute
* @p1: first parameter
- * @ret: adapter status
+ * @p2: second parameter
+ * @p3: third parameter
+ * @p4: forth parameter
+ * @p5: fifth parameter
+ * @p6: sixth parameter
+ * @status: adapter status
+ * @r1: first return value
+ * @r2: second return value
+ * @r3: third return value
+ * @r4: forth return value
*
* This routine will send a synchronous command to the adapter and wait
* for its completion.
@@ -443,6 +452,7 @@
/**
* aac_rx_ioremap
+ * @dev: adapter
* @size: mapping resize request
*
*/
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index aa5d763..c9a1dad 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -135,13 +135,21 @@
* @dev: Adapter
* @command: Command to execute
* @p1: first parameter
+ * @p2: second parameter
+ * @p3: third parameter
+ * @p4: forth parameter
+ * @p5: fifth parameter
+ * @p6: sixth parameter
* @ret: adapter status
+ * @r1: first return value
+ * @r2: second return value
+ * @r3: third return value
+ * @r4: forth return value
*
- * This routine will send a synchronous command to the adapter and wait
+ * This routine will send a synchronous command to the adapter and wait
* for its completion.
*/
-
-static int sa_sync_cmd(struct aac_dev *dev, u32 command,
+static int sa_sync_cmd(struct aac_dev *dev, u32 command,
u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
u32 *ret, u32 *r1, u32 *r2, u32 *r3, u32 *r4)
{
@@ -283,6 +291,7 @@
/**
* aac_sa_ioremap
+ * @dev: device to ioremap
* @size: mapping resize request
*
*/
@@ -300,8 +309,8 @@
* aac_sa_init - initialize an ARM based AAC card
* @dev: device to configure
*
- * Allocate and set up resources for the ARM based AAC variants. The
- * device_interface in the commregion will be allocated and linked
+ * Allocate and set up resources for the ARM based AAC variants. The
+ * device_interface in the commregion will be allocated and linked
* to the comm region.
*/
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c
index 3b66e06..11ef582 100644
--- a/drivers/scsi/aacraid/src.c
+++ b/drivers/scsi/aacraid/src.c
@@ -191,7 +191,16 @@
* @dev: Adapter
* @command: Command to execute
* @p1: first parameter
- * @ret: adapter status
+ * @p2: second parameter
+ * @p3: third parameter
+ * @p4: forth parameter
+ * @p5: fifth parameter
+ * @p6: sixth parameter
+ * @status: adapter status
+ * @r1: first return value
+ * @r2: second return valu
+ * @r3: third return value
+ * @r4: forth return value
*
* This routine will send a synchronous command to the adapter and wait
* for its completion.
@@ -602,6 +611,7 @@
/**
* aac_src_ioremap
+ * @dev: device ioremap
* @size: mapping resize request
*
*/
@@ -632,6 +642,7 @@
/**
* aac_srcv_ioremap
+ * @dev: device ioremap
* @size: mapping resize request
*
*/
@@ -733,10 +744,20 @@
return ctrl_up;
}
+static void aac_src_drop_io(struct aac_dev *dev)
+{
+ if (!dev->soft_reset_support)
+ return;
+
+ aac_adapter_sync_cmd(dev, DROP_IO,
+ 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
+}
+
static void aac_notify_fw_of_iop_reset(struct aac_dev *dev)
{
aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, 0, 0, 0, 0, 0, 0, NULL,
NULL, NULL, NULL, NULL);
+ aac_src_drop_io(dev);
}
static void aac_send_iop_reset(struct aac_dev *dev)
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index a242a62..727d8f0 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -316,7 +316,7 @@
ushort queue_cnt;
ushort entry_to_copy;
ushort res;
- ASC_SG_LIST sg_list[0];
+ ASC_SG_LIST sg_list[];
} ASC_SG_HEAD;
typedef struct asc_scsi_q {
@@ -3366,8 +3366,8 @@
shost->host_no);
seq_printf(m,
- " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
- (unsigned long)v->iop_base,
+ " iop_base 0x%p, cable_detect: %X, err_code %u\n",
+ v->iop_base,
AdvReadWordRegister(iop_base,IOPW_SCSI_CFG1) & CABLE_DETECT,
v->err_code);
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index eb466c2..d8e19af 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -220,7 +220,7 @@
*
**************************************************************************
- see Documentation/scsi/aha152x.txt for configuration details
+ see Documentation/scsi/aha152x.rst for configuration details
**************************************************************************/
@@ -1249,7 +1249,7 @@
"aha152x: unable to verify geometry for disk with >1GB.\n"
" Using default translation. Please verify yourself.\n"
" Perhaps you need to enable extended translation in the driver.\n"
- " See Documentation/scsi/aha152x.txt for details.\n");
+ " See Documentation/scsi/aha152x.rst for details.\n");
}
} else {
info_array[0] = info[0];
@@ -2030,8 +2030,7 @@
fifodata, GETPORT(FIFOSTAT));
SETPORT(DMACNTRL0, ENDMA|_8BIT);
while(fifodata>0) {
- int data;
- data=GETPORT(DATAPORT);
+ GETPORT(DATAPORT);
fifodata--;
DATA_LEN++;
}
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c
index da4150c..5a227c0 100644
--- a/drivers/scsi/aha1740.c
+++ b/drivers/scsi/aha1740.c
@@ -592,7 +592,6 @@
DMA_BIDIRECTIONAL);
if (!host->ecb_dma_addr) {
printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n");
- scsi_host_put (shpnt);
goto err_host_put;
}
diff --git a/drivers/scsi/aic7xxx/.gitignore b/drivers/scsi/aic7xxx/.gitignore
index b8ee24d..9aa7802 100644
--- a/drivers/scsi/aic7xxx/.gitignore
+++ b/drivers/scsi/aic7xxx/.gitignore
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
aic79xx_reg.h
aic79xx_reg_print.c
aic79xx_seq.h
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
index 16743fb..a47dbd5 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -15,7 +15,7 @@
int "Maximum number of TCQ commands per device"
depends on SCSI_AIC79XX
default "32"
- ---help---
+ help
Specify the number of commands you would like to allocate per SCSI
device when Tagged Command Queueing (TCQ) is enabled on that device.
@@ -32,13 +32,13 @@
on some devices. The upper bound is 253. 0 disables tagged queueing.
Per device tag depth can be controlled via the kernel command line
- "tag_info" option. See Documentation/scsi/aic79xx.txt for details.
+ "tag_info" option. See Documentation/scsi/aic79xx.rst for details.
config AIC79XX_RESET_DELAY_MS
int "Initial bus reset delay in milli-seconds"
depends on SCSI_AIC79XX
default "5000"
- ---help---
+ help
The number of milliseconds to delay after an initial bus reset.
The bus settle delay following all error recovery actions is
dictated by the SCSI layer and is not affected by this value.
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index 3546b8c..0cfd92c 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -7,7 +7,7 @@
tristate "Adaptec AIC7xxx Fast -> U160 support"
depends on (PCI || EISA) && SCSI
select SCSI_SPI_ATTRS
- ---help---
+ help
This driver supports all of Adaptec's Fast through Ultra 160 PCI
based SCSI controllers as well as the aic7770 based EISA and VLB
SCSI controllers (the 274x and 284x series). For AAA and ARO based
@@ -20,7 +20,7 @@
int "Maximum number of TCQ commands per device"
depends on SCSI_AIC7XXX
default "32"
- ---help---
+ help
Specify the number of commands you would like to allocate per SCSI
device when Tagged Command Queueing (TCQ) is enabled on that device.
@@ -37,13 +37,13 @@
on some devices. The upper bound is 253. 0 disables tagged queueing.
Per device tag depth can be controlled via the kernel command line
- "tag_info" option. See Documentation/scsi/aic7xxx.txt for details.
+ "tag_info" option. See Documentation/scsi/aic7xxx.rst for details.
config AIC7XXX_RESET_DELAY_MS
int "Initial bus reset delay in milli-seconds"
depends on SCSI_AIC7XXX
default "5000"
- ---help---
+ help
The number of milliseconds to delay after an initial bus reset.
The bus settle delay following all error recovery actions is
dictated by the SCSI layer and is not affected by this value.
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 7e5044b..98b02e7 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -1735,10 +1735,8 @@
sg_list = (struct ahd_dma64_seg*)scb->sg_list;
for (i = 0; i < scb->sg_count; i++) {
uint64_t addr;
- uint32_t len;
addr = ahd_le64toh(sg_list[i].addr);
- len = ahd_le32toh(sg_list[i].len);
printk("sg[%d] - Addr 0x%x%x : Length %d%s\n",
i,
(uint32_t)((addr >> 32) & 0xFFFFFFFF),
@@ -1906,9 +1904,6 @@
{
struct ahd_devinfo devinfo;
struct scb *scb;
- struct ahd_initiator_tinfo *targ_info;
- struct ahd_tmode_tstate *tstate;
- struct ahd_transinfo *tinfo;
u_int scbid;
/*
@@ -1936,12 +1931,6 @@
SCB_GET_LUN(scb),
SCB_GET_CHANNEL(ahd, scb),
ROLE_INITIATOR);
- targ_info = ahd_fetch_transinfo(ahd,
- devinfo.channel,
- devinfo.our_scsiid,
- devinfo.target,
- &tstate);
- tinfo = &targ_info->curr;
ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
AHD_TRANS_ACTIVE, /*paused*/TRUE);
ahd_set_syncrate(ahd, &devinfo, /*period*/0,
@@ -2285,7 +2274,7 @@
switch (scb->hscb->task_management) {
case SIU_TASKMGMT_ABORT_TASK:
tag = SCB_GET_TAG(scb);
- /* fall through */
+ fallthrough;
case SIU_TASKMGMT_ABORT_TASK_SET:
case SIU_TASKMGMT_CLEAR_TASK_SET:
lun = scb->hscb->lun;
@@ -2296,7 +2285,7 @@
break;
case SIU_TASKMGMT_LUN_RESET:
lun = scb->hscb->lun;
- /* fall through */
+ fallthrough;
case SIU_TASKMGMT_TARGET_RESET:
{
struct ahd_devinfo devinfo;
@@ -2669,7 +2658,6 @@
struct scb *scb;
u_int scbid;
u_int lqistat1;
- u_int lqistat2;
u_int msg_out;
u_int curphase;
u_int lastphase;
@@ -2680,7 +2668,7 @@
scb = NULL;
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
lqistat1 = ahd_inb(ahd, LQISTAT1) & ~(LQIPHASE_LQ|LQIPHASE_NLQ);
- lqistat2 = ahd_inb(ahd, LQISTAT2);
+ ahd_inb(ahd, LQISTAT2);
if ((lqistat1 & (LQICRCI_NLQ|LQICRCI_LQ)) == 0
&& (ahd->bugs & AHD_NLQICRC_DELAYED_BUG) != 0) {
u_int lqistate;
@@ -3107,19 +3095,6 @@
printerror = 0;
} else if (ahd_sent_msg(ahd, AHDMSG_1B,
MSG_BUS_DEV_RESET, TRUE)) {
-#ifdef __FreeBSD__
- /*
- * Don't mark the user's request for this BDR
- * as completing with CAM_BDR_SENT. CAM3
- * specifies CAM_REQ_CMP.
- */
- if (scb != NULL
- && scb->io_ctx->ccb_h.func_code== XPT_RESET_DEV
- && ahd_match_scb(ahd, scb, target, 'A',
- CAM_LUN_WILDCARD, SCB_LIST_NULL,
- ROLE_INITIATOR))
- ahd_set_transaction_status(scb, CAM_REQ_CMP);
-#endif
ahd_handle_devreset(ahd, &devinfo, CAM_LUN_WILDCARD,
CAM_BDR_SENT, "Bus Device Reset",
/*verbose_level*/0);
@@ -3675,8 +3650,7 @@
return;
tstate = ahd->enabled_targets[scsi_id];
- if (tstate != NULL)
- kfree(tstate);
+ kfree(tstate);
ahd->enabled_targets[scsi_id] = NULL;
}
#endif
@@ -3817,7 +3791,7 @@
*bus_width = MSG_EXT_WDTR_BUS_16_BIT;
break;
}
- /* FALLTHROUGH */
+ fallthrough;
case MSG_EXT_WDTR_BUS_8_BIT:
*bus_width = MSG_EXT_WDTR_BUS_8_BIT;
break;
@@ -4232,13 +4206,11 @@
pending_scb_count = 0;
LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
struct ahd_devinfo devinfo;
- struct ahd_initiator_tinfo *tinfo;
struct ahd_tmode_tstate *tstate;
ahd_scb_devinfo(ahd, &devinfo, pending_scb);
- tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
- devinfo.our_scsiid,
- devinfo.target, &tstate);
+ ahd_fetch_transinfo(ahd, devinfo.channel, devinfo.our_scsiid,
+ devinfo.target, &tstate);
if ((tstate->auto_negotiate & devinfo.target_mask) == 0
&& (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) {
pending_scb->flags &= ~SCB_AUTO_NEGOTIATE;
@@ -5132,7 +5104,7 @@
break;
case MSG_MESSAGE_REJECT:
response = ahd_handle_msg_reject(ahd, devinfo);
- /* FALLTHROUGH */
+ fallthrough;
case MSG_NOOP:
done = MSGLOOP_MSGCOMPLETE;
break;
@@ -5482,7 +5454,7 @@
ahd_name(ahd), ahd_inb(ahd, SCSISIGI));
#endif
ahd->msg_flags |= MSG_FLAG_EXPECT_QASREJ_BUSFREE;
- /* FALLTHROUGH */
+ fallthrough;
case MSG_TERM_IO_PROC:
default:
reject = TRUE;
@@ -6067,22 +6039,16 @@
{
struct ahd_softc *ahd;
-#ifndef __FreeBSD__
- ahd = kmalloc(sizeof(*ahd), GFP_ATOMIC);
+ ahd = kzalloc(sizeof(*ahd), GFP_ATOMIC);
if (!ahd) {
printk("aic7xxx: cannot malloc softc!\n");
kfree(name);
return NULL;
}
-#else
- ahd = device_get_softc((device_t)platform_arg);
-#endif
- memset(ahd, 0, sizeof(*ahd));
+
ahd->seep_config = kmalloc(sizeof(*ahd->seep_config), GFP_ATOMIC);
if (ahd->seep_config == NULL) {
-#ifndef __FreeBSD__
kfree(ahd);
-#endif
kfree(name);
return (NULL);
}
@@ -6138,8 +6104,7 @@
void
ahd_set_name(struct ahd_softc *ahd, char *name)
{
- if (ahd->name != NULL)
- kfree(ahd->name);
+ kfree(ahd->name);
ahd->name = name;
}
@@ -6152,17 +6117,17 @@
default:
case 5:
ahd_shutdown(ahd);
- /* FALLTHROUGH */
+ fallthrough;
case 4:
ahd_dmamap_unload(ahd, ahd->shared_data_dmat,
ahd->shared_data_map.dmamap);
- /* FALLTHROUGH */
+ fallthrough;
case 3:
ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo,
ahd->shared_data_map.dmamap);
ahd_dmamap_destroy(ahd, ahd->shared_data_dmat,
ahd->shared_data_map.dmamap);
- /* FALLTHROUGH */
+ fallthrough;
case 2:
ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat);
case 1:
@@ -6200,15 +6165,10 @@
kfree(ahd->black_hole);
}
#endif
- if (ahd->name != NULL)
- kfree(ahd->name);
- if (ahd->seep_config != NULL)
- kfree(ahd->seep_config);
- if (ahd->saved_stack != NULL)
- kfree(ahd->saved_stack);
-#ifndef __FreeBSD__
+ kfree(ahd->name);
+ kfree(ahd->seep_config);
+ kfree(ahd->saved_stack);
kfree(ahd);
-#endif
return;
}
@@ -6553,7 +6513,7 @@
}
ahd_dma_tag_destroy(ahd, scb_data->sense_dmat);
}
- /* fall through */
+ fallthrough;
case 6:
{
struct map_node *sg_map;
@@ -6568,7 +6528,7 @@
}
ahd_dma_tag_destroy(ahd, scb_data->sg_dmat);
}
- /* fall through */
+ fallthrough;
case 5:
{
struct map_node *hscb_map;
@@ -7211,7 +7171,7 @@
case FLX_CSTAT_OVER:
case FLX_CSTAT_UNDER:
warn_user++;
- /* fall through */
+ fallthrough;
case FLX_CSTAT_INVALID:
case FLX_CSTAT_OKAY:
if (warn_user == 0 && bootverbose == 0)
@@ -8215,12 +8175,12 @@
if ((scb->flags & SCB_ACTIVE) == 0)
printk("Inactive SCB in qinfifo\n");
ahd_done_with_status(ahd, scb, status);
- /* FALLTHROUGH */
+ fallthrough;
case SEARCH_REMOVE:
break;
case SEARCH_PRINT:
printk(" 0x%x", ahd->qinfifo[qinpos]);
- /* FALLTHROUGH */
+ fallthrough;
case SEARCH_COUNT:
ahd_qinfifo_requeue(ahd, prev_scb, scb);
prev_scb = scb;
@@ -8311,7 +8271,7 @@
if ((mk_msg_scb->flags & SCB_ACTIVE) == 0)
printk("Inactive SCB pending MK_MSG\n");
ahd_done_with_status(ahd, mk_msg_scb, status);
- /* FALLTHROUGH */
+ fallthrough;
case SEARCH_REMOVE:
{
u_int tail_offset;
@@ -8335,7 +8295,7 @@
}
case SEARCH_PRINT:
printk(" 0x%x", SCB_GET_TAG(scb));
- /* FALLTHROUGH */
+ fallthrough;
case SEARCH_COUNT:
break;
}
@@ -8416,7 +8376,7 @@
if ((scb->flags & SCB_ACTIVE) == 0)
printk("Inactive SCB in Waiting List\n");
ahd_done_with_status(ahd, scb, status);
- /* fall through */
+ fallthrough;
case SEARCH_REMOVE:
ahd_rem_wscb(ahd, scbid, prev, next, tid);
*list_tail = prev;
@@ -8425,7 +8385,7 @@
break;
case SEARCH_PRINT:
printk("0x%x ", scbid);
- /* fall through */
+ fallthrough;
case SEARCH_COUNT:
prev = scbid;
break;
@@ -9063,7 +9023,7 @@
case SCSI_STATUS_OK:
printk("%s: Interrupted for status of 0???\n",
ahd_name(ahd));
- /* FALLTHROUGH */
+ fallthrough;
default:
ahd_done(ahd, scb);
break;
@@ -9442,10 +9402,9 @@
if (cs_count != 0) {
cs_count *= sizeof(struct cs);
- ahd->critical_sections = kmalloc(cs_count, GFP_ATOMIC);
+ ahd->critical_sections = kmemdup(cs_table, cs_count, GFP_ATOMIC);
if (ahd->critical_sections == NULL)
panic("ahd_loadseq: Could not malloc");
- memcpy(ahd->critical_sections, cs_table, cs_count);
}
ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE);
@@ -9552,7 +9511,7 @@
fmt3_ins = &instr.format3;
fmt3_ins->address = ahd_resolve_seqaddr(ahd, fmt3_ins->address);
}
- /* fall through */
+ fallthrough;
case AIC_OP_OR:
case AIC_OP_AND:
case AIC_OP_XOR:
@@ -9563,7 +9522,7 @@
fmt1_ins->immediate = dconsts[fmt1_ins->immediate];
}
fmt1_ins->parity = 0;
- /* fall through */
+ fallthrough;
case AIC_OP_ROL:
{
int i, count;
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 5799251..f323989 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -700,9 +700,6 @@
static int
ahd_linux_slave_configure(struct scsi_device *sdev)
{
- struct ahd_softc *ahd;
-
- ahd = *((struct ahd_softc **)sdev->host->hostdata);
if (bootverbose)
sdev_printk(KERN_INFO, sdev, "Slave Configure\n");
@@ -723,24 +720,17 @@
ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int geom[])
{
- uint8_t *bh;
int heads;
int sectors;
int cylinders;
- int ret;
int extended;
struct ahd_softc *ahd;
ahd = *((struct ahd_softc **)sdev->host->hostdata);
- bh = scsi_bios_ptable(bdev);
- if (bh) {
- ret = scsi_partsize(bh, capacity,
- &geom[2], &geom[0], &geom[1]);
- kfree(bh);
- if (ret != -1)
- return (ret);
- }
+ if (scsi_partsize(bdev, capacity, geom))
+ return 0;
+
heads = 64;
sectors = 32;
cylinders = aic_sector_div(capacity, heads, sectors);
@@ -785,16 +775,13 @@
struct scb *reset_scb;
u_int cdb_byte;
int retval = SUCCESS;
- int paused;
- int wait;
struct ahd_initiator_tinfo *tinfo;
struct ahd_tmode_tstate *tstate;
unsigned long flags;
DECLARE_COMPLETION_ONSTACK(done);
reset_scb = NULL;
- paused = FALSE;
- wait = FALSE;
+
ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
scmd_printk(KERN_INFO, cmd,
@@ -965,8 +952,8 @@
ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr,
int flags, bus_dmamap_t *mapp)
{
- *vaddr = pci_alloc_consistent(ahd->dev_softc,
- dmat->maxsize, mapp);
+ *vaddr = dma_alloc_coherent(&ahd->dev_softc->dev, dmat->maxsize, mapp,
+ GFP_ATOMIC);
if (*vaddr == NULL)
return (ENOMEM);
return(0);
@@ -976,8 +963,7 @@
ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat,
void* vaddr, bus_dmamap_t map)
{
- pci_free_consistent(ahd->dev_softc, dmat->maxsize,
- vaddr, map);
+ dma_free_coherent(&ahd->dev_softc->dev, dmat->maxsize, vaddr, map);
}
int
@@ -1800,10 +1786,12 @@
*/
cmd->sense_buffer[0] = 0;
if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG) {
+#ifdef AHD_REPORT_UNDERFLOWS
uint32_t amount_xferred;
amount_xferred =
ahd_get_transfer_length(scb) - ahd_get_residual(scb);
+#endif
if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) {
#ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_MISC) != 0) {
@@ -2046,7 +2034,7 @@
break;
case CAM_AUTOSENSE_FAIL:
new_status = DID_ERROR;
- /* Fallthrough */
+ fallthrough;
case CAM_SCSI_STATUS_ERROR:
scsi_status = ahd_cmd_get_scsi_status(cmd);
@@ -2154,7 +2142,7 @@
u_int last_phase;
u_int saved_scsiid;
u_int cdb_byte;
- int retval;
+ int retval = SUCCESS;
int was_paused;
int paused;
int wait;
@@ -2192,8 +2180,7 @@
* so we must not still own the command.
*/
scmd_printk(KERN_INFO, cmd, "Is not an active device\n");
- retval = SUCCESS;
- goto no_cmd;
+ goto done;
}
/*
@@ -2206,7 +2193,7 @@
if (pending_scb == NULL) {
scmd_printk(KERN_INFO, cmd, "Command not found\n");
- goto no_cmd;
+ goto done;
}
if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {
@@ -2214,7 +2201,7 @@
* We can't queue two recovery actions using the same SCB
*/
retval = FAILED;
- goto done;
+ goto done;
}
/*
@@ -2229,7 +2216,7 @@
if ((pending_scb->flags & SCB_ACTIVE) == 0) {
scmd_printk(KERN_INFO, cmd, "Command already completed\n");
- goto no_cmd;
+ goto done;
}
printk("%s: At time of recovery, card was %spaused\n",
@@ -2246,7 +2233,6 @@
printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
ahd_name(ahd), cmd->device->channel,
cmd->device->id, (u8)cmd->device->lun);
- retval = SUCCESS;
goto done;
}
@@ -2343,17 +2329,10 @@
} else {
scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n");
retval = FAILED;
- goto done;
}
-no_cmd:
- /*
- * Our assumption is that if we don't have the command, no
- * recovery action was required, so we return success. Again,
- * the semantics of the mid-layer recovery engine are not
- * well defined, so this may change in time.
- */
- retval = SUCCESS;
+
+ ahd_restore_modes(ahd, saved_modes);
done:
if (paused)
ahd_unpause(ahd);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
index 8466aa7..8b891a0 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c
@@ -293,7 +293,7 @@
if (!request_mem_region(start, 0x1000, "aic79xx"))
error = ENOMEM;
if (!error) {
- *maddr = ioremap_nocache(base_page, base_offset + 512);
+ *maddr = ioremap(base_page, base_offset + 512);
if (*maddr == NULL) {
error = ENOMEM;
release_mem_region(start, 0x1000);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index 27d85ed..12fed15 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -1834,21 +1834,6 @@
printerror = 0;
} else if (ahc_sent_msg(ahc, AHCMSG_1B,
MSG_BUS_DEV_RESET, TRUE)) {
-#ifdef __FreeBSD__
- /*
- * Don't mark the user's request for this BDR
- * as completing with CAM_BDR_SENT. CAM3
- * specifies CAM_REQ_CMP.
- */
- if (scb != NULL
- && scb->io_ctx->ccb_h.func_code== XPT_RESET_DEV
- && ahc_match_scb(ahc, scb, target, channel,
- CAM_LUN_WILDCARD,
- SCB_LIST_NULL,
- ROLE_INITIATOR)) {
- ahc_set_transaction_status(scb, CAM_REQ_CMP);
- }
-#endif
ahc_compile_devinfo(&devinfo,
initiator_role_id,
target,
@@ -2193,8 +2178,7 @@
if (channel == 'B')
scsi_id += 8;
tstate = ahc->enabled_targets[scsi_id];
- if (tstate != NULL)
- kfree(tstate);
+ kfree(tstate);
ahc->enabled_targets[scsi_id] = NULL;
}
#endif
@@ -2420,7 +2404,7 @@
*bus_width = MSG_EXT_WDTR_BUS_16_BIT;
break;
}
- /* FALLTHROUGH */
+ fallthrough;
case MSG_EXT_WDTR_BUS_8_BIT:
*bus_width = MSG_EXT_WDTR_BUS_8_BIT;
break;
@@ -3615,7 +3599,7 @@
break;
case MSG_MESSAGE_REJECT:
response = ahc_handle_msg_reject(ahc, devinfo);
- /* FALLTHROUGH */
+ fallthrough;
case MSG_NOOP:
done = MSGLOOP_MSGCOMPLETE;
break;
@@ -4399,22 +4383,16 @@
struct ahc_softc *ahc;
int i;
-#ifndef __FreeBSD__
- ahc = kmalloc(sizeof(*ahc), GFP_ATOMIC);
+ ahc = kzalloc(sizeof(*ahc), GFP_ATOMIC);
if (!ahc) {
printk("aic7xxx: cannot malloc softc!\n");
kfree(name);
return NULL;
}
-#else
- ahc = device_get_softc((device_t)platform_arg);
-#endif
- memset(ahc, 0, sizeof(*ahc));
+
ahc->seep_config = kmalloc(sizeof(*ahc->seep_config), GFP_ATOMIC);
if (ahc->seep_config == NULL) {
-#ifndef __FreeBSD__
kfree(ahc);
-#endif
kfree(name);
return (NULL);
}
@@ -4474,8 +4452,7 @@
void
ahc_set_name(struct ahc_softc *ahc, char *name)
{
- if (ahc->name != NULL)
- kfree(ahc->name);
+ kfree(ahc->name);
ahc->name = name;
}
@@ -4488,17 +4465,17 @@
default:
case 5:
ahc_shutdown(ahc);
- /* FALLTHROUGH */
+ fallthrough;
case 4:
ahc_dmamap_unload(ahc, ahc->shared_data_dmat,
ahc->shared_data_dmamap);
- /* FALLTHROUGH */
+ fallthrough;
case 3:
ahc_dmamem_free(ahc, ahc->shared_data_dmat, ahc->qoutfifo,
ahc->shared_data_dmamap);
ahc_dmamap_destroy(ahc, ahc->shared_data_dmat,
ahc->shared_data_dmamap);
- /* FALLTHROUGH */
+ fallthrough;
case 2:
ahc_dma_tag_destroy(ahc, ahc->shared_data_dmat);
case 1:
@@ -4536,13 +4513,9 @@
kfree(ahc->black_hole);
}
#endif
- if (ahc->name != NULL)
- kfree(ahc->name);
- if (ahc->seep_config != NULL)
- kfree(ahc->seep_config);
-#ifndef __FreeBSD__
+ kfree(ahc->name);
+ kfree(ahc->seep_config);
kfree(ahc);
-#endif
return;
}
@@ -4920,38 +4893,37 @@
}
ahc_dma_tag_destroy(ahc, scb_data->sg_dmat);
}
- /* fall through */
+ fallthrough;
case 6:
ahc_dmamap_unload(ahc, scb_data->sense_dmat,
scb_data->sense_dmamap);
- /* fall through */
+ fallthrough;
case 5:
ahc_dmamem_free(ahc, scb_data->sense_dmat, scb_data->sense,
scb_data->sense_dmamap);
ahc_dmamap_destroy(ahc, scb_data->sense_dmat,
scb_data->sense_dmamap);
- /* fall through */
+ fallthrough;
case 4:
ahc_dma_tag_destroy(ahc, scb_data->sense_dmat);
- /* fall through */
+ fallthrough;
case 3:
ahc_dmamap_unload(ahc, scb_data->hscb_dmat,
scb_data->hscb_dmamap);
- /* fall through */
+ fallthrough;
case 2:
ahc_dmamem_free(ahc, scb_data->hscb_dmat, scb_data->hscbs,
scb_data->hscb_dmamap);
ahc_dmamap_destroy(ahc, scb_data->hscb_dmat,
scb_data->hscb_dmamap);
- /* fall through */
+ fallthrough;
case 1:
ahc_dma_tag_destroy(ahc, scb_data->hscb_dmat);
break;
case 0:
break;
}
- if (scb_data->scbarray != NULL)
- kfree(scb_data->scbarray);
+ kfree(scb_data->scbarray);
}
static void
@@ -6009,7 +5981,7 @@
printk("Inactive SCB in Waiting List\n");
ahc_done(ahc, scb);
}
- /* fall through */
+ fallthrough;
case SEARCH_REMOVE:
next = ahc_rem_wscb(ahc, next, prev);
break;
@@ -6907,10 +6879,9 @@
if (cs_count != 0) {
cs_count *= sizeof(struct cs);
- ahc->critical_sections = kmalloc(cs_count, GFP_ATOMIC);
+ ahc->critical_sections = kmemdup(cs_table, cs_count, GFP_ATOMIC);
if (ahc->critical_sections == NULL)
panic("ahc_loadseq: Could not malloc");
- memcpy(ahc->critical_sections, cs_table, cs_count);
}
ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE);
@@ -7015,7 +6986,7 @@
address -= address_offset;
fmt3_ins->address = address;
}
- /* fall through */
+ fallthrough;
case AIC_OP_OR:
case AIC_OP_AND:
case AIC_OP_XOR:
@@ -7041,7 +7012,7 @@
fmt1_ins->opcode = AIC_OP_AND;
fmt1_ins->immediate = 0xff;
}
- /* fall through */
+ fallthrough;
case AIC_OP_ROL:
if ((ahc->features & AHC_ULTRA2) != 0) {
int i, count;
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index d5c4a0d..7bba961 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -564,8 +564,6 @@
struct scsi_target **ahc_targp = ahc_linux_target_in_softc(starget);
unsigned short scsirate;
struct ahc_devinfo devinfo;
- struct ahc_initiator_tinfo *tinfo;
- struct ahc_tmode_tstate *tstate;
char channel = starget->channel + 'A';
unsigned int our_id = ahc->our_id;
unsigned int target_offset;
@@ -612,9 +610,6 @@
spi_max_offset(starget) = 0;
spi_min_period(starget) =
ahc_find_period(ahc, scsirate, maxsync);
-
- tinfo = ahc_fetch_transinfo(ahc, channel, ahc->our_id,
- starget->id, &tstate);
}
ahc_compile_devinfo(&devinfo, our_id, starget->id,
CAM_LUN_WILDCARD, channel,
@@ -671,10 +666,6 @@
static int
ahc_linux_slave_configure(struct scsi_device *sdev)
{
- struct ahc_softc *ahc;
-
- ahc = *((struct ahc_softc **)sdev->host->hostdata);
-
if (bootverbose)
sdev_printk(KERN_INFO, sdev, "Slave Configure\n");
@@ -695,11 +686,9 @@
ahc_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int geom[])
{
- uint8_t *bh;
int heads;
int sectors;
int cylinders;
- int ret;
int extended;
struct ahc_softc *ahc;
u_int channel;
@@ -707,14 +696,9 @@
ahc = *((struct ahc_softc **)sdev->host->hostdata);
channel = sdev_channel(sdev);
- bh = scsi_bios_ptable(bdev);
- if (bh) {
- ret = scsi_partsize(bh, capacity,
- &geom[2], &geom[0], &geom[1]);
- kfree(bh);
- if (ret != -1)
- return (ret);
- }
+ if (scsi_partsize(bdev, capacity, geom))
+ return 0;
+
heads = 64;
sectors = 32;
cylinders = aic_sector_div(capacity, heads, sectors);
@@ -746,7 +730,7 @@
int error;
error = ahc_linux_queue_recovery_cmd(cmd, SCB_ABORT);
- if (error != 0)
+ if (error != SUCCESS)
printk("aic7xxx_abort returns 0x%x\n", error);
return (error);
}
@@ -760,7 +744,7 @@
int error;
error = ahc_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET);
- if (error != 0)
+ if (error != SUCCESS)
printk("aic7xxx_dev_reset returns 0x%x\n", error);
return (error);
}
@@ -1608,7 +1592,6 @@
case AC_TRANSFER_NEG:
{
struct scsi_target *starget;
- struct ahc_linux_target *targ;
struct ahc_initiator_tinfo *tinfo;
struct ahc_tmode_tstate *tstate;
int target_offset;
@@ -1642,7 +1625,6 @@
starget = ahc->platform_data->starget[target_offset];
if (starget == NULL)
break;
- targ = scsi_transport_target_data(starget);
target_ppr_options =
(spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
@@ -1729,10 +1711,12 @@
*/
cmd->sense_buffer[0] = 0;
if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) {
+#ifdef AHC_REPORT_UNDERFLOWS
uint32_t amount_xferred;
amount_xferred =
ahc_get_transfer_length(scb) - ahc_get_residual(scb);
+#endif
if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) {
#ifdef AHC_DEBUG
if ((ahc_debug & AHC_SHOW_MISC) != 0) {
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index 717d8d1..9b293b1 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -372,7 +372,7 @@
if (!request_mem_region(start, 0x1000, "aic7xxx"))
error = ENOMEM;
if (error == 0) {
- *maddr = ioremap_nocache(start, 256);
+ *maddr = ioremap(start, 256);
if (*maddr == NULL) {
error = ENOMEM;
release_mem_region(start, 0x1000);
diff --git a/drivers/scsi/aic94xx/aic94xx.h b/drivers/scsi/aic94xx/aic94xx.h
index c23bbb6..98978bc 100644
--- a/drivers/scsi/aic94xx/aic94xx.h
+++ b/drivers/scsi/aic94xx/aic94xx.h
@@ -42,14 +42,6 @@
extern struct kmem_cache *asd_dma_token_cache;
extern struct kmem_cache *asd_ascb_cache;
-static inline void asd_stringify_sas_addr(char *p, const u8 *sas_addr)
-{
- int i;
- for (i = 0; i < SAS_ADDR_SIZE; i++, p += 2)
- snprintf(p, 3, "%02X", sas_addr[i]);
- *p = '\0';
-}
-
struct asd_ha_struct;
struct asd_ascb;
diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c
index 604a533..73506a4 100644
--- a/drivers/scsi/aic94xx/aic94xx_dev.c
+++ b/drivers/scsi/aic94xx/aic94xx_dev.c
@@ -236,7 +236,7 @@
/**
* asd_init_sata_pm_port_ddb -- SATA Port Multiplier Port
- * dev: pointer to domain device
+ * @dev: pointer to domain device
*
* For SATA Port Multiplier Ports we need to allocate one SATA Port
* Multiplier Port DDB and depending on whether the target on it
@@ -281,7 +281,7 @@
/**
* asd_init_sata_pm_ddb -- SATA Port Multiplier
- * dev: pointer to domain device
+ * @dev: pointer to domain device
*
* For STP and direct-attached SATA Port Multipliers we need
* one target port DDB entry and one SATA PM table DDB entry.
diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c
index c5a46c5..9256ab7 100644
--- a/drivers/scsi/aic94xx/aic94xx_hwi.c
+++ b/drivers/scsi/aic94xx/aic94xx_hwi.c
@@ -575,7 +575,7 @@
/**
* asd_init_ctxmem -- initialize context memory
- * asd_ha: pointer to host adapter structure
+ * @asd_ha: pointer to host adapter structure
*
* This function sets the maximum number of SCBs and
* DDBs which can be used by the sequencer. This is normally
@@ -1146,7 +1146,6 @@
/**
* asd_start_timers -- (add and) start timers of SCBs
* @list: pointer to struct list_head of the scbs
- * @to: timeout in jiffies
*
* If an SCB in the @list has no timer function, assign the default
* one, then start the timer of the SCB. This function is
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index b68dfeb..7a78606 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -40,6 +40,7 @@
/* .name is initialized */
.name = "aic94xx",
.queuecommand = sas_queuecommand,
+ .dma_need_drain = ata_scsi_dma_need_drain,
.target_alloc = sas_target_alloc,
.slave_configure = sas_slave_configure,
.scan_finished = asd_scan_finished,
@@ -55,6 +56,9 @@
.slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = sas_ioctl,
+#endif
.track_queue_depth = 1,
};
@@ -527,7 +531,7 @@
return 0;
}
-/**
+/*
* asd_free_edbs -- free empty data buffers
* asd_ha: pointer to host adapter structure
*/
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c
index 4a80ec0..7b0566f 100644
--- a/drivers/scsi/aic94xx/aic94xx_scb.c
+++ b/drivers/scsi/aic94xx/aic94xx_scb.c
@@ -68,7 +68,6 @@
struct done_list_struct *dl)
{
struct asd_ha_struct *asd_ha = ascb->ha;
- struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
int phy_id = dl->status_block[0] & DL_PHY_MASK;
struct asd_phy *phy = &asd_ha->phys[phy_id];
@@ -81,7 +80,7 @@
ASD_DPRINTK("phy%d: device unplugged\n", phy_id);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(&phy->sas_phy);
- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
+ sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
break;
case CURRENT_OOB_DONE:
/* hot plugged device */
@@ -89,12 +88,12 @@
get_lrate_mode(phy, oob_mode);
ASD_DPRINTK("phy%d device plugged: lrate:0x%x, proto:0x%x\n",
phy_id, phy->sas_phy.linkrate, phy->sas_phy.iproto);
- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
+ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
break;
case CURRENT_SPINUP_HOLD:
/* hot plug SATA, no COMWAKE sent */
asd_turn_led(asd_ha, phy_id, 1);
- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD);
+ sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD);
break;
case CURRENT_GTO_TIMEOUT:
case CURRENT_OOB_ERROR:
@@ -102,7 +101,7 @@
dl->status_block[1]);
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(&phy->sas_phy);
- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR);
+ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR);
break;
}
}
@@ -123,8 +122,8 @@
/**
* asd_get_attached_sas_addr -- extract/generate attached SAS address
- * phy: pointer to asd_phy
- * sas_addr: pointer to buffer where the SAS address is to be written
+ * @phy: pointer to asd_phy
+ * @sas_addr: pointer to buffer where the SAS address is to be written
*
* This function extracts the SAS address from an IDENTIFY frame
* received. If OOB is SATA, then a SAS address is generated from the
@@ -222,7 +221,6 @@
int edb_el = edb_id + ascb->edb_index;
struct asd_dma_tok *edb = ascb->ha->seq.edb_arr[edb_el];
struct asd_phy *phy = &ascb->ha->phys[phy_id];
- struct sas_ha_struct *sas_ha = phy->sas_phy.ha;
u16 size = ((dl->status_block[3] & 7) << 8) | dl->status_block[2];
size = min(size, (u16) sizeof(phy->frame_rcvd));
@@ -234,7 +232,7 @@
spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
asd_dump_frame_rcvd(phy, dl);
asd_form_port(ascb->ha, phy);
- sas_ha->notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED);
+ sas_notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED);
}
static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
@@ -270,7 +268,7 @@
asd_turn_led(asd_ha, phy_id, 0);
sas_phy_disconnected(sas_phy);
asd_deform_port(asd_ha, phy);
- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
if (retries_left == 0) {
int num = 1;
@@ -315,7 +313,7 @@
spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
sas_phy->sas_prim = ffs(cont);
spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
- sas_ha->notify_port_event(sas_phy,PORTE_BROADCAST_RCVD);
+ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
break;
case LmUNKNOWNP:
@@ -336,7 +334,7 @@
/* The sequencer disables all phys on that port.
* We have to re-enable the phys ourselves. */
asd_deform_port(asd_ha, phy);
- sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET);
+ sas_notify_port_event(sas_phy, PORTE_HARD_RESET);
break;
default:
@@ -567,7 +565,7 @@
/* the device is gone */
sas_phy_disconnected(sas_phy);
asd_deform_port(asd_ha, phy);
- sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT);
+ sas_notify_port_event(sas_phy, PORTE_TIMER_EVENT);
break;
default:
ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __func__,
@@ -706,11 +704,11 @@
switch (pd->max_sas_lrate) {
case SAS_LINK_RATE_6_0_GBPS:
*speed_mask &= ~SAS_SPEED_60_DIS;
- /* fall through*/
+ fallthrough;
default:
case SAS_LINK_RATE_3_0_GBPS:
*speed_mask &= ~SAS_SPEED_30_DIS;
- /* fall through*/
+ fallthrough;
case SAS_LINK_RATE_1_5_GBPS:
*speed_mask &= ~SAS_SPEED_15_DIS;
}
@@ -718,7 +716,7 @@
switch (pd->min_sas_lrate) {
case SAS_LINK_RATE_6_0_GBPS:
*speed_mask |= SAS_SPEED_30_DIS;
- /* fall through*/
+ fallthrough;
case SAS_LINK_RATE_3_0_GBPS:
*speed_mask |= SAS_SPEED_15_DIS;
default:
@@ -730,7 +728,7 @@
switch (pd->max_sata_lrate) {
case SAS_LINK_RATE_3_0_GBPS:
*speed_mask &= ~SATA_SPEED_30_DIS;
- /* fall through*/
+ fallthrough;
default:
case SAS_LINK_RATE_1_5_GBPS:
*speed_mask &= ~SATA_SPEED_15_DIS;
@@ -789,7 +787,7 @@
/* link reset retries, this should be nominal */
control_phy->link_reset_retries = 10;
- /* fall through */
+ fallthrough;
case RELEASE_SPINUP_HOLD: /* 0x02 */
/* decide the func_mask */
@@ -847,7 +845,7 @@
/**
* asd_ascb_timedout -- called when a pending SCB's timer has expired
- * @data: unsigned long, a pointer to the ascb in question
+ * @t: Timer context used to fetch the SCB
*
* This is the default timeout function which does the most necessary.
* Upper layers can implement their own timeout function, say to free
diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c
index 3ddc885..105adba 100644
--- a/drivers/scsi/aic94xx/aic94xx_sds.c
+++ b/drivers/scsi/aic94xx/aic94xx_sds.c
@@ -406,7 +406,7 @@
u8 sas_addr[SAS_ADDR_SIZE];
u8 pcba_sn[ASD_PCBA_SN_SIZE];
/* Here start the other segments */
- u8 linked_list[0];
+ u8 linked_list[];
} __attribute__ ((packed));
struct asd_manuf_phy_desc {
@@ -449,7 +449,7 @@
u8 type;
u8 node_desc_index;
u8 conn_desc_index;
- u8 _recvd[0];
+ u8 _recvd[];
} __attribute__ ((packed));
#if 0
@@ -478,12 +478,12 @@
u8 size_sideband_desc;
u32 _resvd;
u8 name[16];
- struct asd_ms_sb_desc sb_desc[0];
+ struct asd_ms_sb_desc sb_desc[];
} __attribute__ ((packed));
struct asd_nd_phy_desc {
u8 vp_attch_type;
- u8 attch_specific[0];
+ u8 attch_specific[];
} __attribute__ ((packed));
#if 0
@@ -503,7 +503,7 @@
u8 size_phy_desc;
u8 _resvd;
u8 name[16];
- struct asd_nd_phy_desc phy_desc[0];
+ struct asd_nd_phy_desc phy_desc[];
} __attribute__ ((packed));
struct asd_ms_conn_map {
@@ -518,7 +518,7 @@
u8 usage_model_id;
u32 _resvd;
struct asd_ms_conn_desc conn_desc[0];
- struct asd_ms_node_desc node_desc[0];
+ struct asd_ms_node_desc node_desc[];
} __attribute__ ((packed));
struct asd_ctrla_phy_entry {
@@ -542,7 +542,7 @@
u8 id0;
u8 id1;
__le16 next;
- u8 something_here[0];
+ u8 something_here[];
} __attribute__ ((packed));
static int asd_poll_flash(struct asd_ha_struct *asd_ha)
diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c
index 11853ec..c0f685c 100644
--- a/drivers/scsi/aic94xx/aic94xx_seq.c
+++ b/drivers/scsi/aic94xx/aic94xx_seq.c
@@ -582,6 +582,7 @@
/**
* asd_init_lseq_mip -- initialize LSEQ Mode independent pages 0-3
* @asd_ha: pointer to host adapter structure
+ * @lseq: link sequencer
*/
static void asd_init_lseq_mip(struct asd_ha_struct *asd_ha, u8 lseq)
{
@@ -669,6 +670,7 @@
/**
* asd_init_lseq_mdp -- initialize LSEQ mode dependent pages.
* @asd_ha: pointer to host adapter structure
+ * @lseq: link sequencer
*/
static void asd_init_lseq_mdp(struct asd_ha_struct *asd_ha, int lseq)
{
@@ -953,6 +955,7 @@
/**
* asd_init_lseq_cio -- initialize LmSEQ CIO registers
* @asd_ha: pointer to host adapter structure
+ * @lseq: link sequencer
*/
static void asd_init_lseq_cio(struct asd_ha_struct *asd_ha, int lseq)
{
@@ -1345,7 +1348,8 @@
/**
* asd_update_port_links -- update port_map_by_links and phy_is_up
- * @sas_phy: pointer to the phy which has been added to a port
+ * @asd_ha: pointer to host adapter structure
+ * @phy: pointer to the phy which has been added to a port
*
* 1) When a link reset has completed and we got BYTES DMAED with a
* valid frame we call this function for that phy, to indicate that
diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
index f814026..0eb6e20 100644
--- a/drivers/scsi/aic94xx/aic94xx_tmf.c
+++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
@@ -490,7 +490,7 @@
switch (tcs.dl_opcode) {
default:
res = asd_clear_nexus(task);
- /* fallthrough */
+ fallthrough;
case TC_NO_ERROR:
break;
/* The task hasn't been sent to the device xor
@@ -673,7 +673,7 @@
/**
* asd_query_task -- send a QUERY TASK TMF to an I_T_L_Q nexus
- * task: pointer to sas_task struct of interest
+ * @task: pointer to sas_task struct of interest
*
* Returns: TMF_RESP_FUNC_COMPLETE if the task is not in the task set,
* or TMF_RESP_FUNC_SUCC if the task is in the task set.
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
index 9220bcf..5d054d5 100644
--- a/drivers/scsi/arcmsr/arcmsr.h
+++ b/drivers/scsi/arcmsr/arcmsr.h
@@ -49,7 +49,7 @@
#define ARCMSR_MAX_OUTSTANDING_CMD 1024
#define ARCMSR_DEFAULT_OUTSTANDING_CMD 128
#define ARCMSR_MIN_OUTSTANDING_CMD 32
-#define ARCMSR_DRIVER_VERSION "v1.40.00.10-20190116"
+#define ARCMSR_DRIVER_VERSION "v1.50.00.02-20200819"
#define ARCMSR_SCSI_INITIATOR_ID 255
#define ARCMSR_MAX_XFER_SECTORS 512
#define ARCMSR_MAX_XFER_SECTORS_B 4096
@@ -80,6 +80,7 @@
#ifndef PCI_DEVICE_ID_ARECA_1884
#define PCI_DEVICE_ID_ARECA_1884 0x1884
#endif
+#define PCI_DEVICE_ID_ARECA_1886 0x188A
#define ARCMSR_HOURS (1000 * 60 * 60 * 4)
#define ARCMSR_MINUTES (1000 * 60 * 60)
/*
@@ -436,6 +437,21 @@
#define ARCMSR_HBEMU_DOORBELL_SYNC 0x100
#define ARCMSR_ARC188X_RESET_ADAPTER 0x00000004
#define ARCMSR_ARC1884_DiagWrite_ENABLE 0x00000080
+
+/*
+*******************************************************************************
+** SPEC. for Areca Type F adapter
+*******************************************************************************
+*/
+#define ARCMSR_SIGNATURE_1886 0x188617D3
+// Doorbell and interrupt definition are same as Type E adapter
+/* ARC-1886 doorbell sync */
+#define ARCMSR_HBFMU_DOORBELL_SYNC 0x100
+//set host rw buffer physical address at inbound message 0, 1 (low,high)
+#define ARCMSR_HBFMU_DOORBELL_SYNC1 0x300
+#define ARCMSR_HBFMU_MESSAGE_FIRMWARE_OK 0x80000000
+#define ARCMSR_HBFMU_MESSAGE_NO_VOLUME_CHANGE 0x20000000
+
/*
*******************************************************************************
** ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504)
@@ -720,6 +736,80 @@
uint32_t msgcode_rwbuffer[256]; /*2200 23FF*/
};
+/*
+*********************************************************************
+** Messaging Unit (MU) of Type F processor(LSI)
+*********************************************************************
+*/
+struct MessageUnit_F {
+ uint32_t iobound_doorbell; /*0000 0003*/
+ uint32_t write_sequence_3xxx; /*0004 0007*/
+ uint32_t host_diagnostic_3xxx; /*0008 000B*/
+ uint32_t posted_outbound_doorbell; /*000C 000F*/
+ uint32_t master_error_attribute; /*0010 0013*/
+ uint32_t master_error_address_low; /*0014 0017*/
+ uint32_t master_error_address_high; /*0018 001B*/
+ uint32_t hcb_size; /*001C 001F*/
+ uint32_t inbound_doorbell; /*0020 0023*/
+ uint32_t diagnostic_rw_data; /*0024 0027*/
+ uint32_t diagnostic_rw_address_low; /*0028 002B*/
+ uint32_t diagnostic_rw_address_high; /*002C 002F*/
+ uint32_t host_int_status; /*0030 0033*/
+ uint32_t host_int_mask; /*0034 0037*/
+ uint32_t dcr_data; /*0038 003B*/
+ uint32_t dcr_address; /*003C 003F*/
+ uint32_t inbound_queueport; /*0040 0043*/
+ uint32_t outbound_queueport; /*0044 0047*/
+ uint32_t hcb_pci_address_low; /*0048 004B*/
+ uint32_t hcb_pci_address_high; /*004C 004F*/
+ uint32_t iop_int_status; /*0050 0053*/
+ uint32_t iop_int_mask; /*0054 0057*/
+ uint32_t iop_inbound_queue_port; /*0058 005B*/
+ uint32_t iop_outbound_queue_port; /*005C 005F*/
+ uint32_t inbound_free_list_index; /*0060 0063*/
+ uint32_t inbound_post_list_index; /*0064 0067*/
+ uint32_t reply_post_producer_index; /*0068 006B*/
+ uint32_t reply_post_consumer_index; /*006C 006F*/
+ uint32_t inbound_doorbell_clear; /*0070 0073*/
+ uint32_t i2o_message_unit_control; /*0074 0077*/
+ uint32_t last_used_message_source_address_low; /*0078 007B*/
+ uint32_t last_used_message_source_address_high; /*007C 007F*/
+ uint32_t pull_mode_data_byte_count[4]; /*0080 008F*/
+ uint32_t message_dest_address_index; /*0090 0093*/
+ uint32_t done_queue_not_empty_int_counter_timer; /*0094 0097*/
+ uint32_t utility_A_int_counter_timer; /*0098 009B*/
+ uint32_t outbound_doorbell; /*009C 009F*/
+ uint32_t outbound_doorbell_clear; /*00A0 00A3*/
+ uint32_t message_source_address_index; /*00A4 00A7*/
+ uint32_t message_done_queue_index; /*00A8 00AB*/
+ uint32_t reserved0; /*00AC 00AF*/
+ uint32_t inbound_msgaddr0; /*00B0 00B3*/
+ uint32_t inbound_msgaddr1; /*00B4 00B7*/
+ uint32_t outbound_msgaddr0; /*00B8 00BB*/
+ uint32_t outbound_msgaddr1; /*00BC 00BF*/
+ uint32_t inbound_queueport_low; /*00C0 00C3*/
+ uint32_t inbound_queueport_high; /*00C4 00C7*/
+ uint32_t outbound_queueport_low; /*00C8 00CB*/
+ uint32_t outbound_queueport_high; /*00CC 00CF*/
+ uint32_t iop_inbound_queue_port_low; /*00D0 00D3*/
+ uint32_t iop_inbound_queue_port_high; /*00D4 00D7*/
+ uint32_t iop_outbound_queue_port_low; /*00D8 00DB*/
+ uint32_t iop_outbound_queue_port_high; /*00DC 00DF*/
+ uint32_t message_dest_queue_port_low; /*00E0 00E3*/
+ uint32_t message_dest_queue_port_high; /*00E4 00E7*/
+ uint32_t last_used_message_dest_address_low; /*00E8 00EB*/
+ uint32_t last_used_message_dest_address_high; /*00EC 00EF*/
+ uint32_t message_done_queue_base_address_low; /*00F0 00F3*/
+ uint32_t message_done_queue_base_address_high; /*00F4 00F7*/
+ uint32_t host_diagnostic; /*00F8 00FB*/
+ uint32_t write_sequence; /*00FC 00FF*/
+ uint32_t reserved1[46]; /*0100 01B7*/
+ uint32_t reply_post_producer_index1; /*01B8 01BB*/
+ uint32_t reply_post_consumer_index1; /*01BC 01BF*/
+};
+
+#define MESG_RW_BUFFER_SIZE (256 * 3)
+
typedef struct deliver_completeQ {
uint16_t cmdFlag;
uint16_t cmdSMID;
@@ -739,6 +829,7 @@
#define ACB_ADAPTER_TYPE_C 0x00000002 /* hbc L IOP */
#define ACB_ADAPTER_TYPE_D 0x00000003 /* hbd M IOP */
#define ACB_ADAPTER_TYPE_E 0x00000004 /* hba L IOP */
+#define ACB_ADAPTER_TYPE_F 0x00000005 /* hba L IOP */
u32 ioqueue_size;
struct pci_dev * pdev;
struct Scsi_Host * host;
@@ -760,10 +851,16 @@
struct MessageUnit_C __iomem *pmuC;
struct MessageUnit_D *pmuD;
struct MessageUnit_E __iomem *pmuE;
+ struct MessageUnit_F __iomem *pmuF;
};
/* message unit ATU inbound base address0 */
void __iomem *mem_base0;
void __iomem *mem_base1;
+ //0x000 - COMPORT_IN (Host sent to ROC)
+ uint32_t *message_wbuffer;
+ //0x100 - COMPORT_OUT (ROC sent to Host)
+ uint32_t *message_rbuffer;
+ uint32_t *msgcode_rwbuffer; //0x200 - BIOS_AREA
uint32_t acb_flags;
u16 dev_id;
uint8_t adapter_index;
@@ -836,8 +933,6 @@
#define FW_NORMAL 0x0000
#define FW_BOG 0x0001
#define FW_DEADLOCK 0x0010
- atomic_t rq_map_token;
- atomic_t ante_token_value;
uint32_t maxOutstanding;
int vector_count;
uint32_t maxFreeCCB;
@@ -848,6 +943,7 @@
uint32_t out_doorbell;
uint32_t completionQ_entry;
pCompletion_Q pCompletionQ;
+ uint32_t completeQ_size;
};/* HW_DEVICE_EXTENSION */
/*
*******************************************************************************
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
index 259d9c2..57be960 100644
--- a/drivers/scsi/arcmsr/arcmsr_attr.c
+++ b/drivers/scsi/arcmsr/arcmsr_attr.c
@@ -41,7 +41,7 @@
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
** For history of changes, see Documentation/scsi/ChangeLog.arcmsr
-** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt
+** Firmware Specification, see Documentation/scsi/arcmsr_spec.rst
*******************************************************************************
*/
#include <linux/module.h>
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 88053b1..9294a2c 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -41,7 +41,7 @@
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
** For history of changes, see Documentation/scsi/ChangeLog.arcmsr
-** Firmware Specification, see Documentation/scsi/arcmsr_spec.txt
+** Firmware Specification, see Documentation/scsi/arcmsr_spec.rst
*******************************************************************************
*/
#include <linux/module.h>
@@ -133,6 +133,7 @@
static void arcmsr_hbaD_message_isr(struct AdapterControlBlock *acb);
static void arcmsr_hbaE_message_isr(struct AdapterControlBlock *acb);
static void arcmsr_hbaE_postqueue_isr(struct AdapterControlBlock *acb);
+static void arcmsr_hbaF_postqueue_isr(struct AdapterControlBlock *acb);
static void arcmsr_hardware_reset(struct AdapterControlBlock *acb);
static const char *arcmsr_info(struct Scsi_Host *);
static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
@@ -209,6 +210,8 @@
.driver_data = ACB_ADAPTER_TYPE_C},
{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1884),
.driver_data = ACB_ADAPTER_TYPE_E},
+ {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1886),
+ .driver_data = ACB_ADAPTER_TYPE_F},
{0, 0}, /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, arcmsr_device_id_table);
@@ -232,12 +235,12 @@
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_B:
case ACB_ADAPTER_TYPE_D:
- case ACB_ADAPTER_TYPE_E: {
+ case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F:
dma_free_coherent(&acb->pdev->dev, acb->ioqueue_size,
acb->dma_coherent2, acb->dma_coherent_handle2);
break;
}
- }
}
static bool arcmsr_remap_pciregion(struct AdapterControlBlock *acb)
@@ -270,7 +273,7 @@
break;
}
case ACB_ADAPTER_TYPE_C:{
- acb->pmuC = ioremap_nocache(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
+ acb->pmuC = ioremap(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
if (!acb->pmuC) {
printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", acb->host->host_no);
return false;
@@ -283,11 +286,10 @@
}
case ACB_ADAPTER_TYPE_D: {
void __iomem *mem_base0;
- unsigned long addr, range, flags;
+ unsigned long addr, range;
addr = (unsigned long)pci_resource_start(pdev, 0);
range = pci_resource_len(pdev, 0);
- flags = pci_resource_flags(pdev, 0);
mem_base0 = ioremap(addr, range);
if (!mem_base0) {
pr_notice("arcmsr%d: memory mapping region fail\n",
@@ -311,6 +313,19 @@
acb->out_doorbell = 0;
break;
}
+ case ACB_ADAPTER_TYPE_F: {
+ acb->pmuF = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+ if (!acb->pmuF) {
+ pr_notice("arcmsr%d: memory mapping region fail\n",
+ acb->host->host_no);
+ return false;
+ }
+ writel(0, &acb->pmuF->host_int_status); /* clear interrupt */
+ writel(ARCMSR_HBFMU_DOORBELL_SYNC, &acb->pmuF->iobound_doorbell);
+ acb->in_doorbell = 0;
+ acb->out_doorbell = 0;
+ break;
+ }
}
return true;
}
@@ -318,26 +333,25 @@
static void arcmsr_unmap_pciregion(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
- case ACB_ADAPTER_TYPE_A:{
+ case ACB_ADAPTER_TYPE_A:
iounmap(acb->pmuA);
- }
- break;
- case ACB_ADAPTER_TYPE_B:{
+ break;
+ case ACB_ADAPTER_TYPE_B:
iounmap(acb->mem_base0);
iounmap(acb->mem_base1);
- }
-
- break;
- case ACB_ADAPTER_TYPE_C:{
+ break;
+ case ACB_ADAPTER_TYPE_C:
iounmap(acb->pmuC);
- }
- break;
+ break;
case ACB_ADAPTER_TYPE_D:
iounmap(acb->mem_base0);
break;
case ACB_ADAPTER_TYPE_E:
iounmap(acb->pmuE);
break;
+ case ACB_ADAPTER_TYPE_F:
+ iounmap(acb->pmuF);
+ break;
}
}
@@ -353,16 +367,11 @@
static int arcmsr_bios_param(struct scsi_device *sdev,
struct block_device *bdev, sector_t capacity, int *geom)
{
- int ret, heads, sectors, cylinders, total_capacity;
- unsigned char *buffer;/* return copy of block device's partition table */
+ int heads, sectors, cylinders, total_capacity;
- buffer = scsi_bios_ptable(bdev);
- if (buffer) {
- ret = scsi_partsize(buffer, capacity, &geom[2], &geom[0], &geom[1]);
- kfree(buffer);
- if (ret != -1)
- return ret;
- }
+ if (scsi_partsize(bdev, capacity, geom))
+ return 0;
+
total_capacity = capacity;
heads = 64;
sectors = 32;
@@ -558,23 +567,20 @@
{
switch (acb->adapter_type) {
- case ACB_ADAPTER_TYPE_A: {
+ case ACB_ADAPTER_TYPE_A:
arcmsr_hbaA_flush_cache(acb);
- }
break;
-
- case ACB_ADAPTER_TYPE_B: {
+ case ACB_ADAPTER_TYPE_B:
arcmsr_hbaB_flush_cache(acb);
- }
break;
- case ACB_ADAPTER_TYPE_C: {
+ case ACB_ADAPTER_TYPE_C:
arcmsr_hbaC_flush_cache(acb);
- }
break;
case ACB_ADAPTER_TYPE_D:
arcmsr_hbaD_flush_cache(acb);
break;
case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F:
arcmsr_hbaE_flush_cache(acb);
break;
}
@@ -632,6 +638,27 @@
reg->msgcode_rwbuffer = MEM_BASE0(ARCMSR_ARC1214_MESSAGE_RWBUFFER);
}
+static void arcmsr_hbaF_assign_regAddr(struct AdapterControlBlock *acb)
+{
+ dma_addr_t host_buffer_dma;
+ struct MessageUnit_F __iomem *pmuF;
+
+ memset(acb->dma_coherent2, 0xff, acb->completeQ_size);
+ acb->message_wbuffer = (uint32_t *)round_up((unsigned long)acb->dma_coherent2 +
+ acb->completeQ_size, 4);
+ acb->message_rbuffer = ((void *)acb->message_wbuffer) + 0x100;
+ acb->msgcode_rwbuffer = ((void *)acb->message_wbuffer) + 0x200;
+ memset((void *)acb->message_wbuffer, 0, MESG_RW_BUFFER_SIZE);
+ host_buffer_dma = round_up(acb->dma_coherent_handle2 + acb->completeQ_size, 4);
+ pmuF = acb->pmuF;
+ /* host buffer low address, bit0:1 all buffer active */
+ writel(lower_32_bits(host_buffer_dma | 1), &pmuF->inbound_msgaddr0);
+ /* host buffer high address */
+ writel(upper_32_bits(host_buffer_dma), &pmuF->inbound_msgaddr1);
+ /* set host buffer physical address */
+ writel(ARCMSR_HBFMU_DOORBELL_SYNC1, &pmuF->iobound_doorbell);
+}
+
static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb)
{
bool rtn = true;
@@ -685,6 +712,28 @@
acb->doneq_index = 0;
}
break;
+ case ACB_ADAPTER_TYPE_F: {
+ uint32_t QueueDepth;
+ uint32_t depthTbl[] = {256, 512, 1024, 128, 64, 32};
+
+ arcmsr_wait_firmware_ready(acb);
+ QueueDepth = depthTbl[readl(&acb->pmuF->outbound_msgaddr1) & 7];
+ acb->completeQ_size = sizeof(struct deliver_completeQ) * QueueDepth + 128;
+ acb->ioqueue_size = roundup(acb->completeQ_size + MESG_RW_BUFFER_SIZE, 32);
+ dma_coherent = dma_alloc_coherent(&pdev->dev, acb->ioqueue_size,
+ &dma_coherent_handle, GFP_KERNEL);
+ if (!dma_coherent) {
+ pr_notice("arcmsr%d: DMA allocation failed\n", acb->host->host_no);
+ return false;
+ }
+ acb->dma_coherent_handle2 = dma_coherent_handle;
+ acb->dma_coherent2 = dma_coherent;
+ acb->pCompletionQ = dma_coherent;
+ acb->completionQ_entry = acb->completeQ_size / sizeof(struct deliver_completeQ);
+ acb->doneq_index = 0;
+ arcmsr_hbaF_assign_regAddr(acb);
+ }
+ break;
default:
break;
}
@@ -719,7 +768,8 @@
acb->host->sg_tablesize = max_sg_entrys;
roundup_ccbsize = roundup(sizeof(struct CommandControlBlock) + (max_sg_entrys - 1) * sizeof(struct SG64ENTRY), 32);
acb->uncache_size = roundup_ccbsize * acb->maxFreeCCB;
- acb->uncache_size += acb->ioqueue_size;
+ if (acb->adapter_type != ACB_ADAPTER_TYPE_F)
+ acb->uncache_size += acb->ioqueue_size;
dma_coherent = dma_alloc_coherent(&pdev->dev, acb->uncache_size, &dma_coherent_handle, GFP_KERNEL);
if(!dma_coherent){
printk(KERN_NOTICE "arcmsr%d: dma_alloc_coherent got error\n", acb->host->host_no);
@@ -742,6 +792,7 @@
case ACB_ADAPTER_TYPE_C:
case ACB_ADAPTER_TYPE_D:
case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F:
ccb_tmp->cdb_phyaddr = cdb_phyaddr;
break;
}
@@ -760,8 +811,10 @@
ccb_tmp = (struct CommandControlBlock *)((unsigned long)ccb_tmp + roundup_ccbsize);
dma_coherent_handle = next_ccb_phy;
}
- acb->dma_coherent_handle2 = dma_coherent_handle;
- acb->dma_coherent2 = ccb_tmp;
+ if (acb->adapter_type != ACB_ADAPTER_TYPE_F) {
+ acb->dma_coherent_handle2 = dma_coherent_handle;
+ acb->dma_coherent2 = ccb_tmp;
+ }
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_B:
acb->pmuB = (struct MessageUnit_B *)acb->dma_coherent2;
@@ -791,7 +844,6 @@
struct scsi_device *psdev;
char diff, temp;
- acb->acb_flags &= ~ACB_F_MSG_GET_CONFIG;
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
struct MessageUnit_A __iomem *reg = acb->pmuA;
@@ -828,8 +880,12 @@
devicemap = (char __iomem *)(®->msgcode_rwbuffer[21]);
break;
}
+ case ACB_ADAPTER_TYPE_F: {
+ signature = (uint32_t __iomem *)(&acb->msgcode_rwbuffer[0]);
+ devicemap = (char __iomem *)(&acb->msgcode_rwbuffer[21]);
+ break;
+ }
}
- atomic_inc(&acb->rq_map_token);
if (readl(signature) != ARCMSR_SIGNATURE_GET_CONFIG)
return;
for (target = 0; target < ARCMSR_MAX_TARGETID - 1;
@@ -860,6 +916,7 @@
devicemap++;
acb_dev_map++;
}
+ acb->acb_flags &= ~ACB_F_MSG_GET_CONFIG;
}
static int
@@ -912,8 +969,6 @@
static void arcmsr_init_get_devmap_timer(struct AdapterControlBlock *pacb)
{
INIT_WORK(&pacb->arcmsr_do_message_isr_bh, arcmsr_message_isr_bh_fn);
- atomic_set(&pacb->rq_map_token, 16);
- atomic_set(&pacb->ante_token_value, 16);
pacb->fw_flag = FW_NORMAL;
timer_setup(&pacb->eternal_timer, arcmsr_request_device_map, 0);
pacb->eternal_timer.expires = jiffies + msecs_to_jiffies(6 * HZ);
@@ -1015,7 +1070,8 @@
if(!error){
goto free_hbb_mu;
}
- arcmsr_free_io_queue(acb);
+ if (acb->adapter_type != ACB_ADAPTER_TYPE_F)
+ arcmsr_free_io_queue(acb);
error = arcmsr_alloc_ccb_pool(acb);
if(error){
goto unmap_pci_region;
@@ -1072,12 +1128,11 @@
static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state)
{
- uint32_t intmask_org;
struct Scsi_Host *host = pci_get_drvdata(pdev);
struct AdapterControlBlock *acb =
(struct AdapterControlBlock *)host->hostdata;
- intmask_org = arcmsr_disable_outbound_ints(acb);
+ arcmsr_disable_outbound_ints(acb);
arcmsr_free_irq(pdev, acb);
del_timer_sync(&acb->eternal_timer);
if (set_date_time)
@@ -1129,6 +1184,14 @@
acb->out_doorbell = 0;
acb->doneq_index = 0;
break;
+ case ACB_ADAPTER_TYPE_F:
+ writel(0, &acb->pmuF->host_int_status);
+ writel(ARCMSR_HBFMU_DOORBELL_SYNC, &acb->pmuF->iobound_doorbell);
+ acb->in_doorbell = 0;
+ acb->out_doorbell = 0;
+ acb->doneq_index = 0;
+ arcmsr_hbaF_assign_regAddr(acb);
+ break;
}
arcmsr_iop_init(acb);
arcmsr_init_get_devmap_timer(acb);
@@ -1141,6 +1204,8 @@
controller_unregister:
scsi_remove_host(host);
arcmsr_free_ccb_pool(acb);
+ if (acb->adapter_type == ACB_ADAPTER_TYPE_F)
+ arcmsr_free_io_queue(acb);
arcmsr_unmap_pciregion(acb);
pci_release_regions(pdev);
scsi_host_put(host);
@@ -1220,25 +1285,20 @@
{
uint8_t rtnval = 0;
switch (acb->adapter_type) {
- case ACB_ADAPTER_TYPE_A: {
+ case ACB_ADAPTER_TYPE_A:
rtnval = arcmsr_hbaA_abort_allcmd(acb);
- }
break;
-
- case ACB_ADAPTER_TYPE_B: {
+ case ACB_ADAPTER_TYPE_B:
rtnval = arcmsr_hbaB_abort_allcmd(acb);
- }
break;
-
- case ACB_ADAPTER_TYPE_C: {
+ case ACB_ADAPTER_TYPE_C:
rtnval = arcmsr_hbaC_abort_allcmd(acb);
- }
break;
-
case ACB_ADAPTER_TYPE_D:
rtnval = arcmsr_hbaD_abort_allcmd(acb);
break;
case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F:
rtnval = arcmsr_hbaE_abort_allcmd(acb);
break;
}
@@ -1314,7 +1374,8 @@
writel(ARCMSR_ARC1214_ALL_INT_DISABLE, reg->pcief0_int_enable);
}
break;
- case ACB_ADAPTER_TYPE_E: {
+ case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F: {
struct MessageUnit_E __iomem *reg = acb->pmuE;
orig_mask = readl(®->host_int_mask);
writel(orig_mask | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR | ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR, ®->host_int_mask);
@@ -1400,7 +1461,7 @@
, pCCB->acb
, pCCB->startdone
, atomic_read(&acb->ccboutstandingcount));
- return;
+ return;
}
arcmsr_report_ccb_state(acb, pCCB, error);
}
@@ -1412,7 +1473,7 @@
struct ARCMSR_CDB *pARCMSR_CDB;
bool error;
struct CommandControlBlock *pCCB;
- unsigned long ccb_cdb_phy, cdb_phy_hipart;
+ unsigned long ccb_cdb_phy;
switch (acb->adapter_type) {
@@ -1494,8 +1555,6 @@
((toggle ^ 0x4000) + 1);
doneq_index = pmu->doneq_index;
spin_unlock_irqrestore(&acb->doneq_lock, flags);
- cdb_phy_hipart = pmu->done_qbuffer[doneq_index &
- 0xFFF].addressHigh;
addressLow = pmu->done_qbuffer[doneq_index &
0xFFF].addressLow;
ccb_cdb_phy = (addressLow & 0xFFFFFFF0);
@@ -1523,6 +1582,9 @@
case ACB_ADAPTER_TYPE_E:
arcmsr_hbaE_postqueue_isr(acb);
break;
+ case ACB_ADAPTER_TYPE_F:
+ arcmsr_hbaF_postqueue_isr(acb);
+ break;
}
}
@@ -1577,6 +1639,8 @@
pdev = acb->pdev;
arcmsr_free_irq(pdev, acb);
arcmsr_free_ccb_pool(acb);
+ if (acb->adapter_type == ACB_ADAPTER_TYPE_F)
+ arcmsr_free_io_queue(acb);
arcmsr_unmap_pciregion(acb);
pci_release_regions(pdev);
scsi_host_put(host);
@@ -1634,6 +1698,8 @@
}
arcmsr_free_irq(pdev, acb);
arcmsr_free_ccb_pool(acb);
+ if (acb->adapter_type == ACB_ADAPTER_TYPE_F)
+ arcmsr_free_io_queue(acb);
arcmsr_unmap_pciregion(acb);
pci_release_regions(pdev);
scsi_host_put(host);
@@ -1711,7 +1777,8 @@
writel(intmask_org | mask, reg->pcief0_int_enable);
break;
}
- case ACB_ADAPTER_TYPE_E: {
+ case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F: {
struct MessageUnit_E __iomem *reg = acb->pmuE;
mask = ~(ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR | ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR);
@@ -1855,6 +1922,23 @@
writel(ccb_post_stamp, &pmu->inbound_queueport_low);
break;
}
+ case ACB_ADAPTER_TYPE_F: {
+ struct MessageUnit_F __iomem *pmu = acb->pmuF;
+ u32 ccb_post_stamp, arc_cdb_size;
+
+ if (ccb->arc_cdb_size <= 0x300)
+ arc_cdb_size = (ccb->arc_cdb_size - 1) >> 6 | 1;
+ else {
+ arc_cdb_size = ((ccb->arc_cdb_size + 0xff) >> 8) + 2;
+ if (arc_cdb_size > 0xF)
+ arc_cdb_size = 0xF;
+ arc_cdb_size = (arc_cdb_size << 1) | 1;
+ }
+ ccb_post_stamp = (ccb->smid | arc_cdb_size);
+ writel(0, &pmu->inbound_queueport_high);
+ writel(ccb_post_stamp, &pmu->inbound_queueport_low);
+ break;
+ }
}
}
@@ -1925,23 +2009,20 @@
static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
- case ACB_ADAPTER_TYPE_A: {
+ case ACB_ADAPTER_TYPE_A:
arcmsr_hbaA_stop_bgrb(acb);
- }
break;
-
- case ACB_ADAPTER_TYPE_B: {
+ case ACB_ADAPTER_TYPE_B:
arcmsr_hbaB_stop_bgrb(acb);
- }
break;
- case ACB_ADAPTER_TYPE_C: {
+ case ACB_ADAPTER_TYPE_C:
arcmsr_hbaC_stop_bgrb(acb);
- }
break;
case ACB_ADAPTER_TYPE_D:
arcmsr_hbaD_stop_bgrb(acb);
break;
case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F:
arcmsr_hbaE_stop_bgrb(acb);
break;
}
@@ -1960,7 +2041,6 @@
writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell);
}
break;
-
case ACB_ADAPTER_TYPE_B: {
struct MessageUnit_B *reg = acb->pmuB;
writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell);
@@ -1978,7 +2058,8 @@
reg->inbound_doorbell);
}
break;
- case ACB_ADAPTER_TYPE_E: {
+ case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F: {
struct MessageUnit_E __iomem *reg = acb->pmuE;
acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
writel(acb->out_doorbell, ®->iobound_doorbell);
@@ -2024,7 +2105,8 @@
reg->inbound_doorbell);
}
break;
- case ACB_ADAPTER_TYPE_E: {
+ case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F: {
struct MessageUnit_E __iomem *reg = acb->pmuE;
acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_WRITE_OK;
writel(acb->out_doorbell, ®->iobound_doorbell);
@@ -2043,7 +2125,6 @@
qbuffer = (struct QBUFFER __iomem *)®->message_rbuffer;
}
break;
-
case ACB_ADAPTER_TYPE_B: {
struct MessageUnit_B *reg = acb->pmuB;
qbuffer = (struct QBUFFER __iomem *)reg->message_rbuffer;
@@ -2064,6 +2145,10 @@
qbuffer = (struct QBUFFER __iomem *)®->message_rbuffer;
}
break;
+ case ACB_ADAPTER_TYPE_F: {
+ qbuffer = (struct QBUFFER __iomem *)acb->message_rbuffer;
+ }
+ break;
}
return qbuffer;
}
@@ -2078,7 +2163,6 @@
pqbuffer = (struct QBUFFER __iomem *) ®->message_wbuffer;
}
break;
-
case ACB_ADAPTER_TYPE_B: {
struct MessageUnit_B *reg = acb->pmuB;
pqbuffer = (struct QBUFFER __iomem *)reg->message_wbuffer;
@@ -2099,6 +2183,9 @@
pqbuffer = (struct QBUFFER __iomem *)®->message_wbuffer;
}
break;
+ case ACB_ADAPTER_TYPE_F:
+ pqbuffer = (struct QBUFFER __iomem *)acb->message_wbuffer;
+ break;
}
return pqbuffer;
}
@@ -2337,10 +2424,17 @@
static void arcmsr_hbaE_doorbell_isr(struct AdapterControlBlock *pACB)
{
- uint32_t outbound_doorbell, in_doorbell, tmp;
+ uint32_t outbound_doorbell, in_doorbell, tmp, i;
struct MessageUnit_E __iomem *reg = pACB->pmuE;
- in_doorbell = readl(®->iobound_doorbell);
+ if (pACB->adapter_type == ACB_ADAPTER_TYPE_F) {
+ for (i = 0; i < 5; i++) {
+ in_doorbell = readl(®->iobound_doorbell);
+ if (in_doorbell != 0)
+ break;
+ }
+ } else
+ in_doorbell = readl(®->iobound_doorbell);
outbound_doorbell = in_doorbell ^ pACB->in_doorbell;
do {
writel(0, ®->host_int_status); /* clear interrupt */
@@ -2450,7 +2544,7 @@
struct MessageUnit_D *pmu;
struct ARCMSR_CDB *arcmsr_cdb;
struct CommandControlBlock *ccb;
- unsigned long flags, ccb_cdb_phy, cdb_phy_hipart;
+ unsigned long flags, ccb_cdb_phy;
spin_lock_irqsave(&acb->doneq_lock, flags);
pmu = acb->pmuD;
@@ -2464,8 +2558,6 @@
pmu->doneq_index = index_stripped ? (index_stripped | toggle) :
((toggle ^ 0x4000) + 1);
doneq_index = pmu->doneq_index;
- cdb_phy_hipart = pmu->done_qbuffer[doneq_index &
- 0xFFF].addressHigh;
addressLow = pmu->done_qbuffer[doneq_index &
0xFFF].addressLow;
ccb_cdb_phy = (addressLow & 0xFFFFFFF0);
@@ -2515,6 +2607,36 @@
spin_unlock_irqrestore(&acb->doneq_lock, flags);
}
+static void arcmsr_hbaF_postqueue_isr(struct AdapterControlBlock *acb)
+{
+ uint32_t doneq_index;
+ uint16_t cmdSMID;
+ int error;
+ struct MessageUnit_F __iomem *phbcmu;
+ struct CommandControlBlock *ccb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&acb->doneq_lock, flags);
+ doneq_index = acb->doneq_index;
+ phbcmu = acb->pmuF;
+ while (1) {
+ cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
+ if (cmdSMID == 0xffff)
+ break;
+ ccb = acb->pccb_pool[cmdSMID];
+ error = (acb->pCompletionQ[doneq_index].cmdFlag &
+ ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? true : false;
+ arcmsr_drain_donequeue(acb, ccb, error);
+ acb->pCompletionQ[doneq_index].cmdSMID = 0xffff;
+ doneq_index++;
+ if (doneq_index >= acb->completionQ_entry)
+ doneq_index = 0;
+ }
+ acb->doneq_index = doneq_index;
+ writel(doneq_index, &phbcmu->reply_post_consumer_index);
+ spin_unlock_irqrestore(&acb->doneq_lock, flags);
+}
+
/*
**********************************************************************************
** Handle a message interrupt
@@ -2705,21 +2827,46 @@
return IRQ_HANDLED;
}
+static irqreturn_t arcmsr_hbaF_handle_isr(struct AdapterControlBlock *pACB)
+{
+ uint32_t host_interrupt_status;
+ struct MessageUnit_F __iomem *phbcmu = pACB->pmuF;
+
+ host_interrupt_status = readl(&phbcmu->host_int_status) &
+ (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR |
+ ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR);
+ if (!host_interrupt_status)
+ return IRQ_NONE;
+ do {
+ /* MU post queue interrupts*/
+ if (host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR)
+ arcmsr_hbaF_postqueue_isr(pACB);
+
+ /* MU ioctl transfer doorbell interrupts*/
+ if (host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR)
+ arcmsr_hbaE_doorbell_isr(pACB);
+
+ host_interrupt_status = readl(&phbcmu->host_int_status);
+ } while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR |
+ ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR));
+ return IRQ_HANDLED;
+}
+
static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A:
return arcmsr_hbaA_handle_isr(acb);
- break;
case ACB_ADAPTER_TYPE_B:
return arcmsr_hbaB_handle_isr(acb);
- break;
case ACB_ADAPTER_TYPE_C:
return arcmsr_hbaC_handle_isr(acb);
case ACB_ADAPTER_TYPE_D:
return arcmsr_hbaD_handle_isr(acb);
case ACB_ADAPTER_TYPE_E:
return arcmsr_hbaE_handle_isr(acb);
+ case ACB_ADAPTER_TYPE_F:
+ return arcmsr_hbaF_handle_isr(acb);
default:
return IRQ_NONE;
}
@@ -3268,6 +3415,31 @@
return true;
}
+static bool arcmsr_hbaF_get_config(struct AdapterControlBlock *pACB)
+{
+ struct MessageUnit_F __iomem *reg = pACB->pmuF;
+ uint32_t intmask_org;
+
+ /* disable all outbound interrupt */
+ intmask_org = readl(®->host_int_mask); /* disable outbound message0 int */
+ writel(intmask_org | ARCMSR_HBEMU_ALL_INTMASKENABLE, ®->host_int_mask);
+ /* wait firmware ready */
+ arcmsr_wait_firmware_ready(pACB);
+ /* post "get config" instruction */
+ writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0);
+
+ pACB->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+ writel(pACB->out_doorbell, ®->iobound_doorbell);
+ /* wait message ready */
+ if (!arcmsr_hbaE_wait_msgint_ready(pACB)) {
+ pr_notice("arcmsr%d: wait get adapter firmware miscellaneous data timeout\n",
+ pACB->host->host_no);
+ return false;
+ }
+ arcmsr_get_adapter_config(pACB, pACB->msgcode_rwbuffer);
+ return true;
+}
+
static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
{
bool rtn = false;
@@ -3288,6 +3460,9 @@
case ACB_ADAPTER_TYPE_E:
rtn = arcmsr_hbaE_get_config(acb);
break;
+ case ACB_ADAPTER_TYPE_F:
+ rtn = arcmsr_hbaF_get_config(acb);
+ break;
default:
break;
}
@@ -3476,8 +3651,8 @@
, pCCB->pcmd->device->id
, (u32)pCCB->pcmd->device->lun
, pCCB);
- pCCB->pcmd->result = DID_ABORT << 16;
- arcmsr_ccb_complete(pCCB);
+ pCCB->pcmd->result = DID_ABORT << 16;
+ arcmsr_ccb_complete(pCCB);
continue;
}
printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb"
@@ -3500,7 +3675,7 @@
bool error;
uint32_t poll_ccb_done = 0, poll_count = 0, flag_ccb;
int rtn, doneq_index, index_stripped, outbound_write_pointer, toggle;
- unsigned long flags, ccb_cdb_phy, cdb_phy_hipart;
+ unsigned long flags, ccb_cdb_phy;
struct ARCMSR_CDB *arcmsr_cdb;
struct CommandControlBlock *pCCB;
struct MessageUnit_D *pmu = acb->pmuD;
@@ -3532,8 +3707,6 @@
((toggle ^ 0x4000) + 1);
doneq_index = pmu->doneq_index;
spin_unlock_irqrestore(&acb->doneq_lock, flags);
- cdb_phy_hipart = pmu->done_qbuffer[doneq_index &
- 0xFFF].addressHigh;
flag_ccb = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow;
ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0);
if (acb->cdb_phyadd_hipart)
@@ -3647,23 +3820,20 @@
int rtn = 0;
switch (acb->adapter_type) {
- case ACB_ADAPTER_TYPE_A: {
+ case ACB_ADAPTER_TYPE_A:
rtn = arcmsr_hbaA_polling_ccbdone(acb, poll_ccb);
- }
break;
-
- case ACB_ADAPTER_TYPE_B: {
+ case ACB_ADAPTER_TYPE_B:
rtn = arcmsr_hbaB_polling_ccbdone(acb, poll_ccb);
- }
break;
- case ACB_ADAPTER_TYPE_C: {
+ case ACB_ADAPTER_TYPE_C:
rtn = arcmsr_hbaC_polling_ccbdone(acb, poll_ccb);
- }
break;
case ACB_ADAPTER_TYPE_D:
rtn = arcmsr_hbaD_polling_ccbdone(acb, poll_ccb);
break;
case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F:
rtn = arcmsr_hbaE_polling_ccbdone(acb, poll_ccb);
break;
}
@@ -3744,6 +3914,16 @@
writel(pacb->out_doorbell, ®->iobound_doorbell);
break;
}
+ case ACB_ADAPTER_TYPE_F: {
+ struct MessageUnit_F __iomem *reg = pacb->pmuF;
+
+ pacb->msgcode_rwbuffer[0] = datetime.b.msg_time[0];
+ pacb->msgcode_rwbuffer[1] = datetime.b.msg_time[1];
+ writel(ARCMSR_INBOUND_MESG0_SYNC_TIMER, ®->inbound_msgaddr0);
+ pacb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+ writel(pacb->out_doorbell, ®->iobound_doorbell);
+ break;
+ }
}
if (sys_tz.tz_minuteswest)
next_time = ARCMSR_HOURS;
@@ -3769,6 +3949,7 @@
dma_coherent_handle = acb->dma_coherent_handle2;
break;
case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F:
dma_coherent_handle = acb->dma_coherent_handle +
offsetof(struct CommandControlBlock, arcmsr_cdb);
break;
@@ -3886,11 +4067,8 @@
writel(cdb_phyaddr, ®->msgcode_rwbuffer[2]);
writel(cdb_phyaddr_hi32, ®->msgcode_rwbuffer[3]);
writel(acb->ccbsize, ®->msgcode_rwbuffer[4]);
- dma_coherent_handle = acb->dma_coherent_handle2;
- cdb_phyaddr = (uint32_t)(dma_coherent_handle & 0xffffffff);
- cdb_phyaddr_hi32 = (uint32_t)((dma_coherent_handle >> 16) >> 16);
- writel(cdb_phyaddr, ®->msgcode_rwbuffer[5]);
- writel(cdb_phyaddr_hi32, ®->msgcode_rwbuffer[6]);
+ writel(lower_32_bits(acb->dma_coherent_handle2), ®->msgcode_rwbuffer[5]);
+ writel(upper_32_bits(acb->dma_coherent_handle2), ®->msgcode_rwbuffer[6]);
writel(acb->ioqueue_size, ®->msgcode_rwbuffer[7]);
writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, ®->inbound_msgaddr0);
acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
@@ -3902,6 +4080,27 @@
}
}
break;
+ case ACB_ADAPTER_TYPE_F: {
+ struct MessageUnit_F __iomem *reg = acb->pmuF;
+
+ acb->msgcode_rwbuffer[0] = ARCMSR_SIGNATURE_SET_CONFIG;
+ acb->msgcode_rwbuffer[1] = ARCMSR_SIGNATURE_1886;
+ acb->msgcode_rwbuffer[2] = cdb_phyaddr;
+ acb->msgcode_rwbuffer[3] = cdb_phyaddr_hi32;
+ acb->msgcode_rwbuffer[4] = acb->ccbsize;
+ acb->msgcode_rwbuffer[5] = lower_32_bits(acb->dma_coherent_handle2);
+ acb->msgcode_rwbuffer[6] = upper_32_bits(acb->dma_coherent_handle2);
+ acb->msgcode_rwbuffer[7] = acb->completeQ_size;
+ writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, ®->inbound_msgaddr0);
+ acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+ writel(acb->out_doorbell, ®->iobound_doorbell);
+ if (!arcmsr_hbaE_wait_msgint_ready(acb)) {
+ pr_notice("arcmsr%d: 'set command Q window' timeout\n",
+ acb->host->host_no);
+ return 1;
+ }
+ }
+ break;
}
return 0;
}
@@ -3950,7 +4149,8 @@
ARCMSR_ARC1214_MESSAGE_FIRMWARE_OK) == 0);
}
break;
- case ACB_ADAPTER_TYPE_E: {
+ case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F: {
struct MessageUnit_E __iomem *reg = acb->pmuE;
do {
if (!(acb->acb_flags & ACB_F_IOP_INITED))
@@ -3965,24 +4165,10 @@
static void arcmsr_request_device_map(struct timer_list *t)
{
struct AdapterControlBlock *acb = from_timer(acb, t, eternal_timer);
- if (unlikely(atomic_read(&acb->rq_map_token) == 0) ||
- (acb->acb_flags & ACB_F_BUS_RESET) ||
- (acb->acb_flags & ACB_F_ABORT)) {
- mod_timer(&acb->eternal_timer,
- jiffies + msecs_to_jiffies(6 * HZ));
+ if (acb->acb_flags & (ACB_F_MSG_GET_CONFIG | ACB_F_BUS_RESET | ACB_F_ABORT)) {
+ mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
} else {
acb->fw_flag = FW_NORMAL;
- if (atomic_read(&acb->ante_token_value) ==
- atomic_read(&acb->rq_map_token)) {
- atomic_set(&acb->rq_map_token, 16);
- }
- atomic_set(&acb->ante_token_value,
- atomic_read(&acb->rq_map_token));
- if (atomic_dec_and_test(&acb->rq_map_token)) {
- mod_timer(&acb->eternal_timer, jiffies +
- msecs_to_jiffies(6 * HZ));
- return;
- }
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
struct MessageUnit_A __iomem *reg = acb->pmuA;
@@ -4012,10 +4198,23 @@
writel(acb->out_doorbell, ®->iobound_doorbell);
break;
}
+ case ACB_ADAPTER_TYPE_F: {
+ struct MessageUnit_F __iomem *reg = acb->pmuF;
+ uint32_t outMsg1 = readl(®->outbound_msgaddr1);
+
+ if (!(outMsg1 & ARCMSR_HBFMU_MESSAGE_FIRMWARE_OK) ||
+ (outMsg1 & ARCMSR_HBFMU_MESSAGE_NO_VOLUME_CHANGE))
+ goto nxt6s;
+ writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0);
+ acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+ writel(acb->out_doorbell, ®->iobound_doorbell);
+ break;
+ }
default:
return;
}
acb->acb_flags |= ACB_F_MSG_GET_CONFIG;
+nxt6s:
mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
}
}
@@ -4097,6 +4296,7 @@
arcmsr_hbaD_start_bgrb(acb);
break;
case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F:
arcmsr_hbaE_start_bgrb(acb);
break;
}
@@ -4176,7 +4376,8 @@
}
}
break;
- case ACB_ADAPTER_TYPE_E: {
+ case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F: {
struct MessageUnit_E __iomem *reg = acb->pmuE;
uint32_t i, tmp;
@@ -4303,7 +4504,8 @@
true : false;
}
break;
- case ACB_ADAPTER_TYPE_E:{
+ case ACB_ADAPTER_TYPE_E:
+ case ACB_ADAPTER_TYPE_F:{
struct MessageUnit_E __iomem *reg = acb->pmuE;
rtn = (readl(®->host_diagnostic_3xxx) &
ARCMSR_ARC188X_RESET_ADAPTER) ? true : false;
@@ -4402,8 +4604,6 @@
goto wait_reset_done;
}
arcmsr_iop_init(acb);
- atomic_set(&acb->rq_map_token, 16);
- atomic_set(&acb->ante_token_value, 16);
acb->fw_flag = FW_NORMAL;
mod_timer(&acb->eternal_timer, jiffies +
msecs_to_jiffies(6 * HZ));
@@ -4412,8 +4612,6 @@
pr_notice("arcmsr: scsi bus reset eh returns with success\n");
} else {
acb->acb_flags &= ~ACB_F_BUS_RESET;
- atomic_set(&acb->rq_map_token, 16);
- atomic_set(&acb->ante_token_value, 16);
acb->fw_flag = FW_NORMAL;
mod_timer(&acb->eternal_timer, jiffies +
msecs_to_jiffies(6 * HZ));
@@ -4483,7 +4681,7 @@
case PCI_DEVICE_ID_ARECA_1202:
case PCI_DEVICE_ID_ARECA_1210:
raid6 = 0;
- /*FALLTHRU*/
+ fallthrough;
case PCI_DEVICE_ID_ARECA_1120:
case PCI_DEVICE_ID_ARECA_1130:
case PCI_DEVICE_ID_ARECA_1160:
@@ -4506,6 +4704,9 @@
case PCI_DEVICE_ID_ARECA_1884:
type = "SAS/SATA";
break;
+ case PCI_DEVICE_ID_ARECA_1886:
+ type = "NVMe/SAS/SATA";
+ break;
default:
type = "unknown";
raid6 = 0;
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index deab665..9a912fd 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -1067,7 +1067,7 @@
* Purpose : ensure that all DMA transfers are up-to-date & host->scsi.SCp is correct
* Params : host - host to finish
* Notes : This is called when a command is:
- * terminating, RESTORE_POINTERS, SAVE_POINTERS, DISCONECT
+ * terminating, RESTORE_POINTERS, SAVE_POINTERS, DISCONNECT
* : This must not return until all transfers are completed.
*/
static
@@ -1816,7 +1816,7 @@
}
/*
- * Function: int acornscsi_reconect_finish(AS_Host *host)
+ * Function: int acornscsi_reconnect_finish(AS_Host *host)
* Purpose : finish reconnecting a command
* Params : host - host to complete
* Returns : 0 if failed
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
index 14e1d00..9dcd912 100644
--- a/drivers/scsi/arm/cumana_2.c
+++ b/drivers/scsi/arm/cumana_2.c
@@ -23,11 +23,11 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
+#include <linux/pgtable.h>
#include <asm/dma.h>
#include <asm/ecard.h>
#include <asm/io.h>
-#include <asm/pgtable.h>
#include "../scsi.h"
#include <scsi/scsi_host.h>
@@ -166,14 +166,15 @@
bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG);
- if (direction == DMA_OUT)
- map_dir = DMA_TO_DEVICE,
- dma_dir = DMA_MODE_WRITE,
+ if (direction == DMA_OUT) {
+ map_dir = DMA_TO_DEVICE;
+ dma_dir = DMA_MODE_WRITE;
alatch_dir = ALATCH_DMA_OUT;
- else
- map_dir = DMA_FROM_DEVICE,
- dma_dir = DMA_MODE_READ,
+ } else {
+ map_dir = DMA_FROM_DEVICE;
+ dma_dir = DMA_MODE_READ;
alatch_dir = ALATCH_DMA_IN;
+ }
dma_map_sg(dev, info->sg, bufs, map_dir);
@@ -326,10 +327,12 @@
cumanascsi_2_terminator_ctl(host, 0);
else
ret = -EINVAL;
- } else
+ } else {
ret = -EINVAL;
- } else
+ }
+ } else {
ret = -EINVAL;
+ }
return ret;
}
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index f441ec8..5eb2415 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -29,11 +29,11 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
+#include <linux/pgtable.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/ecard.h>
-#include <asm/pgtable.h>
#include "../scsi.h"
#include <scsi/scsi_host.h>
@@ -165,12 +165,13 @@
bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG);
- if (direction == DMA_OUT)
- map_dir = DMA_TO_DEVICE,
+ if (direction == DMA_OUT) {
+ map_dir = DMA_TO_DEVICE;
dma_dir = DMA_MODE_WRITE;
- else
- map_dir = DMA_FROM_DEVICE,
+ } else {
+ map_dir = DMA_FROM_DEVICE;
dma_dir = DMA_MODE_READ;
+ }
dma_map_sg(dev, info->sg, bufs, map_dir);
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index 6c68c23..2e687ce 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -603,7 +603,7 @@
msgqueue_flush(&info->scsi.msgs);
msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
info->scsi.phase = PHASE_MSGOUT_EXPECT;
- /* fall through */
+ fallthrough;
case async:
dev->period = info->ifcfg.asyncperiod / 4;
@@ -916,7 +916,7 @@
fas216_done(info, DID_ABORT);
break;
}
- /* else, fall through */
+ fallthrough;
default: /* huh? */
printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %s\n",
@@ -1413,7 +1413,7 @@
case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out -> Status */
case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */
fas216_stoptransfer(info);
- /* fall through */
+ fallthrough;
case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status */
case STATE(STAT_STATUS, PHASE_MSGOUT): /* Message Out -> Status */
@@ -1426,7 +1426,7 @@
case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out -> Message In */
case STATE(STAT_MESGIN, PHASE_DATAIN): /* Data In -> Message In */
fas216_stoptransfer(info);
- /* fall through */
+ fallthrough;
case STATE(STAT_MESGIN, PHASE_COMMAND): /* Command -> Message In */
case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In */
@@ -1581,7 +1581,7 @@
fas216_message(info);
break;
}
- /* else, fall through */
+ fallthrough;
default:
fas216_log(info, 0, "internal phase %s for function done?"
@@ -1964,7 +1964,7 @@
switch (where_from) {
case TYPE_QUEUE:
fas216_allocate_tag(info, SCpnt);
- /* fall through */
+ fallthrough;
case TYPE_OTHER:
fas216_start_command(info, SCpnt);
break;
diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c
index 7c9d361..78f33d5 100644
--- a/drivers/scsi/arm/oak.c
+++ b/drivers/scsi/arm/oak.c
@@ -120,7 +120,7 @@
static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct Scsi_Host *host;
- int ret = -ENOMEM;
+ int ret;
ret = ecard_request_resources(ec);
if (ret)
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index 2dc0df0..9cc73da 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -14,11 +14,11 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
+#include <linux/pgtable.h>
#include <asm/dma.h>
#include <asm/ecard.h>
#include <asm/io.h>
-#include <asm/pgtable.h>
#include "../scsi.h"
#include <scsi/scsi_host.h>
@@ -138,12 +138,13 @@
bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG);
- if (direction == DMA_OUT)
- map_dir = DMA_TO_DEVICE,
+ if (direction == DMA_OUT) {
+ map_dir = DMA_TO_DEVICE;
dma_dir = DMA_MODE_WRITE;
- else
- map_dir = DMA_FROM_DEVICE,
+ } else {
+ map_dir = DMA_FROM_DEVICE;
dma_dir = DMA_MODE_READ;
+ }
dma_map_sg(dev, info->sg, bufs, map_dir);
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index e41f0bb..c6a7523 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1680,7 +1680,7 @@
.bios_param = atp870u_biosparam /* biosparm */,
.can_queue = qcnt /* can_queue */,
.this_id = 7 /* SCSI ID */,
- .sg_tablesize = ATP870U_SCATTER /*SG_ALL*/ /*SG_NONE*/,
+ .sg_tablesize = ATP870U_SCATTER /*SG_ALL*/,
.max_sectors = ATP870U_MAX_SECTORS,
};
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h
index 063dccc..5f9f0b1 100644
--- a/drivers/scsi/be2iscsi/be_cmds.h
+++ b/drivers/scsi/be2iscsi/be_cmds.h
@@ -1300,7 +1300,7 @@
/* Returns the number of items in the field array. */
#define BE_NUMBER_OF_FIELD(_type_, _field_) \
- (FIELD_SIZEOF(_type_, _field_)/sizeof((((_type_ *)0)->_field_[0])))\
+ (sizeof_field(_type_, _field_)/sizeof((((_type_ *)0)->_field_[0])))\
/**
* Different types of iSCSI completions to host driver for both initiator
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index 2058d50..a13c203 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -27,6 +27,7 @@
/**
* beiscsi_session_create - creates a new iscsi session
+ * @ep: pointer to iscsi ep
* @cmds_max: max commands supported
* @qdepth: max queue depth supported
* @initial_cmdsn: initial iscsi CMDSN
@@ -164,6 +165,7 @@
* @cls_session: pointer to iscsi cls session
* @cls_conn: pointer to iscsi cls conn
* @transport_fd: EP handle(64 bit)
+ * @is_leading: indicate if this is the session leading connection (MCS)
*
* This function binds the TCP Conn with iSCSI Connection and Session.
*/
@@ -675,7 +677,7 @@
case ISCSI_PARAM_MAX_XMIT_DLENGTH:
if (conn->max_xmit_dlength > 65536)
conn->max_xmit_dlength = 65536;
- /* fall through */
+ fallthrough;
default:
return 0;
}
@@ -992,7 +994,7 @@
/**
* beiscsi_free_ep - free endpoint
- * @ep: pointer to iscsi endpoint structure
+ * @beiscsi_ep: pointer to device endpoint struct
*/
static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep)
{
@@ -1027,9 +1029,10 @@
/**
* beiscsi_open_conn - Ask FW to open a TCP connection
- * @ep: endpoint to be used
+ * @ep: pointer to device endpoint struct
* @src_addr: The source IP address
* @dst_addr: The Destination IP address
+ * @non_blocking: blocking or non-blocking call
*
* Asks the FW to open a TCP connection
*/
@@ -1123,7 +1126,7 @@
/**
* beiscsi_ep_connect - Ask chip to create TCP Conn
- * @scsi_host: Pointer to scsi_host structure
+ * @shost: Pointer to scsi_host structure
* @dst_addr: The IP address of Target
* @non_blocking: blocking or non-blocking call
*
@@ -1228,7 +1231,7 @@
/**
* beiscsi_conn_close - Invalidate and upload connection
- * @ep: The iscsi endpoint
+ * @beiscsi_ep: pointer to device endpoint struct
*
* Returns 0 on success, -1 on failure.
*/
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 53b33f1..987dc81 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -453,14 +453,14 @@
u8 __iomem *addr;
int pcicfg_reg;
- addr = ioremap_nocache(pci_resource_start(pcidev, 2),
+ addr = ioremap(pci_resource_start(pcidev, 2),
pci_resource_len(pcidev, 2));
if (addr == NULL)
return -ENOMEM;
phba->ctrl.csr = addr;
phba->csr_va = addr;
- addr = ioremap_nocache(pci_resource_start(pcidev, 4), 128 * 1024);
+ addr = ioremap(pci_resource_start(pcidev, 4), 128 * 1024);
if (addr == NULL)
goto pci_map_err;
phba->ctrl.db = addr;
@@ -471,7 +471,7 @@
else
pcicfg_reg = 0;
- addr = ioremap_nocache(pci_resource_start(pcidev, pcicfg_reg),
+ addr = ioremap(pci_resource_start(pcidev, pcicfg_reg),
pci_resource_len(pcidev, pcicfg_reg));
if (addr == NULL)
@@ -977,7 +977,7 @@
* alloc_wrb_handle - To allocate a wrb handle
* @phba: The hba pointer
* @cid: The cid to use for allocation
- * @pwrb_context: ptr to ptr to wrb context
+ * @pcontext: ptr to ptr to wrb context
*
* This happens under session_lock until submission to chip
*/
@@ -1394,7 +1394,7 @@
spin_unlock_bh(&session->back_lock);
}
-/**
+/*
* ASYNC PDUs include
* a. Unsolicited NOP-In (target initiated NOP-In)
* b. ASYNC Messages
@@ -1532,7 +1532,7 @@
break;
case UNSOL_DATA_DIGEST_ERROR_NOTIFY:
error = 1;
- /* fall through */
+ fallthrough;
case UNSOL_DATA_NOTIFY:
pasync_handle = pasync_ctx->async_entry[ci].data;
break;
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index d4febaa..96d6e38 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -97,6 +97,7 @@
/**
* mgmt_open_connection()- Establish a TCP CXN
+ * @phba: driver priv structure
* @dst_addr: Destination Address
* @beiscsi_ep: ptr to device endpoint struct
* @nonemb_cmd: ptr to memory allocated for command
@@ -209,7 +210,7 @@
return tag;
}
-/*
+/**
* beiscsi_exec_nemb_cmd()- execute non-embedded MBX cmd
* @phba: driver priv structure
* @nonemb_cmd: DMA address of the MBX command to be issued
@@ -1178,12 +1179,12 @@
if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) {
avlbl_cids = BEISCSI_ULP_AVLBL_CID(phba, ulp_num);
total_cids = BEISCSI_GET_CID_COUNT(phba, ulp_num);
- len += snprintf(buf+len, PAGE_SIZE - len,
- "ULP%d : %d\n", ulp_num,
- (total_cids - avlbl_cids));
+ len += scnprintf(buf+len, PAGE_SIZE - len,
+ "ULP%d : %d\n", ulp_num,
+ (total_cids - avlbl_cids));
} else
- len += snprintf(buf+len, PAGE_SIZE - len,
- "ULP%d : %d\n", ulp_num, 0);
+ len += scnprintf(buf+len, PAGE_SIZE - len,
+ "ULP%d : %d\n", ulp_num, 0);
}
return len;
@@ -1208,12 +1209,12 @@
for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) {
if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported))
- len += snprintf(buf+len, PAGE_SIZE - len,
- "ULP%d : %d\n", ulp_num,
- BEISCSI_ULP_AVLBL_CID(phba, ulp_num));
+ len += scnprintf(buf+len, PAGE_SIZE - len,
+ "ULP%d : %d\n", ulp_num,
+ BEISCSI_ULP_AVLBL_CID(phba, ulp_num));
else
- len += snprintf(buf+len, PAGE_SIZE - len,
- "ULP%d : %d\n", ulp_num, 0);
+ len += scnprintf(buf+len, PAGE_SIZE - len,
+ "ULP%d : %d\n", ulp_num, 0);
}
return len;
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
index 0f554eb..6846ca8 100644
--- a/drivers/scsi/bfa/bfa_core.c
+++ b/drivers/scsi/bfa/bfa_core.c
@@ -708,7 +708,7 @@
}
}
-bfa_boolean_t
+static bfa_boolean_t
bfa_isr_rspq(struct bfa_s *bfa, int qid)
{
struct bfi_msg_s *m;
@@ -1237,7 +1237,7 @@
complete(&bfad->disable_comp);
}
-/**
+/*
* configure queue registers from firmware response
*/
static void
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index 284baa3..38d1c45 100644
--- a/drivers/scsi/bfa/bfa_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcpim.c
@@ -436,7 +436,7 @@
return BFA_STATUS_OK;
}
-void
+static void
bfa_ioim_profile_comp(struct bfa_ioim_s *ioim)
{
struct bfa_itnim_latency_s *io_lat =
@@ -453,7 +453,7 @@
io_lat->avg[idx] += val;
}
-void
+static void
bfa_ioim_profile_start(struct bfa_ioim_s *ioim)
{
ioim->start_time = jiffies;
@@ -2335,9 +2335,7 @@
wwn_t rpwwn, struct scsi_lun lun)
{
struct bfa_lun_mask_s *lunm_list;
- struct bfa_rport_s *rp = NULL;
struct bfa_fcs_lport_s *port = NULL;
- struct bfa_fcs_rport_s *rp_fcs;
int i;
/* in min cfg lunm_list could be NULL but no commands should run. */
@@ -2353,12 +2351,8 @@
port = bfa_fcs_lookup_port(
&((struct bfad_s *)bfa->bfad)->bfa_fcs,
vf_id, *pwwn);
- if (port) {
+ if (port)
*pwwn = port->port_cfg.pwwn;
- rp_fcs = bfa_fcs_lport_get_rport_by_pwwn(port, rpwwn);
- if (rp_fcs)
- rp = rp_fcs->bfa_rport;
- }
}
lunm_list = bfa_get_lun_mask_list(bfa);
@@ -2578,7 +2572,7 @@
case FCP_IODIR_RW:
bfa_stats(itnim, input_reqs);
bfa_stats(itnim, output_reqs);
- /* fall through */
+ fallthrough;
default:
bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_fn_lpu(ioim->bfa));
}
@@ -2813,7 +2807,7 @@
case BFI_IOIM_STS_TIMEDOUT:
bfa_stats(ioim->itnim, iocomp_timedout);
- /* fall through */
+ fallthrough;
case BFI_IOIM_STS_ABORTED:
rsp->io_status = BFI_IOIM_STS_ABORTED;
bfa_stats(ioim->itnim, iocomp_aborted);
@@ -3209,7 +3203,7 @@
switch (event) {
case BFA_TSKIM_SM_DONE:
bfa_reqq_wcancel(&tskim->reqq_wait);
- /* fall through */
+ fallthrough;
case BFA_TSKIM_SM_QRESUME:
bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup);
bfa_tskim_send_abort(tskim);
@@ -3818,7 +3812,7 @@
}
-/**
+/*
* To send config req, first try to use throttle value from flash
* If 0, then use driver parameter
* We need to use min(flash_val, drv_val) because
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 7c3eadc..3486e40 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -1283,7 +1283,7 @@
n2n_port->reply_oxid = 0;
}
-void
+static void
bfa_fcport_get_loop_attr(struct bfa_fcs_lport_s *port)
{
int i = 0, j = 0, bit = 0, alpa_bit = 0;
@@ -4358,7 +4358,7 @@
bfa_sm_set_state(ns,
bfa_fcs_lport_ns_sm_sending_gid_ft);
bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
- };
+ }
break;
default:
@@ -6422,7 +6422,7 @@
switch (event) {
case BFA_FCS_VPORT_SM_OFFLINE:
bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
- /* fall through */
+ fallthrough;
case BFA_FCS_VPORT_SM_RSP_OK:
case BFA_FCS_VPORT_SM_RSP_ERROR:
@@ -6448,7 +6448,7 @@
switch (event) {
case BFA_FCS_VPORT_SM_OFFLINE:
bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
- /* fall through */
+ fallthrough;
case BFA_FCS_VPORT_SM_RSP_OK:
case BFA_FCS_VPORT_SM_RSP_ERROR:
diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c
index 82801b3..c21aa37 100644
--- a/drivers/scsi/bfa/bfa_fcs_rport.c
+++ b/drivers/scsi/bfa/bfa_fcs_rport.c
@@ -419,13 +419,13 @@
case RPSM_EVENT_LOGO_RCVD:
bfa_fcs_rport_send_logo_acc(rport);
- /* fall through */
+ fallthrough;
case RPSM_EVENT_PRLO_RCVD:
if (rport->prlo == BFA_TRUE)
bfa_fcs_rport_send_prlo_acc(rport);
bfa_fcxp_discard(rport->fcxp);
- /* fall through */
+ fallthrough;
case RPSM_EVENT_FAILED:
if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
rport->plogi_retries++;
@@ -856,7 +856,7 @@
* At least go offline when a PLOGI is received.
*/
bfa_fcxp_discard(rport->fcxp);
- /* fall through */
+ fallthrough;
case RPSM_EVENT_FAILED:
case RPSM_EVENT_ADDRESS_CHANGE:
@@ -1042,7 +1042,7 @@
case RPSM_EVENT_LOGO_RCVD:
bfa_fcs_rport_send_logo_acc(rport);
- /* fall through */
+ fallthrough;
case RPSM_EVENT_PRLO_RCVD:
if (rport->prlo == BFA_TRUE)
bfa_fcs_rport_send_prlo_acc(rport);
@@ -1131,7 +1131,7 @@
bfa_fcs_rport_send_plogiacc(rport, NULL);
break;
}
- /* fall through */
+ fallthrough;
case RPSM_EVENT_ADDRESS_CHANGE:
if (!bfa_fcs_lport_is_online(rport->port)) {
@@ -1288,7 +1288,7 @@
case RPSM_EVENT_LOGO_RCVD:
bfa_fcs_rport_send_logo_acc(rport);
- /* fall through */
+ fallthrough;
case RPSM_EVENT_PRLO_RCVD:
if (rport->prlo == BFA_TRUE)
bfa_fcs_rport_send_prlo_acc(rport);
@@ -1332,7 +1332,7 @@
case RPSM_EVENT_LOGO_RCVD:
bfa_fcs_rport_send_logo_acc(rport);
- /* fall through */
+ fallthrough;
case RPSM_EVENT_PRLO_RCVD:
if (rport->prlo == BFA_TRUE)
bfa_fcs_rport_send_prlo_acc(rport);
@@ -1575,7 +1575,7 @@
bfa_timer_start(rport->fcs->bfa, &rport->timer,
bfa_fcs_rport_timeout, rport,
bfa_fcs_rport_del_timeout);
- };
+ }
break;
case RPSM_EVENT_DELETE:
@@ -2240,15 +2240,12 @@
struct bfa_fcxp_s *fcxp;
struct fchs_s fchs;
struct bfa_fcs_lport_s *port = rport->port;
- struct fc_adisc_s *adisc;
bfa_trc(port->fcs, rx_fchs->s_id);
bfa_trc(port->fcs, rx_fchs->d_id);
rport->stats.adisc_rcvd++;
- adisc = (struct fc_adisc_s *) (rx_fchs + 1);
-
/*
* Accept if the itnim for this rport is online.
* Else reject the ADISC.
@@ -2449,7 +2446,7 @@
bfa_fcs_itnim_brp_online(rport->itnim);
if (!BFA_FCS_PID_IS_WKA(rport->pid))
bfa_fcs_rpf_rport_online(rport);
- };
+ }
wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
wwn2str(rpwwn_buf, rport->pwwn);
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index 93471d7..325ad8a 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -701,7 +701,7 @@
bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
{
struct bfi_ioc_image_hdr_s fwhdr;
- u32 r32, fwstate, pgnum, pgoff, loff = 0;
+ u32 r32, fwstate, pgnum, loff = 0;
int i;
/*
@@ -731,7 +731,6 @@
* Clear fwver hdr
*/
pgnum = PSS_SMEM_PGNUM(iocpf->ioc->ioc_regs.smem_pg0, loff);
- pgoff = PSS_SMEM_PGOFF(loff);
writel(pgnum, iocpf->ioc->ioc_regs.host_page_num_fn);
for (i = 0; i < sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32); i++) {
@@ -970,7 +969,7 @@
case IOCPF_E_INITFAIL:
bfa_iocpf_timer_stop(ioc);
- /* fall through */
+ fallthrough;
case IOCPF_E_TIMEOUT:
writel(1, ioc->ioc_regs.ioc_sem_reg);
@@ -1046,7 +1045,7 @@
case IOCPF_E_FAIL:
bfa_iocpf_timer_stop(ioc);
- /* fall through */
+ fallthrough;
case IOCPF_E_TIMEOUT:
bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL);
@@ -1440,13 +1439,12 @@
void
bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
{
- u32 pgnum, pgoff;
+ u32 pgnum;
u32 loff = 0;
int i;
u32 *fwsig = (u32 *) fwhdr;
pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
- pgoff = PSS_SMEM_PGOFF(loff);
writel(pgnum, ioc->ioc_regs.host_page_num_fn);
for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
@@ -1662,7 +1660,7 @@
bfa_ioc_fwsig_invalidate(struct bfa_ioc_s *ioc)
{
- u32 pgnum, pgoff;
+ u32 pgnum;
u32 loff = 0;
enum bfi_ioc_state ioc_fwstate;
@@ -1671,7 +1669,6 @@
return BFA_STATUS_ADAPTER_ENABLED;
pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
- pgoff = PSS_SMEM_PGOFF(loff);
writel(pgnum, ioc->ioc_regs.host_page_num_fn);
bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, BFA_IOC_FW_INV_SIGN);
@@ -1863,7 +1860,7 @@
u32 boot_env)
{
u32 *fwimg;
- u32 pgnum, pgoff;
+ u32 pgnum;
u32 loff = 0;
u32 chunkno = 0;
u32 i;
@@ -1892,8 +1889,6 @@
pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
- pgoff = PSS_SMEM_PGOFF(loff);
-
writel(pgnum, ioc->ioc_regs.host_page_num_fn);
for (i = 0; i < fwimg_size; i++) {
@@ -4763,11 +4758,9 @@
struct bfa_ioc_s *ioc = diag->ioc;
struct bfa_diag_memtest_result *res = diag->result;
u32 loff = BFI_BOOT_MEMTEST_RES_ADDR;
- u32 pgnum, pgoff, i;
+ u32 pgnum, i;
pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
- pgoff = PSS_SMEM_PGOFF(loff);
-
writel(pgnum, ioc->ioc_regs.host_page_num_fn);
for (i = 0; i < (sizeof(struct bfa_diag_memtest_result) /
@@ -5026,7 +5019,7 @@
/*
* Diag hmbox handler
*/
-void
+static void
bfa_diag_intr(void *diagarg, struct bfi_mbmsg_s *msg)
{
struct bfa_diag_s *diag = diagarg;
@@ -5995,7 +5988,7 @@
case BFA_DCONF_SM_IOCDISABLE:
case BFA_DCONF_SM_FLASH_COMP:
bfa_timer_stop(&dconf->timer);
- /* fall through */
+ fallthrough;
case BFA_DCONF_SM_TIMEOUT:
bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);
@@ -6649,8 +6642,8 @@
BFA_FLASH_READ_STATUS = 0x05, /* read status */
};
-/**
- * @brief hardware error definition
+/*
+ * Hardware error definition
*/
enum bfa_flash_err {
BFA_FLASH_NOT_PRESENT = -1, /*!< flash not present */
@@ -6664,8 +6657,8 @@
BFA_FLASH_ERR_LEN = -9, /*!< invalid length */
};
-/**
- * @brief flash command register data structure
+/*
+ * Flash command register data structure
*/
union bfa_flash_cmd_reg_u {
struct {
@@ -6688,8 +6681,8 @@
u32 i;
};
-/**
- * @brief flash device status register data structure
+/*
+ * Flash device status register data structure
*/
union bfa_flash_dev_status_reg_u {
struct {
@@ -6714,8 +6707,8 @@
u32 i;
};
-/**
- * @brief flash address register data structure
+/*
+ * Flash address register data structure
*/
union bfa_flash_addr_reg_u {
struct {
@@ -6730,7 +6723,7 @@
u32 i;
};
-/**
+/*
* dg flash_raw_private Flash raw private functions
*/
static void
@@ -6771,7 +6764,7 @@
return 0;
}
-/**
+/*
* @brief
* Flush FLI data fifo.
*
@@ -6784,7 +6777,6 @@
bfa_flash_fifo_flush(void __iomem *pci_bar)
{
u32 i;
- u32 t;
union bfa_flash_dev_status_reg_u dev_status;
dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);
@@ -6794,7 +6786,7 @@
/* fifo counter in terms of words */
for (i = 0; i < dev_status.r.fifo_cnt; i++)
- t = readl(pci_bar + FLI_RDDATA_REG);
+ readl(pci_bar + FLI_RDDATA_REG);
/*
* Check the device status. It may take some time.
@@ -6811,7 +6803,7 @@
return 0;
}
-/**
+/*
* @brief
* Read flash status.
*
@@ -6856,7 +6848,7 @@
return ret_status;
}
-/**
+/*
* @brief
* Start flash read operation.
*
@@ -6902,7 +6894,7 @@
return 0;
}
-/**
+/*
* @brief
* Check flash read operation.
*
@@ -6918,7 +6910,8 @@
return 0;
}
-/**
+
+/*
* @brief
* End flash read operation.
*
@@ -6944,7 +6937,7 @@
bfa_flash_fifo_flush(pci_bar);
}
-/**
+/*
* @brief
* Perform flash raw read.
*
@@ -6970,7 +6963,7 @@
}
-bfa_status_t
+static bfa_status_t
bfa_flash_sem_get(void __iomem *bar)
{
u32 n = FLASH_BLOCKING_OP_MAX;
@@ -6983,7 +6976,7 @@
return BFA_STATUS_OK;
}
-void
+static void
bfa_flash_sem_put(void __iomem *bar)
{
writel(0, (bar + FLASH_SEM_LOCK_REG));
diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c
index 18b58b2..fb74829 100644
--- a/drivers/scsi/bfa/bfa_ioc_ct.c
+++ b/drivers/scsi/bfa/bfa_ioc_ct.c
@@ -364,7 +364,7 @@
writel(r32, rb + FNC_PERS_REG);
}
-bfa_boolean_t
+static bfa_boolean_t
bfa_ioc_ct2_lpu_read_stat(struct bfa_ioc_s *ioc)
{
u32 r32;
@@ -496,7 +496,7 @@
return BFA_FALSE;
}
-/**
+/*
* Called from bfa_ioc_attach() to map asic specific calls.
*/
static void
@@ -517,7 +517,7 @@
hwif->ioc_get_alt_fwstate = bfa_ioc_ct_get_alt_ioc_fwstate;
}
-/**
+/*
* Called from bfa_ioc_attach() to map asic specific calls.
*/
void
@@ -532,7 +532,7 @@
ioc->ioc_hwif = &hwif_ct;
}
-/**
+/*
* Called from bfa_ioc_attach() to map asic specific calls.
*/
void
@@ -744,7 +744,7 @@
writel(0, (rb + CT2_MBIST_CTL_REG));
}
-void
+static void
bfa_ioc_ct2_mac_reset(void __iomem *rb)
{
/* put port0, port1 MAC & AHB in reset */
diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c
index 4511ec8..cfe2c9c 100644
--- a/drivers/scsi/bfa/bfa_port.c
+++ b/drivers/scsi/bfa/bfa_port.c
@@ -756,7 +756,7 @@
* @return void
*/
-void
+static void
bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m)
{
union bfi_cee_i2h_msg_u *msg;
@@ -792,7 +792,7 @@
* @return void
*/
-void
+static void
bfa_cee_notify(void *arg, enum bfa_ioc_event_e event)
{
struct bfa_cee_s *cee = (struct bfa_cee_s *) arg;
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index 6d21314..11c0c3e 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -2718,7 +2718,7 @@
case BFA_FCPORT_SM_DPORTDISABLE:
case BFA_FCPORT_SM_ENABLE:
case BFA_FCPORT_SM_START:
- /**
+ /*
* Ignore event for a port that is ddport
*/
break;
@@ -3839,7 +3839,7 @@
return fcport->topology;
}
-/**
+/*
* Get config topology.
*/
enum bfa_port_topology
@@ -4284,7 +4284,7 @@
bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE);
}
-void
+static void
bfa_fcport_ddportenable(struct bfa_s *bfa)
{
/*
@@ -4293,7 +4293,7 @@
bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTENABLE);
}
-void
+static void
bfa_fcport_ddportdisable(struct bfa_s *bfa)
{
/*
@@ -5517,7 +5517,6 @@
struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
struct bfa_uf_buf_s *uf_buf;
uint8_t *buf;
- struct fchs_s *fchs;
uf_buf = (struct bfa_uf_buf_s *)
bfa_mem_get_dmabuf_kva(ufm, uf_tag, uf->pb_len);
@@ -5526,8 +5525,6 @@
m->frm_len = be16_to_cpu(m->frm_len);
m->xfr_len = be16_to_cpu(m->xfr_len);
- fchs = (struct fchs_s *)uf_buf;
-
list_del(&uf->qe); /* dequeue from posted queue */
uf->data_ptr = buf;
@@ -6400,7 +6397,7 @@
dport->test_state = BFA_DPORT_ST_INP;
bfa_dport_result_start(dport, BFA_DPORT_OPMODE_MANU);
}
- /* fall thru */
+ fallthrough;
case BFA_DPORT_SM_REQFAIL:
bfa_sm_set_state(dport, bfa_dport_sm_enabled);
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c
index 93e4011..440ef32 100644
--- a/drivers/scsi/bfa/bfad.c
+++ b/drivers/scsi/bfa/bfad.c
@@ -50,7 +50,7 @@
int bfa_debugfs_enable = 1;
int msix_disable_cb = 0, msix_disable_ct = 0;
int max_xfer_size = BFAD_MAX_SECTORS >> 1;
-int max_rport_logins = BFA_FCS_MAX_RPORT_LOGINS;
+static int max_rport_logins = BFA_FCS_MAX_RPORT_LOGINS;
/* Firmware releated */
u32 bfi_image_cb_size, bfi_image_ct_size, bfi_image_ct2_size;
@@ -1488,8 +1488,7 @@
return ret;
}
-int
-restart_bfa(struct bfad_s *bfad)
+static int restart_bfa(struct bfad_s *bfad)
{
unsigned long flags;
struct pci_dev *pdev = bfad->pcidev;
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index fbfce02..5ae1e3f 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -437,7 +437,7 @@
return status;
}
-int
+static int
bfad_im_issue_fc_host_lip(struct Scsi_Host *shost)
{
struct bfad_im_port_s *im_port =
@@ -562,7 +562,7 @@
return 0;
}
-void
+static void
bfad_im_vport_set_symbolic_name(struct fc_vport *fc_vport)
{
struct bfad_vport_s *vport = (struct bfad_vport_s *)fc_vport->dd_data;
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index a76c968..fc51542 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -15,7 +15,7 @@
BFA_TRC_FILE(LDRV, BSG);
-int
+static int
bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -38,7 +38,7 @@
return 0;
}
-int
+static int
bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -136,7 +136,7 @@
return 0;
}
-int
+static int
bfad_iocmd_ioc_get_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_ioc_stats_s *iocmd = (struct bfa_bsg_ioc_stats_s *)cmd;
@@ -146,7 +146,7 @@
return 0;
}
-int
+static int
bfad_iocmd_ioc_get_fwstats(struct bfad_s *bfad, void *cmd,
unsigned int payload_len)
{
@@ -176,7 +176,7 @@
return 0;
}
-int
+static int
bfad_iocmd_ioc_reset_stats(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -194,7 +194,7 @@
return 0;
}
-int
+static int
bfad_iocmd_ioc_set_name(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
{
struct bfa_bsg_ioc_name_s *iocmd = (struct bfa_bsg_ioc_name_s *) cmd;
@@ -208,7 +208,7 @@
return 0;
}
-int
+static int
bfad_iocmd_iocfc_get_attr(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_iocfc_attr_s *iocmd = (struct bfa_bsg_iocfc_attr_s *)cmd;
@@ -219,7 +219,7 @@
return 0;
}
-int
+static int
bfad_iocmd_ioc_fw_sig_inv(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -231,7 +231,7 @@
return 0;
}
-int
+static int
bfad_iocmd_iocfc_set_intr(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_iocfc_intr_s *iocmd = (struct bfa_bsg_iocfc_intr_s *)cmd;
@@ -244,7 +244,7 @@
return 0;
}
-int
+static int
bfad_iocmd_port_enable(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -265,7 +265,7 @@
return 0;
}
-int
+static int
bfad_iocmd_port_disable(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -315,7 +315,7 @@
return 0;
}
-int
+static int
bfad_iocmd_port_get_stats(struct bfad_s *bfad, void *cmd,
unsigned int payload_len)
{
@@ -349,7 +349,7 @@
return 0;
}
-int
+static int
bfad_iocmd_port_reset_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -370,7 +370,7 @@
return 0;
}
-int
+static int
bfad_iocmd_set_port_cfg(struct bfad_s *bfad, void *iocmd, unsigned int v_cmd)
{
struct bfa_bsg_port_cfg_s *cmd = (struct bfa_bsg_port_cfg_s *)iocmd;
@@ -390,7 +390,7 @@
return 0;
}
-int
+static int
bfad_iocmd_port_cfg_maxfrsize(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_port_cfg_maxfrsize_s *iocmd =
@@ -404,7 +404,7 @@
return 0;
}
-int
+static int
bfad_iocmd_port_cfg_bbcr(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
{
struct bfa_bsg_bbcr_enable_s *iocmd =
@@ -427,7 +427,7 @@
return 0;
}
-int
+static int
bfad_iocmd_port_get_bbcr_attr(struct bfad_s *bfad, void *pcmd)
{
struct bfa_bsg_bbcr_attr_s *iocmd = (struct bfa_bsg_bbcr_attr_s *) pcmd;
@@ -465,7 +465,7 @@
return 0;
}
-int
+static int
bfad_iocmd_lport_get_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_fcs_lport_s *fcs_port;
@@ -489,7 +489,7 @@
return 0;
}
-int
+static int
bfad_iocmd_lport_reset_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_fcs_lport_s *fcs_port;
@@ -523,7 +523,7 @@
return 0;
}
-int
+static int
bfad_iocmd_lport_get_iostats(struct bfad_s *bfad, void *cmd)
{
struct bfa_fcs_lport_s *fcs_port;
@@ -548,7 +548,7 @@
return 0;
}
-int
+static int
bfad_iocmd_lport_get_rports(struct bfad_s *bfad, void *cmd,
unsigned int payload_len)
{
@@ -590,7 +590,7 @@
return 0;
}
-int
+static int
bfad_iocmd_rport_get_attr(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_rport_attr_s *iocmd = (struct bfa_bsg_rport_attr_s *)cmd;
@@ -676,7 +676,7 @@
return 0;
}
-int
+static int
bfad_iocmd_rport_get_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_rport_stats_s *iocmd =
@@ -717,7 +717,7 @@
return 0;
}
-int
+static int
bfad_iocmd_rport_clr_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_rport_reset_stats_s *iocmd =
@@ -753,7 +753,7 @@
return 0;
}
-int
+static int
bfad_iocmd_rport_set_speed(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_rport_set_speed_s *iocmd =
@@ -789,7 +789,7 @@
return 0;
}
-int
+static int
bfad_iocmd_vport_get_attr(struct bfad_s *bfad, void *cmd)
{
struct bfa_fcs_vport_s *fcs_vport;
@@ -812,7 +812,7 @@
return 0;
}
-int
+static int
bfad_iocmd_vport_get_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_fcs_vport_s *fcs_vport;
@@ -840,7 +840,7 @@
return 0;
}
-int
+static int
bfad_iocmd_vport_clr_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_fcs_vport_s *fcs_vport;
@@ -907,7 +907,7 @@
return 0;
}
-int
+static int
bfad_iocmd_qos_set_bw(struct bfad_s *bfad, void *pcmd)
{
struct bfa_bsg_qos_bw_s *iocmd = (struct bfa_bsg_qos_bw_s *)pcmd;
@@ -920,7 +920,7 @@
return 0;
}
-int
+static int
bfad_iocmd_ratelim(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
@@ -949,7 +949,7 @@
return 0;
}
-int
+static int
bfad_iocmd_ratelim_speed(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
{
struct bfa_bsg_trl_speed_s *iocmd = (struct bfa_bsg_trl_speed_s *)pcmd;
@@ -978,7 +978,7 @@
return 0;
}
-int
+static int
bfad_iocmd_cfg_fcpim(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fcpim_s *iocmd = (struct bfa_bsg_fcpim_s *)cmd;
@@ -991,7 +991,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fcpim_get_modstats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fcpim_modstats_s *iocmd =
@@ -1013,7 +1013,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fcpim_clr_modstats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fcpim_modstatsclr_s *iocmd =
@@ -1035,7 +1035,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fcpim_get_del_itn_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fcpim_del_itn_stats_s *iocmd =
@@ -1160,7 +1160,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fcport_enable(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -1173,7 +1173,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fcport_disable(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -1186,7 +1186,7 @@
return 0;
}
-int
+static int
bfad_iocmd_ioc_get_pcifn_cfg(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_pcifn_cfg_s *iocmd = (struct bfa_bsg_pcifn_cfg_s *)cmd;
@@ -1208,7 +1208,7 @@
return 0;
}
-int
+static int
bfad_iocmd_pcifn_create(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd;
@@ -1231,7 +1231,7 @@
return 0;
}
-int
+static int
bfad_iocmd_pcifn_delete(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd;
@@ -1253,7 +1253,7 @@
return 0;
}
-int
+static int
bfad_iocmd_pcifn_bw(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_pcifn_s *iocmd = (struct bfa_bsg_pcifn_s *)cmd;
@@ -1277,7 +1277,7 @@
return 0;
}
-int
+static int
bfad_iocmd_adapter_cfg_mode(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_adapter_cfg_mode_s *iocmd =
@@ -1300,7 +1300,7 @@
return 0;
}
-int
+static int
bfad_iocmd_port_cfg_mode(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_port_cfg_mode_s *iocmd =
@@ -1324,7 +1324,7 @@
return 0;
}
-int
+static int
bfad_iocmd_ablk_optrom(struct bfad_s *bfad, unsigned int cmd, void *pcmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
@@ -1350,7 +1350,7 @@
return 0;
}
-int
+static int
bfad_iocmd_faa_query(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_faa_attr_s *iocmd = (struct bfa_bsg_faa_attr_s *)cmd;
@@ -1373,7 +1373,7 @@
return 0;
}
-int
+static int
bfad_iocmd_cee_attr(struct bfad_s *bfad, void *cmd, unsigned int payload_len)
{
struct bfa_bsg_cee_attr_s *iocmd =
@@ -1409,7 +1409,7 @@
return 0;
}
-int
+static int
bfad_iocmd_cee_get_stats(struct bfad_s *bfad, void *cmd,
unsigned int payload_len)
{
@@ -1446,7 +1446,7 @@
return 0;
}
-int
+static int
bfad_iocmd_cee_reset_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -1460,7 +1460,7 @@
return 0;
}
-int
+static int
bfad_iocmd_sfp_media(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_sfp_media_s *iocmd = (struct bfa_bsg_sfp_media_s *)cmd;
@@ -1482,7 +1482,7 @@
return 0;
}
-int
+static int
bfad_iocmd_sfp_speed(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_sfp_speed_s *iocmd = (struct bfa_bsg_sfp_speed_s *)cmd;
@@ -1503,7 +1503,7 @@
return 0;
}
-int
+static int
bfad_iocmd_flash_get_attr(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_flash_attr_s *iocmd =
@@ -1524,7 +1524,7 @@
return 0;
}
-int
+static int
bfad_iocmd_flash_erase_part(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_flash_s *iocmd = (struct bfa_bsg_flash_s *)cmd;
@@ -1544,7 +1544,7 @@
return 0;
}
-int
+static int
bfad_iocmd_flash_update_part(struct bfad_s *bfad, void *cmd,
unsigned int payload_len)
{
@@ -1576,7 +1576,7 @@
return 0;
}
-int
+static int
bfad_iocmd_flash_read_part(struct bfad_s *bfad, void *cmd,
unsigned int payload_len)
{
@@ -1608,7 +1608,7 @@
return 0;
}
-int
+static int
bfad_iocmd_diag_temp(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_diag_get_temp_s *iocmd =
@@ -1630,7 +1630,7 @@
return 0;
}
-int
+static int
bfad_iocmd_diag_memtest(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_diag_memtest_s *iocmd =
@@ -1653,7 +1653,7 @@
return 0;
}
-int
+static int
bfad_iocmd_diag_loopback(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_diag_loopback_s *iocmd =
@@ -1676,7 +1676,7 @@
return 0;
}
-int
+static int
bfad_iocmd_diag_fwping(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_diag_fwping_s *iocmd =
@@ -1700,7 +1700,7 @@
return 0;
}
-int
+static int
bfad_iocmd_diag_queuetest(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_diag_qtest_s *iocmd = (struct bfa_bsg_diag_qtest_s *)cmd;
@@ -1721,7 +1721,7 @@
return 0;
}
-int
+static int
bfad_iocmd_diag_sfp(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_sfp_show_s *iocmd =
@@ -1744,7 +1744,7 @@
return 0;
}
-int
+static int
bfad_iocmd_diag_led(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_diag_led_s *iocmd = (struct bfa_bsg_diag_led_s *)cmd;
@@ -1757,7 +1757,7 @@
return 0;
}
-int
+static int
bfad_iocmd_diag_beacon_lport(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_diag_beacon_s *iocmd =
@@ -1772,7 +1772,7 @@
return 0;
}
-int
+static int
bfad_iocmd_diag_lb_stat(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_diag_lb_stat_s *iocmd =
@@ -1787,7 +1787,7 @@
return 0;
}
-int
+static int
bfad_iocmd_diag_dport_enable(struct bfad_s *bfad, void *pcmd)
{
struct bfa_bsg_dport_enable_s *iocmd =
@@ -1809,7 +1809,7 @@
return 0;
}
-int
+static int
bfad_iocmd_diag_dport_disable(struct bfad_s *bfad, void *pcmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
@@ -1829,7 +1829,7 @@
return 0;
}
-int
+static int
bfad_iocmd_diag_dport_start(struct bfad_s *bfad, void *pcmd)
{
struct bfa_bsg_dport_enable_s *iocmd =
@@ -1854,7 +1854,7 @@
return 0;
}
-int
+static int
bfad_iocmd_diag_dport_show(struct bfad_s *bfad, void *pcmd)
{
struct bfa_bsg_diag_dport_show_s *iocmd =
@@ -1869,7 +1869,7 @@
}
-int
+static int
bfad_iocmd_phy_get_attr(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_phy_attr_s *iocmd =
@@ -1890,7 +1890,7 @@
return 0;
}
-int
+static int
bfad_iocmd_phy_get_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_phy_stats_s *iocmd =
@@ -1911,7 +1911,7 @@
return 0;
}
-int
+static int
bfad_iocmd_phy_read(struct bfad_s *bfad, void *cmd, unsigned int payload_len)
{
struct bfa_bsg_phy_s *iocmd = (struct bfa_bsg_phy_s *)cmd;
@@ -1943,7 +1943,7 @@
return 0;
}
-int
+static int
bfad_iocmd_vhba_query(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_vhba_attr_s *iocmd =
@@ -1962,7 +1962,7 @@
return 0;
}
-int
+static int
bfad_iocmd_phy_update(struct bfad_s *bfad, void *cmd, unsigned int payload_len)
{
struct bfa_bsg_phy_s *iocmd = (struct bfa_bsg_phy_s *)cmd;
@@ -1992,7 +1992,7 @@
return 0;
}
-int
+static int
bfad_iocmd_porglog_get(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_debug_s *iocmd = (struct bfa_bsg_debug_s *)cmd;
@@ -2012,7 +2012,7 @@
}
#define BFA_DEBUG_FW_CORE_CHUNK_SZ 0x4000U /* 16K chunks for FW dump */
-int
+static int
bfad_iocmd_debug_fw_core(struct bfad_s *bfad, void *cmd,
unsigned int payload_len)
{
@@ -2046,7 +2046,7 @@
return 0;
}
-int
+static int
bfad_iocmd_debug_ctl(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -2067,7 +2067,7 @@
return 0;
}
-int
+static int
bfad_iocmd_porglog_ctl(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_portlogctl_s *iocmd = (struct bfa_bsg_portlogctl_s *)cmd;
@@ -2081,7 +2081,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fcpim_cfg_profile(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
{
struct bfa_bsg_fcpim_profile_s *iocmd =
@@ -2125,7 +2125,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fcport_get_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fcport_stats_s *iocmd =
@@ -2150,7 +2150,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fcport_reset_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -2174,7 +2174,7 @@
return 0;
}
-int
+static int
bfad_iocmd_boot_cfg(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_boot_s *iocmd = (struct bfa_bsg_boot_s *)cmd;
@@ -2196,7 +2196,7 @@
return 0;
}
-int
+static int
bfad_iocmd_boot_query(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_boot_s *iocmd = (struct bfa_bsg_boot_s *)cmd;
@@ -2218,7 +2218,7 @@
return 0;
}
-int
+static int
bfad_iocmd_preboot_query(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_preboot_s *iocmd = (struct bfa_bsg_preboot_s *)cmd;
@@ -2237,7 +2237,7 @@
return 0;
}
-int
+static int
bfad_iocmd_ethboot_cfg(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_ethboot_s *iocmd = (struct bfa_bsg_ethboot_s *)cmd;
@@ -2260,7 +2260,7 @@
return 0;
}
-int
+static int
bfad_iocmd_ethboot_query(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_ethboot_s *iocmd = (struct bfa_bsg_ethboot_s *)cmd;
@@ -2283,7 +2283,7 @@
return 0;
}
-int
+static int
bfad_iocmd_cfg_trunk(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -2323,7 +2323,7 @@
return 0;
}
-int
+static int
bfad_iocmd_trunk_get_attr(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_trunk_attr_s *iocmd = (struct bfa_bsg_trunk_attr_s *)cmd;
@@ -2346,7 +2346,7 @@
return 0;
}
-int
+static int
bfad_iocmd_qos(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -2374,7 +2374,7 @@
return 0;
}
-int
+static int
bfad_iocmd_qos_get_attr(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_qos_attr_s *iocmd = (struct bfa_bsg_qos_attr_s *)cmd;
@@ -2400,7 +2400,7 @@
return 0;
}
-int
+static int
bfad_iocmd_qos_get_vc_attr(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_qos_vc_attr_s *iocmd =
@@ -2432,7 +2432,7 @@
return 0;
}
-int
+static int
bfad_iocmd_qos_get_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fcport_stats_s *iocmd =
@@ -2464,7 +2464,7 @@
return 0;
}
-int
+static int
bfad_iocmd_qos_reset_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
@@ -2495,7 +2495,7 @@
return 0;
}
-int
+static int
bfad_iocmd_vf_get_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_vf_stats_s *iocmd =
@@ -2518,7 +2518,7 @@
return 0;
}
-int
+static int
bfad_iocmd_vf_clr_stats(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_vf_reset_stats_s *iocmd =
@@ -2555,7 +2555,7 @@
bfad_reset_sdev_bflags(vport->drv_port.im_port, lunmask_cfg);
}
-int
+static int
bfad_iocmd_lunmask(struct bfad_s *bfad, void *pcmd, unsigned int v_cmd)
{
struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)pcmd;
@@ -2578,7 +2578,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fcpim_lunmask_query(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fcpim_lunmask_query_s *iocmd =
@@ -2592,7 +2592,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fcpim_cfg_lunmask(struct bfad_s *bfad, void *cmd, unsigned int v_cmd)
{
struct bfa_bsg_fcpim_lunmask_s *iocmd =
@@ -2611,7 +2611,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fcpim_throttle_query(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fcpim_throttle_s *iocmd =
@@ -2626,7 +2626,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fcpim_throttle_set(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fcpim_throttle_s *iocmd =
@@ -2641,7 +2641,7 @@
return 0;
}
-int
+static int
bfad_iocmd_tfru_read(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_tfru_s *iocmd =
@@ -2663,7 +2663,7 @@
return 0;
}
-int
+static int
bfad_iocmd_tfru_write(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_tfru_s *iocmd =
@@ -2685,7 +2685,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fruvpd_read(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fruvpd_s *iocmd =
@@ -2707,7 +2707,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fruvpd_update(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fruvpd_s *iocmd =
@@ -2729,7 +2729,7 @@
return 0;
}
-int
+static int
bfad_iocmd_fruvpd_get_max_size(struct bfad_s *bfad, void *cmd)
{
struct bfa_bsg_fruvpd_max_size_s *iocmd =
@@ -3177,7 +3177,7 @@
}
/* FC passthru call backs */
-u64
+static u64
bfad_fcxp_get_req_sgaddr_cb(void *bfad_fcxp, int sgeid)
{
struct bfad_fcxp *drv_fcxp = bfad_fcxp;
@@ -3189,7 +3189,7 @@
return addr;
}
-u32
+static u32
bfad_fcxp_get_req_sglen_cb(void *bfad_fcxp, int sgeid)
{
struct bfad_fcxp *drv_fcxp = bfad_fcxp;
@@ -3199,7 +3199,7 @@
return sge->sg_len;
}
-u64
+static u64
bfad_fcxp_get_rsp_sgaddr_cb(void *bfad_fcxp, int sgeid)
{
struct bfad_fcxp *drv_fcxp = bfad_fcxp;
@@ -3211,7 +3211,7 @@
return addr;
}
-u32
+static u32
bfad_fcxp_get_rsp_sglen_cb(void *bfad_fcxp, int sgeid)
{
struct bfad_fcxp *drv_fcxp = bfad_fcxp;
@@ -3221,7 +3221,7 @@
return sge->sg_len;
}
-void
+static void
bfad_send_fcpt_cb(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
bfa_status_t req_status, u32 rsp_len, u32 resid_len,
struct fchs_s *rsp_fchs)
@@ -3236,7 +3236,7 @@
complete(&drv_fcxp->comp);
}
-struct bfad_buf_info *
+static struct bfad_buf_info *
bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf,
uint32_t payload_len, uint32_t *num_sgles)
{
@@ -3280,7 +3280,7 @@
return NULL;
}
-void
+static void
bfad_fcxp_free_mem(struct bfad_s *bfad, struct bfad_buf_info *buf_base,
uint32_t num_sgles)
{
@@ -3298,7 +3298,7 @@
}
}
-int
+static int
bfad_fcxp_bsg_send(struct bsg_job *job, struct bfad_fcxp *drv_fcxp,
bfa_bsg_fcpt_t *bsg_fcpt)
{
@@ -3338,7 +3338,7 @@
return BFA_STATUS_OK;
}
-int
+static int
bfad_im_bsg_els_ct_request(struct bsg_job *job)
{
struct bfa_bsg_data *bsg_data;
diff --git a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
index e4469df..698f5eb 100644
--- a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
+++ b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
@@ -813,7 +813,7 @@
/*
- * FCoE conection data base
+ * FCoE connection data base
*/
struct fcoe_conn_db {
#if defined(__BIG_ENDIAN)
diff --git a/drivers/scsi/bnx2fc/Kconfig b/drivers/scsi/bnx2fc/Kconfig
index 40e9c9d..ecdc0f0 100644
--- a/drivers/scsi/bnx2fc/Kconfig
+++ b/drivers/scsi/bnx2fc/Kconfig
@@ -10,5 +10,5 @@
select ETHERNET
select NET_VENDOR_BROADCOM
select CNIC
- ---help---
+ help
This driver supports FCoE offload for the QLogic devices.
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
index 3b84db8..b6e8ed7 100644
--- a/drivers/scsi/bnx2fc/bnx2fc.h
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -66,7 +66,7 @@
#include "bnx2fc_constants.h"
#define BNX2FC_NAME "bnx2fc"
-#define BNX2FC_VERSION "2.12.10"
+#define BNX2FC_VERSION "2.12.13"
#define PFX "bnx2fc: "
@@ -482,7 +482,10 @@
struct bnx2fc_work {
struct list_head list;
struct bnx2fc_rport *tgt;
+ struct fcoe_task_ctx_entry *task;
+ unsigned char rq_data[BNX2FC_RQ_BUF_SZ];
u16 wqe;
+ u8 num_rq;
};
struct bnx2fc_unsol_els {
struct fc_lport *lport;
@@ -550,7 +553,7 @@
enum fc_rport_event event);
void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
struct fcoe_task_ctx_entry *task,
- u8 num_rq);
+ u8 num_rq, unsigned char *rq_data);
void bnx2fc_process_cleanup_compl(struct bnx2fc_cmd *io_req,
struct fcoe_task_ctx_entry *task,
u8 num_rq);
@@ -559,7 +562,7 @@
u8 num_rq);
void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
struct fcoe_task_ctx_entry *task,
- u8 num_rq);
+ u8 num_rq, unsigned char *rq_data);
void bnx2fc_process_els_compl(struct bnx2fc_cmd *els_req,
struct fcoe_task_ctx_entry *task,
u8 num_rq);
@@ -577,7 +580,9 @@
void *arg, u32 timeout);
void bnx2fc_arm_cq(struct bnx2fc_rport *tgt);
int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt);
-void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe);
+void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe,
+ unsigned char *rq_data, u8 num_rq,
+ struct fcoe_task_ctx_entry *task);
struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
u32 port_id);
void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index b4bfab5..8f47bf8 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -50,7 +50,7 @@
* Here the io threads are per cpu but the l2 thread is just one
*/
struct fcoe_percpu_s bnx2fc_global;
-DEFINE_SPINLOCK(bnx2fc_global_lock);
+static DEFINE_SPINLOCK(bnx2fc_global_lock);
static struct cnic_ulp_ops bnx2fc_cnic_cb;
static struct libfc_function_template bnx2fc_libfc_fcn_templ;
@@ -80,7 +80,7 @@
static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba);
static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
struct device *parent, int npiv);
-static void bnx2fc_destroy_work(struct work_struct *work);
+static void bnx2fc_port_destroy(struct fcoe_port *port);
static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev);
static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device
@@ -108,22 +108,22 @@
"\t\t0x10 - fcoe L2 fame related logs.\n"
"\t\t0xff - LOG all messages.");
-uint bnx2fc_devloss_tmo;
+static uint bnx2fc_devloss_tmo;
module_param_named(devloss_tmo, bnx2fc_devloss_tmo, uint, S_IRUGO);
MODULE_PARM_DESC(devloss_tmo, " Change devloss_tmo for the remote ports "
"attached via bnx2fc.");
-uint bnx2fc_max_luns = BNX2FC_MAX_LUN;
+static uint bnx2fc_max_luns = BNX2FC_MAX_LUN;
module_param_named(max_luns, bnx2fc_max_luns, uint, S_IRUGO);
MODULE_PARM_DESC(max_luns, " Change the default max_lun per SCSI host. Default "
"0xffff.");
-uint bnx2fc_queue_depth;
+static uint bnx2fc_queue_depth;
module_param_named(queue_depth, bnx2fc_queue_depth, uint, S_IRUGO);
MODULE_PARM_DESC(queue_depth, " Change the default queue depth of SCSI devices "
"attached via bnx2fc.");
-uint bnx2fc_log_fka;
+static uint bnx2fc_log_fka;
module_param_named(log_fka, bnx2fc_log_fka, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(log_fka, " Print message to kernel log when fcoe is "
"initiating a FIP keep alive when debug logging is enabled.");
@@ -506,7 +506,8 @@
static void bnx2fc_recv_frame(struct sk_buff *skb)
{
- u32 fr_len;
+ u64 crc_err;
+ u32 fr_len, fr_crc;
struct fc_lport *lport;
struct fcoe_rcv_info *fr;
struct fc_stats *stats;
@@ -540,6 +541,11 @@
skb_pull(skb, sizeof(struct fcoe_hdr));
fr_len = skb->len - sizeof(struct fcoe_crc_eof);
+ stats = per_cpu_ptr(lport->stats, get_cpu());
+ stats->RxFrames++;
+ stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
+ put_cpu();
+
fp = (struct fc_frame *)skb;
fc_frame_init(fp);
fr_dev(fp) = lport;
@@ -622,16 +628,15 @@
return;
}
- stats = per_cpu_ptr(lport->stats, smp_processor_id());
- stats->RxFrames++;
- stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
+ fr_crc = le32_to_cpu(fr_crc(fp));
- if (le32_to_cpu(fr_crc(fp)) !=
- ~crc32(~0, skb->data, fr_len)) {
- if (stats->InvalidCRCCount < 5)
+ if (unlikely(fr_crc != ~crc32(~0, skb->data, fr_len))) {
+ stats = per_cpu_ptr(lport->stats, get_cpu());
+ crc_err = (stats->InvalidCRCCount++);
+ put_cpu();
+ if (crc_err < 5)
printk(KERN_WARNING PFX "dropping frame with "
"CRC error\n");
- stats->InvalidCRCCount++;
kfree_skb(skb);
return;
}
@@ -660,7 +665,10 @@
list_for_each_entry_safe(work, tmp, &work_list, list) {
list_del_init(&work->list);
- bnx2fc_process_cq_compl(work->tgt, work->wqe);
+ bnx2fc_process_cq_compl(work->tgt, work->wqe,
+ work->rq_data,
+ work->num_rq,
+ work->task);
kfree(work);
}
@@ -902,9 +910,6 @@
__bnx2fc_destroy(interface);
}
mutex_unlock(&bnx2fc_dev_lock);
-
- /* Ensure ALL destroy work has been completed before return */
- flush_workqueue(bnx2fc_wq);
return;
default:
@@ -942,7 +947,7 @@
*/
if (interface->enabled)
fcoe_ctlr_link_up(ctlr);
- };
+ }
} else if (fcoe_ctlr_link_down(ctlr)) {
switch (cdev->enabled) {
case FCOE_CTLR_DISABLED:
@@ -962,7 +967,7 @@
put_cpu();
fcoe_clean_pending_queue(lport);
wait_for_upload = 1;
- };
+ }
}
}
mutex_unlock(&bnx2fc_dev_lock);
@@ -1068,9 +1073,8 @@
/**
* bnx2fc_update_src_mac - Update Ethernet MAC filters.
*
- * @fip: FCoE controller.
- * @old: Unicast MAC address to delete if the MAC is non-zero.
- * @new: Unicast MAC address to add.
+ * @lport: The local port
+ * @addr: Location of data to copy
*
* Remove any previously-set unicast MAC filter.
* Add secondary FCoE MAC address filter for our OUI.
@@ -1211,8 +1215,8 @@
mutex_unlock(&n_port->lp_mutex);
bnx2fc_free_vport(interface->hba, port->lport);
bnx2fc_port_shutdown(port->lport);
+ bnx2fc_port_destroy(port);
bnx2fc_interface_put(interface);
- queue_work(bnx2fc_wq, &port->destroy_work);
return 0;
}
@@ -1521,7 +1525,6 @@
port->lport = lport;
port->priv = interface;
port->get_netdev = bnx2fc_netdev;
- INIT_WORK(&port->destroy_work, bnx2fc_destroy_work);
/* Configure fcoe_port */
rc = bnx2fc_lport_config(lport);
@@ -1649,15 +1652,14 @@
bnx2fc_interface_cleanup(interface);
bnx2fc_stop(interface);
list_del(&interface->list);
+ bnx2fc_port_destroy(port);
bnx2fc_interface_put(interface);
- queue_work(bnx2fc_wq, &port->destroy_work);
}
/**
* bnx2fc_destroy - Destroy a bnx2fc FCoE interface
*
- * @buffer: The name of the Ethernet interface to be destroyed
- * @kp: The associated kernel parameter
+ * @netdev: The net device that the FCoE interface is on
*
* Called from sysfs.
*
@@ -1691,15 +1693,12 @@
return rc;
}
-static void bnx2fc_destroy_work(struct work_struct *work)
+static void bnx2fc_port_destroy(struct fcoe_port *port)
{
- struct fcoe_port *port;
struct fc_lport *lport;
- port = container_of(work, struct fcoe_port, destroy_work);
lport = port->lport;
-
- BNX2FC_HBA_DBG(lport, "Entered bnx2fc_destroy_work\n");
+ BNX2FC_HBA_DBG(lport, "Entered %s, destroying lport %p\n", __func__, lport);
bnx2fc_if_destroy(lport);
}
@@ -2098,7 +2097,7 @@
return 0;
}
-/**
+/*
* Deperecated: Use bnx2fc_enabled()
*/
static int bnx2fc_disable(struct net_device *netdev)
@@ -2226,7 +2225,7 @@
return 0;
}
-/**
+/*
* Deprecated: Use bnx2fc_enabled()
*/
static int bnx2fc_enable(struct net_device *netdev)
@@ -2520,7 +2519,7 @@
/**
* bnx2fc_ulp_exit - shuts down adapter instance and frees all resources
*
- * @dev cnic device handle
+ * @dev: cnic device handle
*/
static void bnx2fc_ulp_exit(struct cnic_dev *dev)
{
@@ -2553,9 +2552,6 @@
__bnx2fc_destroy(interface);
mutex_unlock(&bnx2fc_dev_lock);
- /* Ensure ALL destroy work has been completed before return */
- flush_workqueue(bnx2fc_wq);
-
bnx2fc_ulp_stop(hba);
/* unregister cnic device */
if (test_and_clear_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic))
@@ -2655,7 +2651,8 @@
/* Free all work in the list */
list_for_each_entry_safe(work, tmp, &p->work_list, list) {
list_del_init(&work->list);
- bnx2fc_process_cq_compl(work->tgt, work->wqe);
+ bnx2fc_process_cq_compl(work->tgt, work->wqe, work->rq_data,
+ work->num_rq, work->task);
kfree(work);
}
@@ -2952,7 +2949,7 @@
NULL,
};
-/**
+/*
* scsi_host_template structure used while registering with SCSI-ml
*/
static struct scsi_host_template bnx2fc_shost_template = {
@@ -2985,7 +2982,7 @@
.rport_event_callback = bnx2fc_rport_event_handler,
};
-/**
+/*
* bnx2fc_cnic_cb - global template of bnx2fc - cnic driver interface
* structure carrying callback function pointers
*/
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
index f069e09..0899209 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -485,7 +485,7 @@
/**
* bnx2fc_send_session_destroy_req - initiates FCoE Session destroy
*
- * @port: port structure pointer
+ * @hba: adapter structure pointer
* @tgt: bnx2fc_rport structure pointer
*/
int bnx2fc_send_session_destroy_req(struct bnx2fc_hba *hba,
@@ -635,7 +635,6 @@
struct bnx2fc_cmd *io_req = NULL;
struct bnx2fc_interface *interface = tgt->port->priv;
struct bnx2fc_hba *hba = interface->hba;
- int task_idx, index;
int rc = 0;
u64 err_warn_bit_map;
u8 err_warn = 0xff;
@@ -701,15 +700,12 @@
BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x\n",
err_entry->data.tx_buf_off, err_entry->data.rx_buf_off);
-
if (xid > hba->max_xid) {
BNX2FC_TGT_DBG(tgt, "xid(0x%x) out of FW range\n",
xid);
goto ret_err_rqe;
}
- task_idx = xid / BNX2FC_TASKS_PER_PAGE;
- index = xid % BNX2FC_TASKS_PER_PAGE;
io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
if (!io_req)
@@ -833,8 +829,6 @@
}
BNX2FC_TGT_DBG(tgt, "warn = 0x%x\n", err_warn);
- task_idx = xid / BNX2FC_TASKS_PER_PAGE;
- index = xid % BNX2FC_TASKS_PER_PAGE;
io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
if (!io_req)
goto ret_warn_rqe;
@@ -863,36 +857,22 @@
}
}
-void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
+void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe,
+ unsigned char *rq_data, u8 num_rq,
+ struct fcoe_task_ctx_entry *task)
{
- struct fcoe_task_ctx_entry *task;
- struct fcoe_task_ctx_entry *task_page;
struct fcoe_port *port = tgt->port;
struct bnx2fc_interface *interface = port->priv;
struct bnx2fc_hba *hba = interface->hba;
struct bnx2fc_cmd *io_req;
- int task_idx, index;
+
u16 xid;
u8 cmd_type;
u8 rx_state = 0;
- u8 num_rq;
spin_lock_bh(&tgt->tgt_lock);
+
xid = wqe & FCOE_PEND_WQ_CQE_TASK_ID;
- if (xid >= hba->max_tasks) {
- printk(KERN_ERR PFX "ERROR:xid out of range\n");
- spin_unlock_bh(&tgt->tgt_lock);
- return;
- }
- task_idx = xid / BNX2FC_TASKS_PER_PAGE;
- index = xid % BNX2FC_TASKS_PER_PAGE;
- task_page = (struct fcoe_task_ctx_entry *)hba->task_ctx[task_idx];
- task = &(task_page[index]);
-
- num_rq = ((task->rxwr_txrd.var_ctx.rx_flags &
- FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE) >>
- FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT);
-
io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
if (io_req == NULL) {
@@ -912,7 +892,8 @@
switch (cmd_type) {
case BNX2FC_SCSI_CMD:
if (rx_state == FCOE_TASK_RX_STATE_COMPLETED) {
- bnx2fc_process_scsi_cmd_compl(io_req, task, num_rq);
+ bnx2fc_process_scsi_cmd_compl(io_req, task, num_rq,
+ rq_data);
spin_unlock_bh(&tgt->tgt_lock);
return;
}
@@ -929,7 +910,7 @@
case BNX2FC_TASK_MGMT_CMD:
BNX2FC_IO_DBG(io_req, "Processing TM complete\n");
- bnx2fc_process_tm_compl(io_req, task, num_rq);
+ bnx2fc_process_tm_compl(io_req, task, num_rq, rq_data);
break;
case BNX2FC_ABTS:
@@ -987,7 +968,9 @@
}
-static struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe)
+static struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe,
+ unsigned char *rq_data, u8 num_rq,
+ struct fcoe_task_ctx_entry *task)
{
struct bnx2fc_work *work;
work = kzalloc(sizeof(struct bnx2fc_work), GFP_ATOMIC);
@@ -997,29 +980,86 @@
INIT_LIST_HEAD(&work->list);
work->tgt = tgt;
work->wqe = wqe;
+ work->num_rq = num_rq;
+ work->task = task;
+ if (rq_data)
+ memcpy(work->rq_data, rq_data, BNX2FC_RQ_BUF_SZ);
+
return work;
}
/* Pending work request completion */
-static void bnx2fc_pending_work(struct bnx2fc_rport *tgt, unsigned int wqe)
+static bool bnx2fc_pending_work(struct bnx2fc_rport *tgt, unsigned int wqe)
{
unsigned int cpu = wqe % num_possible_cpus();
struct bnx2fc_percpu_s *fps;
struct bnx2fc_work *work;
+ struct fcoe_task_ctx_entry *task;
+ struct fcoe_task_ctx_entry *task_page;
+ struct fcoe_port *port = tgt->port;
+ struct bnx2fc_interface *interface = port->priv;
+ struct bnx2fc_hba *hba = interface->hba;
+ unsigned char *rq_data = NULL;
+ unsigned char rq_data_buff[BNX2FC_RQ_BUF_SZ];
+ int task_idx, index;
+ u16 xid;
+ u8 num_rq;
+ int i;
+
+ xid = wqe & FCOE_PEND_WQ_CQE_TASK_ID;
+ if (xid >= hba->max_tasks) {
+ pr_err(PFX "ERROR:xid out of range\n");
+ return false;
+ }
+
+ task_idx = xid / BNX2FC_TASKS_PER_PAGE;
+ index = xid % BNX2FC_TASKS_PER_PAGE;
+ task_page = (struct fcoe_task_ctx_entry *)hba->task_ctx[task_idx];
+ task = &task_page[index];
+
+ num_rq = ((task->rxwr_txrd.var_ctx.rx_flags &
+ FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE) >>
+ FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT);
+
+ memset(rq_data_buff, 0, BNX2FC_RQ_BUF_SZ);
+
+ if (!num_rq)
+ goto num_rq_zero;
+
+ rq_data = bnx2fc_get_next_rqe(tgt, 1);
+
+ if (num_rq > 1) {
+ /* We do not need extra sense data */
+ for (i = 1; i < num_rq; i++)
+ bnx2fc_get_next_rqe(tgt, 1);
+ }
+
+ if (rq_data)
+ memcpy(rq_data_buff, rq_data, BNX2FC_RQ_BUF_SZ);
+
+ /* return RQ entries */
+ for (i = 0; i < num_rq; i++)
+ bnx2fc_return_rqe(tgt, 1);
+
+num_rq_zero:
fps = &per_cpu(bnx2fc_percpu, cpu);
spin_lock_bh(&fps->fp_work_lock);
if (fps->iothread) {
- work = bnx2fc_alloc_work(tgt, wqe);
+ work = bnx2fc_alloc_work(tgt, wqe, rq_data_buff,
+ num_rq, task);
if (work) {
list_add_tail(&work->list, &fps->work_list);
wake_up_process(fps->iothread);
spin_unlock_bh(&fps->fp_work_lock);
- return;
+ return true;
}
}
spin_unlock_bh(&fps->fp_work_lock);
- bnx2fc_process_cq_compl(tgt, wqe);
+ bnx2fc_process_cq_compl(tgt, wqe,
+ rq_data_buff, num_rq, task);
+
+ return true;
}
int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt)
@@ -1056,8 +1096,8 @@
/* Unsolicited event notification */
bnx2fc_process_unsol_compl(tgt, wqe);
} else {
- bnx2fc_pending_work(tgt, wqe);
- num_free_sqes++;
+ if (bnx2fc_pending_work(tgt, wqe))
+ num_free_sqes++;
}
cqe++;
tgt->cq_cons_idx++;
@@ -1294,8 +1334,8 @@
/**
* bnx2fc_indicae_kcqe - process KCQE
*
- * @hba: adapter structure pointer
- * @kcqe: kcqe pointer
+ * @context: adapter structure pointer
+ * @kcq: kcqe pointer
* @num_cqe: Number of completion queue elements
*
* Generic KCQ event handler
@@ -1364,7 +1404,6 @@
break;
case FCOE_KCQE_OPCODE_FCOE_ERROR:
- /* fall thru */
default:
printk(KERN_ERR PFX "unknown opcode 0x%x\n",
kcqe->op_code);
@@ -1414,7 +1453,7 @@
reg_base = pci_resource_start(hba->pcidev,
BNX2X_DOORBELL_PCI_BAR);
reg_off = (1 << BNX2X_DB_SHIFT) * (context_id & 0x1FFFF);
- tgt->ctx_base = ioremap_nocache(reg_base + reg_off, 4);
+ tgt->ctx_base = ioremap(reg_base + reg_off, 4);
if (!tgt->ctx_base)
return -ENOMEM;
return 0;
@@ -1463,7 +1502,6 @@
u64 phys_addr = (u64)orig_io_req->bd_tbl->bd_tbl_dma;
u32 orig_offset = offset;
int bd_count;
- int orig_task_idx, index;
int i;
memset(task, 0, sizeof(struct fcoe_task_ctx_entry));
@@ -1513,8 +1551,6 @@
offset; /* adjusted offset */
task->txwr_only.sgl_ctx.sgl.mul_sgl.cur_sge_idx = i;
} else {
- orig_task_idx = orig_xid / BNX2FC_TASKS_PER_PAGE;
- index = orig_xid % BNX2FC_TASKS_PER_PAGE;
/* Multiple SGEs were used for this IO */
sgl = &task->rxwr_only.union_ctx.read_info.sgl_ctx.sgl;
@@ -2042,11 +2078,7 @@
pbl = hba->hash_tbl_pbl;
i = 0;
while (*pbl && *(pbl + 1)) {
- u32 lo;
- u32 hi;
- lo = *pbl;
++pbl;
- hi = *pbl;
++pbl;
++i;
}
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index a0e7764..ed300a2 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -24,7 +24,7 @@
static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req);
static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
struct fcoe_fcp_rsp_payload *fcp_rsp,
- u8 num_rq);
+ u8 num_rq, unsigned char *rq_data);
void bnx2fc_cmd_timer_set(struct bnx2fc_cmd *io_req,
unsigned int timer_msec)
@@ -864,7 +864,7 @@
abts_io_req = bnx2fc_elstm_alloc(tgt, BNX2FC_ABTS);
if (!abts_io_req) {
- printk(KERN_ERR PFX "abts: couldnt allocate cmd\n");
+ printk(KERN_ERR PFX "abts: couldn't allocate cmd\n");
rc = FAILED;
goto abts_err;
}
@@ -957,7 +957,7 @@
seq_clnp_req = bnx2fc_elstm_alloc(tgt, BNX2FC_SEQ_CLEANUP);
if (!seq_clnp_req) {
- printk(KERN_ERR PFX "cleanup: couldnt allocate cmd\n");
+ printk(KERN_ERR PFX "cleanup: couldn't allocate cmd\n");
rc = -ENOMEM;
kfree(cb_arg);
goto cleanup_err;
@@ -1015,7 +1015,7 @@
cleanup_io_req = bnx2fc_elstm_alloc(tgt, BNX2FC_CLEANUP);
if (!cleanup_io_req) {
- printk(KERN_ERR PFX "cleanup: couldnt allocate cmd\n");
+ printk(KERN_ERR PFX "cleanup: couldn't allocate cmd\n");
rc = -1;
goto cleanup_err;
}
@@ -1081,6 +1081,7 @@
}
static int bnx2fc_abts_cleanup(struct bnx2fc_cmd *io_req)
+ __must_hold(&tgt->tgt_lock)
{
struct bnx2fc_rport *tgt = io_req->tgt;
unsigned int time_left;
@@ -1243,7 +1244,7 @@
/* Wait 2 * RA_TOV + 1 to be sure timeout function hasn't fired */
time_left = wait_for_completion_timeout(&io_req->abts_done,
- (2 * rp->r_a_tov + 1) * HZ);
+ msecs_to_jiffies(2 * rp->r_a_tov + 1));
if (time_left)
BNX2FC_IO_DBG(io_req,
"Timed out in eh_abort waiting for abts_done");
@@ -1519,7 +1520,8 @@
}
void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
- struct fcoe_task_ctx_entry *task, u8 num_rq)
+ struct fcoe_task_ctx_entry *task, u8 num_rq,
+ unsigned char *rq_data)
{
struct bnx2fc_mp_req *tm_req;
struct fc_frame_header *fc_hdr;
@@ -1558,7 +1560,7 @@
if (fc_hdr->fh_r_ctl == FC_RCTL_DD_CMD_STATUS) {
bnx2fc_parse_fcp_rsp(io_req,
(struct fcoe_fcp_rsp_payload *)
- rsp_buf, num_rq);
+ rsp_buf, num_rq, rq_data);
if (io_req->fcp_rsp_code == 0) {
/* TM successful */
if (tm_req->tm_flags & FCP_TMF_LUN_RESET)
@@ -1756,15 +1758,11 @@
static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
struct fcoe_fcp_rsp_payload *fcp_rsp,
- u8 num_rq)
+ u8 num_rq, unsigned char *rq_data)
{
struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
- struct bnx2fc_rport *tgt = io_req->tgt;
u8 rsp_flags = fcp_rsp->fcp_flags.flags;
u32 rq_buff_len = 0;
- int i;
- unsigned char *rq_data;
- unsigned char *dummy;
int fcp_sns_len = 0;
int fcp_rsp_len = 0;
@@ -1810,14 +1808,6 @@
rq_buff_len = num_rq * BNX2FC_RQ_BUF_SZ;
}
- rq_data = bnx2fc_get_next_rqe(tgt, 1);
-
- if (num_rq > 1) {
- /* We do not need extra sense data */
- for (i = 1; i < num_rq; i++)
- dummy = bnx2fc_get_next_rqe(tgt, 1);
- }
-
/* fetch fcp_rsp_code */
if ((fcp_rsp_len == 4) || (fcp_rsp_len == 8)) {
/* Only for task management function */
@@ -1838,9 +1828,6 @@
if (fcp_sns_len)
memcpy(sc_cmd->sense_buffer, rq_data, fcp_sns_len);
- /* return RQ entries */
- for (i = 0; i < num_rq; i++)
- bnx2fc_return_rqe(tgt, 1);
}
}
@@ -1919,7 +1906,7 @@
void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
struct fcoe_task_ctx_entry *task,
- u8 num_rq)
+ u8 num_rq, unsigned char *rq_data)
{
struct fcoe_fcp_rsp_payload *fcp_rsp;
struct bnx2fc_rport *tgt = io_req->tgt;
@@ -1932,6 +1919,12 @@
/* we will not receive ABTS response for this IO */
BNX2FC_IO_DBG(io_req, "Timer context finished processing "
"this scsi cmd\n");
+ if (test_and_clear_bit(BNX2FC_FLAG_IO_CLEANUP,
+ &io_req->req_flags)) {
+ BNX2FC_IO_DBG(io_req,
+ "Actual completion after cleanup request cleaning up\n");
+ bnx2fc_process_cleanup_compl(io_req, task, num_rq);
+ }
return;
}
@@ -1951,7 +1944,7 @@
&(task->rxwr_only.union_ctx.comp_info.fcp_rsp.payload);
/* parse fcp_rsp and obtain sense data from RQ if available */
- bnx2fc_parse_fcp_rsp(io_req, fcp_rsp, num_rq);
+ bnx2fc_parse_fcp_rsp(io_req, fcp_rsp, num_rq, rq_data);
if (!sc_cmd->SCp.ptr) {
printk(KERN_ERR PFX "SCp.ptr is NULL\n");
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index 50384b4..a3e2a38 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -431,7 +431,7 @@
return 0;
}
-/**
+/*
* This event_callback is called after successful completion of libfc
* initiated target login. bnx2fc can proceed with initiating the session
* establishment.
@@ -656,9 +656,8 @@
spin_unlock_bh(&hba->hba_lock);
}
-/**
- *bnx2fc_alloc_session_resc - Allocate qp resources for the session
- *
+/*
+ * bnx2fc_alloc_session_resc - Allocate qp resources for the session
*/
static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
struct bnx2fc_rport *tgt)
diff --git a/drivers/scsi/bnx2i/Kconfig b/drivers/scsi/bnx2i/Kconfig
index a0c0791..0cc06c2 100644
--- a/drivers/scsi/bnx2i/Kconfig
+++ b/drivers/scsi/bnx2i/Kconfig
@@ -10,6 +10,6 @@
select ETHERNET
select NET_VENDOR_BROADCOM
select CNIC
- ---help---
+ help
This driver supports iSCSI offload for the QLogic NetXtreme II
devices.
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 1266631..bad396e 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -181,7 +181,7 @@
/**
* bnx2i_get_rq_buf - copy RQ buffer contents to driver buffer
- * @conn: iscsi connection on which RQ event occurred
+ * @bnx2i_conn: iscsi connection on which RQ event occurred
* @ptr: driver buffer to which RQ buffer contents is to
* be copied
* @len: length of valid data inside RQ buf
@@ -223,7 +223,7 @@
/**
* bnx2i_put_rq_buf - Replenish RQ buffer, if required ring on chip doorbell
- * @conn: iscsi connection on which event to post
+ * @bnx2i_conn: iscsi connection on which event to post
* @count: number of RQ buffer being posted to chip
*
* No need to ring hardware doorbell for 57710 family of devices
@@ -258,7 +258,7 @@
/**
* bnx2i_ring_sq_dbell - Ring SQ doorbell to wake-up the processing engine
- * @conn: iscsi connection to which new SQ entries belong
+ * @bnx2i_conn: iscsi connection to which new SQ entries belong
* @count: number of SQ WQEs to post
*
* SQ DB is updated in host memory and TX Doorbell is rung for 57710 family
@@ -283,7 +283,7 @@
/**
* bnx2i_ring_dbell_update_sq_params - update SQ driver parameters
- * @conn: iscsi connection to which new SQ entries belong
+ * @bnx2i_conn: iscsi connection to which new SQ entries belong
* @count: number of SQ WQEs to post
*
* this routine will update SQ driver parameters and ring the doorbell
@@ -320,9 +320,9 @@
/**
* bnx2i_send_iscsi_login - post iSCSI login request MP WQE to hardware
- * @conn: iscsi connection
- * @cmd: driver command structure which is requesting
- * a WQE to sent to chip for further processing
+ * @bnx2i_conn: iscsi connection
+ * @task: transport layer's command structure pointer which is requesting
+ * a WQE to sent to chip for further processing
*
* prepare and post an iSCSI Login request WQE to CNIC firmware
*/
@@ -373,7 +373,7 @@
/**
* bnx2i_send_iscsi_tmf - post iSCSI task management request MP WQE to hardware
- * @conn: iscsi connection
+ * @bnx2i_conn: iscsi connection
* @mtask: driver command structure which is requesting
* a WQE to sent to chip for further processing
*
@@ -447,7 +447,7 @@
/**
* bnx2i_send_iscsi_text - post iSCSI text WQE to hardware
- * @conn: iscsi connection
+ * @bnx2i_conn: iscsi connection
* @mtask: driver command structure which is requesting
* a WQE to sent to chip for further processing
*
@@ -495,7 +495,7 @@
/**
* bnx2i_send_iscsi_scsicmd - post iSCSI scsicmd request WQE to hardware
- * @conn: iscsi connection
+ * @bnx2i_conn: iscsi connection
* @cmd: driver command structure which is requesting
* a WQE to sent to chip for further processing
*
@@ -517,9 +517,9 @@
/**
* bnx2i_send_iscsi_nopout - post iSCSI NOPOUT request WQE to hardware
- * @conn: iscsi connection
- * @cmd: driver command structure which is requesting
- * a WQE to sent to chip for further processing
+ * @bnx2i_conn: iscsi connection
+ * @task: transport layer's command structure pointer which is
+ * requesting a WQE to sent to chip for further processing
* @datap: payload buffer pointer
* @data_len: payload data length
* @unsol: indicated whether nopout pdu is unsolicited pdu or
@@ -579,9 +579,9 @@
/**
* bnx2i_send_iscsi_logout - post iSCSI logout request WQE to hardware
- * @conn: iscsi connection
- * @cmd: driver command structure which is requesting
- * a WQE to sent to chip for further processing
+ * @bnx2i_conn: iscsi connection
+ * @task: transport layer's command structure pointer which is
+ * requesting a WQE to sent to chip for further processing
*
* prepare and post logout request WQE to CNIC firmware
*/
@@ -678,7 +678,8 @@
/**
* bnx2i_ep_ofld_timer - post iSCSI logout request WQE to hardware
- * @data: endpoint (transport handle) structure pointer
+ * @t: timer context used to fetch the endpoint (transport
+ * handle) structure pointer
*
* routine to handle connection offload/destroy request timeout
*/
@@ -1662,7 +1663,7 @@
/**
* bnx2i_unsol_pdu_adjust_rq - makes adjustments to RQ after unsol pdu is recvd
- * @conn: iscsi connection
+ * @bnx2i_conn: iscsi connection
*
* Firmware advances RQ producer index for every unsolicited PDU even if
* payload data length is '0'. This function makes corresponding
@@ -1885,7 +1886,9 @@
/**
* bnx2i_queue_scsi_cmd_resp - queue cmd completion to the percpu thread
+ * @session: iscsi session
* @bnx2i_conn: bnx2i connection
+ * @cqe: pointer to newly DMA'ed CQE entry for processing
*
* this function is called by generic KCQ handler to queue all pending cmd
* completion CQEs
@@ -2466,8 +2469,9 @@
/**
* bnx2i_indicate_kcqe - process iscsi conn update completion KCQE
- * @hba: adapter structure pointer
- * @update_kcqe: kcqe pointer
+ * @context: adapter structure pointer
+ * @kcqe: kcqe pointer
+ * @num_cqe: number of kcqes to process
*
* Generic KCQ event handler/dispatcher
*/
@@ -2614,8 +2618,7 @@
/**
* bnx2i_cm_remote_close - process received TCP FIN
- * @hba: adapter structure pointer
- * @update_kcqe: kcqe pointer
+ * @cm_sk: cnic sock structure pointer
*
* function callback exported via bnx2i - cnic driver interface to indicate
* async TCP events such as FIN
@@ -2631,8 +2634,7 @@
/**
* bnx2i_cm_remote_abort - process TCP RST and start conn cleanup
- * @hba: adapter structure pointer
- * @update_kcqe: kcqe pointer
+ * @cm_sk: cnic sock structure pointer
*
* function callback exported via bnx2i - cnic driver interface to
* indicate async TCP events (RST) sent by the peer.
@@ -2669,10 +2671,9 @@
}
-/**
+/*
* bnx2i_cnic_cb - global template of bnx2i - cnic driver interface structure
* carrying callback function pointers
- *
*/
struct cnic_ulp_ops bnx2i_cnic_cb = {
.cnic_init = bnx2i_ulp_init,
@@ -2715,7 +2716,7 @@
reg_base = pci_resource_start(ep->hba->pcidev,
BNX2X_DOORBELL_PCI_BAR);
reg_off = (1 << BNX2X_DB_SHIFT) * (cid_num & 0x1FFFF);
- ep->qp.ctx_base = ioremap_nocache(reg_base + reg_off, 4);
+ ep->qp.ctx_base = ioremap(reg_base + reg_off, 4);
if (!ep->qp.ctx_base)
return -ENOMEM;
goto arm_cq;
@@ -2736,7 +2737,7 @@
/* 5709 device in normal node and 5706/5708 devices */
reg_off = CTX_OFFSET + (MB_KERNEL_CTX_SIZE * cid_num);
- ep->qp.ctx_base = ioremap_nocache(ep->hba->reg_base + reg_off,
+ ep->qp.ctx_base = ioremap(ep->hba->reg_base + reg_off,
MB_KERNEL_CTX_SIZE);
if (!ep->qp.ctx_base)
return -ENOMEM;
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 4ebcda8..2b3f0c1 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -73,7 +73,7 @@
/**
* bnx2i_identify_device - identifies NetXtreme II device type
* @hba: Adapter structure pointer
- * @cnic: Corresponding cnic device
+ * @dev: Corresponding cnic device
*
* This function identifies the NX2 device type and sets appropriate
* queue mailbox register access method, 5709 requires driver to
@@ -474,8 +474,6 @@
if (sq_size && !is_power_of_2(sq_size))
sq_size = roundup_pow_of_two(sq_size);
- mutex_init(&bnx2i_dev_lock);
-
bnx2i_scsi_xport_template =
iscsi_register_transport(&bnx2i_iscsi_transport);
if (!bnx2i_scsi_xport_template) {
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 949d20b..21efc73 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -228,7 +228,7 @@
/**
* bnx2i_bind_conn_to_iscsi_cid - bind conn structure to 'iscsi_cid'
* @hba: pointer to adapter instance
- * @conn: pointer to iscsi connection
+ * @bnx2i_conn: pointer to iscsi connection
* @iscsi_cid: iscsi context ID, range 0 - (MAX_CONN - 1)
*
* update iscsi cid table entry with connection pointer. This enables
@@ -463,7 +463,6 @@
* bnx2i_destroy_cmd_pool - destroys iscsi command pool and release BD table
* @hba: adapter instance pointer
* @session: iscsi session pointer
- * @cmd: iscsi command structure
*/
static void bnx2i_destroy_cmd_pool(struct bnx2i_hba *hba,
struct iscsi_session *session)
@@ -582,8 +581,7 @@
/**
* bnx2i_drop_session - notifies iscsid of connection error.
- * @hba: adapter instance pointer
- * @session: iscsi session pointer
+ * @cls_session: iscsi cls session pointer
*
* This notifies iscsid that there is a error, so it can initiate
* recovery.
@@ -1277,7 +1275,8 @@
/**
* bnx2i_session_create - create a new iscsi session
- * @cmds_max: max commands supported
+ * @ep: pointer to iscsi endpoint
+ * @cmds_max: user specified maximum commands
* @qdepth: scsi queue depth to support
* @initial_cmdsn: initial iscsi CMDSN to be used for this session
*
@@ -1971,7 +1970,7 @@
/**
* bnx2i_ep_tcp_conn_active - check EP state transition
- * @ep: endpoint pointer
+ * @bnx2i_ep: endpoint pointer
*
* check if underlying TCP connection is active
*/
@@ -2014,9 +2013,9 @@
}
-/*
+/**
* bnx2i_hw_ep_disconnect - executes TCP connection teardown process in the hw
- * @ep: TCP connection (bnx2i endpoint) handle
+ * @bnx2i_ep: TCP connection (bnx2i endpoint) handle
*
* executes TCP connection teardown process
*/
@@ -2171,8 +2170,8 @@
/**
* bnx2i_nl_set_path - ISCSI_UEVENT_PATH_UPDATE user message handler
- * @buf: pointer to buffer containing iscsi path message
- *
+ * @shost: scsi host pointer
+ * @params: pointer to buffer containing iscsi path message
*/
static int bnx2i_nl_set_path(struct Scsi_Host *shost, struct iscsi_path *params)
{
diff --git a/drivers/scsi/bnx2i/bnx2i_sysfs.c b/drivers/scsi/bnx2i/bnx2i_sysfs.c
index 6d56fd6..3dc7900 100644
--- a/drivers/scsi/bnx2i/bnx2i_sysfs.c
+++ b/drivers/scsi/bnx2i/bnx2i_sysfs.c
@@ -30,6 +30,7 @@
/**
* bnx2i_show_sq_info - return(s currently configured send queue (SQ) size
* @dev: device pointer
+ * @attr: device attribute (unused)
* @buf: buffer to return current SQ size parameter
*
* Returns current SQ size parameter, this paramater determines the number
@@ -47,6 +48,7 @@
/**
* bnx2i_set_sq_info - update send queue (SQ) size parameter
* @dev: device pointer
+ * @attr: device attribute (unused)
* @buf: buffer to return current SQ size parameter
* @count: parameter buffer size
*
@@ -87,6 +89,7 @@
/**
* bnx2i_show_ccell_info - returns command cell (HQ) size
* @dev: device pointer
+ * @attr: device attribute (unused)
* @buf: buffer to return current SQ size parameter
*
* returns per-connection TCP history queue size parameter
@@ -103,6 +106,7 @@
/**
* bnx2i_get_link_state - set command cell (HQ) size
* @dev: device pointer
+ * @attr: device attribute (unused)
* @buf: buffer to return current SQ size parameter
* @count: parameter buffer size
*
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index 76751d6..cb74ab1 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -44,7 +44,6 @@
MODULE_ALIAS_CHARDEV_MAJOR(SCSI_CHANGER_MAJOR);
MODULE_ALIAS_SCSI_DEVICE(TYPE_MEDIUM_CHANGER);
-static DEFINE_MUTEX(ch_mutex);
static int init = 1;
module_param(init, int, 0444);
MODULE_PARM_DESC(init, \
@@ -569,6 +568,7 @@
{
scsi_changer *ch = container_of(ref, scsi_changer, ref);
+ ch->device = NULL;
kfree(ch->dt);
kfree(ch);
}
@@ -590,20 +590,22 @@
scsi_changer *ch;
int minor = iminor(inode);
- mutex_lock(&ch_mutex);
spin_lock(&ch_index_lock);
ch = idr_find(&ch_index_idr, minor);
- if (NULL == ch || scsi_device_get(ch->device)) {
+ if (ch == NULL || !kref_get_unless_zero(&ch->ref)) {
spin_unlock(&ch_index_lock);
- mutex_unlock(&ch_mutex);
return -ENXIO;
}
- kref_get(&ch->ref);
spin_unlock(&ch_index_lock);
-
+ if (scsi_device_get(ch->device)) {
+ kref_put(&ch->ref, ch_destroy);
+ return -ENXIO;
+ }
+ /* Synchronize with ch_probe() */
+ mutex_lock(&ch->lock);
file->private_data = ch;
- mutex_unlock(&ch_mutex);
+ mutex_unlock(&ch->lock);
return 0;
}
@@ -872,6 +874,10 @@
unsigned int cmd, unsigned long arg)
{
scsi_changer *ch = file->private_data;
+ int retval = scsi_ioctl_block_when_processing_errors(ch->device, cmd,
+ file->f_flags & O_NDELAY);
+ if (retval)
+ return retval;
switch (cmd) {
case CHIOGPARAMS:
@@ -883,7 +889,7 @@
case CHIOINITELEM:
case CHIOSVOLTAG:
/* compatible */
- return ch_ioctl(file, cmd, arg);
+ return ch_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
case CHIOGSTATUS32:
{
struct changer_element_status32 ces32;
@@ -898,8 +904,7 @@
return ch_gstatus(ch, ces32.ces_type, data);
}
default:
- // return scsi_ioctl_compat(ch->device, cmd, (void*)arg);
- return -ENOIOCTLCMD;
+ return scsi_compat_ioctl(ch->device, cmd, compat_ptr(arg));
}
}
@@ -935,7 +940,16 @@
ch->minor = ret;
sprintf(ch->name,"ch%d",ch->minor);
+ ret = scsi_device_get(sd);
+ if (ret) {
+ sdev_printk(KERN_WARNING, sd, "ch%d: failed to get device\n",
+ ch->minor);
+ goto remove_idr;
+ }
+ mutex_init(&ch->lock);
+ kref_init(&ch->ref);
+ ch->device = sd;
class_dev = device_create(ch_sysfs_class, dev,
MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch,
"s%s", ch->name);
@@ -943,24 +957,27 @@
sdev_printk(KERN_WARNING, sd, "ch%d: device_create failed\n",
ch->minor);
ret = PTR_ERR(class_dev);
- goto remove_idr;
+ goto put_device;
}
- mutex_init(&ch->lock);
- kref_init(&ch->ref);
- ch->device = sd;
+ mutex_lock(&ch->lock);
ret = ch_readconfig(ch);
- if (ret)
+ if (ret) {
+ mutex_unlock(&ch->lock);
goto destroy_dev;
+ }
if (init)
ch_init_elem(ch);
+ mutex_unlock(&ch->lock);
dev_set_drvdata(dev, ch);
sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name);
return 0;
destroy_dev:
device_destroy(ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR, ch->minor));
+put_device:
+ scsi_device_put(sd);
remove_idr:
idr_remove(&ch_index_idr, ch->minor);
free_ch:
@@ -974,9 +991,11 @@
spin_lock(&ch_index_lock);
idr_remove(&ch_index_idr, ch->minor);
+ dev_set_drvdata(dev, NULL);
spin_unlock(&ch_index_lock);
device_destroy(ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
+ scsi_device_put(ch->device);
kref_put(&ch->ref, ch_destroy);
return 0;
}
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index d4c2a2e..84d73f5 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -404,7 +404,7 @@
"DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
"DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY", "DID_REQUEUE",
"DID_TRANSPORT_DISRUPTED", "DID_TRANSPORT_FAILFAST", "DID_TARGET_FAILURE",
-"DID_NEXUS_FAILURE" };
+"DID_NEXUS_FAILURE", "DID_ALLOC_FAILURE", "DID_MEDIUM_ERROR" };
static const char * const driverbyte_table[]={
"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR",
diff --git a/drivers/scsi/csiostor/csio_hw.c b/drivers/scsi/csiostor/csio_hw.c
index 1b6f935..e43c541 100644
--- a/drivers/scsi/csiostor/csio_hw.c
+++ b/drivers/scsi/csiostor/csio_hw.c
@@ -306,7 +306,7 @@
uint8_t *vpd, csum;
const struct t4_vpd_hdr *v;
/* To get around compilation warning from strstrip */
- char *s;
+ char __always_unused *s;
if (csio_is_valid_vpd(hw))
return 0;
@@ -793,10 +793,10 @@
goto found;
}
- /* Decode Flash part size. The code below looks repetative with
+ /* Decode Flash part size. The code below looks repetitive with
* common encodings, but that's not guaranteed in the JEDEC
- * specification for the Read JADEC ID command. The only thing that
- * we're guaranteed by the JADEC specification is where the
+ * specification for the Read JEDEC ID command. The only thing that
+ * we're guaranteed by the JEDEC specification is where the
* Manufacturer ID is in the returned result. After that each
* Manufacturer ~could~ encode things completely differently.
* Note, all Flash parts must have 64KB sectors.
@@ -983,8 +983,8 @@
waiting -= 50;
/*
- * If neither Error nor Initialialized are indicated
- * by the firmware keep waiting till we exaust our
+ * If neither Error nor Initialized are indicated
+ * by the firmware keep waiting till we exhaust our
* timeout ... and then retry if we haven't exhausted
* our retries ...
*/
@@ -1738,7 +1738,7 @@
* Convert Common Code Forward Error Control settings into the
* Firmware's API. If the current Requested FEC has "Automatic"
* (IEEE 802.3) specified, then we use whatever the Firmware
- * sent us as part of it's IEEE 802.3-based interpratation of
+ * sent us as part of it's IEEE 802.3-based interpretation of
* the Transceiver Module EPROM FEC parameters. Otherwise we
* use whatever is in the current Requested FEC settings.
*/
@@ -2834,7 +2834,7 @@
}
/*
- * csio_hws_initializing - Initialiazing state
+ * csio_hws_initializing - Initializing state
* @hw - HW module
* @evt - Event
*
@@ -2939,7 +2939,7 @@
case CSIO_HWE_FW_DLOAD:
csio_set_state(&hw->sm, csio_hws_resetting);
/* Download firmware */
- /* Fall through */
+ fallthrough;
case CSIO_HWE_HBA_RESET:
csio_set_state(&hw->sm, csio_hws_resetting);
@@ -3049,7 +3049,7 @@
if (!csio_is_hw_master(hw))
break;
/*
- * The BYE should have alerady been issued, so we cant
+ * The BYE should have already been issued, so we can't
* use the mailbox interface. Hence we use the PL_RST
* register directly.
*/
@@ -3104,7 +3104,7 @@
*
* A table driven interrupt handler that applies a set of masks to an
* interrupt status word and performs the corresponding actions if the
- * interrupts described by the mask have occured. The actions include
+ * interrupts described by the mask have occurred. The actions include
* optionally emitting a warning or alert message. The table is terminated
* by an entry specifying mask 0. Returns the number of fatal interrupt
* conditions.
@@ -4219,7 +4219,7 @@
* @hw: Pointer to HW module.
*
* It is assumed that the initialization is a synchronous operation.
- * So when we return afer posting the event, the HW SM should be in
+ * So when we return after posting the event, the HW SM should be in
* the ready state, if there were no errors during init.
*/
int
diff --git a/drivers/scsi/csiostor/csio_hw_t5.c b/drivers/scsi/csiostor/csio_hw_t5.c
index f24def6..1df8891 100644
--- a/drivers/scsi/csiostor/csio_hw_t5.c
+++ b/drivers/scsi/csiostor/csio_hw_t5.c
@@ -148,12 +148,11 @@
{
int i;
uint32_t mc_bist_cmd_reg, mc_bist_cmd_addr_reg, mc_bist_cmd_len_reg;
- uint32_t mc_bist_status_rdata_reg, mc_bist_data_pattern_reg;
+ uint32_t mc_bist_data_pattern_reg;
mc_bist_cmd_reg = MC_REG(MC_P_BIST_CMD_A, idx);
mc_bist_cmd_addr_reg = MC_REG(MC_P_BIST_CMD_ADDR_A, idx);
mc_bist_cmd_len_reg = MC_REG(MC_P_BIST_CMD_LEN_A, idx);
- mc_bist_status_rdata_reg = MC_REG(MC_P_BIST_STATUS_RDATA_A, idx);
mc_bist_data_pattern_reg = MC_REG(MC_P_BIST_DATA_PATTERN_A, idx);
if (csio_rd_reg32(hw, mc_bist_cmd_reg) & START_BIST_F)
@@ -196,7 +195,7 @@
{
int i;
uint32_t edc_bist_cmd_reg, edc_bist_cmd_addr_reg, edc_bist_cmd_len_reg;
- uint32_t edc_bist_cmd_data_pattern, edc_bist_status_rdata_reg;
+ uint32_t edc_bist_cmd_data_pattern;
/*
* These macro are missing in t4_regs.h file.
@@ -208,7 +207,6 @@
edc_bist_cmd_addr_reg = EDC_REG_T5(EDC_H_BIST_CMD_ADDR_A, idx);
edc_bist_cmd_len_reg = EDC_REG_T5(EDC_H_BIST_CMD_LEN_A, idx);
edc_bist_cmd_data_pattern = EDC_REG_T5(EDC_H_BIST_DATA_PATTERN_A, idx);
- edc_bist_status_rdata_reg = EDC_REG_T5(EDC_H_BIST_STATUS_RDATA_A, idx);
#undef EDC_REG_T5
#undef EDC_STRIDE_T5
diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c
index a6dd704..ccbded3 100644
--- a/drivers/scsi/csiostor/csio_init.c
+++ b/drivers/scsi/csiostor/csio_init.c
@@ -154,13 +154,10 @@
/*
* csio_dfs_destroy - Destroys per-hw debugfs.
*/
-static int
+static void
csio_dfs_destroy(struct csio_hw *hw)
{
- if (hw->debugfs_root)
- debugfs_remove_recursive(hw->debugfs_root);
-
- return 0;
+ debugfs_remove_recursive(hw->debugfs_root);
}
/*
@@ -532,7 +529,7 @@
goto err_free_hw;
/* Get the start address of registers from BAR 0 */
- hw->regstart = ioremap_nocache(pci_resource_start(pdev, 0),
+ hw->regstart = ioremap(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
if (!hw->regstart) {
csio_err(hw, "Could not map BAR 0, regstart = %p\n",
@@ -585,7 +582,7 @@
* @hw: The HW module.
* @dev: The device associated with this invocation.
* @probe: Called from probe context or not?
- * @os_pln: Parent lnode if any.
+ * @pln: Parent lnode if any.
*
* Allocates lnode structure via scsi_host_alloc, initializes
* shost, initializes lnode module and registers with SCSI ML
@@ -1257,3 +1254,4 @@
MODULE_VERSION(CSIO_DRV_VERSION);
MODULE_FIRMWARE(FW_FNAME_T5);
MODULE_FIRMWARE(FW_FNAME_T6);
+MODULE_SOFTDEP("pre: cxgb4");
diff --git a/drivers/scsi/csiostor/csio_lnode.c b/drivers/scsi/csiostor/csio_lnode.c
index 23cbe4c..d5ac938 100644
--- a/drivers/scsi/csiostor/csio_lnode.c
+++ b/drivers/scsi/csiostor/csio_lnode.c
@@ -619,7 +619,7 @@
struct fc_els_csp *csp;
struct fc_els_cssp *clsp;
enum fw_retval retval;
- __be32 nport_id;
+ __be32 nport_id = 0;
retval = FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16));
if (retval != FW_SUCCESS) {
@@ -1187,7 +1187,6 @@
break;
case CSIO_LNE_LINK_DOWN:
- /* Fall through */
case CSIO_LNE_DOWN_LINK:
csio_set_state(&ln->sm, csio_lns_uninit);
if (csio_is_phys_ln(ln)) {
@@ -1992,7 +1991,7 @@
csio_ln_init(struct csio_lnode *ln)
{
int rv = -EINVAL;
- struct csio_lnode *rln, *pln;
+ struct csio_lnode *pln;
struct csio_hw *hw = csio_lnode_to_hw(ln);
csio_init_state(&ln->sm, csio_lns_uninit);
@@ -2022,7 +2021,6 @@
* THe rest is common for non-root physical and NPIV lnodes.
* Just get references to all other modules
*/
- rln = csio_root_lnode(ln);
if (csio_is_npiv_ln(ln)) {
/* NPIV */
@@ -2069,10 +2067,9 @@
ln->fcfinfo = NULL;
}
-/**
+/*
* csio_lnode_init - Initialize the members of an lnode.
* @ln: lnode
- *
*/
int
csio_lnode_init(struct csio_lnode *ln, struct csio_hw *hw,
diff --git a/drivers/scsi/csiostor/csio_mb.c b/drivers/scsi/csiostor/csio_mb.c
index 6f13673..94810b1 100644
--- a/drivers/scsi/csiostor/csio_mb.c
+++ b/drivers/scsi/csiostor/csio_mb.c
@@ -1210,7 +1210,7 @@
!csio_is_hw_intr_enabled(hw)) {
csio_err(hw, "Cannot issue mailbox in interrupt mode 0x%x\n",
*((uint8_t *)mbp->mb));
- goto error_out;
+ goto error_out;
}
if (mbm->mcurrent != NULL) {
diff --git a/drivers/scsi/csiostor/csio_rnode.c b/drivers/scsi/csiostor/csio_rnode.c
index e9c3b04..713e13a 100644
--- a/drivers/scsi/csiostor/csio_rnode.c
+++ b/drivers/scsi/csiostor/csio_rnode.c
@@ -862,7 +862,7 @@
/**
* csio_rnode_fwevt_handler - Event handler for firmware rnode events.
* @rn: rnode
- *
+ * @fwevt: firmware event to handle
*/
void
csio_rnode_fwevt_handler(struct csio_rnode *rn, uint8_t fwevt)
diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c
index 00cf335..55e74da 100644
--- a/drivers/scsi/csiostor/csio_scsi.c
+++ b/drivers/scsi/csiostor/csio_scsi.c
@@ -933,14 +933,14 @@
* abort for that I/O by the FW crossed each other.
* The FW returned FW_EINVAL. The original I/O would have
* returned with FW_SUCCESS or any other SCSI error.
- * 3. The FW couldnt sent the abort out on the wire, as there
+ * 3. The FW couldn't sent the abort out on the wire, as there
* was an I-T nexus loss (link down, remote device logged
* out etc). FW sent back an appropriate IT nexus loss status
* for the abort.
* 4. FW sent an abort, but abort timed out (remote device
* didnt respond). FW replied back with
* FW_SCSI_ABORT_TIMEDOUT.
- * 5. FW couldnt genuinely abort the request for some reason,
+ * 5. FW couldn't genuinely abort the request for some reason,
* and sent us an error.
*
* The first 3 scenarios are treated as succesful abort
@@ -1859,7 +1859,7 @@
spin_unlock_irqrestore(&hw->lock, flags);
if (retval != 0) {
- csio_err(hw, "ioreq: %p couldnt be started, status:%d\n",
+ csio_err(hw, "ioreq: %p couldn't be started, status:%d\n",
ioreq, retval);
CSIO_INC_STATS(scsim, n_busy_error);
goto err_put_req;
diff --git a/drivers/scsi/csiostor/csio_wr.c b/drivers/scsi/csiostor/csio_wr.c
index 0ca6951..9010cb6 100644
--- a/drivers/scsi/csiostor/csio_wr.c
+++ b/drivers/scsi/csiostor/csio_wr.c
@@ -808,7 +808,7 @@
csio_q_eqid(hw, i) = CSIO_MAX_QID;
}
- /* fall through */
+ fallthrough;
case CSIO_INGRESS:
if (csio_q_iqid(hw, i) != CSIO_MAX_QID) {
csio_wr_cleanup_iq_ftr(hw, i);
diff --git a/drivers/scsi/cxgbi/cxgb3i/Kconfig b/drivers/scsi/cxgbi/cxgb3i/Kconfig
index 3e4b644..e20e6f3 100644
--- a/drivers/scsi/cxgbi/cxgb3i/Kconfig
+++ b/drivers/scsi/cxgbi/cxgb3i/Kconfig
@@ -8,5 +8,5 @@
select CHELSIO_T3
select CHELSIO_LIB
select SCSI_ISCSI_ATTRS
- ---help---
+ help
This driver supports iSCSI offload for the Chelsio T3 devices.
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
index ec7d01f..37d9935 100644
--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -361,7 +361,7 @@
/* len includes the length of any HW ULP additions */
req->len = htonl(len);
/* V_TX_ULP_SUBMODE sets both the mode and submode */
- req->flags = htonl(V_TX_ULP_SUBMODE(cxgbi_skcb_ulp_mode(skb)) |
+ req->flags = htonl(V_TX_ULP_SUBMODE(cxgbi_skcb_tx_ulp_mode(skb)) |
V_TX_SHOVE((skb_peek(&csk->write_queue) ? 0 : 1)));
req->sndseq = htonl(csk->snd_nxt);
req->param = htonl(V_TX_PORT(l2t->smt_idx));
@@ -375,10 +375,8 @@
}
}
-/**
+/*
* push_tx_frames -- start transmit
- * @c3cn: the offloaded connection
- * @req_completion: request wr_ack or not
*
* Prepends TX_DATA_WR or CPL_CLOSE_CON_REQ headers to buffers waiting in a
* connection's send queue and sends them on to T3. Must be called with the
@@ -442,7 +440,7 @@
req_completion = 1;
csk->wr_una_cred = 0;
}
- len += cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb));
+ len += cxgbi_ulp_extra_len(cxgbi_skcb_tx_ulp_mode(skb));
make_tx_data_wr(csk, skb, len, req_completion);
csk->snd_nxt += len;
cxgbi_skcb_clear_flag(skb, SKCBF_TX_NEED_HDR);
@@ -645,7 +643,7 @@
int *need_rst)
{
switch (abort_reason) {
- case CPL_ERR_BAD_SYN: /* fall through */
+ case CPL_ERR_BAD_SYN:
case CPL_ERR_CONN_RESET:
return csk->state > CTP_ESTABLISHED ? -EPIPE : -ECONNRESET;
case CPL_ERR_XMIT_TIMEDOUT:
@@ -886,11 +884,6 @@
return -ENOMEM;
}
-/**
- * release_offload_resources - release offload resource
- * @c3cn: the offloaded iscsi tcp connection.
- * Release resources held by an offload connection (TID, L2T entry, etc.)
- */
static void l2t_put(struct cxgbi_sock *csk)
{
struct t3cdev *t3dev = (struct t3cdev *)csk->cdev->lldev;
@@ -902,6 +895,10 @@
}
}
+/*
+ * release_offload_resources - release offload resource
+ * Release resources held by an offload connection (TID, L2T entry, etc.)
+ */
static void release_offload_resources(struct cxgbi_sock *csk)
{
struct t3cdev *t3dev = (struct t3cdev *)csk->cdev->lldev;
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kconfig b/drivers/scsi/cxgbi/cxgb4i/Kconfig
index d1bdd75..8b0deec 100644
--- a/drivers/scsi/cxgbi/cxgb4i/Kconfig
+++ b/drivers/scsi/cxgbi/cxgb4i/Kconfig
@@ -9,5 +9,5 @@
select CHELSIO_T4
select CHELSIO_LIB
select SCSI_ISCSI_ATTRS
- ---help---
+ help
This driver supports iSCSI offload for the Chelsio T4 devices.
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index da50e87..2c34915 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -197,7 +197,10 @@
if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR)))
len += sizeof(struct fw_ofld_tx_data_wr);
- return len <= MAX_IMM_TX_PKT_LEN;
+ if (likely(cxgbi_skcb_test_flag((struct sk_buff *)skb, SKCBF_TX_ISO)))
+ len += sizeof(struct cpl_tx_data_iso);
+
+ return (len <= MAX_IMM_OFLD_TX_DATA_WR_LEN);
}
static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb,
@@ -641,7 +644,10 @@
flowc->mnemval[8].mnemonic = 0;
flowc->mnemval[8].val = 0;
flowc->mnemval[8].mnemonic = FW_FLOWC_MNEM_TXDATAPLEN_MAX;
- flowc->mnemval[8].val = 16384;
+ if (csk->cdev->skb_iso_txhdr)
+ flowc->mnemval[8].val = cpu_to_be32(CXGBI_MAX_ISO_DATA_IN_SKB);
+ else
+ flowc->mnemval[8].val = cpu_to_be32(16128);
#ifdef CONFIG_CHELSIO_T4_DCB
flowc->mnemval[9].mnemonic = FW_FLOWC_MNEM_DCBPRIO;
if (vlan == CPL_L2T_VLAN_NONE) {
@@ -667,38 +673,86 @@
return flowclen16;
}
-static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb,
- int dlen, int len, u32 credits, int compl)
+static void
+cxgb4i_make_tx_iso_cpl(struct sk_buff *skb, struct cpl_tx_data_iso *cpl)
{
+ struct cxgbi_iso_info *info = (struct cxgbi_iso_info *)skb->head;
+ u32 imm_en = !!(info->flags & CXGBI_ISO_INFO_IMM_ENABLE);
+ u32 fslice = !!(info->flags & CXGBI_ISO_INFO_FSLICE);
+ u32 lslice = !!(info->flags & CXGBI_ISO_INFO_LSLICE);
+ u32 pdu_type = (info->op == ISCSI_OP_SCSI_CMD) ? 0 : 1;
+ u32 submode = cxgbi_skcb_tx_ulp_mode(skb) & 0x3;
+
+ cpl->op_to_scsi = cpu_to_be32(CPL_TX_DATA_ISO_OP_V(CPL_TX_DATA_ISO) |
+ CPL_TX_DATA_ISO_FIRST_V(fslice) |
+ CPL_TX_DATA_ISO_LAST_V(lslice) |
+ CPL_TX_DATA_ISO_CPLHDRLEN_V(0) |
+ CPL_TX_DATA_ISO_HDRCRC_V(submode & 1) |
+ CPL_TX_DATA_ISO_PLDCRC_V(((submode >> 1) & 1)) |
+ CPL_TX_DATA_ISO_IMMEDIATE_V(imm_en) |
+ CPL_TX_DATA_ISO_SCSI_V(pdu_type));
+
+ cpl->ahs_len = info->ahs;
+ cpl->mpdu = cpu_to_be16(DIV_ROUND_UP(info->mpdu, 4));
+ cpl->burst_size = cpu_to_be32(info->burst_size);
+ cpl->len = cpu_to_be32(info->len);
+ cpl->reserved2_seglen_offset =
+ cpu_to_be32(CPL_TX_DATA_ISO_SEGLEN_OFFSET_V(info->segment_offset));
+ cpl->datasn_offset = cpu_to_be32(info->datasn_offset);
+ cpl->buffer_offset = cpu_to_be32(info->buffer_offset);
+ cpl->reserved3 = cpu_to_be32(0);
+ log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+ "iso: flags 0x%x, op %u, ahs %u, num_pdu %u, mpdu %u, "
+ "burst_size %u, iso_len %u\n",
+ info->flags, info->op, info->ahs, info->num_pdu,
+ info->mpdu, info->burst_size << 2, info->len);
+}
+
+static void
+cxgb4i_make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb, int dlen,
+ int len, u32 credits, int compl)
+{
+ struct cxgbi_device *cdev = csk->cdev;
+ struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
struct fw_ofld_tx_data_wr *req;
- unsigned int submode = cxgbi_skcb_ulp_mode(skb) & 3;
- unsigned int wr_ulp_mode = 0, val;
- bool imm = is_ofld_imm(skb);
+ struct cpl_tx_data_iso *cpl;
+ u32 submode = cxgbi_skcb_tx_ulp_mode(skb) & 0x3;
+ u32 wr_ulp_mode = 0;
+ u32 hdr_size = sizeof(*req);
+ u32 opcode = FW_OFLD_TX_DATA_WR;
+ u32 immlen = 0;
+ u32 force = is_t5(lldi->adapter_type) ? TX_FORCE_V(!submode) :
+ T6_TX_FORCE_F;
- req = __skb_push(skb, sizeof(*req));
-
- if (imm) {
- req->op_to_immdlen = htonl(FW_WR_OP_V(FW_OFLD_TX_DATA_WR) |
- FW_WR_COMPL_F |
- FW_WR_IMMDLEN_V(dlen));
- req->flowid_len16 = htonl(FW_WR_FLOWID_V(csk->tid) |
- FW_WR_LEN16_V(credits));
- } else {
- req->op_to_immdlen =
- cpu_to_be32(FW_WR_OP_V(FW_OFLD_TX_DATA_WR) |
- FW_WR_COMPL_F |
- FW_WR_IMMDLEN_V(0));
- req->flowid_len16 =
- cpu_to_be32(FW_WR_FLOWID_V(csk->tid) |
- FW_WR_LEN16_V(credits));
+ if (cxgbi_skcb_test_flag(skb, SKCBF_TX_ISO)) {
+ hdr_size += sizeof(struct cpl_tx_data_iso);
+ opcode = FW_ISCSI_TX_DATA_WR;
+ immlen += sizeof(struct cpl_tx_data_iso);
+ submode |= 8;
}
+
+ if (is_ofld_imm(skb))
+ immlen += dlen;
+
+ req = (struct fw_ofld_tx_data_wr *)__skb_push(skb, hdr_size);
+ req->op_to_immdlen = cpu_to_be32(FW_WR_OP_V(opcode) |
+ FW_WR_COMPL_V(compl) |
+ FW_WR_IMMDLEN_V(immlen));
+ req->flowid_len16 = cpu_to_be32(FW_WR_FLOWID_V(csk->tid) |
+ FW_WR_LEN16_V(credits));
+ req->plen = cpu_to_be32(len);
+ cpl = (struct cpl_tx_data_iso *)(req + 1);
+
+ if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_ISO)))
+ cxgb4i_make_tx_iso_cpl(skb, cpl);
+
if (submode)
wr_ulp_mode = FW_OFLD_TX_DATA_WR_ULPMODE_V(ULP2_MODE_ISCSI) |
- FW_OFLD_TX_DATA_WR_ULPSUBMODE_V(submode);
- val = skb_peek(&csk->write_queue) ? 0 : 1;
- req->tunnel_to_proxy = htonl(wr_ulp_mode |
- FW_OFLD_TX_DATA_WR_SHOVE_V(val));
- req->plen = htonl(len);
+ FW_OFLD_TX_DATA_WR_ULPSUBMODE_V(submode);
+
+ req->tunnel_to_proxy = cpu_to_be32(wr_ulp_mode | force |
+ FW_OFLD_TX_DATA_WR_SHOVE_V(1U));
+
if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT))
cxgbi_sock_set_flag(csk, CTPF_TX_DATA_SENT);
}
@@ -716,30 +770,34 @@
if (unlikely(csk->state < CTP_ESTABLISHED ||
csk->state == CTP_CLOSE_WAIT_1 || csk->state >= CTP_ABORTING)) {
log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK |
- 1 << CXGBI_DBG_PDU_TX,
- "csk 0x%p,%u,0x%lx,%u, in closing state.\n",
- csk, csk->state, csk->flags, csk->tid);
+ 1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p,%u,0x%lx,%u, in closing state.\n",
+ csk, csk->state, csk->flags, csk->tid);
return 0;
}
- while (csk->wr_cred && (skb = skb_peek(&csk->write_queue)) != NULL) {
- int dlen = skb->len;
- int len = skb->len;
- unsigned int credits_needed;
- int flowclen16 = 0;
+ while (csk->wr_cred && ((skb = skb_peek(&csk->write_queue)) != NULL)) {
+ struct cxgbi_iso_info *iso_cpl;
+ u32 dlen = skb->len;
+ u32 len = skb->len;
+ u32 iso_cpl_len = 0;
+ u32 flowclen16 = 0;
+ u32 credits_needed;
+ u32 num_pdu = 1, hdr_len;
- skb_reset_transport_header(skb);
+ if (cxgbi_skcb_test_flag(skb, SKCBF_TX_ISO))
+ iso_cpl_len = sizeof(struct cpl_tx_data_iso);
+
if (is_ofld_imm(skb))
- credits_needed = DIV_ROUND_UP(dlen, 16);
+ credits_needed = DIV_ROUND_UP(dlen + iso_cpl_len, 16);
else
- credits_needed = DIV_ROUND_UP(
- 8 * calc_tx_flits_ofld(skb),
- 16);
+ credits_needed =
+ DIV_ROUND_UP((8 * calc_tx_flits_ofld(skb)) +
+ iso_cpl_len, 16);
if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR)))
- credits_needed += DIV_ROUND_UP(
- sizeof(struct fw_ofld_tx_data_wr),
- 16);
+ credits_needed +=
+ DIV_ROUND_UP(sizeof(struct fw_ofld_tx_data_wr), 16);
/*
* Assumes the initial credits is large enough to support
@@ -754,14 +812,19 @@
if (csk->wr_cred < credits_needed) {
log_debug(1 << CXGBI_DBG_PDU_TX,
- "csk 0x%p, skb %u/%u, wr %d < %u.\n",
- csk, skb->len, skb->data_len,
- credits_needed, csk->wr_cred);
+ "csk 0x%p, skb %u/%u, wr %d < %u.\n",
+ csk, skb->len, skb->data_len,
+ credits_needed, csk->wr_cred);
+
+ csk->no_tx_credits++;
break;
}
+
+ csk->no_tx_credits = 0;
+
__skb_unlink(skb, &csk->write_queue);
set_wr_txq(skb, CPL_PRIORITY_DATA, csk->port_id);
- skb->csum = credits_needed + flowclen16;
+ skb->csum = (__force __wsum)(credits_needed + flowclen16);
csk->wr_cred -= credits_needed;
csk->wr_una_cred += credits_needed;
cxgbi_sock_enqueue_wr(csk, skb);
@@ -771,25 +834,42 @@
csk, skb->len, skb->data_len, credits_needed,
csk->wr_cred, csk->wr_una_cred);
+ if (!req_completion &&
+ ((csk->wr_una_cred >= (csk->wr_max_cred / 2)) ||
+ after(csk->write_seq, (csk->snd_una + csk->snd_win / 2))))
+ req_completion = 1;
+
if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_NEED_HDR))) {
- len += cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb));
- make_tx_data_wr(csk, skb, dlen, len, credits_needed,
- req_completion);
+ u32 ulp_mode = cxgbi_skcb_tx_ulp_mode(skb);
+
+ if (cxgbi_skcb_test_flag(skb, SKCBF_TX_ISO)) {
+ iso_cpl = (struct cxgbi_iso_info *)skb->head;
+ num_pdu = iso_cpl->num_pdu;
+ hdr_len = cxgbi_skcb_tx_iscsi_hdrlen(skb);
+ len += (cxgbi_ulp_extra_len(ulp_mode) * num_pdu) +
+ (hdr_len * (num_pdu - 1));
+ } else {
+ len += cxgbi_ulp_extra_len(ulp_mode);
+ }
+
+ cxgb4i_make_tx_data_wr(csk, skb, dlen, len,
+ credits_needed, req_completion);
csk->snd_nxt += len;
cxgbi_skcb_clear_flag(skb, SKCBF_TX_NEED_HDR);
} else if (cxgbi_skcb_test_flag(skb, SKCBF_TX_FLAG_COMPL) &&
(csk->wr_una_cred >= (csk->wr_max_cred / 2))) {
struct cpl_close_con_req *req =
(struct cpl_close_con_req *)skb->data;
- req->wr.wr_hi |= htonl(FW_WR_COMPL_F);
+
+ req->wr.wr_hi |= cpu_to_be32(FW_WR_COMPL_F);
}
+
total_size += skb->truesize;
t4_set_arp_err_handler(skb, csk, arp_failure_skb_discard);
log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_TX,
- "csk 0x%p,%u,0x%lx,%u, skb 0x%p, %u.\n",
- csk, csk->state, csk->flags, csk->tid, skb, len);
-
+ "csk 0x%p,%u,0x%lx,%u, skb 0x%p, %u.\n",
+ csk, csk->state, csk->flags, csk->tid, skb, len);
cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t);
}
return total_size;
@@ -1053,7 +1133,7 @@
int *need_rst)
{
switch (abort_reason) {
- case CPL_ERR_BAD_SYN: /* fall through */
+ case CPL_ERR_BAD_SYN:
case CPL_ERR_CONN_RESET:
return csk->state > CTP_ESTABLISHED ?
-EPIPE : -ECONNRESET;
@@ -1127,10 +1207,9 @@
if (!csk)
goto rel_skb;
- if (csk)
- pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u, status %u.\n",
- (&csk->saddr), (&csk->daddr), csk,
- csk->state, csk->flags, csk->tid, rpl->status);
+ pr_info_ipaddr("csk 0x%p,%u,0x%lx,%u, status %u.\n",
+ (&csk->saddr), (&csk->daddr), csk,
+ csk->state, csk->flags, csk->tid, rpl->status);
if (rpl->status == CPL_ERR_ABORT_FAILED)
goto rel_skb;
@@ -2073,7 +2152,6 @@
struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev);
struct net_device *ndev = cdev->ports[0];
struct cxgbi_tag_format tformat;
- unsigned int ppmax;
int i, err;
if (!lldi->vr->iscsi.size) {
@@ -2082,7 +2160,6 @@
}
cdev->flags |= CXGBI_FLAG_USE_PPOD_OFLDQ;
- ppmax = lldi->vr->iscsi.size >> PPOD_SIZE_SHIFT;
memset(&tformat, 0, sizeof(struct cxgbi_tag_format));
for (i = 0; i < 4; i++)
@@ -2114,10 +2191,30 @@
return 0;
}
+static bool is_memfree(struct adapter *adap)
+{
+ u32 io;
+
+ io = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A);
+ if (is_t5(adap->params.chip)) {
+ if ((io & EXT_MEM0_ENABLE_F) || (io & EXT_MEM1_ENABLE_F))
+ return false;
+ } else if (io & EXT_MEM_ENABLE_F) {
+ return false;
+ }
+
+ return true;
+}
+
static void *t4_uld_add(const struct cxgb4_lld_info *lldi)
{
struct cxgbi_device *cdev;
struct port_info *pi;
+ struct net_device *ndev;
+ struct adapter *adap;
+ struct tid_info *t;
+ u32 max_cmds = CXGB4I_SCSI_HOST_QDEPTH;
+ u32 max_conn = CXGBI_MAX_CONN;
int i, rc;
cdev = cxgbi_device_register(sizeof(*lldi), lldi->nports);
@@ -2157,14 +2254,40 @@
pr_info("t4 0x%p ddp init failed %d.\n", cdev, rc);
goto err_out;
}
+
+ ndev = cdev->ports[0];
+ adap = netdev2adap(ndev);
+ if (adap) {
+ t = &adap->tids;
+ if (t->ntids <= CXGBI_MAX_CONN)
+ max_conn = t->ntids;
+
+ if (is_memfree(adap)) {
+ cdev->flags |= CXGBI_FLAG_DEV_ISO_OFF;
+ max_cmds = CXGB4I_SCSI_HOST_QDEPTH >> 2;
+
+ pr_info("%s: 0x%p, tid %u, SO adapter.\n",
+ ndev->name, cdev, t->ntids);
+ }
+ } else {
+ pr_info("%s, 0x%p, NO adapter struct.\n", ndev->name, cdev);
+ }
+
+ /* ISO is enabled in T5/T6 firmware version >= 1.13.43.0 */
+ if (!is_t4(lldi->adapter_type) &&
+ (lldi->fw_vers >= 0x10d2b00) &&
+ !(cdev->flags & CXGBI_FLAG_DEV_ISO_OFF))
+ cdev->skb_iso_txhdr = sizeof(struct cpl_tx_data_iso);
+
rc = cxgb4i_ofld_init(cdev);
if (rc) {
pr_info("t4 0x%p ofld init failed.\n", cdev);
goto err_out;
}
- rc = cxgbi_hbas_add(cdev, CXGB4I_MAX_LUN, CXGBI_MAX_CONN,
- &cxgb4i_host_template, cxgb4i_stt);
+ cxgb4i_host_template.can_queue = max_cmds;
+ rc = cxgbi_hbas_add(cdev, CXGB4I_MAX_LUN, max_conn,
+ &cxgb4i_host_template, cxgb4i_stt);
if (rc)
goto err_out;
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index 40d93fa..ecb134b 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -77,9 +77,9 @@
{
struct cxgbi_ports_map *pmap = &cdev->pmap;
- pmap->port_csk = cxgbi_alloc_big_mem(max_conn *
- sizeof(struct cxgbi_sock *),
- GFP_KERNEL);
+ pmap->port_csk = kvzalloc(array_size(max_conn,
+ sizeof(struct cxgbi_sock *)),
+ GFP_KERNEL | __GFP_NOWARN);
if (!pmap->port_csk) {
pr_warn("cdev 0x%p, portmap OOM %u.\n", cdev, max_conn);
return -ENOMEM;
@@ -124,7 +124,7 @@
if (cdev->cdev2ppm)
cxgbi_ppm_release(cdev->cdev2ppm(cdev));
if (cdev->pmap.max_connect)
- cxgbi_free_big_mem(cdev->pmap.port_csk);
+ kvfree(cdev->pmap.port_csk);
kfree(cdev);
}
@@ -359,13 +359,15 @@
shost->max_lun = max_lun;
shost->max_id = max_conns - 1;
shost->max_channel = 0;
- shost->max_cmd_len = 16;
+ shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE;
chba = iscsi_host_priv(shost);
chba->cdev = cdev;
chba->ndev = cdev->ports[i];
chba->shost = shost;
+ shost->can_queue = sht->can_queue - ISCSI_MGMT_CMDS_MAX;
+
log_debug(1 << CXGBI_DBG_DEV,
"cdev 0x%p, p#%d %s: chba 0x%p.\n",
cdev, i, cdev->ports[i]->name, chba);
@@ -1136,82 +1138,6 @@
}
EXPORT_SYMBOL_GPL(cxgbi_sock_check_wr_invariants);
-static int cxgbi_sock_send_pdus(struct cxgbi_sock *csk, struct sk_buff *skb)
-{
- struct cxgbi_device *cdev = csk->cdev;
- struct sk_buff *next;
- int err, copied = 0;
-
- spin_lock_bh(&csk->lock);
-
- if (csk->state != CTP_ESTABLISHED) {
- log_debug(1 << CXGBI_DBG_PDU_TX,
- "csk 0x%p,%u,0x%lx,%u, EAGAIN.\n",
- csk, csk->state, csk->flags, csk->tid);
- err = -EAGAIN;
- goto out_err;
- }
-
- if (csk->err) {
- log_debug(1 << CXGBI_DBG_PDU_TX,
- "csk 0x%p,%u,0x%lx,%u, EPIPE %d.\n",
- csk, csk->state, csk->flags, csk->tid, csk->err);
- err = -EPIPE;
- goto out_err;
- }
-
- if (csk->write_seq - csk->snd_una >= csk->snd_win) {
- log_debug(1 << CXGBI_DBG_PDU_TX,
- "csk 0x%p,%u,0x%lx,%u, FULL %u-%u >= %u.\n",
- csk, csk->state, csk->flags, csk->tid, csk->write_seq,
- csk->snd_una, csk->snd_win);
- err = -ENOBUFS;
- goto out_err;
- }
-
- while (skb) {
- int frags = skb_shinfo(skb)->nr_frags +
- (skb->len != skb->data_len);
-
- if (unlikely(skb_headroom(skb) < cdev->skb_tx_rsvd)) {
- pr_err("csk 0x%p, skb head %u < %u.\n",
- csk, skb_headroom(skb), cdev->skb_tx_rsvd);
- err = -EINVAL;
- goto out_err;
- }
-
- if (frags >= SKB_WR_LIST_SIZE) {
- pr_err("csk 0x%p, frags %d, %u,%u >%u.\n",
- csk, skb_shinfo(skb)->nr_frags, skb->len,
- skb->data_len, (uint)(SKB_WR_LIST_SIZE));
- err = -EINVAL;
- goto out_err;
- }
-
- next = skb->next;
- skb->next = NULL;
- cxgbi_skcb_set_flag(skb, SKCBF_TX_NEED_HDR);
- cxgbi_sock_skb_entail(csk, skb);
- copied += skb->len;
- csk->write_seq += skb->len +
- cxgbi_ulp_extra_len(cxgbi_skcb_ulp_mode(skb));
- skb = next;
- }
-
- if (likely(skb_queue_len(&csk->write_queue)))
- cdev->csk_push_tx_frames(csk, 1);
-done:
- spin_unlock_bh(&csk->lock);
- return copied;
-
-out_err:
- if (copied == 0 && err == -EPIPE)
- copied = csk->err ? csk->err : -EPIPE;
- else
- copied = err;
- goto done;
-}
-
static inline void
scmd_get_params(struct scsi_cmnd *sc, struct scatterlist **sgl,
unsigned int *sgcnt, unsigned int *dlen,
@@ -1284,8 +1210,6 @@
* APIs interacting with open-iscsi libraries
*/
-static unsigned char padding[4];
-
int cxgbi_ddp_ppm_setup(void **ppm_pp, struct cxgbi_device *cdev,
struct cxgbi_tag_format *tformat,
unsigned int iscsi_size, unsigned int llimit,
@@ -1833,9 +1757,10 @@
return -EFAULT;
}
-static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
- unsigned int dlen, struct page_frag *frags,
- int frag_max)
+static int
+sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
+ unsigned int dlen, struct page_frag *frags,
+ int frag_max, u32 *dlimit)
{
unsigned int datalen = dlen;
unsigned int sglen = sg->length - sgoffset;
@@ -1867,6 +1792,7 @@
if (i >= frag_max) {
pr_warn("too many pages %u, dlen %u.\n",
frag_max, dlen);
+ *dlimit = dlen - datalen;
return -EINVAL;
}
@@ -1883,38 +1809,220 @@
return i;
}
-int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
+static void cxgbi_task_data_sgl_check(struct iscsi_task *task)
{
- struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
+ struct scsi_cmnd *sc = task->sc;
+ struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+ struct scatterlist *sg, *sgl = NULL;
+ u32 sgcnt = 0;
+ int i;
+
+ tdata->flags = CXGBI_TASK_SGL_CHECKED;
+ if (!sc)
+ return;
+
+ scmd_get_params(sc, &sgl, &sgcnt, &tdata->dlen, 0);
+ if (!sgl || !sgcnt) {
+ tdata->flags |= CXGBI_TASK_SGL_COPY;
+ return;
+ }
+
+ for_each_sg(sgl, sg, sgcnt, i) {
+ if (page_count(sg_page(sg)) < 1) {
+ tdata->flags |= CXGBI_TASK_SGL_COPY;
+ return;
+ }
+ }
+}
+
+static int
+cxgbi_task_data_sgl_read(struct iscsi_task *task, u32 offset, u32 count,
+ u32 *dlimit)
+{
+ struct scsi_cmnd *sc = task->sc;
+ struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+ struct scatterlist *sgl = NULL;
+ struct scatterlist *sg;
+ u32 dlen = 0;
+ u32 sgcnt;
+ int err;
+
+ if (!sc)
+ return 0;
+
+ scmd_get_params(sc, &sgl, &sgcnt, &dlen, 0);
+ if (!sgl || !sgcnt)
+ return 0;
+
+ err = sgl_seek_offset(sgl, sgcnt, offset, &tdata->sgoffset, &sg);
+ if (err < 0) {
+ pr_warn("tpdu max, sgl %u, bad offset %u/%u.\n",
+ sgcnt, offset, tdata->dlen);
+ return err;
+ }
+ err = sgl_read_to_frags(sg, tdata->sgoffset, count,
+ tdata->frags, MAX_SKB_FRAGS, dlimit);
+ if (err < 0) {
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "sgl max limit, sgl %u, offset %u, %u/%u, dlimit %u.\n",
+ sgcnt, offset, count, tdata->dlen, *dlimit);
+ return err;
+ }
+ tdata->offset = offset;
+ tdata->count = count;
+ tdata->nr_frags = err;
+ tdata->total_count = count;
+ tdata->total_offset = offset;
+
+ log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+ "%s: offset %u, count %u,\n"
+ "err %u, total_count %u, total_offset %u\n",
+ __func__, offset, count, err, tdata->total_count, tdata->total_offset);
+
+ return 0;
+}
+
+int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 op)
+{
+ struct iscsi_conn *conn = task->conn;
+ struct iscsi_session *session = task->conn->session;
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
struct cxgbi_conn *cconn = tcp_conn->dd_data;
struct cxgbi_device *cdev = cconn->chba->cdev;
- struct iscsi_conn *conn = task->conn;
+ struct cxgbi_sock *csk = cconn->cep ? cconn->cep->csk : NULL;
struct iscsi_tcp_task *tcp_task = task->dd_data;
struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
struct scsi_cmnd *sc = task->sc;
- struct cxgbi_sock *csk = cconn->cep->csk;
- struct net_device *ndev = cdev->ports[csk->port_id];
- int headroom = SKB_TX_ISCSI_PDU_HEADER_MAX;
+ u32 headroom = SKB_TX_ISCSI_PDU_HEADER_MAX;
+ u32 max_txdata_len = conn->max_xmit_dlength;
+ u32 iso_tx_rsvd = 0, local_iso_info = 0;
+ u32 last_tdata_offset, last_tdata_count;
+ int err = 0;
+
+ if (!tcp_task) {
+ pr_err("task 0x%p, tcp_task 0x%p, tdata 0x%p.\n",
+ task, tcp_task, tdata);
+ return -ENOMEM;
+ }
+ if (!csk) {
+ pr_err("task 0x%p, csk gone.\n", task);
+ return -EPIPE;
+ }
+
+ op &= ISCSI_OPCODE_MASK;
tcp_task->dd_data = tdata;
task->hdr = NULL;
- if (SKB_MAX_HEAD(cdev->skb_tx_rsvd) > (512 * MAX_SKB_FRAGS) &&
- (opcode == ISCSI_OP_SCSI_DATA_OUT ||
- (opcode == ISCSI_OP_SCSI_CMD &&
- sc->sc_data_direction == DMA_TO_DEVICE)))
- /* data could goes into skb head */
- headroom += min_t(unsigned int,
- SKB_MAX_HEAD(cdev->skb_tx_rsvd),
- conn->max_xmit_dlength);
+ last_tdata_count = tdata->count;
+ last_tdata_offset = tdata->offset;
- tdata->skb = alloc_skb(cdev->skb_tx_rsvd + headroom, GFP_ATOMIC);
- if (!tdata->skb) {
- ndev->stats.tx_dropped++;
- return -ENOMEM;
+ if ((op == ISCSI_OP_SCSI_DATA_OUT) ||
+ ((op == ISCSI_OP_SCSI_CMD) &&
+ (sc->sc_data_direction == DMA_TO_DEVICE))) {
+ u32 remaining_data_tosend, dlimit = 0;
+ u32 max_pdu_size, max_num_pdu, num_pdu;
+ u32 count;
+
+ /* Preserve conn->max_xmit_dlength because it can get updated to
+ * ISO data size.
+ */
+ if (task->state == ISCSI_TASK_PENDING)
+ tdata->max_xmit_dlength = conn->max_xmit_dlength;
+
+ if (!tdata->offset)
+ cxgbi_task_data_sgl_check(task);
+
+ remaining_data_tosend =
+ tdata->dlen - tdata->offset - tdata->count;
+
+recalculate_sgl:
+ max_txdata_len = tdata->max_xmit_dlength;
+ log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+ "tdata->dlen %u, remaining to send %u "
+ "conn->max_xmit_dlength %u, "
+ "tdata->max_xmit_dlength %u\n",
+ tdata->dlen, remaining_data_tosend,
+ conn->max_xmit_dlength, tdata->max_xmit_dlength);
+
+ if (cdev->skb_iso_txhdr && !csk->disable_iso &&
+ (remaining_data_tosend > tdata->max_xmit_dlength) &&
+ !(remaining_data_tosend % 4)) {
+ u32 max_iso_data;
+
+ if ((op == ISCSI_OP_SCSI_CMD) &&
+ session->initial_r2t_en)
+ goto no_iso;
+
+ max_pdu_size = tdata->max_xmit_dlength +
+ ISCSI_PDU_NONPAYLOAD_LEN;
+ max_iso_data = rounddown(CXGBI_MAX_ISO_DATA_IN_SKB,
+ csk->advmss);
+ max_num_pdu = max_iso_data / max_pdu_size;
+
+ num_pdu = (remaining_data_tosend +
+ tdata->max_xmit_dlength - 1) /
+ tdata->max_xmit_dlength;
+
+ if (num_pdu > max_num_pdu)
+ num_pdu = max_num_pdu;
+
+ conn->max_xmit_dlength = tdata->max_xmit_dlength * num_pdu;
+ max_txdata_len = conn->max_xmit_dlength;
+ iso_tx_rsvd = cdev->skb_iso_txhdr;
+ local_iso_info = sizeof(struct cxgbi_iso_info);
+
+ log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+ "max_pdu_size %u, max_num_pdu %u, "
+ "max_txdata %u, num_pdu %u\n",
+ max_pdu_size, max_num_pdu,
+ max_txdata_len, num_pdu);
+ }
+no_iso:
+ count = min_t(u32, max_txdata_len, remaining_data_tosend);
+ err = cxgbi_task_data_sgl_read(task,
+ tdata->offset + tdata->count,
+ count, &dlimit);
+ if (unlikely(err < 0)) {
+ log_debug(1 << CXGBI_DBG_ISCSI,
+ "task 0x%p, tcp_task 0x%p, tdata 0x%p, "
+ "sgl err %d, count %u, dlimit %u\n",
+ task, tcp_task, tdata, err, count, dlimit);
+ if (dlimit) {
+ remaining_data_tosend =
+ rounddown(dlimit,
+ tdata->max_xmit_dlength);
+ if (!remaining_data_tosend)
+ remaining_data_tosend = dlimit;
+
+ dlimit = 0;
+
+ conn->max_xmit_dlength = remaining_data_tosend;
+ goto recalculate_sgl;
+ }
+
+ pr_err("task 0x%p, tcp_task 0x%p, tdata 0x%p, "
+ "sgl err %d\n",
+ task, tcp_task, tdata, err);
+ goto ret_err;
+ }
+
+ if ((tdata->flags & CXGBI_TASK_SGL_COPY) ||
+ (tdata->nr_frags > MAX_SKB_FRAGS))
+ headroom += conn->max_xmit_dlength;
}
- skb_reserve(tdata->skb, cdev->skb_tx_rsvd);
+ tdata->skb = alloc_skb(local_iso_info + cdev->skb_tx_rsvd +
+ iso_tx_rsvd + headroom, GFP_ATOMIC);
+ if (!tdata->skb) {
+ tdata->count = last_tdata_count;
+ tdata->offset = last_tdata_offset;
+ err = -ENOMEM;
+ goto ret_err;
+ }
+
+ skb_reserve(tdata->skb, local_iso_info + cdev->skb_tx_rsvd +
+ iso_tx_rsvd);
if (task->sc) {
task->hdr = (struct iscsi_hdr *)tdata->skb->data;
@@ -1923,25 +2031,100 @@
if (!task->hdr) {
__kfree_skb(tdata->skb);
tdata->skb = NULL;
- ndev->stats.tx_dropped++;
return -ENOMEM;
}
}
- task->hdr_max = SKB_TX_ISCSI_PDU_HEADER_MAX; /* BHS + AHS */
+
+ task->hdr_max = SKB_TX_ISCSI_PDU_HEADER_MAX;
+
+ if (iso_tx_rsvd)
+ cxgbi_skcb_set_flag(tdata->skb, SKCBF_TX_ISO);
/* data_out uses scsi_cmd's itt */
- if (opcode != ISCSI_OP_SCSI_DATA_OUT)
+ if (op != ISCSI_OP_SCSI_DATA_OUT)
task_reserve_itt(task, &task->hdr->itt);
log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
- "task 0x%p, op 0x%x, skb 0x%p,%u+%u/%u, itt 0x%x.\n",
- task, opcode, tdata->skb, cdev->skb_tx_rsvd, headroom,
- conn->max_xmit_dlength, ntohl(task->hdr->itt));
+ "task 0x%p, op 0x%x, skb 0x%p,%u+%u/%u, itt 0x%x.\n",
+ task, op, tdata->skb, cdev->skb_tx_rsvd, headroom,
+ conn->max_xmit_dlength, be32_to_cpu(task->hdr->itt));
return 0;
+
+ret_err:
+ conn->max_xmit_dlength = tdata->max_xmit_dlength;
+ return err;
}
EXPORT_SYMBOL_GPL(cxgbi_conn_alloc_pdu);
+static int
+cxgbi_prep_iso_info(struct iscsi_task *task, struct sk_buff *skb,
+ u32 count)
+{
+ struct cxgbi_iso_info *iso_info = (struct cxgbi_iso_info *)skb->head;
+ struct iscsi_r2t_info *r2t;
+ struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
+ struct iscsi_conn *conn = task->conn;
+ struct iscsi_session *session = conn->session;
+ struct iscsi_tcp_task *tcp_task = task->dd_data;
+ u32 burst_size = 0, r2t_dlength = 0, dlength;
+ u32 max_pdu_len = tdata->max_xmit_dlength;
+ u32 segment_offset = 0;
+ u32 num_pdu;
+
+ if (unlikely(!cxgbi_skcb_test_flag(skb, SKCBF_TX_ISO)))
+ return 0;
+
+ memset(iso_info, 0, sizeof(struct cxgbi_iso_info));
+
+ if (task->hdr->opcode == ISCSI_OP_SCSI_CMD && session->imm_data_en) {
+ iso_info->flags |= CXGBI_ISO_INFO_IMM_ENABLE;
+ burst_size = count;
+ }
+
+ dlength = ntoh24(task->hdr->dlength);
+ dlength = min(dlength, max_pdu_len);
+ hton24(task->hdr->dlength, dlength);
+
+ num_pdu = (count + max_pdu_len - 1) / max_pdu_len;
+
+ if (iscsi_task_has_unsol_data(task))
+ r2t = &task->unsol_r2t;
+ else
+ r2t = tcp_task->r2t;
+
+ if (r2t) {
+ log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+ "count %u, tdata->count %u, num_pdu %u,"
+ "task->hdr_len %u, r2t->data_length %u, r2t->sent %u\n",
+ count, tdata->count, num_pdu, task->hdr_len,
+ r2t->data_length, r2t->sent);
+
+ r2t_dlength = r2t->data_length - r2t->sent;
+ segment_offset = r2t->sent;
+ r2t->datasn += num_pdu - 1;
+ }
+
+ if (!r2t || !r2t->sent)
+ iso_info->flags |= CXGBI_ISO_INFO_FSLICE;
+
+ if (task->hdr->flags & ISCSI_FLAG_CMD_FINAL)
+ iso_info->flags |= CXGBI_ISO_INFO_LSLICE;
+
+ task->hdr->flags &= ~ISCSI_FLAG_CMD_FINAL;
+
+ iso_info->op = task->hdr->opcode;
+ iso_info->ahs = task->hdr->hlength;
+ iso_info->num_pdu = num_pdu;
+ iso_info->mpdu = max_pdu_len;
+ iso_info->burst_size = (burst_size + r2t_dlength) >> 2;
+ iso_info->len = count + task->hdr_len;
+ iso_info->segment_offset = segment_offset;
+
+ cxgbi_skcb_tx_iscsi_hdrlen(skb) = task->hdr_len;
+ return 0;
+}
+
static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc)
{
if (hcrc || dcrc) {
@@ -1951,133 +2134,260 @@
submode |= 1;
if (dcrc)
submode |= 2;
- cxgbi_skcb_ulp_mode(skb) = (ULP2_MODE_ISCSI << 4) | submode;
+ cxgbi_skcb_tx_ulp_mode(skb) = (ULP2_MODE_ISCSI << 4) | submode;
} else
- cxgbi_skcb_ulp_mode(skb) = 0;
+ cxgbi_skcb_tx_ulp_mode(skb) = 0;
}
+static struct page *rsvd_page;
+
int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
unsigned int count)
{
struct iscsi_conn *conn = task->conn;
+ struct iscsi_tcp_task *tcp_task = task->dd_data;
struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
- struct sk_buff *skb = tdata->skb;
- unsigned int datalen = count;
- int i, padlen = iscsi_padding(count);
+ struct sk_buff *skb;
+ struct scsi_cmnd *sc = task->sc;
+ u32 expected_count, expected_offset;
+ u32 datalen = count, dlimit = 0;
+ u32 i, padlen = iscsi_padding(count);
struct page *pg;
+ int err;
+
+ if (!tcp_task || (tcp_task->dd_data != tdata)) {
+ pr_err("task 0x%p,0x%p, tcp_task 0x%p, tdata 0x%p/0x%p.\n",
+ task, task->sc, tcp_task,
+ tcp_task ? tcp_task->dd_data : NULL, tdata);
+ return -EINVAL;
+ }
+ skb = tdata->skb;
log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
- "task 0x%p,0x%p, skb 0x%p, 0x%x,0x%x,0x%x, %u+%u.\n",
- task, task->sc, skb, (*skb->data) & ISCSI_OPCODE_MASK,
- ntohl(task->cmdsn), ntohl(task->hdr->itt), offset, count);
+ "task 0x%p,0x%p, skb 0x%p, 0x%x,0x%x,0x%x, %u+%u.\n",
+ task, task->sc, skb, (*skb->data) & ISCSI_OPCODE_MASK,
+ be32_to_cpu(task->cmdsn), be32_to_cpu(task->hdr->itt), offset, count);
skb_put(skb, task->hdr_len);
tx_skb_setmode(skb, conn->hdrdgst_en, datalen ? conn->datadgst_en : 0);
- if (!count)
- return 0;
-
- if (task->sc) {
- struct scsi_data_buffer *sdb = &task->sc->sdb;
- struct scatterlist *sg = NULL;
- int err;
-
- tdata->offset = offset;
+ if (!count) {
tdata->count = count;
- err = sgl_seek_offset(
- sdb->table.sgl, sdb->table.nents,
- tdata->offset, &tdata->sgoffset, &sg);
- if (err < 0) {
- pr_warn("tpdu, sgl %u, bad offset %u/%u.\n",
- sdb->table.nents, tdata->offset, sdb->length);
- return err;
- }
- err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count,
- tdata->frags, MAX_PDU_FRAGS);
- if (err < 0) {
- pr_warn("tpdu, sgl %u, bad offset %u + %u.\n",
- sdb->table.nents, tdata->offset, tdata->count);
- return err;
- }
- tdata->nr_frags = err;
+ tdata->offset = offset;
+ tdata->nr_frags = 0;
+ tdata->total_offset = 0;
+ tdata->total_count = 0;
+ if (tdata->max_xmit_dlength)
+ conn->max_xmit_dlength = tdata->max_xmit_dlength;
+ cxgbi_skcb_clear_flag(skb, SKCBF_TX_ISO);
+ return 0;
+ }
- if (tdata->nr_frags > MAX_SKB_FRAGS ||
- (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) {
+ log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
+ "data->total_count %u, tdata->total_offset %u\n",
+ tdata->total_count, tdata->total_offset);
+
+ expected_count = tdata->total_count;
+ expected_offset = tdata->total_offset;
+
+ if ((count != expected_count) ||
+ (offset != expected_offset)) {
+ err = cxgbi_task_data_sgl_read(task, offset, count, &dlimit);
+ if (err < 0) {
+ pr_err("task 0x%p,0x%p, tcp_task 0x%p, tdata 0x%p/0x%p "
+ "dlimit %u, sgl err %d.\n", task, task->sc,
+ tcp_task, tcp_task ? tcp_task->dd_data : NULL,
+ tdata, dlimit, err);
+ return err;
+ }
+ }
+
+ /* Restore original value of conn->max_xmit_dlength because
+ * it can get updated to ISO data size.
+ */
+ conn->max_xmit_dlength = tdata->max_xmit_dlength;
+
+ if (sc) {
+ struct page_frag *frag = tdata->frags;
+
+ if ((tdata->flags & CXGBI_TASK_SGL_COPY) ||
+ (tdata->nr_frags > MAX_SKB_FRAGS) ||
+ (padlen && (tdata->nr_frags ==
+ MAX_SKB_FRAGS))) {
char *dst = skb->data + task->hdr_len;
- struct page_frag *frag = tdata->frags;
/* data fits in the skb's headroom */
for (i = 0; i < tdata->nr_frags; i++, frag++) {
char *src = kmap_atomic(frag->page);
- memcpy(dst, src+frag->offset, frag->size);
+ memcpy(dst, src + frag->offset, frag->size);
dst += frag->size;
kunmap_atomic(src);
}
+
if (padlen) {
memset(dst, 0, padlen);
padlen = 0;
}
skb_put(skb, count + padlen);
} else {
- /* data fit into frag_list */
- for (i = 0; i < tdata->nr_frags; i++) {
- __skb_fill_page_desc(skb, i,
- tdata->frags[i].page,
- tdata->frags[i].offset,
- tdata->frags[i].size);
- skb_frag_ref(skb, i);
+ for (i = 0; i < tdata->nr_frags; i++, frag++) {
+ get_page(frag->page);
+ skb_fill_page_desc(skb, i, frag->page,
+ frag->offset, frag->size);
}
- skb_shinfo(skb)->nr_frags = tdata->nr_frags;
+
skb->len += count;
skb->data_len += count;
skb->truesize += count;
}
-
} else {
- pg = virt_to_page(task->data);
-
+ pg = virt_to_head_page(task->data);
get_page(pg);
- skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data),
- count);
+ skb_fill_page_desc(skb, 0, pg,
+ task->data - (char *)page_address(pg),
+ count);
skb->len += count;
skb->data_len += count;
skb->truesize += count;
}
if (padlen) {
- i = skb_shinfo(skb)->nr_frags;
+ get_page(rsvd_page);
skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
- virt_to_page(padding), offset_in_page(padding),
- padlen);
+ rsvd_page, 0, padlen);
skb->data_len += padlen;
skb->truesize += padlen;
skb->len += padlen;
}
+ if (likely(count > tdata->max_xmit_dlength))
+ cxgbi_prep_iso_info(task, skb, count);
+ else
+ cxgbi_skcb_clear_flag(skb, SKCBF_TX_ISO);
+
return 0;
}
EXPORT_SYMBOL_GPL(cxgbi_conn_init_pdu);
+static int cxgbi_sock_tx_queue_up(struct cxgbi_sock *csk, struct sk_buff *skb)
+{
+ struct cxgbi_device *cdev = csk->cdev;
+ struct cxgbi_iso_info *iso_cpl;
+ u32 frags = skb_shinfo(skb)->nr_frags;
+ u32 extra_len, num_pdu, hdr_len;
+ u32 iso_tx_rsvd = 0;
+
+ if (csk->state != CTP_ESTABLISHED) {
+ log_debug(1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p,%u,0x%lx,%u, EAGAIN.\n",
+ csk, csk->state, csk->flags, csk->tid);
+ return -EPIPE;
+ }
+
+ if (csk->err) {
+ log_debug(1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p,%u,0x%lx,%u, EPIPE %d.\n",
+ csk, csk->state, csk->flags, csk->tid, csk->err);
+ return -EPIPE;
+ }
+
+ if ((cdev->flags & CXGBI_FLAG_DEV_T3) &&
+ before((csk->snd_win + csk->snd_una), csk->write_seq)) {
+ log_debug(1 << CXGBI_DBG_PDU_TX,
+ "csk 0x%p,%u,0x%lx,%u, FULL %u-%u >= %u.\n",
+ csk, csk->state, csk->flags, csk->tid, csk->write_seq,
+ csk->snd_una, csk->snd_win);
+ return -ENOBUFS;
+ }
+
+ if (cxgbi_skcb_test_flag(skb, SKCBF_TX_ISO))
+ iso_tx_rsvd = cdev->skb_iso_txhdr;
+
+ if (unlikely(skb_headroom(skb) < (cdev->skb_tx_rsvd + iso_tx_rsvd))) {
+ pr_err("csk 0x%p, skb head %u < %u.\n",
+ csk, skb_headroom(skb), cdev->skb_tx_rsvd);
+ return -EINVAL;
+ }
+
+ if (skb->len != skb->data_len)
+ frags++;
+
+ if (frags >= SKB_WR_LIST_SIZE) {
+ pr_err("csk 0x%p, frags %u, %u,%u >%lu.\n",
+ csk, skb_shinfo(skb)->nr_frags, skb->len,
+ skb->data_len, SKB_WR_LIST_SIZE);
+ return -EINVAL;
+ }
+
+ cxgbi_skcb_set_flag(skb, SKCBF_TX_NEED_HDR);
+ skb_reset_transport_header(skb);
+ cxgbi_sock_skb_entail(csk, skb);
+
+ extra_len = cxgbi_ulp_extra_len(cxgbi_skcb_tx_ulp_mode(skb));
+
+ if (likely(cxgbi_skcb_test_flag(skb, SKCBF_TX_ISO))) {
+ iso_cpl = (struct cxgbi_iso_info *)skb->head;
+ num_pdu = iso_cpl->num_pdu;
+ hdr_len = cxgbi_skcb_tx_iscsi_hdrlen(skb);
+ extra_len = (cxgbi_ulp_extra_len(cxgbi_skcb_tx_ulp_mode(skb)) *
+ num_pdu) + (hdr_len * (num_pdu - 1));
+ }
+
+ csk->write_seq += (skb->len + extra_len);
+
+ return 0;
+}
+
+static int cxgbi_sock_send_skb(struct cxgbi_sock *csk, struct sk_buff *skb)
+{
+ struct cxgbi_device *cdev = csk->cdev;
+ int len = skb->len;
+ int err;
+
+ spin_lock_bh(&csk->lock);
+ err = cxgbi_sock_tx_queue_up(csk, skb);
+ if (err < 0) {
+ spin_unlock_bh(&csk->lock);
+ return err;
+ }
+
+ if (likely(skb_queue_len(&csk->write_queue)))
+ cdev->csk_push_tx_frames(csk, 0);
+ spin_unlock_bh(&csk->lock);
+ return len;
+}
+
int cxgbi_conn_xmit_pdu(struct iscsi_task *task)
{
struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
struct cxgbi_conn *cconn = tcp_conn->dd_data;
+ struct iscsi_tcp_task *tcp_task = task->dd_data;
struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
struct cxgbi_task_tag_info *ttinfo = &tdata->ttinfo;
- struct sk_buff *skb = tdata->skb;
+ struct sk_buff *skb;
struct cxgbi_sock *csk = NULL;
- unsigned int datalen;
+ u32 pdulen = 0;
+ u32 datalen;
int err;
+ if (!tcp_task || (tcp_task->dd_data != tdata)) {
+ pr_err("task 0x%p,0x%p, tcp_task 0x%p, tdata 0x%p/0x%p.\n",
+ task, task->sc, tcp_task,
+ tcp_task ? tcp_task->dd_data : NULL, tdata);
+ return -EINVAL;
+ }
+
+ skb = tdata->skb;
if (!skb) {
log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
- "task 0x%p\n", task);
+ "task 0x%p, skb NULL.\n", task);
return 0;
}
if (cconn && cconn->cep)
csk = cconn->cep->csk;
+
if (!csk) {
log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
"task 0x%p, csk gone.\n", task);
@@ -2101,13 +2411,12 @@
if (!task->sc)
memcpy(skb->data, task->hdr, SKB_TX_ISCSI_PDU_HEADER_MAX);
- err = cxgbi_sock_send_pdus(cconn->cep->csk, skb);
+ err = cxgbi_sock_send_skb(csk, skb);
if (err > 0) {
- int pdulen = err;
+ pdulen += err;
- log_debug(1 << CXGBI_DBG_PDU_TX,
- "task 0x%p,0x%p, skb 0x%p, len %u/%u, rv %d.\n",
- task, task->sc, skb, skb->len, skb->data_len, err);
+ log_debug(1 << CXGBI_DBG_PDU_TX, "task 0x%p,0x%p, rv %d.\n",
+ task, task->sc, err);
if (task->conn->hdrdgst_en)
pdulen += ISCSI_DIGEST_SIZE;
@@ -2116,24 +2425,42 @@
pdulen += ISCSI_DIGEST_SIZE;
task->conn->txdata_octets += pdulen;
+
+ if (unlikely(cxgbi_is_iso_config(csk) && cxgbi_is_iso_disabled(csk))) {
+ if (time_after(jiffies, csk->prev_iso_ts + HZ)) {
+ csk->disable_iso = false;
+ csk->prev_iso_ts = 0;
+ log_debug(1 << CXGBI_DBG_PDU_TX,
+ "enable iso: csk 0x%p\n", csk);
+ }
+ }
+
return 0;
}
if (err == -EAGAIN || err == -ENOBUFS) {
log_debug(1 << CXGBI_DBG_PDU_TX,
- "task 0x%p, skb 0x%p, len %u/%u, %d EAGAIN.\n",
- task, skb, skb->len, skb->data_len, err);
+ "task 0x%p, skb 0x%p, len %u/%u, %d EAGAIN.\n",
+ task, skb, skb->len, skb->data_len, err);
/* reset skb to send when we are called again */
tdata->skb = skb;
+
+ if (cxgbi_is_iso_config(csk) && !cxgbi_is_iso_disabled(csk) &&
+ (csk->no_tx_credits++ >= 2)) {
+ csk->disable_iso = true;
+ csk->prev_iso_ts = jiffies;
+ log_debug(1 << CXGBI_DBG_PDU_TX,
+ "disable iso:csk 0x%p, ts:%lu\n",
+ csk, csk->prev_iso_ts);
+ }
+
return err;
}
log_debug(1 << CXGBI_DBG_ISCSI | 1 << CXGBI_DBG_PDU_TX,
- "itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
- task->itt, skb, skb->len, skb->data_len, err);
-
+ "itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
+ task->itt, skb, skb->len, skb->data_len, err);
__kfree_skb(skb);
-
iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
return err;
@@ -2145,7 +2472,7 @@
struct iscsi_tcp_task *tcp_task = task->dd_data;
struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task);
- if (!tcp_task || !tdata || (tcp_task->dd_data != tdata)) {
+ if (!tcp_task || (tcp_task->dd_data != tdata)) {
pr_info("task 0x%p,0x%p, tcp_task 0x%p, tdata 0x%p/0x%p.\n",
task, task->sc, tcp_task,
tcp_task ? tcp_task->dd_data : NULL, tdata);
@@ -2285,34 +2612,6 @@
}
EXPORT_SYMBOL_GPL(cxgbi_set_conn_param);
-static inline int csk_print_port(struct cxgbi_sock *csk, char *buf)
-{
- int len;
-
- cxgbi_sock_get(csk);
- len = sprintf(buf, "%hu\n", ntohs(csk->daddr.sin_port));
- cxgbi_sock_put(csk);
-
- return len;
-}
-
-static inline int csk_print_ip(struct cxgbi_sock *csk, char *buf)
-{
- int len;
-
- cxgbi_sock_get(csk);
- if (csk->csk_family == AF_INET)
- len = sprintf(buf, "%pI4",
- &csk->daddr.sin_addr.s_addr);
- else
- len = sprintf(buf, "%pI6",
- &csk->daddr6.sin6_addr);
-
- cxgbi_sock_put(csk);
-
- return len;
-}
-
int cxgbi_get_ep_param(struct iscsi_endpoint *ep, enum iscsi_param param,
char *buf)
{
@@ -2775,14 +3074,19 @@
{
pr_info("%s", version);
- BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, cb) <
+ BUILD_BUG_ON(sizeof_field(struct sk_buff, cb) <
sizeof(struct cxgbi_skb_cb));
+ rsvd_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (!rsvd_page)
+ return -ENOMEM;
+
return 0;
}
static void __exit libcxgbi_exit_module(void)
{
cxgbi_device_unregister_all(0xFF);
+ put_page(rsvd_page);
return;
}
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
index 84b96af..3687b5c 100644
--- a/drivers/scsi/cxgbi/libcxgbi.h
+++ b/drivers/scsi/cxgbi/libcxgbi.h
@@ -76,6 +76,14 @@
#define ULP2_MAX_PDU_PAYLOAD \
(ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN)
+#define CXGBI_ULP2_MAX_ISO_PAYLOAD 65535
+
+#define CXGBI_MAX_ISO_DATA_IN_SKB \
+ min_t(u32, MAX_SKB_FRAGS << PAGE_SHIFT, CXGBI_ULP2_MAX_ISO_PAYLOAD)
+
+#define cxgbi_is_iso_config(csk) ((csk)->cdev->skb_iso_txhdr)
+#define cxgbi_is_iso_disabled(csk) ((csk)->disable_iso)
+
/*
* For iscsi connections HW may inserts digest bytes into the pdu. Those digest
* bytes are not sent by the host but are part of the TCP payload and therefore
@@ -162,6 +170,10 @@
u32 write_seq;
u32 snd_win;
u32 rcv_win;
+
+ bool disable_iso;
+ u32 no_tx_credits;
+ unsigned long prev_iso_ts;
};
/*
@@ -203,6 +215,8 @@
void *handle;
void *arp_err_handler;
struct sk_buff *wr_next;
+ u16 iscsi_hdr_len;
+ u8 ulp_mode;
};
enum cxgbi_skcb_flags {
@@ -218,6 +232,7 @@
SKCBF_RX_HCRC_ERR, /* header digest error */
SKCBF_RX_DCRC_ERR, /* data digest error */
SKCBF_RX_PAD_ERR, /* padding byte error */
+ SKCBF_TX_ISO, /* iso cpl in tx skb */
};
struct cxgbi_skb_cb {
@@ -225,18 +240,18 @@
struct cxgbi_skb_rx_cb rx;
struct cxgbi_skb_tx_cb tx;
};
- unsigned char ulp_mode;
unsigned long flags;
unsigned int seq;
};
#define CXGBI_SKB_CB(skb) ((struct cxgbi_skb_cb *)&((skb)->cb[0]))
#define cxgbi_skcb_flags(skb) (CXGBI_SKB_CB(skb)->flags)
-#define cxgbi_skcb_ulp_mode(skb) (CXGBI_SKB_CB(skb)->ulp_mode)
#define cxgbi_skcb_tcp_seq(skb) (CXGBI_SKB_CB(skb)->seq)
#define cxgbi_skcb_rx_ddigest(skb) (CXGBI_SKB_CB(skb)->rx.ddigest)
#define cxgbi_skcb_rx_pdulen(skb) (CXGBI_SKB_CB(skb)->rx.pdulen)
#define cxgbi_skcb_tx_wr_next(skb) (CXGBI_SKB_CB(skb)->tx.wr_next)
+#define cxgbi_skcb_tx_iscsi_hdrlen(skb) (CXGBI_SKB_CB(skb)->tx.iscsi_hdr_len)
+#define cxgbi_skcb_tx_ulp_mode(skb) (CXGBI_SKB_CB(skb)->tx.ulp_mode)
static inline void cxgbi_skcb_set_flag(struct sk_buff *skb,
enum cxgbi_skcb_flags flag)
@@ -458,6 +473,7 @@
#define CXGBI_FLAG_IPV4_SET 0x10
#define CXGBI_FLAG_USE_PPOD_OFLDQ 0x40
#define CXGBI_FLAG_DDP_OFF 0x100
+#define CXGBI_FLAG_DEV_ISO_OFF 0x400
struct cxgbi_device {
struct list_head list_head;
@@ -477,6 +493,7 @@
unsigned int pfvf;
unsigned int rx_credit_thres;
unsigned int skb_tx_rsvd;
+ u32 skb_iso_txhdr;
unsigned int skb_rx_extra; /* for msg coalesced mode */
unsigned int tx_max_size;
unsigned int rx_max_size;
@@ -523,35 +540,40 @@
struct cxgbi_sock *csk;
};
-#define MAX_PDU_FRAGS ((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512)
struct cxgbi_task_data {
+#define CXGBI_TASK_SGL_CHECKED 0x1
+#define CXGBI_TASK_SGL_COPY 0x2
+ u8 flags;
unsigned short nr_frags;
- struct page_frag frags[MAX_PDU_FRAGS];
+ struct page_frag frags[MAX_SKB_FRAGS];
struct sk_buff *skb;
unsigned int dlen;
unsigned int offset;
unsigned int count;
unsigned int sgoffset;
+ u32 total_count;
+ u32 total_offset;
+ u32 max_xmit_dlength;
struct cxgbi_task_tag_info ttinfo;
};
#define iscsi_task_cxgbi_data(task) \
((task)->dd_data + sizeof(struct iscsi_tcp_task))
-static inline void *cxgbi_alloc_big_mem(unsigned int size,
- gfp_t gfp)
-{
- void *p = kzalloc(size, gfp | __GFP_NOWARN);
-
- if (!p)
- p = vzalloc(size);
-
- return p;
-}
-
-static inline void cxgbi_free_big_mem(void *addr)
-{
- kvfree(addr);
-}
+struct cxgbi_iso_info {
+#define CXGBI_ISO_INFO_FSLICE 0x1
+#define CXGBI_ISO_INFO_LSLICE 0x2
+#define CXGBI_ISO_INFO_IMM_ENABLE 0x4
+ u8 flags;
+ u8 op;
+ u8 ahs;
+ u8 num_pdu;
+ u32 mpdu;
+ u32 burst_size;
+ u32 len;
+ u32 segment_offset;
+ u32 datasn_offset;
+ u32 buffer_offset;
+};
static inline void cxgbi_set_iscsi_ipv4(struct cxgbi_hba *chba, __be32 ipaddr)
{
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 67d681c..e72440d 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -44,14 +44,9 @@
struct afu *afu = cmd->parent;
struct cxlflash_cfg *cfg = afu->parent;
struct device *dev = &cfg->dev->dev;
- struct sisl_ioarcb *ioarcb;
struct sisl_ioasa *ioasa;
u32 resid;
- if (unlikely(!cmd))
- return;
-
- ioarcb = &(cmd->rcb);
ioasa = &(cmd->sa);
if (ioasa->rc.flags & SISL_RC_FLAGS_UNDERRUN) {
@@ -753,16 +748,16 @@
/* SISL_MSI_ASYNC_ERROR is setup only for the primary HWQ */
if (index == PRIMARY_HWQ)
cfg->ops->unmap_afu_irq(hwq->ctx_cookie, 3, hwq);
- /* fall through */
+ fallthrough;
case UNMAP_TWO:
cfg->ops->unmap_afu_irq(hwq->ctx_cookie, 2, hwq);
- /* fall through */
+ fallthrough;
case UNMAP_ONE:
cfg->ops->unmap_afu_irq(hwq->ctx_cookie, 1, hwq);
- /* fall through */
+ fallthrough;
case FREE_IRQ:
cfg->ops->free_afu_irqs(hwq->ctx_cookie);
- /* fall through */
+ fallthrough;
case UNDO_NOOP:
/* No action required */
break;
@@ -976,18 +971,18 @@
switch (cfg->init_state) {
case INIT_STATE_CDEV:
cxlflash_release_chrdev(cfg);
- /* fall through */
+ fallthrough;
case INIT_STATE_SCSI:
cxlflash_term_local_luns(cfg);
scsi_remove_host(cfg->host);
- /* fall through */
+ fallthrough;
case INIT_STATE_AFU:
term_afu(cfg);
- /* fall through */
+ fallthrough;
case INIT_STATE_PCI:
cfg->ops->destroy_afu(cfg->afu_cookie);
pci_disable_device(pdev);
- /* fall through */
+ fallthrough;
case INIT_STATE_NONE:
free_mem(cfg);
scsi_host_put(cfg->host);
@@ -2360,11 +2355,11 @@
cxlflash_schedule_async_reset(cfg);
break;
}
- /* fall through - to retry */
+ fallthrough; /* to retry */
case -EAGAIN:
if (++nretry < 2)
goto retry;
- /* fall through - to exit */
+ fallthrough; /* to exit */
default:
break;
}
@@ -2538,12 +2533,12 @@
cfg->state = STATE_NORMAL;
wake_up_all(&cfg->reset_waitq);
ssleep(1);
- /* fall through */
+ fallthrough;
case STATE_RESET:
wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
if (cfg->state == STATE_NORMAL)
break;
- /* fall through */
+ fallthrough;
default:
rc = FAILED;
break;
@@ -3024,7 +3019,7 @@
wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
if (cfg->state == STATE_NORMAL)
goto retry;
- /* else, fall through */
+ fallthrough;
default:
/* Ideally should not happen */
dev_err(dev, "%s: Device is not ready, state=%d\n",
@@ -3536,7 +3531,7 @@
if (likely(do_ioctl))
break;
- /* fall through */
+ fallthrough;
default:
rc = -EINVAL;
goto out;
@@ -3593,7 +3588,7 @@
.owner = THIS_MODULE,
.open = cxlflash_chr_open,
.unlocked_ioctl = cxlflash_chr_ioctl,
- .compat_ioctl = cxlflash_chr_ioctl,
+ .compat_ioctl = compat_ptr_ioctl,
};
/**
diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 7018cd8..e4e0d76 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -15,7 +15,8 @@
#include <linux/pseudo_fs.h>
#include <linux/poll.h>
#include <linux/sched/signal.h>
-
+#include <linux/interrupt.h>
+#include <asm/xive.h>
#include <misc/ocxl.h>
#include <uapi/misc/cxl.h>
@@ -180,7 +181,7 @@
struct ocxl_hw_afu *afu = ctx->hw_afu;
struct device *dev = afu->dev;
struct ocxlflash_irqs *irq;
- void __iomem *vtrig;
+ struct xive_irq_data *xd;
u32 virq;
int rc = 0;
@@ -204,15 +205,15 @@
goto err1;
}
- vtrig = ioremap(irq->ptrig, PAGE_SIZE);
- if (unlikely(!vtrig)) {
- dev_err(dev, "%s: Trigger page mapping failed\n", __func__);
- rc = -ENOMEM;
+ xd = irq_get_handler_data(virq);
+ if (unlikely(!xd)) {
+ dev_err(dev, "%s: Can't get interrupt data\n", __func__);
+ rc = -ENXIO;
goto err2;
}
irq->virq = virq;
- irq->vtrig = vtrig;
+ irq->vtrig = xd->trig_mmio;
out:
return rc;
err2:
@@ -259,8 +260,6 @@
}
irq = &ctx->irqs[num];
- if (irq->vtrig)
- iounmap(irq->vtrig);
if (irq_find_mapping(NULL, irq->hwirq)) {
free_irq(irq->virq, cookie);
@@ -615,7 +614,6 @@
struct ocxl_hw_afu *afu = ctx->hw_afu;
struct device *dev = afu->dev;
struct ocxlflash_irqs *irqs;
- u64 addr;
int rc = 0;
int hwirq;
int i;
@@ -640,7 +638,7 @@
}
for (i = 0; i < num; i++) {
- rc = ocxl_link_irq_alloc(afu->link_token, &hwirq, &addr);
+ rc = ocxl_link_irq_alloc(afu->link_token, &hwirq);
if (unlikely(rc)) {
dev_err(dev, "%s: ocxl_link_irq_alloc failed rc=%d\n",
__func__, rc);
@@ -648,7 +646,6 @@
}
irqs[i].hwirq = hwirq;
- irqs[i].ptrig = addr;
}
ctx->irqs = irqs;
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index fc6ad4f..f2fe888 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -13,7 +13,6 @@
struct ocxlflash_irqs {
int hwirq;
u32 virq;
- u64 ptrig;
void __iomem *vtrig;
};
diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c
index 593669a..5dddf67 100644
--- a/drivers/scsi/cxlflash/superpipe.c
+++ b/drivers/scsi/cxlflash/superpipe.c
@@ -375,14 +375,13 @@
switch (sshdr.sense_key) {
case NO_SENSE:
case RECOVERED_ERROR:
- /* fall through */
case NOT_READY:
result &= ~SAM_STAT_CHECK_CONDITION;
break;
case UNIT_ATTENTION:
switch (sshdr.asc) {
case 0x29: /* Power on Reset or Device Reset */
- /* fall through */
+ fallthrough;
case 0x2A: /* Device capacity changed */
case 0x3F: /* Report LUNs changed */
/* Retry the command once more */
@@ -1791,13 +1790,12 @@
switch (sshdr.sense_key) {
case NO_SENSE:
case RECOVERED_ERROR:
- /* fall through */
case NOT_READY:
break;
case UNIT_ATTENTION:
switch (sshdr.asc) {
case 0x29: /* Power on Reset or Device Reset */
- /* fall through */
+ fallthrough;
case 0x2A: /* Device settings/capacity changed */
rc = read_cap16(sdev, lli);
if (rc) {
@@ -2157,7 +2155,7 @@
if (unlikely(rc))
goto cxlflash_ioctl_exit;
- /* fall through */
+ fallthrough;
case DK_CXLFLASH_MANAGE_LUN:
known_ioctl = true;
@@ -2168,7 +2166,7 @@
if (likely(do_ioctl))
break;
- /* fall through */
+ fallthrough;
default:
rc = -EINVAL;
goto cxlflash_ioctl_exit;
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 13fbb2e..6cb48ae 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -61,7 +61,6 @@
#include <asm/io.h>
#include <scsi/scsi.h>
-#include <scsi/scsicam.h> /* needed for scsicam_bios_param */
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
@@ -903,7 +902,7 @@
nseg = scsi_dma_map(cmd);
BUG_ON(nseg < 0);
- if (dir == PCI_DMA_NONE || !nseg) {
+ if (dir == DMA_NONE || !nseg) {
dprintkdbg(DBG_0,
"build_srb: [0] len=%d buf=%p use_sg=%d !MAP=%08x\n",
cmd->bufflen, scsi_sglist(cmd), scsi_sg_count(cmd),
@@ -1053,38 +1052,6 @@
static DEF_SCSI_QCMD(dc395x_queue_command)
-/*
- * Return the disk geometry for the given SCSI device.
- */
-static int dc395x_bios_param(struct scsi_device *sdev,
- struct block_device *bdev, sector_t capacity, int *info)
-{
-#ifdef CONFIG_SCSI_DC395x_TRMS1040_TRADMAP
- int heads, sectors, cylinders;
- struct AdapterCtlBlk *acb;
- int size = capacity;
-
- dprintkdbg(DBG_0, "dc395x_bios_param..............\n");
- acb = (struct AdapterCtlBlk *)sdev->host->hostdata;
- heads = 64;
- sectors = 32;
- cylinders = size / (heads * sectors);
-
- if ((acb->gmode2 & NAC_GREATER_1G) && (cylinders > 1024)) {
- heads = 255;
- sectors = 63;
- cylinders = size / (heads * sectors);
- }
- geom[0] = heads;
- geom[1] = sectors;
- geom[2] = cylinders;
- return 0;
-#else
- return scsicam_bios_param(bdev, capacity, info);
-#endif
-}
-
-
static void dump_register_info(struct AdapterCtlBlk *acb,
struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb)
{
@@ -3168,7 +3135,7 @@
struct scsi_cmnd *cmd = srb->cmd;
enum dma_data_direction dir = cmd->sc_data_direction;
- if (scsi_sg_count(cmd) && dir != PCI_DMA_NONE) {
+ if (scsi_sg_count(cmd) && dir != DMA_NONE) {
/* unmap DC395x SG list */
dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n",
srb->sg_bus_addr, SEGMENTX_LEN);
@@ -3366,7 +3333,7 @@
if (!ckc_only && (cmd->result & RES_DID) == 0
&& cmd->cmnd[2] == 0 && scsi_bufflen(cmd) >= 8
- && dir != PCI_DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2)
+ && dir != DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2)
dcb->inquiry7 = ptr->Flags;
/*if( srb->cmd->cmnd[0] == INQUIRY && */
@@ -4159,7 +4126,7 @@
const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
int srb_idx = 0;
unsigned i = 0;
- struct SGentry *uninitialized_var(ptr);
+ struct SGentry *ptr;
for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
acb->srb_array[i].segment_x = NULL;
@@ -4537,14 +4504,8 @@
/*seq_printf(m, "\n"); */
seq_printf(m, "Nr of DCBs: %i\n", list_size(&acb->dcb_list));
- seq_printf(m, "Map of attached LUNs: %02x %02x %02x %02x %02x %02x %02x %02x\n",
- acb->dcb_map[0], acb->dcb_map[1], acb->dcb_map[2],
- acb->dcb_map[3], acb->dcb_map[4], acb->dcb_map[5],
- acb->dcb_map[6], acb->dcb_map[7]);
- seq_printf(m, " %02x %02x %02x %02x %02x %02x %02x %02x\n",
- acb->dcb_map[8], acb->dcb_map[9], acb->dcb_map[10],
- acb->dcb_map[11], acb->dcb_map[12], acb->dcb_map[13],
- acb->dcb_map[14], acb->dcb_map[15]);
+ seq_printf(m, "Map of attached LUNs: %8ph\n", &acb->dcb_map[0]);
+ seq_printf(m, " %8ph\n", &acb->dcb_map[8]);
seq_puts(m,
"Un ID LUN Prty Sync Wide DsCn SndS TagQ nego_period SyncFreq SyncOffs MaxCmd\n");
@@ -4622,7 +4583,6 @@
.show_info = dc395x_show_info,
.name = DC395X_BANNER " " DC395X_VERSION,
.queuecommand = dc395x_queue_command,
- .bios_param = dc395x_bios_param,
.slave_alloc = dc395x_slave_alloc,
.slave_destroy = dc395x_slave_destroy,
.can_queue = DC395x_MAX_CAN_QUEUE,
@@ -4698,6 +4658,7 @@
/* initialise the adapter and everything we need */
if (adapter_init(acb, io_port_base, io_port_len, irq)) {
dprintkl(KERN_INFO, "adapter init failed\n");
+ acb = NULL;
goto fail;
}
@@ -4761,30 +4722,7 @@
.probe = dc395x_init_one,
.remove = dc395x_remove_one,
};
-
-
-/**
- * dc395x_module_init - Module initialization function
- *
- * Used by both module and built-in driver to initialise this driver.
- **/
-static int __init dc395x_module_init(void)
-{
- return pci_register_driver(&dc395x_driver);
-}
-
-
-/**
- * dc395x_module_exit - Module cleanup function.
- **/
-static void __exit dc395x_module_exit(void)
-{
- pci_unregister_driver(&dc395x_driver);
-}
-
-
-module_init(dc395x_module_init);
-module_exit(dc395x_module_exit);
+module_pci_driver(dc395x_driver);
MODULE_AUTHOR("C.L. Huang / Erich Chen / Kurt Garloff");
MODULE_DESCRIPTION("SCSI host adapter driver for Tekram TRM-S1040 based adapters: Tekram DC395 and DC315 series");
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
index 8acd4bb..4a3f783 100644
--- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
@@ -60,7 +60,7 @@
ret = SCSI_DH_OK;
break;
}
- /* Fallthrough */
+ fallthrough;
default:
sdev_printk(KERN_WARNING, sdev,
"%s: sending tur failed, sense %x/%x/%x\n",
@@ -147,7 +147,7 @@
rc = SCSI_DH_RETRY;
break;
}
- /* fall through */
+ fallthrough;
default:
sdev_printk(KERN_WARNING, sdev,
"%s: sending start_stop_unit failed, "
diff --git a/drivers/scsi/dpt/dpti_ioctl.h b/drivers/scsi/dpt/dpti_ioctl.h
index 6bc33f4..25e9251 100644
--- a/drivers/scsi/dpt/dpti_ioctl.h
+++ b/drivers/scsi/dpt/dpti_ioctl.h
@@ -5,7 +5,7 @@
begin : Thu Sep 7 2000
copyright : (C) 2001 by Adaptec
- See Documentation/scsi/dpti.txt for history, notes, license info
+ See Documentation/scsi/dpti.rst for history, notes, license info
and credits
***************************************************************************/
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index abc74fd..4251212 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -8,7 +8,7 @@
July 30, 2001 First version being submitted
for inclusion in the kernel. V2.4
- See Documentation/scsi/dpti.txt for history, notes, license info
+ See Documentation/scsi/dpti.rst for history, notes, license info
and credits
***************************************************************************/
@@ -27,6 +27,7 @@
/*#define UARTDELAY 1 */
#include <linux/module.h>
+#include <linux/pgtable.h>
MODULE_AUTHOR("Deanna Bonds, with _lots_ of help from Mark Salyzyn");
MODULE_DESCRIPTION("Adaptec I2O RAID Driver");
@@ -55,7 +56,6 @@
#include <linux/mutex.h>
#include <asm/processor.h> /* for boot_cpu_data */
-#include <asm/pgtable.h>
#include <asm/io.h> /* for virt_to_bus, etc. */
#include <scsi/scsi.h>
@@ -408,9 +408,6 @@
static int adpt_slave_configure(struct scsi_device * device)
{
struct Scsi_Host *host = device->host;
- adpt_hba* pHba;
-
- pHba = (adpt_hba *) host->hostdata[0];
if (host->can_queue && device->tagged_supported) {
scsi_change_queue_depth(device,
@@ -817,7 +814,7 @@
}
pHba->state &= ~DPTI_STATE_RESET;
- adpt_fail_posted_scbs(pHba);
+ scsi_host_complete_all_commands(pHba->host, DID_RESET);
return 0; /* return success */
}
@@ -1120,7 +1117,7 @@
{
struct adpt_device* d;
- if(chan < 0 || chan >= MAX_CHANNEL)
+ if (chan >= MAX_CHANNEL)
return NULL;
d = pHba->channel[chan].device[id];
@@ -1331,7 +1328,6 @@
printk(KERN_ERR"IOP reset failed - no free memory.\n");
return -ENOMEM;
}
- memset(status,0,4);
msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
@@ -2173,7 +2169,7 @@
readl(reply + 12) - 1);
if(cmd != NULL){
scsi_dma_unmap(cmd);
- adpt_i2o_to_scsi(reply, cmd);
+ adpt_i2o_scsi_complete(reply, cmd);
}
}
writel(m, pHba->reply_port);
@@ -2335,13 +2331,12 @@
host->unique_id = (u32)sys_tbl_pa + pHba->unit;
host->sg_tablesize = pHba->sg_tablesize;
host->can_queue = pHba->post_fifo_size;
- host->use_cmd_list = 1;
return 0;
}
-static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd)
+static void adpt_i2o_scsi_complete(void __iomem *reply, struct scsi_cmnd *cmd)
{
adpt_hba* pHba;
u32 hba_status;
@@ -2459,7 +2454,6 @@
if(cmd->scsi_done != NULL){
cmd->scsi_done(cmd);
}
- return cmd->result;
}
@@ -2647,23 +2641,6 @@
return 0;
}
-static void adpt_fail_posted_scbs(adpt_hba* pHba)
-{
- struct scsi_cmnd* cmd = NULL;
- struct scsi_device* d = NULL;
-
- shost_for_each_device(d, pHba->host) {
- unsigned long flags;
- spin_lock_irqsave(&d->list_lock, flags);
- list_for_each_entry(cmd, &d->cmd_list, list) {
- cmd->result = (DID_OK << 16) | (QUEUE_FULL <<1);
- cmd->scsi_done(cmd);
- }
- spin_unlock_irqrestore(&d->list_lock, flags);
- }
-}
-
-
/*============================================================================
* Routines from i2o subsystem
*============================================================================
@@ -2803,7 +2780,6 @@
pHba->name);
return -ENOMEM;
}
- memset(status, 0, 4);
writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]);
writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]);
@@ -2857,7 +2833,6 @@
printk(KERN_ERR "%s: Could not allocate reply pool\n", pHba->name);
return -ENOMEM;
}
- memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4);
for(i = 0; i < pHba->reply_fifo_size; i++) {
writel(pHba->reply_pool_pa + (i * REPLY_FRAME_SIZE * 4),
@@ -3092,7 +3067,6 @@
printk(KERN_WARNING "SysTab Set failed. Out of memory.\n");
return -ENOMEM;
}
- memset(sys_tbl, 0, sys_tbl_len);
sys_tbl->num_entries = hba_count;
sys_tbl->version = I2OVERSION;
diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h
index 42b1e28..8a079e8 100644
--- a/drivers/scsi/dpti.h
+++ b/drivers/scsi/dpti.h
@@ -5,7 +5,7 @@
begin : Thu Sep 7 2000
copyright : (C) 2001 by Adaptec
- See Documentation/scsi/dpti.txt for history, notes, license info
+ See Documentation/scsi/dpti.rst for history, notes, license info
and credits
***************************************************************************/
@@ -286,7 +286,7 @@
static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba);
static s32 adpt_i2o_hrt_get(adpt_hba* pHba);
static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* dptdevice);
-static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd);
+static void adpt_i2o_scsi_complete(void __iomem *reply, struct scsi_cmnd *cmd);
static s32 adpt_scsi_host_alloc(adpt_hba* pHba,struct scsi_host_template * sht);
static s32 adpt_hba_reset(adpt_hba* pHba);
static s32 adpt_i2o_reset_hba(adpt_hba* pHba);
@@ -295,7 +295,6 @@
static s32 adpt_send_nop(adpt_hba*pHba,u32 m);
static void adpt_i2o_delete_hba(adpt_hba* pHba);
static void adpt_inquiry(adpt_hba* pHba);
-static void adpt_fail_posted_scbs(adpt_hba* pHba);
static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun);
static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) ;
static int adpt_i2o_online_hba(adpt_hba* pHba);
diff --git a/drivers/scsi/esas2r/Kconfig b/drivers/scsi/esas2r/Kconfig
index 19f6d30..c9b43f7 100644
--- a/drivers/scsi/esas2r/Kconfig
+++ b/drivers/scsi/esas2r/Kconfig
@@ -2,5 +2,5 @@
config SCSI_ESAS2R
tristate "ATTO Technology's ExpressSAS RAID adapter driver"
depends on PCI && SCSI
- ---help---
+ help
This driver supports the ATTO ExpressSAS R6xx SAS/SATA RAID controllers.
diff --git a/drivers/scsi/esas2r/esas2r.h b/drivers/scsi/esas2r/esas2r.h
index 7f43b95..e30d2f1 100644
--- a/drivers/scsi/esas2r/esas2r.h
+++ b/drivers/scsi/esas2r/esas2r.h
@@ -1225,8 +1225,9 @@
/* req_table entry should be NULL at this point - if not, halt */
- if (a->req_table[LOWORD(vrq->scsi.handle)])
+ if (a->req_table[LOWORD(vrq->scsi.handle)]) {
esas2r_bugon();
+ }
/* fill in the table for this handle so we can get back to the
* request.
diff --git a/drivers/scsi/esas2r/esas2r_flash.c b/drivers/scsi/esas2r/esas2r_flash.c
index b02ac38..429d642 100644
--- a/drivers/scsi/esas2r/esas2r_flash.c
+++ b/drivers/scsi/esas2r/esas2r_flash.c
@@ -1500,7 +1500,7 @@
return complete_fmapi_req(a, rq, FI_STAT_SUCCESS);
}
- /* fall through */
+ fallthrough;
case FI_ACT_UP: /* Upload the components */
default:
diff --git a/drivers/scsi/esas2r/esas2r_init.c b/drivers/scsi/esas2r/esas2r_init.c
index eb7d139..09c5c24 100644
--- a/drivers/scsi/esas2r/esas2r_init.c
+++ b/drivers/scsi/esas2r/esas2r_init.c
@@ -1236,7 +1236,7 @@
a->init_msg = ESAS2R_INIT_MSG_GET_INIT;
break;
}
- /* fall through */
+ fallthrough;
case ESAS2R_INIT_MSG_GET_INIT:
if (msg == ESAS2R_INIT_MSG_GET_INIT) {
@@ -1250,7 +1250,7 @@
esas2r_hdebug("FAILED");
}
}
- /* fall through */
+ fallthrough;
default:
rq->req_stat = RS_SUCCESS;
diff --git a/drivers/scsi/esas2r/esas2r_ioctl.c b/drivers/scsi/esas2r/esas2r_ioctl.c
index 442c5e7..08f4e43 100644
--- a/drivers/scsi/esas2r/esas2r_ioctl.c
+++ b/drivers/scsi/esas2r/esas2r_ioctl.c
@@ -1510,7 +1510,7 @@
}
/* Always copy the buffer back, if only to pick up the status */
- err = __copy_to_user(arg, ioctl, sizeof(struct atto_express_ioctl));
+ err = copy_to_user(arg, ioctl, sizeof(struct atto_express_ioctl));
if (err != 0) {
esas2r_log(ESAS2R_LOG_WARN,
"ioctl_handler copy_to_user didn't copy everything (err %d, cmd %u)",
@@ -1548,11 +1548,10 @@
a->firmware.orig_len = length;
- a->firmware.data = (u8 *)dma_alloc_coherent(&a->pcid->dev,
- (size_t)length,
- (dma_addr_t *)&a->firmware.
- phys,
- GFP_KERNEL);
+ a->firmware.data = dma_alloc_coherent(&a->pcid->dev,
+ (size_t)length,
+ (dma_addr_t *)&a->firmware.phys,
+ GFP_KERNEL);
if (!a->firmware.data) {
esas2r_debug("buffer alloc failed!");
@@ -1895,11 +1894,11 @@
if (!a->vda_buffer) {
dma_addr_t dma_addr;
- a->vda_buffer = (u8 *)dma_alloc_coherent(&a->pcid->dev,
- (size_t)
- VDA_MAX_BUFFER_SIZE,
- &dma_addr,
- GFP_KERNEL);
+ a->vda_buffer = dma_alloc_coherent(&a->pcid->dev,
+ (size_t)
+ VDA_MAX_BUFFER_SIZE,
+ &dma_addr,
+ GFP_KERNEL);
a->ppvda_buffer = dma_addr;
}
@@ -2064,11 +2063,10 @@
re_allocate_buffer:
a->fs_api_buffer_size = length;
- a->fs_api_buffer = (u8 *)dma_alloc_coherent(
- &a->pcid->dev,
- (size_t)a->fs_api_buffer_size,
- (dma_addr_t *)&a->ppfs_api_buffer,
- GFP_KERNEL);
+ a->fs_api_buffer = dma_alloc_coherent(&a->pcid->dev,
+ (size_t)a->fs_api_buffer_size,
+ (dma_addr_t *)&a->ppfs_api_buffer,
+ GFP_KERNEL);
}
}
diff --git a/drivers/scsi/esas2r/esas2r_log.c b/drivers/scsi/esas2r/esas2r_log.c
index 65fdf22..b545798 100644
--- a/drivers/scsi/esas2r/esas2r_log.c
+++ b/drivers/scsi/esas2r/esas2r_log.c
@@ -75,7 +75,7 @@
/* A lock to protect the shared buffer used for formatting messages. */
static DEFINE_SPINLOCK(event_buffer_lock);
-/**
+/*
* translates an esas2r-defined logging event level to a kernel logging level.
*
* @param [in] level the esas2r-defined logging event level to translate
@@ -101,7 +101,7 @@
}
}
-/**
+/*
* the master logging function. this function will format the message as
* outlined by the formatting string, the input device information and the
* substitution arguments and output the resulting string to the system log.
@@ -170,7 +170,7 @@
return 0;
}
-/**
+/*
* formats and logs a message to the system log.
*
* @param [in] level the event level of the message
@@ -193,7 +193,7 @@
return retval;
}
-/**
+/*
* formats and logs a message to the system log. this message will include
* device information.
*
@@ -221,7 +221,7 @@
return retval;
}
-/**
+/*
* formats and logs a message to the system log. this message will include
* device information.
*
diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c
index fdbda5c..7b49e2e 100644
--- a/drivers/scsi/esas2r/esas2r_main.c
+++ b/drivers/scsi/esas2r/esas2r_main.c
@@ -613,10 +613,17 @@
/* Handle ioctl calls to "/proc/scsi/esas2r/ATTOnode" */
static const struct file_operations esas2r_proc_fops = {
- .compat_ioctl = esas2r_proc_ioctl,
+ .compat_ioctl = compat_ptr_ioctl,
.unlocked_ioctl = esas2r_proc_ioctl,
};
+static const struct proc_ops esas2r_proc_ops = {
+ .proc_ioctl = esas2r_proc_ioctl,
+#ifdef CONFIG_COMPAT
+ .proc_compat_ioctl = compat_ptr_ioctl,
+#endif
+};
+
static struct Scsi_Host *esas2r_proc_host;
static int esas2r_proc_major;
@@ -728,7 +735,7 @@
pde = proc_create(ATTONODE_NAME, 0,
sh->hostt->proc_dir,
- &esas2r_proc_fops);
+ &esas2r_proc_ops);
if (!pde) {
esas2r_log_dev(ESAS2R_LOG_WARN,
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index bb88995..43a1fd1 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -243,8 +243,6 @@
/* Reset the ESP chip, _not_ the SCSI bus. */
static void esp_reset_esp(struct esp *esp)
{
- u8 family_code, version;
-
/* Now reset the ESP chip */
scsi_esp_cmd(esp, ESP_CMD_RC);
scsi_esp_cmd(esp, ESP_CMD_NULL | ESP_CMD_DMA);
@@ -257,14 +255,19 @@
*/
esp->max_period = ((35 * esp->ccycle) / 1000);
if (esp->rev == FAST) {
- version = esp_read8(ESP_UID);
- family_code = (version & 0xf8) >> 3;
- if (family_code == 0x02)
+ u8 family_code = ESP_FAMILY(esp_read8(ESP_UID));
+
+ if (family_code == ESP_UID_F236) {
esp->rev = FAS236;
- else if (family_code == 0x0a)
+ } else if (family_code == ESP_UID_HME) {
esp->rev = FASHME; /* Version is usually '5'. */
- else
+ } else if (family_code == ESP_UID_FSC) {
+ esp->rev = FSC;
+ /* Enable Active Negation */
+ esp_write8(ESP_CONFIG4_RADE, ESP_CFG4);
+ } else {
esp->rev = FAS100A;
+ }
esp->min_period = ((4 * esp->ccycle) / 1000);
} else {
esp->min_period = ((5 * esp->ccycle) / 1000);
@@ -304,11 +307,11 @@
case FASHME:
esp->config2 |= (ESP_CONFIG2_HME32 | ESP_CONFIG2_HMEFENAB);
- /* fallthrough... */
+ fallthrough;
case FAS236:
case PCSCSI:
- /* Fast 236, AM53c974 or HME */
+ case FSC:
esp_write8(esp->config2, ESP_CFG2);
if (esp->rev == FASHME) {
u8 cfg3 = esp->target[0].esp_config3;
@@ -1738,7 +1741,7 @@
case ESP_EVENT_DATA_IN:
write = 1;
- /* fallthru */
+ fallthrough;
case ESP_EVENT_DATA_OUT: {
struct esp_cmd_entry *ent = esp->active_cmd;
@@ -2373,10 +2376,11 @@
"ESP100A",
"ESP236",
"FAS236",
+ "AM53C974",
+ "53CF9x-2",
"FAS100A",
"FAST",
"FASHME",
- "AM53C974",
};
static struct scsi_transport_template *esp_transport_template;
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index 91b32f2..446a3d1 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -78,12 +78,14 @@
#define ESP_CONFIG3_IMS 0x80 /* ID msg chk'ng (esp/fas236) */
#define ESP_CONFIG3_OBPUSH 0x80 /* Push odd-byte to dma (hme) */
-/* ESP config register 4 read-write, found only on am53c974 chips */
-#define ESP_CONFIG4_RADE 0x04 /* Active negation */
-#define ESP_CONFIG4_RAE 0x08 /* Active negation on REQ and ACK */
-#define ESP_CONFIG4_PWD 0x20 /* Reduced power feature */
-#define ESP_CONFIG4_GE0 0x40 /* Glitch eater bit 0 */
-#define ESP_CONFIG4_GE1 0x80 /* Glitch eater bit 1 */
+/* ESP config register 4 read-write */
+#define ESP_CONFIG4_BBTE 0x01 /* Back-to-back transfers (fsc) */
+#define ESP_CONGIG4_TEST 0x02 /* Transfer counter test mode (fsc) */
+#define ESP_CONFIG4_RADE 0x04 /* Active negation (am53c974/fsc) */
+#define ESP_CONFIG4_RAE 0x08 /* Act. negation REQ/ACK (am53c974) */
+#define ESP_CONFIG4_PWD 0x20 /* Reduced power feature (am53c974) */
+#define ESP_CONFIG4_GE0 0x40 /* Glitch eater bit 0 (am53c974) */
+#define ESP_CONFIG4_GE1 0x80 /* Glitch eater bit 1 (am53c974) */
#define ESP_CONFIG_GE_12NS (0)
#define ESP_CONFIG_GE_25NS (ESP_CONFIG_GE1)
@@ -209,10 +211,15 @@
#define ESP_TEST_TS 0x04 /* Tristate test mode */
/* ESP unique ID register read-only, found on fas236+fas100a only */
+#define ESP_UID_FAM 0xf8 /* ESP family bitmask */
+
+#define ESP_FAMILY(uid) (((uid) & ESP_UID_FAM) >> 3)
+
+/* Values for the ESP family bits */
#define ESP_UID_F100A 0x00 /* ESP FAS100A */
#define ESP_UID_F236 0x02 /* ESP FAS236 */
-#define ESP_UID_REV 0x07 /* ESP revision */
-#define ESP_UID_FAM 0xf8 /* ESP family */
+#define ESP_UID_HME 0x0a /* FAS HME */
+#define ESP_UID_FSC 0x14 /* NCR/Symbios Logic 53CF9x-2 */
/* ESP fifo flags register read-only */
/* Note that the following implies a 16 byte FIFO on the ESP. */
@@ -257,15 +264,17 @@
};
#define ESP_CMD_PRIV(CMD) ((struct esp_cmd_priv *)(&(CMD)->SCp))
+/* NOTE: this enum is ordered based on chip features! */
enum esp_rev {
- ESP100 = 0x00, /* NCR53C90 - very broken */
- ESP100A = 0x01, /* NCR53C90A */
- ESP236 = 0x02,
- FAS236 = 0x03,
- FAS100A = 0x04,
- FAST = 0x05,
- FASHME = 0x06,
- PCSCSI = 0x07, /* AM53c974 */
+ ESP100, /* NCR53C90 - very broken */
+ ESP100A, /* NCR53C90A */
+ ESP236,
+ FAS236,
+ PCSCSI, /* AM53c974 */
+ FSC, /* NCR/Symbios Logic 53CF9x-2 */
+ FAS100A,
+ FAST,
+ FASHME,
};
struct esp_cmd_entry {
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 25dae9f..0f92749 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -645,7 +645,7 @@
return 0;
}
-/**
+/*
* fcoe_netdev_features_change - Updates the lport's offload flags based
* on the LLD netdev's FCoE feature flags
*/
@@ -1915,7 +1915,7 @@
case FCOE_CTLR_ENABLED:
case FCOE_CTLR_UNUSED:
fcoe_ctlr_link_up(ctlr);
- };
+ }
} else if (fcoe_ctlr_link_down(ctlr)) {
switch (cdev->enabled) {
case FCOE_CTLR_DISABLED:
@@ -1927,7 +1927,7 @@
stats->LinkFailureCount++;
put_cpu();
fcoe_clean_pending_queue(lport);
- };
+ }
}
out:
return rc;
@@ -2029,7 +2029,7 @@
/**
* fcoe_ctlr_mode() - Switch FIP mode
- * @cdev: The FCoE Controller that is being modified
+ * @ctlr_dev: The FCoE Controller that is being modified
*
* When the FIP mode has been changed we need to update
* the multicast addresses to ensure we get the correct
@@ -2136,9 +2136,7 @@
/**
* fcoe_dcb_create() - Initialize DCB attributes and hooks
- * @netdev: The net_device object of the L2 link that should be queried
- * @port: The fcoe_port to bind FCoE APP priority with
- * @
+ * @fcoe: The new FCoE interface
*/
static void fcoe_dcb_create(struct fcoe_interface *fcoe)
{
@@ -2609,7 +2607,7 @@
fc_lport_logo_resp(seq, fp, lport);
}
-/**
+/*
* fcoe_elsct_send - FCoE specific ELS handler
*
* This does special case handling of FIP encapsualted ELS exchanges for FCoE,
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 07a0dad..5ea426e 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -134,6 +134,7 @@
/**
* fcoe_ctlr_init() - Initialize the FCoE Controller instance
* @fip: The FCoE controller to initialize
+ * @mode: FIP mode to set
*/
void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_mode mode)
{
@@ -336,7 +337,7 @@
printk(KERN_NOTICE "libfcoe: host%d: "
"FIP Fibre-Channel Forwarder MAC %pM deselected\n",
fip->lp->host->host_no, fip->dest_addr);
- memset(fip->dest_addr, 0, ETH_ALEN);
+ eth_zero_addr(fip->dest_addr);
}
if (sel) {
printk(KERN_INFO "libfcoe: host%d: FIP selected "
@@ -449,10 +450,10 @@
switch (fip->mode) {
default:
LIBFCOE_FIP_DBG(fip, "invalid mode %d\n", fip->mode);
- /* fall-through */
+ fallthrough;
case FIP_MODE_AUTO:
LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n");
- /* fall-through */
+ fallthrough;
case FIP_MODE_FABRIC:
case FIP_MODE_NON_FIP:
mutex_unlock(&fip->ctlr_mutex);
@@ -587,6 +588,7 @@
/**
* fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it
* @fip: The FCoE controller for the ELS frame
+ * @lport: The local port
* @dtype: The FIP descriptor type for the frame
* @skb: The FCoE ELS frame including FC header but no FCoE headers
* @d_id: The destination port ID.
@@ -771,7 +773,7 @@
fc_fcoe_set_mac(mac, fh->fh_d_id);
fip->update_mac(lport, mac);
}
- /* fall through */
+ fallthrough;
case ELS_LS_RJT:
op = fr_encaps(fp);
if (op)
@@ -1302,7 +1304,7 @@
/**
* fcoe_ctlr_recv_els() - Handle an incoming link reset frame
* @fip: The FCoE controller that received the frame
- * @fh: The received FIP header
+ * @skb: The received FIP packet
*
* There may be multiple VN_Port descriptors.
* The overall length has already been checked.
@@ -1775,7 +1777,7 @@
/**
* fcoe_ctlr_timeout() - FIP timeout handler
- * @arg: The FCoE controller that timed out
+ * @t: Timer context use to obtain the controller reference
*/
static void fcoe_ctlr_timeout(struct timer_list *t)
{
@@ -1887,6 +1889,7 @@
/**
* fcoe_ctlr_recv_flogi() - Snoop pre-FIP receipt of FLOGI response
* @fip: The FCoE controller
+ * @lport: The local port
* @fp: The FC frame to snoop
*
* Snoop potential response to FLOGI or even incoming FLOGI.
@@ -2158,7 +2161,7 @@
/**
* fcoe_ctlr_disc_stop_locked() - stop discovery in VN2VN mode
- * @fip: The FCoE controller
+ * @lport: The local port
*
* Called with ctlr_mutex held.
*/
@@ -2179,7 +2182,7 @@
/**
* fcoe_ctlr_disc_stop() - stop discovery in VN2VN mode
- * @fip: The FCoE controller
+ * @lport: The local port
*
* Called through the local port template for discovery.
* Called without the ctlr_mutex held.
@@ -2195,7 +2198,7 @@
/**
* fcoe_ctlr_disc_stop_final() - stop discovery for shutdown in VN2VN mode
- * @fip: The FCoE controller
+ * @lport: The local port
*
* Called through the local port template for discovery.
* Called without the ctlr_mutex held.
@@ -2262,7 +2265,7 @@
* fcoe_ctlr_vn_parse - parse probe request or response
* @fip: The FCoE controller
* @skb: incoming packet
- * @rdata: buffer for resulting parsed VN entry plus fcoe_rport
+ * @frport: parsed FCoE rport from the probe request
*
* Returns non-zero error number on error.
* Does not consume the packet.
@@ -2436,7 +2439,7 @@
frport->enode_mac, 0);
break;
}
- /* fall through */
+ fallthrough;
case FIP_ST_VNMP_START:
LIBFCOE_FIP_DBG(fip, "vn_probe_req: "
"restart VN2VN negotiation\n");
@@ -2793,7 +2796,7 @@
* fcoe_ctlr_vlan_parse - parse vlan discovery request or response
* @fip: The FCoE controller
* @skb: incoming packet
- * @rdata: buffer for resulting parsed VLAN entry plus fcoe_rport
+ * @frport: parsed FCoE rport from the probe request
*
* Returns non-zero error number on error.
* Does not consume the packet.
@@ -2892,7 +2895,6 @@
* @fip: The FCoE controller
* @sub: sub-opcode for vlan notification or vn2vn vlan notification
* @dest: The destination Ethernet MAC address
- * @min_len: minimum size of the Ethernet payload to be sent
*/
static void fcoe_ctlr_vlan_send(struct fcoe_ctlr *fip,
enum fip_vlan_subcode sub,
@@ -2969,9 +2971,8 @@
/**
* fcoe_ctlr_vlan_recv - vlan request receive handler for VN2VN mode.
- * @lport: The local port
- * @fp: The received frame
- *
+ * @fip: The FCoE controller
+ * @skb: The received FIP packet
*/
static int fcoe_ctlr_vlan_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
{
@@ -3015,9 +3016,8 @@
fc_frame_free(fp);
}
-/**
- * fcoe_ctlr_disc_recv - start discovery for VN2VN mode.
- * @fip: The FCoE controller
+/*
+ * fcoe_ctlr_disc_start - start discovery for VN2VN mode.
*
* This sets a flag indicating that remote ports should be created
* and started for the peers we discover. We use the disc_callback
diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
index 2cb7a8c..ffef2c8 100644
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -1053,16 +1053,10 @@
int __init fcoe_sysfs_setup(void)
{
- int error;
-
atomic_set(&ctlr_num, 0);
atomic_set(&fcf_num, 0);
- error = bus_register(&fcoe_bus_type);
- if (error)
- return error;
-
- return 0;
+ return bus_register(&fcoe_bus_type);
}
void __exit fcoe_sysfs_teardown(void)
diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c
index a20ddc3..6e187d0 100644
--- a/drivers/scsi/fcoe/fcoe_transport.c
+++ b/drivers/scsi/fcoe/fcoe_transport.c
@@ -382,6 +382,7 @@
/**
* fcoe_check_wait_queue() - Attempt to clear the transmit backlog
* @lport: The local port whose backlog is to be cleared
+ * @skb: The received FIP packet
*
* This empties the wait_queue, dequeues the head of the wait_queue queue
* and calls fcoe_start_io() for each packet. If all skb have been
@@ -439,7 +440,7 @@
/**
* fcoe_queue_timer() - The fcoe queue timer
- * @lport: The local port
+ * @t: Timer context use to obtain the FCoE port
*
* Calls fcoe_check_wait_queue on timeout
*/
@@ -672,6 +673,7 @@
/**
* fcoe_netdev_map_lookup - find the fcoe transport that matches the netdev on which
* it was created
+ * @netdev: The net device that the FCoE interface is on
*
* Returns : ptr to the fcoe transport that supports this netdev or NULL
* if not found.
diff --git a/drivers/scsi/fdomain.h b/drivers/scsi/fdomain.h
index 6f63fc6..93afcee 100644
--- a/drivers/scsi/fdomain.h
+++ b/drivers/scsi/fdomain.h
@@ -103,7 +103,7 @@
#define REG_FIFO_COUNT 14 /* R: FIFO Data Count */
#ifdef CONFIG_PM_SLEEP
-static const struct dev_pm_ops fdomain_pm_ops;
+static const struct dev_pm_ops __maybe_unused fdomain_pm_ops;
#define FDOMAIN_PM_OPS (&fdomain_pm_ops)
#else
#define FDOMAIN_PM_OPS NULL
diff --git a/drivers/scsi/fdomain_isa.c b/drivers/scsi/fdomain_isa.c
index f2da4fa..e0cdcd2 100644
--- a/drivers/scsi/fdomain_isa.c
+++ b/drivers/scsi/fdomain_isa.c
@@ -111,12 +111,11 @@
base = readb(p + sig->base_offset) +
(readb(p + sig->base_offset + 1) << 8);
iounmap(p);
- if (base)
+ if (base) {
dev_info(dev, "BIOS at 0x%lx specifies I/O base 0x%x\n",
bios_base, base);
- else
+ } else { /* no I/O base in BIOS area */
dev_info(dev, "BIOS at 0x%lx\n", bios_base);
- if (!base) { /* no I/O base in BIOS area */
/* save BIOS signature for later use in port probing */
saved_sig = sig;
return 0;
diff --git a/drivers/scsi/fnic/fnic_debugfs.c b/drivers/scsi/fnic/fnic_debugfs.c
index 13f7d88..6c04936 100644
--- a/drivers/scsi/fnic/fnic_debugfs.c
+++ b/drivers/scsi/fnic/fnic_debugfs.c
@@ -120,11 +120,11 @@
len = 0;
trace_type = (u8 *)filp->private_data;
if (*trace_type == fc_trc_flag->fnic_trace)
- len = sprintf(buf, "%u\n", fnic_tracing_enabled);
+ len = sprintf(buf, "%d\n", fnic_tracing_enabled);
else if (*trace_type == fc_trc_flag->fc_trace)
- len = sprintf(buf, "%u\n", fnic_fc_tracing_enabled);
+ len = sprintf(buf, "%d\n", fnic_fc_tracing_enabled);
else if (*trace_type == fc_trc_flag->fc_clear)
- len = sprintf(buf, "%u\n", fnic_fc_trace_cleared);
+ len = sprintf(buf, "%d\n", fnic_fc_trace_cleared);
else
pr_err("fnic: Cannot read to any debugfs file\n");
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index 673887e..e3384af 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -309,12 +309,10 @@
struct fc_frame_header *fh = NULL;
struct fip_desc *desc;
struct fip_encaps *els;
- enum fip_desc_type els_dtype = 0;
u16 op;
u8 els_op;
u8 sub;
- size_t els_len = 0;
size_t rlen;
size_t dlen = 0;
@@ -346,10 +344,8 @@
if (dlen < sizeof(*els) + sizeof(*fh) + 1)
return 0;
- els_len = dlen - sizeof(*els);
els = (struct fip_encaps *)desc;
fh = (struct fc_frame_header *)(els + 1);
- els_dtype = desc->fip_dtype;
if (!fh)
return 0;
@@ -376,7 +372,6 @@
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
struct sk_buff *skb;
char *eth_fr;
- int fr_len;
struct fip_vlan *vlan;
u64 vlan_tov;
@@ -391,7 +386,6 @@
if (!skb)
return;
- fr_len = sizeof(*vlan);
eth_fr = (char *)skb->data;
vlan = (struct fip_vlan *)eth_fr;
@@ -837,7 +831,6 @@
struct sk_buff *skb;
struct fc_frame *fp;
struct fnic_stats *fnic_stats = &fnic->fnic_stats;
- unsigned int eth_hdrs_stripped;
u8 type, color, eop, sop, ingress_port, vlan_stripped;
u8 fcoe = 0, fcoe_sof, fcoe_eof;
u8 fcoe_fc_crc_ok = 1, fcoe_enc_error = 0;
@@ -867,7 +860,6 @@
&ingress_port, &packet_error,
&fcoe_enc_error, &fcs_ok, &vlan_stripped,
&vlan);
- eth_hdrs_stripped = 1;
skb_trim(skb, fcp_bytes_written);
fr_sof(fp) = sof;
fr_eof(fp) = eof;
@@ -884,7 +876,6 @@
&tcp_udp_csum_ok, &udp, &tcp,
&ipv4_csum_ok, &ipv6, &ipv4,
&ipv4_fragment, &fcs_ok);
- eth_hdrs_stripped = 0;
skb_trim(skb, bytes_written);
if (!fcs_ok) {
atomic64_inc(&fnic_stats->misc_stats.frame_errors);
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c
index 3a2618b..4f7befb 100644
--- a/drivers/scsi/fnic/fnic_main.c
+++ b/drivers/scsi/fnic/fnic_main.c
@@ -49,8 +49,8 @@
static struct kmem_cache *fnic_sgl_cache[FNIC_SGL_NUM_CACHES];
static struct kmem_cache *fnic_io_req_cache;
-LIST_HEAD(fnic_list);
-DEFINE_SPINLOCK(fnic_list_lock);
+static LIST_HEAD(fnic_list);
+static DEFINE_SPINLOCK(fnic_list_lock);
/* Supported devices by fnic module */
static struct pci_device_id fnic_id_table[] = {
@@ -443,7 +443,7 @@
default:
/* Using intr for notification for INTx/MSI-X */
break;
- };
+ }
}
static int fnic_dev_wait(struct vnic_dev *vdev,
@@ -552,8 +552,7 @@
static void fnic_set_vlan(struct fnic *fnic, u16 vlan_id)
{
- u16 old_vlan;
- old_vlan = vnic_dev_set_default_vlan(fnic->vdev, vlan_id);
+ vnic_dev_set_default_vlan(fnic->vdev, vlan_id);
}
static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index b607958..d1f7b84 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -23,6 +23,7 @@
#include <linux/scatterlist.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
+#include <linux/etherdevice.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/delay.h>
@@ -275,7 +276,7 @@
}
if (fnic->ctlr.map_dest) {
- memset(gw_mac, 0xff, ETH_ALEN);
+ eth_broadcast_addr(gw_mac);
format = FCPIO_FLOGI_REG_DEF_DEST;
} else {
memcpy(gw_mac, fnic->ctlr.dest_addr, ETH_ALEN);
@@ -1401,7 +1402,7 @@
}
if (!io_req) {
spin_unlock_irqrestore(io_lock, flags);
- goto cleanup_scsi_cmd;
+ continue;
}
CMD_SP(sc) = NULL;
@@ -1416,7 +1417,6 @@
fnic_release_ioreq_buf(fnic, io_req, sc);
mempool_free(io_req, fnic->io_req_pool);
-cleanup_scsi_cmd:
sc->result = DID_TRANSPORT_DISRUPTED << 16;
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
"%s: tag:0x%x : sc:0x%p duration = %lu DID_TRANSPORT_DISRUPTED\n",
@@ -2624,8 +2624,8 @@
unsigned long flags;
spin_lock_irqsave(&fnic->fnic_lock, flags);
- if (fnic->internal_reset_inprogress == 0) {
- fnic->internal_reset_inprogress = 1;
+ if (!fnic->internal_reset_inprogress) {
+ fnic->internal_reset_inprogress = true;
} else {
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
@@ -2654,7 +2654,7 @@
}
spin_lock_irqsave(&fnic->fnic_lock, flags);
- fnic->internal_reset_inprogress = 0;
+ fnic->internal_reset_inprogress = false;
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
return ret;
}
diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c
index a0d01ae..9d52d83 100644
--- a/drivers/scsi/fnic/fnic_trace.c
+++ b/drivers/scsi/fnic/fnic_trace.c
@@ -138,7 +138,7 @@
* Dump trace buffer entry to memory file
* and increment read index @rd_idx
*/
- len += snprintf(fnic_dbgfs_prt->buffer + len,
+ len += scnprintf(fnic_dbgfs_prt->buffer + len,
(trace_max_pages * PAGE_SIZE * 3) - len,
"%16llu.%09lu %-50s %8x %8x %16llx %16llx "
"%16llx %16llx %16llx\n", (u64)val.tv_sec,
@@ -180,7 +180,7 @@
* Dump trace buffer entry to memory file
* and increment read index @rd_idx
*/
- len += snprintf(fnic_dbgfs_prt->buffer + len,
+ len += scnprintf(fnic_dbgfs_prt->buffer + len,
(trace_max_pages * PAGE_SIZE * 3) - len,
"%16llu.%09lu %-50s %8x %8x %16llx %16llx "
"%16llx %16llx %16llx\n", (u64)val.tv_sec,
@@ -220,12 +220,12 @@
struct timespec64 val1, val2;
ktime_get_real_ts64(&val1);
- len = snprintf(debug->debug_buffer + len, buf_size - len,
+ len = scnprintf(debug->debug_buffer + len, buf_size - len,
"------------------------------------------\n"
"\t\tTime\n"
"------------------------------------------\n");
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"Current time : [%lld:%ld]\n"
"Last stats reset time: [%lld:%09ld]\n"
"Last stats read time: [%lld:%ld]\n"
@@ -243,11 +243,11 @@
stats->stats_timestamps.last_read_time = val1;
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"------------------------------------------\n"
"\t\tIO Statistics\n"
"------------------------------------------\n");
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"Number of Active IOs: %lld\nMaximum Active IOs: %lld\n"
"Number of IOs: %lld\nNumber of IO Completions: %lld\n"
"Number of IO Failures: %lld\nNumber of IO NOT Found: %lld\n"
@@ -280,16 +280,16 @@
(u64)atomic64_read(&stats->io_stats.io_btw_10000_to_30000_msec),
(u64)atomic64_read(&stats->io_stats.io_greater_than_30000_msec));
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"\nCurrent Max IO time : %lld\n",
(u64)atomic64_read(&stats->io_stats.current_max_io_time));
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"\n------------------------------------------\n"
"\t\tAbort Statistics\n"
"------------------------------------------\n");
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"Number of Aborts: %lld\n"
"Number of Abort Failures: %lld\n"
"Number of Abort Driver Timeouts: %lld\n"
@@ -318,12 +318,12 @@
(u64)atomic64_read(&stats->abts_stats.abort_issued_btw_50_to_60_sec),
(u64)atomic64_read(&stats->abts_stats.abort_issued_greater_than_60_sec));
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"\n------------------------------------------\n"
"\t\tTerminate Statistics\n"
"------------------------------------------\n");
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"Number of Terminates: %lld\n"
"Maximum Terminates: %lld\n"
"Number of Terminate Driver Timeouts: %lld\n"
@@ -337,12 +337,12 @@
(u64)atomic64_read(&stats->term_stats.terminate_io_not_found),
(u64)atomic64_read(&stats->term_stats.terminate_failures));
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"\n------------------------------------------\n"
"\t\tReset Statistics\n"
"------------------------------------------\n");
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"Number of Device Resets: %lld\n"
"Number of Device Reset Failures: %lld\n"
"Number of Device Reset Aborts: %lld\n"
@@ -368,12 +368,12 @@
&stats->reset_stats.fnic_reset_completions),
(u64)atomic64_read(&stats->reset_stats.fnic_reset_failures));
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"\n------------------------------------------\n"
"\t\tFirmware Statistics\n"
"------------------------------------------\n");
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"Number of Active FW Requests %lld\n"
"Maximum FW Requests: %lld\n"
"Number of FW out of resources: %lld\n"
@@ -383,12 +383,12 @@
(u64)atomic64_read(&stats->fw_stats.fw_out_of_resources),
(u64)atomic64_read(&stats->fw_stats.io_fw_errs));
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"\n------------------------------------------\n"
"\t\tVlan Discovery Statistics\n"
"------------------------------------------\n");
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"Number of Vlan Discovery Requests Sent %lld\n"
"Vlan Response Received with no FCF VLAN ID: %lld\n"
"No solicitations recvd after vlan set, expiry count: %lld\n"
@@ -398,7 +398,7 @@
(u64)atomic64_read(&stats->vlan_stats.sol_expiry_count),
(u64)atomic64_read(&stats->vlan_stats.flogi_rejects));
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"\n------------------------------------------\n"
"\t\tOther Important Statistics\n"
"------------------------------------------\n");
@@ -406,7 +406,7 @@
jiffies_to_timespec64(stats->misc_stats.last_isr_time, &val1);
jiffies_to_timespec64(stats->misc_stats.last_ack_time, &val2);
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"Last ISR time: %llu (%8llu.%09lu)\n"
"Last ACK time: %llu (%8llu.%09lu)\n"
"Max ISR jiffies: %llu\n"
@@ -452,7 +452,7 @@
(u64)atomic64_read(&stats->misc_stats.rport_not_ready),
(u64)atomic64_read(&stats->misc_stats.frame_errors));
- len += snprintf(debug->debug_buffer + len, buf_size - len,
+ len += scnprintf(debug->debug_buffer + len, buf_size - len,
"Firmware reported port speed: %llu\n",
(u64)atomic64_read(
&stats->misc_stats.current_port_speed));
@@ -742,7 +742,7 @@
rd_idx = fc_trace_entries.rd_idx;
wr_idx = fc_trace_entries.wr_idx;
if (rdata_flag == 0) {
- len += snprintf(fnic_dbgfs_prt->buffer + len,
+ len += scnprintf(fnic_dbgfs_prt->buffer + len,
(fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len,
"Time Stamp (UTC)\t\t"
"Host No: F Type: len: FCoE_FRAME:\n");
@@ -762,11 +762,11 @@
} else {
fc_trace = (char *)tdata;
for (j = 0; j < FC_TRC_SIZE_BYTES; j++) {
- len += snprintf(fnic_dbgfs_prt->buffer + len,
+ len += scnprintf(fnic_dbgfs_prt->buffer + len,
(fnic_fc_trace_max_pages * PAGE_SIZE * 3)
- len, "%02x", fc_trace[j] & 0xff);
} /* for loop */
- len += snprintf(fnic_dbgfs_prt->buffer + len,
+ len += scnprintf(fnic_dbgfs_prt->buffer + len,
(fnic_fc_trace_max_pages * PAGE_SIZE * 3) - len,
"\n");
}
@@ -810,7 +810,7 @@
time64_to_tm(tdata->time_stamp.tv_sec, 0, &tm);
fmt = "%02d:%02d:%04ld %02d:%02d:%02d.%09lu ns%8x %c%8x\t";
- len += snprintf(fnic_dbgfs_prt->buffer + len,
+ len += scnprintf(fnic_dbgfs_prt->buffer + len,
max_size - len,
fmt,
tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900,
@@ -823,25 +823,25 @@
for (j = 0; j < min_t(u8, tdata->frame_len,
(u8)(FC_TRC_SIZE_BYTES - FC_TRC_HEADER_SIZE)); j++) {
if (tdata->frame_type == FNIC_FC_LE) {
- len += snprintf(fnic_dbgfs_prt->buffer + len,
+ len += scnprintf(fnic_dbgfs_prt->buffer + len,
max_size - len, "%c", fc_trace[j]);
} else {
- len += snprintf(fnic_dbgfs_prt->buffer + len,
+ len += scnprintf(fnic_dbgfs_prt->buffer + len,
max_size - len, "%02x", fc_trace[j] & 0xff);
- len += snprintf(fnic_dbgfs_prt->buffer + len,
+ len += scnprintf(fnic_dbgfs_prt->buffer + len,
max_size - len, " ");
if (j == ethhdr_len ||
j == ethhdr_len + fcoehdr_len ||
j == ethhdr_len + fcoehdr_len + fchdr_len ||
(i > 3 && j%fchdr_len == 0)) {
- len += snprintf(fnic_dbgfs_prt->buffer
+ len += scnprintf(fnic_dbgfs_prt->buffer
+ len, max_size - len,
"\n\t\t\t\t\t\t\t\t");
i++;
}
} /* end of else*/
} /* End of for loop*/
- len += snprintf(fnic_dbgfs_prt->buffer + len,
+ len += scnprintf(fnic_dbgfs_prt->buffer + len,
max_size - len, "\n");
*orig_len = len;
}
diff --git a/drivers/scsi/fnic/vnic_dev.c b/drivers/scsi/fnic/vnic_dev.c
index c8bf8c7..5988c30 100644
--- a/drivers/scsi/fnic/vnic_dev.c
+++ b/drivers/scsi/fnic/vnic_dev.c
@@ -254,12 +254,12 @@
}
}
-int vnic_dev_cmd1(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, int wait)
+static int vnic_dev_cmd1(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, int wait)
{
struct vnic_devcmd __iomem *devcmd = vdev->devcmd;
int delay;
u32 status;
- int dev_cmd_err[] = {
+ static const int dev_cmd_err[] = {
/* convert from fw's version of error.h to host's version */
0, /* ERR_SUCCESS */
EINVAL, /* ERR_EINVAL */
@@ -316,7 +316,7 @@
return -ETIMEDOUT;
}
-int vnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
+static int vnic_dev_cmd2(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
int wait)
{
struct devcmd2_controller *dc2c = vdev->devcmd2;
@@ -411,7 +411,7 @@
}
-int vnic_dev_init_devcmd1(struct vnic_dev *vdev)
+static int vnic_dev_init_devcmd1(struct vnic_dev *vdev)
{
vdev->devcmd = vnic_dev_get_res(vdev, RES_TYPE_DEVCMD, 0);
if (!vdev->devcmd)
@@ -422,7 +422,7 @@
}
-int vnic_dev_init_devcmd2(struct vnic_dev *vdev)
+static int vnic_dev_init_devcmd2(struct vnic_dev *vdev)
{
int err;
unsigned int fetch_index;
@@ -494,7 +494,7 @@
}
-void vnic_dev_deinit_devcmd2(struct vnic_dev *vdev)
+static void vnic_dev_deinit_devcmd2(struct vnic_dev *vdev)
{
vnic_dev_free_desc_ring(vdev, &vdev->devcmd2->results_ring);
vnic_wq_disable(&vdev->devcmd2->wq);
@@ -505,7 +505,7 @@
}
-int vnic_dev_cmd_no_proxy(struct vnic_dev *vdev,
+static int vnic_dev_cmd_no_proxy(struct vnic_dev *vdev,
enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait)
{
int err;
diff --git a/drivers/scsi/fnic/vnic_devcmd.h b/drivers/scsi/fnic/vnic_devcmd.h
index c5dde55..c20d30e 100644
--- a/drivers/scsi/fnic/vnic_devcmd.h
+++ b/drivers/scsi/fnic/vnic_devcmd.h
@@ -442,7 +442,7 @@
struct vnic_devcmd_provinfo {
u8 oui[3];
u8 type;
- u8 data[0];
+ u8 data[];
};
/*
diff --git a/drivers/scsi/fnic/vnic_wq.c b/drivers/scsi/fnic/vnic_wq.c
index 015af2c..442972c 100644
--- a/drivers/scsi/fnic/vnic_wq.c
+++ b/drivers/scsi/fnic/vnic_wq.c
@@ -25,7 +25,7 @@
#include "vnic_wq.h"
-int vnic_wq_get_ctrl(struct vnic_dev *vdev, struct vnic_wq *wq,
+static int vnic_wq_get_ctrl(struct vnic_dev *vdev, struct vnic_wq *wq,
unsigned int index, enum vnic_res_type res_type)
{
wq->ctrl = vnic_dev_get_res(vdev, res_type, index);
@@ -37,7 +37,7 @@
}
-int vnic_wq_alloc_ring(struct vnic_dev *vdev, struct vnic_wq *wq,
+static int vnic_wq_alloc_ring(struct vnic_dev *vdev, struct vnic_wq *wq,
unsigned int desc_count, unsigned int desc_size)
{
return vnic_dev_alloc_desc_ring(vdev, &wq->ring, desc_count, desc_size);
diff --git a/drivers/scsi/fnic/vnic_wq_copy.c b/drivers/scsi/fnic/vnic_wq_copy.c
index 9eab7e7..7b18635 100644
--- a/drivers/scsi/fnic/vnic_wq_copy.c
+++ b/drivers/scsi/fnic/vnic_wq_copy.c
@@ -79,8 +79,6 @@
unsigned int index, unsigned int desc_count,
unsigned int desc_size)
{
- int err;
-
wq->index = index;
wq->vdev = vdev;
wq->to_use_index = wq->to_clean_index = 0;
@@ -92,11 +90,7 @@
vnic_wq_copy_disable(wq);
- err = vnic_dev_alloc_desc_ring(vdev, &wq->ring, desc_count, desc_size);
- if (err)
- return err;
-
- return 0;
+ return vnic_dev_alloc_desc_ring(vdev, &wq->ring, desc_count, desc_size);
}
void vnic_wq_copy_init(struct vnic_wq_copy *wq, unsigned int cq_index,
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 2ab774e..29e4cdc 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -20,7 +20,7 @@
* Added ISAPNP support for DTC436 adapters,
* Thomas Sailer, sailer@ife.ee.ethz.ch
*
- * See Documentation/scsi/g_NCR5380.txt for more info.
+ * See Documentation/scsi/g_NCR5380.rst for more info.
*/
#include <asm/io.h>
@@ -340,7 +340,7 @@
break;
case BOARD_DTC3181E:
hostdata->io_width = 2; /* 16-bit PDMA */
- /* fall through */
+ fallthrough;
case BOARD_NCR53C400A:
case BOARD_HP_C2502:
hostdata->c400_ctl_status = 9;
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index fe03410..5d80138 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -329,8 +329,8 @@
scp->scsi_done(scp);
}
-int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
- int timeout, u32 *info)
+static int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd,
+ char *cmnd, int timeout, u32 *info)
{
gdth_ha_str *ha = shost_priv(sdev->host);
struct scsi_cmnd *scp;
@@ -3007,7 +3007,6 @@
static int gdth_async_event(gdth_ha_str *ha)
{
gdth_cmd_str *cmdp;
- int cmd_index;
cmdp= ha->pccb;
TRACE2(("gdth_async_event() ha %d serv %d\n",
@@ -3019,7 +3018,6 @@
gdth_delay(0);
cmdp->Service = SCREENSERVICE;
cmdp->RequestBuffer = SCREEN_CMND;
- cmd_index = gdth_get_cmd_index(ha);
gdth_set_sema0(ha);
cmdp->OpCode = GDT_READ;
cmdp->BoardNode = LOCALBOARD;
@@ -3170,81 +3168,6 @@
}
#endif
-static void __init internal_setup(char *str,int *ints)
-{
- int i;
- char *cur_str, *argv;
-
- TRACE2(("internal_setup() str %s ints[0] %d\n",
- str ? str:"NULL", ints ? ints[0]:0));
-
- /* analyse string */
- argv = str;
- while (argv && (cur_str = strchr(argv, ':'))) {
- int val = 0, c = *++cur_str;
-
- if (c == 'n' || c == 'N')
- val = 0;
- else if (c == 'y' || c == 'Y')
- val = 1;
- else
- val = (int)simple_strtoul(cur_str, NULL, 0);
-
- if (!strncmp(argv, "disable:", 8))
- disable = val;
- else if (!strncmp(argv, "reserve_mode:", 13))
- reserve_mode = val;
- else if (!strncmp(argv, "reverse_scan:", 13))
- reverse_scan = val;
- else if (!strncmp(argv, "hdr_channel:", 12))
- hdr_channel = val;
- else if (!strncmp(argv, "max_ids:", 8))
- max_ids = val;
- else if (!strncmp(argv, "rescan:", 7))
- rescan = val;
- else if (!strncmp(argv, "shared_access:", 14))
- shared_access = val;
- else if (!strncmp(argv, "reserve_list:", 13)) {
- reserve_list[0] = val;
- for (i = 1; i < MAX_RES_ARGS; i++) {
- cur_str = strchr(cur_str, ',');
- if (!cur_str)
- break;
- if (!isdigit((int)*++cur_str)) {
- --cur_str;
- break;
- }
- reserve_list[i] =
- (int)simple_strtoul(cur_str, NULL, 0);
- }
- if (!cur_str)
- break;
- argv = ++cur_str;
- continue;
- }
-
- if ((argv = strchr(argv, ',')))
- ++argv;
- }
-}
-
-int __init option_setup(char *str)
-{
- int ints[MAXHA];
- char *cur = str;
- int i = 1;
-
- TRACE2(("option_setup() str %s\n", str ? str:"NULL"));
-
- while (cur && isdigit(*cur) && i < MAXHA) {
- ints[i++] = simple_strtoul(cur, NULL, 0);
- if ((cur = strchr(cur, ',')) != NULL) cur++;
- }
-
- ints[0] = i - 1;
- internal_setup(cur, ints);
- return 1;
-}
static const char *gdth_ctr_name(gdth_ha_str *ha)
{
@@ -4319,5 +4242,81 @@
module_exit(gdth_exit);
#ifndef MODULE
+static void __init internal_setup(char *str,int *ints)
+{
+ int i;
+ char *cur_str, *argv;
+
+ TRACE2(("internal_setup() str %s ints[0] %d\n",
+ str ? str:"NULL", ints ? ints[0]:0));
+
+ /* analyse string */
+ argv = str;
+ while (argv && (cur_str = strchr(argv, ':'))) {
+ int val = 0, c = *++cur_str;
+
+ if (c == 'n' || c == 'N')
+ val = 0;
+ else if (c == 'y' || c == 'Y')
+ val = 1;
+ else
+ val = (int)simple_strtoul(cur_str, NULL, 0);
+
+ if (!strncmp(argv, "disable:", 8))
+ disable = val;
+ else if (!strncmp(argv, "reserve_mode:", 13))
+ reserve_mode = val;
+ else if (!strncmp(argv, "reverse_scan:", 13))
+ reverse_scan = val;
+ else if (!strncmp(argv, "hdr_channel:", 12))
+ hdr_channel = val;
+ else if (!strncmp(argv, "max_ids:", 8))
+ max_ids = val;
+ else if (!strncmp(argv, "rescan:", 7))
+ rescan = val;
+ else if (!strncmp(argv, "shared_access:", 14))
+ shared_access = val;
+ else if (!strncmp(argv, "reserve_list:", 13)) {
+ reserve_list[0] = val;
+ for (i = 1; i < MAX_RES_ARGS; i++) {
+ cur_str = strchr(cur_str, ',');
+ if (!cur_str)
+ break;
+ if (!isdigit((int)*++cur_str)) {
+ --cur_str;
+ break;
+ }
+ reserve_list[i] =
+ (int)simple_strtoul(cur_str, NULL, 0);
+ }
+ if (!cur_str)
+ break;
+ argv = ++cur_str;
+ continue;
+ }
+
+ if ((argv = strchr(argv, ',')))
+ ++argv;
+ }
+}
+
+static int __init option_setup(char *str)
+{
+ int ints[MAXHA];
+ char *cur = str;
+ int i = 1;
+
+ TRACE2(("option_setup() str %s\n", str ? str:"NULL"));
+
+ while (cur && isdigit(*cur) && i < MAXHA) {
+ ints[i++] = simple_strtoul(cur, NULL, 0);
+ if ((cur = strchr(cur, ',')) != NULL) cur++;
+ }
+
+ ints[0] = i - 1;
+ internal_setup(cur, ints);
+ return 1;
+}
+
__setup("gdth=", option_setup);
#endif
diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
index 381d849..c764312 100644
--- a/drivers/scsi/gdth_proc.c
+++ b/drivers/scsi/gdth_proc.c
@@ -193,7 +193,7 @@
for (i = 1; i < MAX_RES_ARGS; i++) {
if (reserve_list[i] == 0xff)
break;
- hlen += snprintf(hrec + hlen , 161 - hlen, ",%d", reserve_list[i]);
+ hlen += scnprintf(hrec + hlen, 161 - hlen, ",%d", reserve_list[i]);
}
}
seq_printf(m,
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
index 11df0ec..727f8c8 100644
--- a/drivers/scsi/gvp11.c
+++ b/drivers/scsi/gvp11.c
@@ -9,7 +9,6 @@
#include <linux/module.h>
#include <asm/page.h>
-#include <asm/pgtable.h>
#include <asm/amigaints.h>
#include <asm/amigahw.h>
diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig
index 90a1745..b8148b1 100644
--- a/drivers/scsi/hisi_sas/Kconfig
+++ b/drivers/scsi/hisi_sas/Kconfig
@@ -6,6 +6,7 @@
select SCSI_SAS_LIBSAS
select BLK_DEV_INTEGRITY
depends on ATA
+ select SATA_HOST
help
This driver supports HiSilicon's SAS HBA, including support based
on platform device
@@ -14,5 +15,6 @@
tristate "HiSilicon SAS on PCI bus"
depends on SCSI_HISI_SAS
depends on PCI
+ depends on ACPI
help
This driver supports HiSilicon's SAS HBA based on PCI device
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 720c4d6..a25cfc1 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -8,6 +8,8 @@
#define _HISI_SAS_H_
#include <linux/acpi.h>
+#include <linux/blk-mq.h>
+#include <linux/blk-mq-pci.h>
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/dmapool.h>
@@ -19,8 +21,10 @@
#include <linux/of_address.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regmap.h>
+#include <linux/timer.h>
#include <scsi/sas_ata.h>
#include <scsi/libsas.h>
@@ -31,6 +35,7 @@
#define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES
#define HISI_SAS_RESET_BIT 0
#define HISI_SAS_REJECT_CMD_BIT 1
+#define HISI_SAS_PM_BIT 2
#define HISI_SAS_MAX_COMMANDS (HISI_SAS_QUEUE_SLOTS)
#define HISI_SAS_RESERVED_IPTT 96
#define HISI_SAS_UNRESERVED_IPTT \
@@ -84,6 +89,7 @@
#define HISI_SAS_PROT_MASK (HISI_SAS_DIF_PROT_MASK | HISI_SAS_DIX_PROT_MASK)
#define HISI_SAS_WAIT_PHYUP_TIMEOUT 20
+#define CLEAR_ITCT_TIMEOUT 20
struct hisi_hba;
@@ -167,6 +173,7 @@
enum sas_linkrate minimum_linkrate;
enum sas_linkrate maximum_linkrate;
int enable;
+ atomic_t down_cnt;
};
struct hisi_sas_port {
@@ -177,10 +184,10 @@
struct hisi_sas_cq {
struct hisi_hba *hisi_hba;
- const struct cpumask *pci_irq_mask;
- struct tasklet_struct tasklet;
+ const struct cpumask *irq_mask;
int rd_point;
int id;
+ int irq_no;
};
struct hisi_sas_dq {
@@ -270,6 +277,39 @@
HISI_SAS_IOST_CACHE,
};
+enum hisi_sas_debugfs_bist_ffe_cfg {
+ FFE_SAS_1_5_GBPS,
+ FFE_SAS_3_0_GBPS,
+ FFE_SAS_6_0_GBPS,
+ FFE_SAS_12_0_GBPS,
+ FFE_RESV,
+ FFE_SATA_1_5_GBPS,
+ FFE_SATA_3_0_GBPS,
+ FFE_SATA_6_0_GBPS,
+ FFE_CFG_MAX
+};
+
+enum hisi_sas_debugfs_bist_fixed_code {
+ FIXED_CODE,
+ FIXED_CODE_1,
+ FIXED_CODE_MAX
+};
+
+enum {
+ HISI_SAS_BIST_CODE_MODE_PRBS7,
+ HISI_SAS_BIST_CODE_MODE_PRBS23,
+ HISI_SAS_BIST_CODE_MODE_PRBS31,
+ HISI_SAS_BIST_CODE_MODE_JTPAT,
+ HISI_SAS_BIST_CODE_MODE_CJTPAT,
+ HISI_SAS_BIST_CODE_MODE_SCRAMBED_0,
+ HISI_SAS_BIST_CODE_MODE_TRAIN,
+ HISI_SAS_BIST_CODE_MODE_TRAIN_DONE,
+ HISI_SAS_BIST_CODE_MODE_HFTP,
+ HISI_SAS_BIST_CODE_MODE_MFTP,
+ HISI_SAS_BIST_CODE_MODE_LFTP,
+ HISI_SAS_BIST_CODE_MODE_FIXED_DATA,
+};
+
struct hisi_sas_hw {
int (*hw_init)(struct hisi_hba *hisi_hba);
void (*setup_itct)(struct hisi_hba *hisi_hba,
@@ -296,8 +336,8 @@
void (*phy_set_linkrate)(struct hisi_hba *hisi_hba, int phy_no,
struct sas_phy_linkrates *linkrates);
enum sas_linkrate (*phy_get_max_linkrate)(void);
- void (*clear_itct)(struct hisi_hba *hisi_hba,
- struct hisi_sas_device *dev);
+ int (*clear_itct)(struct hisi_hba *hisi_hba,
+ struct hisi_sas_device *dev);
void (*free_device)(struct hisi_sas_device *sas_dev);
int (*get_wideport_bitmap)(struct hisi_hba *hisi_hba, int port_id);
void (*dereg_device)(struct hisi_hba *hisi_hba,
@@ -321,6 +361,44 @@
const struct hisi_sas_debugfs_reg *debugfs_reg_port;
};
+#define HISI_SAS_MAX_DEBUGFS_DUMP (50)
+
+struct hisi_sas_debugfs_cq {
+ struct hisi_sas_cq *cq;
+ void *complete_hdr;
+};
+
+struct hisi_sas_debugfs_dq {
+ struct hisi_sas_dq *dq;
+ struct hisi_sas_cmd_hdr *hdr;
+};
+
+struct hisi_sas_debugfs_regs {
+ struct hisi_hba *hisi_hba;
+ u32 *data;
+};
+
+struct hisi_sas_debugfs_port {
+ struct hisi_sas_phy *phy;
+ u32 *data;
+};
+
+struct hisi_sas_debugfs_iost {
+ struct hisi_sas_iost *iost;
+};
+
+struct hisi_sas_debugfs_itct {
+ struct hisi_sas_itct *itct;
+};
+
+struct hisi_sas_debugfs_iost_cache {
+ struct hisi_sas_iost_itct_cache *cache;
+};
+
+struct hisi_sas_debugfs_itct_cache {
+ struct hisi_sas_iost_itct_cache *cache;
+};
+
struct hisi_hba {
/* This must be the first element, used by SHOST_TO_SAS_HA */
struct sas_ha_struct *p;
@@ -390,7 +468,6 @@
u32 intr_coal_count; /* Interrupt count to coalesce */
int cq_nvecs;
- unsigned int *reply_map;
/* bist */
enum sas_linkrate debugfs_bist_linkrate;
@@ -399,22 +476,25 @@
int debugfs_bist_mode;
u32 debugfs_bist_cnt;
int debugfs_bist_enable;
+ u32 debugfs_bist_ffe[HISI_SAS_MAX_PHYS][FFE_CFG_MAX];
+ u32 debugfs_bist_fixed_code[FIXED_CODE_MAX];
/* debugfs memories */
/* Put Global AXI and RAS Register into register array */
- u32 *debugfs_regs[DEBUGFS_REGS_NUM];
- u32 *debugfs_port_reg[HISI_SAS_MAX_PHYS];
- void *debugfs_complete_hdr[HISI_SAS_MAX_QUEUES];
- struct hisi_sas_cmd_hdr *debugfs_cmd_hdr[HISI_SAS_MAX_QUEUES];
- struct hisi_sas_iost *debugfs_iost;
- struct hisi_sas_itct *debugfs_itct;
- u64 *debugfs_iost_cache;
- u64 *debugfs_itct_cache;
+ struct hisi_sas_debugfs_regs debugfs_regs[HISI_SAS_MAX_DEBUGFS_DUMP][DEBUGFS_REGS_NUM];
+ struct hisi_sas_debugfs_port debugfs_port_reg[HISI_SAS_MAX_DEBUGFS_DUMP][HISI_SAS_MAX_PHYS];
+ struct hisi_sas_debugfs_cq debugfs_cq[HISI_SAS_MAX_DEBUGFS_DUMP][HISI_SAS_MAX_QUEUES];
+ struct hisi_sas_debugfs_dq debugfs_dq[HISI_SAS_MAX_DEBUGFS_DUMP][HISI_SAS_MAX_QUEUES];
+ struct hisi_sas_debugfs_iost debugfs_iost[HISI_SAS_MAX_DEBUGFS_DUMP];
+ struct hisi_sas_debugfs_itct debugfs_itct[HISI_SAS_MAX_DEBUGFS_DUMP];
+ struct hisi_sas_debugfs_iost_cache debugfs_iost_cache[HISI_SAS_MAX_DEBUGFS_DUMP];
+ struct hisi_sas_debugfs_itct_cache debugfs_itct_cache[HISI_SAS_MAX_DEBUGFS_DUMP];
+ u64 debugfs_timestamp[HISI_SAS_MAX_DEBUGFS_DUMP];
+ int debugfs_dump_index;
struct dentry *debugfs_dir;
struct dentry *debugfs_dump_dentry;
struct dentry *debugfs_bist_dentry;
- bool debugfs_snapshot;
};
/* Generic HW DMA host memory structures */
@@ -556,6 +636,7 @@
extern struct scsi_transport_template *hisi_sas_stt;
extern bool hisi_sas_debugfs_enable;
+extern u32 hisi_sas_debugfs_dump_count;
extern struct dentry *hisi_sas_debugfs_dir;
extern void hisi_sas_stop_phys(struct hisi_hba *hisi_hba);
@@ -584,7 +665,7 @@
extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba);
extern void hisi_sas_rst_work_handler(struct work_struct *work);
extern void hisi_sas_sync_rst_work_handler(struct work_struct *work);
-extern void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba);
+extern void hisi_sas_sync_irqs(struct hisi_hba *hisi_hba);
extern void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no);
extern bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy,
enum hisi_sas_phy_event event);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 031aa40..1feca45 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -163,13 +163,11 @@
static void hisi_sas_slot_index_free(struct hisi_hba *hisi_hba, int slot_idx)
{
- unsigned long flags;
-
if (hisi_hba->hw->slot_index_alloc ||
slot_idx >= HISI_SAS_UNRESERVED_IPTT) {
- spin_lock_irqsave(&hisi_hba->lock, flags);
+ spin_lock(&hisi_hba->lock);
hisi_sas_slot_index_clear(hisi_hba, slot_idx);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+ spin_unlock(&hisi_hba->lock);
}
}
@@ -185,12 +183,11 @@
{
int index;
void *bitmap = hisi_hba->slot_index_tags;
- unsigned long flags;
if (scsi_cmnd)
return scsi_cmnd->request->tag;
- spin_lock_irqsave(&hisi_hba->lock, flags);
+ spin_lock(&hisi_hba->lock);
index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count,
hisi_hba->last_slot_index + 1);
if (index >= hisi_hba->slot_index_count) {
@@ -198,13 +195,13 @@
hisi_hba->slot_index_count,
HISI_SAS_UNRESERVED_IPTT);
if (index >= hisi_hba->slot_index_count) {
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+ spin_unlock(&hisi_hba->lock);
return -SAS_QUEUE_FULL;
}
}
hisi_sas_slot_index_set(hisi_hba, index);
hisi_hba->last_slot_index = index;
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+ spin_unlock(&hisi_hba->lock);
return index;
}
@@ -220,7 +217,6 @@
void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
struct hisi_sas_slot *slot)
{
- unsigned long flags;
int device_id = slot->device_id;
struct hisi_sas_device *sas_dev = &hisi_hba->devices[device_id];
@@ -233,23 +229,24 @@
task->lldd_task = NULL;
if (!sas_protocol_ata(task->task_proto)) {
- struct sas_ssp_task *ssp_task = &task->ssp_task;
- struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
-
if (slot->n_elem)
dma_unmap_sg(dev, task->scatter,
task->num_scatter,
task->data_dir);
- if (slot->n_elem_dif)
+ if (slot->n_elem_dif) {
+ struct sas_ssp_task *ssp_task = &task->ssp_task;
+ struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
+
dma_unmap_sg(dev, scsi_prot_sglist(scsi_cmnd),
scsi_prot_sg_count(scsi_cmnd),
task->data_dir);
+ }
}
}
- spin_lock_irqsave(&sas_dev->lock, flags);
+ spin_lock(&sas_dev->lock);
list_del_init(&slot->entry);
- spin_unlock_irqrestore(&sas_dev->lock, flags);
+ spin_unlock(&sas_dev->lock);
memset(slot, 0, offsetof(struct hisi_sas_slot, buf));
@@ -338,7 +335,7 @@
}
if (*n_elem > HISI_SAS_SGE_PAGE_CNT) {
- dev_err(dev, "task prep: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT",
+ dev_err(dev, "task prep: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT\n",
*n_elem);
rc = -EINVAL;
goto err_out_dma_unmap;
@@ -421,6 +418,7 @@
struct device *dev = hisi_hba->dev;
int dlvry_queue_slot, dlvry_queue, rc, slot_idx;
int n_elem = 0, n_elem_dif = 0, n_elem_req = 0;
+ struct scsi_cmnd *scmd = NULL;
struct hisi_sas_dq *dq;
unsigned long flags;
int wr_q_index;
@@ -436,11 +434,30 @@
return -ECOMM;
}
- if (hisi_hba->reply_map) {
- int cpu = raw_smp_processor_id();
- unsigned int dq_index = hisi_hba->reply_map[cpu];
+ if (task->uldd_task) {
+ struct ata_queued_cmd *qc;
+ if (dev_is_sata(device)) {
+ qc = task->uldd_task;
+ scmd = qc->scsicmd;
+ } else {
+ scmd = task->uldd_task;
+ }
+ }
+
+ if (scmd && hisi_hba->shost->nr_hw_queues) {
+ unsigned int dq_index;
+ u32 blk_tag;
+
+ blk_tag = blk_mq_unique_tag(scmd->request);
+ dq_index = blk_mq_unique_tag_to_hwq(blk_tag);
*dq_pointer = dq = &hisi_hba->dq[dq_index];
+ } else if (hisi_hba->shost->nr_hw_queues) {
+ struct Scsi_Host *shost = hisi_hba->shost;
+ struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
+ int queue = qmap->mq_map[raw_smp_processor_id()];
+
+ *dq_pointer = dq = &hisi_hba->dq[queue];
} else {
*dq_pointer = dq = sas_dev->dq;
}
@@ -468,35 +485,23 @@
if (hisi_hba->hw->slot_index_alloc)
rc = hisi_hba->hw->slot_index_alloc(hisi_hba, device);
- else {
- struct scsi_cmnd *scsi_cmnd = NULL;
+ else
+ rc = hisi_sas_slot_index_alloc(hisi_hba, scmd);
- if (task->uldd_task) {
- struct ata_queued_cmd *qc;
-
- if (dev_is_sata(device)) {
- qc = task->uldd_task;
- scsi_cmnd = qc->scsicmd;
- } else {
- scsi_cmnd = task->uldd_task;
- }
- }
- rc = hisi_sas_slot_index_alloc(hisi_hba, scsi_cmnd);
- }
if (rc < 0)
goto err_out_dif_dma_unmap;
slot_idx = rc;
slot = &hisi_hba->slot_info[slot_idx];
- spin_lock_irqsave(&dq->lock, flags);
+ spin_lock(&dq->lock);
wr_q_index = dq->wr_point;
dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS;
list_add_tail(&slot->delivery, &dq->list);
- spin_unlock_irqrestore(&dq->lock, flags);
- spin_lock_irqsave(&sas_dev->lock, flags);
+ spin_unlock(&dq->lock);
+ spin_lock(&sas_dev->lock);
list_add_tail(&slot->entry, &sas_dev->list);
- spin_unlock_irqrestore(&sas_dev->lock, flags);
+ spin_unlock(&sas_dev->lock);
dlvry_queue = dq->id;
dlvry_queue_slot = wr_q_index;
@@ -562,7 +567,6 @@
{
u32 rc;
u32 pass = 0;
- unsigned long flags;
struct hisi_hba *hisi_hba;
struct device *dev;
struct domain_device *device = task->dev;
@@ -606,9 +610,9 @@
dev_err(dev, "task exec: failed[%d]!\n", rc);
if (likely(pass)) {
- spin_lock_irqsave(&dq->lock, flags);
+ spin_lock(&dq->lock);
hisi_hba->hw->start_delivery(dq);
- spin_unlock_irqrestore(&dq->lock, flags);
+ spin_unlock(&dq->lock);
}
return rc;
@@ -618,13 +622,17 @@
{
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
- struct sas_ha_struct *sas_ha;
if (!phy->phy_attached)
return;
- sas_ha = &hisi_hba->sha;
- sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE);
+ if (test_bit(HISI_SAS_PM_BIT, &hisi_hba->flags) &&
+ !sas_phy->suspended) {
+ dev_warn(hisi_hba->dev, "phy%d during suspend filtered out\n", phy_no);
+ return;
+ }
+
+ sas_notify_phy_event(sas_phy, PHYE_OOB_DONE);
if (sas_phy->phy) {
struct sas_phy *sphy = sas_phy->phy;
@@ -652,19 +660,18 @@
}
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
- sas_ha->notify_port_event(sas_phy, PORTE_BYTES_DMAED);
+ sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED);
}
static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
{
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct hisi_sas_device *sas_dev = NULL;
- unsigned long flags;
int last = hisi_hba->last_dev_id;
int first = (hisi_hba->last_dev_id + 1) % HISI_SAS_MAX_DEVICES;
int i;
- spin_lock_irqsave(&hisi_hba->lock, flags);
+ spin_lock(&hisi_hba->lock);
for (i = first; i != last; i %= HISI_SAS_MAX_DEVICES) {
if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) {
int queue = i % hisi_hba->queue_count;
@@ -684,7 +691,7 @@
i++;
}
hisi_hba->last_dev_id = i;
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+ spin_unlock(&hisi_hba->lock);
return sas_dev;
}
@@ -1055,6 +1062,7 @@
struct hisi_sas_device *sas_dev = device->lldd_dev;
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct device *dev = hisi_hba->dev;
+ int ret = 0;
dev_info(dev, "dev[%d:%x] is gone\n",
sas_dev->device_id, sas_dev->dev_type);
@@ -1066,13 +1074,16 @@
hisi_sas_dereg_device(hisi_hba, device);
- hisi_hba->hw->clear_itct(hisi_hba, sas_dev);
+ ret = hisi_hba->hw->clear_itct(hisi_hba, sas_dev);
device->lldd_dev = NULL;
}
if (hisi_hba->hw->free_device)
hisi_hba->hw->free_device(sas_dev);
- sas_dev->dev_type = SAS_PHY_UNUSED;
+
+ /* Don't mark it as SAS_PHY_UNUSED if failed to clear ITCT */
+ if (!ret)
+ sas_dev->dev_type = SAS_PHY_UNUSED;
sas_dev->sas_device = NULL;
up(&hisi_hba->sem);
}
@@ -1146,7 +1157,7 @@
hisi_hba->hw->get_events(hisi_hba, phy_no);
break;
}
- /* fallthru */
+ fallthrough;
case PHY_FUNC_RELEASE_SPINUP_HOLD:
default:
return -EOPNOTSUPP;
@@ -1232,10 +1243,10 @@
struct hisi_sas_cq *cq =
&hisi_hba->cq[slot->dlvry_queue];
/*
- * flush tasklet to avoid free'ing task
+ * sync irq to avoid free'ing task
* before using task in IO completion
*/
- tasklet_kill(&cq->tasklet);
+ synchronize_irq(cq->irq_no);
slot->task = NULL;
}
@@ -1404,7 +1415,6 @@
static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 state)
{
- struct sas_ha_struct *sas_ha = &hisi_hba->sha;
struct asd_sas_port *_sas_port = NULL;
int phy_no;
@@ -1412,7 +1422,7 @@
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
struct asd_sas_port *sas_port = sas_phy->port;
- bool do_port_check = !!(_sas_port != sas_port);
+ bool do_port_check = _sas_port != sas_port;
if (!sas_phy->phy->enabled)
continue;
@@ -1425,13 +1435,12 @@
_sas_port = sas_port;
if (dev_is_expander(dev->dev_type))
- sas_ha->notify_port_event(sas_phy,
+ sas_notify_port_event(sas_phy,
PORTE_BROADCAST_RCVD);
}
} else {
hisi_sas_phy_down(hisi_hba, phy_no, 0);
}
-
}
}
@@ -1547,7 +1556,6 @@
void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba)
{
struct Scsi_Host *shost = hisi_hba->shost;
- u32 state;
/* Init and wait for PHYs to come up and all libsas event finished. */
hisi_hba->hw->phys_init(hisi_hba);
@@ -1562,8 +1570,7 @@
scsi_unblock_requests(shost);
clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags);
- state = hisi_hba->hw->get_phys_state(hisi_hba);
- hisi_sas_rescan_topology(hisi_hba, state);
+ hisi_sas_rescan_topology(hisi_hba, hisi_hba->phy_state);
}
EXPORT_SYMBOL_GPL(hisi_sas_controller_reset_done);
@@ -1573,7 +1580,7 @@
struct Scsi_Host *shost = hisi_hba->shost;
int rc;
- if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct)
+ if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct)
queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);
if (!hisi_hba->hw->soft_reset)
@@ -1625,11 +1632,11 @@
if (slot) {
/*
- * flush tasklet to avoid free'ing task
+ * sync irq to avoid free'ing task
* before using task in IO completion
*/
cq = &hisi_hba->cq[slot->dlvry_queue];
- tasklet_kill(&cq->tasklet);
+ synchronize_irq(cq->irq_no);
}
spin_unlock_irqrestore(&task->task_state_lock, flags);
rc = TMF_RESP_FUNC_COMPLETE;
@@ -1693,10 +1700,10 @@
if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) &&
task->lldd_task) {
/*
- * flush tasklet to avoid free'ing task
+ * sync irq to avoid free'ing task
* before using task in IO completion
*/
- tasklet_kill(&cq->tasklet);
+ synchronize_irq(cq->irq_no);
slot->task = NULL;
}
}
@@ -1964,14 +1971,14 @@
slot_idx = rc;
slot = &hisi_hba->slot_info[slot_idx];
- spin_lock_irqsave(&dq->lock, flags);
+ spin_lock(&dq->lock);
wr_q_index = dq->wr_point;
dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS;
list_add_tail(&slot->delivery, &dq->list);
- spin_unlock_irqrestore(&dq->lock, flags);
- spin_lock_irqsave(&sas_dev->lock, flags);
+ spin_unlock(&dq->lock);
+ spin_lock(&sas_dev->lock);
list_add_tail(&slot->entry, &sas_dev->list);
- spin_unlock_irqrestore(&sas_dev->lock, flags);
+ spin_unlock(&sas_dev->lock);
dlvry_queue = dq->id;
dlvry_queue_slot = wr_q_index;
@@ -2000,9 +2007,9 @@
spin_unlock_irqrestore(&task->task_state_lock, flags);
WRITE_ONCE(slot->ready, 1);
/* send abort command to the chip */
- spin_lock_irqsave(&dq->lock, flags);
+ spin_lock(&dq->lock);
hisi_hba->hw->start_delivery(dq);
- spin_unlock_irqrestore(&dq->lock, flags);
+ spin_unlock(&dq->lock);
return 0;
@@ -2065,7 +2072,7 @@
/* Internal abort timed out */
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
- if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct)
+ if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct)
queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
@@ -2075,10 +2082,10 @@
struct hisi_sas_cq *cq =
&hisi_hba->cq[slot->dlvry_queue];
/*
- * flush tasklet to avoid free'ing task
+ * sync irq to avoid free'ing task
* before using task in IO completion
*/
- tasklet_kill(&cq->tasklet);
+ synchronize_irq(cq->irq_no);
slot->task = NULL;
}
dev_err(dev, "internal task abort: timeout and not done.\n");
@@ -2130,7 +2137,7 @@
case HISI_SAS_INT_ABT_DEV:
for (i = 0; i < hisi_hba->cq_nvecs; i++) {
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
- const struct cpumask *mask = cq->pci_irq_mask;
+ const struct cpumask *mask = cq->irq_mask;
if (mask && !cpumask_intersects(cpu_online_mask, mask))
continue;
@@ -2190,7 +2197,6 @@
{
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
- struct sas_ha_struct *sas_ha = &hisi_hba->sha;
struct device *dev = hisi_hba->dev;
if (rdy) {
@@ -2206,7 +2212,7 @@
return;
}
/* Phy down and not ready */
- sas_ha->notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL);
+ sas_notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL);
sas_phy_disconnected(sas_phy);
if (port) {
@@ -2224,17 +2230,17 @@
}
EXPORT_SYMBOL_GPL(hisi_sas_phy_down);
-void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba)
+void hisi_sas_sync_irqs(struct hisi_hba *hisi_hba)
{
int i;
for (i = 0; i < hisi_hba->cq_nvecs; i++) {
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
- tasklet_kill(&cq->tasklet);
+ synchronize_irq(cq->irq_no);
}
}
-EXPORT_SYMBOL_GPL(hisi_sas_kill_tasklets);
+EXPORT_SYMBOL_GPL(hisi_sas_sync_irqs);
int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type)
{
@@ -2698,10 +2704,11 @@
static void hisi_sas_debugfs_snapshot_cq_reg(struct hisi_hba *hisi_hba)
{
int queue_entry_size = hisi_hba->hw->complete_hdr_size;
+ int dump_index = hisi_hba->debugfs_dump_index;
int i;
for (i = 0; i < hisi_hba->queue_count; i++)
- memcpy(hisi_hba->debugfs_complete_hdr[i],
+ memcpy(hisi_hba->debugfs_cq[dump_index][i].complete_hdr,
hisi_hba->complete_hdr[i],
HISI_SAS_QUEUE_SLOTS * queue_entry_size);
}
@@ -2709,13 +2716,14 @@
static void hisi_sas_debugfs_snapshot_dq_reg(struct hisi_hba *hisi_hba)
{
int queue_entry_size = sizeof(struct hisi_sas_cmd_hdr);
+ int dump_index = hisi_hba->debugfs_dump_index;
int i;
for (i = 0; i < hisi_hba->queue_count; i++) {
- struct hisi_sas_cmd_hdr *debugfs_cmd_hdr, *cmd_hdr;
+ struct hisi_sas_cmd_hdr *debugfs_cmd_hdr, *cmd_hdr;
int j;
- debugfs_cmd_hdr = hisi_hba->debugfs_cmd_hdr[i];
+ debugfs_cmd_hdr = hisi_hba->debugfs_dq[dump_index][i].hdr;
cmd_hdr = hisi_hba->cmd_hdr[i];
for (j = 0; j < HISI_SAS_QUEUE_SLOTS; j++)
@@ -2726,6 +2734,7 @@
static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba)
{
+ int dump_index = hisi_hba->debugfs_dump_index;
const struct hisi_sas_debugfs_reg *port =
hisi_hba->hw->debugfs_reg_port;
int i, phy_cnt;
@@ -2733,7 +2742,7 @@
u32 *databuf;
for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) {
- databuf = (u32 *)hisi_hba->debugfs_port_reg[phy_cnt];
+ databuf = hisi_hba->debugfs_port_reg[dump_index][phy_cnt].data;
for (i = 0; i < port->count; i++, databuf++) {
offset = port->base_off + 4 * i;
*databuf = port->read_port_reg(hisi_hba, phy_cnt,
@@ -2744,7 +2753,8 @@
static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba)
{
- u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_GLOBAL];
+ int dump_index = hisi_hba->debugfs_dump_index;
+ u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data;
const struct hisi_sas_hw *hw = hisi_hba->hw;
const struct hisi_sas_debugfs_reg *global =
hw->debugfs_reg_array[DEBUGFS_GLOBAL];
@@ -2756,7 +2766,8 @@
static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba)
{
- u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_AXI];
+ int dump_index = hisi_hba->debugfs_dump_index;
+ u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI].data;
const struct hisi_sas_hw *hw = hisi_hba->hw;
const struct hisi_sas_debugfs_reg *axi =
hw->debugfs_reg_array[DEBUGFS_AXI];
@@ -2769,7 +2780,8 @@
static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba)
{
- u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_RAS];
+ int dump_index = hisi_hba->debugfs_dump_index;
+ u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS].data;
const struct hisi_sas_hw *hw = hisi_hba->hw;
const struct hisi_sas_debugfs_reg *ras =
hw->debugfs_reg_array[DEBUGFS_RAS];
@@ -2782,8 +2794,9 @@
static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba)
{
- void *cachebuf = hisi_hba->debugfs_itct_cache;
- void *databuf = hisi_hba->debugfs_itct;
+ int dump_index = hisi_hba->debugfs_dump_index;
+ void *cachebuf = hisi_hba->debugfs_itct_cache[dump_index].cache;
+ void *databuf = hisi_hba->debugfs_itct[dump_index].itct;
struct hisi_sas_itct *itct;
int i;
@@ -2800,9 +2813,10 @@
static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba)
{
+ int dump_index = hisi_hba->debugfs_dump_index;
int max_command_entries = HISI_SAS_MAX_COMMANDS;
- void *cachebuf = hisi_hba->debugfs_iost_cache;
- void *databuf = hisi_hba->debugfs_iost;
+ void *cachebuf = hisi_hba->debugfs_iost_cache[dump_index].cache;
+ void *databuf = hisi_hba->debugfs_iost[dump_index].iost;
struct hisi_sas_iost *iost;
int i;
@@ -2853,11 +2867,12 @@
static int hisi_sas_debugfs_global_show(struct seq_file *s, void *p)
{
- struct hisi_hba *hisi_hba = s->private;
+ struct hisi_sas_debugfs_regs *global = s->private;
+ struct hisi_hba *hisi_hba = global->hisi_hba;
const struct hisi_sas_hw *hw = hisi_hba->hw;
const void *reg_global = hw->debugfs_reg_array[DEBUGFS_GLOBAL];
- hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_GLOBAL],
+ hisi_sas_debugfs_print_reg(global->data,
reg_global, s);
return 0;
@@ -2879,11 +2894,12 @@
static int hisi_sas_debugfs_axi_show(struct seq_file *s, void *p)
{
- struct hisi_hba *hisi_hba = s->private;
+ struct hisi_sas_debugfs_regs *axi = s->private;
+ struct hisi_hba *hisi_hba = axi->hisi_hba;
const struct hisi_sas_hw *hw = hisi_hba->hw;
const void *reg_axi = hw->debugfs_reg_array[DEBUGFS_AXI];
- hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_AXI],
+ hisi_sas_debugfs_print_reg(axi->data,
reg_axi, s);
return 0;
@@ -2905,11 +2921,12 @@
static int hisi_sas_debugfs_ras_show(struct seq_file *s, void *p)
{
- struct hisi_hba *hisi_hba = s->private;
+ struct hisi_sas_debugfs_regs *ras = s->private;
+ struct hisi_hba *hisi_hba = ras->hisi_hba;
const struct hisi_sas_hw *hw = hisi_hba->hw;
const void *reg_ras = hw->debugfs_reg_array[DEBUGFS_RAS];
- hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_RAS],
+ hisi_sas_debugfs_print_reg(ras->data,
reg_ras, s);
return 0;
@@ -2931,13 +2948,13 @@
static int hisi_sas_debugfs_port_show(struct seq_file *s, void *p)
{
- struct hisi_sas_phy *phy = s->private;
+ struct hisi_sas_debugfs_port *port = s->private;
+ struct hisi_sas_phy *phy = port->phy;
struct hisi_hba *hisi_hba = phy->hisi_hba;
const struct hisi_sas_hw *hw = hisi_hba->hw;
const struct hisi_sas_debugfs_reg *reg_port = hw->debugfs_reg_port;
- u32 *databuf = hisi_hba->debugfs_port_reg[phy->sas_phy.id];
- hisi_sas_debugfs_print_reg(databuf, reg_port, s);
+ hisi_sas_debugfs_print_reg(port->data, reg_port, s);
return 0;
}
@@ -2986,13 +3003,13 @@
seq_puts(s, "\n");
}
-static void hisi_sas_cq_show_slot(struct seq_file *s, int slot, void *cq_ptr)
+static void hisi_sas_cq_show_slot(struct seq_file *s, int slot,
+ struct hisi_sas_debugfs_cq *debugfs_cq)
{
- struct hisi_sas_cq *cq = cq_ptr;
+ struct hisi_sas_cq *cq = debugfs_cq->cq;
struct hisi_hba *hisi_hba = cq->hisi_hba;
- void *complete_queue = hisi_hba->debugfs_complete_hdr[cq->id];
- __le32 *complete_hdr = complete_queue +
- (hisi_hba->hw->complete_hdr_size * slot);
+ __le32 *complete_hdr = debugfs_cq->complete_hdr +
+ (hisi_hba->hw->complete_hdr_size * slot);
hisi_sas_show_row_32(s, slot,
hisi_hba->hw->complete_hdr_size,
@@ -3001,11 +3018,11 @@
static int hisi_sas_debugfs_cq_show(struct seq_file *s, void *p)
{
- struct hisi_sas_cq *cq = s->private;
+ struct hisi_sas_debugfs_cq *debugfs_cq = s->private;
int slot;
for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) {
- hisi_sas_cq_show_slot(s, slot, cq);
+ hisi_sas_cq_show_slot(s, slot, debugfs_cq);
}
return 0;
}
@@ -3025,9 +3042,8 @@
static void hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr)
{
- struct hisi_sas_dq *dq = dq_ptr;
- struct hisi_hba *hisi_hba = dq->hisi_hba;
- void *cmd_queue = hisi_hba->debugfs_cmd_hdr[dq->id];
+ struct hisi_sas_debugfs_dq *debugfs_dq = dq_ptr;
+ void *cmd_queue = debugfs_dq->hdr;
__le32 *cmd_hdr = cmd_queue +
sizeof(struct hisi_sas_cmd_hdr) * slot;
@@ -3059,14 +3075,14 @@
static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p)
{
- struct hisi_hba *hisi_hba = s->private;
- struct hisi_sas_iost *debugfs_iost = hisi_hba->debugfs_iost;
+ struct hisi_sas_debugfs_iost *debugfs_iost = s->private;
+ struct hisi_sas_iost *iost = debugfs_iost->iost;
int i, max_command_entries = HISI_SAS_MAX_COMMANDS;
- for (i = 0; i < max_command_entries; i++, debugfs_iost++) {
- __le64 *iost = &debugfs_iost->qw0;
+ for (i = 0; i < max_command_entries; i++, iost++) {
+ __le64 *data = &iost->qw0;
- hisi_sas_show_row_64(s, i, sizeof(*debugfs_iost), iost);
+ hisi_sas_show_row_64(s, i, sizeof(*iost), data);
}
return 0;
@@ -3087,9 +3103,8 @@
static int hisi_sas_debugfs_iost_cache_show(struct seq_file *s, void *p)
{
- struct hisi_hba *hisi_hba = s->private;
- struct hisi_sas_iost_itct_cache *iost_cache =
- (struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_iost_cache;
+ struct hisi_sas_debugfs_iost_cache *debugfs_iost_cache = s->private;
+ struct hisi_sas_iost_itct_cache *iost_cache = debugfs_iost_cache->cache;
u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4;
int i, tab_idx;
__le64 *iost;
@@ -3128,13 +3143,13 @@
static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p)
{
int i;
- struct hisi_hba *hisi_hba = s->private;
- struct hisi_sas_itct *debugfs_itct = hisi_hba->debugfs_itct;
+ struct hisi_sas_debugfs_itct *debugfs_itct = s->private;
+ struct hisi_sas_itct *itct = debugfs_itct->itct;
- for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, debugfs_itct++) {
- __le64 *itct = &debugfs_itct->qw0;
+ for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) {
+ __le64 *data = &itct->qw0;
- hisi_sas_show_row_64(s, i, sizeof(*debugfs_itct), itct);
+ hisi_sas_show_row_64(s, i, sizeof(*itct), data);
}
return 0;
@@ -3155,9 +3170,8 @@
static int hisi_sas_debugfs_itct_cache_show(struct seq_file *s, void *p)
{
- struct hisi_hba *hisi_hba = s->private;
- struct hisi_sas_iost_itct_cache *itct_cache =
- (struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_itct_cache;
+ struct hisi_sas_debugfs_itct_cache *debugfs_itct_cache = s->private;
+ struct hisi_sas_iost_itct_cache *itct_cache = debugfs_itct_cache->cache;
u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4;
int i, tab_idx;
__le64 *itct;
@@ -3195,6 +3209,8 @@
static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba)
{
+ u64 *debugfs_timestamp;
+ int dump_index = hisi_hba->debugfs_dump_index;
struct dentry *dump_dentry;
struct dentry *dentry;
char name[256];
@@ -3202,19 +3218,26 @@
int c;
int d;
- /* Create dump dir inside device dir */
- dump_dentry = debugfs_create_dir("dump", hisi_hba->debugfs_dir);
- hisi_hba->debugfs_dump_dentry = dump_dentry;
+ snprintf(name, 256, "%d", dump_index);
- debugfs_create_file("global", 0400, dump_dentry, hisi_hba,
- &hisi_sas_debugfs_global_fops);
+ dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry);
+
+ debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index];
+
+ debugfs_create_u64("timestamp", 0400, dump_dentry,
+ debugfs_timestamp);
+
+ debugfs_create_file("global", 0400, dump_dentry,
+ &hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL],
+ &hisi_sas_debugfs_global_fops);
/* Create port dir and files */
dentry = debugfs_create_dir("port", dump_dentry);
for (p = 0; p < hisi_hba->n_phy; p++) {
snprintf(name, 256, "%d", p);
- debugfs_create_file(name, 0400, dentry, &hisi_hba->phy[p],
+ debugfs_create_file(name, 0400, dentry,
+ &hisi_hba->debugfs_port_reg[dump_index][p],
&hisi_sas_debugfs_port_fops);
}
@@ -3223,7 +3246,8 @@
for (c = 0; c < hisi_hba->queue_count; c++) {
snprintf(name, 256, "%d", c);
- debugfs_create_file(name, 0400, dentry, &hisi_hba->cq[c],
+ debugfs_create_file(name, 0400, dentry,
+ &hisi_hba->debugfs_cq[dump_index][c],
&hisi_sas_debugfs_cq_fops);
}
@@ -3232,26 +3256,33 @@
for (d = 0; d < hisi_hba->queue_count; d++) {
snprintf(name, 256, "%d", d);
- debugfs_create_file(name, 0400, dentry, &hisi_hba->dq[d],
+ debugfs_create_file(name, 0400, dentry,
+ &hisi_hba->debugfs_dq[dump_index][d],
&hisi_sas_debugfs_dq_fops);
}
- debugfs_create_file("iost", 0400, dump_dentry, hisi_hba,
+ debugfs_create_file("iost", 0400, dump_dentry,
+ &hisi_hba->debugfs_iost[dump_index],
&hisi_sas_debugfs_iost_fops);
- debugfs_create_file("iost_cache", 0400, dump_dentry, hisi_hba,
+ debugfs_create_file("iost_cache", 0400, dump_dentry,
+ &hisi_hba->debugfs_iost_cache[dump_index],
&hisi_sas_debugfs_iost_cache_fops);
- debugfs_create_file("itct", 0400, dump_dentry, hisi_hba,
+ debugfs_create_file("itct", 0400, dump_dentry,
+ &hisi_hba->debugfs_itct[dump_index],
&hisi_sas_debugfs_itct_fops);
- debugfs_create_file("itct_cache", 0400, dump_dentry, hisi_hba,
+ debugfs_create_file("itct_cache", 0400, dump_dentry,
+ &hisi_hba->debugfs_itct_cache[dump_index],
&hisi_sas_debugfs_itct_cache_fops);
- debugfs_create_file("axi", 0400, dump_dentry, hisi_hba,
+ debugfs_create_file("axi", 0400, dump_dentry,
+ &hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI],
&hisi_sas_debugfs_axi_fops);
- debugfs_create_file("ras", 0400, dump_dentry, hisi_hba,
+ debugfs_create_file("ras", 0400, dump_dentry,
+ &hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS],
&hisi_sas_debugfs_ras_fops);
return;
@@ -3282,8 +3313,7 @@
struct hisi_hba *hisi_hba = file->f_inode->i_private;
char buf[8];
- /* A bit racy, but don't care too much since it's only debugfs */
- if (hisi_hba->debugfs_snapshot)
+ if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count)
return -EFAULT;
if (count > 8)
@@ -3311,21 +3341,6 @@
HISI_SAS_BIST_LOOPBACK_MODE_REMOTE,
};
-enum {
- HISI_SAS_BIST_CODE_MODE_PRBS7 = 0,
- HISI_SAS_BIST_CODE_MODE_PRBS23,
- HISI_SAS_BIST_CODE_MODE_PRBS31,
- HISI_SAS_BIST_CODE_MODE_JTPAT,
- HISI_SAS_BIST_CODE_MODE_CJTPAT,
- HISI_SAS_BIST_CODE_MODE_SCRAMBED_0,
- HISI_SAS_BIST_CODE_MODE_TRAIN,
- HISI_SAS_BIST_CODE_MODE_TRAIN_DONE,
- HISI_SAS_BIST_CODE_MODE_HFTP,
- HISI_SAS_BIST_CODE_MODE_MFTP,
- HISI_SAS_BIST_CODE_MODE_LFTP,
- HISI_SAS_BIST_CODE_MODE_FIXED_DATA,
-};
-
static const struct {
int value;
char *name;
@@ -3550,7 +3565,7 @@
int value;
char *name;
} hisi_sas_debugfs_loop_modes[] = {
- { HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digial" },
+ { HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digital" },
{ HISI_SAS_BIST_LOOPBACK_MODE_SERDES, "serdes" },
{ HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, "remote" },
};
@@ -3681,131 +3696,258 @@
.owner = THIS_MODULE,
};
+static const struct {
+ char *name;
+} hisi_sas_debugfs_ffe_name[FFE_CFG_MAX] = {
+ { "SAS_1_5_GBPS" },
+ { "SAS_3_0_GBPS" },
+ { "SAS_6_0_GBPS" },
+ { "SAS_12_0_GBPS" },
+ { "FFE_RESV" },
+ { "SATA_1_5_GBPS" },
+ { "SATA_3_0_GBPS" },
+ { "SATA_6_0_GBPS" },
+};
+
+static ssize_t hisi_sas_debugfs_write(struct file *filp,
+ const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct seq_file *m = filp->private_data;
+ u32 *val = m->private;
+ int res;
+
+ res = kstrtouint_from_user(buf, count, 0, val);
+ if (res)
+ return res;
+
+ return count;
+}
+
+static int hisi_sas_debugfs_show(struct seq_file *s, void *p)
+{
+ u32 *val = s->private;
+
+ seq_printf(s, "0x%x\n", *val);
+
+ return 0;
+}
+
+static int hisi_sas_debugfs_open(struct inode *inode, struct file *filp)
+{
+ return single_open(filp, hisi_sas_debugfs_show,
+ inode->i_private);
+}
+
+static const struct file_operations hisi_sas_debugfs_ops = {
+ .open = hisi_sas_debugfs_open,
+ .read = seq_read,
+ .write = hisi_sas_debugfs_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+static ssize_t hisi_sas_debugfs_phy_down_cnt_write(struct file *filp,
+ const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct seq_file *s = filp->private_data;
+ struct hisi_sas_phy *phy = s->private;
+ unsigned int set_val;
+ int res;
+
+ res = kstrtouint_from_user(buf, count, 0, &set_val);
+ if (res)
+ return res;
+
+ if (set_val > 0)
+ return -EINVAL;
+
+ atomic_set(&phy->down_cnt, 0);
+
+ return count;
+}
+
+static int hisi_sas_debugfs_phy_down_cnt_show(struct seq_file *s, void *p)
+{
+ struct hisi_sas_phy *phy = s->private;
+
+ seq_printf(s, "%d\n", atomic_read(&phy->down_cnt));
+
+ return 0;
+}
+
+static int hisi_sas_debugfs_phy_down_cnt_open(struct inode *inode,
+ struct file *filp)
+{
+ return single_open(filp, hisi_sas_debugfs_phy_down_cnt_show,
+ inode->i_private);
+}
+
+static const struct file_operations hisi_sas_debugfs_phy_down_cnt_ops = {
+ .open = hisi_sas_debugfs_phy_down_cnt_open,
+ .read = seq_read,
+ .write = hisi_sas_debugfs_phy_down_cnt_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
void hisi_sas_debugfs_work_handler(struct work_struct *work)
{
struct hisi_hba *hisi_hba =
container_of(work, struct hisi_hba, debugfs_work);
+ int debugfs_dump_index = hisi_hba->debugfs_dump_index;
+ struct device *dev = hisi_hba->dev;
+ u64 timestamp = local_clock();
- if (hisi_hba->debugfs_snapshot)
+ if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) {
+ dev_warn(dev, "dump count exceeded!\n");
return;
- hisi_hba->debugfs_snapshot = true;
+ }
+
+ do_div(timestamp, NSEC_PER_MSEC);
+ hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp;
hisi_sas_debugfs_snapshot_regs(hisi_hba);
+ hisi_hba->debugfs_dump_index++;
}
EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler);
-static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba)
+static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba, int dump_index)
{
struct device *dev = hisi_hba->dev;
int i;
- devm_kfree(dev, hisi_hba->debugfs_iost_cache);
- devm_kfree(dev, hisi_hba->debugfs_itct_cache);
- devm_kfree(dev, hisi_hba->debugfs_iost);
+ devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache);
+ devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache);
+ devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost);
+ devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct);
for (i = 0; i < hisi_hba->queue_count; i++)
- devm_kfree(dev, hisi_hba->debugfs_cmd_hdr[i]);
+ devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr);
for (i = 0; i < hisi_hba->queue_count; i++)
- devm_kfree(dev, hisi_hba->debugfs_complete_hdr[i]);
+ devm_kfree(dev,
+ hisi_hba->debugfs_cq[dump_index][i].complete_hdr);
for (i = 0; i < DEBUGFS_REGS_NUM; i++)
- devm_kfree(dev, hisi_hba->debugfs_regs[i]);
+ devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data);
for (i = 0; i < hisi_hba->n_phy; i++)
- devm_kfree(dev, hisi_hba->debugfs_port_reg[i]);
+ devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data);
}
-static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba)
+static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba, int dump_index)
{
const struct hisi_sas_hw *hw = hisi_hba->hw;
struct device *dev = hisi_hba->dev;
- int p, c, d;
+ int p, c, d, r, i;
size_t sz;
- sz = hw->debugfs_reg_array[DEBUGFS_GLOBAL]->count * 4;
- hisi_hba->debugfs_regs[DEBUGFS_GLOBAL] =
- devm_kmalloc(dev, sz, GFP_KERNEL);
+ for (r = 0; r < DEBUGFS_REGS_NUM; r++) {
+ struct hisi_sas_debugfs_regs *regs =
+ &hisi_hba->debugfs_regs[dump_index][r];
- if (!hisi_hba->debugfs_regs[DEBUGFS_GLOBAL])
- goto fail;
+ sz = hw->debugfs_reg_array[r]->count * 4;
+ regs->data = devm_kmalloc(dev, sz, GFP_KERNEL);
+ if (!regs->data)
+ goto fail;
+ regs->hisi_hba = hisi_hba;
+ }
sz = hw->debugfs_reg_port->count * 4;
for (p = 0; p < hisi_hba->n_phy; p++) {
- hisi_hba->debugfs_port_reg[p] =
- devm_kmalloc(dev, sz, GFP_KERNEL);
+ struct hisi_sas_debugfs_port *port =
+ &hisi_hba->debugfs_port_reg[dump_index][p];
- if (!hisi_hba->debugfs_port_reg[p])
+ port->data = devm_kmalloc(dev, sz, GFP_KERNEL);
+ if (!port->data)
goto fail;
+ port->phy = &hisi_hba->phy[p];
}
- sz = hw->debugfs_reg_array[DEBUGFS_AXI]->count * 4;
- hisi_hba->debugfs_regs[DEBUGFS_AXI] =
- devm_kmalloc(dev, sz, GFP_KERNEL);
-
- if (!hisi_hba->debugfs_regs[DEBUGFS_AXI])
- goto fail;
-
- sz = hw->debugfs_reg_array[DEBUGFS_RAS]->count * 4;
- hisi_hba->debugfs_regs[DEBUGFS_RAS] =
- devm_kmalloc(dev, sz, GFP_KERNEL);
-
- if (!hisi_hba->debugfs_regs[DEBUGFS_RAS])
- goto fail;
-
sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
for (c = 0; c < hisi_hba->queue_count; c++) {
- hisi_hba->debugfs_complete_hdr[c] =
- devm_kmalloc(dev, sz, GFP_KERNEL);
+ struct hisi_sas_debugfs_cq *cq =
+ &hisi_hba->debugfs_cq[dump_index][c];
- if (!hisi_hba->debugfs_complete_hdr[c])
+ cq->complete_hdr = devm_kmalloc(dev, sz, GFP_KERNEL);
+ if (!cq->complete_hdr)
goto fail;
+ cq->cq = &hisi_hba->cq[c];
}
sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
for (d = 0; d < hisi_hba->queue_count; d++) {
- hisi_hba->debugfs_cmd_hdr[d] =
- devm_kmalloc(dev, sz, GFP_KERNEL);
+ struct hisi_sas_debugfs_dq *dq =
+ &hisi_hba->debugfs_dq[dump_index][d];
- if (!hisi_hba->debugfs_cmd_hdr[d])
+ dq->hdr = devm_kmalloc(dev, sz, GFP_KERNEL);
+ if (!dq->hdr)
goto fail;
+ dq->dq = &hisi_hba->dq[d];
}
sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost);
- hisi_hba->debugfs_iost = devm_kmalloc(dev, sz, GFP_KERNEL);
- if (!hisi_hba->debugfs_iost)
+ hisi_hba->debugfs_iost[dump_index].iost =
+ devm_kmalloc(dev, sz, GFP_KERNEL);
+ if (!hisi_hba->debugfs_iost[dump_index].iost)
goto fail;
sz = HISI_SAS_IOST_ITCT_CACHE_NUM *
sizeof(struct hisi_sas_iost_itct_cache);
- hisi_hba->debugfs_iost_cache = devm_kmalloc(dev, sz, GFP_KERNEL);
- if (!hisi_hba->debugfs_iost_cache)
+ hisi_hba->debugfs_iost_cache[dump_index].cache =
+ devm_kmalloc(dev, sz, GFP_KERNEL);
+ if (!hisi_hba->debugfs_iost_cache[dump_index].cache)
goto fail;
sz = HISI_SAS_IOST_ITCT_CACHE_NUM *
sizeof(struct hisi_sas_iost_itct_cache);
- hisi_hba->debugfs_itct_cache = devm_kmalloc(dev, sz, GFP_KERNEL);
- if (!hisi_hba->debugfs_itct_cache)
+ hisi_hba->debugfs_itct_cache[dump_index].cache =
+ devm_kmalloc(dev, sz, GFP_KERNEL);
+ if (!hisi_hba->debugfs_itct_cache[dump_index].cache)
goto fail;
/* New memory allocation must be locate before itct */
sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
- hisi_hba->debugfs_itct = devm_kmalloc(dev, sz, GFP_KERNEL);
- if (!hisi_hba->debugfs_itct)
+ hisi_hba->debugfs_itct[dump_index].itct =
+ devm_kmalloc(dev, sz, GFP_KERNEL);
+ if (!hisi_hba->debugfs_itct[dump_index].itct)
goto fail;
return 0;
fail:
- hisi_sas_debugfs_release(hisi_hba);
+ for (i = 0; i < hisi_sas_debugfs_dump_count; i++)
+ hisi_sas_debugfs_release(hisi_hba, i);
return -ENOMEM;
}
+static void hisi_sas_debugfs_phy_down_cnt_init(struct hisi_hba *hisi_hba)
+{
+ struct dentry *dir = debugfs_create_dir("phy_down_cnt",
+ hisi_hba->debugfs_dir);
+ char name[16];
+ int phy_no;
+
+ for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
+ snprintf(name, 16, "%d", phy_no);
+ debugfs_create_file(name, 0600, dir,
+ &hisi_hba->phy[phy_no],
+ &hisi_sas_debugfs_phy_down_cnt_ops);
+ }
+}
+
static void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba)
{
+ struct dentry *ports_dentry;
+ int phy_no;
+
hisi_hba->debugfs_bist_dentry =
debugfs_create_dir("bist", hisi_hba->debugfs_dir);
debugfs_create_file("link_rate", 0600,
@@ -3816,6 +3958,16 @@
hisi_hba->debugfs_bist_dentry, hisi_hba,
&hisi_sas_debugfs_bist_code_mode_ops);
+ debugfs_create_file("fixed_code", 0600,
+ hisi_hba->debugfs_bist_dentry,
+ &hisi_hba->debugfs_bist_fixed_code[0],
+ &hisi_sas_debugfs_ops);
+
+ debugfs_create_file("fixed_code_1", 0600,
+ hisi_hba->debugfs_bist_dentry,
+ &hisi_hba->debugfs_bist_fixed_code[1],
+ &hisi_sas_debugfs_ops);
+
debugfs_create_file("phy_id", 0600, hisi_hba->debugfs_bist_dentry,
hisi_hba, &hisi_sas_debugfs_bist_phy_ops);
@@ -3829,16 +3981,38 @@
debugfs_create_file("enable", 0600, hisi_hba->debugfs_bist_dentry,
hisi_hba, &hisi_sas_debugfs_bist_enable_ops);
+ ports_dentry = debugfs_create_dir("port", hisi_hba->debugfs_bist_dentry);
+
+ for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
+ struct dentry *port_dentry;
+ struct dentry *ffe_dentry;
+ char name[256];
+ int i;
+
+ snprintf(name, 256, "%d", phy_no);
+ port_dentry = debugfs_create_dir(name, ports_dentry);
+ ffe_dentry = debugfs_create_dir("ffe", port_dentry);
+ for (i = 0; i < FFE_CFG_MAX; i++) {
+ if (i == FFE_RESV)
+ continue;
+ debugfs_create_file(hisi_sas_debugfs_ffe_name[i].name,
+ 0600, ffe_dentry,
+ &hisi_hba->debugfs_bist_ffe[phy_no][i],
+ &hisi_sas_debugfs_ops);
+ }
+ }
+
hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS;
}
void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
+ int i;
hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev),
hisi_sas_debugfs_dir);
- debugfs_create_file("trigger_dump", 0600,
+ debugfs_create_file("trigger_dump", 0200,
hisi_hba->debugfs_dir,
hisi_hba,
&hisi_sas_debugfs_trigger_dump_fops);
@@ -3846,9 +4020,17 @@
/* create bist structures */
hisi_sas_debugfs_bist_init(hisi_hba);
- if (hisi_sas_debugfs_alloc(hisi_hba)) {
- debugfs_remove_recursive(hisi_hba->debugfs_dir);
- dev_dbg(dev, "failed to init debugfs!\n");
+ hisi_hba->debugfs_dump_dentry =
+ debugfs_create_dir("dump", hisi_hba->debugfs_dir);
+
+ hisi_sas_debugfs_phy_down_cnt_init(hisi_hba);
+
+ for (i = 0; i < hisi_sas_debugfs_dump_count; i++) {
+ if (hisi_sas_debugfs_alloc(hisi_hba, i)) {
+ debugfs_remove_recursive(hisi_hba->debugfs_dir);
+ dev_dbg(dev, "failed to init debugfs!\n");
+ break;
+ }
}
}
EXPORT_SYMBOL_GPL(hisi_sas_debugfs_init);
@@ -3882,14 +4064,24 @@
module_param_named(debugfs_enable, hisi_sas_debugfs_enable, bool, 0444);
MODULE_PARM_DESC(hisi_sas_debugfs_enable, "Enable driver debugfs (default disabled)");
+u32 hisi_sas_debugfs_dump_count = 1;
+EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dump_count);
+module_param_named(debugfs_dump_count, hisi_sas_debugfs_dump_count, uint, 0444);
+MODULE_PARM_DESC(hisi_sas_debugfs_dump_count, "Number of debugfs dumps to allow");
+
static __init int hisi_sas_init(void)
{
hisi_sas_stt = sas_domain_attach_transport(&hisi_sas_transport_ops);
if (!hisi_sas_stt)
return -ENOMEM;
- if (hisi_sas_debugfs_enable)
+ if (hisi_sas_debugfs_enable) {
hisi_sas_debugfs_dir = debugfs_create_dir("hisi_sas", NULL);
+ if (hisi_sas_debugfs_dump_count > HISI_SAS_MAX_DEBUGFS_DUMP) {
+ pr_info("hisi_sas: Limiting debugfs dump count\n");
+ hisi_sas_debugfs_dump_count = HISI_SAS_MAX_DEBUGFS_DUMP;
+ }
+ }
return 0;
}
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 1443c80..2c10281 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -531,8 +531,8 @@
(0xff00ULL << ITCT_HDR_REJ_OPEN_TL_OFF));
}
-static void clear_itct_v1_hw(struct hisi_hba *hisi_hba,
- struct hisi_sas_device *sas_dev)
+static int clear_itct_v1_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_device *sas_dev)
{
u64 dev_id = sas_dev->device_id;
struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
@@ -551,6 +551,8 @@
qw0 = le64_to_cpu(itct->qw0);
qw0 &= ~ITCT_HDR_VALID_MSK;
itct->qw0 = cpu_to_le64(qw0);
+
+ return 0;
}
static int reset_hw_v1_hw(struct hisi_hba *hisi_hba)
@@ -750,7 +752,7 @@
rc = reset_hw_v1_hw(hisi_hba);
if (rc) {
- dev_err(dev, "hisi_sas_reset_hw failed, rc=%d", rc);
+ dev_err(dev, "hisi_sas_reset_hw failed, rc=%d\n", rc);
return rc;
}
@@ -1164,7 +1166,7 @@
case SAS_PROTOCOL_STP:
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
{
- dev_err(dev, "slot err: SATA/STP not supported");
+ dev_err(dev, "slot err: SATA/STP not supported\n");
}
break;
default:
@@ -1173,15 +1175,14 @@
}
-static int slot_complete_v1_hw(struct hisi_hba *hisi_hba,
- struct hisi_sas_slot *slot)
+static void slot_complete_v1_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
{
struct sas_task *task = slot->task;
struct hisi_sas_device *sas_dev;
struct device *dev = hisi_hba->dev;
struct task_status_struct *ts;
struct domain_device *device;
- enum exec_status sts;
struct hisi_sas_complete_v1_hdr *complete_queue =
hisi_hba->complete_hdr[slot->cmplt_queue];
struct hisi_sas_complete_v1_hdr *complete_hdr;
@@ -1192,7 +1193,7 @@
cmplt_hdr_data = le32_to_cpu(complete_hdr->data);
if (unlikely(!task || !task->lldd_task || !task->dev))
- return -EINVAL;
+ return;
ts = &task->task_status;
device = task->dev;
@@ -1217,35 +1218,35 @@
u32 info_reg = hisi_sas_read32(hisi_hba, HGC_INVLD_DQE_INFO);
if (info_reg & HGC_INVLD_DQE_INFO_DQ_MSK)
- dev_err(dev, "slot complete: [%d:%d] has dq IPTT err",
+ dev_err(dev, "slot complete: [%d:%d] has dq IPTT err\n",
slot->cmplt_queue, slot->cmplt_queue_slot);
if (info_reg & HGC_INVLD_DQE_INFO_TYPE_MSK)
- dev_err(dev, "slot complete: [%d:%d] has dq type err",
+ dev_err(dev, "slot complete: [%d:%d] has dq type err\n",
slot->cmplt_queue, slot->cmplt_queue_slot);
if (info_reg & HGC_INVLD_DQE_INFO_FORCE_MSK)
- dev_err(dev, "slot complete: [%d:%d] has dq force phy err",
+ dev_err(dev, "slot complete: [%d:%d] has dq force phy err\n",
slot->cmplt_queue, slot->cmplt_queue_slot);
if (info_reg & HGC_INVLD_DQE_INFO_PHY_MSK)
- dev_err(dev, "slot complete: [%d:%d] has dq phy id err",
+ dev_err(dev, "slot complete: [%d:%d] has dq phy id err\n",
slot->cmplt_queue, slot->cmplt_queue_slot);
if (info_reg & HGC_INVLD_DQE_INFO_ABORT_MSK)
- dev_err(dev, "slot complete: [%d:%d] has dq abort flag err",
+ dev_err(dev, "slot complete: [%d:%d] has dq abort flag err\n",
slot->cmplt_queue, slot->cmplt_queue_slot);
if (info_reg & HGC_INVLD_DQE_INFO_IPTT_OF_MSK)
- dev_err(dev, "slot complete: [%d:%d] has dq IPTT or ICT err",
+ dev_err(dev, "slot complete: [%d:%d] has dq IPTT or ICT err\n",
slot->cmplt_queue, slot->cmplt_queue_slot);
if (info_reg & HGC_INVLD_DQE_INFO_SSP_ERR_MSK)
- dev_err(dev, "slot complete: [%d:%d] has dq SSP frame type err",
+ dev_err(dev, "slot complete: [%d:%d] has dq SSP frame type err\n",
slot->cmplt_queue, slot->cmplt_queue_slot);
if (info_reg & HGC_INVLD_DQE_INFO_OFL_MSK)
- dev_err(dev, "slot complete: [%d:%d] has dq order frame len err",
+ dev_err(dev, "slot complete: [%d:%d] has dq order frame len err\n",
slot->cmplt_queue, slot->cmplt_queue_slot);
ts->stat = SAS_OPEN_REJECT;
@@ -1257,8 +1258,10 @@
!(cmplt_hdr_data & CMPLT_HDR_RSPNS_XFRD_MSK)) {
slot_err_v1_hw(hisi_hba, task, slot);
- if (unlikely(slot->abort))
- return ts->stat;
+ if (unlikely(slot->abort)) {
+ sas_task_abort(task);
+ return;
+ }
goto out;
}
@@ -1291,7 +1294,7 @@
case SAS_PROTOCOL_SATA:
case SAS_PROTOCOL_STP:
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
- dev_err(dev, "slot complete: SATA/STP not supported");
+ dev_err(dev, "slot complete: SATA/STP not supported\n");
break;
default:
@@ -1307,12 +1310,9 @@
out:
hisi_sas_slot_task_free(hisi_hba, task, slot);
- sts = ts->stat;
if (task->task_done)
task->task_done(task);
-
- return sts;
}
/* Interrupts */
@@ -1408,7 +1408,6 @@
struct hisi_sas_phy *phy = p;
struct hisi_hba *hisi_hba = phy->hisi_hba;
struct asd_sas_phy *sas_phy = &phy->sas_phy;
- struct sas_ha_struct *sha = &hisi_hba->sha;
struct device *dev = hisi_hba->dev;
int phy_no = sas_phy->id;
u32 irq_value;
@@ -1417,14 +1416,14 @@
irq_value = hisi_sas_phy_read32(hisi_hba, phy_no, CHL_INT2);
if (!(irq_value & CHL_INT2_SL_RX_BC_ACK_MSK)) {
- dev_err(dev, "bcast: irq_value = %x not set enable bit",
+ dev_err(dev, "bcast: irq_value = %x not set enable bit\n",
irq_value);
res = IRQ_NONE;
goto end;
}
if (!test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags))
- sha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
end:
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2,
@@ -1755,8 +1754,10 @@
static struct scsi_host_template sht_v1_hw = {
.name = DRV_NAME,
+ .proc_name = DRV_NAME,
.module = THIS_MODULE,
.queuecommand = sas_queuecommand,
+ .dma_need_drain = ata_scsi_dma_need_drain,
.target_alloc = sas_target_alloc,
.slave_configure = hisi_sas_slave_configure,
.scan_finished = hisi_sas_scan_finished,
@@ -1771,6 +1772,9 @@
.slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = sas_ioctl,
+#endif
.shost_attrs = host_attrs_v1_hw,
.host_reset = hisi_sas_host_reset,
};
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 11c7588..b75d543 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -773,7 +773,6 @@
struct hisi_sas_device *sas_dev = device->lldd_dev;
int sata_idx = sas_dev->sata_idx;
int start, end;
- unsigned long flags;
if (!sata_dev) {
/*
@@ -797,12 +796,12 @@
end = 64 * (sata_idx + 2);
}
- spin_lock_irqsave(&hisi_hba->lock, flags);
+ spin_lock(&hisi_hba->lock);
while (1) {
start = find_next_zero_bit(bitmap,
hisi_hba->slot_index_count, start);
if (start >= end) {
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+ spin_unlock(&hisi_hba->lock);
return -SAS_QUEUE_FULL;
}
/*
@@ -814,7 +813,7 @@
}
set_bit(start, bitmap);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+ spin_unlock(&hisi_hba->lock);
return start;
}
@@ -843,9 +842,8 @@
struct hisi_sas_device *sas_dev = NULL;
int i, sata_dev = dev_is_sata(device);
int sata_idx = -1;
- unsigned long flags;
- spin_lock_irqsave(&hisi_hba->lock, flags);
+ spin_lock(&hisi_hba->lock);
if (sata_dev)
if (!sata_index_alloc_v2_hw(hisi_hba, &sata_idx))
@@ -876,7 +874,7 @@
}
out:
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+ spin_unlock(&hisi_hba->lock);
return sas_dev;
}
@@ -974,13 +972,14 @@
(0x1ULL << ITCT_HDR_RTOLT_OFF));
}
-static void clear_itct_v2_hw(struct hisi_hba *hisi_hba,
- struct hisi_sas_device *sas_dev)
+static int clear_itct_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_device *sas_dev)
{
DECLARE_COMPLETION_ONSTACK(completion);
u64 dev_id = sas_dev->device_id;
struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
+ struct device *dev = hisi_hba->dev;
int i;
sas_dev->completion = &completion;
@@ -990,13 +989,19 @@
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
ENT_INT_SRC3_ITC_INT_MSK);
+ /* need to set register twice to clear ITCT for v2 hw */
for (i = 0; i < 2; i++) {
reg_val = ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK);
hisi_sas_write32(hisi_hba, ITCT_CLR, reg_val);
- wait_for_completion(sas_dev->completion);
+ if (!wait_for_completion_timeout(sas_dev->completion,
+ CLEAR_ITCT_TIMEOUT * HZ)) {
+ dev_warn(dev, "failed to clear ITCT\n");
+ return -ETIMEDOUT;
+ }
memset(itct, 0, sizeof(struct hisi_sas_itct));
}
+ return 0;
}
static void free_device_v2_hw(struct hisi_sas_device *sas_dev)
@@ -1197,7 +1202,7 @@
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0x7ffe20fe);
hisi_sas_write32(hisi_hba, SAS_ECC_INTR_MSK, 0xfff00c30);
for (i = 0; i < hisi_hba->queue_count; i++)
- hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK+0x4*i, 0);
+ hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0);
hisi_sas_write32(hisi_hba, AXI_AHB_CLK_CFG, 1);
hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1);
@@ -1377,7 +1382,7 @@
rc = reset_hw_v2_hw(hisi_hba);
if (rc) {
- dev_err(dev, "hisi_sas_reset_hw failed, rc=%d", rc);
+ dev_err(dev, "hisi_sas_reset_hw failed, rc=%d\n", rc);
return rc;
}
@@ -2313,8 +2318,8 @@
}
}
-static int
-slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+static void slot_complete_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
{
struct sas_task *task = slot->task;
struct hisi_sas_device *sas_dev;
@@ -2322,7 +2327,6 @@
struct task_status_struct *ts;
struct domain_device *device;
struct sas_ha_struct *ha;
- enum exec_status sts;
struct hisi_sas_complete_v2_hdr *complete_queue =
hisi_hba->complete_hdr[slot->cmplt_queue];
struct hisi_sas_complete_v2_hdr *complete_hdr =
@@ -2332,7 +2336,7 @@
u32 dw0;
if (unlikely(!task || !task->lldd_task || !task->dev))
- return -EINVAL;
+ return;
ts = &task->task_status;
device = task->dev;
@@ -2400,8 +2404,10 @@
error_info[0], error_info[1],
error_info[2], error_info[3]);
- if (unlikely(slot->abort))
- return ts->stat;
+ if (unlikely(slot->abort)) {
+ sas_task_abort(task);
+ return;
+ }
goto out;
}
@@ -2451,12 +2457,11 @@
}
out:
- sts = ts->stat;
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
dev_info(dev, "slot complete: task(%pK) aborted\n", task);
- return SAS_ABORTED_TASK;
+ return;
}
task->task_state_flags |= SAS_TASK_STATE_DONE;
spin_unlock_irqrestore(&task->task_state_lock, flags);
@@ -2468,15 +2473,13 @@
spin_unlock_irqrestore(&device->done_lock, flags);
dev_info(dev, "slot complete: task(%pK) ignored\n",
task);
- return sts;
+ return;
}
spin_unlock_irqrestore(&device->done_lock, flags);
}
if (task->task_done)
task->task_done(task);
-
- return sts;
}
static void prep_ata_v2_hw(struct hisi_hba *hisi_hba,
@@ -2815,14 +2818,13 @@
{
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
- struct sas_ha_struct *sas_ha = &hisi_hba->sha;
u32 bcast_status;
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 1);
bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS);
if ((bcast_status & RX_BCAST_CHG_MSK) &&
!test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags))
- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
CHL_INT0_SL_RX_BCST_ACK_MSK);
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0);
@@ -3104,9 +3106,9 @@
return IRQ_HANDLED;
}
-static void cq_tasklet_v2_hw(unsigned long val)
+static irqreturn_t cq_thread_v2_hw(int irq_no, void *p)
{
- struct hisi_sas_cq *cq = (struct hisi_sas_cq *)val;
+ struct hisi_sas_cq *cq = p;
struct hisi_hba *hisi_hba = cq->hisi_hba;
struct hisi_sas_slot *slot;
struct hisi_sas_itct *itct;
@@ -3174,6 +3176,8 @@
/* update rd_point */
cq->rd_point = rd_point;
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
+
+ return IRQ_HANDLED;
}
static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
@@ -3184,9 +3188,7 @@
hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
- tasklet_schedule(&cq->tasklet);
-
- return IRQ_HANDLED;
+ return IRQ_WAKE_THREAD;
}
static irqreturn_t sata_int_v2_hw(int irq_no, void *p)
@@ -3299,7 +3301,7 @@
fatal_axi_int_v2_hw
};
-/**
+/*
* There is a limitation in the hip06 chipset that we need
* to map in all mbigen interrupts, even if they are not used.
*/
@@ -3353,18 +3355,18 @@
for (queue_no = 0; queue_no < hisi_hba->queue_count; queue_no++) {
struct hisi_sas_cq *cq = &hisi_hba->cq[queue_no];
- struct tasklet_struct *t = &cq->tasklet;
- irq = irq_map[queue_no + 96];
- rc = devm_request_irq(dev, irq, cq_interrupt_v2_hw, 0,
- DRV_NAME " cq", cq);
+ cq->irq_no = irq_map[queue_no + 96];
+ rc = devm_request_threaded_irq(dev, cq->irq_no,
+ cq_interrupt_v2_hw,
+ cq_thread_v2_hw, IRQF_ONESHOT,
+ DRV_NAME " cq", cq);
if (rc) {
dev_err(dev, "irq init: could not request cq interrupt %d, rc=%d\n",
irq, rc);
rc = -ENOENT;
goto err_out;
}
- tasklet_init(t, cq_tasklet_v2_hw, (unsigned long)cq);
}
hisi_hba->cq_nvecs = hisi_hba->queue_count;
@@ -3425,7 +3427,6 @@
interrupt_disable_v2_hw(hisi_hba);
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
- hisi_sas_kill_tasklets(hisi_hba);
hisi_sas_stop_phys(hisi_hba);
@@ -3529,8 +3530,10 @@
static struct scsi_host_template sht_v2_hw = {
.name = DRV_NAME,
+ .proc_name = DRV_NAME,
.module = THIS_MODULE,
.queuecommand = sas_queuecommand,
+ .dma_need_drain = ata_scsi_dma_need_drain,
.target_alloc = sas_target_alloc,
.slave_configure = hisi_sas_slave_configure,
.scan_finished = hisi_sas_scan_finished,
@@ -3545,6 +3548,9 @@
.slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = sas_ioctl,
+#endif
.shost_attrs = host_attrs_v2_hw,
.host_reset = hisi_sas_host_reset,
};
@@ -3597,11 +3603,6 @@
static int hisi_sas_v2_remove(struct platform_device *pdev)
{
- struct sas_ha_struct *sha = platform_get_drvdata(pdev);
- struct hisi_hba *hisi_hba = sha->lldd_ha;
-
- hisi_sas_kill_tasklets(hisi_hba);
-
return hisi_sas_remove(pdev);
}
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 13f314f..50a1c34 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -191,8 +191,10 @@
#define PHY_CFG_PHY_RST_OFF 3
#define PHY_CFG_PHY_RST_MSK (0x1 << PHY_CFG_PHY_RST_OFF)
#define PROG_PHY_LINK_RATE (PORT_BASE + 0x8)
-#define CFG_PROG_PHY_LINK_RATE_OFF 8
-#define CFG_PROG_PHY_LINK_RATE_MSK (0xf << CFG_PROG_PHY_LINK_RATE_OFF)
+#define CFG_PROG_PHY_LINK_RATE_OFF 0
+#define CFG_PROG_PHY_LINK_RATE_MSK (0xff << CFG_PROG_PHY_LINK_RATE_OFF)
+#define CFG_PROG_OOB_PHY_LINK_RATE_OFF 8
+#define CFG_PROG_OOB_PHY_LINK_RATE_MSK (0xf << CFG_PROG_OOB_PHY_LINK_RATE_OFF)
#define PHY_CTRL (PORT_BASE + 0x14)
#define PHY_CTRL_RESET_OFF 0
#define PHY_CTRL_RESET_MSK (0x1 << PHY_CTRL_RESET_OFF)
@@ -295,6 +297,7 @@
#define DMA_RX_STATUS_BUSY_MSK (0x1 << DMA_RX_STATUS_BUSY_OFF)
#define COARSETUNE_TIME (PORT_BASE + 0x304)
+#define TXDEEMPH_G1 (PORT_BASE + 0x350)
#define ERR_CNT_DWS_LOST (PORT_BASE + 0x380)
#define ERR_CNT_RESET_PROB (PORT_BASE + 0x384)
#define ERR_CNT_INVLD_DW (PORT_BASE + 0x390)
@@ -495,6 +498,13 @@
#define BASE_VECTORS_V3_HW 16
#define MIN_AFFINE_VECTORS_V3_HW (BASE_VECTORS_V3_HW + 1)
+#define CHNL_INT_STS_MSK 0xeeeeeeee
+#define CHNL_INT_STS_PHY_MSK 0xe
+#define CHNL_INT_STS_INT0_MSK BIT(1)
+#define CHNL_INT_STS_INT1_MSK BIT(2)
+#define CHNL_INT_STS_INT2_MSK BIT(3)
+#define CHNL_WIDTH 4
+
enum {
DSM_FUNC_ERR_HANDLE_MSI = 0,
};
@@ -558,7 +568,7 @@
static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
{
- int i;
+ int i, j;
/* Global registers init */
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE,
@@ -586,25 +596,24 @@
hisi_sas_write32(hisi_hba, AWQOS_AWCACHE_CFG, 0xf0f0);
hisi_sas_write32(hisi_hba, ARQOS_ARCACHE_CFG, 0xf0f0);
for (i = 0; i < hisi_hba->queue_count; i++)
- hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK+0x4*i, 0);
+ hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0);
hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1);
for (i = 0; i < hisi_hba->n_phy; i++) {
+ enum sas_linkrate max;
struct hisi_sas_phy *phy = &hisi_hba->phy[i];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
- u32 prog_phy_link_rate = 0x800;
+ u32 prog_phy_link_rate = hisi_sas_phy_read32(hisi_hba, i,
+ PROG_PHY_LINK_RATE);
+ prog_phy_link_rate &= ~CFG_PROG_PHY_LINK_RATE_MSK;
if (!sas_phy->phy || (sas_phy->phy->maximum_linkrate <
- SAS_LINK_RATE_1_5_GBPS)) {
- prog_phy_link_rate = 0x855;
- } else {
- enum sas_linkrate max = sas_phy->phy->maximum_linkrate;
-
- prog_phy_link_rate =
- hisi_sas_get_prog_phy_linkrate_mask(max) |
- 0x800;
- }
+ SAS_LINK_RATE_1_5_GBPS))
+ max = SAS_LINK_RATE_12_0_GBPS;
+ else
+ max = sas_phy->phy->maximum_linkrate;
+ prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max);
hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE,
prog_phy_link_rate);
hisi_sas_phy_write32(hisi_hba, i, SERDES_CFG, 0xffc00);
@@ -629,6 +638,13 @@
/* used for 12G negotiate */
hisi_sas_phy_write32(hisi_hba, i, COARSETUNE_TIME, 0x1e);
hisi_sas_phy_write32(hisi_hba, i, AIP_LIMIT, 0x2ffff);
+
+ /* get default FFE configuration for BIST */
+ for (j = 0; j < FFE_CFG_MAX; j++) {
+ u32 val = hisi_sas_phy_read32(hisi_hba, i,
+ TXDEEMPH_G1 + (j * 0x4));
+ hisi_hba->debugfs_bist_ffe[i][j] = val;
+ }
}
for (i = 0; i < hisi_hba->queue_count; i++) {
@@ -795,13 +811,14 @@
(0x1ULL << ITCT_HDR_RTOLT_OFF));
}
-static void clear_itct_v3_hw(struct hisi_hba *hisi_hba,
- struct hisi_sas_device *sas_dev)
+static int clear_itct_v3_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_device *sas_dev)
{
DECLARE_COMPLETION_ONSTACK(completion);
u64 dev_id = sas_dev->device_id;
struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
+ struct device *dev = hisi_hba->dev;
sas_dev->completion = &completion;
@@ -814,8 +831,14 @@
reg_val = ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK);
hisi_sas_write32(hisi_hba, ITCT_CLR, reg_val);
- wait_for_completion(sas_dev->completion);
+ if (!wait_for_completion_timeout(sas_dev->completion,
+ CLEAR_ITCT_TIMEOUT * HZ)) {
+ dev_warn(dev, "failed to clear ITCT\n");
+ return -ETIMEDOUT;
+ }
+
memset(itct, 0, sizeof(struct hisi_sas_itct));
+ return 0;
}
static void dereg_device_v3_hw(struct hisi_hba *hisi_hba,
@@ -880,13 +903,14 @@
static int hw_init_v3_hw(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
+ struct acpi_device *acpi_dev;
union acpi_object *obj;
guid_t guid;
int rc;
rc = reset_hw_v3_hw(hisi_hba);
if (rc) {
- dev_err(dev, "hisi_sas_reset_hw failed, rc=%d", rc);
+ dev_err(dev, "hisi_sas_reset_hw failed, rc=%d\n", rc);
return rc;
}
@@ -898,14 +922,21 @@
return -EINVAL;
}
- /* Switch over to MSI handling , from PCI AER default */
+ /*
+ * This DSM handles some hardware-related configurations:
+ * 1. Switch over to MSI error handling in kernel
+ * 2. BIOS *may* reset some register values through this method
+ */
obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), &guid, 0,
DSM_FUNC_ERR_HANDLE_MSI, NULL);
if (!obj)
- dev_warn(dev, "Switch over to MSI handling failed\n");
+ dev_warn(dev, "can not find DSM method, ignore\n");
else
ACPI_FREE(obj);
+ acpi_dev = ACPI_COMPANION(dev);
+ if (!acpi_device_power_manageable(acpi_dev))
+ dev_notice(dev, "neither _PS0 nor _PR0 is defined\n");
return 0;
}
@@ -1323,7 +1354,6 @@
hdr->cmd_table_addr = cpu_to_le64(req_dma_addr);
hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot));
-
}
static void prep_ata_v3_hw(struct hisi_hba *hisi_hba,
@@ -1429,7 +1459,6 @@
/* dw7 */
hdr->dw7 = cpu_to_le32(tag_to_abort << CMD_HDR_ABORT_IPTT_OFF);
hdr->transfer_tags = cpu_to_le32(slot->idx);
-
}
static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
@@ -1542,6 +1571,8 @@
u32 phy_state, sl_ctrl, txid_auto;
struct device *dev = hisi_hba->dev;
+ atomic_inc(&phy->down_cnt);
+
del_timer(&phy->timer);
hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1);
@@ -1567,14 +1598,13 @@
{
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
- struct sas_ha_struct *sas_ha = &hisi_hba->sha;
u32 bcast_status;
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 1);
bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS);
if ((bcast_status & RX_BCAST_CHG_MSK) &&
!test_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags))
- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
CHL_INT0_SL_RX_BCST_ACK_MSK);
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0);
@@ -1810,19 +1840,19 @@
int phy_no = 0;
irq_msk = hisi_sas_read32(hisi_hba, CHNL_INT_STATUS)
- & 0xeeeeeeee;
+ & CHNL_INT_STS_MSK;
while (irq_msk) {
- if (irq_msk & (2 << (phy_no * 4)))
+ if (irq_msk & (CHNL_INT_STS_INT0_MSK << (phy_no * CHNL_WIDTH)))
handle_chl_int0_v3_hw(hisi_hba, phy_no);
- if (irq_msk & (4 << (phy_no * 4)))
+ if (irq_msk & (CHNL_INT_STS_INT1_MSK << (phy_no * CHNL_WIDTH)))
handle_chl_int1_v3_hw(hisi_hba, phy_no);
- if (irq_msk & (8 << (phy_no * 4)))
+ if (irq_msk & (CHNL_INT_STS_INT2_MSK << (phy_no * CHNL_WIDTH)))
handle_chl_int2_v3_hw(hisi_hba, phy_no);
- irq_msk &= ~(0xe << (phy_no * 4));
+ irq_msk &= ~(CHNL_INT_STS_PHY_MSK << (phy_no * CHNL_WIDTH));
phy_no++;
}
@@ -2136,8 +2166,8 @@
}
}
-static int
-slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
+static void slot_complete_v3_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
{
struct sas_task *task = slot->task;
struct hisi_sas_device *sas_dev;
@@ -2145,7 +2175,6 @@
struct task_status_struct *ts;
struct domain_device *device;
struct sas_ha_struct *ha;
- enum exec_status sts;
struct hisi_sas_complete_v3_hdr *complete_queue =
hisi_hba->complete_hdr[slot->cmplt_queue];
struct hisi_sas_complete_v3_hdr *complete_hdr =
@@ -2155,7 +2184,7 @@
u32 dw0, dw1, dw3;
if (unlikely(!task || !task->lldd_task || !task->dev))
- return -EINVAL;
+ return;
ts = &task->task_status;
device = task->dev;
@@ -2216,8 +2245,10 @@
dw0, dw1, complete_hdr->act, dw3,
error_info[0], error_info[1],
error_info[2], error_info[3]);
- if (unlikely(slot->abort))
- return ts->stat;
+ if (unlikely(slot->abort)) {
+ sas_task_abort(task);
+ return;
+ }
goto out;
}
@@ -2262,12 +2293,11 @@
}
out:
- sts = ts->stat;
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
dev_info(dev, "slot complete: task(%pK) aborted\n", task);
- return SAS_ABORTED_TASK;
+ return;
}
task->task_state_flags |= SAS_TASK_STATE_DONE;
spin_unlock_irqrestore(&task->task_state_lock, flags);
@@ -2279,20 +2309,18 @@
spin_unlock_irqrestore(&device->done_lock, flags);
dev_info(dev, "slot complete: task(%pK) ignored\n ",
task);
- return sts;
+ return;
}
spin_unlock_irqrestore(&device->done_lock, flags);
}
if (task->task_done)
task->task_done(task);
-
- return sts;
}
-static void cq_tasklet_v3_hw(unsigned long val)
+static irqreturn_t cq_thread_v3_hw(int irq_no, void *p)
{
- struct hisi_sas_cq *cq = (struct hisi_sas_cq *)val;
+ struct hisi_sas_cq *cq = p;
struct hisi_hba *hisi_hba = cq->hisi_hba;
struct hisi_sas_slot *slot;
struct hisi_sas_complete_v3_hdr *complete_queue;
@@ -2329,6 +2357,8 @@
/* update rd_point */
cq->rd_point = rd_point;
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
+
+ return IRQ_HANDLED;
}
static irqreturn_t cq_interrupt_v3_hw(int irq_no, void *p)
@@ -2339,79 +2369,46 @@
hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
- tasklet_schedule(&cq->tasklet);
-
- return IRQ_HANDLED;
+ return IRQ_WAKE_THREAD;
}
-static void setup_reply_map_v3_hw(struct hisi_hba *hisi_hba, int nvecs)
+static int interrupt_preinit_v3_hw(struct hisi_hba *hisi_hba)
{
- const struct cpumask *mask;
- int queue, cpu;
+ int vectors;
+ int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi;
+ struct Scsi_Host *shost = hisi_hba->shost;
+ struct irq_affinity desc = {
+ .pre_vectors = BASE_VECTORS_V3_HW,
+ };
- for (queue = 0; queue < nvecs; queue++) {
- struct hisi_sas_cq *cq = &hisi_hba->cq[queue];
+ min_msi = MIN_AFFINE_VECTORS_V3_HW;
+ vectors = pci_alloc_irq_vectors_affinity(hisi_hba->pci_dev,
+ min_msi, max_msi,
+ PCI_IRQ_MSI |
+ PCI_IRQ_AFFINITY,
+ &desc);
+ if (vectors < 0)
+ return -ENOENT;
- mask = pci_irq_get_affinity(hisi_hba->pci_dev, queue +
- BASE_VECTORS_V3_HW);
- if (!mask)
- goto fallback;
- cq->pci_irq_mask = mask;
- for_each_cpu(cpu, mask)
- hisi_hba->reply_map[cpu] = queue;
- }
- return;
-fallback:
- for_each_possible_cpu(cpu)
- hisi_hba->reply_map[cpu] = cpu % hisi_hba->queue_count;
- /* Don't clean all CQ masks */
+ hisi_hba->cq_nvecs = vectors - BASE_VECTORS_V3_HW;
+ shost->nr_hw_queues = hisi_hba->cq_nvecs;
+
+ return 0;
}
static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
struct pci_dev *pdev = hisi_hba->pci_dev;
- int vectors, rc, i;
- int max_msi = HISI_SAS_MSI_COUNT_V3_HW, min_msi;
-
- if (auto_affine_msi_experimental) {
- struct irq_affinity desc = {
- .pre_vectors = BASE_VECTORS_V3_HW,
- };
-
- min_msi = MIN_AFFINE_VECTORS_V3_HW;
-
- hisi_hba->reply_map = devm_kcalloc(dev, nr_cpu_ids,
- sizeof(unsigned int),
- GFP_KERNEL);
- if (!hisi_hba->reply_map)
- return -ENOMEM;
- vectors = pci_alloc_irq_vectors_affinity(hisi_hba->pci_dev,
- min_msi, max_msi,
- PCI_IRQ_MSI |
- PCI_IRQ_AFFINITY,
- &desc);
- if (vectors < 0)
- return -ENOENT;
- setup_reply_map_v3_hw(hisi_hba, vectors - BASE_VECTORS_V3_HW);
- } else {
- min_msi = max_msi;
- vectors = pci_alloc_irq_vectors(hisi_hba->pci_dev, min_msi,
- max_msi, PCI_IRQ_MSI);
- if (vectors < 0)
- return vectors;
- }
-
- hisi_hba->cq_nvecs = vectors - BASE_VECTORS_V3_HW;
+ int rc, i;
rc = devm_request_irq(dev, pci_irq_vector(pdev, 1),
int_phy_up_down_bcast_v3_hw, 0,
DRV_NAME " phy", hisi_hba);
if (rc) {
dev_err(dev, "could not request phy interrupt, rc=%d\n", rc);
- rc = -ENOENT;
- goto free_irq_vectors;
+ return -ENOENT;
}
rc = devm_request_irq(dev, pci_irq_vector(pdev, 2),
@@ -2419,8 +2416,7 @@
DRV_NAME " channel", hisi_hba);
if (rc) {
dev_err(dev, "could not request chnl interrupt, rc=%d\n", rc);
- rc = -ENOENT;
- goto free_irq_vectors;
+ return -ENOENT;
}
rc = devm_request_irq(dev, pci_irq_vector(pdev, 11),
@@ -2428,35 +2424,37 @@
DRV_NAME " fatal", hisi_hba);
if (rc) {
dev_err(dev, "could not request fatal interrupt, rc=%d\n", rc);
- rc = -ENOENT;
- goto free_irq_vectors;
+ return -ENOENT;
}
- /* Init tasklets for cq only */
+ if (hisi_sas_intr_conv)
+ dev_info(dev, "Enable interrupt converge\n");
+
for (i = 0; i < hisi_hba->cq_nvecs; i++) {
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
- struct tasklet_struct *t = &cq->tasklet;
int nr = hisi_sas_intr_conv ? 16 : 16 + i;
- unsigned long irqflags = hisi_sas_intr_conv ? IRQF_SHARED : 0;
+ unsigned long irqflags = hisi_sas_intr_conv ? IRQF_SHARED :
+ IRQF_ONESHOT;
- rc = devm_request_irq(dev, pci_irq_vector(pdev, nr),
- cq_interrupt_v3_hw, irqflags,
+ cq->irq_no = pci_irq_vector(pdev, nr);
+ rc = devm_request_threaded_irq(dev, cq->irq_no,
+ cq_interrupt_v3_hw,
+ cq_thread_v3_hw,
+ irqflags,
DRV_NAME " cq", cq);
if (rc) {
dev_err(dev, "could not request cq%d interrupt, rc=%d\n",
i, rc);
- rc = -ENOENT;
- goto free_irq_vectors;
+ return -ENOENT;
}
-
- tasklet_init(t, cq_tasklet_v3_hw, (unsigned long)cq);
+ cq->irq_mask = pci_irq_get_affinity(pdev, i + BASE_VECTORS_V3_HW);
+ if (!cq->irq_mask) {
+ dev_err(dev, "could not get cq%d irq affinity!\n", i);
+ return -ENOENT;
+ }
}
return 0;
-
-free_irq_vectors:
- pci_free_irq_vectors(pdev);
- return rc;
}
static int hisi_sas_v3_init(struct hisi_hba *hisi_hba)
@@ -2478,8 +2476,10 @@
struct sas_phy_linkrates *r)
{
enum sas_linkrate max = r->maximum_linkrate;
- u32 prog_phy_link_rate = 0x800;
+ u32 prog_phy_link_rate = hisi_sas_phy_read32(hisi_hba, phy_no,
+ PROG_PHY_LINK_RATE);
+ prog_phy_link_rate &= ~CFG_PROG_PHY_LINK_RATE_MSK;
prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max);
hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
prog_phy_link_rate);
@@ -2493,10 +2493,11 @@
synchronize_irq(pci_irq_vector(pdev, 1));
synchronize_irq(pci_irq_vector(pdev, 2));
synchronize_irq(pci_irq_vector(pdev, 11));
- for (i = 0; i < hisi_hba->queue_count; i++) {
+ for (i = 0; i < hisi_hba->queue_count; i++)
hisi_sas_write32(hisi_hba, OQ0_INT_SRC_MSK + 0x4 * i, 0x1);
+
+ for (i = 0; i < hisi_hba->cq_nvecs; i++)
synchronize_irq(pci_irq_vector(pdev, i + 16));
- }
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xffffffff);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0xffffffff);
@@ -2525,7 +2526,6 @@
interrupt_disable_v3_hw(hisi_hba);
hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
- hisi_sas_kill_tasklets(hisi_hba);
hisi_sas_stop_phys(hisi_hba);
@@ -2722,6 +2722,33 @@
}
static DEVICE_ATTR_RW(intr_coal_count_v3_hw);
+static int slave_configure_v3_hw(struct scsi_device *sdev)
+{
+ struct Scsi_Host *shost = dev_to_shost(&sdev->sdev_gendev);
+ struct domain_device *ddev = sdev_to_domain_dev(sdev);
+ struct hisi_hba *hisi_hba = shost_priv(shost);
+ struct device *dev = hisi_hba->dev;
+ int ret = sas_slave_configure(sdev);
+
+ if (ret)
+ return ret;
+ if (!dev_is_sata(ddev))
+ sas_change_queue_depth(sdev, 64);
+
+ if (sdev->type == TYPE_ENCLOSURE)
+ return 0;
+
+ if (!device_link_add(&sdev->sdev_gendev, dev,
+ DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE)) {
+ if (pm_runtime_enabled(dev)) {
+ dev_info(dev, "add device link failed, disable runtime PM for the host\n");
+ pm_runtime_disable(dev);
+ }
+ }
+
+ return 0;
+}
+
static struct device_attribute *host_attrs_v3_hw[] = {
&dev_attr_phy_event_threshold,
&dev_attr_intr_conv_v3_hw,
@@ -2877,6 +2904,7 @@
};
static const struct hisi_sas_debugfs_reg_lu debugfs_ras_reg_lu[] = {
+ HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR0),
HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR1),
HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR0_MASK),
HISI_SAS_DEBUGFS_REG(SAS_RAS_INTR1_MASK),
@@ -2901,7 +2929,7 @@
wait_cmds_complete_timeout_v3_hw(hisi_hba, 100, 5000);
- hisi_sas_kill_tasklets(hisi_hba);
+ hisi_sas_sync_irqs(hisi_hba);
}
static void debugfs_snapshot_restore_v3_hw(struct hisi_hba *hisi_hba)
@@ -2918,6 +2946,7 @@
{
u32 cache_dw_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ *
HISI_SAS_IOST_ITCT_CACHE_NUM;
+ struct device *dev = hisi_hba->dev;
u32 *buf = cache;
u32 i, val;
@@ -2930,7 +2959,7 @@
}
if (val != 0xffffffff) {
- pr_err("Issue occur when reading IOST/ITCT cache!\n");
+ dev_err(dev, "Issue occurred in reading IOST/ITCT cache!\n");
return;
}
@@ -2944,42 +2973,48 @@
static void hisi_sas_bist_test_prep_v3_hw(struct hisi_hba *hisi_hba)
{
u32 reg_val;
- int phy_id = hisi_hba->debugfs_bist_phy_no;
+ int phy_no = hisi_hba->debugfs_bist_phy_no;
+ int i;
/* disable PHY */
- hisi_sas_phy_enable(hisi_hba, phy_id, 0);
+ hisi_sas_phy_enable(hisi_hba, phy_no, 0);
+
+ /* update FFE */
+ for (i = 0; i < FFE_CFG_MAX; i++)
+ hisi_sas_phy_write32(hisi_hba, phy_no, TXDEEMPH_G1 + (i * 0x4),
+ hisi_hba->debugfs_bist_ffe[phy_no][i]);
/* disable ALOS */
- reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SERDES_CFG);
+ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SERDES_CFG);
reg_val |= CFG_ALOS_CHK_DISABLE_MSK;
- hisi_sas_phy_write32(hisi_hba, phy_id, SERDES_CFG, reg_val);
+ hisi_sas_phy_write32(hisi_hba, phy_no, SERDES_CFG, reg_val);
}
static void hisi_sas_bist_test_restore_v3_hw(struct hisi_hba *hisi_hba)
{
u32 reg_val;
- int phy_id = hisi_hba->debugfs_bist_phy_no;
+ int phy_no = hisi_hba->debugfs_bist_phy_no;
/* disable loopback */
- reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SAS_PHY_BIST_CTRL);
+ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL);
reg_val &= ~(CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK |
CFG_BIST_TEST_MSK);
- hisi_sas_phy_write32(hisi_hba, phy_id, SAS_PHY_BIST_CTRL, reg_val);
+ hisi_sas_phy_write32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL, reg_val);
/* enable ALOS */
- reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, SERDES_CFG);
+ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, SERDES_CFG);
reg_val &= ~CFG_ALOS_CHK_DISABLE_MSK;
- hisi_sas_phy_write32(hisi_hba, phy_id, SERDES_CFG, reg_val);
+ hisi_sas_phy_write32(hisi_hba, phy_no, SERDES_CFG, reg_val);
/* restore the linkrate */
- reg_val = hisi_sas_phy_read32(hisi_hba, phy_id, PROG_PHY_LINK_RATE);
+ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no, PROG_PHY_LINK_RATE);
/* init OOB link rate as 1.5 Gbits */
- reg_val &= ~CFG_PROG_PHY_LINK_RATE_MSK;
- reg_val |= (0x8 << CFG_PROG_PHY_LINK_RATE_OFF);
- hisi_sas_phy_write32(hisi_hba, phy_id, PROG_PHY_LINK_RATE, reg_val);
+ reg_val &= ~CFG_PROG_OOB_PHY_LINK_RATE_MSK;
+ reg_val |= (0x8 << CFG_PROG_OOB_PHY_LINK_RATE_OFF);
+ hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE, reg_val);
/* enable PHY */
- hisi_sas_phy_enable(hisi_hba, phy_id, 1);
+ hisi_sas_phy_enable(hisi_hba, phy_no, 1);
}
#define SAS_PHY_BIST_CODE_INIT 0x1
@@ -2988,74 +3023,101 @@
{
u32 reg_val, mode_tmp;
u32 linkrate = hisi_hba->debugfs_bist_linkrate;
- u32 phy_id = hisi_hba->debugfs_bist_phy_no;
+ u32 phy_no = hisi_hba->debugfs_bist_phy_no;
+ u32 *ffe = hisi_hba->debugfs_bist_ffe[phy_no];
u32 code_mode = hisi_hba->debugfs_bist_code_mode;
u32 path_mode = hisi_hba->debugfs_bist_mode;
+ u32 *fix_code = &hisi_hba->debugfs_bist_fixed_code[0];
struct device *dev = hisi_hba->dev;
- dev_info(dev, "BIST info:linkrate=%d phy_id=%d code_mode=%d path_mode=%d\n",
- linkrate, phy_id, code_mode, path_mode);
+ dev_info(dev, "BIST info:phy%d link_rate=%d code_mode=%d path_mode=%d ffe={0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x} fixed_code={0x%x, 0x%x}\n",
+ phy_no, linkrate, code_mode, path_mode,
+ ffe[FFE_SAS_1_5_GBPS], ffe[FFE_SAS_3_0_GBPS],
+ ffe[FFE_SAS_6_0_GBPS], ffe[FFE_SAS_12_0_GBPS],
+ ffe[FFE_SATA_1_5_GBPS], ffe[FFE_SATA_3_0_GBPS],
+ ffe[FFE_SATA_6_0_GBPS], fix_code[FIXED_CODE],
+ fix_code[FIXED_CODE_1]);
mode_tmp = path_mode ? 2 : 1;
if (enable) {
/* some preparations before bist test */
hisi_sas_bist_test_prep_v3_hw(hisi_hba);
/* set linkrate of bit test*/
- reg_val = hisi_sas_phy_read32(hisi_hba, phy_id,
+ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no,
PROG_PHY_LINK_RATE);
- reg_val &= ~CFG_PROG_PHY_LINK_RATE_MSK;
- reg_val |= (linkrate << CFG_PROG_PHY_LINK_RATE_OFF);
- hisi_sas_phy_write32(hisi_hba, phy_id,
- PROG_PHY_LINK_RATE, reg_val);
+ reg_val &= ~CFG_PROG_OOB_PHY_LINK_RATE_MSK;
+ reg_val |= (linkrate << CFG_PROG_OOB_PHY_LINK_RATE_OFF);
+ hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
+ reg_val);
/* set code mode of bit test */
- reg_val = hisi_sas_phy_read32(hisi_hba, phy_id,
+ reg_val = hisi_sas_phy_read32(hisi_hba, phy_no,
SAS_PHY_BIST_CTRL);
- reg_val &= ~(CFG_BIST_MODE_SEL_MSK |
- CFG_LOOP_TEST_MODE_MSK |
- CFG_RX_BIST_EN_MSK |
- CFG_TX_BIST_EN_MSK |
- CFG_BIST_TEST_MSK);
+ reg_val &= ~(CFG_BIST_MODE_SEL_MSK | CFG_LOOP_TEST_MODE_MSK |
+ CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK |
+ CFG_BIST_TEST_MSK);
reg_val |= ((code_mode << CFG_BIST_MODE_SEL_OFF) |
(mode_tmp << CFG_LOOP_TEST_MODE_OFF) |
CFG_BIST_TEST_MSK);
- hisi_sas_phy_write32(hisi_hba, phy_id,
- SAS_PHY_BIST_CTRL, reg_val);
+ hisi_sas_phy_write32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL,
+ reg_val);
/* set the bist init value */
- hisi_sas_phy_write32(hisi_hba, phy_id,
- SAS_PHY_BIST_CODE,
- SAS_PHY_BIST_CODE_INIT);
- hisi_sas_phy_write32(hisi_hba, phy_id,
- SAS_PHY_BIST_CODE1,
- SAS_PHY_BIST_CODE1_INIT);
+ if (code_mode == HISI_SAS_BIST_CODE_MODE_FIXED_DATA) {
+ reg_val = hisi_hba->debugfs_bist_fixed_code[0];
+ hisi_sas_phy_write32(hisi_hba, phy_no,
+ SAS_PHY_BIST_CODE, reg_val);
+
+ reg_val = hisi_hba->debugfs_bist_fixed_code[1];
+ hisi_sas_phy_write32(hisi_hba, phy_no,
+ SAS_PHY_BIST_CODE1, reg_val);
+ } else {
+ hisi_sas_phy_write32(hisi_hba, phy_no,
+ SAS_PHY_BIST_CODE,
+ SAS_PHY_BIST_CODE_INIT);
+ hisi_sas_phy_write32(hisi_hba, phy_no,
+ SAS_PHY_BIST_CODE1,
+ SAS_PHY_BIST_CODE1_INIT);
+ }
mdelay(100);
reg_val |= (CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK);
- hisi_sas_phy_write32(hisi_hba, phy_id,
- SAS_PHY_BIST_CTRL, reg_val);
+ hisi_sas_phy_write32(hisi_hba, phy_no, SAS_PHY_BIST_CTRL,
+ reg_val);
/* clear error bit */
mdelay(100);
- hisi_sas_phy_read32(hisi_hba, phy_id, SAS_BIST_ERR_CNT);
+ hisi_sas_phy_read32(hisi_hba, phy_no, SAS_BIST_ERR_CNT);
} else {
/* disable bist test and recover it */
hisi_hba->debugfs_bist_cnt += hisi_sas_phy_read32(hisi_hba,
- phy_id, SAS_BIST_ERR_CNT);
+ phy_no, SAS_BIST_ERR_CNT);
hisi_sas_bist_test_restore_v3_hw(hisi_hba);
}
return 0;
}
+static int hisi_sas_map_queues(struct Scsi_Host *shost)
+{
+ struct hisi_hba *hisi_hba = shost_priv(shost);
+ struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
+
+ return blk_mq_pci_map_queues(qmap, hisi_hba->pci_dev,
+ BASE_VECTORS_V3_HW);
+}
+
static struct scsi_host_template sht_v3_hw = {
.name = DRV_NAME,
+ .proc_name = DRV_NAME,
.module = THIS_MODULE,
.queuecommand = sas_queuecommand,
+ .dma_need_drain = ata_scsi_dma_need_drain,
.target_alloc = sas_target_alloc,
- .slave_configure = hisi_sas_slave_configure,
+ .slave_configure = slave_configure_v3_hw,
.scan_finished = hisi_sas_scan_finished,
.scan_start = hisi_sas_scan_start,
+ .map_queues = hisi_sas_map_queues,
.change_queue_depth = sas_change_queue_depth,
.bios_param = sas_bios_param,
.this_id = -1,
@@ -3067,9 +3129,13 @@
.slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = sas_ioctl,
+#endif
.shost_attrs = host_attrs_v3_hw,
.tag_alloc_policy = BLK_TAG_ALLOC_RR,
.host_reset = hisi_sas_host_reset,
+ .host_tagset = 1,
};
static const struct hisi_sas_hw hisi_sas_v3_hw = {
@@ -3241,9 +3307,13 @@
if (hisi_sas_debugfs_enable)
hisi_sas_debugfs_init(hisi_hba);
+ rc = interrupt_preinit_v3_hw(hisi_hba);
+ if (rc)
+ goto err_out_debugfs;
+ dev_err(dev, "%d hw queues\n", shost->nr_hw_queues);
rc = scsi_add_host(shost, dev);
if (rc)
- goto err_out_ha;
+ goto err_out_free_irq_vectors;
rc = sas_register_ha(sha);
if (rc)
@@ -3255,12 +3325,27 @@
scsi_scan_host(shost);
+ /*
+ * For the situation that there are ATA disks connected with SAS
+ * controller, it additionally creates ata_port which will affect the
+ * child_count of hisi_hba->dev. Even if suspended all the disks,
+ * ata_port is still and the child_count of hisi_hba->dev is not 0.
+ * So use pm_suspend_ignore_children() to ignore the effect to
+ * hisi_hba->dev.
+ */
+ pm_suspend_ignore_children(dev, true);
+ pm_runtime_put_noidle(&pdev->dev);
+
return 0;
err_out_register_ha:
scsi_remove_host(shost);
-err_out_ha:
+err_out_free_irq_vectors:
+ pci_free_irq_vectors(pdev);
+err_out_debugfs:
hisi_sas_debugfs_exit(hisi_hba);
+err_out_ha:
+ hisi_sas_free(hisi_hba);
scsi_host_put(shost);
err_out_regions:
pci_release_regions(pdev);
@@ -3294,8 +3379,7 @@
struct hisi_hba *hisi_hba = sha->lldd_ha;
struct Scsi_Host *shost = sha->core.shost;
- hisi_sas_debugfs_exit(hisi_hba);
-
+ pm_runtime_get_noresume(dev);
if (timer_pending(&hisi_hba->timer))
del_timer(&hisi_hba->timer);
@@ -3303,10 +3387,10 @@
sas_remove_host(sha->core.shost);
hisi_sas_v3_destroy_irqs(pdev, hisi_hba);
- hisi_sas_kill_tasklets(hisi_hba);
pci_release_regions(pdev);
pci_disable_device(pdev);
hisi_sas_free(hisi_hba);
+ hisi_sas_debugfs_exit(hisi_hba);
scsi_host_put(shost);
}
@@ -3350,8 +3434,9 @@
hip08,
};
-static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state)
+static int _suspend_v3_hw(struct device *device)
{
+ struct pci_dev *pdev = to_pci_dev(device);
struct sas_ha_struct *sha = pci_get_drvdata(pdev);
struct hisi_hba *hisi_hba = sha->lldd_ha;
struct device *dev = hisi_hba->dev;
@@ -3382,7 +3467,7 @@
hisi_sas_init_mem(hisi_hba);
- device_state = pci_choose_state(pdev, state);
+ device_state = pci_choose_state(pdev, PMSG_SUSPEND);
dev_warn(dev, "entering operating state [D%d]\n",
device_state);
pci_save_state(pdev);
@@ -3395,8 +3480,9 @@
return 0;
}
-static int hisi_sas_v3_resume(struct pci_dev *pdev)
+static int _resume_v3_hw(struct device *device)
{
+ struct pci_dev *pdev = to_pci_dev(device);
struct sas_ha_struct *sha = pci_get_drvdata(pdev);
struct hisi_hba *hisi_hba = sha->lldd_ha;
struct Scsi_Host *shost = hisi_hba->shost;
@@ -3433,6 +3519,34 @@
return 0;
}
+static int suspend_v3_hw(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct sas_ha_struct *sha = pci_get_drvdata(pdev);
+ struct hisi_hba *hisi_hba = sha->lldd_ha;
+ int rc;
+
+ set_bit(HISI_SAS_PM_BIT, &hisi_hba->flags);
+
+ rc = _suspend_v3_hw(device);
+ if (rc)
+ clear_bit(HISI_SAS_PM_BIT, &hisi_hba->flags);
+
+ return rc;
+}
+
+static int resume_v3_hw(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct sas_ha_struct *sha = pci_get_drvdata(pdev);
+ struct hisi_hba *hisi_hba = sha->lldd_ha;
+ int rc = _resume_v3_hw(device);
+
+ clear_bit(HISI_SAS_PM_BIT, &hisi_hba->flags);
+
+ return rc;
+}
+
static const struct pci_device_id sas_v3_pci_table[] = {
{ PCI_VDEVICE(HUAWEI, 0xa230), hip08 },
{}
@@ -3444,14 +3558,29 @@
.reset_done = hisi_sas_reset_done_v3_hw,
};
+static int runtime_suspend_v3_hw(struct device *dev)
+{
+ return suspend_v3_hw(dev);
+}
+
+static int runtime_resume_v3_hw(struct device *dev)
+{
+ return resume_v3_hw(dev);
+}
+
+static const struct dev_pm_ops hisi_sas_v3_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(suspend_v3_hw, resume_v3_hw)
+ SET_RUNTIME_PM_OPS(runtime_suspend_v3_hw,
+ runtime_resume_v3_hw, NULL)
+};
+
static struct pci_driver sas_v3_pci_driver = {
.name = DRV_NAME,
.id_table = sas_v3_pci_table,
.probe = hisi_sas_v3_probe,
.remove = hisi_sas_v3_remove,
- .suspend = hisi_sas_v3_suspend,
- .resume = hisi_sas_v3_resume,
.err_handler = &hisi_sas_err_handler,
+ .driver.pm = &hisi_sas_v3_pm_ops,
};
module_pci_driver(sas_v3_pci_driver);
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 7c736e4..d664c46 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -38,6 +38,7 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
+#include <scsi/scsi_cmnd.h>
#include "scsi_priv.h"
#include "scsi_logging.h"
@@ -219,7 +220,8 @@
goto fail;
}
- shost->cmd_per_lun = min_t(short, shost->cmd_per_lun,
+ /* Use min_t(int, ...) in case shost->can_queue exceeds SHRT_MAX */
+ shost->cmd_per_lun = min_t(int, shost->cmd_per_lun,
shost->can_queue);
error = scsi_init_sense_cache(shost);
@@ -273,8 +275,10 @@
if (shost->transportt->create_work_queue) {
snprintf(shost->work_q_name, sizeof(shost->work_q_name),
"scsi_wq_%d", shost->host_no);
- shost->work_q = create_singlethread_workqueue(
- shost->work_q_name);
+ shost->work_q = alloc_workqueue("%s",
+ WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND,
+ 1, shost->work_q_name);
+
if (!shost->work_q) {
error = -EINVAL;
goto out_del_dev;
@@ -425,6 +429,7 @@
shost->cmd_per_lun = sht->cmd_per_lun;
shost->unchecked_isa_dma = sht->unchecked_isa_dma;
shost->no_write_same = sht->no_write_same;
+ shost->host_tagset = sht->host_tagset;
if (shost_eh_deadline == -1 || !sht->eh_host_reset_handler)
shost->eh_deadline = -1;
@@ -494,7 +499,7 @@
}
shost->tmf_work_q = alloc_workqueue("scsi_tmf_%d",
- WQ_UNBOUND | WQ_MEM_RECLAIM,
+ WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS,
1, shost->host_no);
if (!shost->tmf_work_q) {
shost_printk(KERN_WARNING, shost,
@@ -563,13 +568,29 @@
}
EXPORT_SYMBOL(scsi_host_get);
+static bool scsi_host_check_in_flight(struct request *rq, void *data,
+ bool reserved)
+{
+ int *count = data;
+ struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
+
+ if (test_bit(SCMD_STATE_INFLIGHT, &cmd->state))
+ (*count)++;
+
+ return true;
+}
+
/**
* scsi_host_busy - Return the host busy counter
* @shost: Pointer to Scsi_Host to inc.
**/
int scsi_host_busy(struct Scsi_Host *shost)
{
- return atomic_read(&shost->host_busy);
+ int cnt = 0;
+
+ blk_mq_tagset_busy_iter(&shost->tag_set,
+ scsi_host_check_in_flight, &cnt);
+ return cnt;
}
EXPORT_SYMBOL(scsi_host_busy);
@@ -642,3 +663,68 @@
flush_workqueue(shost->work_q);
}
EXPORT_SYMBOL_GPL(scsi_flush_work);
+
+static bool complete_all_cmds_iter(struct request *rq, void *data, bool rsvd)
+{
+ struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq);
+ int status = *(int *)data;
+
+ scsi_dma_unmap(scmd);
+ scmd->result = status << 16;
+ scmd->scsi_done(scmd);
+ return true;
+}
+
+/**
+ * scsi_host_complete_all_commands - Terminate all running commands
+ * @shost: Scsi Host on which commands should be terminated
+ * @status: Status to be set for the terminated commands
+ *
+ * There is no protection against modification of the number
+ * of outstanding commands. It is the responsibility of the
+ * caller to ensure that concurrent I/O submission and/or
+ * completion is stopped when calling this function.
+ */
+void scsi_host_complete_all_commands(struct Scsi_Host *shost, int status)
+{
+ blk_mq_tagset_busy_iter(&shost->tag_set, complete_all_cmds_iter,
+ &status);
+}
+EXPORT_SYMBOL_GPL(scsi_host_complete_all_commands);
+
+struct scsi_host_busy_iter_data {
+ bool (*fn)(struct scsi_cmnd *, void *, bool);
+ void *priv;
+};
+
+static bool __scsi_host_busy_iter_fn(struct request *req, void *priv,
+ bool reserved)
+{
+ struct scsi_host_busy_iter_data *iter_data = priv;
+ struct scsi_cmnd *sc = blk_mq_rq_to_pdu(req);
+
+ return iter_data->fn(sc, iter_data->priv, reserved);
+}
+
+/**
+ * scsi_host_busy_iter - Iterate over all busy commands
+ * @shost: Pointer to Scsi_Host.
+ * @fn: Function to call on each busy command
+ * @priv: Data pointer passed to @fn
+ *
+ * If locking against concurrent command completions is required
+ * ithas to be provided by the caller
+ **/
+void scsi_host_busy_iter(struct Scsi_Host *shost,
+ bool (*fn)(struct scsi_cmnd *, void *, bool),
+ void *priv)
+{
+ struct scsi_host_busy_iter_data iter_data = {
+ .fn = fn,
+ .priv = priv,
+ };
+
+ blk_mq_tagset_busy_iter(&shost->tag_set, __scsi_host_busy_iter_fn,
+ &iter_data);
+}
+EXPORT_SYMBOL_GPL(scsi_host_busy_iter);
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index bac7059..8df70c9 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1,5 +1,6 @@
/*
* Disk Array driver for HP Smart Array SAS controllers
+ * Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
* Copyright 2016 Microsemi Corporation
* Copyright 2014-2015 PMC-Sierra, Inc.
* Copyright 2000,2009-2015 Hewlett-Packard Development Company, L.P.
@@ -59,7 +60,7 @@
* HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.'
* with an optional trailing '-' followed by a byte value (0-255).
*/
-#define HPSA_DRIVER_VERSION "3.4.20-170"
+#define HPSA_DRIVER_VERSION "3.4.20-200"
#define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")"
#define HPSA "hpsa"
@@ -254,6 +255,10 @@
static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id);
static int hpsa_ioctl(struct scsi_device *dev, unsigned int cmd,
void __user *arg);
+static int hpsa_passthru_ioctl(struct ctlr_info *h,
+ IOCTL_Command_struct *iocommand);
+static int hpsa_big_passthru_ioctl(struct ctlr_info *h,
+ BIG_IOCTL_Command_struct *ioc);
#ifdef CONFIG_COMPAT
static int hpsa_compat_ioctl(struct scsi_device *dev, unsigned int cmd,
@@ -2130,6 +2135,7 @@
}
/* configure scsi device based on internal per-device structure */
+#define CTLR_TIMEOUT (120 * HZ)
static int hpsa_slave_configure(struct scsi_device *sdev)
{
struct hpsa_scsi_dev_t *sd;
@@ -2140,17 +2146,21 @@
if (sd) {
sd->was_removed = 0;
+ queue_depth = sd->queue_depth != 0 ?
+ sd->queue_depth : sdev->host->can_queue;
if (sd->external) {
queue_depth = EXTERNAL_QD;
sdev->eh_timeout = HPSA_EH_PTRAID_TIMEOUT;
blk_queue_rq_timeout(sdev->request_queue,
HPSA_EH_PTRAID_TIMEOUT);
- } else {
- queue_depth = sd->queue_depth != 0 ?
- sd->queue_depth : sdev->host->can_queue;
}
- } else
+ if (is_hba_lunid(sd->scsi3addr)) {
+ sdev->eh_timeout = CTLR_TIMEOUT;
+ blk_queue_rq_timeout(sdev->request_queue, CTLR_TIMEOUT);
+ }
+ } else {
queue_depth = sdev->host->can_queue;
+ }
scsi_change_queue_depth(sdev, queue_depth);
@@ -3439,9 +3449,14 @@
struct ErrorInfo *ei = NULL;
struct bmic_sense_storage_box_params *bssbp = NULL;
struct bmic_identify_physical_device *id_phys = NULL;
- struct ext_report_lun_entry *rle = &rlep->LUN[rle_index];
+ struct ext_report_lun_entry *rle;
u16 bmic_device_index = 0;
+ if (rle_index < 0 || rle_index >= HPSA_MAX_PHYS_LUN)
+ return;
+
+ rle = &rlep->LUN[rle_index];
+
encl_dev->eli =
hpsa_get_enclosure_logical_identifier(h, scsi3addr);
@@ -4170,6 +4185,9 @@
int rc;
struct ext_report_lun_entry *rle;
+ if (rle_index < 0 || rle_index >= HPSA_MAX_PHYS_LUN)
+ return;
+
rle = &rlep->LUN[rle_index];
dev->ioaccel_handle = rle->ioaccel_handle;
@@ -4194,7 +4212,12 @@
struct ReportExtendedLUNdata *rlep, int rle_index,
struct bmic_identify_physical_device *id_phys)
{
- struct ext_report_lun_entry *rle = &rlep->LUN[rle_index];
+ struct ext_report_lun_entry *rle;
+
+ if (rle_index < 0 || rle_index >= HPSA_MAX_PHYS_LUN)
+ return;
+
+ rle = &rlep->LUN[rle_index];
if ((rle->device_flags & 0x08) && this_device->ioaccel_handle)
this_device->hba_ioaccel_enabled = 1;
@@ -4416,7 +4439,8 @@
/*
* Skip over some devices such as a spare.
*/
- if (!tmpdevice->external && physical_device) {
+ if (phys_dev_index >= 0 && !tmpdevice->external &&
+ physical_device) {
skip_device = hpsa_skip_device(h, lunaddrbytes,
&physdev_list->LUN[phys_dev_index]);
if (skip_device)
@@ -4674,7 +4698,7 @@
case WRITE_6:
case WRITE_12:
is_write = 1;
- /* fall through */
+ fallthrough;
case READ_6:
case READ_12:
if (*cdb_len == 6) {
@@ -5124,7 +5148,7 @@
switch (cmd->cmnd[0]) {
case WRITE_6:
is_write = 1;
- /* fall through */
+ fallthrough;
case READ_6:
first_block = (((cmd->cmnd[1] & 0x1F) << 16) |
(cmd->cmnd[2] << 8) |
@@ -5135,7 +5159,7 @@
break;
case WRITE_10:
is_write = 1;
- /* fall through */
+ fallthrough;
case READ_10:
first_block =
(((u64) cmd->cmnd[2]) << 24) |
@@ -5148,7 +5172,7 @@
break;
case WRITE_12:
is_write = 1;
- /* fall through */
+ fallthrough;
case READ_12:
first_block =
(((u64) cmd->cmnd[2]) << 24) |
@@ -5163,7 +5187,7 @@
break;
case WRITE_16:
is_write = 1;
- /* fall through */
+ fallthrough;
case READ_16:
first_block =
(((u64) cmd->cmnd[2]) << 56) |
@@ -6217,75 +6241,63 @@
static int hpsa_ioctl32_passthru(struct scsi_device *dev, unsigned int cmd,
void __user *arg)
{
- IOCTL32_Command_struct __user *arg32 =
- (IOCTL32_Command_struct __user *) arg;
+ struct ctlr_info *h = sdev_to_hba(dev);
+ IOCTL32_Command_struct __user *arg32 = arg;
IOCTL_Command_struct arg64;
- IOCTL_Command_struct __user *p = compat_alloc_user_space(sizeof(arg64));
int err;
u32 cp;
+ if (!arg)
+ return -EINVAL;
+
memset(&arg64, 0, sizeof(arg64));
- err = 0;
- err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
- sizeof(arg64.LUN_info));
- err |= copy_from_user(&arg64.Request, &arg32->Request,
- sizeof(arg64.Request));
- err |= copy_from_user(&arg64.error_info, &arg32->error_info,
- sizeof(arg64.error_info));
- err |= get_user(arg64.buf_size, &arg32->buf_size);
- err |= get_user(cp, &arg32->buf);
- arg64.buf = compat_ptr(cp);
- err |= copy_to_user(p, &arg64, sizeof(arg64));
-
- if (err)
+ if (copy_from_user(&arg64, arg32, offsetof(IOCTL_Command_struct, buf)))
return -EFAULT;
+ if (get_user(cp, &arg32->buf))
+ return -EFAULT;
+ arg64.buf = compat_ptr(cp);
- err = hpsa_ioctl(dev, CCISS_PASSTHRU, p);
+ if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0)
+ return -EAGAIN;
+ err = hpsa_passthru_ioctl(h, &arg64);
+ atomic_inc(&h->passthru_cmds_avail);
if (err)
return err;
- err |= copy_in_user(&arg32->error_info, &p->error_info,
- sizeof(arg32->error_info));
- if (err)
+ if (copy_to_user(&arg32->error_info, &arg64.error_info,
+ sizeof(arg32->error_info)))
return -EFAULT;
- return err;
+ return 0;
}
static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
unsigned int cmd, void __user *arg)
{
- BIG_IOCTL32_Command_struct __user *arg32 =
- (BIG_IOCTL32_Command_struct __user *) arg;
+ struct ctlr_info *h = sdev_to_hba(dev);
+ BIG_IOCTL32_Command_struct __user *arg32 = arg;
BIG_IOCTL_Command_struct arg64;
- BIG_IOCTL_Command_struct __user *p =
- compat_alloc_user_space(sizeof(arg64));
int err;
u32 cp;
+ if (!arg)
+ return -EINVAL;
memset(&arg64, 0, sizeof(arg64));
- err = 0;
- err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
- sizeof(arg64.LUN_info));
- err |= copy_from_user(&arg64.Request, &arg32->Request,
- sizeof(arg64.Request));
- err |= copy_from_user(&arg64.error_info, &arg32->error_info,
- sizeof(arg64.error_info));
- err |= get_user(arg64.buf_size, &arg32->buf_size);
- err |= get_user(arg64.malloc_size, &arg32->malloc_size);
- err |= get_user(cp, &arg32->buf);
- arg64.buf = compat_ptr(cp);
- err |= copy_to_user(p, &arg64, sizeof(arg64));
-
- if (err)
+ if (copy_from_user(&arg64, arg32,
+ offsetof(BIG_IOCTL32_Command_struct, buf)))
return -EFAULT;
+ if (get_user(cp, &arg32->buf))
+ return -EFAULT;
+ arg64.buf = compat_ptr(cp);
- err = hpsa_ioctl(dev, CCISS_BIG_PASSTHRU, p);
+ if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0)
+ return -EAGAIN;
+ err = hpsa_big_passthru_ioctl(h, &arg64);
+ atomic_inc(&h->passthru_cmds_avail);
if (err)
return err;
- err |= copy_in_user(&arg32->error_info, &p->error_info,
- sizeof(arg32->error_info));
- if (err)
+ if (copy_to_user(&arg32->error_info, &arg64.error_info,
+ sizeof(arg32->error_info)))
return -EFAULT;
- return err;
+ return 0;
}
static int hpsa_compat_ioctl(struct scsi_device *dev, unsigned int cmd,
@@ -6358,37 +6370,33 @@
return 0;
}
-static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
+static int hpsa_passthru_ioctl(struct ctlr_info *h,
+ IOCTL_Command_struct *iocommand)
{
- IOCTL_Command_struct iocommand;
struct CommandList *c;
char *buff = NULL;
u64 temp64;
int rc = 0;
- if (!argp)
- return -EINVAL;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
- if (copy_from_user(&iocommand, argp, sizeof(iocommand)))
- return -EFAULT;
- if ((iocommand.buf_size < 1) &&
- (iocommand.Request.Type.Direction != XFER_NONE)) {
+ if ((iocommand->buf_size < 1) &&
+ (iocommand->Request.Type.Direction != XFER_NONE)) {
return -EINVAL;
}
- if (iocommand.buf_size > 0) {
- buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
+ if (iocommand->buf_size > 0) {
+ buff = kmalloc(iocommand->buf_size, GFP_KERNEL);
if (buff == NULL)
return -ENOMEM;
- if (iocommand.Request.Type.Direction & XFER_WRITE) {
+ if (iocommand->Request.Type.Direction & XFER_WRITE) {
/* Copy the data into the buffer we created */
- if (copy_from_user(buff, iocommand.buf,
- iocommand.buf_size)) {
+ if (copy_from_user(buff, iocommand->buf,
+ iocommand->buf_size)) {
rc = -EFAULT;
goto out_kfree;
}
} else {
- memset(buff, 0, iocommand.buf_size);
+ memset(buff, 0, iocommand->buf_size);
}
}
c = cmd_alloc(h);
@@ -6398,23 +6406,23 @@
c->scsi_cmd = SCSI_CMD_BUSY;
/* Fill in Command Header */
c->Header.ReplyQueue = 0; /* unused in simple mode */
- if (iocommand.buf_size > 0) { /* buffer to fill */
+ if (iocommand->buf_size > 0) { /* buffer to fill */
c->Header.SGList = 1;
c->Header.SGTotal = cpu_to_le16(1);
} else { /* no buffers to fill */
c->Header.SGList = 0;
c->Header.SGTotal = cpu_to_le16(0);
}
- memcpy(&c->Header.LUN, &iocommand.LUN_info, sizeof(c->Header.LUN));
+ memcpy(&c->Header.LUN, &iocommand->LUN_info, sizeof(c->Header.LUN));
/* Fill in Request block */
- memcpy(&c->Request, &iocommand.Request,
+ memcpy(&c->Request, &iocommand->Request,
sizeof(c->Request));
/* Fill in the scatter gather information */
- if (iocommand.buf_size > 0) {
+ if (iocommand->buf_size > 0) {
temp64 = dma_map_single(&h->pdev->dev, buff,
- iocommand.buf_size, DMA_BIDIRECTIONAL);
+ iocommand->buf_size, DMA_BIDIRECTIONAL);
if (dma_mapping_error(&h->pdev->dev, (dma_addr_t) temp64)) {
c->SG[0].Addr = cpu_to_le64(0);
c->SG[0].Len = cpu_to_le32(0);
@@ -6422,12 +6430,12 @@
goto out;
}
c->SG[0].Addr = cpu_to_le64(temp64);
- c->SG[0].Len = cpu_to_le32(iocommand.buf_size);
+ c->SG[0].Len = cpu_to_le32(iocommand->buf_size);
c->SG[0].Ext = cpu_to_le32(HPSA_SG_LAST); /* not chaining */
}
rc = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE,
NO_TIMEOUT);
- if (iocommand.buf_size > 0)
+ if (iocommand->buf_size > 0)
hpsa_pci_unmap(h->pdev, c, 1, DMA_BIDIRECTIONAL);
check_ioctl_unit_attention(h, c);
if (rc) {
@@ -6436,16 +6444,12 @@
}
/* Copy the error information out */
- memcpy(&iocommand.error_info, c->err_info,
- sizeof(iocommand.error_info));
- if (copy_to_user(argp, &iocommand, sizeof(iocommand))) {
- rc = -EFAULT;
- goto out;
- }
- if ((iocommand.Request.Type.Direction & XFER_READ) &&
- iocommand.buf_size > 0) {
+ memcpy(&iocommand->error_info, c->err_info,
+ sizeof(iocommand->error_info));
+ if ((iocommand->Request.Type.Direction & XFER_READ) &&
+ iocommand->buf_size > 0) {
/* Copy the data out of the buffer we created */
- if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) {
+ if (copy_to_user(iocommand->buf, buff, iocommand->buf_size)) {
rc = -EFAULT;
goto out;
}
@@ -6457,9 +6461,9 @@
return rc;
}
-static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
+static int hpsa_big_passthru_ioctl(struct ctlr_info *h,
+ BIG_IOCTL_Command_struct *ioc)
{
- BIG_IOCTL_Command_struct *ioc;
struct CommandList *c;
unsigned char **buff = NULL;
int *buff_size = NULL;
@@ -6470,29 +6474,17 @@
u32 sz;
BYTE __user *data_ptr;
- if (!argp)
- return -EINVAL;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
- ioc = vmemdup_user(argp, sizeof(*ioc));
- if (IS_ERR(ioc)) {
- status = PTR_ERR(ioc);
- goto cleanup1;
- }
+
if ((ioc->buf_size < 1) &&
- (ioc->Request.Type.Direction != XFER_NONE)) {
- status = -EINVAL;
- goto cleanup1;
- }
+ (ioc->Request.Type.Direction != XFER_NONE))
+ return -EINVAL;
/* Check kmalloc limits using all SGs */
- if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
- status = -EINVAL;
- goto cleanup1;
- }
- if (ioc->buf_size > ioc->malloc_size * SG_ENTRIES_IN_CMD) {
- status = -EINVAL;
- goto cleanup1;
- }
+ if (ioc->malloc_size > MAX_KMALLOC_SIZE)
+ return -EINVAL;
+ if (ioc->buf_size > ioc->malloc_size * SG_ENTRIES_IN_CMD)
+ return -EINVAL;
buff = kcalloc(SG_ENTRIES_IN_CMD, sizeof(char *), GFP_KERNEL);
if (!buff) {
status = -ENOMEM;
@@ -6565,10 +6557,6 @@
/* Copy the error information out */
memcpy(&ioc->error_info, c->err_info, sizeof(ioc->error_info));
- if (copy_to_user(argp, ioc, sizeof(*ioc))) {
- status = -EFAULT;
- goto cleanup0;
- }
if ((ioc->Request.Type.Direction & XFER_READ) && ioc->buf_size > 0) {
int i;
@@ -6594,7 +6582,6 @@
kfree(buff);
}
kfree(buff_size);
- kvfree(ioc);
return status;
}
@@ -6610,14 +6597,11 @@
* ioctl
*/
static int hpsa_ioctl(struct scsi_device *dev, unsigned int cmd,
- void __user *arg)
+ void __user *argp)
{
- struct ctlr_info *h;
- void __user *argp = (void __user *)arg;
+ struct ctlr_info *h = sdev_to_hba(dev);
int rc;
- h = sdev_to_hba(dev);
-
switch (cmd) {
case CCISS_DEREGDISK:
case CCISS_REGNEWDISK:
@@ -6628,18 +6612,35 @@
return hpsa_getpciinfo_ioctl(h, argp);
case CCISS_GETDRIVVER:
return hpsa_getdrivver_ioctl(h, argp);
- case CCISS_PASSTHRU:
+ case CCISS_PASSTHRU: {
+ IOCTL_Command_struct iocommand;
+
+ if (!argp)
+ return -EINVAL;
+ if (copy_from_user(&iocommand, argp, sizeof(iocommand)))
+ return -EFAULT;
if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0)
return -EAGAIN;
- rc = hpsa_passthru_ioctl(h, argp);
+ rc = hpsa_passthru_ioctl(h, &iocommand);
atomic_inc(&h->passthru_cmds_avail);
+ if (!rc && copy_to_user(argp, &iocommand, sizeof(iocommand)))
+ rc = -EFAULT;
return rc;
- case CCISS_BIG_PASSTHRU:
+ }
+ case CCISS_BIG_PASSTHRU: {
+ BIG_IOCTL_Command_struct ioc;
+ if (!argp)
+ return -EINVAL;
+ if (copy_from_user(&ioc, argp, sizeof(ioc)))
+ return -EFAULT;
if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0)
return -EAGAIN;
- rc = hpsa_big_passthru_ioctl(h, argp);
+ rc = hpsa_big_passthru_ioctl(h, &ioc);
atomic_inc(&h->passthru_cmds_avail);
+ if (!rc && copy_to_user(argp, &ioc, sizeof(ioc)))
+ rc = -EFAULT;
return rc;
+ }
default:
return -ENOTTY;
}
@@ -6897,7 +6898,7 @@
{
ulong page_base = ((ulong) base) & PAGE_MASK;
ulong page_offs = ((ulong) base) - page_base;
- void __iomem *page_remapped = ioremap_nocache(page_base,
+ void __iomem *page_remapped = ioremap(page_base,
page_offs + size);
return page_remapped ? (page_remapped + page_offs) : NULL;
@@ -9331,10 +9332,10 @@
static void hpsa_free_ioaccel1_cmd_and_bft(struct ctlr_info *h)
{
if (h->ioaccel_cmd_pool) {
- pci_free_consistent(h->pdev,
- h->nr_cmds * sizeof(*h->ioaccel_cmd_pool),
- h->ioaccel_cmd_pool,
- h->ioaccel_cmd_pool_dhandle);
+ dma_free_coherent(&h->pdev->dev,
+ h->nr_cmds * sizeof(*h->ioaccel_cmd_pool),
+ h->ioaccel_cmd_pool,
+ h->ioaccel_cmd_pool_dhandle);
h->ioaccel_cmd_pool = NULL;
h->ioaccel_cmd_pool_dhandle = 0;
}
@@ -9384,10 +9385,10 @@
hpsa_free_ioaccel2_sg_chain_blocks(h);
if (h->ioaccel2_cmd_pool) {
- pci_free_consistent(h->pdev,
- h->nr_cmds * sizeof(*h->ioaccel2_cmd_pool),
- h->ioaccel2_cmd_pool,
- h->ioaccel2_cmd_pool_dhandle);
+ dma_free_coherent(&h->pdev->dev,
+ h->nr_cmds * sizeof(*h->ioaccel2_cmd_pool),
+ h->ioaccel2_cmd_pool,
+ h->ioaccel2_cmd_pool_dhandle);
h->ioaccel2_cmd_pool = NULL;
h->ioaccel2_cmd_pool_dhandle = 0;
}
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index f8c88fc..99b0750 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -1,5 +1,6 @@
/*
* Disk Array driver for HP Smart Array SAS controllers
+ * Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
* Copyright 2016 Microsemi Corporation
* Copyright 2014-2015 PMC-Sierra, Inc.
* Copyright 2000,2009-2015 Hewlett-Packard Development Company, L.P.
@@ -57,7 +58,7 @@
bool added_to_port;
};
-#define EXTERNAL_QD 7
+#define EXTERNAL_QD 128
struct hpsa_scsi_dev_t {
unsigned int devtype;
int bus, target, lun; /* as presented to the OS */
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index 7825cbf..46df2e3 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -1,5 +1,6 @@
/*
* Disk Array driver for HP Smart Array SAS controllers
+ * Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
* Copyright 2016 Microsemi Corporation
* Copyright 2014-2015 PMC-Sierra, Inc.
* Copyright 2000,2009-2015 Hewlett-Packard Development Company, L.P.
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 5f8bdc5..f6d6539 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -133,6 +133,8 @@
static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *);
static void ibmvfc_tgt_query_target(struct ibmvfc_target *);
static void ibmvfc_npiv_logout(struct ibmvfc_host *);
+static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *);
+static void ibmvfc_tgt_move_login(struct ibmvfc_target *);
static const char *unknown_error = "unknown error";
@@ -413,22 +415,59 @@
* @tgt: ibmvfc target struct
* @action: action to perform
*
+ * Returns:
+ * 0 if action changed / non-zero if not changed
**/
-static void ibmvfc_set_tgt_action(struct ibmvfc_target *tgt,
+static int ibmvfc_set_tgt_action(struct ibmvfc_target *tgt,
enum ibmvfc_target_action action)
{
+ int rc = -EINVAL;
+
switch (tgt->action) {
- case IBMVFC_TGT_ACTION_DEL_RPORT:
- if (action == IBMVFC_TGT_ACTION_DELETED_RPORT)
+ case IBMVFC_TGT_ACTION_LOGOUT_RPORT:
+ if (action == IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT ||
+ action == IBMVFC_TGT_ACTION_DEL_RPORT) {
tgt->action = action;
+ rc = 0;
+ }
+ break;
+ case IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT:
+ if (action == IBMVFC_TGT_ACTION_DEL_RPORT ||
+ action == IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT) {
+ tgt->action = action;
+ rc = 0;
+ }
+ break;
+ case IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT:
+ if (action == IBMVFC_TGT_ACTION_LOGOUT_RPORT) {
+ tgt->action = action;
+ rc = 0;
+ }
+ break;
+ case IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT:
+ if (action == IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT) {
+ tgt->action = action;
+ rc = 0;
+ }
+ break;
+ case IBMVFC_TGT_ACTION_DEL_RPORT:
+ if (action == IBMVFC_TGT_ACTION_DELETED_RPORT) {
+ tgt->action = action;
+ rc = 0;
+ }
+ break;
case IBMVFC_TGT_ACTION_DELETED_RPORT:
break;
default:
- if (action == IBMVFC_TGT_ACTION_DEL_RPORT)
- tgt->add_rport = 0;
tgt->action = action;
+ rc = 0;
break;
}
+
+ if (action >= IBMVFC_TGT_ACTION_LOGOUT_RPORT)
+ tgt->add_rport = 0;
+
+ return rc;
}
/**
@@ -525,7 +564,8 @@
**/
static void ibmvfc_reinit_host(struct ibmvfc_host *vhost)
{
- if (vhost->action == IBMVFC_HOST_ACTION_NONE) {
+ if (vhost->action == IBMVFC_HOST_ACTION_NONE &&
+ vhost->state == IBMVFC_ACTIVE) {
if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
scsi_block_requests(vhost->host);
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
@@ -537,6 +577,19 @@
}
/**
+ * ibmvfc_del_tgt - Schedule cleanup and removal of the target
+ * @tgt: ibmvfc target struct
+ * @job_step: job step to perform
+ *
+ **/
+static void ibmvfc_del_tgt(struct ibmvfc_target *tgt)
+{
+ if (!ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_RPORT))
+ tgt->job_step = ibmvfc_tgt_implicit_logout_and_del;
+ wake_up(&tgt->vhost->work_wait_q);
+}
+
+/**
* ibmvfc_link_down - Handle a link down event from the adapter
* @vhost: ibmvfc host struct
* @state: ibmvfc host state to enter
@@ -550,7 +603,7 @@
ENTER;
scsi_block_requests(vhost->host);
list_for_each_entry(tgt, &vhost->targets, queue)
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_del_tgt(tgt);
ibmvfc_set_host_state(vhost, state);
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_TGT_DEL);
vhost->events_to_log |= IBMVFC_AE_LINKDOWN;
@@ -583,7 +636,7 @@
vhost->async_crq.cur = 0;
list_for_each_entry(tgt, &vhost->targets, queue)
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_del_tgt(tgt);
scsi_block_requests(vhost->host);
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT);
vhost->job_step = ibmvfc_npiv_login;
@@ -1308,7 +1361,7 @@
}
/**
- * ibmvfc_map_sg_data - Maps dma for a scatterlist and initializes decriptor fields
+ * ibmvfc_map_sg_data - Maps dma for a scatterlist and initializes descriptor fields
* @scmd: struct scsi_cmnd with the scatterlist
* @evt: ibmvfc event struct
* @vfc_cmd: vfc_cmd that contains the memory descriptor
@@ -1500,7 +1553,7 @@
list_for_each_entry(tgt, &vhost->targets, queue) {
if (rport == tgt->rport) {
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_del_tgt(tgt);
break;
}
}
@@ -1830,7 +1883,7 @@
port_id = (bsg_request->rqst_data.h_els.port_id[0] << 16) |
(bsg_request->rqst_data.h_els.port_id[1] << 8) |
bsg_request->rqst_data.h_els.port_id[2];
- /* fall through */
+ fallthrough;
case FC_BSG_RPT_ELS:
fc_flags = IBMVFC_FC_ELS;
break;
@@ -1839,7 +1892,7 @@
port_id = (bsg_request->rqst_data.h_ct.port_id[0] << 16) |
(bsg_request->rqst_data.h_ct.port_id[1] << 8) |
bsg_request->rqst_data.h_ct.port_id[2];
- /* fall through */
+ fallthrough;
case FC_BSG_RPT_CT:
fc_flags = IBMVFC_FC_CT_IU;
break;
@@ -2538,7 +2591,9 @@
struct ibmvfc_host *vhost = shost_priv(shost);
struct fc_rport *dev_rport;
struct scsi_device *sdev;
- unsigned long rc;
+ struct ibmvfc_target *tgt;
+ unsigned long rc, flags;
+ unsigned int found;
ENTER;
shost_for_each_device(sdev, shost) {
@@ -2552,6 +2607,27 @@
if (rc == FAILED)
ibmvfc_issue_fc_host_lip(shost);
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ found = 0;
+ list_for_each_entry(tgt, &vhost->targets, queue) {
+ if (tgt->scsi_id == rport->port_id) {
+ found++;
+ break;
+ }
+ }
+
+ if (found && tgt->action == IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT) {
+ /*
+ * If we get here, that means we previously attempted to send
+ * an implicit logout to the target but it failed, most likely
+ * due to I/O being pending, so we need to send it again
+ */
+ ibmvfc_del_tgt(tgt);
+ ibmvfc_reinit_host(vhost);
+ }
+
+ spin_unlock_irqrestore(shost->host_lock, flags);
LEAVE;
}
@@ -2686,7 +2762,7 @@
if (tgt->need_login && be64_to_cpu(crq->event) == IBMVFC_AE_ELS_LOGO)
tgt->logo_rcvd = 1;
if (!tgt->need_login || be64_to_cpu(crq->event) == IBMVFC_AE_ELS_PLOGI) {
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_del_tgt(tgt);
ibmvfc_reinit_host(vhost);
}
}
@@ -3222,8 +3298,8 @@
static void ibmvfc_init_tgt(struct ibmvfc_target *tgt,
void (*job_step) (struct ibmvfc_target *))
{
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT);
- tgt->job_step = job_step;
+ if (!ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT))
+ tgt->job_step = job_step;
wake_up(&tgt->vhost->work_wait_q);
}
@@ -3239,7 +3315,7 @@
void (*job_step) (struct ibmvfc_target *))
{
if (++tgt->init_retries > IBMVFC_MAX_TGT_INIT_RETRIES) {
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_del_tgt(tgt);
wake_up(&tgt->vhost->work_wait_q);
return 0;
} else
@@ -3314,13 +3390,13 @@
tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR;
tgt->add_rport = 1;
} else
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_del_tgt(tgt);
} else if (prli_rsp[index].retry)
ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli);
else
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_del_tgt(tgt);
} else
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_del_tgt(tgt);
break;
case IBMVFC_MAD_DRIVER_FAILED:
break;
@@ -3337,7 +3413,7 @@
else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli);
else
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_del_tgt(tgt);
tgt_log(tgt, level, "Process Login failed: %s (%x:%x) rc=0x%02X\n",
ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
@@ -3436,7 +3512,7 @@
if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi);
else
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_del_tgt(tgt);
tgt_log(tgt, level, "Port Login failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
@@ -3517,40 +3593,54 @@
break;
}
- if (vhost->action == IBMVFC_HOST_ACTION_TGT_INIT)
- ibmvfc_init_tgt(tgt, ibmvfc_tgt_send_plogi);
- else if (vhost->action == IBMVFC_HOST_ACTION_QUERY_TGTS &&
- tgt->scsi_id != tgt->new_scsi_id)
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_init_tgt(tgt, ibmvfc_tgt_send_plogi);
kref_put(&tgt->kref, ibmvfc_release_tgt);
wake_up(&vhost->work_wait_q);
}
/**
+ * __ibmvfc_tgt_get_implicit_logout_evt - Allocate and init an event for implicit logout
+ * @tgt: ibmvfc target struct
+ *
+ * Returns:
+ * Allocated and initialized ibmvfc_event struct
+ **/
+static struct ibmvfc_event *__ibmvfc_tgt_get_implicit_logout_evt(struct ibmvfc_target *tgt,
+ void (*done) (struct ibmvfc_event *))
+{
+ struct ibmvfc_implicit_logout *mad;
+ struct ibmvfc_host *vhost = tgt->vhost;
+ struct ibmvfc_event *evt;
+
+ kref_get(&tgt->kref);
+ evt = ibmvfc_get_event(vhost);
+ ibmvfc_init_event(evt, done, IBMVFC_MAD_FORMAT);
+ evt->tgt = tgt;
+ mad = &evt->iu.implicit_logout;
+ memset(mad, 0, sizeof(*mad));
+ mad->common.version = cpu_to_be32(1);
+ mad->common.opcode = cpu_to_be32(IBMVFC_IMPLICIT_LOGOUT);
+ mad->common.length = cpu_to_be16(sizeof(*mad));
+ mad->old_scsi_id = cpu_to_be64(tgt->scsi_id);
+ return evt;
+}
+
+/**
* ibmvfc_tgt_implicit_logout - Initiate an Implicit Logout for specified target
* @tgt: ibmvfc target struct
*
**/
static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt)
{
- struct ibmvfc_implicit_logout *mad;
struct ibmvfc_host *vhost = tgt->vhost;
struct ibmvfc_event *evt;
if (vhost->discovery_threads >= disc_threads)
return;
- kref_get(&tgt->kref);
- evt = ibmvfc_get_event(vhost);
vhost->discovery_threads++;
- ibmvfc_init_event(evt, ibmvfc_tgt_implicit_logout_done, IBMVFC_MAD_FORMAT);
- evt->tgt = tgt;
- mad = &evt->iu.implicit_logout;
- memset(mad, 0, sizeof(*mad));
- mad->common.version = cpu_to_be32(1);
- mad->common.opcode = cpu_to_be32(IBMVFC_IMPLICIT_LOGOUT);
- mad->common.length = cpu_to_be16(sizeof(*mad));
- mad->old_scsi_id = cpu_to_be64(tgt->scsi_id);
+ evt = __ibmvfc_tgt_get_implicit_logout_evt(tgt,
+ ibmvfc_tgt_implicit_logout_done);
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
if (ibmvfc_send_event(evt, vhost, default_timeout)) {
@@ -3562,6 +3652,157 @@
}
/**
+ * ibmvfc_tgt_implicit_logout_and_del_done - Completion handler for Implicit Logout MAD
+ * @evt: ibmvfc event struct
+ *
+ **/
+static void ibmvfc_tgt_implicit_logout_and_del_done(struct ibmvfc_event *evt)
+{
+ struct ibmvfc_target *tgt = evt->tgt;
+ struct ibmvfc_host *vhost = evt->vhost;
+ struct ibmvfc_passthru_mad *mad = &evt->xfer_iu->passthru;
+ u32 status = be16_to_cpu(mad->common.status);
+
+ vhost->discovery_threads--;
+ ibmvfc_free_event(evt);
+
+ /*
+ * If our state is IBMVFC_HOST_OFFLINE, we could be unloading the
+ * driver in which case we need to free up all the targets. If we are
+ * not unloading, we will still go through a hard reset to get out of
+ * offline state, so there is no need to track the old targets in that
+ * case.
+ */
+ if (status == IBMVFC_MAD_SUCCESS || vhost->state == IBMVFC_HOST_OFFLINE)
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ else
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT);
+
+ tgt_dbg(tgt, "Implicit Logout %s\n", (status == IBMVFC_MAD_SUCCESS) ? "succeeded" : "failed");
+ kref_put(&tgt->kref, ibmvfc_release_tgt);
+ wake_up(&vhost->work_wait_q);
+}
+
+/**
+ * ibmvfc_tgt_implicit_logout_and_del - Initiate an Implicit Logout for specified target
+ * @tgt: ibmvfc target struct
+ *
+ **/
+static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *tgt)
+{
+ struct ibmvfc_host *vhost = tgt->vhost;
+ struct ibmvfc_event *evt;
+
+ if (!vhost->logged_in) {
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ return;
+ }
+
+ if (vhost->discovery_threads >= disc_threads)
+ return;
+
+ vhost->discovery_threads++;
+ evt = __ibmvfc_tgt_get_implicit_logout_evt(tgt,
+ ibmvfc_tgt_implicit_logout_and_del_done);
+
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT);
+ if (ibmvfc_send_event(evt, vhost, default_timeout)) {
+ vhost->discovery_threads--;
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ kref_put(&tgt->kref, ibmvfc_release_tgt);
+ } else
+ tgt_dbg(tgt, "Sent Implicit Logout\n");
+}
+
+/**
+ * ibmvfc_tgt_move_login_done - Completion handler for Move Login
+ * @evt: ibmvfc event struct
+ *
+ **/
+static void ibmvfc_tgt_move_login_done(struct ibmvfc_event *evt)
+{
+ struct ibmvfc_target *tgt = evt->tgt;
+ struct ibmvfc_host *vhost = evt->vhost;
+ struct ibmvfc_move_login *rsp = &evt->xfer_iu->move_login;
+ u32 status = be16_to_cpu(rsp->common.status);
+ int level = IBMVFC_DEFAULT_LOG_LEVEL;
+
+ vhost->discovery_threads--;
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
+ switch (status) {
+ case IBMVFC_MAD_SUCCESS:
+ tgt_dbg(tgt, "Move Login succeeded for old scsi_id: %llX\n", tgt->old_scsi_id);
+ tgt->ids.node_name = wwn_to_u64(rsp->service_parms.node_name);
+ tgt->ids.port_name = wwn_to_u64(rsp->service_parms.port_name);
+ tgt->ids.port_id = tgt->scsi_id;
+ memcpy(&tgt->service_parms, &rsp->service_parms,
+ sizeof(tgt->service_parms));
+ memcpy(&tgt->service_parms_change, &rsp->service_parms_change,
+ sizeof(tgt->service_parms_change));
+ ibmvfc_init_tgt(tgt, ibmvfc_tgt_send_prli);
+ break;
+ case IBMVFC_MAD_DRIVER_FAILED:
+ break;
+ case IBMVFC_MAD_CRQ_ERROR:
+ ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_move_login);
+ break;
+ case IBMVFC_MAD_FAILED:
+ default:
+ level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_move_login);
+
+ tgt_log(tgt, level,
+ "Move Login failed: old scsi_id: %llX, flags:%x, vios_flags:%x, rc=0x%02X\n",
+ tgt->old_scsi_id, be32_to_cpu(rsp->flags), be16_to_cpu(rsp->vios_flags),
+ status);
+ break;
+ }
+
+ kref_put(&tgt->kref, ibmvfc_release_tgt);
+ ibmvfc_free_event(evt);
+ wake_up(&vhost->work_wait_q);
+}
+
+
+/**
+ * ibmvfc_tgt_move_login - Initiate a move login for specified target
+ * @tgt: ibmvfc target struct
+ *
+ **/
+static void ibmvfc_tgt_move_login(struct ibmvfc_target *tgt)
+{
+ struct ibmvfc_host *vhost = tgt->vhost;
+ struct ibmvfc_move_login *move;
+ struct ibmvfc_event *evt;
+
+ if (vhost->discovery_threads >= disc_threads)
+ return;
+
+ kref_get(&tgt->kref);
+ evt = ibmvfc_get_event(vhost);
+ vhost->discovery_threads++;
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
+ ibmvfc_init_event(evt, ibmvfc_tgt_move_login_done, IBMVFC_MAD_FORMAT);
+ evt->tgt = tgt;
+ move = &evt->iu.move_login;
+ memset(move, 0, sizeof(*move));
+ move->common.version = cpu_to_be32(1);
+ move->common.opcode = cpu_to_be32(IBMVFC_MOVE_LOGIN);
+ move->common.length = cpu_to_be16(sizeof(*move));
+
+ move->old_scsi_id = cpu_to_be64(tgt->old_scsi_id);
+ move->new_scsi_id = cpu_to_be64(tgt->scsi_id);
+ move->wwpn = cpu_to_be64(tgt->wwpn);
+ move->node_name = cpu_to_be64(tgt->ids.node_name);
+
+ if (ibmvfc_send_event(evt, vhost, default_timeout)) {
+ vhost->discovery_threads--;
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ kref_put(&tgt->kref, ibmvfc_release_tgt);
+ } else
+ tgt_dbg(tgt, "Sent Move Login for old scsi_id: %llX\n", tgt->old_scsi_id);
+}
+
+/**
* ibmvfc_adisc_needs_plogi - Does device need PLOGI?
* @mad: ibmvfc passthru mad struct
* @tgt: ibmvfc target struct
@@ -3602,13 +3843,13 @@
case IBMVFC_MAD_SUCCESS:
tgt_dbg(tgt, "ADISC succeeded\n");
if (ibmvfc_adisc_needs_plogi(mad, tgt))
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_del_tgt(tgt);
break;
case IBMVFC_MAD_DRIVER_FAILED:
break;
case IBMVFC_MAD_FAILED:
default:
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_del_tgt(tgt);
fc_reason = (be32_to_cpu(mad->fc_iu.response[1]) & 0x00ff0000) >> 16;
fc_explain = (be32_to_cpu(mad->fc_iu.response[1]) & 0x0000ff00) >> 8;
tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
@@ -3801,9 +4042,8 @@
switch (status) {
case IBMVFC_MAD_SUCCESS:
tgt_dbg(tgt, "Query Target succeeded\n");
- tgt->new_scsi_id = be64_to_cpu(rsp->scsi_id);
if (be64_to_cpu(rsp->scsi_id) != tgt->scsi_id)
- ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout);
+ ibmvfc_del_tgt(tgt);
else
ibmvfc_init_tgt(tgt, ibmvfc_tgt_adisc);
break;
@@ -3817,11 +4057,11 @@
if ((be16_to_cpu(rsp->status) & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED &&
be16_to_cpu(rsp->error) == IBMVFC_UNABLE_TO_PERFORM_REQ &&
be16_to_cpu(rsp->fc_explain) == IBMVFC_PORT_NAME_NOT_REG)
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_del_tgt(tgt);
else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_query_target);
else
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ ibmvfc_del_tgt(tgt);
tgt_log(tgt, level, "Query Target failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
@@ -3880,32 +4120,77 @@
* Returns:
* 0 on success / other on failure
**/
-static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, u64 scsi_id)
+static int ibmvfc_alloc_target(struct ibmvfc_host *vhost,
+ struct ibmvfc_discover_targets_entry *target)
{
+ struct ibmvfc_target *stgt = NULL;
+ struct ibmvfc_target *wtgt = NULL;
struct ibmvfc_target *tgt;
unsigned long flags;
+ u64 scsi_id = be32_to_cpu(target->scsi_id) & IBMVFC_DISC_TGT_SCSI_ID_MASK;
+ u64 wwpn = be64_to_cpu(target->wwpn);
+ /* Look to see if we already have a target allocated for this SCSI ID or WWPN */
spin_lock_irqsave(vhost->host->host_lock, flags);
list_for_each_entry(tgt, &vhost->targets, queue) {
- if (tgt->scsi_id == scsi_id) {
- if (tgt->need_login)
- ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout);
- goto unlock_out;
+ if (tgt->wwpn == wwpn) {
+ wtgt = tgt;
+ break;
}
}
+
+ list_for_each_entry(tgt, &vhost->targets, queue) {
+ if (tgt->scsi_id == scsi_id) {
+ stgt = tgt;
+ break;
+ }
+ }
+
+ if (wtgt && !stgt) {
+ /*
+ * A WWPN target has moved and we still are tracking the old
+ * SCSI ID. The only way we should be able to get here is if
+ * we attempted to send an implicit logout for the old SCSI ID
+ * and it failed for some reason, such as there being I/O
+ * pending to the target. In this case, we will have already
+ * deleted the rport from the FC transport so we do a move
+ * login, which works even with I/O pending, as it will cancel
+ * any active commands.
+ */
+ if (wtgt->action == IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT) {
+ /*
+ * Do a move login here. The old target is no longer
+ * known to the transport layer We don't use the
+ * normal ibmvfc_set_tgt_action to set this, as we
+ * don't normally want to allow this state change.
+ */
+ wtgt->old_scsi_id = wtgt->scsi_id;
+ wtgt->scsi_id = scsi_id;
+ wtgt->action = IBMVFC_TGT_ACTION_INIT;
+ ibmvfc_init_tgt(wtgt, ibmvfc_tgt_move_login);
+ goto unlock_out;
+ } else {
+ tgt_err(wtgt, "Unexpected target state: %d, %p\n",
+ wtgt->action, wtgt->rport);
+ }
+ } else if (stgt) {
+ if (tgt->need_login)
+ ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout);
+ goto unlock_out;
+ }
spin_unlock_irqrestore(vhost->host->host_lock, flags);
tgt = mempool_alloc(vhost->tgt_pool, GFP_NOIO);
memset(tgt, 0, sizeof(*tgt));
tgt->scsi_id = scsi_id;
- tgt->new_scsi_id = scsi_id;
+ tgt->wwpn = wwpn;
tgt->vhost = vhost;
tgt->need_login = 1;
- tgt->cancel_key = vhost->task_set++;
timer_setup(&tgt->timer, ibmvfc_adisc_timeout, 0);
kref_init(&tgt->kref);
ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout);
spin_lock_irqsave(vhost->host->host_lock, flags);
+ tgt->cancel_key = vhost->task_set++;
list_add_tail(&tgt->queue, &vhost->targets);
unlock_out:
@@ -3925,9 +4210,7 @@
int i, rc;
for (i = 0, rc = 0; !rc && i < vhost->num_targets; i++)
- rc = ibmvfc_alloc_target(vhost,
- be32_to_cpu(vhost->disc_buf->scsi_id[i]) &
- IBMVFC_DISC_TGT_SCSI_ID_MASK);
+ rc = ibmvfc_alloc_target(vhost, &vhost->disc_buf[i]);
return rc;
}
@@ -3987,6 +4270,7 @@
mad->bufflen = cpu_to_be32(vhost->disc_buf_sz);
mad->buffer.va = cpu_to_be64(vhost->disc_buf_dma);
mad->buffer.len = cpu_to_be32(vhost->disc_buf_sz);
+ mad->flags = cpu_to_be32(IBMVFC_DISC_TGT_PORT_ID_WWPN_LIST);
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT);
if (!ibmvfc_send_event(evt, vhost, default_timeout))
@@ -4024,7 +4308,7 @@
return;
case IBMVFC_MAD_CRQ_ERROR:
ibmvfc_retry_host_init(vhost);
- /* fall through */
+ fallthrough;
case IBMVFC_MAD_DRIVER_FAILED:
ibmvfc_free_event(evt);
return;
@@ -4191,6 +4475,25 @@
}
/**
+ * ibmvfc_dev_logo_to_do - Is there target logout work to do?
+ * @vhost: ibmvfc host struct
+ *
+ * Returns:
+ * 1 if work to do / 0 if not
+ **/
+static int ibmvfc_dev_logo_to_do(struct ibmvfc_host *vhost)
+{
+ struct ibmvfc_target *tgt;
+
+ list_for_each_entry(tgt, &vhost->targets, queue) {
+ if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT ||
+ tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT)
+ return 1;
+ }
+ return 0;
+}
+
+/**
* __ibmvfc_work_to_do - Is there task level work to do? (no locking)
* @vhost: ibmvfc host struct
*
@@ -4219,11 +4522,20 @@
if (tgt->action == IBMVFC_TGT_ACTION_INIT_WAIT)
return 0;
return 1;
+ case IBMVFC_HOST_ACTION_TGT_DEL:
+ case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
+ if (vhost->discovery_threads == disc_threads)
+ return 0;
+ list_for_each_entry(tgt, &vhost->targets, queue)
+ if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT)
+ return 1;
+ list_for_each_entry(tgt, &vhost->targets, queue)
+ if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT)
+ return 0;
+ return 1;
case IBMVFC_HOST_ACTION_LOGO:
case IBMVFC_HOST_ACTION_INIT:
case IBMVFC_HOST_ACTION_ALLOC_TGTS:
- case IBMVFC_HOST_ACTION_TGT_DEL:
- case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
case IBMVFC_HOST_ACTION_QUERY:
case IBMVFC_HOST_ACTION_RESET:
case IBMVFC_HOST_ACTION_REENABLE:
@@ -4294,6 +4606,13 @@
del_timer_sync(&tgt->timer);
kref_put(&tgt->kref, ibmvfc_release_tgt);
return;
+ } else if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT) {
+ tgt_dbg(tgt, "Deleting rport with outstanding I/O\n");
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT);
+ tgt->rport = NULL;
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ fc_remote_port_delete(rport);
+ return;
} else if (rport && tgt->action == IBMVFC_TGT_ACTION_DELETED_RPORT) {
spin_unlock_irqrestore(vhost->host->host_lock, flags);
return;
@@ -4412,6 +4731,18 @@
case IBMVFC_HOST_ACTION_TGT_DEL:
case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
list_for_each_entry(tgt, &vhost->targets, queue) {
+ if (tgt->action == IBMVFC_TGT_ACTION_LOGOUT_RPORT) {
+ tgt->job_step(tgt);
+ break;
+ }
+ }
+
+ if (ibmvfc_dev_logo_to_do(vhost)) {
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ return;
+ }
+
+ list_for_each_entry(tgt, &vhost->targets, queue) {
if (tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) {
tgt_dbg(tgt, "Deleting rport\n");
rport = tgt->rport;
@@ -4424,6 +4755,15 @@
del_timer_sync(&tgt->timer);
kref_put(&tgt->kref, ibmvfc_release_tgt);
return;
+ } else if (tgt->action == IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT) {
+ tgt_dbg(tgt, "Deleting rport with I/O outstanding\n");
+ rport = tgt->rport;
+ tgt->rport = NULL;
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT);
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ if (rport)
+ fc_remote_port_delete(rport);
+ return;
}
}
@@ -4656,7 +4996,7 @@
goto free_sg_pool;
}
- vhost->disc_buf_sz = sizeof(vhost->disc_buf->scsi_id[0]) * max_targets;
+ vhost->disc_buf_sz = sizeof(*vhost->disc_buf) * max_targets;
vhost->disc_buf = dma_alloc_coherent(dev, vhost->disc_buf_sz,
&vhost->disc_buf_dma, GFP_KERNEL);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 7da89f4..34debcc 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -120,10 +120,14 @@
IBMVFC_PORT_LOGIN = 0x0004,
IBMVFC_PROCESS_LOGIN = 0x0008,
IBMVFC_QUERY_TARGET = 0x0010,
+ IBMVFC_MOVE_LOGIN = 0x0020,
IBMVFC_IMPLICIT_LOGOUT = 0x0040,
IBMVFC_PASSTHRU = 0x0200,
IBMVFC_TMF_MAD = 0x0100,
IBMVFC_NPIV_LOGOUT = 0x0800,
+ IBMVFC_CHANNEL_ENQUIRY = 0x1000,
+ IBMVFC_CHANNEL_SETUP = 0x2000,
+ IBMVFC_CONNECTION_INFO = 0x4000,
};
struct ibmvfc_mad_common {
@@ -133,16 +137,16 @@
__be16 status;
__be16 length;
__be64 tag;
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
struct ibmvfc_npiv_login_mad {
struct ibmvfc_mad_common common;
struct srp_direct_buf buffer;
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
struct ibmvfc_npiv_logout_mad {
struct ibmvfc_mad_common common;
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
#define IBMVFC_MAX_NAME 256
@@ -162,13 +166,15 @@
__be32 max_cmds;
__be64 capabilities;
#define IBMVFC_CAN_MIGRATE 0x01
+#define IBMVFC_CAN_USE_CHANNELS 0x02
+#define IBMVFC_CAN_HANDLE_FPIN 0x04
__be64 node_name;
struct srp_direct_buf async;
u8 partition_name[IBMVFC_MAX_NAME];
u8 device_name[IBMVFC_MAX_NAME];
u8 drc_name[IBMVFC_MAX_NAME];
__be64 reserved2[2];
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
struct ibmvfc_common_svc_parms {
__be16 fcph_version;
@@ -177,7 +183,7 @@
__be16 bb_rcv_sz; /* upper nibble is BB_SC_N */
__be32 ratov;
__be32 edtov;
-}__attribute__((packed, aligned (4)));
+} __packed __aligned(4);
struct ibmvfc_service_parms {
struct ibmvfc_common_svc_parms common;
@@ -192,7 +198,8 @@
__be32 ext_len;
__be32 reserved[30];
__be32 clk_sync_qos[2];
-}__attribute__((packed, aligned (4)));
+ __be32 reserved2;
+} __packed __aligned(4);
struct ibmvfc_npiv_login_resp {
__be32 version;
@@ -204,6 +211,7 @@
__be64 capabilities;
#define IBMVFC_CAN_FLUSH_ON_HALT 0x08
#define IBMVFC_CAN_SUPPRESS_ABTS 0x10
+#define IBMVFC_CAN_SUPPORT_CHANNELS 0x20
__be32 max_cmds;
__be32 scsi_id_sz;
__be64 max_dma_len;
@@ -217,29 +225,32 @@
u8 drc_name[IBMVFC_MAX_NAME];
struct ibmvfc_service_parms service_parms;
__be64 reserved2;
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
union ibmvfc_npiv_login_data {
struct ibmvfc_npiv_login login;
struct ibmvfc_npiv_login_resp resp;
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
-struct ibmvfc_discover_targets_buf {
- __be32 scsi_id[1];
+struct ibmvfc_discover_targets_entry {
+ __be32 scsi_id;
+ __be32 pad;
+ __be64 wwpn;
#define IBMVFC_DISC_TGT_SCSI_ID_MASK 0x00ffffff
-};
+} __packed __aligned(8);
struct ibmvfc_discover_targets {
struct ibmvfc_mad_common common;
struct srp_direct_buf buffer;
__be32 flags;
+#define IBMVFC_DISC_TGT_PORT_ID_WWPN_LIST 0x02
__be16 status;
__be16 error;
__be32 bufflen;
__be32 num_avail;
__be32 num_written;
__be64 reserved[2];
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
enum ibmvfc_fc_reason {
IBMVFC_INVALID_ELS_CMD_CODE = 0x01,
@@ -283,7 +294,27 @@
struct ibmvfc_service_parms service_parms;
struct ibmvfc_service_parms service_parms_change;
__be64 reserved3[2];
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
+
+struct ibmvfc_move_login {
+ struct ibmvfc_mad_common common;
+ __be64 old_scsi_id;
+ __be64 new_scsi_id;
+ __be64 wwpn;
+ __be64 node_name;
+ __be32 flags;
+#define IBMVFC_MOVE_LOGIN_IMPLICIT_OLD_FAILED 0x01
+#define IBMVFC_MOVE_LOGIN_IMPLICIT_NEW_FAILED 0x02
+#define IBMVFC_MOVE_LOGIN_PORT_LOGIN_FAILED 0x04
+ __be32 reserved;
+ struct ibmvfc_service_parms service_parms;
+ struct ibmvfc_service_parms service_parms_change;
+ __be32 reserved2;
+ __be16 service_class;
+ __be16 vios_flags;
+#define IBMVFC_MOVE_LOGIN_VF_NOT_SENT_ADAPTER 0x01
+ __be64 reserved3;
+} __packed __aligned(8);
struct ibmvfc_prli_svc_parms {
u8 type;
@@ -303,7 +334,7 @@
#define IBMVFC_PRLI_TARGET_FUNC 0x00000010
#define IBMVFC_PRLI_READ_FCP_XFER_RDY_DISABLED 0x00000002
#define IBMVFC_PRLI_WR_FCP_XFER_RDY_DISABLED 0x00000001
-}__attribute__((packed, aligned (4)));
+} __packed __aligned(4);
struct ibmvfc_process_login {
struct ibmvfc_mad_common common;
@@ -314,7 +345,7 @@
__be16 error; /* also fc_reason */
__be32 reserved2;
__be64 reserved3[2];
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
struct ibmvfc_query_tgt {
struct ibmvfc_mad_common common;
@@ -325,13 +356,13 @@
__be16 fc_explain;
__be16 fc_type;
__be64 reserved[2];
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
struct ibmvfc_implicit_logout {
struct ibmvfc_mad_common common;
__be64 old_scsi_id;
__be64 reserved[2];
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
struct ibmvfc_tmf {
struct ibmvfc_mad_common common;
@@ -348,7 +379,7 @@
__be32 my_cancel_key;
__be32 pad;
__be64 reserved[2];
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
enum ibmvfc_fcp_rsp_info_codes {
RSP_NO_FAILURE = 0x00,
@@ -361,7 +392,7 @@
u8 reserved[3];
u8 rsp_code;
u8 reserved2[4];
-}__attribute__((packed, aligned (2)));
+} __packed __aligned(2);
enum ibmvfc_fcp_rsp_flags {
FCP_BIDI_RSP = 0x80,
@@ -377,7 +408,7 @@
union ibmvfc_fcp_rsp_data {
struct ibmvfc_fcp_rsp_info info;
u8 sense[SCSI_SENSE_BUFFERSIZE + sizeof(struct ibmvfc_fcp_rsp_info)];
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
struct ibmvfc_fcp_rsp {
__be64 reserved;
@@ -388,7 +419,7 @@
__be32 fcp_sense_len;
__be32 fcp_rsp_len;
union ibmvfc_fcp_rsp_data data;
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
enum ibmvfc_cmd_flags {
IBMVFC_SCATTERLIST = 0x0001,
@@ -422,7 +453,7 @@
#define IBMVFC_WRDATA 0x01
u8 cdb[IBMVFC_MAX_CDB_LEN];
__be32 xfer_len;
-}__attribute__((packed, aligned (4)));
+} __packed __aligned(4);
struct ibmvfc_cmd {
__be64 task_tag;
@@ -446,7 +477,7 @@
__be64 reserved3[2];
struct ibmvfc_fcp_cmd_iu iu;
struct ibmvfc_fcp_rsp rsp;
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
struct ibmvfc_passthru_fc_iu {
__be32 payload[7];
@@ -473,18 +504,64 @@
__be64 scsi_id;
__be64 tag;
__be64 reserved2[2];
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
struct ibmvfc_passthru_mad {
struct ibmvfc_mad_common common;
struct srp_direct_buf cmd_ioba;
struct ibmvfc_passthru_iu iu;
struct ibmvfc_passthru_fc_iu fc_iu;
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
+
+struct ibmvfc_channel_enquiry {
+ struct ibmvfc_mad_common common;
+ __be32 flags;
+#define IBMVFC_NO_CHANNELS_TO_CRQ_SUPPORT 0x01
+#define IBMVFC_SUPPORT_VARIABLE_SUBQ_MSG 0x02
+#define IBMVFC_NO_N_TO_M_CHANNELS_SUPPORT 0x04
+ __be32 num_scsi_subq_channels;
+ __be32 num_nvmeof_subq_channels;
+ __be32 num_scsi_vas_channels;
+ __be32 num_nvmeof_vas_channels;
+} __packed __aligned(8);
+
+struct ibmvfc_channel_setup_mad {
+ struct ibmvfc_mad_common common;
+ struct srp_direct_buf buffer;
+} __packed __aligned(8);
+
+#define IBMVFC_MAX_CHANNELS 502
+
+struct ibmvfc_channel_setup {
+ __be32 flags;
+#define IBMVFC_CANCEL_CHANNELS 0x01
+#define IBMVFC_USE_BUFFER 0x02
+#define IBMVFC_CHANNELS_CANCELED 0x04
+ __be32 reserved;
+ __be32 num_scsi_subq_channels;
+ __be32 num_nvmeof_subq_channels;
+ __be32 num_scsi_vas_channels;
+ __be32 num_nvmeof_vas_channels;
+ struct srp_direct_buf buffer;
+ __be64 reserved2[5];
+ __be64 channel_handles[IBMVFC_MAX_CHANNELS];
+} __packed __aligned(8);
+
+struct ibmvfc_connection_info {
+ struct ibmvfc_mad_common common;
+ __be64 information_bits;
+#define IBMVFC_NO_FC_IO_CHANNEL 0x01
+#define IBMVFC_NO_PHYP_VAS 0x02
+#define IBMVFC_NO_PHYP_SUBQ 0x04
+#define IBMVFC_PHYP_DEPRECATED_SUBQ 0x08
+#define IBMVFC_PHYP_PRESERVED_SUBQ 0x10
+#define IBMVFC_PHYP_FULL_SUBQ 0x20
+ __be64 reserved[16];
+} __packed __aligned(8);
struct ibmvfc_trace_start_entry {
u32 xfer_len;
-}__attribute__((packed));
+} __packed;
struct ibmvfc_trace_end_entry {
u16 status;
@@ -493,7 +570,7 @@
u8 rsp_code;
u8 scsi_status;
u8 reserved;
-}__attribute__((packed));
+} __packed;
struct ibmvfc_trace_entry {
struct ibmvfc_event *evt;
@@ -510,7 +587,7 @@
struct ibmvfc_trace_start_entry start;
struct ibmvfc_trace_end_entry end;
} u;
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
enum ibmvfc_crq_formats {
IBMVFC_CMD_FORMAT = 0x01,
@@ -532,6 +609,7 @@
IBMVFC_AE_HALT = 0x0400,
IBMVFC_AE_RESUME = 0x0800,
IBMVFC_AE_ADAPTER_FAILED = 0x1000,
+ IBMVFC_AE_FPIN = 0x2000,
};
struct ibmvfc_async_desc {
@@ -545,7 +623,7 @@
volatile u8 format;
u8 reserved[6];
volatile __be64 ioba;
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
struct ibmvfc_crq_queue {
struct ibmvfc_crq *msgs;
@@ -560,17 +638,25 @@
IBMVFC_AE_LS_LINK_DEAD = 0x08,
};
+enum ibmvfc_ae_fpin_status {
+ IBMVFC_AE_FPIN_LINK_CONGESTED = 0x1,
+ IBMVFC_AE_FPIN_PORT_CONGESTED = 0x2,
+ IBMVFC_AE_FPIN_PORT_CLEARED = 0x3,
+ IBMVFC_AE_FPIN_PORT_DEGRADED = 0x4,
+};
+
struct ibmvfc_async_crq {
volatile u8 valid;
u8 link_state;
- u8 pad[2];
+ u8 fpin_status;
+ u8 pad;
__be32 pad2;
volatile __be64 event;
volatile __be64 scsi_id;
volatile __be64 wwpn;
volatile __be64 node_name;
__be64 reserved;
-}__attribute__((packed, aligned (8)));
+} __packed __aligned(8);
struct ibmvfc_async_crq_queue {
struct ibmvfc_async_crq *msgs;
@@ -585,26 +671,35 @@
struct ibmvfc_discover_targets discover_targets;
struct ibmvfc_port_login plogi;
struct ibmvfc_process_login prli;
+ struct ibmvfc_move_login move_login;
struct ibmvfc_query_tgt query_tgt;
struct ibmvfc_implicit_logout implicit_logout;
struct ibmvfc_tmf tmf;
struct ibmvfc_cmd cmd;
struct ibmvfc_passthru_mad passthru;
-}__attribute__((packed, aligned (8)));
+ struct ibmvfc_channel_enquiry channel_enquiry;
+ struct ibmvfc_channel_setup_mad channel_setup;
+ struct ibmvfc_connection_info connection_info;
+} __packed __aligned(8);
enum ibmvfc_target_action {
IBMVFC_TGT_ACTION_NONE = 0,
IBMVFC_TGT_ACTION_INIT,
IBMVFC_TGT_ACTION_INIT_WAIT,
+ IBMVFC_TGT_ACTION_LOGOUT_RPORT,
+ IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT,
IBMVFC_TGT_ACTION_DEL_RPORT,
IBMVFC_TGT_ACTION_DELETED_RPORT,
+ IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT,
+ IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT,
};
struct ibmvfc_target {
struct list_head queue;
struct ibmvfc_host *vhost;
u64 scsi_id;
- u64 new_scsi_id;
+ u64 wwpn;
+ u64 old_scsi_id;
struct fc_rport *rport;
int target_id;
enum ibmvfc_target_action action;
@@ -700,7 +795,7 @@
dma_addr_t login_buf_dma;
int disc_buf_sz;
int log_level;
- struct ibmvfc_discover_targets_buf *disc_buf;
+ struct ibmvfc_discover_targets_entry *disc_buf;
struct mutex passthru_mutex;
int task_set;
int init_retries;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 1ab0a61..29fcc44 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -669,7 +669,7 @@
}
/**
- * map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields
+ * map_sg_data: - Maps dma for a scatterlist and initializes descriptor fields
* @cmd: struct scsi_cmnd with the scatterlist
* @srp_cmd: srp_cmd that contains the memory descriptor
* @dev: device for which to map dma memory
@@ -2402,7 +2402,7 @@
static struct srp_function_template ibmvscsi_transport_functions = {
};
-int __init ibmvscsi_module_init(void)
+static int __init ibmvscsi_module_init(void)
{
int ret;
@@ -2424,7 +2424,7 @@
return ret;
}
-void __exit ibmvscsi_module_exit(void)
+static void __exit ibmvscsi_module_exit(void)
{
vio_unregister_driver(&ibmvscsi_driver);
srp_release_transport(ibmvscsi_transport_template);
diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
index a929fe7..cc3908c 100644
--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
+++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
@@ -1581,7 +1581,7 @@
case H_PERMISSION:
if (connection_broken(vscsi))
flag_bits = (RESPONSE_Q_DOWN | CLIENT_FAILED);
- /* Fall through */
+ fallthrough;
default:
dev_err(&vscsi->dev, "adapter_info: h_copy_rdma to client failed, rc %ld\n",
rc);
@@ -1877,7 +1877,6 @@
*/
struct viosrp_crq *crq = (struct viosrp_crq *)&msg_hi;
struct ibmvscsis_cmd *cmd, *nxt;
- struct iu_entry *iue;
long rc = ADAPT_SUCCESS;
bool retry = false;
@@ -1931,8 +1930,6 @@
*/
vscsi->credit += 1;
} else {
- iue = cmd->iue;
-
crq->valid = VALID_CMD_RESP_EL;
crq->format = cmd->rsp.format;
@@ -2354,7 +2351,6 @@
{
struct iu_entry *iue = cmd->iue;
struct srp_i_logout *log_out = &vio_iu(iue)->srp.i_logout;
- long rc = ADAPT_SUCCESS;
if ((vscsi->debit > 0) || !list_empty(&vscsi->schedule_q) ||
!list_empty(&vscsi->waiting_rsp)) {
@@ -2370,7 +2366,7 @@
ibmvscsis_post_disconnect(vscsi, WAIT_IDLE, 0);
}
- return rc;
+ return ADAPT_SUCCESS;
}
/* Called with intr lock held */
@@ -2493,10 +2489,10 @@
break;
case H_CLOSED:
vscsi->flags |= CLIENT_FAILED;
- /* Fall through */
+ fallthrough;
case H_DROPPED:
vscsi->flags |= RESPONSE_Q_DOWN;
- /* Fall through */
+ fallthrough;
case H_REMOTE_PARM:
dev_err(&vscsi->dev, "ping_response: h_send_crq failed, rc %ld\n",
rc);
@@ -3797,7 +3793,6 @@
se_cmd);
struct iu_entry *iue = cmd->iue;
struct scsi_info *vscsi = cmd->adapter;
- char *sd;
uint len = 0;
int rc;
@@ -3805,7 +3800,6 @@
1);
if (rc) {
dev_err(&vscsi->dev, "srp_transfer_data failed: %d\n", rc);
- sd = se_cmd->sense_buffer;
se_cmd->scsi_sense_length = 18;
memset(se_cmd->sense_buffer, 0, se_cmd->scsi_sense_length);
/* Logical Unit Communication Time-out asc/ascq = 0x0801 */
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index 2519fb7..862d35a 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -801,7 +801,7 @@
case 1: /* Phase 1 - Connected */
imm_connect(dev, CONNECT_EPP_MAYBE);
cmd->SCp.phase++;
- /* fall through */
+ fallthrough;
case 2: /* Phase 2 - We are now talking to the scsi bus */
if (!imm_select(dev, scmd_id(cmd))) {
@@ -809,7 +809,7 @@
return 0;
}
cmd->SCp.phase++;
- /* fall through */
+ fallthrough;
case 3: /* Phase 3 - Ready to accept a command */
w_ctr(ppb, 0x0c);
@@ -819,7 +819,7 @@
if (!imm_send_command(cmd))
return 0;
cmd->SCp.phase++;
- /* fall through */
+ fallthrough;
case 4: /* Phase 4 - Setup scatter/gather buffers */
if (scsi_bufflen(cmd)) {
@@ -835,7 +835,7 @@
cmd->SCp.phase++;
if (cmd->SCp.this_residual & 0x01)
cmd->SCp.this_residual++;
- /* fall through */
+ fallthrough;
case 5: /* Phase 5 - Pre-Data transfer stage */
/* Spin lock for BUSY */
@@ -852,7 +852,7 @@
if (imm_negotiate(dev))
return 0;
cmd->SCp.phase++;
- /* fall through */
+ fallthrough;
case 6: /* Phase 6 - Data transfer stage */
/* Spin lock for BUSY */
@@ -868,7 +868,7 @@
return 1;
}
cmd->SCp.phase++;
- /* fall through */
+ fallthrough;
case 7: /* Phase 7 - Post data transfer stage */
if ((dev->dp) && (dev->rd)) {
@@ -880,7 +880,7 @@
}
}
cmd->SCp.phase++;
- /* fall through */
+ fallthrough;
case 8: /* Phase 8 - Read status/message */
/* Check for data overrun */
@@ -903,7 +903,6 @@
w_ctr(ppb, 0x4);
}
return 0; /* Finished */
- break;
default:
printk("imm: Invalid scsi phase\n");
@@ -969,10 +968,8 @@
case 1: /* Have not connected to interface */
dev->cur_cmd = NULL; /* Forget the problem */
return SUCCESS;
- break;
default: /* SCSI command sent, can not abort */
return FAILED;
- break;
}
}
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index 41fd64c..ca16ef4 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -1640,7 +1640,7 @@
*
*/
-int initio_state_7(struct initio_host * host)
+static int initio_state_7(struct initio_host * host)
{
int cnt, i;
@@ -2962,20 +2962,8 @@
.probe = initio_probe_one,
.remove = initio_remove_one,
};
-
-static int __init initio_init_driver(void)
-{
- return pci_register_driver(&initio_pci_driver);
-}
-
-static void __exit initio_exit_driver(void)
-{
- pci_unregister_driver(&initio_pci_driver);
-}
+module_pci_driver(initio_pci_driver);
MODULE_DESCRIPTION("Initio INI-9X00U/UW SCSI device driver");
MODULE_AUTHOR("Initio Corporation");
MODULE_LICENSE("GPL");
-
-module_init(initio_init_driver);
-module_exit(initio_exit_driver);
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 7a57b61..b0aa58d 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -670,6 +670,7 @@
/**
* ipr_init_ipr_cmnd - Initialize an IPR Cmnd block
* @ipr_cmd: ipr command struct
+ * @fast_done: fast done function call-back
*
* Return value:
* none
@@ -687,7 +688,7 @@
/**
* __ipr_get_free_ipr_cmnd - Get a free IPR Cmnd block
- * @ioa_cfg: ioa config struct
+ * @hrrq: hrr queue
*
* Return value:
* pointer to ipr command struct
@@ -737,7 +738,6 @@
static void ipr_mask_and_clear_interrupts(struct ipr_ioa_cfg *ioa_cfg,
u32 clr_ints)
{
- volatile u32 int_reg;
int i;
/* Stop new interrupts */
@@ -757,7 +757,7 @@
if (ioa_cfg->sis64)
writel(~0, ioa_cfg->regs.clr_interrupt_reg);
writel(clr_ints, ioa_cfg->regs.clr_interrupt_reg32);
- int_reg = readl(ioa_cfg->regs.sense_interrupt_reg);
+ readl(ioa_cfg->regs.sense_interrupt_reg);
}
/**
@@ -1164,7 +1164,7 @@
default:
res->ata_class = ATA_DEV_UNKNOWN;
break;
- };
+ }
}
/**
@@ -1287,7 +1287,7 @@
/**
* __ipr_format_res_path - Format the resource path for printing.
* @res_path: resource path
- * @buf: buffer
+ * @buffer: buffer
* @len: length of buffer provided
*
* Return value:
@@ -1299,9 +1299,9 @@
char *p = buffer;
*p = '\0';
- p += snprintf(p, buffer + len - p, "%02X", res_path[0]);
+ p += scnprintf(p, buffer + len - p, "%02X", res_path[0]);
for (i = 1; res_path[i] != 0xff && ((i * 3) < len); i++)
- p += snprintf(p, buffer + len - p, "-%02X", res_path[i]);
+ p += scnprintf(p, buffer + len - p, "-%02X", res_path[i]);
return buffer;
}
@@ -1310,7 +1310,7 @@
* ipr_format_res_path - Format the resource path for printing.
* @ioa_cfg: ioa config struct
* @res_path: resource path
- * @buf: buffer
+ * @buffer: buffer
* @len: length of buffer provided
*
* Return value:
@@ -1322,7 +1322,7 @@
char *p = buffer;
*p = '\0';
- p += snprintf(p, buffer + len - p, "%d/", ioa_cfg->host->host_no);
+ p += scnprintf(p, buffer + len - p, "%d/", ioa_cfg->host->host_no);
__ipr_format_res_path(res_path, p, len - (buffer - p));
return buffer;
}
@@ -1391,7 +1391,6 @@
* ipr_clear_res_target - Clear the bit in the bit map representing the target
* for the resource.
* @res: resource entry struct
- * @cfgtew: config table entry wrapper struct
*
* Return value:
* none
@@ -2667,7 +2666,7 @@
/**
* ipr_timeout - An internally generated op has timed out.
- * @ipr_cmd: ipr command struct
+ * @t: Timer context used to fetch ipr command struct
*
* This function blocks host requests and initiates an
* adapter reset.
@@ -2700,7 +2699,7 @@
/**
* ipr_oper_timeout - Adapter timed out transitioning to operational
- * @ipr_cmd: ipr command struct
+ * @t: Timer context used to fetch ipr command struct
*
* This function blocks host requests and initiates an
* adapter reset.
@@ -3484,6 +3483,7 @@
/**
* ipr_show_fw_version - Show the firmware version
* @dev: class device struct
+ * @attr: device attribute (unused)
* @buf: buffer
*
* Return value:
@@ -3518,6 +3518,7 @@
/**
* ipr_show_log_level - Show the adapter's error logging level
* @dev: class device struct
+ * @attr: device attribute (unused)
* @buf: buffer
*
* Return value:
@@ -3540,7 +3541,9 @@
/**
* ipr_store_log_level - Change the adapter's error logging level
* @dev: class device struct
+ * @attr: device attribute (unused)
* @buf: buffer
+ * @count: buffer size
*
* Return value:
* number of bytes printed to buffer
@@ -3571,6 +3574,7 @@
/**
* ipr_store_diagnostics - IOA Diagnostics interface
* @dev: device struct
+ * @attr: device attribute (unused)
* @buf: buffer
* @count: buffer size
*
@@ -3631,7 +3635,8 @@
/**
* ipr_show_adapter_state - Show the adapter's state
- * @class_dev: device struct
+ * @dev: device struct
+ * @attr: device attribute (unused)
* @buf: buffer
*
* Return value:
@@ -3657,6 +3662,7 @@
/**
* ipr_store_adapter_state - Change adapter state
* @dev: device struct
+ * @attr: device attribute (unused)
* @buf: buffer
* @count: buffer size
*
@@ -3708,6 +3714,7 @@
/**
* ipr_store_reset_adapter - Reset the adapter
* @dev: device struct
+ * @attr: device attribute (unused)
* @buf: buffer
* @count: buffer size
*
@@ -3749,6 +3756,7 @@
/**
* ipr_show_iopoll_weight - Show ipr polling mode
* @dev: class device struct
+ * @attr: device attribute (unused)
* @buf: buffer
*
* Return value:
@@ -3772,7 +3780,9 @@
/**
* ipr_store_iopoll_weight - Change the adapter's polling mode
* @dev: class device struct
+ * @attr: device attribute (unused)
* @buf: buffer
+ * @count: buffer size
*
* Return value:
* number of bytes printed to buffer
@@ -3871,7 +3881,7 @@
/**
* ipr_free_ucode_buffer - Frees a microcode download buffer
- * @p_dnld: scatter/gather list pointer
+ * @sglist: scatter/gather list pointer
*
* Free a DMA'able ucode download buffer previously allocated with
* ipr_alloc_ucode_buffer
@@ -4059,7 +4069,8 @@
/**
* ipr_store_update_fw - Update the firmware on the adapter
- * @class_dev: device struct
+ * @dev: device struct
+ * @attr: device attribute (unused)
* @buf: buffer
* @count: buffer size
*
@@ -4139,6 +4150,7 @@
/**
* ipr_show_fw_type - Show the adapter's firmware type.
* @dev: class device struct
+ * @attr: device attribute (unused)
* @buf: buffer
*
* Return value:
@@ -4480,7 +4492,6 @@
* ipr_change_queue_depth - Change the device's queue depth
* @sdev: scsi device struct
* @qdepth: depth to set
- * @reason: calling context
*
* Return value:
* actual depth set
@@ -4650,6 +4661,7 @@
/**
* ipr_show_raw_mode - Show the adapter's raw mode
* @dev: class device struct
+ * @attr: device attribute (unused)
* @buf: buffer
*
* Return value:
@@ -4677,7 +4689,9 @@
/**
* ipr_store_raw_mode - Change the adapter's raw mode
* @dev: class device struct
+ * @attr: device attribute (unused)
* @buf: buffer
+ * @count: buffer size
*
* Return value:
* number of bytes printed to buffer
@@ -5060,7 +5074,7 @@
/**
* ipr_cmnd_is_free - Check if a command is free or not
- * @ipr_cmd ipr command struct
+ * @ipr_cmd: ipr command struct
*
* Returns:
* true / false
@@ -5096,7 +5110,7 @@
/**
* ipr_wait_for_ops - Wait for matching commands to complete
- * @ipr_cmd: ipr command struct
+ * @ioa_cfg: ioa config struct
* @device: device to match (sdev)
* @match: match function to use
*
@@ -5261,6 +5275,7 @@
* ipr_sata_reset - Reset the SATA port
* @link: SATA link to reset
* @classes: class of the attached device
+ * @deadline: unused
*
* This function issues a SATA phy reset to the affected ATA link.
*
@@ -5440,7 +5455,7 @@
/**
* ipr_abort_timeout - An abort task has timed out
- * @ipr_cmd: ipr command struct
+ * @t: Timer context used to fetch ipr command struct
*
* This function handles when an abort task times out. If this
* happens we issue a bus reset since we have resources tied
@@ -5494,7 +5509,7 @@
struct ipr_ioa_cfg *ioa_cfg;
struct ipr_resource_entry *res;
struct ipr_cmd_pkt *cmd_pkt;
- u32 ioasc, int_reg;
+ u32 ioasc;
int i, op_found = 0;
struct ipr_hrr_queue *hrrq;
@@ -5517,7 +5532,7 @@
* by a still not detected EEH error. In such cases, reading a register will
* trigger the EEH recovery infrastructure.
*/
- int_reg = readl(ioa_cfg->regs.sense_interrupt_reg);
+ readl(ioa_cfg->regs.sense_interrupt_reg);
if (!ipr_is_gscsi(res))
return FAILED;
@@ -5569,7 +5584,8 @@
/**
* ipr_eh_abort - Abort a single op
- * @scsi_cmd: scsi command struct
+ * @shost: scsi host struct
+ * @elapsed_time: elapsed time
*
* Return value:
* 0 if scan in progress / 1 if scan is complete
@@ -5696,6 +5712,7 @@
* ipr_isr_eh - Interrupt service routine error handler
* @ioa_cfg: ioa config struct
* @msg: message to log
+ * @number: various meanings depending on the caller/message
*
* Return value:
* none
@@ -5762,7 +5779,6 @@
static int ipr_iopoll(struct irq_poll *iop, int budget)
{
- struct ipr_ioa_cfg *ioa_cfg;
struct ipr_hrr_queue *hrrq;
struct ipr_cmnd *ipr_cmd, *temp;
unsigned long hrrq_flags;
@@ -5770,7 +5786,6 @@
LIST_HEAD(doneq);
hrrq = container_of(iop, struct ipr_hrr_queue, iopoll);
- ioa_cfg = hrrq->ioa_cfg;
spin_lock_irqsave(hrrq->lock, hrrq_flags);
completed_ops = ipr_process_hrrq(hrrq, budget, &doneq);
@@ -6268,8 +6283,7 @@
/**
* ipr_gen_sense - Generate SCSI sense data from an IOASA
- * @ioasa: IOASA
- * @sense_buf: sense data buffer
+ * @ipr_cmd: ipr command struct
*
* Return value:
* none
@@ -6702,7 +6716,7 @@
/**
* ipr_info - Get information about the card/driver
- * @scsi_host: scsi host struct
+ * @host: scsi host struct
*
* Return value:
* pointer to buffer with description string
@@ -6727,7 +6741,11 @@
.name = "IPR",
.info = ipr_ioa_info,
.ioctl = ipr_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = ipr_ioctl,
+#endif
.queuecommand = ipr_queuecommand,
+ .dma_need_drain = ata_scsi_dma_need_drain,
.eh_abort_handler = ipr_eh_abort,
.eh_device_reset_handler = ipr_eh_dev_reset,
.eh_host_reset_handler = ipr_eh_host_reset,
@@ -7588,7 +7606,7 @@
/**
* ipr_build_mode_sense - Builds a mode sense command
* @ipr_cmd: ipr command struct
- * @res: resource entry struct
+ * @res_handle: resource entry struct
* @parm: Byte 2 of mode sense command
* @dma_addr: DMA address of mode sense buffer
* @xfer_len: Size of DMA buffer
@@ -7935,6 +7953,7 @@
/**
* ipr_ioafp_set_caching_parameters - Issue Set Cache parameters service
* action
+ * @ipr_cmd: ipr command struct
*
* Return value:
* none
@@ -7971,6 +7990,10 @@
/**
* ipr_ioafp_inquiry - Send an Inquiry to the adapter.
* @ipr_cmd: ipr command struct
+ * @flags: flags to send
+ * @page: page to inquire
+ * @dma_addr: DMA address
+ * @xfer_len: transfer data length
*
* This utility function sends an inquiry to the adapter.
*
@@ -8261,7 +8284,7 @@
/**
* ipr_reset_timer_done - Adapter reset timer function
- * @ipr_cmd: ipr command struct
+ * @t: Timer context used to fetch ipr command struct
*
* Description: This function is used in adapter reset processing
* for timing events. If the reset_cmd pointer in the IOA
@@ -8655,7 +8678,6 @@
static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
{
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
- u32 int_reg;
ENTER;
ioa_cfg->pdev->state_saved = true;
@@ -8671,7 +8693,7 @@
if (ioa_cfg->sis64) {
/* Set the adapter to the correct endian mode. */
writel(IPR_ENDIAN_SWAP_KEY, ioa_cfg->regs.endian_swap_reg);
- int_reg = readl(ioa_cfg->regs.endian_swap_reg);
+ readl(ioa_cfg->regs.endian_swap_reg);
}
if (ioa_cfg->ioa_unit_checked) {
@@ -9479,7 +9501,6 @@
* Description: This is the second phase of adapter initialization
* This function takes care of initilizing the adapter to the point
* where it can accept new commands.
-
* Return value:
* 0 on success / -EIO on failure
**/
@@ -9526,8 +9547,7 @@
}
}
- if (ioa_cfg->ipr_cmd_pool)
- dma_pool_destroy(ioa_cfg->ipr_cmd_pool);
+ dma_pool_destroy(ioa_cfg->ipr_cmd_pool);
kfree(ioa_cfg->ipr_cmnd_list);
kfree(ioa_cfg->ipr_cmnd_list_dma);
@@ -9594,7 +9614,7 @@
/**
* ipr_free_all_resources - Free all allocated resources for an adapter.
- * @ipr_cmd: ipr command struct
+ * @ioa_cfg: ioa config struct
*
* This function frees all allocated resources for the
* specified adapter.
@@ -10056,7 +10076,8 @@
/**
* ipr_test_intr - Handle the interrupt generated in ipr_test_msi().
- * @pdev: PCI device struct
+ * @devp: PCI device struct
+ * @irq: IRQ number
*
* Description: Simply set the msi_received flag to 1 indicating that
* Message Signaled Interrupts are supported.
@@ -10082,6 +10103,7 @@
/**
* ipr_test_msi - Test for Message Signaled Interrupt (MSI) support.
+ * @ioa_cfg: ioa config struct
* @pdev: PCI device struct
*
* Description: This routine sets up and initiates a test interrupt to determine
@@ -10094,7 +10116,6 @@
static int ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg, struct pci_dev *pdev)
{
int rc;
- volatile u32 int_reg;
unsigned long lock_flags = 0;
int irq = pci_irq_vector(pdev, 0);
@@ -10105,7 +10126,7 @@
ioa_cfg->msi_received = 0;
ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
writel(IPR_PCII_IO_DEBUG_ACKNOWLEDGE, ioa_cfg->regs.clr_interrupt_mask_reg32);
- int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
+ readl(ioa_cfg->regs.sense_interrupt_mask_reg);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
rc = request_irq(irq, ipr_test_intr, 0, IPR_NAME, ioa_cfg);
@@ -10116,7 +10137,7 @@
dev_info(&pdev->dev, "IRQ assigned: %d\n", irq);
writel(IPR_PCII_IO_DEBUG_ACKNOWLEDGE, ioa_cfg->regs.sense_interrupt_reg32);
- int_reg = readl(ioa_cfg->regs.sense_interrupt_reg);
+ readl(ioa_cfg->regs.sense_interrupt_reg);
wait_event_timeout(ioa_cfg->msi_wait_q, ioa_cfg->msi_received, HZ);
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
@@ -10527,6 +10548,8 @@
/**
* ipr_probe - Adapter hot plug add entry point
+ * @pdev: pci device struct
+ * @dev_id: pci device ID
*
* Return value:
* 0 on success / non-zero on failure
@@ -10783,6 +10806,7 @@
/**
* ipr_halt_done - Shutdown prepare completion
+ * @ipr_cmd: ipr command struct
*
* Return value:
* none
@@ -10794,6 +10818,9 @@
/**
* ipr_halt - Issue shutdown prepare to all adapters
+ * @nb: Notifier block
+ * @event: Notifier event
+ * @buf: Notifier data (unused)
*
* Return value:
* NOTIFY_OK on success / NOTIFY_DONE on failure
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index b97aa9a..783ee03 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -451,12 +451,12 @@
struct ipr_config_table {
struct ipr_config_table_hdr hdr;
- struct ipr_config_table_entry dev[0];
+ struct ipr_config_table_entry dev[];
}__attribute__((packed, aligned (4)));
struct ipr_config_table64 {
struct ipr_config_table_hdr64 hdr64;
- struct ipr_config_table_entry64 dev[0];
+ struct ipr_config_table_entry64 dev[];
}__attribute__((packed, aligned (8)));
struct ipr_config_table_entry_wrapper {
@@ -792,7 +792,7 @@
struct ipr_mode_page_hdr hdr;
u8 num_entries;
u8 entry_length;
- struct ipr_dev_bus_entry bus[0];
+ struct ipr_dev_bus_entry bus[];
}__attribute__((packed));
struct ipr_mode_page24 {
@@ -1684,7 +1684,7 @@
struct ipr_dump_location_entry {
struct ipr_dump_entry_header hdr;
u8 location[20];
-}__attribute__((packed));
+}__attribute__((packed, aligned (4)));
struct ipr_dump_trace_entry {
struct ipr_dump_entry_header hdr;
@@ -1708,7 +1708,7 @@
struct ipr_dump_location_entry location_entry;
struct ipr_dump_ioa_type_entry ioa_type_entry;
struct ipr_dump_trace_entry trace_entry;
-}__attribute__((packed));
+}__attribute__((packed, aligned (4)));
struct ipr_ioa_dump {
struct ipr_dump_entry_header hdr;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index e8bc8d3..2e6077c 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -498,7 +498,7 @@
int i;
char *key;
char *value;
- IPS_OPTION options[] = {
+ static const IPS_OPTION options[] = {
{"noi2o", &ips_force_i2o, 0},
{"nommap", &ips_force_memio, 0},
{"ioctlsize", &ips_ioctlsize, IPS_IOCTL_SIZE},
@@ -2239,7 +2239,7 @@
major = 0;
minor = 0;
- strncpy(ha->bios_version, " ?", 8);
+ memcpy(ha->bios_version, " ?", 8);
if (ha->pcidev->device == IPS_DEVICEID_COPPERHEAD) {
if (IPS_USE_MEMIO(ha)) {
@@ -3515,11 +3515,11 @@
inquiry.Flags[1] =
IPS_SCSI_INQ_WBus16 |
IPS_SCSI_INQ_Sync;
- strncpy(inquiry.VendorId, "IBM ",
+ memcpy(inquiry.VendorId, "IBM ",
8);
- strncpy(inquiry.ProductId,
+ memcpy(inquiry.ProductId,
"SERVERAID ", 16);
- strncpy(inquiry.ProductRevisionLevel,
+ memcpy(inquiry.ProductRevisionLevel,
"1.00", 4);
ips_scmd_buf_write(scb->scsi_cmd,
@@ -4036,9 +4036,9 @@
inquiry.Flags[0] = IPS_SCSI_INQ_Address16;
inquiry.Flags[1] =
IPS_SCSI_INQ_WBus16 | IPS_SCSI_INQ_Sync | IPS_SCSI_INQ_CmdQue;
- strncpy(inquiry.VendorId, "IBM ", 8);
- strncpy(inquiry.ProductId, "SERVERAID ", 16);
- strncpy(inquiry.ProductRevisionLevel, "1.00", 4);
+ memcpy(inquiry.VendorId, "IBM ", 8);
+ memcpy(inquiry.ProductId, "SERVERAID ", 16);
+ memcpy(inquiry.ProductRevisionLevel, "1.00", 4);
ips_scmd_buf_write(scb->scsi_cmd, &inquiry, sizeof (inquiry));
@@ -4697,7 +4697,6 @@
uint8_t Isr;
uint8_t Cbsp;
uint8_t PostByte[IPS_MAX_POST_BYTES];
- uint8_t ConfigByte[IPS_MAX_CONFIG_BYTES];
int i, j;
METHOD_TRACE("ips_init_copperhead", 1);
@@ -4742,7 +4741,7 @@
/* error occurred */
return (0);
- ConfigByte[i] = inb(ha->io_addr + IPS_REG_ISPR);
+ inb(ha->io_addr + IPS_REG_ISPR);
outb(Isr, ha->io_addr + IPS_REG_HISR);
}
@@ -4791,7 +4790,6 @@
uint8_t Isr = 0;
uint8_t Cbsp;
uint8_t PostByte[IPS_MAX_POST_BYTES];
- uint8_t ConfigByte[IPS_MAX_CONFIG_BYTES];
int i, j;
METHOD_TRACE("ips_init_copperhead_memio", 1);
@@ -4836,7 +4834,7 @@
/* error occurred */
return (0);
- ConfigByte[i] = readb(ha->mem_ptr + IPS_REG_ISPR);
+ readb(ha->mem_ptr + IPS_REG_ISPR);
writeb(Isr, ha->mem_ptr + IPS_REG_HISR);
}
@@ -5622,10 +5620,10 @@
/* change values (as needed) */
ha->nvram->operating_system = IPS_OS_LINUX;
ha->nvram->adapter_type = ha->ad_type;
- strncpy((char *) ha->nvram->driver_high, IPS_VERSION_HIGH, 4);
- strncpy((char *) ha->nvram->driver_low, IPS_VERSION_LOW, 4);
- strncpy((char *) ha->nvram->bios_high, ha->bios_version, 4);
- strncpy((char *) ha->nvram->bios_low, ha->bios_version + 4, 4);
+ memcpy((char *) ha->nvram->driver_high, IPS_VERSION_HIGH, 4);
+ memcpy((char *) ha->nvram->driver_low, IPS_VERSION_LOW, 4);
+ memcpy((char *) ha->nvram->bios_high, ha->bios_version, 4);
+ memcpy((char *) ha->nvram->bios_low, ha->bios_version + 4, 4);
ha->nvram->versioning = 0; /* Indicate the Driver Does Not Support Versioning */
@@ -6835,8 +6833,6 @@
uint32_t mem_addr;
uint32_t io_len;
uint32_t mem_len;
- uint8_t bus;
- uint8_t func;
int j;
int index;
dma_addr_t dma_address;
@@ -6856,10 +6852,6 @@
if (index >= IPS_MAX_ADAPTERS)
return -1;
- /* stuff that we get in dev */
- bus = pci_dev->bus->number;
- func = pci_dev->devfn;
-
/* Init MEM/IO addresses to 0 */
mem_addr = 0;
io_addr = 0;
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index 7b5deae..7ebfa3c 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -2671,7 +2671,6 @@
struct isci_request *ireq)
{
enum sci_status status;
- u16 index;
switch (ihost->sm.current_state_id) {
case SCIC_STOPPING:
@@ -2682,7 +2681,6 @@
if (status != SCI_SUCCESS)
return status;
- index = ISCI_TAG_TCI(ireq->io_tag);
clear_bit(IREQ_ACTIVE, &ireq->flags);
return SCI_SUCCESS;
default:
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index c33bcf8..9d7cc62 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -142,7 +142,7 @@
static DEVICE_ATTR(isci_id, S_IRUGO, isci_show_id, NULL);
-struct device_attribute *isci_host_attrs[] = {
+static struct device_attribute *isci_host_attrs[] = {
&dev_attr_isci_id,
NULL
};
@@ -153,6 +153,7 @@
.name = DRV_NAME,
.proc_name = DRV_NAME,
.queuecommand = sas_queuecommand,
+ .dma_need_drain = ata_scsi_dma_need_drain,
.target_alloc = sas_target_alloc,
.slave_configure = sas_slave_configure,
.scan_finished = isci_host_scan_finished,
@@ -169,6 +170,9 @@
.slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = sas_ioctl,
+#endif
.shost_attrs = isci_host_attrs,
.track_queue_depth = 1,
};
@@ -619,7 +623,7 @@
return -ENOMEM;
pci_set_drvdata(pdev, pci_info);
- if (efi_enabled(EFI_RUNTIME_SERVICES))
+ if (efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE))
orom = isci_get_efi_var(pdev);
if (!orom)
diff --git a/drivers/scsi/isci/isci.h b/drivers/scsi/isci/isci.h
index 680e309..4e6b1de 100644
--- a/drivers/scsi/isci/isci.h
+++ b/drivers/scsi/isci/isci.h
@@ -500,19 +500,19 @@
static inline
void sci_init_timer(struct sci_timer *tmr, void (*fn)(struct timer_list *t))
{
- tmr->cancel = 0;
+ tmr->cancel = false;
timer_setup(&tmr->timer, fn, 0);
}
static inline void sci_mod_timer(struct sci_timer *tmr, unsigned long msec)
{
- tmr->cancel = 0;
+ tmr->cancel = false;
mod_timer(&tmr->timer, jiffies + msecs_to_jiffies(msec));
}
static inline void sci_del_timer(struct sci_timer *tmr)
{
- tmr->cancel = 1;
+ tmr->cancel = true;
del_timer(&tmr->timer);
}
diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c
index 7f9b3f2..7041e2e 100644
--- a/drivers/scsi/isci/phy.c
+++ b/drivers/scsi/isci/phy.c
@@ -669,7 +669,7 @@
phy_state_name(state), phy_event_name(code), code)
-void scu_link_layer_set_txcomsas_timeout(struct isci_phy *iphy, u32 timeout)
+static void scu_link_layer_set_txcomsas_timeout(struct isci_phy *iphy, u32 timeout)
{
u32 val;
@@ -778,7 +778,7 @@
break;
case SCU_EVENT_LINK_FAILURE:
scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);
- /* fall through */
+ fallthrough;
case SCU_EVENT_HARD_RESET_RECEIVED:
/* Start the oob/sn state machine over again */
sci_change_state(&iphy->sm, SCI_PHY_STARTING);
diff --git a/drivers/scsi/isci/port.c b/drivers/scsi/isci/port.c
index 1df45f0..e50c3b0 100644
--- a/drivers/scsi/isci/port.c
+++ b/drivers/scsi/isci/port.c
@@ -164,7 +164,8 @@
"%s: isci_phy = %p, sas_phy = %p\n",
__func__, iphy, &iphy->sas_phy);
- ihost->sas_ha.notify_port_event(&iphy->sas_phy, PORTE_BROADCAST_RCVD);
+ sas_notify_port_event_gfp(&iphy->sas_phy,
+ PORTE_BROADCAST_RCVD, GFP_ATOMIC);
sci_port_bcn_enable(iport);
}
@@ -223,8 +224,8 @@
/* Notify libsas that we have an address frame, if indeed
* we've found an SSP, SMP, or STP target */
if (success)
- isci_host->sas_ha.notify_port_event(&iphy->sas_phy,
- PORTE_BYTES_DMAED);
+ sas_notify_port_event_gfp(&iphy->sas_phy,
+ PORTE_BYTES_DMAED, GFP_ATOMIC);
}
@@ -270,8 +271,8 @@
* isci_port_deformed and isci_dev_gone functions.
*/
sas_phy_disconnected(&isci_phy->sas_phy);
- isci_host->sas_ha.notify_phy_event(&isci_phy->sas_phy,
- PHYE_LOSS_OF_SIGNAL);
+ sas_notify_phy_event_gfp(&isci_phy->sas_phy,
+ PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
dev_dbg(&isci_host->pdev->dev,
"%s: isci_port = %p - Done\n", __func__, isci_port);
diff --git a/drivers/scsi/isci/port_config.c b/drivers/scsi/isci/port_config.c
index 9e8de14..b1c1975 100644
--- a/drivers/scsi/isci/port_config.c
+++ b/drivers/scsi/isci/port_config.c
@@ -147,7 +147,7 @@
/**
*
* @controller: This is the controller object that contains the port agent
- * @port_agent: This is the port configruation agent for the controller.
+ * @port_agent: This is the port configuration agent for the controller.
*
* This routine will validate the port configuration is correct for the SCU
* hardware. The SCU hardware allows for port configurations as follows. LP0
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c
index 49aa4e6..c3f540b 100644
--- a/drivers/scsi/isci/remote_device.c
+++ b/drivers/scsi/isci/remote_device.c
@@ -310,7 +310,7 @@
/* Kill all outstanding requests for the device. */
sci_remote_device_terminate_requests(idev);
- /* Fall through - into the default case... */
+ fallthrough; /* into the default case */
default:
clear_bit(IDEV_IO_READY, &idev->flags);
break;
@@ -593,7 +593,7 @@
break;
}
- /* fall through - and treat as unhandled... */
+ fallthrough; /* and treat as unhandled */
default:
dev_dbg(scirdev_to_dev(idev),
"%s: device: %p event code: %x: %s\n",
@@ -1504,7 +1504,7 @@
* This function builds the isci_remote_device when a libsas dev_found message
* is received.
* @isci_host: This parameter specifies the isci host object.
- * @port: This parameter specifies the isci_port conected to this device.
+ * @port: This parameter specifies the isci_port connected to this device.
*
* pointer to new isci_remote_device.
*/
diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c
index 474a434..68333f5 100644
--- a/drivers/scsi/isci/remote_node_context.c
+++ b/drivers/scsi/isci/remote_node_context.c
@@ -225,7 +225,7 @@
case RNC_DEST_READY:
case RNC_DEST_SUSPENDED_RESUME:
rnc->destination_state = RNC_DEST_READY;
- /* Fall through... */
+ fallthrough;
case RNC_DEST_FINAL:
sci_remote_node_context_resume(rnc, rnc->user_callback,
rnc->user_cookie);
@@ -601,9 +601,9 @@
__func__, sci_rnc);
return SCI_FAILURE_INVALID_STATE;
}
- /* Fall through - and handle like SCI_RNC_POSTING */
+ fallthrough; /* and handle like SCI_RNC_POSTING */
case SCI_RNC_RESUMING:
- /* Fall through - and handle like SCI_RNC_POSTING */
+ fallthrough; /* and handle like SCI_RNC_POSTING */
case SCI_RNC_POSTING:
/* Set the destination state to AWAIT - this signals the
* entry into the SCI_RNC_READY state that a suspension
diff --git a/drivers/scsi/isci/remote_node_table.h b/drivers/scsi/isci/remote_node_table.h
index 721ab98..0ddfdda 100644
--- a/drivers/scsi/isci/remote_node_table.h
+++ b/drivers/scsi/isci/remote_node_table.h
@@ -61,7 +61,7 @@
/**
*
*
- * Remote node sets are sets of remote node index in the remtoe node table The
+ * Remote node sets are sets of remote node index in the remote node table. The
* SCU hardware requires that STP remote node entries take three consecutive
* remote node index so the table is arranged in sets of three. The bits are
* used as 0111 0111 to make a byte and the bits define the set of three remote
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index 343d24c..6e08179 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -894,7 +894,7 @@
* and don't wait for the task response.
*/
sci_change_state(&ireq->sm, SCI_REQ_ABORTING);
- /* Fall through - and handle like ABORTING... */
+ fallthrough; /* and handle like ABORTING */
case SCI_REQ_ABORTING:
if (!isci_remote_device_is_safe_to_abort(ireq->target_device))
set_bit(IREQ_PENDING_ABORT, &ireq->flags);
@@ -3444,7 +3444,7 @@
int isci_request_execute(struct isci_host *ihost, struct isci_remote_device *idev,
struct sas_task *task, u16 tag)
{
- enum sci_status status = SCI_FAILURE_UNSUPPORTED_PROTOCOL;
+ enum sci_status status;
struct isci_request *ireq;
unsigned long flags;
int ret = 0;
diff --git a/drivers/scsi/isci/sas.h b/drivers/scsi/isci/sas.h
index dc26b4a..15d8f36 100644
--- a/drivers/scsi/isci/sas.h
+++ b/drivers/scsi/isci/sas.h
@@ -201,7 +201,7 @@
u8 func; /* byte 1 */
u8 alloc_resp_len; /* byte 2 */
u8 req_len; /* byte 3 */
- u8 req_data[0];
+ u8 req_data[];
} __packed;
/*
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index b5dd1ca..df47557 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -736,6 +736,7 @@
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
struct sockaddr_in6 addr;
+ struct socket *sock;
int rc;
switch(param) {
@@ -747,13 +748,17 @@
spin_unlock_bh(&conn->session->frwd_lock);
return -ENOTCONN;
}
+ sock = tcp_sw_conn->sock;
+ sock_hold(sock->sk);
+ spin_unlock_bh(&conn->session->frwd_lock);
+
if (param == ISCSI_PARAM_LOCAL_PORT)
- rc = kernel_getsockname(tcp_sw_conn->sock,
+ rc = kernel_getsockname(sock,
(struct sockaddr *)&addr);
else
- rc = kernel_getpeername(tcp_sw_conn->sock,
+ rc = kernel_getpeername(sock,
(struct sockaddr *)&addr);
- spin_unlock_bh(&conn->session->frwd_lock);
+ sock_put(sock->sk);
if (rc < 0)
return rc;
@@ -775,6 +780,7 @@
struct iscsi_tcp_conn *tcp_conn;
struct iscsi_sw_tcp_conn *tcp_sw_conn;
struct sockaddr_in6 addr;
+ struct socket *sock;
int rc;
switch (param) {
@@ -789,16 +795,18 @@
return -ENOTCONN;
}
tcp_conn = conn->dd_data;
-
tcp_sw_conn = tcp_conn->dd_data;
- if (!tcp_sw_conn->sock) {
+ sock = tcp_sw_conn->sock;
+ if (!sock) {
spin_unlock_bh(&session->frwd_lock);
return -ENOTCONN;
}
-
- rc = kernel_getsockname(tcp_sw_conn->sock,
- (struct sockaddr *)&addr);
+ sock_hold(sock->sk);
spin_unlock_bh(&session->frwd_lock);
+
+ rc = kernel_getsockname(sock,
+ (struct sockaddr *)&addr);
+ sock_put(sock->sk);
if (rc < 0)
return rc;
@@ -962,8 +970,8 @@
struct iscsi_conn *conn = session->leadconn;
if (conn->datadgst_en)
- sdev->request_queue->backing_dev_info->capabilities
- |= BDI_CAP_STABLE_WRITES;
+ blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES,
+ sdev->request_queue);
blk_queue_dma_alignment(sdev->request_queue, 0);
return 0;
}
diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c
index f55b07a..60a88a9 100644
--- a/drivers/scsi/jazz_esp.c
+++ b/drivers/scsi/jazz_esp.c
@@ -203,21 +203,9 @@
.name = "jazz_esp",
},
};
-
-static int __init jazz_esp_init(void)
-{
- return platform_driver_register(&esp_jazz_driver);
-}
-
-static void __exit jazz_esp_exit(void)
-{
- platform_driver_unregister(&esp_jazz_driver);
-}
+module_platform_driver(esp_jazz_driver);
MODULE_DESCRIPTION("JAZZ ESP SCSI driver");
MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-
-module_init(jazz_esp_init);
-module_exit(jazz_esp_exit);
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index abac2f3..de71d24 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -31,7 +31,6 @@
#include <linux/slab.h>
#include <asm/page.h>
-#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#include <asm/parisc-device.h>
@@ -98,7 +97,7 @@
hostdata->dev = &dev->dev;
dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
- hostdata->base = ioremap_nocache(base, 0x100);
+ hostdata->base = ioremap(base, 0x100);
hostdata->differential = 0;
if (dev->id.sversion == LASI_700_SVERSION) {
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index 589ddf0..942fc60 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -301,8 +301,8 @@
struct fc_lport *lport = fc_disc_lport(disc);
unsigned long delay = 0;
- FC_DISC_DBG(disc, "Error %ld, retries %d/%d\n",
- PTR_ERR(fp), disc->retry_count,
+ FC_DISC_DBG(disc, "Error %d, retries %d/%d\n",
+ PTR_ERR_OR_ZERO(fp), disc->retry_count,
FC_DISC_RETRY_LIMIT);
if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) {
@@ -337,7 +337,7 @@
/**
* fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request
- * @lport: The discovery context
+ * @disc: The discovery context
*/
static void fc_disc_gpn_ft_req(struct fc_disc *disc)
{
@@ -370,7 +370,7 @@
/**
* fc_disc_gpn_ft_parse() - Parse the body of the dNS GPN_FT response.
- * @lport: The local port the GPN_FT was received on
+ * @disc: The discovery context
* @buf: The GPN_FT response buffer
* @len: The size of response buffer
*
@@ -488,7 +488,7 @@
* fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT)
* @sp: The sequence that the GPN_FT response was received on
* @fp: The GPN_FT response frame
- * @lp_arg: The discovery context
+ * @disc_arg: The discovery context
*
* Locking Note: This function is called without disc mutex held, and
* should do all its processing with the mutex held
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index e5b18e5..a50f1ee 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -49,6 +49,8 @@
* @total_exches: Total allocated exchanges
* @lock: Exch pool lock
* @ex_list: List of exchanges
+ * @left: Cache of free slot in exch array
+ * @right: Cache of free slot in exch array
*
* This structure manages per cpu exchanges in array of exchange pointers.
* This array is allocated followed by struct fc_exch_pool memory for
@@ -60,7 +62,6 @@
u16 next_index;
u16 total_exches;
- /* two cache of free slot in exch array */
u16 left;
u16 right;
} ____cacheline_aligned_in_smp;
@@ -74,6 +75,7 @@
* @ep_pool: Reserved exchange pointers
* @pool_max_index: Max exch array index in exch pool
* @pool: Per cpu exch pool
+ * @lport: Local exchange port
* @stats: Statistics structure
*
* This structure is the center for creating exchanges and sequences.
@@ -702,6 +704,9 @@
/**
* fc_invoke_resp() - invoke ep->resp()
+ * @ep: The exchange to be operated on
+ * @fp: The frame pointer to pass through to ->resp()
+ * @sp: The sequence pointer to pass through to ->resp()
*
* Notes:
* It is assumed that after initialization finished (this means the
@@ -2115,7 +2120,7 @@
switch (op) {
case ELS_LS_RJT:
FC_EXCH_DBG(aborted_ep, "LS_RJT for RRQ\n");
- /* fall through */
+ fallthrough;
case ELS_LS_ACC:
goto cleanup;
default:
@@ -2629,7 +2634,7 @@
case FC_EOF_T:
if (f_ctl & FC_FC_END_SEQ)
skb_trim(fp_skb(fp), fr_len(fp) - FC_FC_FILL(f_ctl));
- /* fall through */
+ fallthrough;
case FC_EOF_N:
if (fh->fh_type == FC_TYPE_BLS)
fc_exch_recv_bls(ema->mp, fp);
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index bf2cc96..7cfeb68 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -289,6 +289,7 @@
/**
* fc_fcp_retry_cmd() - Retry a fcp_pkt
* @fsp: The FCP packet to be retried
+ * @status_code: The FCP status code to set
*
* Sets the status code to be FC_ERROR and then calls
* fc_fcp_complete_locked() which in turn calls fc_io_compl().
@@ -580,7 +581,7 @@
/**
* fc_fcp_send_data() - Send SCSI data to a target
* @fsp: The FCP packet the data is on
- * @sp: The sequence the data is to be sent on
+ * @seq: The sequence the data is to be sent on
* @offset: The starting offset for this data request
* @seq_blen: The burst length for this data request
*
@@ -751,7 +752,7 @@
brp = fc_frame_payload_get(fp, sizeof(*brp));
if (brp && brp->br_reason == FC_BA_RJT_LOG_ERR)
break;
- /* fall thru */
+ fallthrough;
default:
/*
* we will let the command timeout
@@ -1283,7 +1284,7 @@
/**
* fc_lun_reset_send() - Send LUN reset command
- * @data: The FCP packet that identifies the LUN to be reset
+ * @t: Timer context used to fetch the FSP packet
*/
static void fc_lun_reset_send(struct timer_list *t)
{
@@ -1409,7 +1410,7 @@
/**
* fc_fcp_timeout() - Handler for fcp_pkt timeouts
- * @data: The FCP packet that has timed out
+ * @t: Timer context used to fetch the FSP packet
*
* If REC is supported then just issue it and return. The REC exchange will
* complete or time out and recovery can continue at that point. Otherwise,
@@ -1535,7 +1536,7 @@
"device %x invalid REC reject %d/%d\n",
fsp->rport->port_id, rjt->er_reason,
rjt->er_explan);
- /* fall through */
+ fallthrough;
case ELS_RJT_UNSUP:
FC_FCP_DBG(fsp, "device does not support REC\n");
rpriv = fsp->rport->dd_data;
@@ -1667,7 +1668,7 @@
FC_FCP_DBG(fsp, "REC %p fid %6.6x error unexpected error %d\n",
fsp, fsp->rport->port_id, error);
fsp->status_code = FC_CMD_PLOGO;
- /* fall through */
+ fallthrough;
case -FC_EX_TIMEOUT:
/*
@@ -1691,6 +1692,7 @@
/**
* fc_fcp_recovery() - Handler for fcp_pkt recovery
* @fsp: The FCP pkt that needs to be aborted
+ * @code: The FCP status code to set
*/
static void fc_fcp_recovery(struct fc_fcp_pkt *fsp, u8 code)
{
@@ -1709,6 +1711,7 @@
* fc_fcp_srr() - Send a SRR request (Sequence Retransmission Request)
* @fsp: The FCP packet the SRR is to be sent on
* @r_ctl: The R_CTL field for the SRR request
+ * @offset: The SRR relative offset
* This is called after receiving status but insufficient data, or
* when expecting status but the request has timed out.
*/
@@ -1827,7 +1830,7 @@
break;
case -FC_EX_CLOSED: /* e.g., link failure */
FC_FCP_DBG(fsp, "SRR error, exchange closed\n");
- /* fall through */
+ fallthrough;
default:
fc_fcp_retry_cmd(fsp, FC_ERROR);
break;
@@ -1851,7 +1854,7 @@
/**
* fc_queuecommand() - The queuecommand function of the SCSI template
* @shost: The Scsi_Host that the command was issued to
- * @cmd: The scsi_cmnd to be executed
+ * @sc_cmd: The scsi_cmnd to be executed
*
* This is the i/o strategy routine, called by the SCSI layer.
*/
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 9399e14..abb14b2 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -405,7 +405,7 @@
/**
* fc_lport_recv_echo_req() - Handle received ECHO request
* @lport: The local port receiving the ECHO
- * @fp: ECHO request frame
+ * @in_fp: ECHO request frame
*/
static void fc_lport_recv_echo_req(struct fc_lport *lport,
struct fc_frame *in_fp)
@@ -440,7 +440,7 @@
/**
* fc_lport_recv_rnid_req() - Handle received Request Node ID data request
* @lport: The local port receiving the RNID
- * @fp: The RNID request frame
+ * @in_fp: The RNID request frame
*/
static void fc_lport_recv_rnid_req(struct fc_lport *lport,
struct fc_frame *in_fp)
@@ -1325,6 +1325,7 @@
/**
* fc_lport_enter_ns() - register some object with the name server
* @lport: Fibre Channel local port to register
+ * @state: Local port state
*/
static void fc_lport_enter_ns(struct fc_lport *lport, enum fc_lport_state state)
{
@@ -1423,6 +1424,7 @@
/**
* fc_lport_enter_ms() - management server commands
* @lport: Fibre Channel local port to register
+ * @state: Local port state
*/
static void fc_lport_enter_ms(struct fc_lport *lport, enum fc_lport_state state)
{
@@ -1576,7 +1578,7 @@
case LPORT_ST_DPRT:
FC_LPORT_DBG(lport, "Skipping lport state %s to SCR\n",
fc_lport_state(lport));
- /* fall thru */
+ fallthrough;
case LPORT_ST_SCR:
fc_lport_enter_scr(lport);
break;
@@ -1932,6 +1934,7 @@
* @job: The BSG Passthrough job
* @lport: The local port sending the request
* @did: The destination port id
+ * @tov: The timeout period (in ms)
*/
static int fc_lport_els_request(struct bsg_job *job,
struct fc_lport *lport,
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 326bd60..f40edb0 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -121,7 +121,7 @@
/**
* fc_rport_create() - Create a new remote port
* @lport: The local port this remote port will be associated with
- * @ids: The identifiers for the new remote port
+ * @port_id: The identifiers for the new remote port
*
* The remote port will start in the INIT state.
*/
@@ -635,6 +635,8 @@
fc_rport_enter_ready(rdata);
break;
case RPORT_ST_PRLI:
+ fc_rport_enter_plogi(rdata);
+ break;
case RPORT_ST_ADISC:
fc_rport_enter_logo(rdata);
break;
@@ -1446,7 +1448,7 @@
* fc_rport_logo_resp() - Handler for logout (LOGO) responses
* @sp: The sequence the LOGO was on
* @fp: The LOGO response frame
- * @lport_arg: The local port
+ * @rdata_arg: The remote port
*/
static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
void *rdata_arg)
@@ -1724,7 +1726,7 @@
kref_put(&rdata->kref, fc_rport_destroy);
goto busy;
}
- /* fall through */
+ fallthrough;
default:
FC_RPORT_DBG(rdata,
"Reject ELS 0x%02x while in state %s\n",
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index eeba618..d4e66c5 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -248,7 +248,7 @@
hdr_lun = scsilun_to_int(&tmf->lun);
if (hdr_lun != task->sc->device->lun)
return 0;
- /* fall through */
+ fallthrough;
case ISCSI_TM_FUNC_TARGET_WARM_RESET:
/*
* Fail all SCSI cmd PDUs
@@ -1669,7 +1669,7 @@
sc->result = DID_NO_CONNECT << 16;
break;
}
- /* fall through */
+ fallthrough;
case ISCSI_STATE_IN_RECOVERY:
reason = FAILURE_SESSION_IN_RECOVERY;
sc->result = DID_IMM_RETRY << 16;
@@ -2233,7 +2233,7 @@
"progress\n");
goto success;
}
- /* fall through */
+ fallthrough;
default:
session->tmf_state = TMF_INITIAL;
goto failed;
@@ -2620,7 +2620,9 @@
if (xmit_can_sleep) {
snprintf(ihost->workq_name, sizeof(ihost->workq_name),
"iscsi_q_%d", shost->host_no);
- ihost->workq = create_singlethread_workqueue(ihost->workq_name);
+ ihost->workq = alloc_workqueue("%s",
+ WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND,
+ 1, ihost->workq_name);
if (!ihost->workq)
goto free_host;
}
@@ -2764,7 +2766,7 @@
"must be a power of 2.\n", total_cmds);
total_cmds = rounddown_pow_of_two(total_cmds);
if (total_cmds < ISCSI_TOTAL_CMDS_MIN)
- return NULL;
+ goto dec_session_count;
printk(KERN_INFO "iscsi: Rounding can_queue to %d.\n",
total_cmds);
}
@@ -2948,6 +2950,8 @@
{
struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session;
+ char *tmp_persistent_address = conn->persistent_address;
+ char *tmp_local_ipaddr = conn->local_ipaddr;
del_timer_sync(&conn->transport_timer);
@@ -2969,8 +2973,6 @@
spin_lock_bh(&session->frwd_lock);
free_pages((unsigned long) conn->data,
get_order(ISCSI_DEF_MAX_RECV_SEG_LEN));
- kfree(conn->persistent_address);
- kfree(conn->local_ipaddr);
/* regular RX path uses back_lock */
spin_lock_bh(&session->back_lock);
kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task,
@@ -2982,6 +2984,8 @@
mutex_unlock(&session->eh_mutex);
iscsi_destroy_conn(cls_conn);
+ kfree(tmp_persistent_address);
+ kfree(tmp_local_ipaddr);
}
EXPORT_SYMBOL_GPL(iscsi_conn_teardown);
@@ -3079,9 +3083,10 @@
}
}
-static void iscsi_start_session_recovery(struct iscsi_session *session,
- struct iscsi_conn *conn, int flag)
+void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
{
+ struct iscsi_conn *conn = cls_conn->dd_data;
+ struct iscsi_session *session = conn->session;
int old_stop_stage;
mutex_lock(&session->eh_mutex);
@@ -3139,22 +3144,6 @@
spin_unlock_bh(&session->frwd_lock);
mutex_unlock(&session->eh_mutex);
}
-
-void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
-{
- struct iscsi_conn *conn = cls_conn->dd_data;
- struct iscsi_session *session = conn->session;
-
- switch (flag) {
- case STOP_CONN_RECOVER:
- case STOP_CONN_TERM:
- iscsi_start_session_recovery(session, conn, flag);
- break;
- default:
- iscsi_conn_printk(KERN_ERR, conn,
- "invalid stop flag %d\n", flag);
- }
-}
EXPORT_SYMBOL_GPL(iscsi_conn_stop);
int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index 6ef93c7..83f14b2 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -128,7 +128,7 @@
* coalescing neighboring slab objects into a single frag which
* triggers one of hardened usercopy checks.
*/
- if (!recv && page_count(sg_page(sg)) >= 1 && !PageSlab(sg_page(sg)))
+ if (!recv && sendpage_ok(sg_page(sg)))
return;
if (recv) {
@@ -772,7 +772,7 @@
iscsi_tcp_data_recv_prep(tcp_conn);
return 0;
}
- /* fall through */
+ fallthrough;
case ISCSI_OP_LOGOUT_RSP:
case ISCSI_OP_NOOP_IN:
case ISCSI_OP_SCSI_TMFUNC_RSP:
diff --git a/drivers/scsi/libsas/Kconfig b/drivers/scsi/libsas/Kconfig
index 5c6a5ef..052ee3a 100644
--- a/drivers/scsi/libsas/Kconfig
+++ b/drivers/scsi/libsas/Kconfig
@@ -19,6 +19,7 @@
bool "ATA support for libsas (requires libata)"
depends on SCSI_SAS_LIBSAS
depends on ATA = y || ATA = SCSI_SAS_LIBSAS
+ select SATA_HOST
help
Builds in ATA support into libsas. Will necessitate
the loading of libata along with libsas.
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 5d28bb7..8b9a390 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -137,7 +137,7 @@
} else {
ac = sas_to_ata_err(stat);
if (ac) {
- pr_warn("%s: SAS error %x\n", __func__, stat->stat);
+ pr_warn("%s: SAS error 0x%x\n", __func__, stat->stat);
/* We saw a SAS error. Send a vague error. */
if (!link->sactive) {
qc->err_mask = ac;
@@ -160,6 +160,7 @@
}
static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
+ __must_hold(ap->lock)
{
struct sas_task *task;
struct scatterlist *sg;
@@ -325,7 +326,7 @@
case SAS_END_DEVICE:
if (ex_phy->attached_sata_dev)
return sas_ata_clear_pending(dev, ex_phy);
- /* fall through */
+ fallthrough;
default:
return -ENODEV;
}
@@ -508,10 +509,23 @@
spin_unlock_irqrestore(&ha->lock, flags);
}
+static int sas_ata_prereset(struct ata_link *link, unsigned long deadline)
+{
+ struct ata_port *ap = link->ap;
+ struct domain_device *dev = ap->private_data;
+ struct sas_phy *local_phy = sas_get_local_phy(dev);
+ int res = 0;
+
+ if (!local_phy->enabled || test_bit(SAS_DEV_GONE, &dev->state))
+ res = -ENOENT;
+ sas_put_local_phy(local_phy);
+
+ return res;
+}
+
static struct ata_port_operations sas_sata_ops = {
- .prereset = ata_std_prereset,
+ .prereset = sas_ata_prereset,
.hardreset = sas_ata_hard_reset,
- .postreset = ata_std_postreset,
.error_handler = ata_std_error_handler,
.post_internal_cmd = sas_ata_post_internal,
.qc_defer = ata_std_qc_defer,
@@ -711,19 +725,13 @@
*/
int sas_discover_sata(struct domain_device *dev)
{
- int res;
-
if (dev->dev_type == SAS_SATA_PM)
return -ENODEV;
dev->sata_dev.class = sas_get_ata_command_set(dev);
sas_fill_in_rphy(dev, dev->rphy);
- res = sas_notify_lldd_dev_found(dev);
- if (res)
- return res;
-
- return 0;
+ return sas_notify_lldd_dev_found(dev);
}
static void async_sas_ata_eh(void *data, async_cookie_t cookie)
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index 10975f3..161c9b3 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -108,7 +108,7 @@
rphy = NULL;
break;
}
- /* fall through */
+ fallthrough;
case SAS_END_DEVICE:
rphy = sas_end_device_alloc(port->port);
break;
@@ -179,7 +179,7 @@
res = i->dft->lldd_dev_found(dev);
if (res) {
- pr_warn("driver on host %s cannot handle device %llx, error:%d\n",
+ pr_warn("driver on host %s cannot handle device %016llx, error:%d\n",
dev_name(sas_ha->dev),
SAS_ADDR(dev->sas_addr), res);
return res;
@@ -278,13 +278,7 @@
*/
int sas_discover_end_dev(struct domain_device *dev)
{
- int res;
-
- res = sas_notify_lldd_dev_found(dev);
- if (res)
- return res;
-
- return 0;
+ return sas_notify_lldd_dev_found(dev);
}
/* ---------- Device registration and unregistration ---------- */
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index a1852f6..ba266a1 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -109,7 +109,7 @@
sas_phy = container_of(port->phy_list.next, struct asd_sas_phy,
port_phy_el);
- ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
}
mutex_unlock(&ha->disco_mutex);
}
@@ -131,18 +131,15 @@
sas_free_event(ev);
}
-static int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event)
+static int __sas_notify_port_event(struct asd_sas_phy *phy,
+ enum port_event event,
+ struct asd_sas_event *ev)
{
- struct asd_sas_event *ev;
struct sas_ha_struct *ha = phy->ha;
int ret;
BUG_ON(event >= PORT_NUM_EVENTS);
- ev = sas_alloc_event(phy);
- if (!ev)
- return -ENOMEM;
-
INIT_SAS_EVENT(ev, sas_port_event_worker, phy, event);
ret = sas_queue_event(event, &ev->work, ha);
@@ -152,18 +149,40 @@
return ret;
}
-int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
+int sas_notify_port_event_gfp(struct asd_sas_phy *phy, enum port_event event,
+ gfp_t gfp_flags)
{
struct asd_sas_event *ev;
- struct sas_ha_struct *ha = phy->ha;
- int ret;
- BUG_ON(event >= PHY_NUM_EVENTS);
+ ev = sas_alloc_event_gfp(phy, gfp_flags);
+ if (!ev)
+ return -ENOMEM;
+
+ return __sas_notify_port_event(phy, event, ev);
+}
+EXPORT_SYMBOL_GPL(sas_notify_port_event_gfp);
+
+int sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event)
+{
+ struct asd_sas_event *ev;
ev = sas_alloc_event(phy);
if (!ev)
return -ENOMEM;
+ return __sas_notify_port_event(phy, event, ev);
+}
+EXPORT_SYMBOL_GPL(sas_notify_port_event);
+
+static inline int __sas_notify_phy_event(struct asd_sas_phy *phy,
+ enum phy_event event,
+ struct asd_sas_event *ev)
+{
+ struct sas_ha_struct *ha = phy->ha;
+ int ret;
+
+ BUG_ON(event >= PHY_NUM_EVENTS);
+
INIT_SAS_EVENT(ev, sas_phy_event_worker, phy, event);
ret = sas_queue_event(event, &ev->work, ha);
@@ -173,10 +192,27 @@
return ret;
}
-int sas_init_events(struct sas_ha_struct *sas_ha)
+int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event,
+ gfp_t gfp_flags)
{
- sas_ha->notify_port_event = sas_notify_port_event;
- sas_ha->notify_phy_event = sas_notify_phy_event;
+ struct asd_sas_event *ev;
- return 0;
+ ev = sas_alloc_event_gfp(phy, gfp_flags);
+ if (!ev)
+ return -ENOMEM;
+
+ return __sas_notify_phy_event(phy, event, ev);
}
+EXPORT_SYMBOL_GPL(sas_notify_phy_event_gfp);
+
+int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event)
+{
+ struct asd_sas_event *ev;
+
+ ev = sas_alloc_event(phy);
+ if (!ev)
+ return -ENOMEM;
+
+ return __sas_notify_phy_event(phy, event, ev);
+}
+EXPORT_SYMBOL_GPL(sas_notify_phy_event);
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 9fdb9c9..8d6bcc1 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -427,7 +427,7 @@
static int sas_expander_discover(struct domain_device *dev)
{
struct expander_device *ex = &dev->ex_dev;
- int res = -ENOMEM;
+ int res;
ex->ex_phy = kcalloc(ex->num_phys, sizeof(*ex->ex_phy), GFP_KERNEL);
if (!ex->ex_phy)
@@ -500,7 +500,7 @@
ex_assign_report_general(dev, rg_resp);
if (dev->ex_dev.configuring) {
- pr_debug("RG: ex %llx self-configuring...\n",
+ pr_debug("RG: ex %016llx self-configuring...\n",
SAS_ADDR(dev->sas_addr));
schedule_timeout_interruptible(5*HZ);
} else
@@ -881,7 +881,7 @@
res = sas_discover_end_dev(child);
if (res) {
- pr_notice("sas_discover_end_dev() for device %16llx at %016llx:%02d returned 0x%x\n",
+ pr_notice("sas_discover_end_dev() for device %016llx at %016llx:%02d returned 0x%x\n",
SAS_ADDR(child->sas_addr),
SAS_ADDR(parent->sas_addr), phy_id, res);
goto out_list_del;
@@ -1096,7 +1096,7 @@
} else
memcpy(dev->port->disc.fanout_sas_addr,
ex_phy->attached_sas_addr, SAS_ADDR_SIZE);
- /* fallthrough */
+ fallthrough;
case SAS_EDGE_EXPANDER_DEVICE:
child = sas_ex_discover_expander(dev, phy_id);
break;
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 21c43b1..f8ae1f0 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -123,12 +123,6 @@
goto Undo_phys;
}
- error = sas_init_events(sas_ha);
- if (error) {
- pr_notice("couldn't start event thread:%d\n", error);
- goto Undo_ports;
- }
-
error = -ENOMEM;
snprintf(name, sizeof(name), "%s_event_q", dev_name(sas_ha->dev));
sas_ha->event_q = create_singlethread_workqueue(name);
@@ -590,16 +584,15 @@
}
EXPORT_SYMBOL_GPL(sas_domain_attach_transport);
-
-struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy)
+static struct asd_sas_event *__sas_alloc_event(struct asd_sas_phy *phy,
+ gfp_t gfp_flags)
{
struct asd_sas_event *event;
- gfp_t flags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
struct sas_ha_struct *sas_ha = phy->ha;
struct sas_internal *i =
to_sas_internal(sas_ha->core.shost->transportt);
- event = kmem_cache_zalloc(sas_event_cache, flags);
+ event = kmem_cache_zalloc(sas_event_cache, gfp_flags);
if (!event)
return NULL;
@@ -610,7 +603,8 @@
if (cmpxchg(&phy->in_shutdown, 0, 1) == 0) {
pr_notice("The phy%d bursting events, shut it down.\n",
phy->id);
- sas_notify_phy_event(phy, PHYE_SHUTDOWN);
+ sas_notify_phy_event_gfp(phy, PHYE_SHUTDOWN,
+ gfp_flags);
}
} else {
/* Do not support PHY control, stop allocating events */
@@ -624,6 +618,17 @@
return event;
}
+struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy)
+{
+ return __sas_alloc_event(phy, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+}
+
+struct asd_sas_event *sas_alloc_event_gfp(struct asd_sas_phy *phy,
+ gfp_t gfp_flags)
+{
+ return __sas_alloc_event(phy, gfp_flags);
+}
+
void sas_free_event(struct asd_sas_event *event)
{
struct asd_sas_phy *phy = event->phy;
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 01f1738..52e09c3 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -49,12 +49,13 @@
void sas_unregister_phys(struct sas_ha_struct *sas_ha);
struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy);
+struct asd_sas_event *sas_alloc_event_gfp(struct asd_sas_phy *phy,
+ gfp_t gfp_flags);
void sas_free_event(struct asd_sas_event *event);
int sas_register_ports(struct sas_ha_struct *sas_ha);
void sas_unregister_ports(struct sas_ha_struct *sas_ha);
-int sas_init_events(struct sas_ha_struct *sas_ha);
void sas_disable_revalidation(struct sas_ha_struct *ha);
void sas_enable_revalidation(struct sas_ha_struct *ha);
void __sas_drain_work(struct sas_ha_struct *ha);
@@ -78,6 +79,8 @@
int sas_smp_get_phy_events(struct sas_phy *phy);
int sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event);
+int sas_notify_phy_event_gfp(struct asd_sas_phy *phy, enum phy_event event,
+ gfp_t flags);
void sas_device_set_phy(struct domain_device *dev, struct sas_port *port);
struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy);
struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id);
@@ -107,7 +110,7 @@
static inline void sas_fail_probe(struct domain_device *dev, const char *func, int err)
{
- pr_warn("%s: for %s device %16llx returned %d\n",
+ pr_warn("%s: for %s device %016llx returned %d\n",
func, dev->parent ? "exp-attached" :
"direct-attached",
SAS_ADDR(dev->sas_addr), err);
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index f751a12..e3d03d7 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -165,7 +165,7 @@
}
sas_port_add_phy(port->port, phy->phy);
- pr_debug("%s added to %s, phy_mask:0x%x (%16llx)\n",
+ pr_debug("%s added to %s, phy_mask:0x%x (%016llx)\n",
dev_name(&phy->phy->dev), dev_name(&port->port->dev),
port->phy_mask,
SAS_ADDR(port->attached_sas_addr));
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 081f314..ee44a0d 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -330,7 +330,7 @@
int_to_scsilun(cmd->device->lun, &lun);
- pr_notice("eh: device %llx LUN %llx has the task\n",
+ pr_notice("eh: device %016llx LUN 0x%llx has the task\n",
SAS_ADDR(dev->sas_addr),
cmd->device->lun);
@@ -615,14 +615,14 @@
reset:
tmf_resp = sas_recover_lu(task->dev, cmd);
if (tmf_resp == TMF_RESP_FUNC_COMPLETE) {
- pr_notice("dev %016llx LU %llx is recovered\n",
+ pr_notice("dev %016llx LU 0x%llx is recovered\n",
SAS_ADDR(task->dev),
cmd->device->lun);
sas_eh_finish_cmd(cmd);
sas_scsi_clear_queue_lu(work_q, cmd);
goto Again;
}
- /* fallthrough */
+ fallthrough;
case TASK_IS_NOT_AT_LU:
case TASK_ABORT_FAILED:
pr_notice("task 0x%p is not at LU: I_T recover\n",
@@ -666,7 +666,7 @@
* of effort could recover from errors. Quite
* possibly the HA just disappeared.
*/
- pr_err("error from device %llx, LUN %llx couldn't be recovered in any way\n",
+ pr_err("error from device %016llx, LUN 0x%llx couldn't be recovered in any way\n",
SAS_ADDR(task->dev->sas_addr),
cmd->device->lun);
@@ -851,7 +851,7 @@
if (scsi_dev->tagged_supported) {
scsi_change_queue_depth(scsi_dev, SAS_DEF_QD);
} else {
- pr_notice("device %llx, LUN %llx doesn't support TCQ\n",
+ pr_notice("device %016llx, LUN 0x%llx doesn't support TCQ\n",
SAS_ADDR(dev->sas_addr), scsi_dev->lun);
scsi_change_queue_depth(scsi_dev, 1);
}
diff --git a/drivers/scsi/libsas/sas_task.c b/drivers/scsi/libsas/sas_task.c
index 1ded7d8..e2d4259 100644
--- a/drivers/scsi/libsas/sas_task.c
+++ b/drivers/scsi/libsas/sas_task.c
@@ -27,7 +27,7 @@
memcpy(tstat->buf, iu->sense_data, tstat->buf_valid_size);
if (iu->status != SAM_STAT_CHECK_CONDITION)
- dev_warn(dev, "dev %llx sent sense data, but stat(%x) is not CHECK CONDITION\n",
+ dev_warn(dev, "dev %016llx sent sense data, but stat(0x%x) is not CHECK CONDITION\n",
SAS_ADDR(task->dev->sas_addr), iu->status);
}
else
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 8943d42..03bc472 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -143,7 +143,7 @@
struct lpfc_nvmet_ctxbuf {
struct list_head list;
- struct lpfc_nvmet_rcv_ctx *context;
+ struct lpfc_async_xchg_ctx *context;
struct lpfc_iocbq *iocbq;
struct lpfc_sglq *sglq;
struct work_struct defer_work;
@@ -207,8 +207,7 @@
} rev;
struct {
#ifdef __BIG_ENDIAN_BITFIELD
- uint32_t rsvd3 :19; /* Reserved */
- uint32_t cdss : 1; /* Configure Data Security SLI */
+ uint32_t rsvd3 :20; /* Reserved */
uint32_t rsvd2 : 3; /* Reserved */
uint32_t cbg : 1; /* Configure BlockGuard */
uint32_t cmv : 1; /* Configure Max VPIs */
@@ -230,8 +229,7 @@
uint32_t cmv : 1; /* Configure Max VPIs */
uint32_t cbg : 1; /* Configure BlockGuard */
uint32_t rsvd2 : 3; /* Reserved */
- uint32_t cdss : 1; /* Configure Data Security SLI */
- uint32_t rsvd3 :19; /* Reserved */
+ uint32_t rsvd3 :20; /* Reserved */
#endif
} sli3Feat;
} lpfc_vpd_t;
@@ -262,7 +260,6 @@
uint32_t elsRcvPRLI;
uint32_t elsRcvLIRR;
uint32_t elsRcvRLS;
- uint32_t elsRcvRPS;
uint32_t elsRcvRPL;
uint32_t elsRcvRRQ;
uint32_t elsRcvRTV;
@@ -377,6 +374,7 @@
#define FC_VPORT_LOGO_RCVD 0x200 /* LOGO received on vport */
#define FC_RSCN_DISCOVERY 0x400 /* Auth all devices after RSCN */
#define FC_LOGO_RCVD_DID_CHNG 0x800 /* FDISC on phys port detect DID chng*/
+#define FC_PT2PT_NO_NVME 0x1000 /* Don't send NVME PRLI */
#define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */
#define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */
#define FC_NDISC_ACTIVE 0x10000 /* NPort discovery active */
@@ -481,8 +479,8 @@
struct dentry *debug_nodelist;
struct dentry *debug_nvmestat;
struct dentry *debug_scsistat;
- struct dentry *debug_nvmektime;
- struct dentry *debug_cpucheck;
+ struct dentry *debug_ioktime;
+ struct dentry *debug_hdwqstat;
struct dentry *vport_debugfs_root;
struct lpfc_debugfs_trc *disc_trc;
atomic_t disc_trc_cnt;
@@ -605,6 +603,12 @@
spinlock_t lock; /* lock for expedite pool */
};
+enum ras_state {
+ INACTIVE,
+ REG_INPROGRESS,
+ ACTIVE
+};
+
struct lpfc_ras_fwlog {
uint8_t *fwlog_buff;
uint32_t fw_buffcount; /* Buffer size posted to FW */
@@ -621,7 +625,28 @@
bool ras_enabled; /* Ras Enabled for the function */
#define LPFC_RAS_DISABLE_LOGGING 0x00
#define LPFC_RAS_ENABLE_LOGGING 0x01
- bool ras_active; /* RAS logging running state */
+ enum ras_state state; /* RAS logging running state */
+};
+
+#define DBG_LOG_STR_SZ 256
+#define DBG_LOG_SZ 256
+
+struct dbg_log_ent {
+ char log[DBG_LOG_STR_SZ];
+ u64 t_ns;
+};
+
+enum lpfc_irq_chann_mode {
+ /* Assign IRQs to all possible cpus that have hardware queues */
+ NORMAL_MODE,
+
+ /* Assign IRQs only to cpus on the same numa node as HBA */
+ NUMA_MODE,
+
+ /* Assign IRQs only on non-hyperthreaded CPUs. This is the
+ * same as normal_mode, but assign IRQS only on physical CPUs.
+ */
+ NHT_MODE,
};
struct lpfc_hba {
@@ -693,6 +718,9 @@
struct workqueue_struct *wq;
struct delayed_work eq_delay_work;
+#define LPFC_IDLE_STAT_DELAY 1000
+ struct delayed_work idle_stat_delay_work;
+
struct lpfc_sli sli;
uint8_t pci_dev_grp; /* lpfc PCI dev group: 0x0, 0x1, 0x2,... */
uint32_t sli_rev; /* SLI2, SLI3, or SLI4 */
@@ -725,7 +753,8 @@
#define HBA_FCOE_MODE 0x4 /* HBA function in FCoE Mode */
#define HBA_SP_QUEUE_EVT 0x8 /* Slow-path qevt posted to worker thread*/
#define HBA_POST_RECEIVE_BUFFER 0x10 /* Rcv buffers need to be posted */
-#define ELS_XRI_ABORT_EVENT 0x40
+#define HBA_PERSISTENT_TOPO 0x20 /* Persistent topology support in hba */
+#define ELS_XRI_ABORT_EVENT 0x40 /* ELS_XRI abort event was queued */
#define ASYNC_EVENT 0x80
#define LINK_DISABLED 0x100 /* Link disabled by user */
#define FCF_TS_INPROG 0x200 /* FCF table scan in progress */
@@ -735,7 +764,6 @@
#define HBA_DEVLOSS_TMO 0x2000 /* HBA in devloss timeout */
#define HBA_RRQ_ACTIVE 0x4000 /* process the rrq active list */
#define HBA_IOQ_FLUSH 0x8000 /* FCP/NVME I/O queues being flushed */
-#define HBA_FW_DUMP_OP 0x10000 /* Skips fn reset before FW dump */
#define HBA_RECOVERABLE_UE 0x20000 /* Firmware supports recoverable UE */
#define HBA_FORCED_LINK_SPEED 0x40000 /*
* Firmware supports Forced Link Speed
@@ -744,6 +772,7 @@
#define HBA_FLOGI_ISSUED 0x100000 /* FLOGI was issued */
#define HBA_DEFER_FLOGI 0x800000 /* Defer FLOGI till read_sparm cmpl */
+ struct completion *fw_dump_cmpl; /* cmpl event tracker for fw_dump */
uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/
struct lpfc_dmabuf slim2p;
@@ -870,10 +899,19 @@
uint32_t cfg_hostmem_hgp;
uint32_t cfg_log_verbose;
uint32_t cfg_enable_fc4_type;
+#define LPFC_ENABLE_FCP 1
+#define LPFC_ENABLE_NVME 2
+#define LPFC_ENABLE_BOTH 3
+#if (IS_ENABLED(CONFIG_NVME_FC))
+#define LPFC_MAX_ENBL_FC4_TYPE LPFC_ENABLE_BOTH
+#define LPFC_DEF_ENBL_FC4_TYPE LPFC_ENABLE_BOTH
+#else
+#define LPFC_MAX_ENBL_FC4_TYPE LPFC_ENABLE_FCP
+#define LPFC_DEF_ENBL_FC4_TYPE LPFC_ENABLE_FCP
+#endif
uint32_t cfg_aer_support;
uint32_t cfg_sriov_nr_virtfn;
uint32_t cfg_request_firmware_upgrade;
- uint32_t cfg_iocb_cnt;
uint32_t cfg_suppress_link_up;
uint32_t cfg_rrq_xri_bitmap_sz;
uint32_t cfg_delay_discovery;
@@ -881,7 +919,6 @@
#define LPFC_INITIALIZE_LINK 0 /* do normal init_link mbox */
#define LPFC_DELAY_INIT_LINK 1 /* layered driver hold off */
#define LPFC_DELAY_INIT_LINK_INDEFINITELY 2 /* wait, manual intervention */
- uint32_t cfg_enable_dss;
uint32_t cfg_fdmi_on;
#define LPFC_FDMI_NO_SUPPORT 0 /* FDMI not supported */
#define LPFC_FDMI_SUPPORT 1 /* FDMI supported? */
@@ -892,9 +929,6 @@
uint32_t cfg_ras_fwlog_func;
uint32_t cfg_enable_bbcr; /* Enable BB Credit Recovery */
uint32_t cfg_enable_dpp; /* Enable Direct Packet Push */
-#define LPFC_ENABLE_FCP 1
-#define LPFC_ENABLE_NVME 2
-#define LPFC_ENABLE_BOTH 3
uint32_t cfg_enable_pbde;
struct nvmet_fc_target_port *targetport;
lpfc_vpd_t vpd; /* vital product data */
@@ -991,7 +1025,6 @@
struct dma_pool *lpfc_drb_pool; /* data receive buffer pool */
struct dma_pool *lpfc_nvmet_drb_pool; /* data receive buffer pool */
struct dma_pool *lpfc_hbq_pool; /* SLI3 hbq buffer pool */
- struct dma_pool *txrdy_payload_pool;
struct dma_pool *lpfc_cmd_rsp_buf_pool;
struct lpfc_dma_pool lpfc_mbuf_safety_pool;
@@ -1001,6 +1034,7 @@
mempool_t *active_rrq_pool;
struct fc_host_statistics link_stats;
+ enum lpfc_irq_chann_mode irq_chann_mode;
enum intr_type_t intr_type;
uint32_t intr_mode;
#define LPFC_INTR_ERROR 0xFFFFFFFF
@@ -1056,6 +1090,7 @@
#ifdef LPFC_HDWQ_LOCK_STAT
struct dentry *debug_lockstat;
#endif
+ struct dentry *debug_ras_log;
atomic_t nvmeio_trc_cnt;
uint32_t nvmeio_trc_size;
uint32_t nvmeio_trc_output_idx;
@@ -1150,8 +1185,6 @@
uint32_t iocb_cnt;
uint32_t iocb_max;
atomic_t sdev_cnt;
- uint8_t fips_spec_rev;
- uint8_t fips_level;
spinlock_t devicelock; /* lock for luns list */
mempool_t *device_data_mem_pool;
struct list_head luns;
@@ -1169,12 +1202,11 @@
uint16_t sfp_warning;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
- uint16_t cpucheck_on;
+ uint16_t hdwqstat_on;
#define LPFC_CHECK_OFF 0
#define LPFC_CHECK_NVME_IO 1
-#define LPFC_CHECK_NVMET_RCV 2
-#define LPFC_CHECK_NVMET_IO 4
-#define LPFC_CHECK_SCSI_IO 8
+#define LPFC_CHECK_NVMET_IO 2
+#define LPFC_CHECK_SCSI_IO 4
uint16_t ktime_on;
uint64_t ktime_data_samples;
uint64_t ktime_status_samples;
@@ -1219,6 +1251,15 @@
#define LPFC_POLL_SLOWPATH 1 /* called from slowpath */
char os_host_name[MAXHOSTNAMELEN];
+
+ /* SCSI host template information - for physical port */
+ struct scsi_host_template port_template;
+ /* SCSI host template information - for all vports */
+ struct scsi_host_template vport_template;
+ atomic_t dbg_log_idx;
+ atomic_t dbg_log_cnt;
+ atomic_t dbg_log_dmping;
+ struct dbg_log_ent dbg_log[DBG_LOG_SZ];
};
static inline struct Scsi_Host *
@@ -1309,6 +1350,26 @@
}
/**
+ * lpfc_next_online_cpu - Finds next online CPU on cpumask
+ * @mask: Pointer to phba's cpumask member.
+ * @start: starting cpu index
+ *
+ * Note: If no valid cpu found, then nr_cpu_ids is returned.
+ *
+ **/
+static inline unsigned int
+lpfc_next_online_cpu(const struct cpumask *mask, unsigned int start)
+{
+ unsigned int cpu_it;
+
+ for_each_cpu_wrap(cpu_it, mask, start) {
+ if (cpu_online(cpu_it))
+ break;
+ }
+
+ return cpu_it;
+}
+/**
* lpfc_sli4_mod_hba_eq_delay - update EQ delay
* @phba: Pointer to HBA context object.
* @q: The Event Queue to update.
@@ -1327,3 +1388,32 @@
writel(reg_data.word0, phba->sli4_hba.u.if_type2.EQDregaddr);
eq->q_mode = delay;
}
+
+
+/*
+ * Macro that declares tables and a routine to perform enum type to
+ * ascii string lookup.
+ *
+ * Defines a <key,value> table for an enum. Uses xxx_INIT defines for
+ * the enum to populate the table. Macro defines a routine (named
+ * by caller) that will search all elements of the table for the key
+ * and return the name string if found or "Unrecognized" if not found.
+ */
+#define DECLARE_ENUM2STR_LOOKUP(routine, enum_name, enum_init) \
+static struct { \
+ enum enum_name value; \
+ char *name; \
+} fc_##enum_name##_e2str_names[] = enum_init; \
+static const char *routine(enum enum_name table_key) \
+{ \
+ int i; \
+ char *name = "Unrecognized"; \
+ \
+ for (i = 0; i < ARRAY_SIZE(fc_##enum_name##_e2str_names); i++) {\
+ if (fc_##enum_name##_e2str_names[i].value == table_key) {\
+ name = fc_##enum_name##_e2str_names[i].name; \
+ break; \
+ } \
+ } \
+ return name; \
+}
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 45db19e..f0d1ced 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -37,8 +37,6 @@
#include <scsi/scsi_transport_fc.h>
#include <scsi/fc/fc_fs.h>
-#include <linux/nvme-fc-driver.h>
-
#include "lpfc_hw4.h"
#include "lpfc_hw.h"
#include "lpfc_sli.h"
@@ -48,7 +46,6 @@
#include "lpfc.h"
#include "lpfc_scsi.h"
#include "lpfc_nvme.h"
-#include "lpfc_nvmet.h"
#include "lpfc_logmsg.h"
#include "lpfc_version.h"
#include "lpfc_compat.h"
@@ -1145,6 +1142,9 @@
pmboxq->u.mb.mbxCommand = MBX_DOWN_LINK;
pmboxq->u.mb.mbxOwner = OWN_HOST;
+ if ((vport->fc_flag & FC_PT2PT) && (vport->fc_flag & FC_PT2PT_NO_NVME))
+ vport->fc_flag &= ~FC_PT2PT_NO_NVME;
+
mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO * 2);
if ((mbxstatus == MBX_SUCCESS) &&
@@ -1475,8 +1475,9 @@
int i;
msleep(100);
- lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
- &portstat_reg.word0);
+ if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
+ &portstat_reg.word0))
+ return -EIO;
/* verify if privileged for the request operation */
if (!bf_get(lpfc_sliport_status_rn, &portstat_reg) &&
@@ -1486,8 +1487,9 @@
/* wait for the SLI port firmware ready after firmware reset */
for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) {
msleep(10);
- lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
- &portstat_reg.word0);
+ if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
+ &portstat_reg.word0))
+ continue;
if (!bf_get(lpfc_sliport_status_err, &portstat_reg))
continue;
if (!bf_get(lpfc_sliport_status_rn, &portstat_reg))
@@ -1537,25 +1539,25 @@
before_fc_flag = phba->pport->fc_flag;
sriov_nr_virtfn = phba->cfg_sriov_nr_virtfn;
- /* Disable SR-IOV virtual functions if enabled */
- if (phba->cfg_sriov_nr_virtfn) {
- pci_disable_sriov(pdev);
- phba->cfg_sriov_nr_virtfn = 0;
+ if (opcode == LPFC_FW_DUMP) {
+ init_completion(&online_compl);
+ phba->fw_dump_cmpl = &online_compl;
+ } else {
+ /* Disable SR-IOV virtual functions if enabled */
+ if (phba->cfg_sriov_nr_virtfn) {
+ pci_disable_sriov(pdev);
+ phba->cfg_sriov_nr_virtfn = 0;
+ }
+
+ status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
+
+ if (status != 0)
+ return status;
+
+ /* wait for the device to be quiesced before firmware reset */
+ msleep(100);
}
- if (opcode == LPFC_FW_DUMP)
- phba->hba_flag |= HBA_FW_DUMP_OP;
-
- status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
-
- if (status != 0) {
- phba->hba_flag &= ~HBA_FW_DUMP_OP;
- return status;
- }
-
- /* wait for the device to be quiesced before firmware reset */
- msleep(100);
-
reg_val = readl(phba->sli4_hba.conf_regs_memmap_p +
LPFC_CTL_PDEV_CTL_OFFSET);
@@ -1584,24 +1586,42 @@
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"3153 Fail to perform the requested "
"access: x%x\n", reg_val);
+ if (phba->fw_dump_cmpl)
+ phba->fw_dump_cmpl = NULL;
return rc;
}
/* keep the original port state */
- if (before_fc_flag & FC_OFFLINE_MODE)
+ if (before_fc_flag & FC_OFFLINE_MODE) {
+ if (phba->fw_dump_cmpl)
+ phba->fw_dump_cmpl = NULL;
goto out;
+ }
- init_completion(&online_compl);
- job_posted = lpfc_workq_post_event(phba, &status, &online_compl,
- LPFC_EVT_ONLINE);
- if (!job_posted)
- goto out;
+ /* Firmware dump will trigger an HA_ERATT event, and
+ * lpfc_handle_eratt_s4 routine already handles bringing the port back
+ * online.
+ */
+ if (opcode == LPFC_FW_DUMP) {
+ wait_for_completion(phba->fw_dump_cmpl);
+ } else {
+ init_completion(&online_compl);
+ job_posted = lpfc_workq_post_event(phba, &status, &online_compl,
+ LPFC_EVT_ONLINE);
+ if (!job_posted)
+ goto out;
- wait_for_completion(&online_compl);
-
+ wait_for_completion(&online_compl);
+ }
out:
/* in any case, restore the virtual functions enabled as before */
if (sriov_nr_virtfn) {
+ /* If fw_dump was performed, first disable to clean up */
+ if (opcode == LPFC_FW_DUMP) {
+ pci_disable_sriov(pdev);
+ phba->cfg_sriov_nr_virtfn = 0;
+ }
+
sriov_err =
lpfc_sli_probe_sriov_nr_virtfn(phba, sriov_nr_virtfn);
if (!sriov_err)
@@ -1642,7 +1662,7 @@
{
LPFC_MBOXQ_t *mbox = NULL;
unsigned long val = 0;
- char *pval = 0;
+ char *pval = NULL;
int rc = 0;
if (!strncmp("enable", buff_out,
@@ -2228,66 +2248,6 @@
}
/**
- * lpfc_fips_level_show - Return the current FIPS level for the HBA
- * @dev: class unused variable.
- * @attr: device attribute, not used.
- * @buf: on return contains the module description text.
- *
- * Returns: size of formatted string.
- **/
-static ssize_t
-lpfc_fips_level_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(dev);
- struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
- struct lpfc_hba *phba = vport->phba;
-
- return scnprintf(buf, PAGE_SIZE, "%d\n", phba->fips_level);
-}
-
-/**
- * lpfc_fips_rev_show - Return the FIPS Spec revision for the HBA
- * @dev: class unused variable.
- * @attr: device attribute, not used.
- * @buf: on return contains the module description text.
- *
- * Returns: size of formatted string.
- **/
-static ssize_t
-lpfc_fips_rev_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(dev);
- struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
- struct lpfc_hba *phba = vport->phba;
-
- return scnprintf(buf, PAGE_SIZE, "%d\n", phba->fips_spec_rev);
-}
-
-/**
- * lpfc_dss_show - Return the current state of dss and the configured state
- * @dev: class converted to a Scsi_host structure.
- * @attr: device attribute, not used.
- * @buf: on return contains the formatted text.
- *
- * Returns: size of formatted string.
- **/
-static ssize_t
-lpfc_dss_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct Scsi_Host *shost = class_to_shost(dev);
- struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
- struct lpfc_hba *phba = vport->phba;
-
- return scnprintf(buf, PAGE_SIZE, "%s - %sOperational\n",
- (phba->cfg_enable_dss) ? "Enabled" : "Disabled",
- (phba->sli3_options & LPFC_SLI3_DSS_ENABLED) ?
- "" : "Not ");
-}
-
-/**
* lpfc_sriov_hw_max_virtfn_show - Return maximum number of virtual functions
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
@@ -2702,9 +2662,6 @@
static DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL);
static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);
static DEVICE_ATTR_RO(lpfc_temp_sensor);
-static DEVICE_ATTR_RO(lpfc_fips_level);
-static DEVICE_ATTR_RO(lpfc_fips_rev);
-static DEVICE_ATTR_RO(lpfc_dss);
static DEVICE_ATTR_RO(lpfc_sriov_hw_max_virtfn);
static DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL);
static DEVICE_ATTR(lpfc_xlane_supported, S_IRUGO, lpfc_oas_supported_show,
@@ -3532,6 +3489,31 @@
LPFC_ATTR_R(suppress_link_up, LPFC_INITIALIZE_LINK, LPFC_INITIALIZE_LINK,
LPFC_DELAY_INIT_LINK_INDEFINITELY,
"Suppress Link Up at initialization");
+
+static ssize_t
+lpfc_pls_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n",
+ phba->sli4_hba.pc_sli4_params.pls);
+}
+static DEVICE_ATTR(pls, 0444,
+ lpfc_pls_show, NULL);
+
+static ssize_t
+lpfc_pt_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n",
+ (phba->hba_flag & HBA_PERSISTENT_TOPO) ? 1 : 0);
+}
+static DEVICE_ATTR(pt, 0444,
+ lpfc_pt_show, NULL);
+
/*
# lpfc_cnt: Number of IOCBs allocated for ELS, CT, and ABTS
# 1 - (1024)
@@ -3579,9 +3561,6 @@
static DEVICE_ATTR(txcmplq_hw, S_IRUGO,
lpfc_txcmplq_hw_show, NULL);
-LPFC_ATTR_R(iocb_cnt, 2, 1, 5,
- "Number of IOCBs alloc for ELS, CT, and ABTS: 1k to 5k IOCBs");
-
/*
# lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
# until the timer expires. Value range is [0,255]. Default value is 30.
@@ -3821,8 +3800,8 @@
* 3 - register both FCP and NVME
* Supported values are [1,3]. Default value is 3
*/
-LPFC_ATTR_R(enable_fc4_type, LPFC_ENABLE_BOTH,
- LPFC_ENABLE_FCP, LPFC_ENABLE_BOTH,
+LPFC_ATTR_R(enable_fc4_type, LPFC_DEF_ENBL_FC4_TYPE,
+ LPFC_ENABLE_FCP, LPFC_MAX_ENBL_FC4_TYPE,
"Enable FC4 Protocol support - FCP / NVME");
/*
@@ -3843,12 +3822,9 @@
/*
# lun_queue_depth: This parameter is used to limit the number of outstanding
-# commands per FCP LUN. Value range is [1,512]. Default value is 30.
-# If this parameter value is greater than 1/8th the maximum number of exchanges
-# supported by the HBA port, then the lun queue depth will be reduced to
-# 1/8th the maximum number of exchanges.
+# commands per FCP LUN.
*/
-LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 512,
+LPFC_VPORT_ATTR_R(lun_queue_depth, 64, 1, 512,
"Max number of FCP commands we can queue to a specific LUN");
/*
@@ -4095,8 +4071,16 @@
val);
return -EINVAL;
}
- if ((phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC ||
- phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC) &&
+ /*
+ * The 'topology' is not a configurable parameter if :
+ * - persistent topology enabled
+ * - G7/G6 with no private loop support
+ */
+
+ if ((phba->hba_flag & HBA_PERSISTENT_TOPO ||
+ (!phba->sli4_hba.pc_sli4_params.pls &&
+ (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC ||
+ phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC))) &&
val == 4) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
"3114 Loop mode not supported\n");
@@ -4750,7 +4734,7 @@
* Description:
* If the @buf contains 1 and the device currently has the AER support
* enabled, then invokes the kernel AER helper routine
- * pci_cleanup_aer_uncorrect_error_status to clean up the uncorrectable
+ * pci_aer_clear_nonfatal_status() to clean up the uncorrectable
* error status register.
*
* Notes:
@@ -4776,7 +4760,7 @@
return -EINVAL;
if (phba->hba_flag & HBA_AER_ENABLED)
- rc = pci_cleanup_aer_uncorrect_error_status(phba->pcidev);
+ rc = pci_aer_clear_nonfatal_status(phba->pcidev);
if (rc == 0)
return strlen(buf);
@@ -4910,7 +4894,7 @@
struct Scsi_Host *shost = class_to_shost(dev);
struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
struct lpfc_hba *phba = vport->phba;
- int val = 0, rc = -EINVAL;
+ int val = 0, rc;
/* Sanity check on user data */
if (!isdigit(buf[0]))
@@ -5297,7 +5281,7 @@
len += scnprintf(buf + len, PAGE_SIZE - len,
"CPU %02d not present\n",
phba->sli4_hba.curr_disp_cpu);
- else if (cpup->irq == LPFC_VECTOR_MAP_EMPTY) {
+ else if (cpup->eq == LPFC_VECTOR_MAP_EMPTY) {
if (cpup->hdwq == LPFC_VECTOR_MAP_EMPTY)
len += scnprintf(
buf + len, PAGE_SIZE - len,
@@ -5310,10 +5294,10 @@
else
len += scnprintf(
buf + len, PAGE_SIZE - len,
- "CPU %02d EQ %04d hdwq %04d "
+ "CPU %02d EQ None hdwq %04d "
"physid %d coreid %d ht %d ua %d\n",
phba->sli4_hba.curr_disp_cpu,
- cpup->eq, cpup->hdwq, cpup->phys_id,
+ cpup->hdwq, cpup->phys_id,
cpup->core_id,
(cpup->flag & LPFC_CPU_MAP_HYPER),
(cpup->flag & LPFC_CPU_MAP_UNASSIGN));
@@ -5328,7 +5312,7 @@
cpup->core_id,
(cpup->flag & LPFC_CPU_MAP_HYPER),
(cpup->flag & LPFC_CPU_MAP_UNASSIGN),
- cpup->irq);
+ lpfc_get_irq(cpup->eq));
else
len += scnprintf(
buf + len, PAGE_SIZE - len,
@@ -5339,7 +5323,7 @@
cpup->core_id,
(cpup->flag & LPFC_CPU_MAP_HYPER),
(cpup->flag & LPFC_CPU_MAP_UNASSIGN),
- cpup->irq);
+ lpfc_get_irq(cpup->eq));
}
phba->sli4_hba.curr_disp_cpu++;
@@ -5374,8 +5358,7 @@
lpfc_fcp_cpu_map_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- int status = -EINVAL;
- return status;
+ return -EINVAL;
}
/*
@@ -5710,7 +5693,7 @@
* the driver will advertise it supports to the SCSI layer.
*
* 0 = Set nr_hw_queues by the number of CPUs or HW queues.
- * 1,128 = Manually specify the maximum nr_hw_queue value to be set,
+ * 1,256 = Manually specify nr_hw_queue value to be advertised,
*
* Value range is [0,256]. Default value is 8.
*/
@@ -5728,30 +5711,192 @@
* A hardware IO queue maps (qidx) to a specific driver CQ/WQ.
*
* 0 = Configure the number of hdw queues to the number of active CPUs.
- * 1,128 = Manually specify how many hdw queues to use.
+ * 1,256 = Manually specify how many hdw queues to use.
*
- * Value range is [0,128]. Default value is 0.
+ * Value range is [0,256]. Default value is 0.
*/
LPFC_ATTR_R(hdw_queue,
LPFC_HBA_HDWQ_DEF,
LPFC_HBA_HDWQ_MIN, LPFC_HBA_HDWQ_MAX,
"Set the number of I/O Hardware Queues");
+#if IS_ENABLED(CONFIG_X86)
+/**
+ * lpfc_cpumask_irq_mode_init - initalizes cpumask of phba based on
+ * irq_chann_mode
+ * @phba: Pointer to HBA context object.
+ **/
+static void
+lpfc_cpumask_irq_mode_init(struct lpfc_hba *phba)
+{
+ unsigned int cpu, first_cpu, numa_node = NUMA_NO_NODE;
+ const struct cpumask *sibling_mask;
+ struct cpumask *aff_mask = &phba->sli4_hba.irq_aff_mask;
+
+ cpumask_clear(aff_mask);
+
+ if (phba->irq_chann_mode == NUMA_MODE) {
+ /* Check if we're a NUMA architecture */
+ numa_node = dev_to_node(&phba->pcidev->dev);
+ if (numa_node == NUMA_NO_NODE) {
+ phba->irq_chann_mode = NORMAL_MODE;
+ return;
+ }
+ }
+
+ for_each_possible_cpu(cpu) {
+ switch (phba->irq_chann_mode) {
+ case NUMA_MODE:
+ if (cpu_to_node(cpu) == numa_node)
+ cpumask_set_cpu(cpu, aff_mask);
+ break;
+ case NHT_MODE:
+ sibling_mask = topology_sibling_cpumask(cpu);
+ first_cpu = cpumask_first(sibling_mask);
+ if (first_cpu < nr_cpu_ids)
+ cpumask_set_cpu(first_cpu, aff_mask);
+ break;
+ default:
+ break;
+ }
+ }
+}
+#endif
+
+static void
+lpfc_assign_default_irq_chann(struct lpfc_hba *phba)
+{
+#if IS_ENABLED(CONFIG_X86)
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ /* If AMD architecture, then default is NUMA_MODE */
+ phba->irq_chann_mode = NUMA_MODE;
+ break;
+ case X86_VENDOR_INTEL:
+ /* If Intel architecture, then default is no hyperthread mode */
+ phba->irq_chann_mode = NHT_MODE;
+ break;
+ default:
+ phba->irq_chann_mode = NORMAL_MODE;
+ break;
+ }
+ lpfc_cpumask_irq_mode_init(phba);
+#else
+ phba->irq_chann_mode = NORMAL_MODE;
+#endif
+}
+
/*
* lpfc_irq_chann: Set the number of IRQ vectors that are available
* for Hardware Queues to utilize. This also will map to the number
* of EQ / MSI-X vectors the driver will create. This should never be
* more than the number of Hardware Queues
*
- * 0 = Configure number of IRQ Channels to the number of active CPUs.
- * 1,128 = Manually specify how many IRQ Channels to use.
+ * 0 = Configure number of IRQ Channels to:
+ * if AMD architecture, number of CPUs on HBA's NUMA node
+ * if Intel architecture, number of physical CPUs.
+ * otherwise, number of active CPUs.
+ * [1,256] = Manually specify how many IRQ Channels to use.
*
- * Value range is [0,128]. Default value is 0.
+ * Value range is [0,256]. Default value is [0].
*/
-LPFC_ATTR_R(irq_chann,
- LPFC_HBA_HDWQ_DEF,
- LPFC_HBA_HDWQ_MIN, LPFC_HBA_HDWQ_MAX,
- "Set the number of I/O IRQ Channels");
+static uint lpfc_irq_chann = LPFC_IRQ_CHANN_DEF;
+module_param(lpfc_irq_chann, uint, 0444);
+MODULE_PARM_DESC(lpfc_irq_chann, "Set number of interrupt vectors to allocate");
+
+/* lpfc_irq_chann_init - Set the hba irq_chann initial value
+ * @phba: lpfc_hba pointer.
+ * @val: contains the initial value
+ *
+ * Description:
+ * Validates the initial value is within range and assigns it to the
+ * adapter. If not in range, an error message is posted and the
+ * default value is assigned.
+ *
+ * Returns:
+ * zero if value is in range and is set
+ * -EINVAL if value was out of range
+ **/
+static int
+lpfc_irq_chann_init(struct lpfc_hba *phba, uint32_t val)
+{
+ const struct cpumask *aff_mask;
+
+ if (phba->cfg_use_msi != 2) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "8532 use_msi = %u ignoring cfg_irq_numa\n",
+ phba->cfg_use_msi);
+ phba->irq_chann_mode = NORMAL_MODE;
+ phba->cfg_irq_chann = LPFC_IRQ_CHANN_DEF;
+ return 0;
+ }
+
+ /* Check if default setting was passed */
+ if (val == LPFC_IRQ_CHANN_DEF)
+ lpfc_assign_default_irq_chann(phba);
+
+ if (phba->irq_chann_mode != NORMAL_MODE) {
+ aff_mask = &phba->sli4_hba.irq_aff_mask;
+
+ if (cpumask_empty(aff_mask)) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "8533 Could not identify CPUS for "
+ "mode %d, ignoring\n",
+ phba->irq_chann_mode);
+ phba->irq_chann_mode = NORMAL_MODE;
+ phba->cfg_irq_chann = LPFC_IRQ_CHANN_DEF;
+ } else {
+ phba->cfg_irq_chann = cpumask_weight(aff_mask);
+
+ /* If no hyperthread mode, then set hdwq count to
+ * aff_mask weight as well
+ */
+ if (phba->irq_chann_mode == NHT_MODE)
+ phba->cfg_hdw_queue = phba->cfg_irq_chann;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "8543 lpfc_irq_chann set to %u "
+ "(mode: %d)\n", phba->cfg_irq_chann,
+ phba->irq_chann_mode);
+ }
+ } else {
+ if (val > LPFC_IRQ_CHANN_MAX) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "8545 lpfc_irq_chann attribute cannot "
+ "be set to %u, allowed range is "
+ "[%u,%u]\n",
+ val,
+ LPFC_IRQ_CHANN_MIN,
+ LPFC_IRQ_CHANN_MAX);
+ phba->cfg_irq_chann = LPFC_IRQ_CHANN_DEF;
+ return -EINVAL;
+ }
+ phba->cfg_irq_chann = val;
+ }
+
+ return 0;
+}
+
+/**
+ * lpfc_irq_chann_show - Display value of irq_chann
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains a string with the list sizes
+ *
+ * Returns: size of formatted string.
+ **/
+static ssize_t
+lpfc_irq_chann_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", phba->cfg_irq_chann);
+}
+
+static DEVICE_ATTR_RO(lpfc_irq_chann);
/*
# lpfc_enable_hba_reset: Allow or prevent HBA resets to the hardware.
@@ -5881,7 +6026,8 @@
len = scnprintf(buf, PAGE_SIZE, "SGL sz: %d total SGEs: %d\n",
phba->cfg_sg_dma_buf_size, phba->cfg_total_seg_cnt);
- len += scnprintf(buf + len, PAGE_SIZE, "Cfg: %d SCSI: %d NVME: %d\n",
+ len += scnprintf(buf + len, PAGE_SIZE - len,
+ "Cfg: %d SCSI: %d NVME: %d\n",
phba->cfg_sg_seg_cnt, phba->cfg_scsi_seg_cnt,
phba->cfg_nvme_seg_cnt);
return len;
@@ -5932,7 +6078,53 @@
* [1-4] = Multiple of 1/4th Mb of host memory for FW logging
* Value range [0..4]. Default value is 0
*/
-LPFC_ATTR_RW(ras_fwlog_buffsize, 0, 0, 4, "Host memory for FW logging");
+LPFC_ATTR(ras_fwlog_buffsize, 0, 0, 4, "Host memory for FW logging");
+lpfc_param_show(ras_fwlog_buffsize);
+
+static ssize_t
+lpfc_ras_fwlog_buffsize_set(struct lpfc_hba *phba, uint val)
+{
+ int ret = 0;
+ enum ras_state state;
+
+ if (!lpfc_rangecheck(val, 0, 4))
+ return -EINVAL;
+
+ if (phba->cfg_ras_fwlog_buffsize == val)
+ return 0;
+
+ if (phba->cfg_ras_fwlog_func != PCI_FUNC(phba->pcidev->devfn))
+ return -EINVAL;
+
+ spin_lock_irq(&phba->hbalock);
+ state = phba->ras_fwlog.state;
+ spin_unlock_irq(&phba->hbalock);
+
+ if (state == REG_INPROGRESS) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "6147 RAS Logging "
+ "registration is in progress\n");
+ return -EBUSY;
+ }
+
+ /* For disable logging: stop the logs and free the DMA.
+ * For ras_fwlog_buffsize size change we still need to free and
+ * reallocate the DMA in lpfc_sli4_ras_fwlog_init.
+ */
+ phba->cfg_ras_fwlog_buffsize = val;
+ if (state == ACTIVE) {
+ lpfc_ras_stop_fwlog(phba);
+ lpfc_sli4_ras_dma_free(phba);
+ }
+
+ lpfc_sli4_ras_init(phba);
+ if (phba->ras_fwlog.ras_enabled)
+ ret = lpfc_sli4_ras_fwlog_init(phba, phba->cfg_ras_fwlog_level,
+ LPFC_RAS_ENABLE_LOGGING);
+ return ret;
+}
+
+lpfc_param_store(ras_fwlog_buffsize);
+static DEVICE_ATTR_RW(lpfc_ras_fwlog_buffsize);
/*
* lpfc_ras_fwlog_level: Firmware logging verbosity level
@@ -6070,13 +6262,11 @@
&dev_attr_lpfc_sriov_nr_virtfn,
&dev_attr_lpfc_req_fw_upgrade,
&dev_attr_lpfc_suppress_link_up,
- &dev_attr_lpfc_iocb_cnt,
&dev_attr_iocb_hw,
+ &dev_attr_pls,
+ &dev_attr_pt,
&dev_attr_txq_hw,
&dev_attr_txcmplq_hw,
- &dev_attr_lpfc_fips_level,
- &dev_attr_lpfc_fips_rev,
- &dev_attr_lpfc_dss,
&dev_attr_lpfc_sriov_hw_max_virtfn,
&dev_attr_protocol,
&dev_attr_lpfc_xlane_supported,
@@ -6112,8 +6302,6 @@
&dev_attr_lpfc_max_scsicmpl_time,
&dev_attr_lpfc_stat_data_ctrl,
&dev_attr_lpfc_static_vport,
- &dev_attr_lpfc_fips_level,
- &dev_attr_lpfc_fips_rev,
NULL,
};
@@ -6511,9 +6699,15 @@
}
} else if (lpfc_is_link_up(phba) && (phba->hba_flag & HBA_FCOE_MODE)) {
switch (phba->fc_linkspeed) {
+ case LPFC_ASYNC_LINK_SPEED_1GBPS:
+ fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
+ break;
case LPFC_ASYNC_LINK_SPEED_10GBPS:
fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
break;
+ case LPFC_ASYNC_LINK_SPEED_20GBPS:
+ fc_host_speed(shost) = FC_PORTSPEED_20GBIT;
+ break;
case LPFC_ASYNC_LINK_SPEED_25GBPS:
fc_host_speed(shost) = FC_PORTSPEED_25GBIT;
break;
@@ -7100,11 +7294,22 @@
static void
lpfc_get_hba_function_mode(struct lpfc_hba *phba)
{
- /* If it's a SkyHawk FCoE adapter */
- if (phba->pcidev->device == PCI_DEVICE_ID_SKYHAWK)
+ /* If the adapter supports FCoE mode */
+ switch (phba->pcidev->device) {
+ case PCI_DEVICE_ID_SKYHAWK:
+ case PCI_DEVICE_ID_SKYHAWK_VF:
+ case PCI_DEVICE_ID_LANCER_FCOE:
+ case PCI_DEVICE_ID_LANCER_FCOE_VF:
+ case PCI_DEVICE_ID_ZEPHYR_DCSP:
+ case PCI_DEVICE_ID_HORNET:
+ case PCI_DEVICE_ID_TIGERSHARK:
+ case PCI_DEVICE_ID_TOMCAT:
phba->hba_flag |= HBA_FCOE_MODE;
- else
+ break;
+ default:
+ /* for others, clear the flag */
phba->hba_flag &= ~HBA_FCOE_MODE;
+ }
}
/**
@@ -7114,6 +7319,7 @@
void
lpfc_get_cfgparam(struct lpfc_hba *phba)
{
+ lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);
lpfc_fcp_io_sched_init(phba, lpfc_fcp_io_sched);
lpfc_ns_query_init(phba, lpfc_ns_query);
lpfc_fcp2_no_tgt_reset_init(phba, lpfc_fcp2_no_tgt_reset);
@@ -7220,15 +7426,12 @@
phba->cfg_soft_wwpn = 0L;
lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt);
lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);
- lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);
lpfc_aer_support_init(phba, lpfc_aer_support);
lpfc_sriov_nr_virtfn_init(phba, lpfc_sriov_nr_virtfn);
lpfc_request_firmware_upgrade_init(phba, lpfc_req_fw_upgrade);
lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up);
- lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt);
lpfc_delay_discovery_init(phba, lpfc_delay_discovery);
lpfc_sli_mode_init(phba, lpfc_sli_mode);
- phba->cfg_enable_dss = 1;
lpfc_enable_mds_diags_init(phba, lpfc_enable_mds_diags);
lpfc_ras_fwlog_buffsize_init(phba, lpfc_ras_fwlog_buffsize);
lpfc_ras_fwlog_level_init(phba, lpfc_ras_fwlog_level);
@@ -7245,12 +7448,26 @@
void
lpfc_nvme_mod_param_dep(struct lpfc_hba *phba)
{
- if (phba->cfg_hdw_queue > phba->sli4_hba.num_present_cpu)
+ int logit = 0;
+
+ if (phba->cfg_hdw_queue > phba->sli4_hba.num_present_cpu) {
phba->cfg_hdw_queue = phba->sli4_hba.num_present_cpu;
- if (phba->cfg_irq_chann > phba->sli4_hba.num_present_cpu)
+ logit = 1;
+ }
+ if (phba->cfg_irq_chann > phba->sli4_hba.num_present_cpu) {
phba->cfg_irq_chann = phba->sli4_hba.num_present_cpu;
- if (phba->cfg_irq_chann > phba->cfg_hdw_queue)
+ logit = 1;
+ }
+ if (phba->cfg_irq_chann > phba->cfg_hdw_queue) {
phba->cfg_irq_chann = phba->cfg_hdw_queue;
+ logit = 1;
+ }
+ if (logit)
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "2006 Reducing Queues - CPU limitation: "
+ "IRQ %d HDWQ %d\n",
+ phba->cfg_irq_chann,
+ phba->cfg_hdw_queue);
if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME &&
phba->nvmet_support) {
@@ -7271,11 +7488,11 @@
}
if (!phba->cfg_nvmet_mrq)
- phba->cfg_nvmet_mrq = phba->cfg_irq_chann;
+ phba->cfg_nvmet_mrq = phba->cfg_hdw_queue;
/* Adjust lpfc_nvmet_mrq to avoid running out of WQE slots */
- if (phba->cfg_nvmet_mrq > phba->cfg_irq_chann) {
- phba->cfg_nvmet_mrq = phba->cfg_irq_chann;
+ if (phba->cfg_nvmet_mrq > phba->cfg_hdw_queue) {
+ phba->cfg_nvmet_mrq = phba->cfg_hdw_queue;
lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
"6018 Adjust lpfc_nvmet_mrq to %d\n",
phba->cfg_nvmet_mrq);
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 6c2b034..6f9d648 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -2404,33 +2404,27 @@
union lpfc_sli4_cfg_shdr *shdr;
uint32_t shdr_status, shdr_add_status;
struct diag_status *diag_status_reply;
- int mbxstatus, rc = 0;
+ int mbxstatus, rc = -ENODEV, rc1 = 0;
shost = fc_bsg_to_shost(job);
- if (!shost) {
- rc = -ENODEV;
+ if (!shost)
goto job_error;
- }
- vport = shost_priv(shost);
- if (!vport) {
- rc = -ENODEV;
- goto job_error;
- }
- phba = vport->phba;
- if (!phba) {
- rc = -ENODEV;
- goto job_error;
- }
- if (phba->sli_rev < LPFC_SLI_REV4) {
- rc = -ENODEV;
+ vport = shost_priv(shost);
+ if (!vport)
goto job_error;
- }
+
+ phba = vport->phba;
+ if (!phba)
+ goto job_error;
+
+
+ if (phba->sli_rev < LPFC_SLI_REV4)
+ goto job_error;
+
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) <
- LPFC_SLI_INTF_IF_TYPE_2) {
- rc = -ENODEV;
+ LPFC_SLI_INTF_IF_TYPE_2)
goto job_error;
- }
if (job->request_len < sizeof(struct fc_bsg_request) +
sizeof(struct sli4_link_diag)) {
@@ -2465,8 +2459,10 @@
alloc_len = lpfc_sli4_config(phba, pmboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
LPFC_MBOX_OPCODE_FCOE_LINK_DIAG_STATE,
req_len, LPFC_SLI4_MBX_EMBED);
- if (alloc_len != req_len)
+ if (alloc_len != req_len) {
+ rc = -ENOMEM;
goto link_diag_test_exit;
+ }
run_link_diag_test = &pmboxq->u.mqe.un.link_diag_test;
bf_set(lpfc_mbx_run_diag_test_link_num, &run_link_diag_test->u.req,
@@ -2498,13 +2494,12 @@
diag_status_reply = (struct diag_status *)
bsg_reply->reply_data.vendor_reply.vendor_rsp;
- if (job->reply_len <
- sizeof(struct fc_bsg_request) + sizeof(struct diag_status)) {
+ if (job->reply_len < sizeof(*bsg_reply) + sizeof(*diag_status_reply)) {
lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
"3012 Received Run link diag test reply "
"below minimum size (%d): reply_len:%d\n",
- (int)(sizeof(struct fc_bsg_request) +
- sizeof(struct diag_status)),
+ (int)(sizeof(*bsg_reply) +
+ sizeof(*diag_status_reply)),
job->reply_len);
rc = -EINVAL;
goto job_error;
@@ -2515,7 +2510,7 @@
diag_status_reply->shdr_add_status = shdr_add_status;
link_diag_test_exit:
- rc = lpfc_sli4_bsg_set_link_diag_state(phba, 0);
+ rc1 = lpfc_sli4_bsg_set_link_diag_state(phba, 0);
if (pmboxq)
mempool_free(pmboxq, phba->mbox_mem_pool);
@@ -2524,6 +2519,8 @@
job_error:
/* make error code available to userspace */
+ if (rc1 && !rc)
+ rc = rc1;
bsg_reply->result = rc;
/* complete the job back to userspace if no error */
if (rc == 0)
@@ -3420,8 +3417,7 @@
event_reply = (struct get_mgmt_rev_reply *)
bsg_reply->reply_data.vendor_reply.vendor_rsp;
- if (job->reply_len <
- sizeof(struct fc_bsg_request) + sizeof(struct get_mgmt_rev_reply)) {
+ if (job->reply_len < sizeof(*bsg_reply) + sizeof(*event_reply)) {
lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
"2741 Received GET_DFC_REV reply below "
"minimum size\n");
@@ -4306,6 +4302,7 @@
case COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES:
case COMN_OPCODE_GET_CNTL_ATTRIBUTES:
case COMN_OPCODE_GET_PROFILE_CONFIG:
+ case COMN_OPCODE_SET_FEATURES:
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
"3106 Handled SLI_CONFIG "
"subsys_comn, opcode:x%x\n",
@@ -5203,8 +5200,8 @@
goto no_dd_data;
}
- if (job->reply_len <
- sizeof(struct fc_bsg_request) + sizeof(struct menlo_response)) {
+ if (job->reply_len < sizeof(*bsg_reply) +
+ sizeof(struct menlo_response)) {
lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
"2785 Received MENLO_CMD reply below "
"minimum size\n");
@@ -5360,9 +5357,7 @@
forced_reply = (struct forced_link_speed_support_reply *)
bsg_reply->reply_data.vendor_reply.vendor_rsp;
- if (job->reply_len <
- sizeof(struct fc_bsg_request) +
- sizeof(struct forced_link_speed_support_reply)) {
+ if (job->reply_len < sizeof(*bsg_reply) + sizeof(*forced_reply)) {
lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
"0049 Received FORCED_LINK_SPEED reply below "
"minimum size\n");
@@ -5438,10 +5433,12 @@
bsg_reply->reply_data.vendor_reply.vendor_rsp;
/* Current logging state */
- if (ras_fwlog->ras_active == true)
+ spin_lock_irq(&phba->hbalock);
+ if (ras_fwlog->state == ACTIVE)
ras_reply->state = LPFC_RASLOG_STATE_RUNNING;
else
ras_reply->state = LPFC_RASLOG_STATE_STOPPED;
+ spin_unlock_irq(&phba->hbalock);
ras_reply->log_level = phba->ras_fwlog.fw_loglevel;
ras_reply->log_buff_sz = phba->cfg_ras_fwlog_buffsize;
@@ -5498,10 +5495,13 @@
if (action == LPFC_RASACTION_STOP_LOGGING) {
/* Check if already disabled */
- if (ras_fwlog->ras_active == false) {
+ spin_lock_irq(&phba->hbalock);
+ if (ras_fwlog->state != ACTIVE) {
+ spin_unlock_irq(&phba->hbalock);
rc = -ESRCH;
goto ras_job_error;
}
+ spin_unlock_irq(&phba->hbalock);
/* Disable logging */
lpfc_ras_stop_fwlog(phba);
@@ -5512,8 +5512,10 @@
* FW-logging with new log-level. Return status
* "Logging already Running" to caller.
**/
- if (ras_fwlog->ras_active)
+ spin_lock_irq(&phba->hbalock);
+ if (ras_fwlog->state != INACTIVE)
action_status = -EINPROGRESS;
+ spin_unlock_irq(&phba->hbalock);
/* Enable logging */
rc = lpfc_sli4_ras_fwlog_init(phba, log_level,
@@ -5629,10 +5631,13 @@
goto ras_job_error;
/* Logging to be stopped before reading */
- if (ras_fwlog->ras_active == true) {
+ spin_lock_irq(&phba->hbalock);
+ if (ras_fwlog->state == ACTIVE) {
+ spin_unlock_irq(&phba->hbalock);
rc = -EINPROGRESS;
goto ras_job_error;
}
+ spin_unlock_irq(&phba->hbalock);
if (job->request_len <
sizeof(struct fc_bsg_request) +
@@ -5706,8 +5711,7 @@
event_reply = (struct lpfc_trunk_info *)
bsg_reply->reply_data.vendor_reply.vendor_rsp;
- if (job->reply_len <
- sizeof(struct fc_bsg_request) + sizeof(struct lpfc_trunk_info)) {
+ if (job->reply_len < sizeof(*bsg_reply) + sizeof(*event_reply)) {
lpfc_printf_log(phba, KERN_WARNING, LOG_LIBDFC,
"2728 Received GET TRUNK _INFO reply below "
"minimum size\n");
diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h
index d170813..2dc7124 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.h
+++ b/drivers/scsi/lpfc/lpfc_bsg.h
@@ -225,6 +225,10 @@
uint32_t reserved5;
};
+#define LPFC_CSF_BOOT_DEV 0x1D
+#define LPFC_CSF_QUERY 0
+#define LPFC_CSF_SAVE 1
+
struct lpfc_sli_config_emb0_subsys {
struct lpfc_sli_config_hdr sli_config_hdr;
#define LPFC_MBX_SLI_CONFIG_MAX_MSE 19
@@ -243,6 +247,15 @@
#define FCOE_OPCODE_ADD_FCF 0x09
#define FCOE_OPCODE_SET_DPORT_MODE 0x27
#define FCOE_OPCODE_GET_DPORT_RESULTS 0x28
+ uint32_t timeout; /* comn_set_feature timeout */
+ uint32_t request_length; /* comn_set_feature request len */
+ uint32_t version; /* comn_set_feature version */
+ uint32_t csf_feature; /* comn_set_feature feature */
+ uint32_t word69; /* comn_set_feature parameter len */
+ uint32_t word70; /* comn_set_feature parameter val0 */
+#define lpfc_emb0_subcmnd_csf_p0_SHIFT 0
+#define lpfc_emb0_subcmnd_csf_p0_MASK 0x3
+#define lpfc_emb0_subcmnd_csf_p0_WORD word70
};
struct lpfc_sli_config_emb1_subsys {
@@ -261,6 +274,7 @@
#define COMN_OPCODE_WRITE_OBJECT 0xAC
#define COMN_OPCODE_READ_OBJECT_LIST 0xAD
#define COMN_OPCODE_DELETE_OBJECT 0xAE
+#define COMN_OPCODE_SET_FEATURES 0xBF
#define COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES 0x79
#define COMN_OPCODE_GET_CNTL_ATTRIBUTES 0x20
uint32_t timeout;
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index bdb1f38..26f4a34 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -24,7 +24,6 @@
struct fc_rport;
struct fc_frame_header;
-struct lpfc_nvmet_rcv_ctx;
void lpfc_down_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_sli_read_link_ste(struct lpfc_hba *);
void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t, uint16_t);
@@ -137,9 +136,10 @@
int lpfc_issue_els_adisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
int lpfc_issue_els_logo(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
int lpfc_issue_els_npiv_logo(struct lpfc_vport *, struct lpfc_nodelist *);
-int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t);
+int lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry);
int lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry);
int lpfc_issue_fabric_reglogin(struct lpfc_vport *);
+int lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry);
int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
@@ -383,7 +383,7 @@
int lpfc_link_reset(struct lpfc_vport *vport);
/* Function prototypes. */
-int lpfc_check_pci_resettable(const struct lpfc_hba *phba);
+int lpfc_check_pci_resettable(struct lpfc_hba *phba);
const char* lpfc_info(struct Scsi_Host *);
int lpfc_scan_finished(struct Scsi_Host *, unsigned long);
@@ -400,9 +400,7 @@
extern struct device_attribute *lpfc_hba_attrs[];
extern struct device_attribute *lpfc_vport_attrs[];
extern struct scsi_host_template lpfc_template;
-extern struct scsi_host_template lpfc_template_no_hr;
extern struct scsi_host_template lpfc_template_nvme;
-extern struct scsi_host_template lpfc_vport_template;
extern struct fc_function_template lpfc_transport_functions;
extern struct fc_function_template lpfc_vport_transport_functions;
@@ -562,12 +560,16 @@
int lpfc_nvmet_create_targetport(struct lpfc_hba *phba);
int lpfc_nvmet_update_targetport(struct lpfc_hba *phba);
void lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba);
-void lpfc_nvmet_unsol_ls_event(struct lpfc_hba *phba,
- struct lpfc_sli_ring *pring, struct lpfc_iocbq *piocb);
+int lpfc_nvme_handle_lsreq(struct lpfc_hba *phba,
+ struct lpfc_async_xchg_ctx *axchg);
+int lpfc_nvmet_handle_lsreq(struct lpfc_hba *phba,
+ struct lpfc_async_xchg_ctx *axchg);
void lpfc_nvmet_unsol_fcp_event(struct lpfc_hba *phba, uint32_t idx,
struct rqb_dmabuf *nvmebuf, uint64_t isr_ts,
uint8_t cqflag);
void lpfc_nvme_mod_param_dep(struct lpfc_hba *phba);
+void lpfc_nvmet_invalidate_host(struct lpfc_hba *phba,
+ struct lpfc_nodelist *ndlp);
void lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba,
struct lpfc_iocbq *cmdiocb,
struct lpfc_wcqe_complete *abts_cmpl);
@@ -586,9 +588,11 @@
int);
void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *ncmd,
struct lpfc_sli4_hdw_queue *qp);
+void lpfc_io_ktime(struct lpfc_hba *phba, struct lpfc_io_buf *ncmd);
void lpfc_nvme_cmd_template(void);
void lpfc_nvmet_cmd_template(void);
void lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn);
+void lpfc_nvme_prep_abort_wqe(struct lpfc_iocbq *pwqeq, u16 xritag, u8 opt);
extern int lpfc_enable_nvmet_cnt;
extern unsigned long long lpfc_enable_nvmet[];
extern int lpfc_no_hba_reset_cnt;
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index e672fa9..a8bf4d0 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -44,7 +44,6 @@
#include "lpfc_disc.h"
#include "lpfc.h"
#include "lpfc_scsi.h"
-#include "lpfc_nvme.h"
#include "lpfc_logmsg.h"
#include "lpfc_crtn.h"
#include "lpfc_version.h"
@@ -301,7 +300,7 @@
return 0;
}
-/**
+/*
* lpfc_gen_req - Build and issue a GEN_REQUEST command to the SLI Layer
* @vport: pointer to a host virtual N_Port data structure.
* @bmp: Pointer to BPL for SLI command
@@ -388,6 +387,8 @@
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, geniocb, 0);
if (rc == IOCB_ERROR) {
+ geniocb->context_un.ndlp = NULL;
+ lpfc_nlp_put(ndlp);
lpfc_sli_release_iocbq(phba, geniocb);
return 1;
}
@@ -395,7 +396,7 @@
return 0;
}
-/**
+/*
* lpfc_ct_cmd - Build and issue a CT command
* @vport: pointer to a host virtual N_Port data structure.
* @inmp: Pointer to data buffer for response data.
@@ -714,7 +715,8 @@
/* This is a GID_FT completing so the gidft_inp counter was
* incremented before the GID_FT was issued to the wire.
*/
- vport->gidft_inp--;
+ if (vport->gidft_inp)
+ vport->gidft_inp--;
/*
* Skip processing the NS response
@@ -742,16 +744,19 @@
goto out;
/* CT command is being retried */
- vport->gidft_inp--;
rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
vport->fc_ns_retry, type);
if (rc == 0)
goto out;
+ else { /* Unable to send NS cmd */
+ if (vport->gidft_inp)
+ vport->gidft_inp--;
+ }
}
if (vport->fc_flag & FC_RSCN_MODE)
lpfc_els_flush_rscn(vport);
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0257 GID_FT Query error: 0x%x 0x%x\n",
irsp->ulpStatus, vport->fc_ns_retry);
} else {
@@ -762,9 +767,11 @@
cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"0208 NameServer Rsp Data: x%x x%x "
- "sz x%x\n",
+ "x%x x%x sz x%x\n",
vport->fc_flag,
CTreq->un.gid.Fc4Type,
+ vport->num_disc_nodes,
+ vport->gidft_inp,
irsp->un.genreq64.bdl.bdeSize);
lpfc_ns_rsp(vport,
@@ -810,7 +817,7 @@
} else {
/* NameServer Rsp Error */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0241 NameServer Rsp Error "
"Data: x%x x%x x%x x%x\n",
CTrsp->CommandResponse.bits.CmdRsp,
@@ -824,7 +831,8 @@
(uint32_t) CTrsp->ReasonCode,
(uint32_t) CTrsp->Explanation);
}
- vport->gidft_inp--;
+ if (vport->gidft_inp)
+ vport->gidft_inp--;
}
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
@@ -917,7 +925,8 @@
/* This is a GID_PT completing so the gidft_inp counter was
* incremented before the GID_PT was issued to the wire.
*/
- vport->gidft_inp--;
+ if (vport->gidft_inp)
+ vport->gidft_inp--;
/*
* Skip processing the NS response
@@ -941,16 +950,19 @@
vport->fc_ns_retry++;
/* CT command is being retried */
- vport->gidft_inp--;
rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_PT,
vport->fc_ns_retry, GID_PT_N_PORT);
if (rc == 0)
goto out;
+ else { /* Unable to send NS cmd */
+ if (vport->gidft_inp)
+ vport->gidft_inp--;
+ }
}
if (vport->fc_flag & FC_RSCN_MODE)
lpfc_els_flush_rscn(vport);
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"4103 GID_FT Query error: 0x%x 0x%x\n",
irsp->ulpStatus, vport->fc_ns_retry);
} else {
@@ -960,9 +972,13 @@
if (CTrsp->CommandResponse.bits.CmdRsp ==
cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
- "4105 NameServer Rsp Data: x%x x%x\n",
+ "4105 NameServer Rsp Data: x%x x%x "
+ "x%x x%x sz x%x\n",
vport->fc_flag,
- CTreq->un.gid.Fc4Type);
+ CTreq->un.gid.Fc4Type,
+ vport->num_disc_nodes,
+ vport->gidft_inp,
+ irsp->un.genreq64.bdl.bdeSize);
lpfc_ns_rsp(vport,
outp,
@@ -1007,7 +1023,7 @@
}
} else {
/* NameServer Rsp Error */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"4109 NameServer Rsp Error "
"Data: x%x x%x x%x x%x\n",
CTrsp->CommandResponse.bits.CmdRsp,
@@ -1022,8 +1038,14 @@
(uint32_t)CTrsp->ReasonCode,
(uint32_t)CTrsp->Explanation);
}
- vport->gidft_inp--;
+ if (vport->gidft_inp)
+ vport->gidft_inp--;
}
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "6450 GID_PT cmpl inp %d disc %d\n",
+ vport->gidft_inp, vport->num_disc_nodes);
+
/* Link up / RSCN discovery */
if ((vport->num_disc_nodes == 0) &&
(vport->gidft_inp == 0)) {
@@ -1133,7 +1155,7 @@
}
}
}
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0267 NameServer GFF Rsp "
"x%x Error (%d %d) Data: x%x x%x\n",
did, irsp->ulpStatus, irsp->un.ulpWord[4],
@@ -1158,6 +1180,11 @@
/* Link up / RSCN discovery */
if (vport->num_disc_nodes)
vport->num_disc_nodes--;
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "6451 GFF_ID cmpl inp %d disc %d\n",
+ vport->gidft_inp, vport->num_disc_nodes);
+
if (vport->num_disc_nodes == 0) {
/*
* The driver has cycled through all Nports in the RSCN payload.
@@ -1256,7 +1283,7 @@
}
}
} else
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"3065 GFT_ID failed x%08x\n", irsp->ulpStatus);
lpfc_ct_free_iocb(phba, cmdiocb);
@@ -1305,7 +1332,7 @@
irsp->ulpStatus, irsp->un.ulpWord[4], cmdcode);
if (irsp->ulpStatus) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0268 NS cmd x%x Error (x%x x%x)\n",
cmdcode, irsp->ulpStatus, irsp->un.ulpWord[4]);
@@ -1828,7 +1855,7 @@
ns_cmd_free_mp:
kfree(mp);
ns_cmd_exit:
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0266 Issue NameServer Req x%x err %d Data: x%x x%x\n",
cmdcode, rc, vport->fc_flag, vport->fc_rscn_id_cnt);
return 1;
@@ -2436,7 +2463,6 @@
ae = &ad->AttrValue;
memset(ae, 0, sizeof(*ae));
- ae->un.AttrTypes[3] = 0x02; /* Type 0x1 - ELS */
ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */
ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */
@@ -2754,7 +2780,6 @@
ae = &ad->AttrValue;
memset(ae, 0, sizeof(*ae));
- ae->un.AttrTypes[3] = 0x02; /* Type 0x1 - ELS */
ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */
ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */
@@ -3006,8 +3031,8 @@
* lpfc_fdmi_cmd - Build and send a FDMI cmd to the specified NPort
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: ndlp to send FDMI cmd to (if NULL use FDMI_DID)
- * cmdcode: FDMI command to send
- * mask: Mask of HBA or PORT Attributes to send
+ * @cmdcode: FDMI command to send
+ * @new_mask: Mask of HBA or PORT Attributes to send
*
* Builds and sends a FDMI command using the CT subsystem.
*/
@@ -3179,7 +3204,7 @@
case SLI_MGMT_GHAT:
case SLI_MGMT_GRPL:
rsp_size = FC_MAX_NS_RSP;
- /* fall through */
+ fallthrough;
case SLI_MGMT_DHBA:
case SLI_MGMT_DHAT:
pe = (struct lpfc_fdmi_port_entry *)&CtReq->un.PortID;
@@ -3192,7 +3217,7 @@
case SLI_MGMT_GPAT:
case SLI_MGMT_GPAS:
rsp_size = FC_MAX_NS_RSP;
- /* fall through */
+ fallthrough;
case SLI_MGMT_DPRT:
case SLI_MGMT_DPA:
pe = (struct lpfc_fdmi_port_entry *)&CtReq->un.PortID;
@@ -3249,7 +3274,7 @@
/**
* lpfc_delayed_disc_tmo - Timeout handler for delayed discovery timer.
- * @ptr - Context object of the timer.
+ * @t: Context object of the timer.
*
* This function set the WORKER_DELAYED_DISC_TMO flag and wake up
* the worker thread.
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 3c9248d..beaf3a8 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -31,6 +31,7 @@
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/ctype.h>
+#include <linux/vmalloc.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
@@ -38,8 +39,6 @@
#include <scsi/scsi_transport_fc.h>
#include <scsi/fc/fc_fs.h>
-#include <linux/nvme-fc-driver.h>
-
#include "lpfc_hw4.h"
#include "lpfc_hw.h"
#include "lpfc_sli.h"
@@ -49,7 +48,6 @@
#include "lpfc.h"
#include "lpfc_scsi.h"
#include "lpfc_nvme.h"
-#include "lpfc_nvmet.h"
#include "lpfc_logmsg.h"
#include "lpfc_crtn.h"
#include "lpfc_vport.h"
@@ -1034,7 +1032,7 @@
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_nvmet_tgtport *tgtp;
- struct lpfc_nvmet_rcv_ctx *ctxp, *next_ctxp;
+ struct lpfc_async_xchg_ctx *ctxp, *next_ctxp;
struct nvme_fc_local_port *localport;
struct lpfc_fc4_ctrl_stat *cstat;
struct lpfc_nvme_lport *lport;
@@ -1299,8 +1297,88 @@
return len;
}
+void
+lpfc_io_ktime(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
+{
+ uint64_t seg1, seg2, seg3, seg4;
+ uint64_t segsum;
+
+ if (!lpfc_cmd->ts_last_cmd ||
+ !lpfc_cmd->ts_cmd_start ||
+ !lpfc_cmd->ts_cmd_wqput ||
+ !lpfc_cmd->ts_isr_cmpl ||
+ !lpfc_cmd->ts_data_io)
+ return;
+
+ if (lpfc_cmd->ts_data_io < lpfc_cmd->ts_cmd_start)
+ return;
+ if (lpfc_cmd->ts_cmd_start < lpfc_cmd->ts_last_cmd)
+ return;
+ if (lpfc_cmd->ts_cmd_wqput < lpfc_cmd->ts_cmd_start)
+ return;
+ if (lpfc_cmd->ts_isr_cmpl < lpfc_cmd->ts_cmd_wqput)
+ return;
+ if (lpfc_cmd->ts_data_io < lpfc_cmd->ts_isr_cmpl)
+ return;
+ /*
+ * Segment 1 - Time from Last FCP command cmpl is handed
+ * off to NVME Layer to start of next command.
+ * Segment 2 - Time from Driver receives a IO cmd start
+ * from NVME Layer to WQ put is done on IO cmd.
+ * Segment 3 - Time from Driver WQ put is done on IO cmd
+ * to MSI-X ISR for IO cmpl.
+ * Segment 4 - Time from MSI-X ISR for IO cmpl to when
+ * cmpl is handled off to the NVME Layer.
+ */
+ seg1 = lpfc_cmd->ts_cmd_start - lpfc_cmd->ts_last_cmd;
+ if (seg1 > 5000000) /* 5 ms - for sequential IOs only */
+ seg1 = 0;
+
+ /* Calculate times relative to start of IO */
+ seg2 = (lpfc_cmd->ts_cmd_wqput - lpfc_cmd->ts_cmd_start);
+ segsum = seg2;
+ seg3 = lpfc_cmd->ts_isr_cmpl - lpfc_cmd->ts_cmd_start;
+ if (segsum > seg3)
+ return;
+ seg3 -= segsum;
+ segsum += seg3;
+
+ seg4 = lpfc_cmd->ts_data_io - lpfc_cmd->ts_cmd_start;
+ if (segsum > seg4)
+ return;
+ seg4 -= segsum;
+
+ phba->ktime_data_samples++;
+ phba->ktime_seg1_total += seg1;
+ if (seg1 < phba->ktime_seg1_min)
+ phba->ktime_seg1_min = seg1;
+ else if (seg1 > phba->ktime_seg1_max)
+ phba->ktime_seg1_max = seg1;
+ phba->ktime_seg2_total += seg2;
+ if (seg2 < phba->ktime_seg2_min)
+ phba->ktime_seg2_min = seg2;
+ else if (seg2 > phba->ktime_seg2_max)
+ phba->ktime_seg2_max = seg2;
+ phba->ktime_seg3_total += seg3;
+ if (seg3 < phba->ktime_seg3_min)
+ phba->ktime_seg3_min = seg3;
+ else if (seg3 > phba->ktime_seg3_max)
+ phba->ktime_seg3_max = seg3;
+ phba->ktime_seg4_total += seg4;
+ if (seg4 < phba->ktime_seg4_min)
+ phba->ktime_seg4_min = seg4;
+ else if (seg4 > phba->ktime_seg4_max)
+ phba->ktime_seg4_max = seg4;
+
+ lpfc_cmd->ts_last_cmd = 0;
+ lpfc_cmd->ts_cmd_start = 0;
+ lpfc_cmd->ts_cmd_wqput = 0;
+ lpfc_cmd->ts_isr_cmpl = 0;
+ lpfc_cmd->ts_data_io = 0;
+}
+
/**
- * lpfc_debugfs_nvmektime_data - Dump target node list to a buffer
+ * lpfc_debugfs_ioktime_data - Dump target node list to a buffer
* @vport: The vport to gather target node info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
@@ -1313,13 +1391,13 @@
* not exceed @size.
**/
static int
-lpfc_debugfs_nvmektime_data(struct lpfc_vport *vport, char *buf, int size)
+lpfc_debugfs_ioktime_data(struct lpfc_vport *vport, char *buf, int size)
{
struct lpfc_hba *phba = vport->phba;
int len = 0;
if (phba->nvmet_support == 0) {
- /* NVME Initiator */
+ /* Initiator */
len += scnprintf(buf + len, PAGE_SIZE - len,
"ktime %s: Total Samples: %lld\n",
(phba->ktime_on ? "Enabled" : "Disabled"),
@@ -1329,8 +1407,8 @@
len += scnprintf(
buf + len, PAGE_SIZE - len,
- "Segment 1: Last NVME Cmd cmpl "
- "done -to- Start of next NVME cnd (in driver)\n");
+ "Segment 1: Last Cmd cmpl "
+ "done -to- Start of next Cmd (in driver)\n");
len += scnprintf(
buf + len, PAGE_SIZE - len,
"avg:%08lld min:%08lld max %08lld\n",
@@ -1340,7 +1418,7 @@
phba->ktime_seg1_max);
len += scnprintf(
buf + len, PAGE_SIZE - len,
- "Segment 2: Driver start of NVME cmd "
+ "Segment 2: Driver start of Cmd "
"-to- Firmware WQ doorbell\n");
len += scnprintf(
buf + len, PAGE_SIZE - len,
@@ -1363,7 +1441,7 @@
len += scnprintf(
buf + len, PAGE_SIZE - len,
"Segment 4: MSI-X ISR cmpl -to- "
- "NVME cmpl done\n");
+ "Cmd cmpl done\n");
len += scnprintf(
buf + len, PAGE_SIZE - len,
"avg:%08lld min:%08lld max %08lld\n",
@@ -1602,89 +1680,124 @@
}
/**
- * lpfc_debugfs_cpucheck_data - Dump target node list to a buffer
+ * lpfc_debugfs_hdwqstat_data - Dump I/O stats to a buffer
* @vport: The vport to gather target node info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
*
* Description:
- * This routine dumps the NVME statistics associated with @vport
+ * This routine dumps the NVME + SCSI statistics associated with @vport
*
* Return Value:
* This routine returns the amount of bytes that were dumped into @buf and will
* not exceed @size.
**/
static int
-lpfc_debugfs_cpucheck_data(struct lpfc_vport *vport, char *buf, int size)
+lpfc_debugfs_hdwqstat_data(struct lpfc_vport *vport, char *buf, int size)
{
struct lpfc_hba *phba = vport->phba;
- struct lpfc_sli4_hdw_queue *qp;
- int i, j, max_cnt;
- int len = 0;
+ struct lpfc_hdwq_stat *c_stat;
+ int i, j, len;
uint32_t tot_xmt;
uint32_t tot_rcv;
uint32_t tot_cmpl;
+ char tmp[LPFC_MAX_SCSI_INFO_TMP_LEN] = {0};
- len += scnprintf(buf + len, PAGE_SIZE - len,
- "CPUcheck %s ",
- (phba->cpucheck_on & LPFC_CHECK_NVME_IO ?
- "Enabled" : "Disabled"));
- if (phba->nvmet_support) {
- len += scnprintf(buf + len, PAGE_SIZE - len,
- "%s\n",
- (phba->cpucheck_on & LPFC_CHECK_NVMET_RCV ?
- "Rcv Enabled\n" : "Rcv Disabled\n"));
- } else {
- len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
- }
- max_cnt = size - LPFC_DEBUG_OUT_LINE_SZ;
+ scnprintf(tmp, sizeof(tmp), "HDWQ Stats:\n\n");
+ if (strlcat(buf, tmp, size) >= size)
+ goto buffer_done;
+
+ scnprintf(tmp, sizeof(tmp), "(NVME Accounting: %s) ",
+ (phba->hdwqstat_on &
+ (LPFC_CHECK_NVME_IO | LPFC_CHECK_NVMET_IO) ?
+ "Enabled" : "Disabled"));
+ if (strlcat(buf, tmp, size) >= size)
+ goto buffer_done;
+
+ scnprintf(tmp, sizeof(tmp), "(SCSI Accounting: %s) ",
+ (phba->hdwqstat_on & LPFC_CHECK_SCSI_IO ?
+ "Enabled" : "Disabled"));
+ if (strlcat(buf, tmp, size) >= size)
+ goto buffer_done;
+
+ scnprintf(tmp, sizeof(tmp), "\n\n");
+ if (strlcat(buf, tmp, size) >= size)
+ goto buffer_done;
for (i = 0; i < phba->cfg_hdw_queue; i++) {
- qp = &phba->sli4_hba.hdwq[i];
-
tot_rcv = 0;
tot_xmt = 0;
tot_cmpl = 0;
- for (j = 0; j < LPFC_CHECK_CPU_CNT; j++) {
- tot_xmt += qp->cpucheck_xmt_io[j];
- tot_cmpl += qp->cpucheck_cmpl_io[j];
+
+ for_each_present_cpu(j) {
+ c_stat = per_cpu_ptr(phba->sli4_hba.c_stat, j);
+
+ /* Only display for this HDWQ */
+ if (i != c_stat->hdwq_no)
+ continue;
+
+ /* Only display non-zero counters */
+ if (!c_stat->xmt_io && !c_stat->cmpl_io &&
+ !c_stat->rcv_io)
+ continue;
+
+ if (!tot_xmt && !tot_cmpl && !tot_rcv) {
+ /* Print HDWQ string only the first time */
+ scnprintf(tmp, sizeof(tmp), "[HDWQ %d]:\t", i);
+ if (strlcat(buf, tmp, size) >= size)
+ goto buffer_done;
+ }
+
+ tot_xmt += c_stat->xmt_io;
+ tot_cmpl += c_stat->cmpl_io;
if (phba->nvmet_support)
- tot_rcv += qp->cpucheck_rcv_io[j];
+ tot_rcv += c_stat->rcv_io;
+
+ scnprintf(tmp, sizeof(tmp), "| [CPU %d]: ", j);
+ if (strlcat(buf, tmp, size) >= size)
+ goto buffer_done;
+
+ if (phba->nvmet_support) {
+ scnprintf(tmp, sizeof(tmp),
+ "XMT 0x%x CMPL 0x%x RCV 0x%x |",
+ c_stat->xmt_io, c_stat->cmpl_io,
+ c_stat->rcv_io);
+ if (strlcat(buf, tmp, size) >= size)
+ goto buffer_done;
+ } else {
+ scnprintf(tmp, sizeof(tmp),
+ "XMT 0x%x CMPL 0x%x |",
+ c_stat->xmt_io, c_stat->cmpl_io);
+ if (strlcat(buf, tmp, size) >= size)
+ goto buffer_done;
+ }
}
- /* Only display Hardware Qs with something */
+ /* Check if nothing to display */
if (!tot_xmt && !tot_cmpl && !tot_rcv)
continue;
- len += scnprintf(buf + len, PAGE_SIZE - len,
- "HDWQ %03d: ", i);
- for (j = 0; j < LPFC_CHECK_CPU_CNT; j++) {
- /* Only display non-zero counters */
- if (!qp->cpucheck_xmt_io[j] &&
- !qp->cpucheck_cmpl_io[j] &&
- !qp->cpucheck_rcv_io[j])
- continue;
- if (phba->nvmet_support) {
- len += scnprintf(buf + len, PAGE_SIZE - len,
- "CPU %03d: %x/%x/%x ", j,
- qp->cpucheck_rcv_io[j],
- qp->cpucheck_xmt_io[j],
- qp->cpucheck_cmpl_io[j]);
- } else {
- len += scnprintf(buf + len, PAGE_SIZE - len,
- "CPU %03d: %x/%x ", j,
- qp->cpucheck_xmt_io[j],
- qp->cpucheck_cmpl_io[j]);
- }
- }
- len += scnprintf(buf + len, PAGE_SIZE - len,
- "Total: %x\n", tot_xmt);
- if (len >= max_cnt) {
- len += scnprintf(buf + len, PAGE_SIZE - len,
- "Truncated ...\n");
- return len;
+ scnprintf(tmp, sizeof(tmp), "\t->\t[HDWQ Total: ");
+ if (strlcat(buf, tmp, size) >= size)
+ goto buffer_done;
+
+ if (phba->nvmet_support) {
+ scnprintf(tmp, sizeof(tmp),
+ "XMT 0x%x CMPL 0x%x RCV 0x%x]\n\n",
+ tot_xmt, tot_cmpl, tot_rcv);
+ if (strlcat(buf, tmp, size) >= size)
+ goto buffer_done;
+ } else {
+ scnprintf(tmp, sizeof(tmp),
+ "XMT 0x%x CMPL 0x%x]\n\n",
+ tot_xmt, tot_cmpl);
+ if (strlcat(buf, tmp, size) >= size)
+ goto buffer_done;
}
}
+
+buffer_done:
+ len = strnlen(buf, size);
return len;
}
@@ -2047,10 +2160,6 @@
char *pbuf;
int i;
- /* Protect copy from user */
- if (!access_ok(buf, nbytes))
- return -EFAULT;
-
memset(mybuf, 0, sizeof(mybuf));
if (copy_from_user(mybuf, buf, nbytes))
@@ -2078,6 +2187,103 @@
}
#endif
+static int lpfc_debugfs_ras_log_data(struct lpfc_hba *phba,
+ char *buffer, int size)
+{
+ int copied = 0;
+ struct lpfc_dmabuf *dmabuf, *next;
+
+ memset(buffer, 0, size);
+
+ spin_lock_irq(&phba->hbalock);
+ if (phba->ras_fwlog.state != ACTIVE) {
+ spin_unlock_irq(&phba->hbalock);
+ return -EINVAL;
+ }
+ spin_unlock_irq(&phba->hbalock);
+
+ list_for_each_entry_safe(dmabuf, next,
+ &phba->ras_fwlog.fwlog_buff_list, list) {
+ /* Check if copying will go over size and a '\0' char */
+ if ((copied + LPFC_RAS_MAX_ENTRY_SIZE) >= (size - 1)) {
+ memcpy(buffer + copied, dmabuf->virt,
+ size - copied - 1);
+ copied += size - copied - 1;
+ break;
+ }
+ memcpy(buffer + copied, dmabuf->virt, LPFC_RAS_MAX_ENTRY_SIZE);
+ copied += LPFC_RAS_MAX_ENTRY_SIZE;
+ }
+ return copied;
+}
+
+static int
+lpfc_debugfs_ras_log_release(struct inode *inode, struct file *file)
+{
+ struct lpfc_debug *debug = file->private_data;
+
+ vfree(debug->buffer);
+ kfree(debug);
+
+ return 0;
+}
+
+/**
+ * lpfc_debugfs_ras_log_open - Open the RAS log debugfs buffer
+ * @inode: The inode pointer that contains a vport pointer.
+ * @file: The file pointer to attach the log output.
+ *
+ * Description:
+ * This routine is the entry point for the debugfs open file operation. It gets
+ * the vport from the i_private field in @inode, allocates the necessary buffer
+ * for the log, fills the buffer from the in-memory log for this vport, and then
+ * returns a pointer to that log in the private_data field in @file.
+ *
+ * Returns:
+ * This function returns zero if successful. On error it will return a negative
+ * error value.
+ **/
+static int
+lpfc_debugfs_ras_log_open(struct inode *inode, struct file *file)
+{
+ struct lpfc_hba *phba = inode->i_private;
+ struct lpfc_debug *debug;
+ int size;
+ int rc = -ENOMEM;
+
+ spin_lock_irq(&phba->hbalock);
+ if (phba->ras_fwlog.state != ACTIVE) {
+ spin_unlock_irq(&phba->hbalock);
+ rc = -EINVAL;
+ goto out;
+ }
+ spin_unlock_irq(&phba->hbalock);
+ debug = kmalloc(sizeof(*debug), GFP_KERNEL);
+ if (!debug)
+ goto out;
+
+ size = LPFC_RAS_MIN_BUFF_POST_SIZE * phba->cfg_ras_fwlog_buffsize;
+ debug->buffer = vmalloc(size);
+ if (!debug->buffer)
+ goto free_debug;
+
+ debug->len = lpfc_debugfs_ras_log_data(phba, debug->buffer, size);
+ if (debug->len < 0) {
+ rc = -EINVAL;
+ goto free_buffer;
+ }
+ file->private_data = debug;
+
+ return 0;
+
+free_buffer:
+ vfree(debug->buffer);
+free_debug:
+ kfree(debug);
+out:
+ return rc;
+}
+
/**
* lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer
* @inode: The inode pointer that contains a vport pointer.
@@ -2220,7 +2426,8 @@
return -EFAULT;
if (dent == phba->debug_InjErrLBA) {
- if ((buf[0] == 'o') && (buf[1] == 'f') && (buf[2] == 'f'))
+ if ((dstbuf[0] == 'o') && (dstbuf[1] == 'f') &&
+ (dstbuf[2] == 'f'))
tmp = (uint64_t)(-1);
}
@@ -2405,10 +2612,6 @@
if (nbytes > 64)
nbytes = 64;
- /* Protect copy from user */
- if (!access_ok(buf, nbytes))
- return -EFAULT;
-
memset(mybuf, 0, sizeof(mybuf));
if (copy_from_user(mybuf, buf, nbytes))
@@ -2571,10 +2774,6 @@
char mybuf[6] = {0};
int i;
- /* Protect copy from user */
- if (!access_ok(buf, nbytes))
- return -EFAULT;
-
if (copy_from_user(mybuf, buf, (nbytes >= sizeof(mybuf)) ?
(sizeof(mybuf) - 1) : nbytes))
return -EFAULT;
@@ -2591,7 +2790,7 @@
}
static int
-lpfc_debugfs_nvmektime_open(struct inode *inode, struct file *file)
+lpfc_debugfs_ioktime_open(struct inode *inode, struct file *file)
{
struct lpfc_vport *vport = inode->i_private;
struct lpfc_debug *debug;
@@ -2602,14 +2801,14 @@
goto out;
/* Round to page boundary */
- debug->buffer = kmalloc(LPFC_NVMEKTIME_SIZE, GFP_KERNEL);
+ debug->buffer = kmalloc(LPFC_IOKTIME_SIZE, GFP_KERNEL);
if (!debug->buffer) {
kfree(debug);
goto out;
}
- debug->len = lpfc_debugfs_nvmektime_data(vport, debug->buffer,
- LPFC_NVMEKTIME_SIZE);
+ debug->len = lpfc_debugfs_ioktime_data(vport, debug->buffer,
+ LPFC_IOKTIME_SIZE);
debug->i_private = inode->i_private;
file->private_data = debug;
@@ -2620,8 +2819,8 @@
}
static ssize_t
-lpfc_debugfs_nvmektime_write(struct file *file, const char __user *buf,
- size_t nbytes, loff_t *ppos)
+lpfc_debugfs_ioktime_write(struct file *file, const char __user *buf,
+ size_t nbytes, loff_t *ppos)
{
struct lpfc_debug *debug = file->private_data;
struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private;
@@ -2757,8 +2956,8 @@
char mybuf[64];
char *pbuf;
- if (nbytes > 64)
- nbytes = 64;
+ if (nbytes > 63)
+ nbytes = 63;
memset(mybuf, 0, sizeof(mybuf));
@@ -2823,7 +3022,7 @@
}
static int
-lpfc_debugfs_cpucheck_open(struct inode *inode, struct file *file)
+lpfc_debugfs_hdwqstat_open(struct inode *inode, struct file *file)
{
struct lpfc_vport *vport = inode->i_private;
struct lpfc_debug *debug;
@@ -2834,14 +3033,14 @@
goto out;
/* Round to page boundary */
- debug->buffer = kmalloc(LPFC_CPUCHECK_SIZE, GFP_KERNEL);
+ debug->buffer = kcalloc(1, LPFC_SCSISTAT_SIZE, GFP_KERNEL);
if (!debug->buffer) {
kfree(debug);
goto out;
}
- debug->len = lpfc_debugfs_cpucheck_data(vport, debug->buffer,
- LPFC_CPUCHECK_SIZE);
+ debug->len = lpfc_debugfs_hdwqstat_data(vport, debug->buffer,
+ LPFC_SCSISTAT_SIZE);
debug->i_private = inode->i_private;
file->private_data = debug;
@@ -2852,16 +3051,16 @@
}
static ssize_t
-lpfc_debugfs_cpucheck_write(struct file *file, const char __user *buf,
+lpfc_debugfs_hdwqstat_write(struct file *file, const char __user *buf,
size_t nbytes, loff_t *ppos)
{
struct lpfc_debug *debug = file->private_data;
struct lpfc_vport *vport = (struct lpfc_vport *)debug->i_private;
struct lpfc_hba *phba = vport->phba;
- struct lpfc_sli4_hdw_queue *qp;
+ struct lpfc_hdwq_stat *c_stat;
char mybuf[64];
char *pbuf;
- int i, j;
+ int i;
if (nbytes > 64)
nbytes = 64;
@@ -2874,41 +3073,39 @@
if ((strncmp(pbuf, "on", sizeof("on") - 1) == 0)) {
if (phba->nvmet_support)
- phba->cpucheck_on |= LPFC_CHECK_NVMET_IO;
+ phba->hdwqstat_on |= LPFC_CHECK_NVMET_IO;
else
- phba->cpucheck_on |= (LPFC_CHECK_NVME_IO |
+ phba->hdwqstat_on |= (LPFC_CHECK_NVME_IO |
LPFC_CHECK_SCSI_IO);
return strlen(pbuf);
} else if ((strncmp(pbuf, "nvme_on", sizeof("nvme_on") - 1) == 0)) {
if (phba->nvmet_support)
- phba->cpucheck_on |= LPFC_CHECK_NVMET_IO;
+ phba->hdwqstat_on |= LPFC_CHECK_NVMET_IO;
else
- phba->cpucheck_on |= LPFC_CHECK_NVME_IO;
+ phba->hdwqstat_on |= LPFC_CHECK_NVME_IO;
return strlen(pbuf);
} else if ((strncmp(pbuf, "scsi_on", sizeof("scsi_on") - 1) == 0)) {
- phba->cpucheck_on |= LPFC_CHECK_SCSI_IO;
+ if (!phba->nvmet_support)
+ phba->hdwqstat_on |= LPFC_CHECK_SCSI_IO;
return strlen(pbuf);
- } else if ((strncmp(pbuf, "rcv",
- sizeof("rcv") - 1) == 0)) {
- if (phba->nvmet_support)
- phba->cpucheck_on |= LPFC_CHECK_NVMET_RCV;
- else
- return -EINVAL;
+ } else if ((strncmp(pbuf, "nvme_off", sizeof("nvme_off") - 1) == 0)) {
+ phba->hdwqstat_on &= ~(LPFC_CHECK_NVME_IO |
+ LPFC_CHECK_NVMET_IO);
+ return strlen(pbuf);
+ } else if ((strncmp(pbuf, "scsi_off", sizeof("scsi_off") - 1) == 0)) {
+ phba->hdwqstat_on &= ~LPFC_CHECK_SCSI_IO;
return strlen(pbuf);
} else if ((strncmp(pbuf, "off",
sizeof("off") - 1) == 0)) {
- phba->cpucheck_on = LPFC_CHECK_OFF;
+ phba->hdwqstat_on = LPFC_CHECK_OFF;
return strlen(pbuf);
} else if ((strncmp(pbuf, "zero",
sizeof("zero") - 1) == 0)) {
- for (i = 0; i < phba->cfg_hdw_queue; i++) {
- qp = &phba->sli4_hba.hdwq[i];
-
- for (j = 0; j < LPFC_CHECK_CPU_CNT; j++) {
- qp->cpucheck_rcv_io[j] = 0;
- qp->cpucheck_xmt_io[j] = 0;
- qp->cpucheck_cmpl_io[j] = 0;
- }
+ for_each_present_cpu(i) {
+ c_stat = per_cpu_ptr(phba->sli4_hba.c_stat, i);
+ c_stat->xmt_io = 0;
+ c_stat->cmpl_io = 0;
+ c_stat->rcv_io = 0;
}
return strlen(pbuf);
}
@@ -5286,6 +5483,15 @@
};
#endif
+#undef lpfc_debugfs_ras_log
+static const struct file_operations lpfc_debugfs_ras_log = {
+ .owner = THIS_MODULE,
+ .open = lpfc_debugfs_ras_log_open,
+ .llseek = lpfc_debugfs_lseek,
+ .read = lpfc_debugfs_read,
+ .release = lpfc_debugfs_ras_log_release,
+};
+
#undef lpfc_debugfs_op_dumpHBASlim
static const struct file_operations lpfc_debugfs_op_dumpHBASlim = {
.owner = THIS_MODULE,
@@ -5324,13 +5530,13 @@
.release = lpfc_debugfs_release,
};
-#undef lpfc_debugfs_op_nvmektime
-static const struct file_operations lpfc_debugfs_op_nvmektime = {
+#undef lpfc_debugfs_op_ioktime
+static const struct file_operations lpfc_debugfs_op_ioktime = {
.owner = THIS_MODULE,
- .open = lpfc_debugfs_nvmektime_open,
+ .open = lpfc_debugfs_ioktime_open,
.llseek = lpfc_debugfs_lseek,
.read = lpfc_debugfs_read,
- .write = lpfc_debugfs_nvmektime_write,
+ .write = lpfc_debugfs_ioktime_write,
.release = lpfc_debugfs_release,
};
@@ -5344,13 +5550,13 @@
.release = lpfc_debugfs_release,
};
-#undef lpfc_debugfs_op_cpucheck
-static const struct file_operations lpfc_debugfs_op_cpucheck = {
+#undef lpfc_debugfs_op_hdwqstat
+static const struct file_operations lpfc_debugfs_op_hdwqstat = {
.owner = THIS_MODULE,
- .open = lpfc_debugfs_cpucheck_open,
+ .open = lpfc_debugfs_hdwqstat_open,
.llseek = lpfc_debugfs_lseek,
.read = lpfc_debugfs_read,
- .write = lpfc_debugfs_cpucheck_write,
+ .write = lpfc_debugfs_hdwqstat_write,
.release = lpfc_debugfs_release,
};
@@ -5456,7 +5662,6 @@
.write = lpfc_idiag_extacc_write,
.release = lpfc_idiag_cmd_release,
};
-
#endif
/* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command
@@ -5707,6 +5912,19 @@
goto debug_failed;
}
+ /* RAS log */
+ snprintf(name, sizeof(name), "ras_log");
+ phba->debug_ras_log =
+ debugfs_create_file(name, 0644,
+ phba->hba_debugfs_root,
+ phba, &lpfc_debugfs_ras_log);
+ if (!phba->debug_ras_log) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "6148 Cannot create debugfs"
+ " ras_log\n");
+ goto debug_failed;
+ }
+
/* Setup hbqinfo */
snprintf(name, sizeof(name), "hbqinfo");
phba->debug_hbqinfo =
@@ -5723,7 +5941,7 @@
phba, &lpfc_debugfs_op_lockstat);
if (!phba->debug_lockstat) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
- "4610 Cant create debugfs lockstat\n");
+ "4610 Can't create debugfs lockstat\n");
goto debug_failed;
}
#endif
@@ -5956,17 +6174,22 @@
goto debug_failed;
}
- snprintf(name, sizeof(name), "nvmektime");
- vport->debug_nvmektime =
+ snprintf(name, sizeof(name), "ioktime");
+ vport->debug_ioktime =
debugfs_create_file(name, 0644,
vport->vport_debugfs_root,
- vport, &lpfc_debugfs_op_nvmektime);
+ vport, &lpfc_debugfs_op_ioktime);
+ if (!vport->debug_ioktime) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ "0815 Cannot create debugfs ioktime\n");
+ goto debug_failed;
+ }
- snprintf(name, sizeof(name), "cpucheck");
- vport->debug_cpucheck =
+ snprintf(name, sizeof(name), "hdwqstat");
+ vport->debug_hdwqstat =
debugfs_create_file(name, 0644,
vport->vport_debugfs_root,
- vport, &lpfc_debugfs_op_cpucheck);
+ vport, &lpfc_debugfs_op_hdwqstat);
/*
* The following section is for additional directories/files for the
@@ -6097,11 +6320,11 @@
debugfs_remove(vport->debug_scsistat); /* scsistat */
vport->debug_scsistat = NULL;
- debugfs_remove(vport->debug_nvmektime); /* nvmektime */
- vport->debug_nvmektime = NULL;
+ debugfs_remove(vport->debug_ioktime); /* ioktime */
+ vport->debug_ioktime = NULL;
- debugfs_remove(vport->debug_cpucheck); /* cpucheck */
- vport->debug_cpucheck = NULL;
+ debugfs_remove(vport->debug_hdwqstat); /* hdwqstat */
+ vport->debug_hdwqstat = NULL;
if (vport->vport_debugfs_root) {
debugfs_remove(vport->vport_debugfs_root); /* vportX */
@@ -6117,6 +6340,9 @@
debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */
phba->debug_hbqinfo = NULL;
+ debugfs_remove(phba->debug_ras_log);
+ phba->debug_ras_log = NULL;
+
#ifdef LPFC_HDWQ_LOCK_STAT
debugfs_remove(phba->debug_lockstat); /* lockstat */
phba->debug_lockstat = NULL;
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
index 20f2537..7ab6d3b 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.h
+++ b/drivers/scsi/lpfc/lpfc_debugfs.h
@@ -46,8 +46,7 @@
/* nvmestat output buffer size */
#define LPFC_NVMESTAT_SIZE 8192
-#define LPFC_NVMEKTIME_SIZE 8192
-#define LPFC_CPUCHECK_SIZE 8192
+#define LPFC_IOKTIME_SIZE 8192
#define LPFC_NVMEIO_TRC_SIZE 8192
/* scsistat output buffer size */
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 482e4a8..1437e44 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -41,6 +41,7 @@
LPFC_EVT_DEV_LOSS,
LPFC_EVT_FASTPATH_MGMT_EVT,
LPFC_EVT_RESET_HBA,
+ LPFC_EVT_RECOVER_PORT
};
/* structure used to queue event to the discovery tasklet */
@@ -128,6 +129,7 @@
struct lpfc_vport *vport;
struct lpfc_work_evt els_retry_evt;
struct lpfc_work_evt dev_loss_evt;
+ struct lpfc_work_evt recovery_evt;
struct kref kref;
atomic_t cmd_pending;
uint32_t cmd_qdepth;
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 2040aff..387b0cd 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -100,7 +100,7 @@
return 0;
/* Pending Link Event during Discovery */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0237 Pending Link Event during "
"Discovery: State x%x\n",
phba->pport->port_state);
@@ -440,8 +440,9 @@
fail:
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
- "0249 Cannot issue Register Fabric login: Err %d\n", err);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "0249 Cannot issue Register Fabric login: Err %d\n",
+ err);
return -ENXIO;
}
@@ -524,8 +525,8 @@
}
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
- "0289 Issue Register VFI failed: Err %d\n", rc);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "0289 Issue Register VFI failed: Err %d\n", rc);
return rc;
}
@@ -550,7 +551,7 @@
mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mboxq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2556 UNREG_VFI mbox allocation failed"
"HBA state x%x\n", phba->pport->port_state);
return -ENOMEM;
@@ -562,7 +563,7 @@
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2557 UNREG_VFI issue mbox failed rc x%x "
"HBA state x%x\n",
rc, phba->pport->port_state);
@@ -1041,18 +1042,18 @@
if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT &&
((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) ==
IOERR_LOOP_OPEN_FAILURE)))
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
- "2858 FLOGI failure Status:x%x/x%x "
- "TMO:x%x Data x%x x%x\n",
- irsp->ulpStatus, irsp->un.ulpWord[4],
- irsp->ulpTimeout, phba->hba_flag,
- phba->fcf.fcf_flag);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "2858 FLOGI failure Status:x%x/x%x TMO"
+ ":x%x Data x%x x%x\n",
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->ulpTimeout, phba->hba_flag,
+ phba->fcf.fcf_flag);
/* Check for retry */
if (lpfc_els_retry(phba, cmdiocb, rspiocb))
goto out;
- lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_TRACE_EVENT,
"0150 FLOGI failure Status:x%x/x%x "
"xri x%x TMO:x%x\n",
irsp->ulpStatus, irsp->un.ulpWord[4],
@@ -1066,7 +1067,8 @@
/* FLOGI failed, so there is no fabric */
spin_lock_irq(shost->host_lock);
- vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+ vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP |
+ FC_PT2PT_NO_NVME);
spin_unlock_irq(shost->host_lock);
/* If private loop, then allow max outstanding els to be
@@ -1132,8 +1134,7 @@
else if (!(phba->hba_flag & HBA_FCOE_MODE))
rc = lpfc_cmpl_els_flogi_nport(vport, ndlp, sp);
else {
- lpfc_printf_vlog(vport, KERN_ERR,
- LOG_FIP | LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"2831 FLOGI response with cleared Fabric "
"bit fcf_index 0x%x "
"Switch Name %02x%02x%02x%02x%02x%02x%02x%02x "
@@ -1943,7 +1944,7 @@
ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || ndlp != rrq->ndlp) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"2882 RRQ completes to NPort x%x "
"with no ndlp. Data: x%x x%x x%x\n",
irsp->un.elsreq64.remoteID,
@@ -1966,10 +1967,11 @@
(((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) &&
((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) ||
(phba)->pport->cfg_log_verbose & LOG_ELS)
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
- "2881 RRQ failure DID:%06X Status:x%x/x%x\n",
- ndlp->nlp_DID, irsp->ulpStatus,
- irsp->un.ulpWord[4]);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "2881 RRQ failure DID:%06X Status:"
+ "x%x/x%x\n",
+ ndlp->nlp_DID, irsp->ulpStatus,
+ irsp->un.ulpWord[4]);
}
out:
if (rrq)
@@ -2019,7 +2021,7 @@
ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0136 PLOGI completes to NPort x%x "
"with no ndlp. Data: x%x x%x x%x\n",
irsp->un.elsreq64.remoteID,
@@ -2068,7 +2070,7 @@
(((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) &&
((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) ||
(phba)->pport->cfg_log_verbose & LOG_ELS)
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"2753 PLOGI failure DID:%06X Status:x%x/x%x\n",
ndlp->nlp_DID, irsp->ulpStatus,
irsp->un.ulpWord[4]);
@@ -2246,6 +2248,7 @@
IOCB_t *irsp;
struct lpfc_nodelist *ndlp;
char *mode;
+ u32 loglevel;
/* we pass cmdiocb to state machine which needs rspiocb as well */
cmdiocb->context_un.rsp_iocb = rspiocb;
@@ -2287,13 +2290,16 @@
* could be expected.
*/
if ((vport->fc_flag & FC_FABRIC) ||
- (vport->cfg_enable_fc4_type != LPFC_ENABLE_BOTH))
+ (vport->cfg_enable_fc4_type != LPFC_ENABLE_BOTH)) {
mode = KERN_ERR;
- else
+ loglevel = LOG_TRACE_EVENT;
+ } else {
mode = KERN_INFO;
+ loglevel = LOG_ELS;
+ }
/* PRLI failed */
- lpfc_printf_vlog(vport, mode, LOG_ELS,
+ lpfc_printf_vlog(vport, mode, loglevel,
"2754 PRLI failure DID:%06X Status:x%x/x%x, "
"data: x%x\n",
ndlp->nlp_DID, irsp->ulpStatus,
@@ -2704,7 +2710,7 @@
goto out;
}
/* ADISC failed */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"2755 ADISC failure DID:%06X Status:x%x/x%x\n",
ndlp->nlp_DID, irsp->ulpStatus,
irsp->un.ulpWord[4]);
@@ -2862,7 +2868,7 @@
*/
if (irsp->ulpStatus) {
/* LOGO failed */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"2756 LOGO failure, No Retry DID:%06X Status:x%x/x%x\n",
ndlp->nlp_DID, irsp->ulpStatus,
irsp->un.ulpWord[4]);
@@ -3017,10 +3023,9 @@
* This routine is a generic completion callback function for ELS commands.
* Specifically, it is the callback function which does not need to perform
* any command specific operations. It is currently used by the ELS command
- * issuing routines for the ELS State Change Request (SCR),
- * lpfc_issue_els_scr(), and the ELS Fibre Channel Address Resolution
- * Protocol Response (FARPR) routine, lpfc_issue_els_farpr(). Other than
- * certain debug loggings, this callback function simply invokes the
+ * issuing routines for RSCN, lpfc_issue_els_rscn, and the ELS Fibre Channel
+ * Address Resolution Protocol Response (FARPR) routine, lpfc_issue_els_farpr().
+ * Other than certain debug loggings, this callback function simply invokes the
* lpfc_els_chk_latt() routine to check whether link went down during the
* discovery process.
**/
@@ -3034,14 +3039,117 @@
irsp = &rspiocb->iocb;
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
- "ELS cmd cmpl: status:x%x/x%x did:x%x",
- irsp->ulpStatus, irsp->un.ulpWord[4],
- irsp->un.elsreq64.remoteID);
+ "ELS cmd cmpl: status:x%x/x%x did:x%x",
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->un.elsreq64.remoteID);
+
/* ELS cmd tag <ulpIoTag> completes */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n",
irsp->ulpIoTag, irsp->ulpStatus,
irsp->un.ulpWord[4], irsp->ulpTimeout);
+
+ /* Check to see if link went down during discovery */
+ lpfc_els_chk_latt(vport);
+ lpfc_els_free_iocb(phba, cmdiocb);
+}
+
+/**
+ * lpfc_cmpl_els_disc_cmd - Completion callback function for Discovery ELS cmd
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is a generic completion callback function for Discovery ELS cmd.
+ * Currently used by the ELS command issuing routines for the ELS State Change
+ * Request (SCR), lpfc_issue_els_scr() and the ELS RDF, lpfc_issue_els_rdf().
+ * These commands will be retried once only for ELS timeout errors.
+ **/
+static void
+lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ struct lpfc_iocbq *rspiocb)
+{
+ struct lpfc_vport *vport = cmdiocb->vport;
+ IOCB_t *irsp;
+ struct lpfc_els_rdf_rsp *prdf;
+ struct lpfc_dmabuf *pcmd, *prsp;
+ u32 *pdata;
+ u32 cmd;
+
+ irsp = &rspiocb->iocb;
+
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "ELS cmd cmpl: status:x%x/x%x did:x%x",
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->un.elsreq64.remoteID);
+ /* ELS cmd tag <ulpIoTag> completes */
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0217 ELS cmd tag x%x completes Data: x%x x%x x%x "
+ "x%x\n",
+ irsp->ulpIoTag, irsp->ulpStatus,
+ irsp->un.ulpWord[4], irsp->ulpTimeout,
+ cmdiocb->retry);
+
+ pcmd = (struct lpfc_dmabuf *)cmdiocb->context2;
+ if (!pcmd)
+ goto out;
+
+ pdata = (u32 *)pcmd->virt;
+ if (!pdata)
+ goto out;
+ cmd = *pdata;
+
+ /* Only 1 retry for ELS Timeout only */
+ if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT &&
+ ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) ==
+ IOERR_SEQUENCE_TIMEOUT)) {
+ cmdiocb->retry++;
+ if (cmdiocb->retry <= 1) {
+ switch (cmd) {
+ case ELS_CMD_SCR:
+ lpfc_issue_els_scr(vport, cmdiocb->retry);
+ break;
+ case ELS_CMD_RDF:
+ cmdiocb->context1 = NULL; /* save ndlp refcnt */
+ lpfc_issue_els_rdf(vport, cmdiocb->retry);
+ break;
+ }
+ goto out;
+ }
+ phba->fc_stat.elsRetryExceeded++;
+ }
+ if (irsp->ulpStatus) {
+ /* ELS discovery cmd completes with error */
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
+ "4203 ELS cmd x%x error: x%x x%X\n", cmd,
+ irsp->ulpStatus, irsp->un.ulpWord[4]);
+ goto out;
+ }
+
+ /* The RDF response doesn't have any impact on the running driver
+ * but the notification descriptors are dumped here for support.
+ */
+ if (cmd == ELS_CMD_RDF) {
+ int i;
+
+ prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
+ if (!prsp)
+ goto out;
+
+ prdf = (struct lpfc_els_rdf_rsp *)prsp->virt;
+ if (!prdf)
+ goto out;
+
+ for (i = 0; i < ELS_RDF_REG_TAG_CNT &&
+ i < be32_to_cpu(prdf->reg_d1.reg_desc.count); i++)
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "4677 Fabric RDF Notification Grant Data: "
+ "0x%08x\n",
+ be32_to_cpu(
+ prdf->reg_d1.desc_tags[i]));
+ }
+
+out:
/* Check to see if link went down during discovery */
lpfc_els_chk_latt(vport);
lpfc_els_free_iocb(phba, cmdiocb);
@@ -3051,11 +3159,10 @@
/**
* lpfc_issue_els_scr - Issue a scr to an node on a vport
* @vport: pointer to a host virtual N_Port data structure.
- * @nportid: N_Port identifier to the remote node.
- * @retry: number of retries to the command IOCB.
+ * @retry: retry counter for the command IOCB.
*
* This routine issues a State Change Request (SCR) to a fabric node
- * on a @vport. The remote node @nportid is passed into the function. It
+ * on a @vport. The remote node is Fabric Controller (0xfffffd). It
* first search the @vport node list to find the matching ndlp. If no such
* ndlp is found, a new ndlp shall be created for this (SCR) purpose. An
* IOCB is allocated, payload prepared, and the lpfc_sli_issue_iocb()
@@ -3071,7 +3178,7 @@
* 1 - Failed to issue scr command
**/
int
-lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
+lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
{
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *elsiocb;
@@ -3081,9 +3188,9 @@
cmdsize = (sizeof(uint32_t) + sizeof(SCR));
- ndlp = lpfc_findnode_did(vport, nportid);
+ ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID);
if (!ndlp) {
- ndlp = lpfc_nlp_init(vport, nportid);
+ ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID);
if (!ndlp)
return 1;
lpfc_enqueue_node(vport, ndlp);
@@ -3118,7 +3225,7 @@
ndlp->nlp_DID, 0, 0);
phba->fc_stat.elsXmitSCR++;
- elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
+ elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd;
if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) ==
IOCB_ERROR) {
/* The additional lpfc_nlp_put will cause the following
@@ -3348,6 +3455,105 @@
/* This will cause the callback-function lpfc_cmpl_els_cmd to
* trigger the release of the node.
*/
+ /* Don't release reference count as RDF is likely outstanding */
+ return 0;
+}
+
+/**
+ * lpfc_issue_els_rdf - Register for diagnostic functions from the fabric.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @retry: retry counter for the command IOCB.
+ *
+ * This routine issues an ELS RDF to the Fabric Controller to register
+ * for diagnostic functions.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the RDF ELS command.
+ *
+ * Return code
+ * 0 - Successfully issued rdf command
+ * 1 - Failed to issue rdf command
+ **/
+int
+lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
+{
+ struct lpfc_hba *phba = vport->phba;
+ struct lpfc_iocbq *elsiocb;
+ struct lpfc_els_rdf_req *prdf;
+ struct lpfc_nodelist *ndlp;
+ uint16_t cmdsize;
+
+ cmdsize = sizeof(*prdf);
+
+ ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID);
+ if (!ndlp) {
+ ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID);
+ if (!ndlp)
+ return -ENODEV;
+ lpfc_enqueue_node(vport, ndlp);
+ } else if (!NLP_CHK_NODE_ACT(ndlp)) {
+ ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
+ if (!ndlp)
+ return -ENODEV;
+ }
+
+ /* RDF ELS is not required on an NPIV VN_Port. */
+ if (vport->port_type == LPFC_NPIV_PORT) {
+ lpfc_nlp_put(ndlp);
+ return -EACCES;
+ }
+
+ elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
+ ndlp->nlp_DID, ELS_CMD_RDF);
+ if (!elsiocb) {
+ /* This will trigger the release of the node just
+ * allocated
+ */
+ lpfc_nlp_put(ndlp);
+ return -ENOMEM;
+ }
+
+ /* Configure the payload for the supported FPIN events. */
+ prdf = (struct lpfc_els_rdf_req *)
+ (((struct lpfc_dmabuf *)elsiocb->context2)->virt);
+ memset(prdf, 0, cmdsize);
+ prdf->rdf.fpin_cmd = ELS_RDF;
+ prdf->rdf.desc_len = cpu_to_be32(sizeof(struct lpfc_els_rdf_req) -
+ sizeof(struct fc_els_rdf));
+ prdf->reg_d1.reg_desc.desc_tag = cpu_to_be32(ELS_DTAG_FPIN_REGISTER);
+ prdf->reg_d1.reg_desc.desc_len = cpu_to_be32(
+ FC_TLV_DESC_LENGTH_FROM_SZ(prdf->reg_d1));
+ prdf->reg_d1.reg_desc.count = cpu_to_be32(ELS_RDF_REG_TAG_CNT);
+ prdf->reg_d1.desc_tags[0] = cpu_to_be32(ELS_DTAG_LNK_INTEGRITY);
+ prdf->reg_d1.desc_tags[1] = cpu_to_be32(ELS_DTAG_DELIVERY);
+ prdf->reg_d1.desc_tags[2] = cpu_to_be32(ELS_DTAG_PEER_CONGEST);
+ prdf->reg_d1.desc_tags[3] = cpu_to_be32(ELS_DTAG_CONGESTION);
+
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue RDF: did:x%x",
+ ndlp->nlp_DID, 0, 0);
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "6444 Xmit RDF to remote NPORT x%x\n",
+ ndlp->nlp_DID);
+
+ elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd;
+ if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) ==
+ IOCB_ERROR) {
+ /* The additional lpfc_nlp_put will cause the following
+ * lpfc_els_free_iocb routine to trigger the rlease of
+ * the node.
+ */
+ lpfc_nlp_put(ndlp);
+ lpfc_els_free_iocb(phba, elsiocb);
+ return -EIO;
+ }
+
+ /* An RDF was issued - this put ensures the ndlp is cleaned up
+ * when the RDF completes.
+ */
lpfc_nlp_put(ndlp);
return 0;
}
@@ -3409,7 +3615,7 @@
/**
* lpfc_els_retry_delay - Timer function with a ndlp delayed function timer
- * @ptr: holder for the pointer to the timer function associated data (ndlp).
+ * @t: pointer to the timer function associated data (ndlp).
*
* This routine is invoked by the ndlp delayed-function timer to check
* whether there is any pending ELS retry event(s) with the node. If not, it
@@ -3546,7 +3752,7 @@
"2851 Attempt link reset\n");
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2852 Failed to allocate mbox memory");
return 1;
}
@@ -3568,7 +3774,7 @@
mbox->vport = vport;
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2853 Failed to issue INIT_LINK "
"mbox command, rc:x%x\n", rc);
mempool_free(mbox, phba->mbox_mem_pool);
@@ -3672,7 +3878,7 @@
break;
case IOERR_ILLEGAL_COMMAND:
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0124 Retry illegal cmd x%x "
"retry:x%x delay:x%x\n",
cmd, cmdiocb->retry, delay);
@@ -3740,14 +3946,35 @@
/* Added for Vendor specifc support
* Just keep retrying for these Rsn / Exp codes
*/
+ if ((vport->fc_flag & FC_PT2PT) &&
+ cmd == ELS_CMD_NVMEPRLI) {
+ switch (stat.un.b.lsRjtRsnCode) {
+ case LSRJT_UNABLE_TPC:
+ case LSRJT_INVALID_CMD:
+ case LSRJT_LOGICAL_ERR:
+ case LSRJT_CMD_UNSUPPORTED:
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
+ "0168 NVME PRLI LS_RJT "
+ "reason %x port doesn't "
+ "support NVME, disabling NVME\n",
+ stat.un.b.lsRjtRsnCode);
+ retry = 0;
+ vport->fc_flag |= FC_PT2PT_NO_NVME;
+ goto out_retry;
+ }
+ }
switch (stat.un.b.lsRjtRsnCode) {
case LSRJT_UNABLE_TPC:
/* The driver has a VALID PLOGI but the rport has
* rejected the PRLI - can't do it now. Delay
- * for 1 second and try again - don't care about
- * the explanation.
+ * for 1 second and try again.
+ *
+ * However, if explanation is REQ_UNSUPPORTED there's
+ * no point to retry PRLI.
*/
- if (cmd == ELS_CMD_PRLI || cmd == ELS_CMD_NVMEPRLI) {
+ if ((cmd == ELS_CMD_PRLI || cmd == ELS_CMD_NVMEPRLI) &&
+ stat.un.b.lsRjtRsnCodeExp !=
+ LSEXP_REQ_UNSUPPORTED) {
delay = 1000;
maxretry = lpfc_max_els_tries + 1;
retry = 1;
@@ -3782,7 +4009,8 @@
if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
(cmd == ELS_CMD_FDISC) &&
(stat.un.b.lsRjtRsnCodeExp == LSEXP_OUT_OF_RESOURCE)){
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0125 FDISC Failed (x%x). "
"Fabric out of resources\n",
stat.un.lsRjtError);
@@ -3821,7 +4049,8 @@
LSEXP_NOTHING_MORE) {
vport->fc_sparam.cmn.bbRcvSizeMsb &= 0xf;
retry = 1;
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0820 FLOGI Failed (x%x). "
"BBCredit Not Supported\n",
stat.un.lsRjtError);
@@ -3834,7 +4063,8 @@
((stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_PNAME) ||
(stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_NPORT_ID))
) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0122 FDISC Failed (x%x). "
"Fabric Detected Bad WWN\n",
stat.un.lsRjtError);
@@ -4012,7 +4242,7 @@
}
/* No retry ELS command <elsCmd> to remote NPORT <did> */
if (logerr) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0137 No retry ELS command x%x to remote "
"NPORT x%x: Out of Resources: Error:x%x/%x\n",
cmd, did, irsp->ulpStatus,
@@ -4310,6 +4540,11 @@
irsp = &rspiocb->iocb;
+ if (!vport) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "3177 ELS response failed\n");
+ goto out;
+ }
if (cmdiocb->context_un.mbox)
mbox = cmdiocb->context_un.mbox;
@@ -4412,7 +4647,7 @@
ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
/* ELS rsp: Cannot issue reg_login for <NPortid> */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0138 ELS rsp: Cannot issue reg_login for x%x "
"Data: x%x x%x x%x\n",
ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
@@ -4652,7 +4887,7 @@
/**
* lpfc_els_rsp_reject - Propare and issue a rjt response iocb command
* @vport: pointer to a virtual N_Port data structure.
- * @rejectError:
+ * @rejectError: reject response to issue
* @oldiocb: pointer to the original lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
* @mbox: pointer to the driver internal queue element for mailbox command.
@@ -5281,6 +5516,11 @@
}
}
}
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "6452 Discover PLOGI %d flag x%x\n",
+ sentplogi, vport->fc_flag);
+
if (sentplogi) {
lpfc_set_disctmo(vport);
}
@@ -6215,8 +6455,8 @@
lcb_context->rx_id = cmdiocb->iocb.ulpContext;
lcb_context->ndlp = lpfc_nlp_get(ndlp);
if (lpfc_sli4_set_beacon(vport, lcb_context, state)) {
- lpfc_printf_vlog(ndlp->vport, KERN_ERR,
- LOG_ELS, "0193 failed to send mail box");
+ lpfc_printf_vlog(ndlp->vport, KERN_ERR, LOG_TRACE_EVENT,
+ "0193 failed to send mail box");
kfree(lcb_context);
lpfc_nlp_put(ndlp);
rjt_err = LSRJT_UNABLE_TPC;
@@ -6425,7 +6665,7 @@
rscn_event_data = kmalloc(sizeof(struct lpfc_rscn_event_header) +
payload_len, GFP_KERNEL);
if (!rscn_event_data) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0147 Failed to allocate memory for RSCN event\n");
return;
}
@@ -6691,9 +6931,10 @@
/* RSCN processed */
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
- "0215 RSCN processed Data: x%x x%x x%x x%x\n",
+ "0215 RSCN processed Data: x%x x%x x%x x%x x%x x%x\n",
vport->fc_flag, 0, vport->fc_rscn_id_cnt,
- vport->port_state);
+ vport->port_state, vport->num_disc_nodes,
+ vport->gidft_inp);
/* To process RSCN, first compare RSCN data with NameServer */
vport->fc_ns_retry = 0;
@@ -6801,7 +7042,7 @@
/* An FLOGI ELS command <elsCmd> was received from DID <did> in
Loop Mode */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0113 An FLOGI ELS command x%x was "
"received from DID x%x in Loop Mode\n",
cmd, did);
@@ -7135,108 +7376,12 @@
}
/**
- * lpfc_els_rsp_rps_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd
- * @phba: pointer to lpfc hba data structure.
- * @pmb: pointer to the driver internal queue element for mailbox command.
- *
- * This routine is the completion callback function for the MBX_READ_LNK_STAT
- * mailbox command. This callback function is to actually send the Accept
- * (ACC) response to a Read Port Status (RPS) unsolicited IOCB event. It
- * collects the link statistics from the completion of the MBX_READ_LNK_STAT
- * mailbox command, constructs the RPS response with the link statistics
- * collected, and then invokes the lpfc_sli_issue_iocb() routine to send ACC
- * response to the RPS.
- *
- * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
- * will be incremented by 1 for holding the ndlp and the reference to ndlp
- * will be stored into the context1 field of the IOCB for the completion
- * callback function to the RPS Accept Response ELS IOCB command.
- *
- **/
-static void
-lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
-{
- MAILBOX_t *mb;
- IOCB_t *icmd;
- RPS_RSP *rps_rsp;
- uint8_t *pcmd;
- struct lpfc_iocbq *elsiocb;
- struct lpfc_nodelist *ndlp;
- uint16_t status;
- uint16_t oxid;
- uint16_t rxid;
- uint32_t cmdsize;
-
- mb = &pmb->u.mb;
-
- ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp;
- rxid = (uint16_t)((unsigned long)(pmb->ctx_buf) & 0xffff);
- oxid = (uint16_t)(((unsigned long)(pmb->ctx_buf) >> 16) & 0xffff);
- pmb->ctx_ndlp = NULL;
- pmb->ctx_buf = NULL;
-
- if (mb->mbxStatus) {
- mempool_free(pmb, phba->mbox_mem_pool);
- return;
- }
-
- cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t);
- mempool_free(pmb, phba->mbox_mem_pool);
- elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize,
- lpfc_max_els_tries, ndlp,
- ndlp->nlp_DID, ELS_CMD_ACC);
-
- /* Decrement the ndlp reference count from previous mbox command */
- lpfc_nlp_put(ndlp);
-
- if (!elsiocb)
- return;
-
- icmd = &elsiocb->iocb;
- icmd->ulpContext = rxid;
- icmd->unsli3.rcvsli3.ox_id = oxid;
-
- pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
- *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
- pcmd += sizeof(uint32_t); /* Skip past command */
- rps_rsp = (RPS_RSP *)pcmd;
-
- if (phba->fc_topology != LPFC_TOPOLOGY_LOOP)
- status = 0x10;
- else
- status = 0x8;
- if (phba->pport->fc_flag & FC_FABRIC)
- status |= 0x4;
-
- rps_rsp->rsvd1 = 0;
- rps_rsp->portStatus = cpu_to_be16(status);
- rps_rsp->linkFailureCnt = cpu_to_be32(mb->un.varRdLnk.linkFailureCnt);
- rps_rsp->lossSyncCnt = cpu_to_be32(mb->un.varRdLnk.lossSyncCnt);
- rps_rsp->lossSignalCnt = cpu_to_be32(mb->un.varRdLnk.lossSignalCnt);
- rps_rsp->primSeqErrCnt = cpu_to_be32(mb->un.varRdLnk.primSeqErrCnt);
- rps_rsp->invalidXmitWord = cpu_to_be32(mb->un.varRdLnk.invalidXmitWord);
- rps_rsp->crcCnt = cpu_to_be32(mb->un.varRdLnk.crcCnt);
- /* Xmit ELS RPS ACC response tag <ulpIoTag> */
- lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS,
- "0118 Xmit ELS RPS ACC response tag x%x xri x%x, "
- "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
- elsiocb->iotag, elsiocb->iocb.ulpContext,
- ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
- ndlp->nlp_rpi);
- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
- phba->fc_stat.elsXmitACC++;
- if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == IOCB_ERROR)
- lpfc_els_free_iocb(phba, elsiocb);
- return;
-}
-
-/**
* lpfc_els_rcv_rls - Process an unsolicited rls iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
- * This routine processes Read Port Status (RPL) IOCB received as an
+ * This routine processes Read Link Status (RLS) IOCB received as an
* ELS unsolicited event. It first checks the remote port state. If the
* remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE
* state, it invokes the lpfc_els_rsl_reject() routine to send the reject
@@ -7258,7 +7403,7 @@
if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
(ndlp->nlp_state != NLP_STE_MAPPED_NODE))
- /* reject the unsolicited RPS request and done with it */
+ /* reject the unsolicited RLS request and done with it */
goto reject_out;
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC);
@@ -7306,7 +7451,7 @@
* Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
* will be incremented by 1 for holding the ndlp and the reference to ndlp
* will be stored into the context1 field of the IOCB for the completion
- * callback function to the RPS Accept Response ELS IOCB command.
+ * callback function to the RTV Accept Response ELS IOCB command.
*
* Return codes
* 0 - Successfully processed rtv iocb (currently always return 0)
@@ -7325,7 +7470,7 @@
if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
(ndlp->nlp_state != NLP_STE_MAPPED_NODE))
- /* reject the unsolicited RPS request and done with it */
+ /* reject the unsolicited RTV request and done with it */
goto reject_out;
cmdsize = sizeof(struct RTV_RSP) + sizeof(uint32_t);
@@ -7378,84 +7523,7 @@
return 0;
}
-/* lpfc_els_rcv_rps - Process an unsolicited rps iocb
- * @vport: pointer to a host virtual N_Port data structure.
- * @cmdiocb: pointer to lpfc command iocb data structure.
- * @ndlp: pointer to a node-list data structure.
- *
- * This routine processes Read Port Status (RPS) IOCB received as an
- * ELS unsolicited event. It first checks the remote port state. If the
- * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE
- * state, it invokes the lpfc_els_rsp_reject() routine to send the reject
- * response. Otherwise, it issue the MBX_READ_LNK_STAT mailbox command
- * for reading the HBA link statistics. It is for the callback function,
- * lpfc_els_rsp_rps_acc(), set to the MBX_READ_LNK_STAT mailbox command
- * to actually sending out RPS Accept (ACC) response.
- *
- * Return codes
- * 0 - Successfully processed rps iocb (currently always return 0)
- **/
-static int
-lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
- struct lpfc_nodelist *ndlp)
-{
- struct lpfc_hba *phba = vport->phba;
- uint32_t *lp;
- uint8_t flag;
- LPFC_MBOXQ_t *mbox;
- struct lpfc_dmabuf *pcmd;
- RPS *rps;
- struct ls_rjt stat;
-
- if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
- (ndlp->nlp_state != NLP_STE_MAPPED_NODE))
- /* reject the unsolicited RPS request and done with it */
- goto reject_out;
-
- pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
- lp = (uint32_t *) pcmd->virt;
- flag = (be32_to_cpu(*lp++) & 0xf);
- rps = (RPS *) lp;
-
- if ((flag == 0) ||
- ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) ||
- ((flag == 2) && (memcmp(&rps->un.portName, &vport->fc_portname,
- sizeof(struct lpfc_name)) == 0))) {
-
- printk("Fix me....\n");
- dump_stack();
- mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC);
- if (mbox) {
- lpfc_read_lnk_stat(phba, mbox);
- mbox->ctx_buf = (void *)((unsigned long)
- ((cmdiocb->iocb.unsli3.rcvsli3.ox_id << 16) |
- cmdiocb->iocb.ulpContext)); /* rx_id */
- mbox->ctx_ndlp = lpfc_nlp_get(ndlp);
- mbox->vport = vport;
- mbox->mbox_cmpl = lpfc_els_rsp_rps_acc;
- if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
- != MBX_NOT_FINISHED)
- /* Mbox completion will send ELS Response */
- return 0;
- /* Decrement reference count used for the failed mbox
- * command.
- */
- lpfc_nlp_put(ndlp);
- mempool_free(mbox, phba->mbox_mem_pool);
- }
- }
-
-reject_out:
- /* issue rejection response */
- stat.un.b.lsRjtRsvd0 = 0;
- stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
- stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
- stat.un.b.vendorUnique = 0;
- lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
- return 0;
-}
-
-/* lpfc_issue_els_rrq - Process an unsolicited rps iocb
+/* lpfc_issue_els_rrq - Process an unsolicited rrq iocb
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @did: DID of the target.
@@ -7855,7 +7923,7 @@
/**
* lpfc_els_timeout - Handler funciton to the els timer
- * @ptr: holder for the timer function associated data.
+ * @t: timer context used to obtain the vport.
*
* This routine is invoked by the ELS timer after timeout. It posts the ELS
* timer timeout event by setting the WORKER_ELS_TMO bit to the work port
@@ -7912,19 +7980,13 @@
if (unlikely(!pring))
return;
- if ((phba->pport->load_flag & FC_UNLOADING))
+ if (phba->pport->load_flag & FC_UNLOADING)
return;
+
spin_lock_irq(&phba->hbalock);
if (phba->sli_rev == LPFC_SLI_REV4)
spin_lock(&pring->ring_lock);
- if ((phba->pport->load_flag & FC_UNLOADING)) {
- if (phba->sli_rev == LPFC_SLI_REV4)
- spin_unlock(&pring->ring_lock);
- spin_unlock_irq(&phba->hbalock);
- return;
- }
-
list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
cmd = &piocb->iocb;
@@ -7970,7 +8032,7 @@
list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) {
cmd = &piocb->iocb;
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0127 ELS timeout Data: x%x x%x x%x "
"x%x\n", els_command,
remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
@@ -8080,7 +8142,7 @@
spin_unlock_irqrestore(&phba->hbalock, iflags);
}
if (!list_empty(&abort_list))
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"3387 abort list for txq not empty\n");
INIT_LIST_HEAD(&abort_list);
@@ -8234,7 +8296,7 @@
* lpfc_send_els_event - Posts unsolicited els event
* @vport: Pointer to vport object.
* @ndlp: Pointer FC node object.
- * @cmd: ELS command code.
+ * @payload: ELS command code type.
*
* This function posts an event when there is an incoming
* unsolicited ELS command.
@@ -8251,7 +8313,7 @@
if (*payload == ELS_CMD_LOGO) {
logo_data = kmalloc(sizeof(struct lpfc_logo_event), GFP_KERNEL);
if (!logo_data) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0148 Failed to allocate memory "
"for LOGO event\n");
return;
@@ -8261,7 +8323,7 @@
els_data = kmalloc(sizeof(struct lpfc_els_event_header),
GFP_KERNEL);
if (!els_data) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0149 Failed to allocate memory "
"for ELS event\n");
return;
@@ -8310,6 +8372,90 @@
}
+DECLARE_ENUM2STR_LOOKUP(lpfc_get_tlv_dtag_nm, fc_ls_tlv_dtag,
+ FC_LS_TLV_DTAG_INIT);
+
+DECLARE_ENUM2STR_LOOKUP(lpfc_get_fpin_li_event_nm, fc_fpin_li_event_types,
+ FC_FPIN_LI_EVT_TYPES_INIT);
+
+/**
+ * lpfc_els_rcv_fpin_li - Process an FPIN Link Integrity Event.
+ * @vport: Pointer to vport object.
+ * @tlv: Pointer to the Link Integrity Notification Descriptor.
+ *
+ * This function processes a link integrity FPIN event by
+ * logging a message
+ **/
+static void
+lpfc_els_rcv_fpin_li(struct lpfc_vport *vport, struct fc_tlv_desc *tlv)
+{
+ struct fc_fn_li_desc *li = (struct fc_fn_li_desc *)tlv;
+ const char *li_evt_str;
+ u32 li_evt;
+
+ li_evt = be16_to_cpu(li->event_type);
+ li_evt_str = lpfc_get_fpin_li_event_nm(li_evt);
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "4680 FPIN Link Integrity %s (x%x) "
+ "Detecting PN x%016llx Attached PN x%016llx "
+ "Duration %d mSecs Count %d Port Cnt %d\n",
+ li_evt_str, li_evt,
+ be64_to_cpu(li->detecting_wwpn),
+ be64_to_cpu(li->attached_wwpn),
+ be32_to_cpu(li->event_threshold),
+ be32_to_cpu(li->event_count),
+ be32_to_cpu(li->pname_count));
+}
+
+static void
+lpfc_els_rcv_fpin(struct lpfc_vport *vport, struct fc_els_fpin *fpin,
+ u32 fpin_length)
+{
+ struct fc_tlv_desc *tlv;
+ const char *dtag_nm;
+ uint32_t desc_cnt = 0, bytes_remain;
+ u32 dtag;
+
+ /* FPINs handled only if we are in the right discovery state */
+ if (vport->port_state < LPFC_DISC_AUTH)
+ return;
+
+ /* make sure there is the full fpin header */
+ if (fpin_length < sizeof(struct fc_els_fpin))
+ return;
+
+ tlv = (struct fc_tlv_desc *)&fpin->fpin_desc[0];
+ bytes_remain = fpin_length - offsetof(struct fc_els_fpin, fpin_desc);
+ bytes_remain = min_t(u32, bytes_remain, be32_to_cpu(fpin->desc_len));
+
+ /* process each descriptor */
+ while (bytes_remain >= FC_TLV_DESC_HDR_SZ &&
+ bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) {
+
+ dtag = be32_to_cpu(tlv->desc_tag);
+ switch (dtag) {
+ case ELS_DTAG_LNK_INTEGRITY:
+ lpfc_els_rcv_fpin_li(vport, tlv);
+ break;
+ default:
+ dtag_nm = lpfc_get_tlv_dtag_nm(dtag);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "4678 skipped FPIN descriptor[%d]: "
+ "tag x%x (%s)\n",
+ desc_cnt, dtag, dtag_nm);
+ break;
+ }
+
+ desc_cnt++;
+ bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv);
+ tlv = fc_tlv_next_desc(tlv);
+ }
+
+ fc_host_fpin_rcv(lpfc_shost_from_vport(vport), fpin_length,
+ (char *)fpin);
+}
+
/**
* lpfc_els_unsol_buffer - Process an unsolicited event data buffer
* @phba: pointer to lpfc hba data structure.
@@ -8331,7 +8477,7 @@
struct Scsi_Host *shost;
struct lpfc_nodelist *ndlp;
struct ls_rjt stat;
- uint32_t *payload;
+ uint32_t *payload, payload_len;
uint32_t cmd, did, newnode;
uint8_t rjt_exp, rjt_err = 0, init_link = 0;
IOCB_t *icmd = &elsiocb->iocb;
@@ -8342,6 +8488,7 @@
newnode = 0;
payload = ((struct lpfc_dmabuf *)elsiocb->context2)->virt;
+ payload_len = elsiocb->iocb.unsli3.rcvsli3.acc_len;
cmd = *payload;
if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0)
lpfc_post_buffer(phba, pring, 1);
@@ -8634,16 +8781,6 @@
if (newnode)
lpfc_nlp_put(ndlp);
break;
- case ELS_CMD_RPS:
- lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
- "RCV RPS: did:x%x/ste:x%x flg:x%x",
- did, vport->port_state, ndlp->nlp_flag);
-
- phba->fc_stat.elsRcvRPS++;
- lpfc_els_rcv_rps(vport, elsiocb, ndlp);
- if (newnode)
- lpfc_nlp_put(ndlp);
- break;
case ELS_CMD_RPL:
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
"RCV RPL: did:x%x/ste:x%x flg:x%x",
@@ -8699,12 +8836,14 @@
rjt_exp = LSEXP_INVALID_OX_RX;
break;
case ELS_CMD_FPIN:
- /*
- * Received FPIN from fabric - pass it to the
- * transport FPIN handler.
- */
- fc_host_fpin_rcv(shost, elsiocb->iocb.unsli3.rcvsli3.acc_len,
- (char *)payload);
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+ "RCV FPIN: did:x%x/ste:x%x flg:x%x",
+ did, vport->port_state, ndlp->nlp_flag);
+
+ lpfc_els_rcv_fpin(vport, (struct fc_els_fpin *)payload,
+ payload_len);
+
+ /* There are no replies, so no rjt codes */
break;
default:
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
@@ -8716,7 +8855,7 @@
rjt_exp = LSEXP_NOTHING_MORE;
/* Unknown ELS command <elsCmd> received from NPORT <did> */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0115 Unknown ELS command x%x "
"received from NPORT x%x\n", cmd, did);
if (newnode)
@@ -8761,7 +8900,7 @@
dropit:
if (vport && !(vport->load_flag & FC_UNLOADING))
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0111 Dropping received ELS cmd "
"Data: x%x x%x x%x\n",
icmd->ulpStatus, icmd->un.ulpWord[4], icmd->ulpTimeout);
@@ -8911,7 +9050,7 @@
spin_lock_irq(shost->host_lock);
if (vport->fc_flag & FC_DISC_DELAYED) {
spin_unlock_irq(shost->host_lock);
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3334 Delay fc port discovery for %d seconds\n",
phba->fc_ratov);
mod_timer(&vport->delayed_disc_tmo,
@@ -8929,7 +9068,7 @@
return;
}
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0251 NameServer login: no memory\n");
return;
}
@@ -8941,7 +9080,7 @@
return;
}
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0348 NameServer login: node freed\n");
return;
}
@@ -8952,7 +9091,7 @@
if (lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0)) {
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0252 Cannot issue NameServer login\n");
return;
}
@@ -8989,7 +9128,7 @@
spin_unlock_irq(shost->host_lock);
if (mb->mbxStatus) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0915 Register VPI failed : Status: x%x"
" upd bit: x%x \n", mb->mbxStatus,
mb->un.varRegVpi.upd);
@@ -9019,15 +9158,15 @@
rc = lpfc_sli_issue_mbox(phba, pmb,
MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
- lpfc_printf_vlog(vport,
- KERN_ERR, LOG_MBOX,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"2732 Failed to issue INIT_VPI"
" mailbox command\n");
} else {
lpfc_nlp_put(ndlp);
return;
}
- /* fall through */
+ fallthrough;
default:
/* Try to recover from this error */
if (phba->sli_rev == LPFC_SLI_REV4)
@@ -9108,12 +9247,12 @@
lpfc_nlp_put(ndlp);
mempool_free(mbox, phba->mbox_mem_pool);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0253 Register VPI: Can't send mbox\n");
goto mbox_err_exit;
}
} else {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0254 Register VPI: no memory\n");
goto mbox_err_exit;
}
@@ -9275,7 +9414,7 @@
if (lpfc_els_retry(phba, cmdiocb, rspiocb))
goto out;
/* FDISC failed */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0126 FDISC failed. (x%x/x%x)\n",
irsp->ulpStatus, irsp->un.ulpWord[4]);
goto fdisc_failed;
@@ -9397,7 +9536,7 @@
ELS_CMD_FDISC);
if (!elsiocb) {
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0255 Issue FDISC: no IOCB\n");
return 1;
}
@@ -9451,7 +9590,7 @@
if (rc == IOCB_ERROR) {
lpfc_els_free_iocb(phba, elsiocb);
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0256 Issue FDISC: Cannot send IOCB\n");
return 1;
}
@@ -9571,7 +9710,7 @@
/**
* lpfc_fabric_block_timeout - Handler function to the fabric block timer
- * @ptr: holder for the timer function associated data.
+ * @t: timer context used to obtain the lpfc hba.
*
* This routine is invoked by the fabric iocb block timer after
* timeout. It posts the fabric iocb block timeout event by setting the
@@ -10032,8 +10171,7 @@
"rport in state 0x%x\n", ndlp->nlp_state);
return;
}
- lpfc_printf_log(phba, KERN_ERR,
- LOG_ELS | LOG_FCP_ERROR | LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3094 Start rport recovery on shost id 0x%x "
"fc_id 0x%06x vpi 0x%x rpi 0x%x state 0x%x "
"flags 0x%x\n",
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 0dc1d56..68ff233 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -36,8 +36,6 @@
#include <scsi/scsi_transport_fc.h>
#include <scsi/fc/fc_fs.h>
-#include <linux/nvme-fc-driver.h>
-
#include "lpfc_hw4.h"
#include "lpfc_hw.h"
#include "lpfc_nl.h"
@@ -158,17 +156,17 @@
return;
if (rport->port_name != wwn_to_u64(ndlp->nlp_portname.u.wwn))
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
- "6789 rport name %llx != node port name %llx",
- rport->port_name,
- wwn_to_u64(ndlp->nlp_portname.u.wwn));
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "6789 rport name %llx != node port name %llx",
+ rport->port_name,
+ wwn_to_u64(ndlp->nlp_portname.u.wwn));
evtp = &ndlp->dev_loss_evt;
if (!list_empty(&evtp->evt_listp)) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
- "6790 rport name %llx dev_loss_evt pending",
- rport->port_name);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "6790 rport name %llx dev_loss_evt pending",
+ rport->port_name);
return;
}
@@ -298,7 +296,7 @@
}
if (warn_on) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0203 Devloss timeout on "
"WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
"NPort x%06x Data: x%x x%x x%x\n",
@@ -307,7 +305,7 @@
ndlp->nlp_DID, ndlp->nlp_flag,
ndlp->nlp_state, ndlp->nlp_rpi);
} else {
- lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_TRACE_EVENT,
"0204 Devloss timeout on "
"WWPN %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
"NPort x%06x Data: x%x x%x x%x\n",
@@ -554,6 +552,15 @@
fcf_inuse,
nlp_did);
break;
+ case LPFC_EVT_RECOVER_PORT:
+ ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1);
+ lpfc_sli_abts_recover_port(ndlp->vport, ndlp);
+ free_evt = 0;
+ /* decrement the node reference count held for
+ * this queued work
+ */
+ lpfc_nlp_put(ndlp);
+ break;
case LPFC_EVT_ONLINE:
if (phba->link_state < LPFC_LINK_DOWN)
*(int *) (evtp->evt_arg1) = lpfc_online(phba);
@@ -628,10 +635,16 @@
if (phba->pci_dev_grp == LPFC_PCI_DEV_OC)
lpfc_sli4_post_async_mbox(phba);
- if (ha_copy & HA_ERATT)
+ if (ha_copy & HA_ERATT) {
/* Handle the error attention event */
lpfc_handle_eratt(phba);
+ if (phba->fw_dump_cmpl) {
+ complete(phba->fw_dump_cmpl);
+ phba->fw_dump_cmpl = NULL;
+ }
+ }
+
if (ha_copy & HA_MBATT)
lpfc_sli_handle_mb_event(phba);
@@ -758,7 +771,7 @@
|| kthread_should_stop()));
/* Signal wakeup shall terminate the worker thread */
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0433 Wakeup on signal: rc=x%x\n", rc);
break;
}
@@ -826,6 +839,12 @@
if ((phba->sli_rev < LPFC_SLI_REV4) &&
(!remove && ndlp->nlp_type & NLP_FABRIC))
continue;
+
+ /* Notify transport of connectivity loss to trigger cleanup. */
+ if (phba->nvmet_support &&
+ ndlp->nlp_state == NLP_STE_UNMAPPED_NODE)
+ lpfc_nvmet_invalidate_host(phba, ndlp);
+
lpfc_disc_state_machine(vport, ndlp, NULL,
remove
? NLP_EVT_DEVICE_RM
@@ -1089,7 +1108,7 @@
/* Check for error */
if ((mb->mbxStatus) && (mb->mbxStatus != 0x1601)) {
/* CLEAR_LA mbox error <mbxStatus> state <hba_state> */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0320 CLEAR_LA mbxStatus error x%x hba "
"state x%x\n",
mb->mbxStatus, vport->port_state);
@@ -1141,13 +1160,14 @@
struct lpfc_vport *vport = pmb->vport;
LPFC_MBOXQ_t *sparam_mb;
struct lpfc_dmabuf *sparam_mp;
+ u16 status = pmb->u.mb.mbxStatus;
int rc;
- if (pmb->u.mb.mbxStatus)
- goto out;
-
mempool_free(pmb, phba->mbox_mem_pool);
+ if (status)
+ goto out;
+
/* don't perform discovery for SLI4 loopback diagnostic test */
if ((phba->sli_rev == LPFC_SLI_REV4) &&
!(phba->hba_flag & HBA_FCOE_MODE) &&
@@ -1209,16 +1229,14 @@
return;
out:
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
- "0306 CONFIG_LINK mbxStatus error x%x "
- "HBA state x%x\n",
- pmb->u.mb.mbxStatus, vport->port_state);
-sparam_out:
- mempool_free(pmb, phba->mbox_mem_pool);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "0306 CONFIG_LINK mbxStatus error x%x HBA state x%x\n",
+ status, vport->port_state);
+sparam_out:
lpfc_linkdown(phba);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0200 CONFIG_LINK bad hba state x%x\n",
vport->port_state);
@@ -1228,7 +1246,7 @@
/**
* lpfc_sli4_clear_fcf_rr_bmask
- * @phba pointer to the struct lpfc_hba for this port.
+ * @phba: pointer to the struct lpfc_hba for this port.
* This fucnction resets the round robin bit mask and clears the
* fcf priority list. The list deletions are done while holding the
* hbalock. The ON_LIST flag and the FLOGI_FAILED flags are cleared
@@ -1254,10 +1272,10 @@
struct lpfc_vport *vport = mboxq->vport;
if (mboxq->u.mb.mbxStatus) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
- "2017 REG_FCFI mbxStatus error x%x "
- "HBA state x%x\n",
- mboxq->u.mb.mbxStatus, vport->port_state);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "2017 REG_FCFI mbxStatus error x%x "
+ "HBA state x%x\n", mboxq->u.mb.mbxStatus,
+ vport->port_state);
goto fail_out;
}
@@ -1327,7 +1345,7 @@
/**
* lpfc_sw_name_match - Check if the fcf switch name match.
- * @fab_name: pointer to fabric name.
+ * @sw_name: pointer to switch name.
* @new_fcf_record: pointer to fcf record.
*
* This routine compare the fcf record's switch name with provided
@@ -1390,14 +1408,14 @@
}
/**
- * lpfc_update_fcf_record - Update driver fcf record
* __lpfc_update_fcf_record_pri - update the lpfc_fcf_pri record.
* @phba: pointer to lpfc hba data structure.
* @fcf_index: Index for the lpfc_fcf_record.
* @new_fcf_record: pointer to hba fcf record.
*
* This routine updates the driver FCF priority record from the new HBA FCF
- * record. This routine is called with the host lock held.
+ * record. The hbalock is asserted held in the code path calling this
+ * routine.
**/
static void
__lpfc_update_fcf_record_pri(struct lpfc_hba *phba, uint16_t fcf_index,
@@ -1406,8 +1424,6 @@
{
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 */
@@ -1417,7 +1433,7 @@
/**
* lpfc_copy_fcf_record - Copy fcf information to lpfc_hba.
- * @fcf: pointer to driver fcf record.
+ * @fcf_rec: pointer to driver fcf record.
* @new_fcf_record: pointer to fcf record.
*
* This routine copies the FCF information from the FCF
@@ -1485,7 +1501,7 @@
*
* This routine updates the driver FCF record from the new HBA FCF record
* together with the address mode, vlan_id, and other informations. This
- * routine is called with the host lock held.
+ * routine is called with the hbalock held.
**/
static void
__lpfc_update_fcf_record(struct lpfc_hba *phba, struct lpfc_fcf_rec *fcf_rec,
@@ -1880,7 +1896,7 @@
*/
lpfc_sli4_mbx_sge_get(mboxq, 0, &sge);
if (unlikely(!mboxq->sge_array)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2524 Failed to get the non-embedded SGE "
"virtual address\n");
return NULL;
@@ -1896,11 +1912,12 @@
if (shdr_status || shdr_add_status) {
if (shdr_status == STATUS_FCF_TABLE_EMPTY ||
if_type == LPFC_SLI_INTF_IF_TYPE_2)
- lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"2726 READ_FCF_RECORD Indicates empty "
"FCF table.\n");
else
- lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2521 READ_FCF_RECORD mailbox failed "
"with status x%x add_status x%x, "
"mbx\n", shdr_status, shdr_add_status);
@@ -1984,7 +2001,7 @@
}
/**
- lpfc_sli4_fcf_record_match - testing new FCF record for matching existing FCF
+ * lpfc_sli4_fcf_record_match - testing new FCF record for matching existing FCF
* @phba: pointer to lpfc hba data structure.
* @fcf_rec: pointer to an existing FCF record.
* @new_fcf_record: pointer to a new FCF record.
@@ -2098,7 +2115,7 @@
/**
* lpfc_sli4_fcf_pri_list_del
* @phba: pointer to lpfc hba data structure.
- * @fcf_index the index of the fcf record to delete
+ * @fcf_index: the index of the fcf record to delete
* This routine checks the on list flag of the fcf_index to be deleted.
* If it is one the list then it is removed from the list, and the flag
* is cleared. This routine grab the hbalock before removing the fcf
@@ -2128,7 +2145,7 @@
/**
* lpfc_sli4_set_fcf_flogi_fail
* @phba: pointer to lpfc hba data structure.
- * @fcf_index the index of the fcf record to update
+ * @fcf_index: the index of the fcf record to update
* This routine acquires the hbalock and then set the LPFC_FCF_FLOGI_FAILED
* flag so the the round robin slection for the particular priority level
* will try a different fcf record that does not have this bit set.
@@ -2148,7 +2165,8 @@
/**
* lpfc_sli4_fcf_pri_list_add
* @phba: pointer to lpfc hba data structure.
- * @fcf_index the index of the fcf record to add
+ * @fcf_index: the index of the fcf record to add
+ * @new_fcf_record: pointer to a new FCF record.
* This routine checks the priority of the fcf_index to be added.
* If it is a lower priority than the current head of the fcf_pri list
* then it is added to the list in the right order.
@@ -2278,7 +2296,7 @@
new_fcf_record = lpfc_sli4_fcf_rec_mbox_parse(phba, mboxq,
&next_fcf_index);
if (!new_fcf_record) {
- lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2765 Mailbox command READ_FCF_RECORD "
"failed to retrieve a FCF record.\n");
/* Let next new FCF event trigger fast failover */
@@ -2322,7 +2340,8 @@
new_fcf_record, LPFC_FCOE_IGNORE_VID)) {
if (bf_get(lpfc_fcf_record_fcf_index, new_fcf_record) !=
phba->fcf.current_rec.fcf_indx) {
- lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"2862 FCF (x%x) matches property "
"of in-use FCF (x%x)\n",
bf_get(lpfc_fcf_record_fcf_index,
@@ -2392,7 +2411,7 @@
phba->pport->fc_flag);
goto out;
} else
- lpfc_printf_log(phba, KERN_ERR, LOG_FIP,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2863 New FCF (x%x) matches "
"property of in-use FCF (x%x)\n",
bf_get(lpfc_fcf_record_fcf_index,
@@ -2806,10 +2825,9 @@
(bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
LPFC_SLI_INTF_IF_TYPE_0) &&
mboxq->u.mb.mbxStatus != MBX_VFI_IN_USE) {
- lpfc_printf_vlog(vport, KERN_ERR,
- LOG_MBOX,
- "2891 Init VFI mailbox failed 0x%x\n",
- mboxq->u.mb.mbxStatus);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "2891 Init VFI mailbox failed 0x%x\n",
+ mboxq->u.mb.mbxStatus);
mempool_free(mboxq, phba->mbox_mem_pool);
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
return;
@@ -2837,7 +2855,7 @@
mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mboxq) {
lpfc_printf_vlog(vport, KERN_ERR,
- LOG_MBOX, "2892 Failed to allocate "
+ LOG_TRACE_EVENT, "2892 Failed to allocate "
"init_vfi mailbox\n");
return;
}
@@ -2845,8 +2863,8 @@
mboxq->mbox_cmpl = lpfc_init_vfi_cmpl;
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
- lpfc_printf_vlog(vport, KERN_ERR,
- LOG_MBOX, "2893 Failed to issue init_vfi mailbox\n");
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "2893 Failed to issue init_vfi mailbox\n");
mempool_free(mboxq, vport->phba->mbox_mem_pool);
}
}
@@ -2866,10 +2884,9 @@
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
if (mboxq->u.mb.mbxStatus) {
- lpfc_printf_vlog(vport, KERN_ERR,
- LOG_MBOX,
- "2609 Init VPI mailbox failed 0x%x\n",
- mboxq->u.mb.mbxStatus);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "2609 Init VPI mailbox failed 0x%x\n",
+ mboxq->u.mb.mbxStatus);
mempool_free(mboxq, phba->mbox_mem_pool);
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
return;
@@ -2883,7 +2900,7 @@
ndlp = lpfc_findnode_did(vport, Fabric_DID);
if (!ndlp)
lpfc_printf_vlog(vport, KERN_ERR,
- LOG_DISCOVERY,
+ LOG_TRACE_EVENT,
"2731 Cannot find fabric "
"controller node\n");
else
@@ -2896,7 +2913,7 @@
lpfc_initial_fdisc(vport);
else {
lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"2606 No NPIV Fabric support\n");
}
mempool_free(mboxq, phba->mbox_mem_pool);
@@ -2919,8 +2936,7 @@
if ((vport->port_type != LPFC_PHYSICAL_PORT) && (!vport->vpi)) {
vpi = lpfc_alloc_vpi(vport->phba);
if (!vpi) {
- lpfc_printf_vlog(vport, KERN_ERR,
- LOG_MBOX,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"3303 Failed to obtain vport vpi\n");
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
return;
@@ -2931,7 +2947,7 @@
mboxq = mempool_alloc(vport->phba->mbox_mem_pool, GFP_KERNEL);
if (!mboxq) {
lpfc_printf_vlog(vport, KERN_ERR,
- LOG_MBOX, "2607 Failed to allocate "
+ LOG_TRACE_EVENT, "2607 Failed to allocate "
"init_vpi mailbox\n");
return;
}
@@ -2940,8 +2956,8 @@
mboxq->mbox_cmpl = lpfc_init_vpi_cmpl;
rc = lpfc_sli_issue_mbox(vport->phba, mboxq, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
- lpfc_printf_vlog(vport, KERN_ERR,
- LOG_MBOX, "2608 Failed to issue init_vpi mailbox\n");
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "2608 Failed to issue init_vpi mailbox\n");
mempool_free(mboxq, vport->phba->mbox_mem_pool);
}
}
@@ -2985,7 +3001,7 @@
lpfc_vport_set_state(vports[i],
FC_VPORT_NO_FABRIC_SUPP);
lpfc_printf_vlog(vports[i], KERN_ERR,
- LOG_ELS,
+ LOG_TRACE_EVENT,
"0259 No NPIV "
"Fabric support\n");
}
@@ -3009,10 +3025,10 @@
(bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
LPFC_SLI_INTF_IF_TYPE_0) &&
mboxq->u.mb.mbxStatus != MBX_VFI_IN_USE) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
- "2018 REG_VFI mbxStatus error x%x "
- "HBA state x%x\n",
- mboxq->u.mb.mbxStatus, vport->port_state);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "2018 REG_VFI mbxStatus error x%x "
+ "HBA state x%x\n",
+ mboxq->u.mb.mbxStatus, vport->port_state);
if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
/* FLOGI failed, use loop map to make discovery list */
lpfc_disc_list_loopmap(vport);
@@ -3099,7 +3115,7 @@
/* Check for error */
if (mb->mbxStatus) {
/* READ_SPARAM mbox error <mbxStatus> state <hba_state> */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0319 READ_SPARAM mbxStatus error x%x "
"hba state x%x>\n",
mb->mbxStatus, vport->port_state);
@@ -3316,7 +3332,7 @@
GFP_KERNEL);
if (unlikely(!fcf_record)) {
lpfc_printf_log(phba, KERN_ERR,
- LOG_MBOX | LOG_SLI,
+ LOG_TRACE_EVENT,
"2554 Could not allocate memory for "
"fcf record\n");
rc = -ENODEV;
@@ -3328,7 +3344,7 @@
rc = lpfc_sli4_add_fcf_record(phba, fcf_record);
if (unlikely(rc)) {
lpfc_printf_log(phba, KERN_ERR,
- LOG_MBOX | LOG_SLI,
+ LOG_TRACE_EVENT,
"2013 Could not manually add FCF "
"record 0, status %d\n", rc);
rc = -ENODEV;
@@ -3370,7 +3386,7 @@
return;
out:
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0263 Discovery Mailbox error: state: 0x%x : x%px x%px\n",
vport->port_state, sparam_mbox, cfglink_mbox);
lpfc_issue_clear_la(phba, vport);
@@ -3504,8 +3520,8 @@
phba->pport->port_state, vport->fc_flag);
else if (attn_type == LPFC_ATT_UNEXP_WWPN)
lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
- "1313 Link Down UNEXP WWPN Event x%x received "
- "Data: x%x x%x x%x x%x x%x\n",
+ "1313 Link Down Unexpected FA WWPN Event x%x "
+ "received Data: x%x x%x x%x x%x x%x\n",
la->eventTag, phba->fc_eventTag,
phba->pport->port_state, vport->fc_flag,
bf_get(lpfc_mbx_read_top_mm, la),
@@ -3643,7 +3659,7 @@
break;
/* If VPI is busy, reset the HBA */
case 0x9700:
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"2798 Unreg_vpi failed vpi 0x%x, mb status = 0x%x\n",
vport->vpi, mb->mbxStatus);
if (!(phba->pport->load_flag & FC_UNLOADING))
@@ -3681,7 +3697,7 @@
mbox->mbox_cmpl = lpfc_mbx_cmpl_unreg_vpi;
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1800 Could not issue unreg_vpi\n");
mempool_free(mbox, phba->mbox_mem_pool);
vport->unreg_vpi_cmpl = VPORT_ERROR;
@@ -3768,7 +3784,7 @@
pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0542 lpfc_create_static_vport failed to"
" allocate mailbox memory\n");
return;
@@ -3778,7 +3794,7 @@
vport_info = kzalloc(sizeof(struct static_vport_info), GFP_KERNEL);
if (!vport_info) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0543 lpfc_create_static_vport failed to"
" allocate vport_info\n");
mempool_free(pmb, phba->mbox_mem_pool);
@@ -3839,11 +3855,12 @@
if ((le32_to_cpu(vport_info->signature) != VPORT_INFO_SIG) ||
((le32_to_cpu(vport_info->rev) & VPORT_INFO_REV_MASK)
!= VPORT_INFO_REV)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0545 lpfc_create_static_vport bad"
- " information header 0x%x 0x%x\n",
- le32_to_cpu(vport_info->signature),
- le32_to_cpu(vport_info->rev) & VPORT_INFO_REV_MASK);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0545 lpfc_create_static_vport bad"
+ " information header 0x%x 0x%x\n",
+ le32_to_cpu(vport_info->signature),
+ le32_to_cpu(vport_info->rev) &
+ VPORT_INFO_REV_MASK);
goto out;
}
@@ -3907,7 +3924,7 @@
pmb->ctx_buf = NULL;
if (mb->mbxStatus) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0258 Register Fabric login error: 0x%x\n",
mb->mbxStatus);
lpfc_mbuf_free(phba, mp->virt, mp->phys);
@@ -3980,7 +3997,8 @@
/* Cannot issue NameServer FCP Query, so finish up
* discovery
*/
- lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0604 %s FC TYPE %x %s\n",
"Failed to issue GID_FT to ",
FC_TYPE_FCP,
@@ -3996,7 +4014,8 @@
/* Cannot issue NameServer NVME Query, so finish up
* discovery
*/
- lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0605 %s FC_TYPE %x %s %d\n",
"Failed to issue GID_FT to ",
FC_TYPE_NVME,
@@ -4028,7 +4047,7 @@
/* Cannot issue NameServer FCP Query, so finish up
* discovery
*/
- lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0606 %s Port TYPE %x %s\n",
"Failed to issue GID_PT to ",
GID_PT_N_PORT,
@@ -4058,7 +4077,7 @@
vport->gidft_inp = 0;
if (mb->mbxStatus) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0260 Register NameServer error: 0x%x\n",
mb->mbxStatus);
@@ -4094,7 +4113,7 @@
ndlp->nlp_flag |= NLP_RPI_REGISTERED;
ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
- lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY,
"0003 rpi:%x DID:%x flg:%x %d map%x x%px\n",
ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag,
kref_read(&ndlp->kref),
@@ -4117,7 +4136,9 @@
FC_TYPE_NVME);
/* Issue SCR just before NameServer GID_FT Query */
- lpfc_issue_els_scr(vport, SCR_DID, 0);
+ lpfc_issue_els_scr(vport, 0);
+
+ lpfc_issue_els_rdf(vport, 0);
}
vport->fc_ns_retry = 0;
@@ -4368,7 +4389,7 @@
GFP_KERNEL);
if (!ndlp->lat_data)
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0286 lpfc_nlp_state_cleanup failed to "
"allocate statistical data buffer DID "
"0x%x\n", ndlp->nlp_DID);
@@ -4508,6 +4529,8 @@
INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp);
INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp);
timer_setup(&ndlp->nlp_delayfunc, lpfc_els_retry_delay, 0);
+ INIT_LIST_HEAD(&ndlp->recovery_evt.evt_listp);
+
ndlp->nlp_DID = did;
ndlp->vport = vport;
ndlp->phba = vport->phba;
@@ -4623,8 +4646,10 @@
return ndlp;
free_rpi:
- if (phba->sli_rev == LPFC_SLI_REV4)
+ if (phba->sli_rev == LPFC_SLI_REV4) {
lpfc_sli4_free_rpi(vport->phba, rpi);
+ ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
+ }
return NULL;
}
@@ -4747,15 +4772,14 @@
case CMD_GEN_REQUEST64_CR:
if (iocb->context_un.ndlp == ndlp)
return 1;
- /* fall through */
+ fallthrough;
case CMD_ELS_REQUEST64_CR:
if (icmd->un.elsreq64.remoteID == ndlp->nlp_DID)
return 1;
- /* fall through */
+ fallthrough;
case CMD_XMIT_ELS_RSP64_CX:
if (iocb->context1 == (uint8_t *) ndlp)
return 1;
- /* fall through */
}
} else if (pring->ringno == LPFC_FCP_RING) {
/* Skip match check if waiting to relogin to FCP target */
@@ -4883,6 +4907,7 @@
if (ndlp->nlp_flag & NLP_RELEASE_RPI) {
lpfc_sli4_free_rpi(vport->phba, ndlp->nlp_rpi);
ndlp->nlp_flag &= ~NLP_RELEASE_RPI;
+ ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
}
ndlp->nlp_flag &= ~NLP_UNREG_INP;
}
@@ -4946,7 +4971,8 @@
if (ndlp->nlp_flag & NLP_RPI_REGISTERED ||
ndlp->nlp_flag & NLP_REG_LOGIN_SEND) {
if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)
- lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
+ lpfc_printf_vlog(vport, KERN_INFO,
+ LOG_NODE | LOG_DISCOVERY,
"3366 RPI x%x needs to be "
"unregistered nlp_flag x%x "
"did x%x\n",
@@ -4957,7 +4983,8 @@
* no need to queue up another one.
*/
if (ndlp->nlp_flag & NLP_UNREG_INP) {
- lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_INFO,
+ LOG_NODE | LOG_DISCOVERY,
"1436 unreg_rpi SKIP UNREG x%x on "
"NPort x%x deferred x%x flg x%x "
"Data: x%px\n",
@@ -4987,7 +5014,8 @@
(!(vport->fc_flag & FC_OFFLINE_MODE)))
ndlp->nlp_flag |= NLP_UNREG_INP;
- lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_INFO,
+ LOG_NODE | LOG_DISCOVERY,
"1433 unreg_rpi UNREG x%x on "
"NPort x%x deferred flg x%x "
"Data:x%px\n",
@@ -4999,6 +5027,29 @@
mempool_free(mbox, phba->mbox_mem_pool);
acc_plogi = 1;
}
+ } else {
+ lpfc_printf_vlog(vport, KERN_INFO,
+ LOG_NODE | LOG_DISCOVERY,
+ "1444 Failed to allocate mempool "
+ "unreg_rpi UNREG x%x, "
+ "DID x%x, flag x%x, "
+ "ndlp x%px\n",
+ ndlp->nlp_rpi, ndlp->nlp_DID,
+ ndlp->nlp_flag, ndlp);
+
+ /* Because mempool_alloc failed, we
+ * will issue a LOGO here and keep the rpi alive if
+ * not unloading.
+ */
+ if (!(vport->load_flag & FC_UNLOADING)) {
+ ndlp->nlp_flag &= ~NLP_UNREG_INP;
+ lpfc_issue_els_logo(vport, ndlp, 0);
+ ndlp->nlp_prev_state = ndlp->nlp_state;
+ lpfc_nlp_set_state(vport, ndlp,
+ NLP_STE_NPR_NODE);
+ }
+
+ return 1;
}
lpfc_no_rpi(phba, ndlp);
out:
@@ -5031,8 +5082,8 @@
vports = lpfc_create_vport_work_array(phba);
if (!vports) {
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
- "2884 Vport array allocation failed \n");
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2884 Vport array allocation failed \n");
return;
}
for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
@@ -5075,9 +5126,10 @@
mempool_free(mbox, phba->mbox_mem_pool);
if ((rc == MBX_TIMEOUT) || (rc == MBX_NOT_FINISHED))
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT,
- "1836 Could not issue "
- "unreg_login(all_rpis) status %d\n", rc);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "1836 Could not issue "
+ "unreg_login(all_rpis) status %d\n",
+ rc);
}
}
@@ -5104,7 +5156,7 @@
mempool_free(mbox, phba->mbox_mem_pool);
if ((rc == MBX_TIMEOUT) || (rc == MBX_NOT_FINISHED))
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1815 Could not issue "
"unreg_did (default rpis) status %d\n",
rc);
@@ -5201,6 +5253,7 @@
list_del_init(&ndlp->els_retry_evt.evt_listp);
list_del_init(&ndlp->dev_loss_evt.evt_listp);
+ list_del_init(&ndlp->recovery_evt.evt_listp);
lpfc_cleanup_vports_rrqs(vport, ndlp);
if (phba->sli_rev == LPFC_SLI_REV4)
ndlp->nlp_flag |= NLP_RELEASE_RPI;
@@ -5243,8 +5296,10 @@
/* For this case we need to cleanup the default rpi
* allocated by the firmware.
*/
- lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE,
- "0005 rpi:%x DID:%x flg:%x %d map:%x x%px\n",
+ lpfc_printf_vlog(vport, KERN_INFO,
+ LOG_NODE | LOG_DISCOVERY,
+ "0005 Cleanup Default rpi:x%x DID:x%x flg:x%x "
+ "ref %d map:x%x ndlp x%px\n",
ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag,
kref_read(&ndlp->kref),
ndlp->nlp_usg_map, ndlp);
@@ -5281,8 +5336,9 @@
*/
lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE,
"0940 removed node x%px DID x%x "
- " rport not null x%px\n",
- ndlp, ndlp->nlp_DID, ndlp->rport);
+ "rpi %d rport not null x%px\n",
+ ndlp, ndlp->nlp_DID, ndlp->nlp_rpi,
+ ndlp->rport);
rport = ndlp->rport;
rdata = rport->dd_data;
rdata->pnode = NULL;
@@ -5440,6 +5496,13 @@
if (!ndlp)
return NULL;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "6453 Setup New Node 2B_DISC x%x "
+ "Data:x%x x%x x%x\n",
+ ndlp->nlp_DID, ndlp->nlp_flag,
+ ndlp->nlp_state, vport->fc_flag);
+
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
spin_unlock_irq(shost->host_lock);
@@ -5453,6 +5516,12 @@
"0014 Could not enable ndlp\n");
return NULL;
}
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "6454 Setup Enabled Node 2B_DISC x%x "
+ "Data:x%x x%x x%x\n",
+ ndlp->nlp_DID, ndlp->nlp_flag,
+ ndlp->nlp_state, vport->fc_flag);
+
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
spin_unlock_irq(shost->host_lock);
@@ -5472,6 +5541,12 @@
*/
lpfc_cancel_retry_delay_tmo(vport, ndlp);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "6455 Setup RSCN Node 2B_DISC x%x "
+ "Data:x%x x%x x%x\n",
+ ndlp->nlp_DID, ndlp->nlp_flag,
+ ndlp->nlp_state, vport->fc_flag);
+
/* NVME Target mode waits until rport is known to be
* impacted by the RSCN before it transitions. No
* active management - just go to NPR provided the
@@ -5494,9 +5569,21 @@
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
spin_unlock_irq(shost->host_lock);
- } else
+ } else {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "6456 Skip Setup RSCN Node x%x "
+ "Data:x%x x%x x%x\n",
+ ndlp->nlp_DID, ndlp->nlp_flag,
+ ndlp->nlp_state, vport->fc_flag);
ndlp = NULL;
+ }
} else {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "6457 Setup Active Node 2B_DISC x%x "
+ "Data:x%x x%x x%x\n",
+ ndlp->nlp_DID, ndlp->nlp_flag,
+ ndlp->nlp_state, vport->fc_flag);
+
/* If the initiator received a PLOGI from this NPort or if the
* initiator is already in the process of discovery on it,
* there's no need to try to discover it again.
@@ -5648,10 +5735,10 @@
/* Start Discovery state <hba_state> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
- "0202 Start Discovery hba state x%x "
- "Data: x%x x%x x%x\n",
+ "0202 Start Discovery port state x%x "
+ "flg x%x Data: x%x x%x x%x\n",
vport->port_state, vport->fc_flag, vport->fc_plogi_cnt,
- vport->fc_adisc_cnt);
+ vport->fc_adisc_cnt, vport->fc_npr_cnt);
/* First do ADISCs - if any */
num_sent = lpfc_els_disc_adisc(vport);
@@ -5891,7 +5978,8 @@
case LPFC_FLOGI:
/* port_state is identically LPFC_FLOGI while waiting for FLOGI cmpl */
/* Initial FLOGI timeout */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0222 Initial %s timeout\n",
vport->vpi ? "FDISC" : "FLOGI");
@@ -5909,7 +5997,8 @@
case LPFC_FABRIC_CFG_LINK:
/* hba_state is identically LPFC_FABRIC_CFG_LINK while waiting for
NameServer login */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0223 Timeout while waiting for "
"NameServer login\n");
/* Next look for NameServer ndlp */
@@ -5922,7 +6011,8 @@
case LPFC_NS_QRY:
/* Check for wait for NameServer Rsp timeout */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0224 NameServer Query timeout "
"Data: x%x x%x\n",
vport->fc_ns_retry, LPFC_MAX_NS_RETRY);
@@ -5955,7 +6045,8 @@
/* Setup and issue mailbox INITIALIZE LINK command */
initlinkmbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!initlinkmbox) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0206 Device Discovery "
"completion error\n");
phba->link_state = LPFC_HBA_ERROR;
@@ -5977,7 +6068,8 @@
case LPFC_DISC_AUTH:
/* Node Authentication timeout */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0227 Node Authentication timeout\n");
lpfc_disc_flush_list(vport);
@@ -5997,7 +6089,8 @@
case LPFC_VPORT_READY:
if (vport->fc_flag & FC_RSCN_MODE) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0231 RSCN timeout Data: x%x "
"x%x\n",
vport->fc_ns_retry, LPFC_MAX_NS_RETRY);
@@ -6011,7 +6104,8 @@
break;
default:
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0273 Unexpected discovery timeout, "
"vport State x%x\n", vport->port_state);
break;
@@ -6020,21 +6114,23 @@
switch (phba->link_state) {
case LPFC_CLEAR_LA:
/* CLEAR LA timeout */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0228 CLEAR LA timeout\n");
clrlaerr = 1;
break;
case LPFC_LINK_UP:
lpfc_issue_clear_la(phba, vport);
- /* fall through */
+ fallthrough;
case LPFC_LINK_UNKNOWN:
case LPFC_WARM_START:
case LPFC_INIT_START:
case LPFC_INIT_MBX_CMDS:
case LPFC_LINK_DOWN:
case LPFC_HBA_ERROR:
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0230 Unexpected timeout, hba link "
"state x%x\n", phba->link_state);
clrlaerr = 1;
@@ -6079,7 +6175,7 @@
ndlp->nlp_flag |= NLP_RPI_REGISTERED;
ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
- lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI,
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY,
"0004 rpi:%x DID:%x flg:%x %d map:%x x%px\n",
ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag,
kref_read(&ndlp->kref),
@@ -6225,9 +6321,9 @@
}
if (i >= phba->max_vpi) {
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "2936 Could not find Vport mapped "
- "to vpi %d\n", vpi);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2936 Could not find Vport mapped "
+ "to vpi %d\n", vpi);
return NULL;
}
}
@@ -6268,12 +6364,12 @@
INIT_LIST_HEAD(&ndlp->nlp_listp);
if (vport->phba->sli_rev == LPFC_SLI_REV4) {
ndlp->nlp_rpi = rpi;
- lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE,
- "0007 rpi:%x DID:%x flg:%x refcnt:%d "
- "map:%x x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID,
- ndlp->nlp_flag,
- kref_read(&ndlp->kref),
- ndlp->nlp_usg_map, ndlp);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY,
+ "0007 Init New ndlp x%px, rpi:x%x DID:%x "
+ "flg:x%x refcnt:%d map:x%x\n",
+ ndlp, ndlp->nlp_rpi, ndlp->nlp_DID,
+ ndlp->nlp_flag, kref_read(&ndlp->kref),
+ ndlp->nlp_usg_map);
ndlp->active_rrqs_xri_bitmap =
mempool_alloc(vport->phba->active_rrq_pool,
@@ -6502,7 +6598,8 @@
goto out;
} else if (ndlp->nlp_flag & NLP_RPI_REGISTERED) {
ret = 1;
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
+ lpfc_printf_log(phba, KERN_INFO,
+ LOG_NODE | LOG_DISCOVERY,
"2624 RPI %x DID %x flag %x "
"still logged in\n",
ndlp->nlp_rpi, ndlp->nlp_DID,
@@ -6530,10 +6627,10 @@
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
if (mboxq->u.mb.mbxStatus) {
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX,
- "2555 UNREG_VFI mbxStatus error x%x "
- "HBA state x%x\n",
- mboxq->u.mb.mbxStatus, vport->port_state);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2555 UNREG_VFI mbxStatus error x%x "
+ "HBA state x%x\n",
+ mboxq->u.mb.mbxStatus, vport->port_state);
}
spin_lock_irq(shost->host_lock);
phba->pport->fc_flag &= ~FC_VFI_REGISTERED;
@@ -6555,10 +6652,10 @@
struct lpfc_vport *vport = mboxq->vport;
if (mboxq->u.mb.mbxStatus) {
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX,
- "2550 UNREG_FCFI mbxStatus error x%x "
- "HBA state x%x\n",
- mboxq->u.mb.mbxStatus, vport->port_state);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2550 UNREG_FCFI mbxStatus error x%x "
+ "HBA state x%x\n",
+ mboxq->u.mb.mbxStatus, vport->port_state);
}
mempool_free(mboxq, phba->mbox_mem_pool);
return;
@@ -6647,7 +6744,7 @@
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox) {
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2551 UNREG_FCFI mbox allocation failed"
"HBA state x%x\n", phba->pport->port_state);
return -ENOMEM;
@@ -6658,7 +6755,7 @@
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2552 Unregister FCFI command failed rc x%x "
"HBA state x%x\n",
rc, phba->pport->port_state);
@@ -6682,7 +6779,7 @@
/* Preparation for unregistering fcf */
rc = lpfc_unregister_fcf_prep(phba);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2748 Failed to prepare for unregistering "
"HBA's FCF record: rc=%d\n", rc);
return;
@@ -6718,7 +6815,7 @@
spin_lock_irq(&phba->hbalock);
phba->fcf.fcf_flag &= ~FCF_INIT_DISC;
spin_unlock_irq(&phba->hbalock);
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2553 lpfc_unregister_unused_fcf failed "
"to read FCF record HBA state x%x\n",
phba->pport->port_state);
@@ -6740,7 +6837,7 @@
/* Preparation for unregistering fcf */
rc = lpfc_unregister_fcf_prep(phba);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2749 Failed to prepare for unregistering "
"HBA's FCF record: rc=%d\n", rc);
return;
@@ -6827,9 +6924,9 @@
conn_entry = kzalloc(sizeof(struct lpfc_fcf_conn_entry),
GFP_KERNEL);
if (!conn_entry) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2566 Failed to allocate connection"
- " table entry\n");
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2566 Failed to allocate connection"
+ " table entry\n");
return;
}
@@ -6973,7 +7070,7 @@
/* Check the region signature first */
if (memcmp(buff, LPFC_REGION23_SIGNATURE, 4)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2567 Config region 23 has bad signature\n");
return;
}
@@ -6982,8 +7079,8 @@
/* Check the data structure version */
if (buff[offset] != LPFC_REGION23_VERSION) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2568 Config region 23 has bad version\n");
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2568 Config region 23 has bad version\n");
return;
}
offset += 4;
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index b5642c8..c20034b 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -22,7 +22,7 @@
#define FDMI_DID 0xfffffaU
#define NameServer_DID 0xfffffcU
-#define SCR_DID 0xfffffdU
+#define Fabric_Cntl_DID 0xfffffdU
#define Fabric_DID 0xfffffeU
#define Bcast_DID 0xffffffU
#define Mask_DID 0xffffffU
@@ -588,6 +588,7 @@
#define ELS_CMD_RRQ 0x12000000
#define ELS_CMD_REC 0x13000000
#define ELS_CMD_RDP 0x18000000
+#define ELS_CMD_RDF 0x19000000
#define ELS_CMD_PRLI 0x20100014
#define ELS_CMD_NVMEPRLI 0x20140018
#define ELS_CMD_PRLO 0x21100014
@@ -597,7 +598,6 @@
#define ELS_CMD_ADISC 0x52000000
#define ELS_CMD_FARP 0x54000000
#define ELS_CMD_FARPR 0x55000000
-#define ELS_CMD_RPS 0x56000000
#define ELS_CMD_RPL 0x57000000
#define ELS_CMD_FAN 0x60000000
#define ELS_CMD_RSCN 0x61040000
@@ -630,6 +630,7 @@
#define ELS_CMD_RRQ 0x12
#define ELS_CMD_REC 0x13
#define ELS_CMD_RDP 0x18
+#define ELS_CMD_RDF 0x19
#define ELS_CMD_PRLI 0x14001020
#define ELS_CMD_NVMEPRLI 0x18001420
#define ELS_CMD_PRLO 0x14001021
@@ -639,7 +640,6 @@
#define ELS_CMD_ADISC 0x52
#define ELS_CMD_FARP 0x54
#define ELS_CMD_FARPR 0x55
-#define ELS_CMD_RPS 0x56
#define ELS_CMD_RPL 0x57
#define ELS_CMD_FAN 0x60
#define ELS_CMD_RSCN 0x0461
@@ -919,24 +919,6 @@
} un;
} __packed RNID;
-typedef struct _RPS { /* Structure is in Big Endian format */
- union {
- uint32_t portNum;
- struct lpfc_name portName;
- } un;
-} RPS;
-
-typedef struct _RPS_RSP { /* Structure is in Big Endian format */
- uint16_t rsvd1;
- uint16_t portStatus;
- uint32_t linkFailureCnt;
- uint32_t lossSyncCnt;
- uint32_t lossSignalCnt;
- uint32_t primSeqErrCnt;
- uint32_t invalidXmitWord;
- uint32_t crcCnt;
-} RPS_RSP;
-
struct RLS { /* Structure is in Big Endian format */
uint32_t rls;
#define rls_rsvd_SHIFT 24
@@ -3280,8 +3262,7 @@
#endif
#ifdef __BIG_ENDIAN_BITFIELD
- uint32_t rsvd1 : 19; /* Reserved */
- uint32_t cdss : 1; /* Configure Data Security SLI */
+ uint32_t rsvd1 : 20; /* Reserved */
uint32_t casabt : 1; /* Configure async abts status notice */
uint32_t rsvd2 : 2; /* Reserved */
uint32_t cbg : 1; /* Configure BlockGuard */
@@ -3305,12 +3286,10 @@
uint32_t cbg : 1; /* Configure BlockGuard */
uint32_t rsvd2 : 2; /* Reserved */
uint32_t casabt : 1; /* Configure async abts status notice */
- uint32_t cdss : 1; /* Configure Data Security SLI */
- uint32_t rsvd1 : 19; /* Reserved */
+ uint32_t rsvd1 : 20; /* Reserved */
#endif
#ifdef __BIG_ENDIAN_BITFIELD
- uint32_t rsvd3 : 19; /* Reserved */
- uint32_t gdss : 1; /* Configure Data Security SLI */
+ uint32_t rsvd3 : 20; /* Reserved */
uint32_t gasabt : 1; /* Grant async abts status notice */
uint32_t rsvd4 : 2; /* Reserved */
uint32_t gbg : 1; /* Grant BlockGuard */
@@ -3334,8 +3313,7 @@
uint32_t gbg : 1; /* Grant BlockGuard */
uint32_t rsvd4 : 2; /* Reserved */
uint32_t gasabt : 1; /* Grant async abts status notice */
- uint32_t gdss : 1; /* Configure Data Security SLI */
- uint32_t rsvd3 : 19; /* Reserved */
+ uint32_t rsvd3 : 20; /* Reserved */
#endif
#ifdef __BIG_ENDIAN_BITFIELD
@@ -3357,15 +3335,11 @@
uint32_t rsvd6; /* Reserved */
#ifdef __BIG_ENDIAN_BITFIELD
- uint32_t fips_rev : 3; /* FIPS Spec Revision */
- uint32_t fips_level : 4; /* FIPS Level */
- uint32_t sec_err : 9; /* security crypto error */
+ uint32_t rsvd7 : 16;
uint32_t max_vpi : 16; /* Max number of virt N-Ports */
#else /* __LITTLE_ENDIAN */
uint32_t max_vpi : 16; /* Max number of virt N-Ports */
- uint32_t sec_err : 9; /* security crypto error */
- uint32_t fips_level : 4; /* FIPS Level */
- uint32_t fips_rev : 3; /* FIPS Spec Revision */
+ uint32_t rsvd7 : 16;
#endif
} CONFIG_PORT_VAR;
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index b8a772f..47e832b 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -20,6 +20,8 @@
* included with this package. *
*******************************************************************/
+#include <uapi/scsi/fc/fc_els.h>
+
/* Macros to deal with bit fields. Each bit field must have 3 #defines
* associated with it (_SHIFT, _MASK, and _WORD).
* EG. For a bit field that is in the 7th bit of the "field4" field of a
@@ -211,7 +213,6 @@
#define LPFC_MAX_IMAX 5000000
#define LPFC_DEF_IMAX 0
-#define LPFC_IMAX_THRESHOLD 1000
#define LPFC_MAX_AUTO_EQ_DELAY 120
#define LPFC_EQ_DELAY_STEP 15
#define LPFC_EQD_ISR_TRIGGER 20000
@@ -650,6 +651,9 @@
#define lpfc_sliport_status_oti_SHIFT 29
#define lpfc_sliport_status_oti_MASK 0x1
#define lpfc_sliport_status_oti_WORD word0
+#define lpfc_sliport_status_dip_SHIFT 25
+#define lpfc_sliport_status_dip_MASK 0x1
+#define lpfc_sliport_status_dip_WORD word0
#define lpfc_sliport_status_rn_SHIFT 24
#define lpfc_sliport_status_rn_MASK 0x1
#define lpfc_sliport_status_rn_WORD word0
@@ -2321,6 +2325,7 @@
#define ADD_STATUS_OPERATION_ALREADY_ACTIVE 0x67
#define ADD_STATUS_FW_NOT_SUPPORTED 0xEB
#define ADD_STATUS_INVALID_REQUEST 0x4B
+#define ADD_STATUS_FW_DOWNLOAD_HW_DISABLED 0x58
struct lpfc_mbx_sli4_config {
struct mbox_header header;
@@ -2810,6 +2815,15 @@
#define lpfc_mbx_rd_conf_trunk_SHIFT 12
#define lpfc_mbx_rd_conf_trunk_MASK 0x0000000F
#define lpfc_mbx_rd_conf_trunk_WORD word2
+#define lpfc_mbx_rd_conf_pt_SHIFT 20
+#define lpfc_mbx_rd_conf_pt_MASK 0x00000003
+#define lpfc_mbx_rd_conf_pt_WORD word2
+#define lpfc_mbx_rd_conf_tf_SHIFT 22
+#define lpfc_mbx_rd_conf_tf_MASK 0x00000001
+#define lpfc_mbx_rd_conf_tf_WORD word2
+#define lpfc_mbx_rd_conf_ptv_SHIFT 23
+#define lpfc_mbx_rd_conf_ptv_MASK 0x00000001
+#define lpfc_mbx_rd_conf_ptv_WORD word2
#define lpfc_mbx_rd_conf_topology_SHIFT 24
#define lpfc_mbx_rd_conf_topology_MASK 0x000000FF
#define lpfc_mbx_rd_conf_topology_WORD word2
@@ -3309,6 +3323,9 @@
#define cfg_bv1s_SHIFT 10
#define cfg_bv1s_MASK 0x00000001
#define cfg_bv1s_WORD word19
+#define cfg_pvl_SHIFT 13
+#define cfg_pvl_MASK 0x00000001
+#define cfg_pvl_WORD word19
#define cfg_nsler_SHIFT 12
#define cfg_nsler_MASK 0x00000001
@@ -3347,7 +3364,8 @@
};
#define LPFC_SET_UE_RECOVERY 0x10
-#define LPFC_SET_MDS_DIAGS 0x11
+#define LPFC_SET_MDS_DIAGS 0x12
+#define LPFC_SET_DUAL_DUMP 0x1e
struct lpfc_mbx_set_feature {
struct mbox_header header;
uint32_t feature;
@@ -3356,12 +3374,21 @@
#define lpfc_mbx_set_feature_UER_SHIFT 0
#define lpfc_mbx_set_feature_UER_MASK 0x00000001
#define lpfc_mbx_set_feature_UER_WORD word6
-#define lpfc_mbx_set_feature_mds_SHIFT 0
+#define lpfc_mbx_set_feature_mds_SHIFT 2
#define lpfc_mbx_set_feature_mds_MASK 0x00000001
#define lpfc_mbx_set_feature_mds_WORD word6
#define lpfc_mbx_set_feature_mds_deep_loopbk_SHIFT 1
#define lpfc_mbx_set_feature_mds_deep_loopbk_MASK 0x00000001
#define lpfc_mbx_set_feature_mds_deep_loopbk_WORD word6
+#define lpfc_mbx_set_feature_dd_SHIFT 0
+#define lpfc_mbx_set_feature_dd_MASK 0x00000001
+#define lpfc_mbx_set_feature_dd_WORD word6
+#define lpfc_mbx_set_feature_ddquery_SHIFT 1
+#define lpfc_mbx_set_feature_ddquery_MASK 0x00000001
+#define lpfc_mbx_set_feature_ddquery_WORD word6
+#define LPFC_DISABLE_DUAL_DUMP 0
+#define LPFC_ENABLE_DUAL_DUMP 1
+#define LPFC_QUERY_OP_DUAL_DUMP 2
uint32_t word7;
#define lpfc_mbx_set_feature_UERP_SHIFT 0
#define lpfc_mbx_set_feature_UERP_MASK 0x0000ffff
@@ -3733,6 +3760,9 @@
#define LPFC_CHANGE_STATUS_FW_RESET 0x02
#define LPFC_CHANGE_STATUS_PORT_MIGRATION 0x04
#define LPFC_CHANGE_STATUS_PCI_RESET 0x05
+#define lpfc_wr_object_csf_SHIFT 8
+#define lpfc_wr_object_csf_MASK 0x00000001
+#define lpfc_wr_object_csf_WORD word5
} response;
} u;
};
@@ -4089,6 +4119,8 @@
#define LPFC_SLI_EVENT_TYPE_DIAG_DUMP 0x5
#define LPFC_SLI_EVENT_TYPE_MISCONFIGURED 0x9
#define LPFC_SLI_EVENT_TYPE_REMOTE_DPORT 0xA
+#define LPFC_SLI_EVENT_TYPE_MISCONF_FAWWN 0xF
+#define LPFC_SLI_EVENT_TYPE_EEPROM_FAILURE 0x10
};
/*
@@ -4487,6 +4519,7 @@
uint32_t rsvd_12_15[4]; /* word 12-15 */
};
+#define INHIBIT_ABORT 1
#define T_REQUEST_TAG 3
#define T_XRI_TAG 1
@@ -4595,6 +4628,23 @@
uint32_t fc_hdr_wd5; /* word 15 */
};
+#define ELS_RDF_REG_TAG_CNT 4
+struct lpfc_els_rdf_reg_desc {
+ struct fc_df_desc_fpin_reg reg_desc; /* descriptor header */
+ __be32 desc_tags[ELS_RDF_REG_TAG_CNT];
+ /* tags in reg_desc */
+};
+
+struct lpfc_els_rdf_req {
+ struct fc_els_rdf rdf; /* hdr up to descriptors */
+ struct lpfc_els_rdf_reg_desc reg_d1; /* 1st descriptor */
+};
+
+struct lpfc_els_rdf_rsp {
+ struct fc_els_rdf_resp rdf_resp; /* hdr up to descriptors */
+ struct lpfc_els_rdf_reg_desc reg_d1; /* 1st descriptor */
+};
+
union lpfc_wqe {
uint32_t words[16];
struct lpfc_wqe_generic generic;
@@ -4635,8 +4685,8 @@
struct send_frame_wqe send_frame;
};
-#define MAGIC_NUMER_G6 0xFEAA0003
-#define MAGIC_NUMER_G7 0xFEAA0005
+#define MAGIC_NUMBER_G6 0xFEAA0003
+#define MAGIC_NUMBER_G7 0xFEAA0005
struct lpfc_grp_hdr {
uint32_t size;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index b5cee2a..1149bfc 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -40,6 +40,7 @@
#include <linux/irq.h>
#include <linux/bitops.h>
#include <linux/crash_dump.h>
+#include <linux/cpu.h>
#include <linux/cpuhotplug.h>
#include <scsi/scsi.h>
@@ -49,8 +50,6 @@
#include <scsi/scsi_tcq.h>
#include <scsi/fc/fc_fs.h>
-#include <linux/nvme-fc-driver.h>
-
#include "lpfc_hw4.h"
#include "lpfc_hw.h"
#include "lpfc_sli.h"
@@ -60,7 +59,6 @@
#include "lpfc.h"
#include "lpfc_scsi.h"
#include "lpfc_nvme.h"
-#include "lpfc_nvmet.h"
#include "lpfc_logmsg.h"
#include "lpfc_crtn.h"
#include "lpfc_vport.h"
@@ -155,7 +153,7 @@
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
if (rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0324 Config Port initialization "
"error, mbxCmd x%x READ_NVPARM, "
"mbxStatus x%x\n",
@@ -179,7 +177,7 @@
lpfc_read_rev(phba, pmb);
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
if (rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0439 Adapter failed to init, mbxCmd x%x "
"READ_REV, mbxStatus x%x\n",
mb->mbxCommand, mb->mbxStatus);
@@ -194,7 +192,7 @@
*/
if (mb->un.varRdRev.rr == 0) {
vp->rev.rBit = 0;
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0440 Adapter failed to init, READ_REV has "
"missing revision information.\n");
mempool_free(pmb, phba->mbox_mem_pool);
@@ -255,13 +253,15 @@
*/
if (mb->un.varDmp.word_cnt == 0)
break;
- if (mb->un.varDmp.word_cnt > DMP_VPD_SIZE - offset)
- mb->un.varDmp.word_cnt = DMP_VPD_SIZE - offset;
+
+ i = mb->un.varDmp.word_cnt * sizeof(uint32_t);
+ if (offset + i > DMP_VPD_SIZE)
+ i = DMP_VPD_SIZE - offset;
lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
- lpfc_vpd_data + offset,
- mb->un.varDmp.word_cnt);
- offset += mb->un.varDmp.word_cnt;
- } while (mb->un.varDmp.word_cnt && offset < DMP_VPD_SIZE);
+ lpfc_vpd_data + offset, i);
+ offset += i;
+ } while (offset < DMP_VPD_SIZE);
+
lpfc_parse_vpd(phba, lpfc_vpd_data, offset);
kfree(lpfc_vpd_data);
@@ -444,7 +444,7 @@
pmb->vport = vport;
if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0448 Adapter failed init, mbxCmd x%x "
"READ_SPARM mbxStatus x%x\n",
mb->mbxCommand, mb->mbxStatus);
@@ -498,7 +498,7 @@
lpfc_read_config(phba, pmb);
pmb->vport = vport;
if (lpfc_sli_issue_mbox(phba, pmb, MBX_POLL) != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0453 Adapter failed to init, mbxCmd x%x "
"READ_CONFIG, mbxStatus x%x\n",
mb->mbxCommand, mb->mbxStatus);
@@ -511,21 +511,12 @@
lpfc_sli_read_link_ste(phba);
/* Reset the DFT_HBA_Q_DEPTH to the max xri */
- i = (mb->un.varRdConfig.max_xri + 1);
- if (phba->cfg_hba_queue_depth > i) {
+ if (phba->cfg_hba_queue_depth > mb->un.varRdConfig.max_xri) {
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
"3359 HBA queue depth changed from %d to %d\n",
- phba->cfg_hba_queue_depth, i);
- phba->cfg_hba_queue_depth = i;
- }
-
- /* Reset the DFT_LUN_Q_DEPTH to (max xri >> 3) */
- i = (mb->un.varRdConfig.max_xri >> 3);
- if (phba->pport->cfg_lun_queue_depth > i) {
- lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
- "3360 LUN queue depth changed from %d to %d\n",
- phba->pport->cfg_lun_queue_depth, i);
- phba->pport->cfg_lun_queue_depth = i;
+ phba->cfg_hba_queue_depth,
+ mb->un.varRdConfig.max_xri);
+ phba->cfg_hba_queue_depth = mb->un.varRdConfig.max_xri;
}
phba->lmt = mb->un.varRdConfig.lmt;
@@ -556,7 +547,7 @@
}
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
if (rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0352 Config MSI mailbox command "
"failed, mbxCmd x%x, mbxStatus x%x\n",
pmb->u.mb.mbxCommand,
@@ -607,17 +598,15 @@
jiffies + msecs_to_jiffies(1000 * phba->eratt_poll_interval));
if (phba->hba_flag & LINK_DISABLED) {
- lpfc_printf_log(phba,
- KERN_ERR, LOG_INIT,
- "2598 Adapter Link is disabled.\n");
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2598 Adapter Link is disabled.\n");
lpfc_down_link(phba, pmb);
pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
if ((rc != MBX_SUCCESS) && (rc != MBX_BUSY)) {
- lpfc_printf_log(phba,
- KERN_ERR, LOG_INIT,
- "2599 Adapter failed to issue DOWN_LINK"
- " mbox command rc 0x%x\n", rc);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2599 Adapter failed to issue DOWN_LINK"
+ " mbox command rc 0x%x\n", rc);
mempool_free(pmb, phba->mbox_mem_pool);
return -EIO;
@@ -641,9 +630,7 @@
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
- lpfc_printf_log(phba,
- KERN_ERR,
- LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0456 Adapter failed to issue "
"ASYNCEVT_ENABLE mbox status x%x\n",
rc);
@@ -663,7 +650,8 @@
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0435 Adapter failed "
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0435 Adapter failed "
"to get Option ROM version status x%x\n", rc);
mempool_free(pmb, phba->mbox_mem_pool);
}
@@ -741,10 +729,10 @@
((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_64G) &&
!(phba->lmt & LMT_64Gb))) {
/* Reset link speed to auto */
- lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
- "1302 Invalid speed for this board:%d "
- "Reset link speed to auto.\n",
- phba->cfg_link_speed);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "1302 Invalid speed for this board:%d "
+ "Reset link speed to auto.\n",
+ phba->cfg_link_speed);
phba->cfg_link_speed = LPFC_USER_LINK_SPEED_AUTO;
}
lpfc_init_link(phba, pmb, fc_topology, phba->cfg_link_speed);
@@ -753,10 +741,10 @@
lpfc_set_loopback_flag(phba);
rc = lpfc_sli_issue_mbox(phba, pmb, flag);
if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0498 Adapter failed to init, mbxCmd x%x "
- "INIT_LINK, mbxStatus x%x\n",
- mb->mbxCommand, mb->mbxStatus);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0498 Adapter failed to init, mbxCmd x%x "
+ "INIT_LINK, mbxStatus x%x\n",
+ mb->mbxCommand, mb->mbxStatus);
if (phba->sli_rev <= LPFC_SLI_REV3) {
/* Clear all interrupt enable conditions */
writel(0, phba->HCregaddr);
@@ -802,17 +790,15 @@
return -ENOMEM;
}
- lpfc_printf_log(phba,
- KERN_ERR, LOG_INIT,
- "0491 Adapter Link is disabled.\n");
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0491 Adapter Link is disabled.\n");
lpfc_down_link(phba, pmb);
pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
rc = lpfc_sli_issue_mbox(phba, pmb, flag);
if ((rc != MBX_SUCCESS) && (rc != MBX_BUSY)) {
- lpfc_printf_log(phba,
- KERN_ERR, LOG_INIT,
- "2522 Adapter failed to issue DOWN_LINK"
- " mbox command rc 0x%x\n", rc);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2522 Adapter failed to issue DOWN_LINK"
+ " mbox command rc 0x%x\n", rc);
mempool_free(pmb, phba->mbox_mem_pool);
return -EIO;
@@ -1007,7 +993,6 @@
/**
* lpfc_hba_down_post_s3 - Perform lpfc uninitialization after HBA reset
- int i;
* @phba: pointer to lpfc HBA data structure.
*
* This routine will do uninitialization after the HBA is reset when bring
@@ -1040,7 +1025,7 @@
lpfc_hba_down_post_s4(struct lpfc_hba *phba)
{
struct lpfc_io_buf *psb, *psb_next;
- struct lpfc_nvmet_rcv_ctx *ctxp, *ctxp_next;
+ struct lpfc_async_xchg_ctx *ctxp, *ctxp_next;
struct lpfc_sli4_hdw_queue *qp;
LIST_HEAD(aborts);
LIST_HEAD(nvme_aborts);
@@ -1107,7 +1092,7 @@
&nvmet_aborts);
spin_unlock_irq(&phba->sli4_hba.abts_nvmet_buf_list_lock);
list_for_each_entry_safe(ctxp, ctxp_next, &nvmet_aborts, list) {
- ctxp->flag &= ~(LPFC_NVMET_XBUSY | LPFC_NVMET_ABORT_OP);
+ ctxp->flag &= ~(LPFC_NVME_XBUSY | LPFC_NVME_ABORT_OP);
lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
}
}
@@ -1135,7 +1120,7 @@
/**
* lpfc_hb_timeout - The HBA-timer timeout handler
- * @ptr: unsigned long holds the pointer to lpfc hba data structure.
+ * @t: timer context used to obtain the pointer to lpfc hba data structure.
*
* This is the HBA-timer timeout handler registered to the lpfc driver. When
* this timer fires, a HBA timeout event shall be posted to the lpfc driver
@@ -1169,7 +1154,7 @@
/**
* lpfc_rrq_timeout - The RRQ-timer timeout handler
- * @ptr: unsigned long holds the pointer to lpfc hba data structure.
+ * @t: timer context used to obtain the pointer to lpfc hba data structure.
*
* This is the RRQ-timer timeout handler registered to the lpfc driver. When
* this timer fires, a RRQ timeout event shall be posted to the lpfc driver
@@ -1233,6 +1218,75 @@
return;
}
+/*
+ * lpfc_idle_stat_delay_work - idle_stat tracking
+ *
+ * This routine tracks per-cq idle_stat and determines polling decisions.
+ *
+ * Return codes:
+ * None
+ **/
+static void
+lpfc_idle_stat_delay_work(struct work_struct *work)
+{
+ struct lpfc_hba *phba = container_of(to_delayed_work(work),
+ struct lpfc_hba,
+ idle_stat_delay_work);
+ struct lpfc_queue *cq;
+ struct lpfc_sli4_hdw_queue *hdwq;
+ struct lpfc_idle_stat *idle_stat;
+ u32 i, idle_percent;
+ u64 wall, wall_idle, diff_wall, diff_idle, busy_time;
+
+ if (phba->pport->load_flag & FC_UNLOADING)
+ return;
+
+ if (phba->link_state == LPFC_HBA_ERROR ||
+ phba->pport->fc_flag & FC_OFFLINE_MODE)
+ goto requeue;
+
+ for_each_present_cpu(i) {
+ hdwq = &phba->sli4_hba.hdwq[phba->sli4_hba.cpu_map[i].hdwq];
+ cq = hdwq->io_cq;
+
+ /* Skip if we've already handled this cq's primary CPU */
+ if (cq->chann != i)
+ continue;
+
+ idle_stat = &phba->sli4_hba.idle_stat[i];
+
+ /* get_cpu_idle_time returns values as running counters. Thus,
+ * to know the amount for this period, the prior counter values
+ * need to be subtracted from the current counter values.
+ * From there, the idle time stat can be calculated as a
+ * percentage of 100 - the sum of the other consumption times.
+ */
+ wall_idle = get_cpu_idle_time(i, &wall, 1);
+ diff_idle = wall_idle - idle_stat->prev_idle;
+ diff_wall = wall - idle_stat->prev_wall;
+
+ if (diff_wall <= diff_idle)
+ busy_time = 0;
+ else
+ busy_time = diff_wall - diff_idle;
+
+ idle_percent = div64_u64(100 * busy_time, diff_wall);
+ idle_percent = 100 - idle_percent;
+
+ if (idle_percent < 15)
+ cq->poll_mode = LPFC_QUEUE_WORK;
+ else
+ cq->poll_mode = LPFC_IRQ_POLL;
+
+ idle_stat->prev_idle = wall_idle;
+ idle_stat->prev_wall = wall;
+ }
+
+requeue:
+ schedule_delayed_work(&phba->idle_stat_delay_work,
+ msecs_to_jiffies(LPFC_IDLE_STAT_DELAY));
+}
+
static void
lpfc_hb_eq_delay_work(struct work_struct *work)
{
@@ -1240,10 +1294,9 @@
struct lpfc_hba, eq_delay_work);
struct lpfc_eq_intr_info *eqi, *eqi_new;
struct lpfc_queue *eq, *eq_next;
- unsigned char *eqcnt = NULL;
+ unsigned char *ena_delay = NULL;
uint32_t usdelay;
int i;
- bool update = false;
if (!phba->cfg_auto_imax || phba->pport->load_flag & FC_UNLOADING)
return;
@@ -1252,44 +1305,36 @@
phba->pport->fc_flag & FC_OFFLINE_MODE)
goto requeue;
- eqcnt = kcalloc(num_possible_cpus(), sizeof(unsigned char),
- GFP_KERNEL);
- if (!eqcnt)
+ ena_delay = kcalloc(phba->sli4_hba.num_possible_cpu, sizeof(*ena_delay),
+ GFP_KERNEL);
+ if (!ena_delay)
goto requeue;
- if (phba->cfg_irq_chann > 1) {
- /* Loop thru all IRQ vectors */
- for (i = 0; i < phba->cfg_irq_chann; i++) {
- /* Get the EQ corresponding to the IRQ vector */
- eq = phba->sli4_hba.hba_eq_hdl[i].eq;
- if (!eq)
- continue;
- if (eq->q_mode) {
- update = true;
- break;
- }
- if (eqcnt[eq->last_cpu] < 2)
- eqcnt[eq->last_cpu]++;
+ for (i = 0; i < phba->cfg_irq_chann; i++) {
+ /* Get the EQ corresponding to the IRQ vector */
+ eq = phba->sli4_hba.hba_eq_hdl[i].eq;
+ if (!eq)
+ continue;
+ if (eq->q_mode || eq->q_flag & HBA_EQ_DELAY_CHK) {
+ eq->q_flag &= ~HBA_EQ_DELAY_CHK;
+ ena_delay[eq->last_cpu] = 1;
}
- } else
- update = true;
+ }
for_each_present_cpu(i) {
eqi = per_cpu_ptr(phba->sli4_hba.eq_info, i);
- if (!update && eqcnt[i] < 2) {
- eqi->icnt = 0;
- continue;
+ if (ena_delay[i]) {
+ usdelay = (eqi->icnt >> 10) * LPFC_EQ_DELAY_STEP;
+ if (usdelay > LPFC_MAX_AUTO_EQ_DELAY)
+ usdelay = LPFC_MAX_AUTO_EQ_DELAY;
+ } else {
+ usdelay = 0;
}
- usdelay = (eqi->icnt / LPFC_IMAX_THRESHOLD) *
- LPFC_EQ_DELAY_STEP;
- if (usdelay > LPFC_MAX_AUTO_EQ_DELAY)
- usdelay = LPFC_MAX_AUTO_EQ_DELAY;
-
eqi->icnt = 0;
list_for_each_entry_safe(eq, eq_next, &eqi->list, cpu_list) {
- if (eq->last_cpu != i) {
+ if (unlikely(eq->last_cpu != i)) {
eqi_new = per_cpu_ptr(phba->sli4_hba.eq_info,
eq->last_cpu);
list_move_tail(&eq->cpu_list, &eqi_new->list);
@@ -1301,7 +1346,7 @@
}
}
- kfree(eqcnt);
+ kfree(ena_delay);
requeue:
queue_delayed_work(phba->wq, &phba->eq_delay_work,
@@ -1558,11 +1603,11 @@
return;
}
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0479 Deferred Adapter Hardware Error "
- "Data: x%x x%x x%x\n",
- phba->work_hs,
- phba->work_status[0], phba->work_status[1]);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0479 Deferred Adapter Hardware Error "
+ "Data: x%x x%x x%x\n",
+ phba->work_hs, phba->work_status[0],
+ phba->work_status[1]);
spin_lock_irq(&phba->hbalock);
psli->sli_flag &= ~LPFC_SLI_ACTIVE;
@@ -1713,7 +1758,7 @@
temp_event_data.event_code = LPFC_CRIT_TEMP;
temp_event_data.data = (uint32_t)temperature;
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0406 Adapter maximum temperature exceeded "
"(%ld), taking this port offline "
"Data: x%x x%x x%x\n",
@@ -1737,7 +1782,7 @@
* failure is a value other than FFER6. Do not call the offline
* twice. This is the adapter hardware error path.
*/
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0457 Adapter Hardware Error "
"Data: x%x x%x x%x\n",
phba->work_hs,
@@ -1758,7 +1803,7 @@
* lpfc_sli4_port_sta_fn_reset - The SLI4 function reset due to port status reg
* @phba: pointer to lpfc hba data structure.
* @mbx_action: flag for mailbox shutdown action.
- *
+ * @en_rn_msg: send reset/port recovery message.
* This routine is invoked to perform an SLI4 port PCI function reset in
* response to port status register polling attention. It waits for port
* status register (ERR, RDY, RN) bits before proceeding with function reset.
@@ -1785,7 +1830,7 @@
/* need reset: attempt for port recovery */
if (en_rn_msg)
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2887 Reset Needed: Attempting Port "
"Recovery...\n");
lpfc_offline_prep(phba, mbx_action);
@@ -1795,14 +1840,14 @@
lpfc_sli4_disable_intr(phba);
rc = lpfc_sli_brdrestart(phba);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6309 Failed to restart board\n");
return rc;
}
/* request and enable interrupt */
intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode);
if (intr_mode == LPFC_INTR_ERROR) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3175 Failed to enable interrupt\n");
return -EIO;
}
@@ -1841,7 +1886,7 @@
* we cannot communicate with the pci card anyway.
*/
if (pci_channel_offline(phba->pcidev)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3166 pci channel is offline\n");
lpfc_sli4_offline_eratt(phba);
return;
@@ -1864,7 +1909,7 @@
lpfc_sli4_offline_eratt(phba);
return;
}
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"7623 Checking UE recoverable");
for (i = 0; i < phba->sli4_hba.ue_to_sr / 1000; i++) {
@@ -1881,7 +1926,7 @@
msleep(1000);
}
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"4827 smphr_port_status x%x : Waited %dSec",
smphr_port_status, i);
@@ -1899,14 +1944,14 @@
LPFC_MBX_NO_WAIT, en_rn_msg);
if (rc == 0)
return;
- lpfc_printf_log(phba,
- KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"4215 Failed to recover UE");
break;
}
}
}
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"7624 Firmware not ready: Failing UE recovery,"
" waited %dSec", i);
phba->link_state = LPFC_HBA_ERROR;
@@ -1919,7 +1964,7 @@
&portstat_reg.word0);
/* consider PCI bus read error as pci_channel_offline */
if (pci_rd_rc1 == -EIO) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3151 PCI bus read access failure: x%x\n",
readl(phba->sli4_hba.u.if_type2.STATUSregaddr));
lpfc_sli4_offline_eratt(phba);
@@ -1928,10 +1973,10 @@
reg_err1 = readl(phba->sli4_hba.u.if_type2.ERR1regaddr);
reg_err2 = readl(phba->sli4_hba.u.if_type2.ERR2regaddr);
if (bf_get(lpfc_sliport_status_oti, &portstat_reg)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2889 Port Overtemperature event, "
- "taking port offline Data: x%x x%x\n",
- reg_err1, reg_err2);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2889 Port Overtemperature event, "
+ "taking port offline Data: x%x x%x\n",
+ reg_err1, reg_err2);
phba->sfp_alarm |= LPFC_TRANSGRESSION_HIGH_TEMPERATURE;
temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT;
@@ -1953,17 +1998,17 @@
}
if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 &&
reg_err2 == SLIPORT_ERR2_REG_FW_RESTART) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"3143 Port Down: Firmware Update "
"Detected\n");
en_rn_msg = false;
} else if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 &&
reg_err2 == SLIPORT_ERR2_REG_FORCED_DUMP)
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3144 Port Down: Debug Dump\n");
else if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 &&
reg_err2 == SLIPORT_ERR2_REG_FUNC_PROVISON)
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3145 Port Down: Provisioning\n");
/* If resets are disabled then leave the HBA alone and return */
@@ -1982,7 +2027,7 @@
break;
}
/* fall through for not able to recover */
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3152 Unrecoverable error\n");
phba->link_state = LPFC_HBA_ERROR;
break;
@@ -2100,8 +2145,8 @@
lpfc_linkdown(phba);
phba->link_state = LPFC_HBA_ERROR;
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
- "0300 LATT: Cannot issue READ_LA: Data:%d\n", rc);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0300 LATT: Cannot issue READ_LA: Data:%d\n", rc);
return;
}
@@ -2850,12 +2895,13 @@
*/
while (!list_empty(&vport->fc_nodes)) {
if (i++ > 3000) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0233 Nodelist not empty\n");
list_for_each_entry_safe(ndlp, next_ndlp,
&vport->fc_nodes, nlp_listp) {
lpfc_printf_vlog(ndlp->vport, KERN_ERR,
- LOG_NODE,
+ LOG_TRACE_EVENT,
"0282 did:x%x ndlp:x%px "
"usgmap:x%x refcnt:%d\n",
ndlp->nlp_DID, (void *)ndlp,
@@ -2942,6 +2988,7 @@
if (phba->pport)
lpfc_stop_vport_timers(phba->pport);
cancel_delayed_work_sync(&phba->eq_delay_work);
+ cancel_delayed_work_sync(&phba->idle_stat_delay_work);
del_timer_sync(&phba->sli.mbox_tmo);
del_timer_sync(&phba->fabric_block_timer);
del_timer_sync(&phba->eratt_poll);
@@ -2962,7 +3009,7 @@
lpfc_sli4_stop_fcf_redisc_wait_timer(phba);
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0297 Invalid device group (x%x)\n",
phba->pci_dev_grp);
break;
@@ -2973,6 +3020,7 @@
/**
* lpfc_block_mgmt_io - Mark a HBA's management interface as blocked
* @phba: pointer to lpfc hba data structure.
+ * @mbx_action: flag for mailbox no wait action.
*
* This routine marks a HBA's management interface as blocked. Once the HBA's
* management interface is marked as blocked, all the user space access to
@@ -3009,10 +3057,10 @@
/* Check active mailbox complete status every 2ms */
msleep(2);
if (time_after(jiffies, timeout)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2813 Mgmt IO is Blocked %x "
- "- mbox cmd %x still active\n",
- phba->sli.sli_flag, actcmd);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2813 Mgmt IO is Blocked %x "
+ "- mbox cmd %x still active\n",
+ phba->sli.sli_flag, actcmd);
break;
}
}
@@ -3058,11 +3106,12 @@
continue;
}
ndlp->nlp_rpi = rpi;
- lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE,
- "0009 rpi:%x DID:%x "
- "flg:%x map:%x x%px\n", ndlp->nlp_rpi,
- ndlp->nlp_DID, ndlp->nlp_flag,
- ndlp->nlp_usg_map, ndlp);
+ lpfc_printf_vlog(ndlp->vport, KERN_INFO,
+ LOG_NODE | LOG_DISCOVERY,
+ "0009 Assign RPI x%x to ndlp x%px "
+ "DID:x%06x flg:x%x map:x%x\n",
+ ndlp->nlp_rpi, ndlp, ndlp->nlp_DID,
+ ndlp->nlp_flag, ndlp->nlp_usg_map);
}
}
lpfc_destroy_vport_work_array(phba, vports);
@@ -3356,7 +3405,7 @@
!phba->nvmet_support) {
error = lpfc_nvme_create_localport(phba->pport);
if (error)
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6132 NVME restore reg failed "
"on nvmei error x%x\n", error);
}
@@ -3422,6 +3471,7 @@
/**
* lpfc_offline_prep - Prepare a HBA to be brought offline
* @phba: pointer to lpfc hba data structure.
+ * @mbx_action: flag for mailbox shutdown action.
*
* This routine is invoked to prepare a HBA to be brought offline. It performs
* unregistration login to all the nodes on all vports and flushes the mailbox
@@ -3460,10 +3510,15 @@
list_for_each_entry_safe(ndlp, next_ndlp,
&vports[i]->fc_nodes,
nlp_listp) {
- if (!NLP_CHK_NODE_ACT(ndlp))
+ if ((!NLP_CHK_NODE_ACT(ndlp)) ||
+ ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
+ /* Driver must assume RPI is invalid for
+ * any unused or inactive node.
+ */
+ ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
continue;
- if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
- continue;
+ }
+
if (ndlp->nlp_type & NLP_FABRIC) {
lpfc_disc_state_machine(vports[i], ndlp,
NULL, NLP_EVT_DEVICE_RECOVERY);
@@ -3479,16 +3534,16 @@
* comes back online.
*/
if (phba->sli_rev == LPFC_SLI_REV4) {
- lpfc_printf_vlog(ndlp->vport,
- KERN_INFO, LOG_NODE,
- "0011 lpfc_offline: "
- "ndlp:x%px did %x "
- "usgmap:x%x rpi:%x\n",
- ndlp, ndlp->nlp_DID,
- ndlp->nlp_usg_map,
- ndlp->nlp_rpi);
-
+ lpfc_printf_vlog(ndlp->vport, KERN_INFO,
+ LOG_NODE | LOG_DISCOVERY,
+ "0011 Free RPI x%x on "
+ "ndlp:x%px did x%x "
+ "usgmap:x%x\n",
+ ndlp->nlp_rpi, ndlp,
+ ndlp->nlp_DID,
+ ndlp->nlp_usg_map);
lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi);
+ ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
}
lpfc_unreg_rpi(vports[i], ndlp);
}
@@ -3691,7 +3746,8 @@
sglq_entry = kzalloc(sizeof(struct lpfc_sglq),
GFP_KERNEL);
if (sglq_entry == NULL) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"2562 Failure to allocate an "
"ELS sgl entry:%d\n", i);
rc = -ENOMEM;
@@ -3702,7 +3758,8 @@
&sglq_entry->phys);
if (sglq_entry->virt == NULL) {
kfree(sglq_entry);
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"2563 Failure to allocate an "
"ELS mbuf:%d\n", i);
rc = -ENOMEM;
@@ -3757,7 +3814,8 @@
&phba->sli4_hba.lpfc_els_sgl_list, list) {
lxri = lpfc_sli4_next_xritag(phba);
if (lxri == NO_XRI) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"2400 Failed to allocate xri for "
"ELS sgl\n");
rc = -ENOMEM;
@@ -3812,7 +3870,8 @@
sglq_entry = kzalloc(sizeof(struct lpfc_sglq),
GFP_KERNEL);
if (sglq_entry == NULL) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"6303 Failure to allocate an "
"NVMET sgl entry:%d\n", i);
rc = -ENOMEM;
@@ -3823,7 +3882,8 @@
&sglq_entry->phys);
if (sglq_entry->virt == NULL) {
kfree(sglq_entry);
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"6304 Failure to allocate an "
"NVMET buf:%d\n", i);
rc = -ENOMEM;
@@ -3879,7 +3939,8 @@
&phba->sli4_hba.lpfc_nvmet_sgl_list, list) {
lxri = lpfc_sli4_next_xritag(phba);
if (lxri == NO_XRI) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"6307 Failed to allocate xri for "
"NVMET sgl\n");
rc = -ENOMEM;
@@ -4053,7 +4114,8 @@
&io_sgl_list, list) {
lxri = lpfc_sli4_next_xritag(phba);
if (lxri == NO_XRI) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"6075 Failed to allocate xri for "
"nvme buffer\n");
rc = -ENOMEM;
@@ -4072,8 +4134,8 @@
/**
* lpfc_new_io_buf - IO buffer allocator for HBA with SLI4 IF spec
- * @vport: The virtual port for which this call being executed.
- * @num_to_allocate: The requested number of buffers to allocate.
+ * @phba: Pointer to lpfc hba data structure.
+ * @num_to_alloc: The requested number of buffers to allocate.
*
* This routine allocates nvme buffers for device with SLI-4 interface spec,
* the nvme buffer contains all the necessary information needed to initiate
@@ -4123,7 +4185,8 @@
if ((phba->sli3_options & LPFC_SLI3_BG_ENABLED) &&
(((unsigned long)(lpfc_ncmd->data) &
(unsigned long)(SLI4_PAGE_SIZE - 1)) != 0)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"3369 Memory alignment err: "
"addr=%lx\n",
(unsigned long)lpfc_ncmd->data);
@@ -4152,7 +4215,7 @@
dma_pool_free(phba->lpfc_sg_dma_buf_pool,
lpfc_ncmd->data, lpfc_ncmd->dma_handle);
kfree(lpfc_ncmd);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6121 Failed to allocate IOTAG for"
" XRI:0x%x\n", lxri);
lpfc_sli4_free_xri(phba, lxri);
@@ -4203,7 +4266,7 @@
lpfc_read_nv(phba, mboxq);
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
if (rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6019 Mailbox failed , mbxCmd x%x "
"READ_NV, mbxStatus x%x\n",
bf_get(lpfc_mqe_command, &mboxq->u.mqe),
@@ -4242,6 +4305,7 @@
{
struct lpfc_vport *vport;
struct Scsi_Host *shost = NULL;
+ struct scsi_host_template *template;
int error = 0;
int i;
uint64_t wwn;
@@ -4262,7 +4326,8 @@
for (i = 0; i < lpfc_no_hba_reset_cnt; i++) {
if (wwn == lpfc_no_hba_reset[i]) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"6020 Setting use_no_reset port=%llx\n",
wwn);
use_no_reset_hba = true;
@@ -4270,22 +4335,50 @@
}
}
- if (phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP) {
- if (dev != &phba->pcidev->dev) {
- shost = scsi_host_alloc(&lpfc_vport_template,
- sizeof(struct lpfc_vport));
+ /* Seed template for SCSI host registration */
+ if (dev == &phba->pcidev->dev) {
+ template = &phba->port_template;
+
+ if (phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP) {
+ /* Seed physical port template */
+ memcpy(template, &lpfc_template, sizeof(*template));
+
+ if (use_no_reset_hba) {
+ /* template is for a no reset SCSI Host */
+ template->max_sectors = 0xffff;
+ template->eh_host_reset_handler = NULL;
+ }
+
+ /* Template for all vports this physical port creates */
+ memcpy(&phba->vport_template, &lpfc_template,
+ sizeof(*template));
+ phba->vport_template.max_sectors = 0xffff;
+ phba->vport_template.shost_attrs = lpfc_vport_attrs;
+ phba->vport_template.eh_bus_reset_handler = NULL;
+ phba->vport_template.eh_host_reset_handler = NULL;
+ phba->vport_template.vendor_id = 0;
+
+ /* Initialize the host templates with updated value */
+ if (phba->sli_rev == LPFC_SLI_REV4) {
+ template->sg_tablesize = phba->cfg_scsi_seg_cnt;
+ phba->vport_template.sg_tablesize =
+ phba->cfg_scsi_seg_cnt;
+ } else {
+ template->sg_tablesize = phba->cfg_sg_seg_cnt;
+ phba->vport_template.sg_tablesize =
+ phba->cfg_sg_seg_cnt;
+ }
+
} else {
- if (!use_no_reset_hba)
- shost = scsi_host_alloc(&lpfc_template,
- sizeof(struct lpfc_vport));
- else
- shost = scsi_host_alloc(&lpfc_template_no_hr,
- sizeof(struct lpfc_vport));
+ /* NVMET is for physical port only */
+ memcpy(template, &lpfc_template_nvme,
+ sizeof(*template));
}
- } else if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) {
- shost = scsi_host_alloc(&lpfc_template_nvme,
- sizeof(struct lpfc_vport));
+ } else {
+ template = &phba->vport_template;
}
+
+ shost = scsi_host_alloc(template, sizeof(struct lpfc_vport));
if (!shost)
goto out;
@@ -4340,6 +4433,12 @@
vport->port_type = LPFC_PHYSICAL_PORT;
}
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP,
+ "9081 CreatePort TMPLATE type %x TBLsize %d "
+ "SEGcnt %d/%d\n",
+ vport->port_type, shost->sg_tablesize,
+ phba->cfg_scsi_seg_cnt, phba->cfg_sg_seg_cnt);
+
/* Initialize all internally managed lists. */
INIT_LIST_HEAD(&vport->fc_nodes);
INIT_LIST_HEAD(&vport->rcv_buffer_list);
@@ -4478,6 +4577,13 @@
struct lpfc_hba *phba = vport->phba;
fc_host_supported_speeds(shost) = 0;
+ /*
+ * Avoid reporting supported link speed for FCoE as it can't be
+ * controlled via FCoE.
+ */
+ if (phba->hba_flag & HBA_FCOE_MODE)
+ return;
+
if (phba->lmt & LMT_128Gb)
fc_host_supported_speeds(shost) |= FC_PORTSPEED_128GBIT;
if (phba->lmt & LMT_64Gb)
@@ -4625,7 +4731,7 @@
/**
* lpfc_sli4_fcf_redisc_wait_tmo - FCF table rediscover wait timeout
- * @ptr: Map to lpfc_hba data structure pointer.
+ * @t: Timer context used to obtain the pointer to lpfc hba data structure.
*
* This routine is invoked when waiting for FCF table rediscover has been
* timed out. If new FCF record(s) has (have) been discovered during the
@@ -4673,7 +4779,7 @@
case LPFC_ASYNC_LINK_FAULT_LR_LRR:
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0398 Unknown link fault code: x%x\n",
bf_get(lpfc_acqe_link_fault, acqe_link));
break;
@@ -4709,7 +4815,7 @@
att_type = LPFC_ATT_LINK_UP;
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0399 Invalid link attention type: x%x\n",
bf_get(lpfc_acqe_link_status, acqe_link));
att_type = LPFC_ATT_RESERVED;
@@ -4811,6 +4917,9 @@
case LPFC_ASYNC_LINK_SPEED_40GBPS:
port_speed = 40000;
break;
+ case LPFC_ASYNC_LINK_SPEED_100GBPS:
+ port_speed = 100000;
+ break;
default:
port_speed = 0;
}
@@ -4881,19 +4990,19 @@
phba->fcoe_eventtag = acqe_link->event_tag;
pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0395 The mboxq allocation failed\n");
return;
}
mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
if (!mp) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0396 The lpfc_dmabuf allocation failed\n");
goto out_free_pmb;
}
mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
if (!mp->virt) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0397 The mbuf allocation failed\n");
goto out_free_dmabuf;
}
@@ -4992,7 +5101,6 @@
* lpfc_async_link_speed_to_read_top - Parse async evt link speed code to read
* topology.
* @phba: pointer to lpfc hba data structure.
- * @evt_code: asynchronous event code.
* @speed_code: asynchronous event link speed code.
*
* This routine is to parse the giving SLI4 async event link speed code into
@@ -5094,7 +5202,7 @@
phba->trunk_link.link3.fault = port_fault & 0x8 ? err : 0;
}
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2910 Async FC Trunking Event - Speed:%d\n"
"\tLogical speed:%d "
"port0: %s port1: %s port2: %s port3: %s\n",
@@ -5104,7 +5212,7 @@
trunk_link_status(2), trunk_link_status(3));
if (port_fault)
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3202 trunk error:0x%x (%s) seen on port0:%s "
/*
* SLI-4: We have only 0xA error codes
@@ -5138,7 +5246,7 @@
if (bf_get(lpfc_trailer_type, acqe_fc) !=
LPFC_FC_LA_EVENT_TYPE_FC_LINK) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2895 Non FC link Event detected.(%d)\n",
bf_get(lpfc_trailer_type, acqe_fc));
return;
@@ -5186,19 +5294,19 @@
phba->sli4_hba.link_state.fault);
pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2897 The mboxq allocation failed\n");
return;
}
mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
if (!mp) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2898 The lpfc_dmabuf allocation failed\n");
goto out_free_pmb;
}
mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
if (!mp->virt) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2899 The mbuf allocation failed\n");
goto out_free_dmabuf;
}
@@ -5270,7 +5378,7 @@
/**
* lpfc_sli4_async_sli_evt - Process the asynchronous SLI link event
* @phba: pointer to lpfc hba data structure.
- * @acqe_fc: pointer to the async SLI completion queue entry.
+ * @acqe_sli: pointer to the async SLI completion queue entry.
*
* This routine is to handle the SLI4 asynchronous SLI events.
**/
@@ -5291,10 +5399,10 @@
evt_type = bf_get(lpfc_trailer_type, acqe_sli);
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- "2901 Async SLI event - Event Data1:x%08x Event Data2:"
- "x%08x SLI Event Type:%d\n",
+ "2901 Async SLI event - Type:%d, Event Data: x%08x "
+ "x%08x x%08x x%08x\n", evt_type,
acqe_sli->event_data1, acqe_sli->event_data2,
- evt_type);
+ acqe_sli->reserved, acqe_sli->trailer);
port_name = phba->Port[0];
if (port_name == 0x00)
@@ -5365,7 +5473,7 @@
&misconfigured->theEvent);
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3296 "
"LPFC_SLI_EVENT_TYPE_MISCONFIGURED "
"event: Invalid link %d",
@@ -5417,7 +5525,8 @@
rc = lpfc_sli4_read_config(phba);
if (rc) {
phba->lmt = 0;
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"3194 Unable to retrieve supported "
"speeds, rc = 0x%x\n", rc);
}
@@ -5441,11 +5550,26 @@
"Event Data1:x%08x Event Data2: x%08x\n",
acqe_sli->event_data1, acqe_sli->event_data2);
break;
+ case LPFC_SLI_EVENT_TYPE_MISCONF_FAWWN:
+ /* Misconfigured WWN. Reports that the SLI Port is configured
+ * to use FA-WWN, but the attached device doesn’t support it.
+ * No driver action is required.
+ * Event Data1 - N.A, Event Data2 - N.A
+ */
+ lpfc_log_msg(phba, KERN_WARNING, LOG_SLI,
+ "2699 Misconfigured FA-WWN - Attached device does "
+ "not support FA-WWN\n");
+ break;
+ case LPFC_SLI_EVENT_TYPE_EEPROM_FAILURE:
+ /* EEPROM failure. No driver action is required */
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "2518 EEPROM failure - "
+ "Event Data1: x%08x Event Data2: x%08x\n",
+ acqe_sli->event_data1, acqe_sli->event_data2);
+ break;
default:
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- "3193 Async SLI event - Event Data1:x%08x Event Data2:"
- "x%08x SLI Event Type:%d\n",
- acqe_sli->event_data1, acqe_sli->event_data2,
+ "3193 Unrecognized SLI event, type: 0x%x",
evt_type);
break;
}
@@ -5510,7 +5634,7 @@
/**
* lpfc_sli4_perform_all_vport_cvl - Perform clear virtual link on all vports
- * @vport: pointer to lpfc hba data structure.
+ * @phba: pointer to lpfc hba data structure.
*
* This routine is to perform Clear Virtual Link (CVL) on all vports in
* response to a FCF dead event.
@@ -5531,7 +5655,7 @@
/**
* lpfc_sli4_async_fip_evt - Process the asynchronous FCoE FIP event
* @phba: pointer to lpfc hba data structure.
- * @acqe_link: pointer to the async fcoe completion queue entry.
+ * @acqe_fip: pointer to the async fcoe completion queue entry.
*
* This routine is to handle the SLI4 asynchronous fcoe event.
**/
@@ -5554,8 +5678,7 @@
case LPFC_FIP_EVENT_TYPE_NEW_FCF:
case LPFC_FIP_EVENT_TYPE_FCF_PARAM_MOD:
if (event_type == LPFC_FIP_EVENT_TYPE_NEW_FCF)
- lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
- LOG_DISCOVERY,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2546 New FCF event, evt_tag:x%x, "
"index:x%x\n",
acqe_fip->event_tag,
@@ -5608,23 +5731,24 @@
rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba,
LPFC_FCOE_FCF_GET_FIRST);
if (rc)
- lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2547 Issue FCF scan read FCF mailbox "
"command failed (x%x)\n", rc);
break;
case LPFC_FIP_EVENT_TYPE_FCF_TABLE_FULL:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2548 FCF Table full count 0x%x tag 0x%x\n",
- bf_get(lpfc_acqe_fip_fcf_count, acqe_fip),
- acqe_fip->event_tag);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2548 FCF Table full count 0x%x tag 0x%x\n",
+ bf_get(lpfc_acqe_fip_fcf_count, acqe_fip),
+ acqe_fip->event_tag);
break;
case LPFC_FIP_EVENT_TYPE_FCF_DEAD:
phba->fcoe_cvl_eventtag = acqe_fip->event_tag;
- lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
- "2549 FCF (x%x) disconnected from network, "
- "tag:x%x\n", acqe_fip->index, acqe_fip->event_tag);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2549 FCF (x%x) disconnected from network, "
+ "tag:x%x\n", acqe_fip->index,
+ acqe_fip->event_tag);
/*
* If we are in the middle of FCF failover process, clear
* the corresponding FCF bit in the roundrobin bitmap.
@@ -5661,7 +5785,7 @@
rc = lpfc_sli4_redisc_fcf_table(phba);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
- LOG_DISCOVERY,
+ LOG_TRACE_EVENT,
"2772 Issue FCF rediscover mailbox "
"command failed, fail through to FCF "
"dead event\n");
@@ -5685,7 +5809,8 @@
break;
case LPFC_FIP_EVENT_TYPE_CVL:
phba->fcoe_cvl_eventtag = acqe_fip->event_tag;
- lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"2718 Clear Virtual Link Received for VPI 0x%x"
" tag 0x%x\n", acqe_fip->index, acqe_fip->event_tag);
@@ -5752,7 +5877,7 @@
rc = lpfc_sli4_redisc_fcf_table(phba);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
- LOG_DISCOVERY,
+ LOG_TRACE_EVENT,
"2774 Issue FCF rediscover "
"mailbox command failed, "
"through to CVL event\n");
@@ -5773,9 +5898,9 @@
}
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "0288 Unknown FCoE event type 0x%x event tag "
- "0x%x\n", event_type, acqe_fip->event_tag);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0288 Unknown FCoE event type 0x%x event tag "
+ "0x%x\n", event_type, acqe_fip->event_tag);
break;
}
}
@@ -5783,7 +5908,7 @@
/**
* lpfc_sli4_async_dcbx_evt - Process the asynchronous dcbx event
* @phba: pointer to lpfc hba data structure.
- * @acqe_link: pointer to the async dcbx completion queue entry.
+ * @acqe_dcbx: pointer to the async dcbx completion queue entry.
*
* This routine is to handle the SLI4 asynchronous dcbx event.
**/
@@ -5792,7 +5917,7 @@
struct lpfc_acqe_dcbx *acqe_dcbx)
{
phba->fc_eventTag = acqe_dcbx->event_tag;
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0290 The SLI4 DCBX asynchronous event is not "
"handled yet\n");
}
@@ -5800,7 +5925,7 @@
/**
* lpfc_sli4_async_grp5_evt - Process the asynchronous group5 event
* @phba: pointer to lpfc hba data structure.
- * @acqe_link: pointer to the async grp5 completion queue entry.
+ * @acqe_grp5: pointer to the async grp5 completion queue entry.
*
* This routine is to handle the SLI4 asynchronous grp5 event. A grp5 event
* is an asynchronous notified of a logical link speed change. The Port
@@ -5833,18 +5958,21 @@
void lpfc_sli4_async_event_proc(struct lpfc_hba *phba)
{
struct lpfc_cq_event *cq_event;
+ unsigned long iflags;
/* First, declare the async event has been handled */
- spin_lock_irq(&phba->hbalock);
+ spin_lock_irqsave(&phba->hbalock, iflags);
phba->hba_flag &= ~ASYNC_EVENT;
- spin_unlock_irq(&phba->hbalock);
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+
/* Now, handle all the async events */
+ spin_lock_irqsave(&phba->sli4_hba.asynce_list_lock, iflags);
while (!list_empty(&phba->sli4_hba.sp_asynce_work_queue)) {
- /* Get the first event from the head of the event queue */
- spin_lock_irq(&phba->hbalock);
list_remove_head(&phba->sli4_hba.sp_asynce_work_queue,
cq_event, struct lpfc_cq_event, list);
- spin_unlock_irq(&phba->hbalock);
+ spin_unlock_irqrestore(&phba->sli4_hba.asynce_list_lock,
+ iflags);
+
/* Process the asynchronous event */
switch (bf_get(lpfc_trailer_code, &cq_event->cqe.mcqe_cmpl)) {
case LPFC_TRAILER_CODE_LINK:
@@ -5869,15 +5997,19 @@
lpfc_sli4_async_sli_evt(phba, &cq_event->cqe.acqe_sli);
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "1804 Invalid asynchrous event code: "
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
+ "1804 Invalid asynchronous event code: "
"x%x\n", bf_get(lpfc_trailer_code,
&cq_event->cqe.mcqe_cmpl));
break;
}
+
/* Free the completion event processed to the free pool */
lpfc_sli4_cq_event_release(phba, cq_event);
+ spin_lock_irqsave(&phba->sli4_hba.asynce_list_lock, iflags);
}
+ spin_unlock_irqrestore(&phba->sli4_hba.asynce_list_lock, iflags);
}
/**
@@ -5905,7 +6037,7 @@
"2777 Start post-quiescent FCF table scan\n");
rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST);
if (rc)
- lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2747 Issue FCF scan read FCF mailbox "
"command failed 0x%x\n", rc);
}
@@ -5976,7 +6108,7 @@
"0480 Enabled MSI-X interrupt mode.\n");
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0482 Illegal interrupt mode.\n");
break;
}
@@ -6024,7 +6156,7 @@
out_disable_device:
pci_disable_device(pdev);
out_error:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1401 Failed to enable pci device\n");
return -ENODEV;
}
@@ -6125,7 +6257,7 @@
max_nr_vfn = lpfc_sli_sriov_nr_virtfn_get(phba);
if (nr_vfn > max_nr_vfn) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3057 Requested vfs (%d) greater than "
"supported vfs (%d)", nr_vfn, max_nr_vfn);
return -EINVAL;
@@ -6164,6 +6296,9 @@
* Driver resources common to all SLI revisions
*/
atomic_set(&phba->fast_event_count, 0);
+ atomic_set(&phba->dbg_log_idx, 0);
+ atomic_set(&phba->dbg_log_cnt, 0);
+ atomic_set(&phba->dbg_log_dmping, 0);
spin_lock_init(&phba->hbalock);
/* Initialize ndlp management spinlock */
@@ -6217,6 +6352,9 @@
INIT_DELAYED_WORK(&phba->eq_delay_work, lpfc_hb_eq_delay_work);
+ INIT_DELAYED_WORK(&phba->idle_stat_delay_work,
+ lpfc_idle_stat_delay_work);
+
return 0;
}
@@ -6274,11 +6412,6 @@
* used to create the sg_dma_buf_pool must be dynamically calculated.
*/
- /* Initialize the host templates the configured values. */
- lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt;
- lpfc_template_no_hr.sg_tablesize = phba->cfg_sg_seg_cnt;
- lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt;
-
if (phba->sli_rev == LPFC_SLI_REV4)
entry_sz = sizeof(struct sli4_sge);
else
@@ -6319,7 +6452,7 @@
}
lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP,
- "9088 sg_tablesize:%d dmabuf_size:%d total_bde:%d\n",
+ "9088 INIT sg_tablesize:%d dmabuf_size:%d total_bde:%d\n",
phba->cfg_sg_seg_cnt, phba->cfg_sg_dma_buf_size,
phba->cfg_total_seg_cnt);
@@ -6422,7 +6555,7 @@
u32 if_fam;
phba->sli4_hba.num_present_cpu = lpfc_present_cpu;
- phba->sli4_hba.num_possible_cpu = num_possible_cpus();
+ phba->sli4_hba.num_possible_cpu = cpumask_last(cpu_possible_mask) + 1;
phba->sli4_hba.curr_disp_cpu = 0;
/* Get all the module params for configuring this host */
@@ -6501,6 +6634,8 @@
/* This abort list used by worker thread */
spin_lock_init(&phba->sli4_hba.sgl_list_lock);
spin_lock_init(&phba->sli4_hba.nvmet_io_wait_lock);
+ spin_lock_init(&phba->sli4_hba.asynce_list_lock);
+ spin_lock_init(&phba->sli4_hba.els_xri_abrt_list_lock);
/*
* Initialize driver internal slow-path work queues
@@ -6512,8 +6647,6 @@
INIT_LIST_HEAD(&phba->sli4_hba.sp_queue_event);
/* Asynchronous event CQ Event work queue list */
INIT_LIST_HEAD(&phba->sli4_hba.sp_asynce_work_queue);
- /* Fast-path XRI aborted CQ Event work queue list */
- INIT_LIST_HEAD(&phba->sli4_hba.sp_fcp_xri_aborted_work_queue);
/* Slow-path XRI aborted CQ Event work queue list */
INIT_LIST_HEAD(&phba->sli4_hba.sp_els_xri_aborted_work_queue);
/* Receive queue CQ Event work queue list */
@@ -6591,7 +6724,8 @@
lpfc_read_nv(phba, mboxq);
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
if (rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"6016 Mailbox failed , mbxCmd x%x "
"READ_NV, mbxStatus x%x\n",
bf_get(lpfc_mqe_command, &mboxq->u.mqe),
@@ -6620,17 +6754,26 @@
phba->nvmet_support = 1; /* a match */
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"6017 NVME Target %016llx\n",
wwn);
#else
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"6021 Can't enable NVME Target."
" NVME_TARGET_FC infrastructure"
" is not in kernel\n");
#endif
/* Not supported for NVMET */
phba->cfg_xri_rebalancing = 0;
+ if (phba->irq_chann_mode == NHT_MODE) {
+ phba->cfg_irq_chann =
+ phba->sli4_hba.num_present_cpu;
+ phba->cfg_hdw_queue =
+ phba->sli4_hba.num_present_cpu;
+ phba->irq_chann_mode = NORMAL_MODE;
+ }
break;
}
}
@@ -6651,9 +6794,9 @@
&phba->sli4_hba.sli_intf);
if (phba->sli4_hba.extents_in_use &&
phba->sli4_hba.rpi_hdrs_in_use) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2999 Unsupported SLI4 Parameters "
- "Extents and RPI headers enabled.\n");
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2999 Unsupported SLI4 Parameters "
+ "Extents and RPI headers enabled.\n");
if (if_type == LPFC_SLI_INTF_IF_TYPE_0 &&
if_fam == LPFC_SLI_INTF_FAMILY_BE2) {
mempool_free(mboxq, phba->mbox_mem_pool);
@@ -6760,11 +6903,6 @@
phba->cfg_nvme_seg_cnt = phba->cfg_sg_seg_cnt;
}
- /* Initialize the host templates with the updated values. */
- lpfc_vport_template.sg_tablesize = phba->cfg_scsi_seg_cnt;
- lpfc_template.sg_tablesize = phba->cfg_scsi_seg_cnt;
- lpfc_template_no_hr.sg_tablesize = phba->cfg_scsi_seg_cnt;
-
lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP,
"9087 sg_seg_cnt:%d dmabuf_size:%d "
"total:%d scsi:%d nvme:%d\n",
@@ -6818,13 +6956,13 @@
/* Allocate and initialize active sgl array */
rc = lpfc_init_active_sgl_array(phba);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1430 Failed to initialize sgl list.\n");
goto out_destroy_cq_event_pool;
}
rc = lpfc_sli4_init_rpi_hdrs(phba);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1432 Failed to initialize rpi headers.\n");
goto out_free_active_sgl;
}
@@ -6834,7 +6972,7 @@
phba->fcf.fcf_rr_bmask = kcalloc(longs, sizeof(unsigned long),
GFP_KERNEL);
if (!phba->fcf.fcf_rr_bmask) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2759 Failed allocate memory for FCF round "
"robin failover bmask\n");
rc = -ENOMEM;
@@ -6845,7 +6983,7 @@
sizeof(struct lpfc_hba_eq_hdl),
GFP_KERNEL);
if (!phba->sli4_hba.hba_eq_hdl) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2572 Failed allocate memory for "
"fast-path per-EQ handle array\n");
rc = -ENOMEM;
@@ -6856,7 +6994,7 @@
sizeof(struct lpfc_vector_map_info),
GFP_KERNEL);
if (!phba->sli4_hba.cpu_map) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3327 Failed allocate memory for msi-x "
"interrupt vector mapping\n");
rc = -ENOMEM;
@@ -6865,11 +7003,32 @@
phba->sli4_hba.eq_info = alloc_percpu(struct lpfc_eq_intr_info);
if (!phba->sli4_hba.eq_info) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3321 Failed allocation for per_cpu stats\n");
rc = -ENOMEM;
goto out_free_hba_cpu_map;
}
+
+ phba->sli4_hba.idle_stat = kcalloc(phba->sli4_hba.num_possible_cpu,
+ sizeof(*phba->sli4_hba.idle_stat),
+ GFP_KERNEL);
+ if (!phba->sli4_hba.idle_stat) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "3390 Failed allocation for idle_stat\n");
+ rc = -ENOMEM;
+ goto out_free_hba_eq_info;
+ }
+
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ phba->sli4_hba.c_stat = alloc_percpu(struct lpfc_hdwq_stat);
+ if (!phba->sli4_hba.c_stat) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "3332 Failed allocating per cpu hdwq stats\n");
+ rc = -ENOMEM;
+ goto out_free_hba_idle_stat;
+ }
+#endif
+
/*
* Enable sr-iov virtual functions if supported and configured
* through the module parameter.
@@ -6889,6 +7048,12 @@
return 0;
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+out_free_hba_idle_stat:
+ kfree(phba->sli4_hba.idle_stat);
+#endif
+out_free_hba_eq_info:
+ free_percpu(phba->sli4_hba.eq_info);
out_free_hba_cpu_map:
kfree(phba->sli4_hba.cpu_map);
out_free_hba_eq_hdl:
@@ -6927,12 +7092,17 @@
struct lpfc_fcf_conn_entry *conn_entry, *next_conn_entry;
free_percpu(phba->sli4_hba.eq_info);
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ free_percpu(phba->sli4_hba.c_stat);
+#endif
+ kfree(phba->sli4_hba.idle_stat);
/* Free memory allocated for msi-x interrupt vector to CPU mapping */
kfree(phba->sli4_hba.cpu_map);
phba->sli4_hba.num_possible_cpu = 0;
phba->sli4_hba.num_present_cpu = 0;
phba->sli4_hba.curr_disp_cpu = 0;
+ cpumask_clear(&phba->sli4_hba.irq_aff_mask);
/* Free memory allocated for fast-path work queue handles */
kfree(phba->sli4_hba.hba_eq_hdl);
@@ -7000,7 +7170,7 @@
phba->lpfc_stop_port = lpfc_stop_port_s4;
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1431 Invalid HBA PCI-device group: 0x%x\n",
dev_grp);
return -ENODEV;
@@ -7084,6 +7254,7 @@
/**
* lpfc_init_iocb_list - Allocate and initialize iocb list.
* @phba: pointer to lpfc hba data structure.
+ * @iocb_count: number of requested iocbs
*
* This routine is invoked to allocate and initizlize the driver's IOCB
* list and set up the IOCB tag array accordingly.
@@ -7106,7 +7277,7 @@
if (iocbq_entry == NULL) {
printk(KERN_ERR "%s: only allocated %d iocbs of "
"expected %d count. Unloading driver.\n",
- __func__, i, LPFC_IOCB_LIST_CNT);
+ __func__, i, iocb_count);
goto out_free_iocbq;
}
@@ -7295,7 +7466,7 @@
rpi_hdr = lpfc_sli4_create_rpi_hdr(phba);
if (!rpi_hdr) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0391 Error during rpi post operation\n");
lpfc_sli4_remove_rpis(phba);
rc = -ENODEV;
@@ -7525,18 +7696,10 @@
if (phba->nvmet_support) {
/* Only 1 vport (pport) will support NVME target */
- if (phba->txrdy_payload_pool == NULL) {
- phba->txrdy_payload_pool = dma_pool_create(
- "txrdy_pool", &phba->pcidev->dev,
- TXRDY_PAYLOAD_LEN, 16, 0);
- if (phba->txrdy_payload_pool) {
- phba->targetport = NULL;
- phba->cfg_enable_fc4_type = LPFC_ENABLE_NVME;
- lpfc_printf_log(phba, KERN_INFO,
- LOG_INIT | LOG_NVME_DISC,
- "6076 NVME Target Found\n");
- }
- }
+ phba->targetport = NULL;
+ phba->cfg_enable_fc4_type = LPFC_ENABLE_NVME;
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_NVME_DISC,
+ "6076 NVME Target Found\n");
}
lpfc_debugfs_initialize(vport);
@@ -7615,7 +7778,7 @@
if (phba->cfg_prot_mask && phba->cfg_prot_guard) {
if ((old_mask != phba->cfg_prot_mask) ||
(old_guard != phba->cfg_prot_guard))
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1475 Registering BlockGuard with the "
"SCSI layer: mask %d guard %d\n",
phba->cfg_prot_mask,
@@ -7624,7 +7787,7 @@
scsi_host_set_prot(shost, phba->cfg_prot_mask);
scsi_host_set_guard(shost, phba->cfg_prot_guard);
} else
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1479 Not Registering BlockGuard with the SCSI "
"layer, Bad protection parameters: %d %d\n",
old_mask, old_guard);
@@ -7855,7 +8018,7 @@
* other register reads as the data may not be valid. Just exit.
*/
if (port_error) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1408 Port Failed POST - portsmphr=0x%x, "
"perr=x%x, sfi=x%x, nip=x%x, ipc=x%x, scr1=x%x, "
"scr2=x%x, hscratch=x%x, pstatus=x%x\n",
@@ -7904,7 +8067,8 @@
readl(phba->sli4_hba.u.if_type0.UERRHIregaddr);
if ((~phba->sli4_hba.ue_mask_lo & uerrlo_reg.word0) ||
(~phba->sli4_hba.ue_mask_hi & uerrhi_reg.word0)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"1422 Unrecoverable Error "
"Detected during POST "
"uerr_lo_reg=0x%x, "
@@ -7931,7 +8095,7 @@
phba->work_status[1] =
readl(phba->sli4_hba.u.if_type2.
ERR2regaddr);
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2888 Unrecoverable port error "
"following POST: port status reg "
"0x%x, port_smphr reg 0x%x, "
@@ -8044,6 +8208,7 @@
/**
* lpfc_sli4_bar1_register_memmap - Set up SLI4 BAR1 register memory map.
* @phba: pointer to lpfc hba data structure.
+ * @if_type: sli if type to operate on.
*
* This routine is invoked to set up SLI4 BAR1 register memory map.
**/
@@ -8215,6 +8380,85 @@
memset(&phba->sli4_hba.bmbx, 0, sizeof(struct lpfc_bmbx));
}
+static const char * const lpfc_topo_to_str[] = {
+ "Loop then P2P",
+ "Loopback",
+ "P2P Only",
+ "Unsupported",
+ "Loop Only",
+ "Unsupported",
+ "P2P then Loop",
+};
+
+#define LINK_FLAGS_DEF 0x0
+#define LINK_FLAGS_P2P 0x1
+#define LINK_FLAGS_LOOP 0x2
+/**
+ * lpfc_map_topology - Map the topology read from READ_CONFIG
+ * @phba: pointer to lpfc hba data structure.
+ * @rd_config: pointer to read config data
+ *
+ * This routine is invoked to map the topology values as read
+ * from the read config mailbox command. If the persistent
+ * topology feature is supported, the firmware will provide the
+ * saved topology information to be used in INIT_LINK
+ **/
+static void
+lpfc_map_topology(struct lpfc_hba *phba, struct lpfc_mbx_read_config *rd_config)
+{
+ u8 ptv, tf, pt;
+
+ ptv = bf_get(lpfc_mbx_rd_conf_ptv, rd_config);
+ tf = bf_get(lpfc_mbx_rd_conf_tf, rd_config);
+ pt = bf_get(lpfc_mbx_rd_conf_pt, rd_config);
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "2027 Read Config Data : ptv:0x%x, tf:0x%x pt:0x%x",
+ ptv, tf, pt);
+ if (!ptv) {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "2019 FW does not support persistent topology "
+ "Using driver parameter defined value [%s]",
+ lpfc_topo_to_str[phba->cfg_topology]);
+ return;
+ }
+ /* FW supports persistent topology - override module parameter value */
+ phba->hba_flag |= HBA_PERSISTENT_TOPO;
+ switch (phba->pcidev->device) {
+ case PCI_DEVICE_ID_LANCER_G7_FC:
+ case PCI_DEVICE_ID_LANCER_G6_FC:
+ if (!tf) {
+ phba->cfg_topology = ((pt == LINK_FLAGS_LOOP)
+ ? FLAGS_TOPOLOGY_MODE_LOOP
+ : FLAGS_TOPOLOGY_MODE_PT_PT);
+ } else {
+ phba->hba_flag &= ~HBA_PERSISTENT_TOPO;
+ }
+ break;
+ default: /* G5 */
+ if (tf) {
+ /* If topology failover set - pt is '0' or '1' */
+ phba->cfg_topology = (pt ? FLAGS_TOPOLOGY_MODE_PT_LOOP :
+ FLAGS_TOPOLOGY_MODE_LOOP_PT);
+ } else {
+ phba->cfg_topology = ((pt == LINK_FLAGS_P2P)
+ ? FLAGS_TOPOLOGY_MODE_PT_PT
+ : FLAGS_TOPOLOGY_MODE_LOOP);
+ }
+ break;
+ }
+ if (phba->hba_flag & HBA_PERSISTENT_TOPO) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "2020 Using persistent topology value [%s]",
+ lpfc_topo_to_str[phba->cfg_topology]);
+ } else {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "2021 Invalid topology values from FW "
+ "Using driver parameter defined value [%s]",
+ lpfc_topo_to_str[phba->cfg_topology]);
+ }
+}
+
/**
* lpfc_sli4_read_config - Get the config parameters.
* @phba: pointer to lpfc hba data structure.
@@ -8245,7 +8489,7 @@
pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2011 Unable to allocate memory for issuing "
"SLI_CONFIG_SPECIAL mailbox command\n");
return -ENOMEM;
@@ -8255,11 +8499,11 @@
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
if (rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2012 Mailbox failed , mbxCmd x%x "
- "READ_CONFIG, mbxStatus x%x\n",
- bf_get(lpfc_mqe_command, &pmb->u.mqe),
- bf_get(lpfc_mqe_status, &pmb->u.mqe));
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2012 Mailbox failed , mbxCmd x%x "
+ "READ_CONFIG, mbxStatus x%x\n",
+ bf_get(lpfc_mqe_command, &pmb->u.mqe),
+ bf_get(lpfc_mqe_status, &pmb->u.mqe));
rc = -EIO;
} else {
rd_config = &pmb->u.mqe.un.rd_config;
@@ -8326,13 +8570,14 @@
phba->max_vpi = (phba->sli4_hba.max_cfg_param.max_vpi > 0) ?
(phba->sli4_hba.max_cfg_param.max_vpi - 1) : 0;
phba->max_vports = phba->max_vpi;
+ lpfc_map_topology(phba, rd_config);
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"2003 cfg params Extents? %d "
"XRI(B:%d M:%d), "
"VPI(B:%d M:%d) "
"VFI(B:%d M:%d) "
"RPI(B:%d M:%d) "
- "FCFI:%d EQ:%d CQ:%d WQ:%d RQ:%d\n",
+ "FCFI:%d EQ:%d CQ:%d WQ:%d RQ:%d lmt:x%x\n",
phba->sli4_hba.extents_in_use,
phba->sli4_hba.max_cfg_param.xri_base,
phba->sli4_hba.max_cfg_param.max_xri,
@@ -8346,7 +8591,8 @@
phba->sli4_hba.max_cfg_param.max_eq,
phba->sli4_hba.max_cfg_param.max_cq,
phba->sli4_hba.max_cfg_param.max_wq,
- phba->sli4_hba.max_cfg_param.max_rq);
+ phba->sli4_hba.max_cfg_param.max_rq,
+ phba->lmt);
/*
* Calculate queue resources based on how
@@ -8368,8 +8614,9 @@
/* Check to see if there is enough for NVME */
if ((phba->cfg_irq_chann > qmin) ||
(phba->cfg_hdw_queue > qmin)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "2005 Reducing Queues: "
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2005 Reducing Queues - "
+ "FW resource limitation: "
"WQ %d CQ %d EQ %d: min %d: "
"IRQ %d HDWQ %d\n",
phba->sli4_hba.max_cfg_param.max_wq,
@@ -8434,7 +8681,8 @@
LPFC_USER_LINK_SPEED_AUTO;
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"0047 Unrecognized link "
"speed : %d\n",
forced_link_speed);
@@ -8471,7 +8719,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (rc2 || shdr_status || shdr_add_status) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3026 Mailbox failed , mbxCmd x%x "
"GET_FUNCTION_CONFIG, mbxStatus x%x\n",
bf_get(lpfc_mqe_command, &pmb->u.mqe),
@@ -8508,7 +8756,7 @@
"vf_number:%d\n", phba->sli4_hba.iov.pf_number,
phba->sli4_hba.iov.vf_number);
else
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3028 GET_FUNCTION_CONFIG: failed to find "
"Resource Descriptor:x%x\n",
LPFC_RSRC_DESC_TYPE_FCFCOE);
@@ -8545,7 +8793,7 @@
mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
GFP_KERNEL);
if (!mboxq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0492 Unable to allocate memory for "
"issuing SLI_CONFIG_SPECIAL mailbox "
"command\n");
@@ -8560,7 +8808,7 @@
memcpy(&mboxq->u.mqe, &endian_mb_data, sizeof(endian_mb_data));
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
if (rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0493 SLI_CONFIG_SPECIAL mailbox "
"failed with status x%x\n",
rc);
@@ -8599,8 +8847,8 @@
*/
if (phba->nvmet_support) {
- if (phba->cfg_irq_chann < phba->cfg_nvmet_mrq)
- phba->cfg_nvmet_mrq = phba->cfg_irq_chann;
+ if (phba->cfg_hdw_queue < phba->cfg_nvmet_mrq)
+ phba->cfg_nvmet_mrq = phba->cfg_hdw_queue;
if (phba->cfg_nvmet_mrq > LPFC_NVMET_MRQ_MAX)
phba->cfg_nvmet_mrq = LPFC_NVMET_MRQ_MAX;
}
@@ -8640,8 +8888,9 @@
phba->sli4_hba.cq_esize,
phba->sli4_hba.cq_ecount, cpu);
if (!qdesc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0499 Failed allocate fast-path IO CQ (%d)\n", idx);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0499 Failed allocate fast-path IO CQ (%d)\n",
+ idx);
return 1;
}
qdesc->qe_valid = 1;
@@ -8663,7 +8912,7 @@
phba->sli4_hba.wq_ecount, cpu);
if (!qdesc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0503 Failed allocate fast-path IO WQ (%d)\n",
idx);
return 1;
@@ -8719,7 +8968,7 @@
phba->cfg_hdw_queue, sizeof(struct lpfc_sli4_hdw_queue),
GFP_KERNEL);
if (!phba->sli4_hba.hdwq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6427 Failed allocate memory for "
"fast-path Hardware Queue array\n");
goto out_error;
@@ -8751,7 +9000,7 @@
sizeof(struct lpfc_queue *),
GFP_KERNEL);
if (!phba->sli4_hba.nvmet_cqset) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3121 Fail allocate memory for "
"fast-path CQ set array\n");
goto out_error;
@@ -8761,7 +9010,7 @@
sizeof(struct lpfc_queue *),
GFP_KERNEL);
if (!phba->sli4_hba.nvmet_mrq_hdr) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3122 Fail allocate memory for "
"fast-path RQ set hdr array\n");
goto out_error;
@@ -8771,7 +9020,7 @@
sizeof(struct lpfc_queue *),
GFP_KERNEL);
if (!phba->sli4_hba.nvmet_mrq_data) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3124 Fail allocate memory for "
"fast-path RQ set data array\n");
goto out_error;
@@ -8799,7 +9048,7 @@
phba->sli4_hba.eq_esize,
phba->sli4_hba.eq_ecount, cpu);
if (!qdesc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0497 Failed allocate EQ (%d)\n",
cpup->hdwq);
goto out_error;
@@ -8853,7 +9102,7 @@
phba->sli4_hba.cq_ecount,
cpu);
if (!qdesc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3142 Failed allocate NVME "
"CQ Set (%d)\n", idx);
goto out_error;
@@ -8875,7 +9124,7 @@
phba->sli4_hba.cq_esize,
phba->sli4_hba.cq_ecount, cpu);
if (!qdesc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0500 Failed allocate slow-path mailbox CQ\n");
goto out_error;
}
@@ -8887,7 +9136,7 @@
phba->sli4_hba.cq_esize,
phba->sli4_hba.cq_ecount, cpu);
if (!qdesc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0501 Failed allocate slow-path ELS CQ\n");
goto out_error;
}
@@ -8906,7 +9155,7 @@
phba->sli4_hba.mq_esize,
phba->sli4_hba.mq_ecount, cpu);
if (!qdesc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0505 Failed allocate slow-path MQ\n");
goto out_error;
}
@@ -8922,7 +9171,7 @@
phba->sli4_hba.wq_esize,
phba->sli4_hba.wq_ecount, cpu);
if (!qdesc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0504 Failed allocate slow-path ELS WQ\n");
goto out_error;
}
@@ -8936,7 +9185,7 @@
phba->sli4_hba.cq_esize,
phba->sli4_hba.cq_ecount, cpu);
if (!qdesc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6079 Failed allocate NVME LS CQ\n");
goto out_error;
}
@@ -8949,7 +9198,7 @@
phba->sli4_hba.wq_esize,
phba->sli4_hba.wq_ecount, cpu);
if (!qdesc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6080 Failed allocate NVME LS WQ\n");
goto out_error;
}
@@ -8967,7 +9216,7 @@
phba->sli4_hba.rq_esize,
phba->sli4_hba.rq_ecount, cpu);
if (!qdesc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0506 Failed allocate receive HRQ\n");
goto out_error;
}
@@ -8978,7 +9227,7 @@
phba->sli4_hba.rq_esize,
phba->sli4_hba.rq_ecount, cpu);
if (!qdesc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0507 Failed allocate receive DRQ\n");
goto out_error;
}
@@ -8996,7 +9245,7 @@
LPFC_NVMET_RQE_DEF_COUNT,
cpu);
if (!qdesc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3146 Failed allocate "
"receive HRQ\n");
goto out_error;
@@ -9009,7 +9258,7 @@
GFP_KERNEL,
cpu_to_node(cpu));
if (qdesc->rqbp == NULL) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6131 Failed allocate "
"Header RQBP\n");
goto out_error;
@@ -9025,7 +9274,7 @@
LPFC_NVMET_RQE_DEF_COUNT,
cpu);
if (!qdesc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3156 Failed allocate "
"receive DRQ\n");
goto out_error;
@@ -9216,7 +9465,7 @@
int rc;
if (!eq || !cq || !wq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6085 Fast-path %s (%d) not allocated\n",
((eq) ? ((cq) ? "WQ" : "CQ") : "EQ"), qidx);
return -ENOMEM;
@@ -9226,9 +9475,9 @@
rc = lpfc_cq_create(phba, cq, eq,
(qtype == LPFC_MBOX) ? LPFC_MCQ : LPFC_WCQ, qtype);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "6086 Failed setup of CQ (%d), rc = 0x%x\n",
- qidx, (uint32_t)rc);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "6086 Failed setup of CQ (%d), rc = 0x%x\n",
+ qidx, (uint32_t)rc);
return rc;
}
@@ -9244,7 +9493,7 @@
/* create the wq */
rc = lpfc_wq_create(phba, wq, cq, qtype);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"4618 Fail setup fastpath WQ (%d), rc = 0x%x\n",
qidx, (uint32_t)rc);
/* no need to tear down cq - caller will do so */
@@ -9262,9 +9511,9 @@
} else {
rc = lpfc_mq_create(phba, wq, cq, LPFC_MBOX);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0539 Failed setup of slow-path MQ: "
- "rc = 0x%x\n", rc);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0539 Failed setup of slow-path MQ: "
+ "rc = 0x%x\n", rc);
/* no need to tear down cq - caller will do so */
return rc;
}
@@ -9337,7 +9586,7 @@
/* Check for dual-ULP support */
mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mboxq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3249 Unable to allocate memory for "
"QUERY_FW_CFG mailbox command\n");
return -ENOMEM;
@@ -9355,7 +9604,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3250 QUERY_FW_CFG mailbox failed with status "
"x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -9384,7 +9633,7 @@
/* Set up HBA event queue */
if (!qp) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3147 Fast-path EQs not allocated\n");
rc = -ENOMEM;
goto out_error;
@@ -9408,7 +9657,7 @@
rc = lpfc_eq_create(phba, qp[cpup->hdwq].hba_eq,
phba->cfg_fcp_imax);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0523 Failed setup of fast-path"
" EQ (%d), rc = 0x%x\n",
cpup->eq, (uint32_t)rc);
@@ -9440,7 +9689,7 @@
qidx,
LPFC_IO);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0535 Failed to setup fastpath "
"IO WQ/CQ (%d), rc = 0x%x\n",
qidx, (uint32_t)rc);
@@ -9455,7 +9704,7 @@
/* Set up slow-path MBOX CQ/MQ */
if (!phba->sli4_hba.mbx_cq || !phba->sli4_hba.mbx_wq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0528 %s not allocated\n",
phba->sli4_hba.mbx_cq ?
"Mailbox WQ" : "Mailbox CQ");
@@ -9468,14 +9717,14 @@
phba->sli4_hba.mbx_wq,
NULL, 0, LPFC_MBOX);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0529 Failed setup of mailbox WQ/CQ: rc = 0x%x\n",
(uint32_t)rc);
goto out_destroy;
}
if (phba->nvmet_support) {
if (!phba->sli4_hba.nvmet_cqset) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3165 Fast-path NVME CQ Set "
"array not allocated\n");
rc = -ENOMEM;
@@ -9487,7 +9736,7 @@
qp,
LPFC_WCQ, LPFC_NVMET);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3164 Failed setup of NVME CQ "
"Set, rc = 0x%x\n",
(uint32_t)rc);
@@ -9499,7 +9748,7 @@
qp[0].hba_eq,
LPFC_WCQ, LPFC_NVMET);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6089 Failed setup NVMET CQ: "
"rc = 0x%x\n", (uint32_t)rc);
goto out_destroy;
@@ -9516,7 +9765,7 @@
/* Set up slow-path ELS WQ/CQ */
if (!phba->sli4_hba.els_cq || !phba->sli4_hba.els_wq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0530 ELS %s not allocated\n",
phba->sli4_hba.els_cq ? "WQ" : "CQ");
rc = -ENOMEM;
@@ -9527,7 +9776,7 @@
phba->sli4_hba.els_wq,
NULL, 0, LPFC_ELS);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0525 Failed setup of ELS WQ/CQ: rc = 0x%x\n",
(uint32_t)rc);
goto out_destroy;
@@ -9540,7 +9789,7 @@
if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) {
/* Set up NVME LS Complete Queue */
if (!phba->sli4_hba.nvmels_cq || !phba->sli4_hba.nvmels_wq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6091 LS %s not allocated\n",
phba->sli4_hba.nvmels_cq ? "WQ" : "CQ");
rc = -ENOMEM;
@@ -9551,7 +9800,7 @@
phba->sli4_hba.nvmels_wq,
NULL, 0, LPFC_NVME_LS);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0526 Failed setup of NVVME LS WQ/CQ: "
"rc = 0x%x\n", (uint32_t)rc);
goto out_destroy;
@@ -9571,7 +9820,7 @@
if ((!phba->sli4_hba.nvmet_cqset) ||
(!phba->sli4_hba.nvmet_mrq_hdr) ||
(!phba->sli4_hba.nvmet_mrq_data)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6130 MRQ CQ Queues not "
"allocated\n");
rc = -ENOMEM;
@@ -9584,7 +9833,7 @@
phba->sli4_hba.nvmet_cqset,
LPFC_NVMET);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6098 Failed setup of NVMET "
"MRQ: rc = 0x%x\n",
(uint32_t)rc);
@@ -9598,7 +9847,7 @@
phba->sli4_hba.nvmet_cqset[0],
LPFC_NVMET);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6057 Failed setup of NVMET "
"Receive Queue: rc = 0x%x\n",
(uint32_t)rc);
@@ -9617,7 +9866,7 @@
}
if (!phba->sli4_hba.hdr_rq || !phba->sli4_hba.dat_rq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0540 Receive Queue not allocated\n");
rc = -ENOMEM;
goto out_destroy;
@@ -9626,7 +9875,7 @@
rc = lpfc_rq_create(phba, phba->sli4_hba.hdr_rq, phba->sli4_hba.dat_rq,
phba->sli4_hba.els_cq, LPFC_USOL);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0541 Failed setup of Receive Queue: "
"rc = 0x%x\n", (uint32_t)rc);
goto out_destroy;
@@ -9654,7 +9903,7 @@
phba->sli4_hba.cq_lookup = kcalloc((phba->sli4_hba.cq_max + 1),
sizeof(struct lpfc_queue *), GFP_KERNEL);
if (!phba->sli4_hba.cq_lookup) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0549 Failed setup of CQ Lookup table: "
"size 0x%x\n", phba->sli4_hba.cq_max);
rc = -ENOMEM;
@@ -9901,26 +10150,28 @@
static void
lpfc_sli4_cq_event_release_all(struct lpfc_hba *phba)
{
- LIST_HEAD(cqelist);
- struct lpfc_cq_event *cqe;
+ LIST_HEAD(cq_event_list);
+ struct lpfc_cq_event *cq_event;
unsigned long iflags;
/* Retrieve all the pending WCQEs from pending WCQE lists */
- spin_lock_irqsave(&phba->hbalock, iflags);
- /* Pending FCP XRI abort events */
- list_splice_init(&phba->sli4_hba.sp_fcp_xri_aborted_work_queue,
- &cqelist);
- /* Pending ELS XRI abort events */
- list_splice_init(&phba->sli4_hba.sp_els_xri_aborted_work_queue,
- &cqelist);
- /* Pending asynnc events */
- list_splice_init(&phba->sli4_hba.sp_asynce_work_queue,
- &cqelist);
- spin_unlock_irqrestore(&phba->hbalock, iflags);
- while (!list_empty(&cqelist)) {
- list_remove_head(&cqelist, cqe, struct lpfc_cq_event, list);
- lpfc_sli4_cq_event_release(phba, cqe);
+ /* Pending ELS XRI abort events */
+ spin_lock_irqsave(&phba->sli4_hba.els_xri_abrt_list_lock, iflags);
+ list_splice_init(&phba->sli4_hba.sp_els_xri_aborted_work_queue,
+ &cq_event_list);
+ spin_unlock_irqrestore(&phba->sli4_hba.els_xri_abrt_list_lock, iflags);
+
+ /* Pending asynnc events */
+ spin_lock_irqsave(&phba->sli4_hba.asynce_list_lock, iflags);
+ list_splice_init(&phba->sli4_hba.sp_asynce_work_queue,
+ &cq_event_list);
+ spin_unlock_irqrestore(&phba->sli4_hba.asynce_list_lock, iflags);
+
+ while (!list_empty(&cq_event_list)) {
+ list_remove_head(&cq_event_list, cq_event,
+ struct lpfc_cq_event, list);
+ lpfc_sli4_cq_event_release(phba, cq_event);
}
}
@@ -9954,7 +10205,7 @@
mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
GFP_KERNEL);
if (!mboxq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0494 Unable to allocate memory for "
"issuing SLI_FUNCTION_RESET mailbox "
"command\n");
@@ -9973,7 +10224,7 @@
&shdr->response);
mempool_free(mboxq, phba->mbox_mem_pool);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0495 SLI_FUNCTION_RESET mailbox "
"failed with status x%x add_status x%x,"
" mbx status x%x\n",
@@ -10005,7 +10256,7 @@
phba->sli4_hba.u.if_type2.ERR1regaddr);
phba->work_status[1] = readl(
phba->sli4_hba.u.if_type2.ERR2regaddr);
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2890 Port not ready, port status reg "
"0x%x error 1=0x%x, error 2=0x%x\n",
reg_data.word0,
@@ -10047,7 +10298,7 @@
out:
/* Catch the not-ready port failure after a port reset. */
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3317 HBA not functional: IP Reset Failed "
"try: echo fw_reset > board_mode\n");
rc = -ENODEV;
@@ -10097,7 +10348,7 @@
/* There is no SLI3 failback for SLI4 devices. */
if (bf_get(lpfc_sli_intf_valid, &phba->sli4_hba.sli_intf) !=
LPFC_SLI_INTF_VALID) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2894 SLI_INTF reg contents invalid "
"sli_intf reg 0x%x\n",
phba->sli4_hba.sli_intf.word0);
@@ -10300,6 +10551,8 @@
case LPFC_SLI_INTF_IF_TYPE_6:
iounmap(phba->sli4_hba.drbl_regs_memmap_p);
iounmap(phba->sli4_hba.conf_regs_memmap_p);
+ if (phba->sli4_hba.dpp_regs_memmap_p)
+ iounmap(phba->sli4_hba.dpp_regs_memmap_p);
break;
case LPFC_SLI_INTF_IF_TYPE_1:
default:
@@ -10370,7 +10623,7 @@
if (!pmb) {
rc = -ENOMEM;
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0474 Unable to allocate memory for issuing "
"MBOX_CONFIG_MSI command\n");
goto mem_fail_out;
@@ -10453,6 +10706,7 @@
/**
* lpfc_sli_enable_intr - Enable device interrupt to SLI-3 device.
* @phba: pointer to lpfc hba data structure.
+ * @cfg_mode: Interrupt configuration mode (INTx, MSI or MSI-X).
*
* This routine is invoked to enable device interrupt and associate driver's
* interrupt handler(s) to interrupt vector(s) to device with SLI-3 interface
@@ -10561,7 +10815,6 @@
*/
if ((match == LPFC_FIND_BY_EQ) &&
(cpup->flag & LPFC_CPU_FIRST_IRQ) &&
- (cpup->irq != LPFC_VECTOR_MAP_EMPTY) &&
(cpup->eq == id))
return cpu;
@@ -10599,6 +10852,75 @@
}
#endif
+/*
+ * lpfc_assign_eq_map_info - Assigns eq for vector_map structure
+ * @phba: pointer to lpfc hba data structure.
+ * @eqidx: index for eq and irq vector
+ * @flag: flags to set for vector_map structure
+ * @cpu: cpu used to index vector_map structure
+ *
+ * The routine assigns eq info into vector_map structure
+ */
+static inline void
+lpfc_assign_eq_map_info(struct lpfc_hba *phba, uint16_t eqidx, uint16_t flag,
+ unsigned int cpu)
+{
+ struct lpfc_vector_map_info *cpup = &phba->sli4_hba.cpu_map[cpu];
+ struct lpfc_hba_eq_hdl *eqhdl = lpfc_get_eq_hdl(eqidx);
+
+ cpup->eq = eqidx;
+ cpup->flag |= flag;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "3336 Set Affinity: CPU %d irq %d eq %d flag x%x\n",
+ cpu, eqhdl->irq, cpup->eq, cpup->flag);
+}
+
+/**
+ * lpfc_cpu_map_array_init - Initialize cpu_map structure
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * The routine initializes the cpu_map array structure
+ */
+static void
+lpfc_cpu_map_array_init(struct lpfc_hba *phba)
+{
+ struct lpfc_vector_map_info *cpup;
+ struct lpfc_eq_intr_info *eqi;
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ cpup = &phba->sli4_hba.cpu_map[cpu];
+ cpup->phys_id = LPFC_VECTOR_MAP_EMPTY;
+ cpup->core_id = LPFC_VECTOR_MAP_EMPTY;
+ cpup->hdwq = LPFC_VECTOR_MAP_EMPTY;
+ cpup->eq = LPFC_VECTOR_MAP_EMPTY;
+ cpup->flag = 0;
+ eqi = per_cpu_ptr(phba->sli4_hba.eq_info, cpu);
+ INIT_LIST_HEAD(&eqi->list);
+ eqi->icnt = 0;
+ }
+}
+
+/**
+ * lpfc_hba_eq_hdl_array_init - Initialize hba_eq_hdl structure
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * The routine initializes the hba_eq_hdl array structure
+ */
+static void
+lpfc_hba_eq_hdl_array_init(struct lpfc_hba *phba)
+{
+ struct lpfc_hba_eq_hdl *eqhdl;
+ int i;
+
+ for (i = 0; i < phba->cfg_irq_chann; i++) {
+ eqhdl = lpfc_get_eq_hdl(i);
+ eqhdl->irq = LPFC_VECTOR_MAP_EMPTY;
+ eqhdl->phba = phba;
+ }
+}
+
/**
* lpfc_cpu_affinity_check - Check vector CPU affinity mappings
* @phba: pointer to lpfc hba data structure.
@@ -10617,21 +10939,12 @@
int max_core_id, min_core_id;
struct lpfc_vector_map_info *cpup;
struct lpfc_vector_map_info *new_cpup;
- const struct cpumask *maskp;
#ifdef CONFIG_X86
struct cpuinfo_x86 *cpuinfo;
#endif
-
- /* Init cpu_map array */
- for_each_possible_cpu(cpu) {
- cpup = &phba->sli4_hba.cpu_map[cpu];
- cpup->phys_id = LPFC_VECTOR_MAP_EMPTY;
- cpup->core_id = LPFC_VECTOR_MAP_EMPTY;
- cpup->hdwq = LPFC_VECTOR_MAP_EMPTY;
- cpup->eq = LPFC_VECTOR_MAP_EMPTY;
- cpup->irq = LPFC_VECTOR_MAP_EMPTY;
- cpup->flag = 0;
- }
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ struct lpfc_hdwq_stat *c_stat;
+#endif
max_phys_id = 0;
min_phys_id = LPFC_VECTOR_MAP_EMPTY;
@@ -10668,65 +10981,6 @@
min_core_id = cpup->core_id;
}
- for_each_possible_cpu(i) {
- struct lpfc_eq_intr_info *eqi =
- per_cpu_ptr(phba->sli4_hba.eq_info, i);
-
- INIT_LIST_HEAD(&eqi->list);
- eqi->icnt = 0;
- }
-
- /* This loop sets up all CPUs that are affinitized with a
- * irq vector assigned to the driver. All affinitized CPUs
- * will get a link to that vectors IRQ and EQ.
- *
- * NULL affinity mask handling:
- * If irq count is greater than one, log an error message.
- * If the null mask is received for the first irq, find the
- * first present cpu, and assign the eq index to ensure at
- * least one EQ is assigned.
- */
- for (idx = 0; idx < phba->cfg_irq_chann; idx++) {
- /* Get a CPU mask for all CPUs affinitized to this vector */
- maskp = pci_irq_get_affinity(phba->pcidev, idx);
- if (!maskp) {
- if (phba->cfg_irq_chann > 1)
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "3329 No affinity mask found "
- "for vector %d (%d)\n",
- idx, phba->cfg_irq_chann);
- if (!idx) {
- cpu = cpumask_first(cpu_present_mask);
- cpup = &phba->sli4_hba.cpu_map[cpu];
- cpup->eq = idx;
- cpup->irq = pci_irq_vector(phba->pcidev, idx);
- cpup->flag |= LPFC_CPU_FIRST_IRQ;
- }
- break;
- }
-
- i = 0;
- /* Loop through all CPUs associated with vector idx */
- for_each_cpu_and(cpu, maskp, cpu_present_mask) {
- /* Set the EQ index and IRQ for that vector */
- cpup = &phba->sli4_hba.cpu_map[cpu];
- cpup->eq = idx;
- cpup->irq = pci_irq_vector(phba->pcidev, idx);
-
- /* If this is the first CPU thats assigned to this
- * vector, set LPFC_CPU_FIRST_IRQ.
- */
- if (!i)
- cpup->flag |= LPFC_CPU_FIRST_IRQ;
- i++;
-
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "3336 Set Affinity: CPU %d "
- "irq %d eq %d flag x%x\n",
- cpu, cpup->irq, cpup->eq, cpup->flag);
- }
- }
-
/* After looking at each irq vector assigned to this pcidev, its
* possible to see that not ALL CPUs have been accounted for.
* Next we will set any unassigned (unaffinitized) cpu map
@@ -10752,7 +11006,7 @@
for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) {
new_cpup = &phba->sli4_hba.cpu_map[new_cpu];
if (!(new_cpup->flag & LPFC_CPU_MAP_UNASSIGN) &&
- (new_cpup->irq != LPFC_VECTOR_MAP_EMPTY) &&
+ (new_cpup->eq != LPFC_VECTOR_MAP_EMPTY) &&
(new_cpup->phys_id == cpup->phys_id))
goto found_same;
new_cpu = cpumask_next(
@@ -10765,7 +11019,6 @@
found_same:
/* We found a matching phys_id, so copy the IRQ info */
cpup->eq = new_cpup->eq;
- cpup->irq = new_cpup->irq;
/* Bump start_cpu to the next slot to minmize the
* chance of having multiple unassigned CPU entries
@@ -10777,9 +11030,10 @@
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"3337 Set Affinity: CPU %d "
- "irq %d from id %d same "
+ "eq %d from peer cpu %d same "
"phys_id (%d)\n",
- cpu, cpup->irq, new_cpu, cpup->phys_id);
+ cpu, cpup->eq, new_cpu,
+ cpup->phys_id);
}
}
@@ -10803,7 +11057,7 @@
for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) {
new_cpup = &phba->sli4_hba.cpu_map[new_cpu];
if (!(new_cpup->flag & LPFC_CPU_MAP_UNASSIGN) &&
- (new_cpup->irq != LPFC_VECTOR_MAP_EMPTY))
+ (new_cpup->eq != LPFC_VECTOR_MAP_EMPTY))
goto found_any;
new_cpu = cpumask_next(
new_cpu, cpu_present_mask);
@@ -10813,13 +11067,12 @@
/* We should never leave an entry unassigned */
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3339 Set Affinity: CPU %d "
- "irq %d UNASSIGNED\n",
- cpup->hdwq, cpup->irq);
+ "eq %d UNASSIGNED\n",
+ cpup->hdwq, cpup->eq);
continue;
found_any:
/* We found an available entry, copy the IRQ info */
cpup->eq = new_cpup->eq;
- cpup->irq = new_cpup->irq;
/* Bump start_cpu to the next slot to minmize the
* chance of having multiple unassigned CPU entries
@@ -10831,8 +11084,8 @@
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"3338 Set Affinity: CPU %d "
- "irq %d from id %d (%d/%d)\n",
- cpu, cpup->irq, new_cpu,
+ "eq %d from peer cpu %d (%d/%d)\n",
+ cpu, cpup->eq, new_cpu,
new_cpup->phys_id, new_cpup->core_id);
}
}
@@ -10851,13 +11104,13 @@
/* 1 to 1, the first LPFC_CPU_FIRST_IRQ cpus to a unique hdwq */
cpup->hdwq = idx;
idx++;
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"3333 Set Affinity: CPU %d (phys %d core %d): "
- "hdwq %d eq %d irq %d flg x%x\n",
+ "hdwq %d eq %d flg x%x\n",
cpu, cpup->phys_id, cpup->core_id,
- cpup->hdwq, cpup->eq, cpup->irq, cpup->flag);
+ cpup->hdwq, cpup->eq, cpup->flag);
}
- /* Finally we need to associate a hdwq with each cpu_map entry
+ /* Associate a hdwq with each cpu_map entry
* This will be 1 to 1 - hdwq to cpu, unless there are less
* hardware queues then CPUs. For that case we will just round-robin
* the available hardware queues as they get assigned to CPUs.
@@ -10929,11 +11182,35 @@
start_cpu = first_cpu;
cpup->hdwq = new_cpup->hdwq;
logit:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"3335 Set Affinity: CPU %d (phys %d core %d): "
- "hdwq %d eq %d irq %d flg x%x\n",
+ "hdwq %d eq %d flg x%x\n",
cpu, cpup->phys_id, cpup->core_id,
- cpup->hdwq, cpup->eq, cpup->irq, cpup->flag);
+ cpup->hdwq, cpup->eq, cpup->flag);
+ }
+
+ /*
+ * Initialize the cpu_map slots for not-present cpus in case
+ * a cpu is hot-added. Perform a simple hdwq round robin assignment.
+ */
+ idx = 0;
+ for_each_possible_cpu(cpu) {
+ cpup = &phba->sli4_hba.cpu_map[cpu];
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ c_stat = per_cpu_ptr(phba->sli4_hba.c_stat, cpu);
+ c_stat->hdwq_no = cpup->hdwq;
+#endif
+ if (cpup->hdwq != LPFC_VECTOR_MAP_EMPTY)
+ continue;
+
+ cpup->hdwq = idx++ % phba->cfg_hdw_queue;
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ c_stat->hdwq_no = cpup->hdwq;
+#endif
+ lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+ "3340 Set Affinity: not present "
+ "CPU %d hdwq %d\n",
+ cpu, cpup->hdwq);
}
/* The cpu_map array will be used later during initialization
@@ -10947,19 +11224,21 @@
*
* @phba: pointer to lpfc hba data structure.
* @cpu: cpu going offline
- * @eqlist:
+ * @eqlist: eq list to append to
*/
-static void
+static int
lpfc_cpuhp_get_eq(struct lpfc_hba *phba, unsigned int cpu,
struct list_head *eqlist)
{
- struct lpfc_vector_map_info *map;
const struct cpumask *maskp;
struct lpfc_queue *eq;
- unsigned int i;
- cpumask_t tmp;
+ struct cpumask *tmp;
u16 idx;
+ tmp = kzalloc(cpumask_size(), GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+
for (idx = 0; idx < phba->cfg_irq_chann; idx++) {
maskp = pci_irq_get_affinity(phba->pcidev, idx);
if (!maskp)
@@ -10969,7 +11248,7 @@
* then we don't need to poll the eq attached
* to it.
*/
- if (!cpumask_and(&tmp, maskp, cpumask_of(cpu)))
+ if (!cpumask_and(tmp, maskp, cpumask_of(cpu)))
continue;
/* get the cpus that are online and are affini-
* tized to this irq vector. If the count is
@@ -10977,8 +11256,8 @@
* down this vector. Since this cpu has not
* gone offline yet, we need >1.
*/
- cpumask_and(&tmp, maskp, cpu_online_mask);
- if (cpumask_weight(&tmp) > 1)
+ cpumask_and(tmp, maskp, cpu_online_mask);
+ if (cpumask_weight(tmp) > 1)
continue;
/* Now that we have an irq to shutdown, get the eq
@@ -10986,16 +11265,11 @@
* the software can share an eq, but eventually
* only eq will be mapped to this vector
*/
- for_each_possible_cpu(i) {
- map = &phba->sli4_hba.cpu_map[i];
- if (!(map->irq == pci_irq_vector(phba->pcidev, idx)))
- continue;
- eq = phba->sli4_hba.hdwq[map->hdwq].hba_eq;
- list_add(&eq->_poll_list, eqlist);
- /* 1 is good enough. others will be a copy of this */
- break;
- }
+ eq = phba->sli4_hba.hba_eq_hdl[idx].eq;
+ list_add(&eq->_poll_list, eqlist);
}
+ kfree(tmp);
+ return 0;
}
static void __lpfc_cpuhp_remove(struct lpfc_hba *phba)
@@ -11028,11 +11302,9 @@
rcu_read_lock();
- if (!list_empty(&phba->poll_list)) {
- timer_setup(&phba->cpuhp_poll_timer, lpfc_sli4_poll_hbtimer, 0);
+ if (!list_empty(&phba->poll_list))
mod_timer(&phba->cpuhp_poll_timer,
jiffies + msecs_to_jiffies(LPFC_POLL_HB));
- }
rcu_read_unlock();
@@ -11056,6 +11328,99 @@
return false;
}
+/**
+ * lpfc_irq_set_aff - set IRQ affinity
+ * @eqhdl: EQ handle
+ * @cpu: cpu to set affinity
+ *
+ **/
+static inline void
+lpfc_irq_set_aff(struct lpfc_hba_eq_hdl *eqhdl, unsigned int cpu)
+{
+ cpumask_clear(&eqhdl->aff_mask);
+ cpumask_set_cpu(cpu, &eqhdl->aff_mask);
+ irq_set_status_flags(eqhdl->irq, IRQ_NO_BALANCING);
+ irq_set_affinity_hint(eqhdl->irq, &eqhdl->aff_mask);
+}
+
+/**
+ * lpfc_irq_clear_aff - clear IRQ affinity
+ * @eqhdl: EQ handle
+ *
+ **/
+static inline void
+lpfc_irq_clear_aff(struct lpfc_hba_eq_hdl *eqhdl)
+{
+ cpumask_clear(&eqhdl->aff_mask);
+ irq_clear_status_flags(eqhdl->irq, IRQ_NO_BALANCING);
+}
+
+/**
+ * lpfc_irq_rebalance - rebalances IRQ affinity according to cpuhp event
+ * @phba: pointer to HBA context object.
+ * @cpu: cpu going offline/online
+ * @offline: true, cpu is going offline. false, cpu is coming online.
+ *
+ * If cpu is going offline, we'll try our best effort to find the next
+ * online cpu on the phba's original_mask and migrate all offlining IRQ
+ * affinities.
+ *
+ * If cpu is coming online, reaffinitize the IRQ back to the onlining cpu.
+ *
+ * Note: Call only if NUMA or NHT mode is enabled, otherwise rely on
+ * PCI_IRQ_AFFINITY to auto-manage IRQ affinity.
+ *
+ **/
+static void
+lpfc_irq_rebalance(struct lpfc_hba *phba, unsigned int cpu, bool offline)
+{
+ struct lpfc_vector_map_info *cpup;
+ struct cpumask *aff_mask;
+ unsigned int cpu_select, cpu_next, idx;
+ const struct cpumask *orig_mask;
+
+ if (phba->irq_chann_mode == NORMAL_MODE)
+ return;
+
+ orig_mask = &phba->sli4_hba.irq_aff_mask;
+
+ if (!cpumask_test_cpu(cpu, orig_mask))
+ return;
+
+ cpup = &phba->sli4_hba.cpu_map[cpu];
+
+ if (!(cpup->flag & LPFC_CPU_FIRST_IRQ))
+ return;
+
+ if (offline) {
+ /* Find next online CPU on original mask */
+ cpu_next = cpumask_next_wrap(cpu, orig_mask, cpu, true);
+ cpu_select = lpfc_next_online_cpu(orig_mask, cpu_next);
+
+ /* Found a valid CPU */
+ if ((cpu_select < nr_cpu_ids) && (cpu_select != cpu)) {
+ /* Go through each eqhdl and ensure offlining
+ * cpu aff_mask is migrated
+ */
+ for (idx = 0; idx < phba->cfg_irq_chann; idx++) {
+ aff_mask = lpfc_get_aff_mask(idx);
+
+ /* Migrate affinity */
+ if (cpumask_test_cpu(cpu, aff_mask))
+ lpfc_irq_set_aff(lpfc_get_eq_hdl(idx),
+ cpu_select);
+ }
+ } else {
+ /* Rely on irqbalance if no online CPUs left on NUMA */
+ for (idx = 0; idx < phba->cfg_irq_chann; idx++)
+ lpfc_irq_clear_aff(lpfc_get_eq_hdl(idx));
+ }
+ } else {
+ /* Migrate affinity back to this CPU */
+ lpfc_irq_set_aff(lpfc_get_eq_hdl(cpup->eq), cpu);
+ }
+}
+
static int lpfc_cpu_offline(unsigned int cpu, struct hlist_node *node)
{
struct lpfc_hba *phba = hlist_entry_safe(node, struct lpfc_hba, cpuhp);
@@ -11071,7 +11436,11 @@
if (__lpfc_cpuhp_checks(phba, &retval))
return retval;
- lpfc_cpuhp_get_eq(phba, cpu, &eqlist);
+ lpfc_irq_rebalance(phba, cpu, true);
+
+ retval = lpfc_cpuhp_get_eq(phba, cpu, &eqlist);
+ if (retval)
+ return retval;
/* start polling on these eq's */
list_for_each_entry_safe(eq, next, &eqlist, _poll_list) {
@@ -11097,6 +11466,8 @@
if (__lpfc_cpuhp_checks(phba, &retval))
return retval;
+ lpfc_irq_rebalance(phba, cpu, false);
+
list_for_each_entry_safe(eq, next, &phba->poll_list, _poll_list) {
n = lpfc_find_cpu_handle(phba, eq->hdwq, LPFC_FIND_BY_HDWQ);
if (n == cpu)
@@ -11111,7 +11482,24 @@
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to enable the MSI-X interrupt vectors to device
- * with SLI-4 interface spec.
+ * with SLI-4 interface spec. It also allocates MSI-X vectors and maps them
+ * to cpus on the system.
+ *
+ * When cfg_irq_numa is enabled, the adapter will only allocate vectors for
+ * the number of cpus on the same numa node as this adapter. The vectors are
+ * allocated without requesting OS affinity mapping. A vector will be
+ * allocated and assigned to each online and offline cpu. If the cpu is
+ * online, then affinity will be set to that cpu. If the cpu is offline, then
+ * affinity will be set to the nearest peer cpu within the numa node that is
+ * online. If there are no online cpus within the numa node, affinity is not
+ * assigned and the OS may do as it pleases. Note: cpu vector affinity mapping
+ * is consistent with the way cpu online/offline is handled when cfg_irq_numa is
+ * configured.
+ *
+ * If numa mode is not enabled and there is more than 1 vector allocated, then
+ * the driver relies on the managed irq interface where the OS assigns vector to
+ * cpu affinity. The driver will then use that affinity mapping to setup its
+ * cpu mapping table.
*
* Return codes
* 0 - successful
@@ -11122,13 +11510,33 @@
{
int vectors, rc, index;
char *name;
+ const struct cpumask *aff_mask = NULL;
+ unsigned int cpu = 0, cpu_cnt = 0, cpu_select = nr_cpu_ids;
+ struct lpfc_vector_map_info *cpup;
+ struct lpfc_hba_eq_hdl *eqhdl;
+ const struct cpumask *maskp;
+ unsigned int flags = PCI_IRQ_MSIX;
/* Set up MSI-X multi-message vectors */
vectors = phba->cfg_irq_chann;
- rc = pci_alloc_irq_vectors(phba->pcidev,
- 1,
- vectors, PCI_IRQ_MSIX | PCI_IRQ_AFFINITY);
+ if (phba->irq_chann_mode != NORMAL_MODE)
+ aff_mask = &phba->sli4_hba.irq_aff_mask;
+
+ if (aff_mask) {
+ cpu_cnt = cpumask_weight(aff_mask);
+ vectors = min(phba->cfg_irq_chann, cpu_cnt);
+
+ /* cpu: iterates over aff_mask including offline or online
+ * cpu_select: iterates over online aff_mask to set affinity
+ */
+ cpu = cpumask_first(aff_mask);
+ cpu_select = lpfc_next_online_cpu(aff_mask, cpu);
+ } else {
+ flags |= PCI_IRQ_AFFINITY;
+ }
+
+ rc = pci_alloc_irq_vectors(phba->pcidev, 1, vectors, flags);
if (rc < 0) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"0484 PCI enable MSI-X failed (%d)\n", rc);
@@ -11138,43 +11546,92 @@
/* Assign MSI-X vectors to interrupt handlers */
for (index = 0; index < vectors; index++) {
- name = phba->sli4_hba.hba_eq_hdl[index].handler_name;
+ eqhdl = lpfc_get_eq_hdl(index);
+ name = eqhdl->handler_name;
memset(name, 0, LPFC_SLI4_HANDLER_NAME_SZ);
snprintf(name, LPFC_SLI4_HANDLER_NAME_SZ,
LPFC_DRIVER_HANDLER_NAME"%d", index);
- phba->sli4_hba.hba_eq_hdl[index].idx = index;
- phba->sli4_hba.hba_eq_hdl[index].phba = phba;
+ eqhdl->idx = index;
rc = request_irq(pci_irq_vector(phba->pcidev, index),
&lpfc_sli4_hba_intr_handler, 0,
- name,
- &phba->sli4_hba.hba_eq_hdl[index]);
+ name, eqhdl);
if (rc) {
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
"0486 MSI-X fast-path (%d) "
"request_irq failed (%d)\n", index, rc);
goto cfg_fail_out;
}
+
+ eqhdl->irq = pci_irq_vector(phba->pcidev, index);
+
+ if (aff_mask) {
+ /* If found a neighboring online cpu, set affinity */
+ if (cpu_select < nr_cpu_ids)
+ lpfc_irq_set_aff(eqhdl, cpu_select);
+
+ /* Assign EQ to cpu_map */
+ lpfc_assign_eq_map_info(phba, index,
+ LPFC_CPU_FIRST_IRQ,
+ cpu);
+
+ /* Iterate to next offline or online cpu in aff_mask */
+ cpu = cpumask_next(cpu, aff_mask);
+
+ /* Find next online cpu in aff_mask to set affinity */
+ cpu_select = lpfc_next_online_cpu(aff_mask, cpu);
+ } else if (vectors == 1) {
+ cpu = cpumask_first(cpu_present_mask);
+ lpfc_assign_eq_map_info(phba, index, LPFC_CPU_FIRST_IRQ,
+ cpu);
+ } else {
+ maskp = pci_irq_get_affinity(phba->pcidev, index);
+
+ /* Loop through all CPUs associated with vector index */
+ for_each_cpu_and(cpu, maskp, cpu_present_mask) {
+ cpup = &phba->sli4_hba.cpu_map[cpu];
+
+ /* If this is the first CPU thats assigned to
+ * this vector, set LPFC_CPU_FIRST_IRQ.
+ *
+ * With certain platforms its possible that irq
+ * vectors are affinitized to all the cpu's.
+ * This can result in each cpu_map.eq to be set
+ * to the last vector, resulting in overwrite
+ * of all the previous cpu_map.eq. Ensure that
+ * each vector receives a place in cpu_map.
+ * Later call to lpfc_cpu_affinity_check will
+ * ensure we are nicely balanced out.
+ */
+ if (cpup->eq != LPFC_VECTOR_MAP_EMPTY)
+ continue;
+ lpfc_assign_eq_map_info(phba, index,
+ LPFC_CPU_FIRST_IRQ,
+ cpu);
+ break;
+ }
+ }
}
if (vectors != phba->cfg_irq_chann) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3238 Reducing IO channels to match number of "
"MSI-X vectors, requested %d got %d\n",
phba->cfg_irq_chann, vectors);
if (phba->cfg_irq_chann > vectors)
phba->cfg_irq_chann = vectors;
- if (phba->nvmet_support && (phba->cfg_nvmet_mrq > vectors))
- phba->cfg_nvmet_mrq = vectors;
}
return rc;
cfg_fail_out:
/* free the irq already requested */
- for (--index; index >= 0; index--)
- free_irq(pci_irq_vector(phba->pcidev, index),
- &phba->sli4_hba.hba_eq_hdl[index]);
+ for (--index; index >= 0; index--) {
+ eqhdl = lpfc_get_eq_hdl(index);
+ lpfc_irq_clear_aff(eqhdl);
+ irq_set_affinity_hint(eqhdl->irq, NULL);
+ free_irq(eqhdl->irq, eqhdl);
+ }
/* Unconfigure MSI-X capability structure */
pci_free_irq_vectors(phba->pcidev);
@@ -11201,6 +11658,8 @@
lpfc_sli4_enable_msi(struct lpfc_hba *phba)
{
int rc, index;
+ unsigned int cpu;
+ struct lpfc_hba_eq_hdl *eqhdl;
rc = pci_alloc_irq_vectors(phba->pcidev, 1, 1,
PCI_IRQ_MSI | PCI_IRQ_AFFINITY);
@@ -11222,9 +11681,15 @@
return rc;
}
+ eqhdl = lpfc_get_eq_hdl(0);
+ eqhdl->irq = pci_irq_vector(phba->pcidev, 0);
+
+ cpu = cpumask_first(cpu_present_mask);
+ lpfc_assign_eq_map_info(phba, 0, LPFC_CPU_FIRST_IRQ, cpu);
+
for (index = 0; index < phba->cfg_irq_chann; index++) {
- phba->sli4_hba.hba_eq_hdl[index].idx = index;
- phba->sli4_hba.hba_eq_hdl[index].phba = phba;
+ eqhdl = lpfc_get_eq_hdl(index);
+ eqhdl->idx = index;
}
return 0;
@@ -11233,6 +11698,7 @@
/**
* lpfc_sli4_enable_intr - Enable device interrupt to SLI-4 device
* @phba: pointer to lpfc hba data structure.
+ * @cfg_mode: Interrupt configuration mode (INTx, MSI or MSI-X).
*
* This routine is invoked to enable device interrupt and associate driver's
* interrupt handler(s) to interrupt vector(s) to device with SLI-4
@@ -11282,15 +11748,21 @@
IRQF_SHARED, LPFC_DRIVER_NAME, phba);
if (!retval) {
struct lpfc_hba_eq_hdl *eqhdl;
+ unsigned int cpu;
/* Indicate initialization to INTx mode */
phba->intr_type = INTx;
intr_mode = 0;
+ eqhdl = lpfc_get_eq_hdl(0);
+ eqhdl->irq = pci_irq_vector(phba->pcidev, 0);
+
+ cpu = cpumask_first(cpu_present_mask);
+ lpfc_assign_eq_map_info(phba, 0, LPFC_CPU_FIRST_IRQ,
+ cpu);
for (idx = 0; idx < phba->cfg_irq_chann; idx++) {
- eqhdl = &phba->sli4_hba.hba_eq_hdl[idx];
+ eqhdl = lpfc_get_eq_hdl(idx);
eqhdl->idx = idx;
- eqhdl->phba = phba;
}
}
}
@@ -11312,14 +11784,14 @@
/* Disable the currently initialized interrupt mode */
if (phba->intr_type == MSIX) {
int index;
+ struct lpfc_hba_eq_hdl *eqhdl;
/* Free up MSI-X multi-message vectors */
for (index = 0; index < phba->cfg_irq_chann; index++) {
- irq_set_affinity_hint(
- pci_irq_vector(phba->pcidev, index),
- NULL);
- free_irq(pci_irq_vector(phba->pcidev, index),
- &phba->sli4_hba.hba_eq_hdl[index]);
+ eqhdl = lpfc_get_eq_hdl(index);
+ lpfc_irq_clear_aff(eqhdl);
+ irq_set_affinity_hint(eqhdl->irq, NULL);
+ free_irq(eqhdl->irq, eqhdl);
}
} else {
free_irq(phba->pcidev->irq, phba);
@@ -11416,17 +11888,17 @@
while (!els_xri_cmpl || !io_xri_cmpl || !nvmet_xri_cmpl) {
if (wait_time > LPFC_XRI_EXCH_BUSY_WAIT_TMO) {
if (!nvmet_xri_cmpl)
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6424 NVMET XRI exchange busy "
"wait time: %d seconds.\n",
wait_time/1000);
if (!io_xri_cmpl)
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6100 IO XRI exchange busy "
"wait time: %d seconds.\n",
wait_time/1000);
if (!els_xri_cmpl)
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2878 ELS XRI exchange busy "
"wait time: %d seconds.\n",
wait_time/1000);
@@ -11615,6 +12087,7 @@
sli4_params->cqav = bf_get(cfg_cqav, mbx_sli4_parameters);
sli4_params->wqsize = bf_get(cfg_wqsize, mbx_sli4_parameters);
sli4_params->bv1s = bf_get(cfg_bv1s, mbx_sli4_parameters);
+ sli4_params->pls = bf_get(cfg_pvl, mbx_sli4_parameters);
sli4_params->sgl_pages_max = bf_get(cfg_sgl_page_cnt,
mbx_sli4_parameters);
sli4_params->wqpcnt = bf_get(cfg_wqpcnt, mbx_sli4_parameters);
@@ -11666,13 +12139,10 @@
}
/* If the NVME FC4 type is enabled, scale the sg_seg_cnt to
- * accommodate 512K and 1M IOs in a single nvme buf and supply
- * enough NVME LS iocb buffers for larger connectivity counts.
+ * accommodate 512K and 1M IOs in a single nvme buf.
*/
- if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) {
+ if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME)
phba->cfg_sg_seg_cnt = LPFC_MAX_NVME_SEG_CNT;
- phba->cfg_iocb_cnt = 5;
- }
/* Only embed PBDE for if_type 6, PBDE support requires xib be set */
if ((bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
@@ -11852,14 +12322,14 @@
/* Configure and enable interrupt */
intr_mode = lpfc_sli_enable_intr(phba, cfg_mode);
if (intr_mode == LPFC_INTR_ERROR) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0431 Failed to enable interrupt.\n");
error = -ENODEV;
goto out_free_sysfs_attr;
}
/* SLI-3 HBA setup */
if (lpfc_sli_hba_setup(phba)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1477 Failed to set up hba\n");
error = -ENODEV;
goto out_remove_device;
@@ -12117,7 +12587,7 @@
/* Configure and enable interrupt */
intr_mode = lpfc_sli_enable_intr(phba, phba->intr_mode);
if (intr_mode == LPFC_INTR_ERROR) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0430 PM resume Failed to enable interrupt\n");
return -EIO;
} else
@@ -12143,7 +12613,7 @@
static void
lpfc_sli_prep_dev_for_recover(struct lpfc_hba *phba)
{
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2723 PCI channel I/O abort preparing for recovery\n");
/*
@@ -12164,7 +12634,7 @@
static void
lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba)
{
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2710 PCI channel disable preparing for reset\n");
/* Block any management I/Os to the device */
@@ -12195,7 +12665,7 @@
static void
lpfc_sli_prep_dev_for_perm_failure(struct lpfc_hba *phba)
{
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2711 PCI channel permanent disable for failure\n");
/* Block all SCSI devices' I/Os on the host */
lpfc_scsi_dev_block(phba);
@@ -12246,7 +12716,7 @@
return PCI_ERS_RESULT_DISCONNECT;
default:
/* Unknown state, prepare and request slot reset */
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0472 Unknown PCI error state: x%x\n", state);
lpfc_sli_prep_dev_for_reset(phba);
return PCI_ERS_RESULT_NEED_RESET;
@@ -12304,7 +12774,7 @@
/* Configure and enable interrupt */
intr_mode = lpfc_sli_enable_intr(phba, phba->intr_mode);
if (intr_mode == LPFC_INTR_ERROR) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0427 Cannot re-enable interrupt after "
"slot reset.\n");
return PCI_ERS_RESULT_DISCONNECT;
@@ -12389,35 +12859,56 @@
}
-static void
+static int
lpfc_log_write_firmware_error(struct lpfc_hba *phba, uint32_t offset,
uint32_t magic_number, uint32_t ftype, uint32_t fid, uint32_t fsize,
const struct firmware *fw)
{
- if ((offset == ADD_STATUS_FW_NOT_SUPPORTED) ||
- (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC &&
- magic_number != MAGIC_NUMER_G6) ||
- (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC &&
- magic_number != MAGIC_NUMER_G7))
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "3030 This firmware version is not supported on "
- "this HBA model. Device:%x Magic:%x Type:%x "
- "ID:%x Size %d %zd\n",
- phba->pcidev->device, magic_number, ftype, fid,
- fsize, fw->size);
- else
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "3022 FW Download failed. Device:%x Magic:%x Type:%x "
- "ID:%x Size %d %zd\n",
- phba->pcidev->device, magic_number, ftype, fid,
- fsize, fw->size);
-}
+ int rc;
+ /* Three cases: (1) FW was not supported on the detected adapter.
+ * (2) FW update has been locked out administratively.
+ * (3) Some other error during FW update.
+ * In each case, an unmaskable message is written to the console
+ * for admin diagnosis.
+ */
+ if (offset == ADD_STATUS_FW_NOT_SUPPORTED ||
+ (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC &&
+ magic_number != MAGIC_NUMBER_G6) ||
+ (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC &&
+ magic_number != MAGIC_NUMBER_G7)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "3030 This firmware version is not supported on"
+ " this HBA model. Device:%x Magic:%x Type:%x "
+ "ID:%x Size %d %zd\n",
+ phba->pcidev->device, magic_number, ftype, fid,
+ fsize, fw->size);
+ rc = -EINVAL;
+ } else if (offset == ADD_STATUS_FW_DOWNLOAD_HW_DISABLED) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "3021 Firmware downloads have been prohibited "
+ "by a system configuration setting on "
+ "Device:%x Magic:%x Type:%x ID:%x Size %d "
+ "%zd\n",
+ phba->pcidev->device, magic_number, ftype, fid,
+ fsize, fw->size);
+ rc = -EACCES;
+ } else {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "3022 FW Download failed. Add Status x%x "
+ "Device:%x Magic:%x Type:%x ID:%x Size %d "
+ "%zd\n",
+ offset, phba->pcidev->device, magic_number,
+ ftype, fid, fsize, fw->size);
+ rc = -EIO;
+ }
+ return rc;
+}
/**
* lpfc_write_firmware - attempt to write a firmware image to the port
* @fw: pointer to firmware image returned from request_firmware.
- * @phba: pointer to lpfc hba data structure.
+ * @context: pointer to firmware image returned from request_firmware.
*
**/
static void
@@ -12447,7 +12938,7 @@
INIT_LIST_HEAD(&dma_buffer_list);
lpfc_decode_firmware_rev(phba, fwrev, 1);
if (strncmp(fwrev, image->revision, strnlen(image->revision, 16))) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3023 Updating Firmware, Current Version:%s "
"New Version:%s\n",
fwrev, image->revision);
@@ -12486,14 +12977,18 @@
rc = lpfc_wr_object(phba, &dma_buffer_list,
(fw->size - offset), &offset);
if (rc) {
- lpfc_log_write_firmware_error(phba, offset,
- magic_number, ftype, fid, fsize, fw);
+ rc = lpfc_log_write_firmware_error(phba, offset,
+ magic_number,
+ ftype,
+ fid,
+ fsize,
+ fw);
goto release_out;
}
}
rc = offset;
} else
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3029 Skipped Firmware update, Current "
"Version:%s New Version:%s\n",
fwrev, image->revision);
@@ -12507,14 +13002,18 @@
}
release_firmware(fw);
out:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "3024 Firmware update done: %d.\n", rc);
- return;
+ if (rc < 0)
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "3062 Firmware update error, status %d.\n", rc);
+ else
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "3024 Firmware update success: size %d.\n", rc);
}
/**
* lpfc_sli4_request_firmware_update - Request linux generic firmware upgrade
* @phba: pointer to lpfc hba data structure.
+ * @fw_upgrade: which firmware to update.
*
* This routine is called to perform Linux generic firmware upgrade on device
* that supports such feature.
@@ -12581,6 +13080,8 @@
if (!phba)
return -ENOMEM;
+ INIT_LIST_HEAD(&phba->poll_list);
+
/* Perform generic PCI device enabling operation */
error = lpfc_enable_pci_dev(phba);
if (error)
@@ -12628,10 +13129,16 @@
phba->pport = NULL;
lpfc_stop_port(phba);
+ /* Init cpu_map array */
+ lpfc_cpu_map_array_init(phba);
+
+ /* Init hba_eq_hdl array */
+ lpfc_hba_eq_hdl_array_init(phba);
+
/* Configure and enable interrupt */
intr_mode = lpfc_sli4_enable_intr(phba, cfg_mode);
if (intr_mode == LPFC_INTR_ERROR) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0426 Failed to enable interrupt.\n");
error = -ENODEV;
goto out_unset_driver_resource;
@@ -12666,7 +13173,7 @@
/* Set up SLI-4 HBA */
if (lpfc_sli4_hba_setup(phba)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1421 Failed to set up hba\n");
error = -ENODEV;
goto out_free_sysfs_attr;
@@ -12691,7 +13198,7 @@
*/
error = lpfc_nvme_create_localport(vport);
if (error) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6004 NVME registration "
"failed, error x%x\n",
error);
@@ -12709,7 +13216,7 @@
/* Enable RAS FW log support */
lpfc_sli4_ras_setup(phba);
- INIT_LIST_HEAD(&phba->poll_list);
+ timer_setup(&phba->cpuhp_poll_timer, lpfc_sli4_poll_hbtimer, 0);
cpuhp_state_add_instance_nocalls(lpfc_cpuhp_state, &phba->cpuhp);
return 0;
@@ -12924,7 +13431,7 @@
/* Configure and enable interrupt */
intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode);
if (intr_mode == LPFC_INTR_ERROR) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0294 PM resume Failed to enable interrupt\n");
return -EIO;
} else
@@ -12950,7 +13457,7 @@
static void
lpfc_sli4_prep_dev_for_recover(struct lpfc_hba *phba)
{
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2828 PCI channel I/O abort preparing for recovery\n");
/*
* There may be errored I/Os through HBA, abort all I/Os on txcmplq
@@ -12970,7 +13477,7 @@
static void
lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba)
{
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2826 PCI channel disable preparing for reset\n");
/* Block any management I/Os to the device */
@@ -13002,7 +13509,7 @@
static void
lpfc_sli4_prep_dev_for_perm_failure(struct lpfc_hba *phba)
{
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2827 PCI channel permanent disable for failure\n");
/* Block all SCSI devices' I/Os on the host */
@@ -13052,7 +13559,7 @@
return PCI_ERS_RESULT_DISCONNECT;
default:
/* Unknown state, prepare and request slot reset */
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2825 Unknown PCI error state: x%x\n", state);
lpfc_sli4_prep_dev_for_reset(phba);
return PCI_ERS_RESULT_NEED_RESET;
@@ -13110,7 +13617,7 @@
/* Configure and enable interrupt */
intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode);
if (intr_mode == LPFC_INTR_ERROR) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2824 Cannot re-enable interrupt after "
"slot reset.\n");
return PCI_ERS_RESULT_DISCONNECT;
@@ -13215,7 +13722,7 @@
lpfc_pci_remove_one_s4(pdev);
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1424 Invalid PCI device group: 0x%x\n",
phba->pci_dev_grp);
break;
@@ -13252,7 +13759,7 @@
rc = lpfc_pci_suspend_one_s4(pdev, msg);
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1425 Invalid PCI device group: 0x%x\n",
phba->pci_dev_grp);
break;
@@ -13288,7 +13795,7 @@
rc = lpfc_pci_resume_one_s4(pdev);
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1426 Invalid PCI device group: 0x%x\n",
phba->pci_dev_grp);
break;
@@ -13326,7 +13833,7 @@
rc = lpfc_io_error_detected_s4(pdev, state);
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1427 Invalid PCI device group: 0x%x\n",
phba->pci_dev_grp);
break;
@@ -13363,7 +13870,7 @@
rc = lpfc_io_slot_reset_s4(pdev);
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1428 Invalid PCI device group: 0x%x\n",
phba->pci_dev_grp);
break;
@@ -13395,7 +13902,7 @@
lpfc_io_resume_s4(pdev);
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1429 Invalid PCI device group: 0x%x\n",
phba->pci_dev_grp);
break;
@@ -13424,8 +13931,7 @@
phba->cfg_fof = 1;
} else {
phba->cfg_fof = 0;
- if (phba->device_data_mem_pool)
- mempool_destroy(phba->device_data_mem_pool);
+ mempool_destroy(phba->device_data_mem_pool);
phba->device_data_mem_pool = NULL;
}
@@ -13504,25 +14010,26 @@
{
int error = 0;
- printk(LPFC_MODULE_DESC "\n");
- printk(LPFC_COPYRIGHT "\n");
+ pr_info(LPFC_MODULE_DESC "\n");
+ pr_info(LPFC_COPYRIGHT "\n");
error = misc_register(&lpfc_mgmt_dev);
if (error)
printk(KERN_ERR "Could not register lpfcmgmt device, "
"misc_register returned with status %d", error);
+ error = -ENOMEM;
lpfc_transport_functions.vport_create = lpfc_vport_create;
lpfc_transport_functions.vport_delete = lpfc_vport_delete;
lpfc_transport_template =
fc_attach_transport(&lpfc_transport_functions);
if (lpfc_transport_template == NULL)
- return -ENOMEM;
+ goto unregister;
lpfc_vport_transport_template =
fc_attach_transport(&lpfc_vport_transport_functions);
if (lpfc_vport_transport_template == NULL) {
fc_release_transport(lpfc_transport_template);
- return -ENOMEM;
+ goto unregister;
}
lpfc_nvme_cmd_template();
lpfc_nvmet_cmd_template();
@@ -13548,10 +14055,91 @@
cpuhp_failure:
fc_release_transport(lpfc_transport_template);
fc_release_transport(lpfc_vport_transport_template);
+unregister:
+ misc_deregister(&lpfc_mgmt_dev);
return error;
}
+void lpfc_dmp_dbg(struct lpfc_hba *phba)
+{
+ unsigned int start_idx;
+ unsigned int dbg_cnt;
+ unsigned int temp_idx;
+ int i;
+ int j = 0;
+ unsigned long rem_nsec;
+
+ if (phba->cfg_log_verbose)
+ return;
+
+ if (atomic_cmpxchg(&phba->dbg_log_dmping, 0, 1) != 0)
+ return;
+
+ start_idx = (unsigned int)atomic_read(&phba->dbg_log_idx) % DBG_LOG_SZ;
+ dbg_cnt = (unsigned int)atomic_read(&phba->dbg_log_cnt);
+ temp_idx = start_idx;
+ if (dbg_cnt >= DBG_LOG_SZ) {
+ dbg_cnt = DBG_LOG_SZ;
+ temp_idx -= 1;
+ } else {
+ if ((start_idx + dbg_cnt) > (DBG_LOG_SZ - 1)) {
+ temp_idx = (start_idx + dbg_cnt) % DBG_LOG_SZ;
+ } else {
+ if (start_idx < dbg_cnt)
+ start_idx = DBG_LOG_SZ - (dbg_cnt - start_idx);
+ else
+ start_idx -= dbg_cnt;
+ }
+ }
+ dev_info(&phba->pcidev->dev, "start %d end %d cnt %d\n",
+ start_idx, temp_idx, dbg_cnt);
+
+ for (i = 0; i < dbg_cnt; i++) {
+ if ((start_idx + i) < DBG_LOG_SZ)
+ temp_idx = (start_idx + i) % DBG_LOG_SZ;
+ else
+ temp_idx = j++;
+ rem_nsec = do_div(phba->dbg_log[temp_idx].t_ns, NSEC_PER_SEC);
+ dev_info(&phba->pcidev->dev, "%d: [%5lu.%06lu] %s",
+ temp_idx,
+ (unsigned long)phba->dbg_log[temp_idx].t_ns,
+ rem_nsec / 1000,
+ phba->dbg_log[temp_idx].log);
+ }
+ atomic_set(&phba->dbg_log_cnt, 0);
+ atomic_set(&phba->dbg_log_dmping, 0);
+}
+
+__printf(2, 3)
+void lpfc_dbg_print(struct lpfc_hba *phba, const char *fmt, ...)
+{
+ unsigned int idx;
+ va_list args;
+ int dbg_dmping = atomic_read(&phba->dbg_log_dmping);
+ struct va_format vaf;
+
+
+ va_start(args, fmt);
+ if (unlikely(dbg_dmping)) {
+ vaf.fmt = fmt;
+ vaf.va = &args;
+ dev_info(&phba->pcidev->dev, "%pV", &vaf);
+ va_end(args);
+ return;
+ }
+ idx = (unsigned int)atomic_fetch_add(1, &phba->dbg_log_idx) %
+ DBG_LOG_SZ;
+
+ atomic_inc(&phba->dbg_log_cnt);
+
+ vscnprintf(phba->dbg_log[idx].log,
+ sizeof(phba->dbg_log[idx].log), fmt, args);
+ va_end(args);
+
+ phba->dbg_log[idx].t_ns = local_clock();
+}
+
/**
* lpfc_exit - lpfc module removal routine
*
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h
index ea10f03..5660a87 100644
--- a/drivers/scsi/lpfc/lpfc_logmsg.h
+++ b/drivers/scsi/lpfc/lpfc_logmsg.h
@@ -44,13 +44,40 @@
#define LOG_NVME_DISC 0x00200000 /* NVME Discovery/Connect events. */
#define LOG_NVME_ABTS 0x00400000 /* NVME ABTS events. */
#define LOG_NVME_IOERR 0x00800000 /* NVME IO Error events. */
-#define LOG_ALL_MSG 0xffffffff /* LOG all messages */
+#define LOG_TRACE_EVENT 0x80000000 /* Dmp the DBG log on this err */
+#define LOG_ALL_MSG 0x7fffffff /* LOG all messages */
+
+void lpfc_dmp_dbg(struct lpfc_hba *phba);
+void lpfc_dbg_print(struct lpfc_hba *phba, const char *fmt, ...);
+
+/* generate message by verbose log setting or severity */
+#define lpfc_vlog_msg(vport, level, mask, fmt, arg...) \
+{ if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '4')) \
+ dev_printk(level, &((vport)->phba->pcidev)->dev, "%d:(%d):" \
+ fmt, (vport)->phba->brd_no, vport->vpi, ##arg); }
+
+#define lpfc_log_msg(phba, level, mask, fmt, arg...) \
+do { \
+ { uint32_t log_verbose = (phba)->pport ? \
+ (phba)->pport->cfg_log_verbose : \
+ (phba)->cfg_log_verbose; \
+ if (((mask) & log_verbose) || (level[1] <= '4')) \
+ dev_printk(level, &((phba)->pcidev)->dev, "%d:" \
+ fmt, phba->brd_no, ##arg); \
+ } \
+} while (0)
#define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \
do { \
- { if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '3')) \
+ { if (((mask) & (vport)->cfg_log_verbose) || (level[1] <= '3')) { \
+ if ((mask) & LOG_TRACE_EVENT) \
+ lpfc_dmp_dbg((vport)->phba); \
dev_printk(level, &((vport)->phba->pcidev)->dev, "%d:(%d):" \
- fmt, (vport)->phba->brd_no, vport->vpi, ##arg); } \
+ fmt, (vport)->phba->brd_no, vport->vpi, ##arg); \
+ } else if (!(vport)->cfg_log_verbose) \
+ lpfc_dbg_print((vport)->phba, "%d:(%d):" fmt, \
+ (vport)->phba->brd_no, (vport)->vpi, ##arg); \
+ } \
} while (0)
#define lpfc_printf_log(phba, level, mask, fmt, arg...) \
@@ -58,8 +85,12 @@
{ uint32_t log_verbose = (phba)->pport ? \
(phba)->pport->cfg_log_verbose : \
(phba)->cfg_log_verbose; \
- if (((mask) & log_verbose) || (level[1] <= '3')) \
+ if (((mask) & log_verbose) || (level[1] <= '3')) { \
+ if ((mask) & LOG_TRACE_EVENT) \
+ lpfc_dmp_dbg(phba); \
dev_printk(level, &((phba)->pcidev)->dev, "%d:" \
- fmt, phba->brd_no, ##arg); \
+ fmt, phba->brd_no, ##arg); \
+ } else if (!(phba)->cfg_log_verbose)\
+ lpfc_dbg_print(phba, "%d:" fmt, phba->brd_no, ##arg); \
} \
} while (0)
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 4a33116..8764fdf 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -515,6 +515,7 @@
if ((phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC ||
phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC) &&
+ !(phba->sli4_hba.pc_sli4_params.pls) &&
mb->un.varInitLnk.link_flags & FLAGS_TOPOLOGY_MODE_LOOP) {
mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
phba->cfg_topology = FLAGS_TOPOLOGY_MODE_PT_PT;
@@ -867,9 +868,7 @@
/**
* lpfc_reg_vpi - Prepare a mailbox command for registering vport identifier
- * @phba: pointer to lpfc hba data structure.
- * @vpi: virtual N_Port identifier.
- * @sid: Fibre Channel S_ID (N_Port_ID assigned to a virtual N_Port).
+ * @vport: pointer to a vport object.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
* The registration vport identifier mailbox command is used to activate a
@@ -1198,7 +1197,7 @@
/**
* lpfc_config_ring - Prepare a mailbox command for configuring an IOCB ring
* @phba: pointer to lpfc hba data structure.
- * @ring:
+ * @ring: ring number/index
* @pmb: pointer to the driver internal queue element for mailbox command.
*
* The configure ring mailbox command is used to configure an IOCB ring. This
@@ -1298,8 +1297,6 @@
if (phba->sli_rev == LPFC_SLI_REV3 && phba->vpd.sli3Feat.cerbm) {
if (phba->cfg_enable_bg)
mb->un.varCfgPort.cbg = 1; /* configure BlockGuard */
- if (phba->cfg_enable_dss)
- mb->un.varCfgPort.cdss = 1; /* Configure Security */
mb->un.varCfgPort.cerbm = 1; /* Request HBQs */
mb->un.varCfgPort.ccrp = 1; /* Command Ring Polling */
mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count();
@@ -1379,7 +1376,8 @@
*/
if (phba->cfg_hostmem_hgp && phba->sli_rev != 3) {
- phba->host_gp = &phba->mbox->us.s2.host[0];
+ phba->host_gp = (struct lpfc_hgp __iomem *)
+ &phba->mbox->us.s2.host[0];
phba->hbq_put = NULL;
offset = (uint8_t *)&phba->mbox->us.s2.host -
(uint8_t *)phba->slim2p.virt;
@@ -1613,7 +1611,7 @@
/**
* lpfc_mbox_tmo_val - Retrieve mailbox command timeout value
* @phba: pointer to lpfc hba data structure.
- * @cmd: mailbox command code.
+ * @mboxq: pointer to the driver internal queue element for mailbox command.
*
* This routine retrieves the proper timeout value according to the mailbox
* command code.
@@ -1700,6 +1698,7 @@
* lpfc_sli4_mbx_sge_get - Get a sge entry from non-embedded mailbox command
* @mbox: pointer to lpfc mbox command.
* @sgentry: sge entry index.
+ * @sge: pointer to lpfc mailbox sge to load into.
*
* This routine gets an entry from the non-embedded mailbox command at the sge
* index location.
@@ -1767,6 +1766,7 @@
* @subsystem: The sli4 config sub mailbox subsystem.
* @opcode: The sli4 config sub mailbox command opcode.
* @length: Length of the sli4 config mailbox command (including sub-header).
+ * @emb: True if embedded mbox command should be setup.
*
* This routine sets up the header fields of SLI4 specific mailbox command
* for sending IOCTL command.
@@ -2012,6 +2012,7 @@
/**
* lpfc_sli4_mbx_read_fcf_rec - Allocate and construct read fcf mbox cmd
* @phba: pointer to lpfc hba data structure.
+ * @mboxq: pointer to lpfc mbox command.
* @fcf_index: index to fcf table.
*
* This routine routine allocates and constructs non-embedded mailbox command
@@ -2068,6 +2069,7 @@
/**
* lpfc_request_features: Configure SLI4 REQUEST_FEATURES mailbox
+ * @phba: pointer to lpfc hba data structure.
* @mboxq: pointer to lpfc mbox command.
*
* This routine sets up the mailbox for an SLI4 REQUEST_FEATURES
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index ef75fd6..be54fbf 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -31,8 +31,6 @@
#include <scsi/scsi_transport_fc.h>
#include <scsi/fc/fc_fs.h>
-#include <linux/nvme-fc-driver.h>
-
#include "lpfc_hw4.h"
#include "lpfc_hw.h"
#include "lpfc_sli.h"
@@ -41,14 +39,14 @@
#include "lpfc_disc.h"
#include "lpfc.h"
#include "lpfc_scsi.h"
-#include "lpfc_nvme.h"
-#include "lpfc_nvmet.h"
#include "lpfc_crtn.h"
#include "lpfc_logmsg.h"
#define LPFC_MBUF_POOL_SIZE 64 /* max elements in MBUF safety pool */
#define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */
#define LPFC_DEVICE_DATA_POOL_SIZE 64 /* max elements in device data pool */
+#define LPFC_RRQ_POOL_SIZE 256 /* max elements in non-DMA pool */
+#define LPFC_MBX_POOL_SIZE 256 /* max elements in MBX non-DMA pool */
int
lpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *phba) {
@@ -71,6 +69,7 @@
/**
* lpfc_mem_alloc - create and allocate all PCI and memory pools
* @phba: HBA to allocate pools for
+ * @align: alignment requirement for blocks; must be a power of two
*
* Description: Creates and allocates PCI pools lpfc_mbuf_pool,
* lpfc_hrb_pool. Creates and allocates kmalloc-backed mempools
@@ -113,8 +112,8 @@
pool->current_count++;
}
- phba->mbox_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE,
- sizeof(LPFC_MBOXQ_t));
+ phba->mbox_mem_pool = mempool_create_kmalloc_pool(LPFC_MBX_POOL_SIZE,
+ sizeof(LPFC_MBOXQ_t));
if (!phba->mbox_mem_pool)
goto fail_free_mbuf_pool;
@@ -125,7 +124,7 @@
if (phba->sli_rev == LPFC_SLI_REV4) {
phba->rrq_pool =
- mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE,
+ mempool_create_kmalloc_pool(LPFC_RRQ_POOL_SIZE,
sizeof(struct lpfc_node_rrq));
if (!phba->rrq_pool)
goto fail_free_nlp_mem_pool;
@@ -230,9 +229,6 @@
dma_pool_destroy(phba->lpfc_hrb_pool);
phba->lpfc_hrb_pool = NULL;
- dma_pool_destroy(phba->txrdy_payload_pool);
- phba->txrdy_payload_pool = NULL;
-
dma_pool_destroy(phba->lpfc_hbq_pool);
phba->lpfc_hbq_pool = NULL;
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index fdd8750..e33f752 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -32,8 +32,6 @@
#include <scsi/scsi_transport_fc.h>
#include <scsi/fc/fc_fs.h>
-#include <linux/nvme-fc-driver.h>
-
#include "lpfc_hw4.h"
#include "lpfc_hw.h"
#include "lpfc_sli.h"
@@ -154,7 +152,7 @@
memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name));
return 1;
bad_service_param:
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0207 Device %x "
"(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x) sent "
"invalid service parameters. Ignoring device.\n",
@@ -303,7 +301,7 @@
/* Check for CONFIG_LINK error */
if (mb->mbxStatus) {
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"4575 CONFIG_LINK fails pt2pt discovery: %x\n",
mb->mbxStatus);
mempool_free(login_mbox, phba->mbox_mem_pool);
@@ -318,7 +316,7 @@
rc = lpfc_els_rsp_acc(link_mbox->vport, ELS_CMD_PLOGI,
save_iocb, ndlp, login_mbox);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"4576 PLOGI ACC fails pt2pt discovery: %x\n",
rc);
mempool_free(login_mbox, phba->mbox_mem_pool);
@@ -363,7 +361,7 @@
lpfc_sli4_unreg_rpi_cmpl_clr(phba, pmb);
if (!piocb) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY | LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"4578 PLOGI ACC fail\n");
if (mbox)
mempool_free(mbox, phba->mbox_mem_pool);
@@ -372,7 +370,7 @@
rc = lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, piocb, ndlp, mbox);
if (rc) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY | LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"4579 PLOGI ACC fail %x\n", rc);
if (mbox)
mempool_free(mbox, phba->mbox_mem_pool);
@@ -407,7 +405,7 @@
lp = (uint32_t *) pcmd->virt;
sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
if (wwn_to_u64(sp->portName.u.wwn) == 0) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0140 PLOGI Reject: invalid nname\n");
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_PNAME;
@@ -416,7 +414,7 @@
return 0;
}
if (wwn_to_u64(sp->nodeName.u.wwn) == 0) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0141 PLOGI Reject: invalid pname\n");
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_NNAME;
@@ -466,7 +464,7 @@
case NLP_STE_NPR_NODE:
if (!(ndlp->nlp_flag & NLP_NPR_ADISC))
break;
- /* fall through */
+ fallthrough;
case NLP_STE_REG_LOGIN_ISSUE:
case NLP_STE_PRLI_ISSUE:
case NLP_STE_UNMAPPED_NODE:
@@ -483,7 +481,7 @@
}
if (nlp_portwwn != 0 &&
nlp_portwwn != wwn_to_u64(sp->portName.u.wwn))
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0143 PLOGI recv'd from DID: x%x "
"WWPN changed: old %llx new %llx\n",
ndlp->nlp_DID,
@@ -491,6 +489,11 @@
(unsigned long long)
wwn_to_u64(sp->portName.u.wwn));
+ /* Notify transport of connectivity loss to trigger cleanup. */
+ if (phba->nvmet_support &&
+ ndlp->nlp_state == NLP_STE_UNMAPPED_NODE)
+ lpfc_nvmet_invalidate_host(phba, ndlp);
+
ndlp->nlp_prev_state = ndlp->nlp_state;
/* rport needs to be unregistered first */
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
@@ -686,7 +689,7 @@
return 1;
out:
if (defer_acc)
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"4577 discovery failure: %p %p %p\n",
save_iocb, link_mbox, login_mbox);
kfree(save_iocb);
@@ -794,11 +797,17 @@
ndlp, NULL);
}
out:
- /* If we are authenticated, move to the proper state */
- if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET))
- lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
- else
- lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
+ /* If we are authenticated, move to the proper state.
+ * It is possible an ADISC arrived and the remote nport
+ * is already in MAPPED or UNMAPPED state. Catch this
+ * condition and don't set the nlp_state again because
+ * it causes an unnecessary transport unregister/register.
+ */
+ if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET)) {
+ if (ndlp->nlp_state != NLP_STE_MAPPED_NODE)
+ lpfc_nlp_set_state(vport, ndlp,
+ NLP_STE_MAPPED_NODE);
+ }
return 1;
}
@@ -841,6 +850,12 @@
lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
else
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
+
+ /* Notify transport of connectivity loss to trigger cleanup. */
+ if (phba->nvmet_support &&
+ ndlp->nlp_state == NLP_STE_UNMAPPED_NODE)
+ lpfc_nvmet_invalidate_host(phba, ndlp);
+
if (ndlp->nlp_DID == Fabric_DID) {
if (vport->port_state <= LPFC_FDISC)
goto out;
@@ -1058,6 +1073,7 @@
* lpfc_release_rpi - Release a RPI by issuing unreg_login mailbox cmd.
* @phba : Pointer to lpfc_hba structure.
* @vport: Pointer to lpfc_vport structure.
+ * @ndlp: Pointer to lpfc_nodelist structure.
* @rpi : rpi to be release.
*
* This function will send a unreg_login mailbox command to the firmware
@@ -1087,8 +1103,8 @@
pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
GFP_KERNEL);
if (!pmb)
- lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
- "2796 mailbox memory allocation failed \n");
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "2796 mailbox memory allocation failed \n");
else {
lpfc_unreg_login(phba, vport->vpi, rpi, pmb);
pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
@@ -1126,7 +1142,7 @@
rpi = pmb->u.mb.un.varWords[0];
lpfc_release_rpi(phba, vport, ndlp, rpi);
}
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0271 Illegal State Transition: node x%x "
"event x%x, state x%x Data: x%x x%x\n",
ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,
@@ -1144,11 +1160,11 @@
* to stop it.
*/
if (!(ndlp->nlp_flag & NLP_RCV_PLOGI)) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
- "0272 Illegal State Transition: node x%x "
- "event x%x, state x%x Data: x%x x%x\n",
- ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,
- ndlp->nlp_flag);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "0272 Illegal State Transition: node x%x "
+ "event x%x, state x%x Data: x%x x%x\n",
+ ndlp->nlp_DID, evt, ndlp->nlp_state,
+ ndlp->nlp_rpi, ndlp->nlp_flag);
}
return ndlp->nlp_state;
}
@@ -1368,7 +1384,7 @@
if ((ndlp->nlp_DID != FDMI_DID) &&
(wwn_to_u64(sp->portName.u.wwn) == 0 ||
wwn_to_u64(sp->nodeName.u.wwn) == 0)) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0142 PLOGI RSP: Invalid WWN.\n");
goto out;
}
@@ -1430,7 +1446,8 @@
} else {
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0133 PLOGI: no memory "
"for config_link "
"Data: x%x x%x x%x x%x\n",
@@ -1455,7 +1472,7 @@
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0018 PLOGI: no memory for reg_login "
"Data: x%x x%x x%x x%x\n",
ndlp->nlp_DID, ndlp->nlp_state,
@@ -1495,7 +1512,7 @@
kfree(mp);
mempool_free(mbox, phba->mbox_mem_pool);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0134 PLOGI: cannot issue reg_login "
"Data: x%x x%x x%x x%x\n",
ndlp->nlp_DID, ndlp->nlp_state,
@@ -1503,7 +1520,7 @@
} else {
mempool_free(mbox, phba->mbox_mem_pool);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0135 PLOGI: cannot format reg_login "
"Data: x%x x%x x%x x%x\n",
ndlp->nlp_DID, ndlp->nlp_state,
@@ -1514,7 +1531,7 @@
out:
if (ndlp->nlp_DID == NameServer_DID) {
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0261 Cannot Register NameServer login\n");
}
@@ -1733,7 +1750,13 @@
}
}
- if (ndlp->nlp_type & NLP_FCP_TARGET) {
+ if (ndlp->nlp_type & NLP_FCP_TARGET)
+ ndlp->nlp_fc4_type |= NLP_FC4_FCP;
+
+ if (ndlp->nlp_type & NLP_NVME_TARGET)
+ ndlp->nlp_fc4_type |= NLP_FC4_NVME;
+
+ if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET)) {
ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
} else {
@@ -1936,8 +1959,8 @@
if (mb->mbxStatus) {
/* RegLogin failed */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
- "0246 RegLogin failed Data: x%x x%x x%x x%x "
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "0246 RegLogin failed Data: x%x x%x x%x x%x "
"x%x\n",
did, mb->mbxStatus, vport->port_state,
mb->un.varRegLogin.vpi,
@@ -1987,8 +2010,9 @@
* is configured try it.
*/
ndlp->nlp_fc4_type |= NLP_FC4_FCP;
- if ((vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||
- (vport->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) {
+ if ((!(vport->fc_flag & FC_PT2PT_NO_NVME)) &&
+ (vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH ||
+ vport->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) {
ndlp->nlp_fc4_type |= NLP_FC4_NVME;
/* We need to update the localport also */
lpfc_nvme_update_localport(vport);
@@ -2214,7 +2238,9 @@
if (bf_get_be32(prli_init, nvpr))
ndlp->nlp_type |= NLP_NVME_INITIATOR;
- if (phba->nsler && bf_get_be32(prli_nsler, nvpr))
+ if (phba->nsler && bf_get_be32(prli_nsler, nvpr) &&
+ bf_get_be32(prli_conf, nvpr))
+
ndlp->nlp_nvme_info |= NLP_NVME_NSLER;
else
ndlp->nlp_nvme_info &= ~NLP_NVME_NSLER;
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 5a86a1e..03c81ce 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -36,9 +36,6 @@
#include <scsi/scsi_transport_fc.h>
#include <scsi/fc/fc_fs.h>
-#include <linux/nvme.h>
-#include <linux/nvme-fc-driver.h>
-#include <linux/nvme-fc.h>
#include "lpfc_version.h"
#include "lpfc_hw4.h"
#include "lpfc_hw.h"
@@ -196,9 +193,51 @@
}
/**
+ * lpfc_nvme_prep_abort_wqe - set up 'abort' work queue entry.
+ * @pwqeq: Pointer to command iocb.
+ * @xritag: Tag that uniqely identifies the local exchange resource.
+ * @opt: Option bits -
+ * bit 0 = inhibit sending abts on the link
+ *
+ * This function is called with hbalock held.
+ **/
+void
+lpfc_nvme_prep_abort_wqe(struct lpfc_iocbq *pwqeq, u16 xritag, u8 opt)
+{
+ union lpfc_wqe128 *wqe = &pwqeq->wqe;
+
+ /* WQEs are reused. Clear stale data and set key fields to
+ * zero like ia, iaab, iaar, xri_tag, and ctxt_tag.
+ */
+ memset(wqe, 0, sizeof(*wqe));
+
+ if (opt & INHIBIT_ABORT)
+ bf_set(abort_cmd_ia, &wqe->abort_cmd, 1);
+ /* Abort specified xri tag, with the mask deliberately zeroed */
+ bf_set(abort_cmd_criteria, &wqe->abort_cmd, T_XRI_TAG);
+
+ bf_set(wqe_cmnd, &wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX);
+
+ /* Abort the IO associated with this outstanding exchange ID. */
+ wqe->abort_cmd.wqe_com.abort_tag = xritag;
+
+ /* iotag for the wqe completion. */
+ bf_set(wqe_reqtag, &wqe->abort_cmd.wqe_com, pwqeq->iotag);
+
+ bf_set(wqe_qosd, &wqe->abort_cmd.wqe_com, 1);
+ bf_set(wqe_lenloc, &wqe->abort_cmd.wqe_com, LPFC_WQE_LENLOC_NONE);
+
+ bf_set(wqe_cmd_type, &wqe->abort_cmd.wqe_com, OTHER_COMMAND);
+ bf_set(wqe_wqec, &wqe->abort_cmd.wqe_com, 1);
+ bf_set(wqe_cqid, &wqe->abort_cmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
+}
+
+/**
* lpfc_nvme_create_queue -
+ * @pnvme_lport: Transport localport that LS is to be issued from
* @lpfc_pnvme: Pointer to the driver's nvme instance data
* @qidx: An cpu index used to affinitize IO queues and MSIX vectors.
+ * @qsize: Size of the queue in bytes
* @handle: An opaque driver handle used in follow-up calls.
*
* Driver registers this routine to preallocate and initialize any
@@ -255,7 +294,7 @@
/**
* lpfc_nvme_delete_queue -
- * @lpfc_pnvme: Pointer to the driver's nvme instance data
+ * @pnvme_lport: Transport localport that LS is to be issued from
* @qidx: An cpu index used to affinitize IO queues and MSIX vectors.
* @handle: An opaque driver handle from lpfc_nvme_create_queue
*
@@ -356,18 +395,131 @@
return;
}
+/**
+ * lpfc_nvme_handle_lsreq - Process an unsolicited NVME LS request
+ * @phba: pointer to lpfc hba data structure.
+ * @axchg: pointer to exchange context for the NVME LS request
+ *
+ * This routine is used for processing an asychronously received NVME LS
+ * request. Any remaining validation is done and the LS is then forwarded
+ * to the nvme-fc transport via nvme_fc_rcv_ls_req().
+ *
+ * The calling sequence should be: nvme_fc_rcv_ls_req() -> (processing)
+ * -> lpfc_nvme_xmt_ls_rsp/cmp -> req->done.
+ * __lpfc_nvme_xmt_ls_rsp_cmp should free the allocated axchg.
+ *
+ * Returns 0 if LS was handled and delivered to the transport
+ * Returns 1 if LS failed to be handled and should be dropped
+ */
+int
+lpfc_nvme_handle_lsreq(struct lpfc_hba *phba,
+ struct lpfc_async_xchg_ctx *axchg)
+{
+#if (IS_ENABLED(CONFIG_NVME_FC))
+ struct lpfc_vport *vport;
+ struct lpfc_nvme_rport *lpfc_rport;
+ struct nvme_fc_remote_port *remoteport;
+ struct lpfc_nvme_lport *lport;
+ uint32_t *payload = axchg->payload;
+ int rc;
+
+ vport = axchg->ndlp->vport;
+ lpfc_rport = axchg->ndlp->nrport;
+ if (!lpfc_rport)
+ return -EINVAL;
+
+ remoteport = lpfc_rport->remoteport;
+ if (!vport->localport)
+ return -EINVAL;
+
+ lport = vport->localport->private;
+ if (!lport)
+ return -EINVAL;
+
+ rc = nvme_fc_rcv_ls_req(remoteport, &axchg->ls_rsp, axchg->payload,
+ axchg->size);
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
+ "6205 NVME Unsol rcv: sz %d rc %d: %08x %08x %08x "
+ "%08x %08x %08x\n",
+ axchg->size, rc,
+ *payload, *(payload+1), *(payload+2),
+ *(payload+3), *(payload+4), *(payload+5));
+
+ if (!rc)
+ return 0;
+#endif
+ return 1;
+}
+
+/**
+ * __lpfc_nvme_ls_req_cmp - Generic completion handler for a NVME
+ * LS request.
+ * @phba: Pointer to HBA context object
+ * @vport: The local port that issued the LS
+ * @cmdwqe: Pointer to driver command WQE object.
+ * @wcqe: Pointer to driver response CQE object.
+ *
+ * This function is the generic completion handler for NVME LS requests.
+ * The function updates any states and statistics, calls the transport
+ * ls_req done() routine, then tears down the command and buffers used
+ * for the LS request.
+ **/
+void
+__lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport,
+ struct lpfc_iocbq *cmdwqe,
+ struct lpfc_wcqe_complete *wcqe)
+{
+ struct nvmefc_ls_req *pnvme_lsreq;
+ struct lpfc_dmabuf *buf_ptr;
+ struct lpfc_nodelist *ndlp;
+ uint32_t status;
+
+ pnvme_lsreq = (struct nvmefc_ls_req *)cmdwqe->context2;
+ ndlp = (struct lpfc_nodelist *)cmdwqe->context1;
+ status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK;
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,
+ "6047 NVMEx LS REQ %px cmpl DID %x Xri: %x "
+ "status %x reason x%x cmd:x%px lsreg:x%px bmp:x%px "
+ "ndlp:x%px\n",
+ pnvme_lsreq, ndlp ? ndlp->nlp_DID : 0,
+ cmdwqe->sli4_xritag, status,
+ (wcqe->parameter & 0xffff),
+ cmdwqe, pnvme_lsreq, cmdwqe->context3, ndlp);
+
+ lpfc_nvmeio_data(phba, "NVMEx LS CMPL: xri x%x stat x%x parm x%x\n",
+ cmdwqe->sli4_xritag, status, wcqe->parameter);
+
+ if (cmdwqe->context3) {
+ buf_ptr = (struct lpfc_dmabuf *)cmdwqe->context3;
+ lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
+ kfree(buf_ptr);
+ cmdwqe->context3 = NULL;
+ }
+ if (pnvme_lsreq->done)
+ pnvme_lsreq->done(pnvme_lsreq, status);
+ else
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "6046 NVMEx cmpl without done call back? "
+ "Data %px DID %x Xri: %x status %x\n",
+ pnvme_lsreq, ndlp ? ndlp->nlp_DID : 0,
+ cmdwqe->sli4_xritag, status);
+ if (ndlp) {
+ lpfc_nlp_put(ndlp);
+ cmdwqe->context1 = NULL;
+ }
+ lpfc_sli_release_iocbq(phba, cmdwqe);
+}
+
static void
-lpfc_nvme_cmpl_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
struct lpfc_wcqe_complete *wcqe)
{
struct lpfc_vport *vport = cmdwqe->vport;
struct lpfc_nvme_lport *lport;
uint32_t status;
- struct nvmefc_ls_req *pnvme_lsreq;
- struct lpfc_dmabuf *buf_ptr;
- struct lpfc_nodelist *ndlp;
- pnvme_lsreq = (struct nvmefc_ls_req *)cmdwqe->context2;
status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK;
if (vport->localport) {
@@ -382,38 +534,7 @@
}
}
- ndlp = (struct lpfc_nodelist *)cmdwqe->context1;
- lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,
- "6047 nvme cmpl Enter "
- "Data %px DID %x Xri: %x status %x reason x%x "
- "cmd:x%px lsreg:x%px bmp:x%px ndlp:x%px\n",
- pnvme_lsreq, ndlp ? ndlp->nlp_DID : 0,
- cmdwqe->sli4_xritag, status,
- (wcqe->parameter & 0xffff),
- cmdwqe, pnvme_lsreq, cmdwqe->context3, ndlp);
-
- lpfc_nvmeio_data(phba, "NVME LS CMPL: xri x%x stat x%x parm x%x\n",
- cmdwqe->sli4_xritag, status, wcqe->parameter);
-
- if (cmdwqe->context3) {
- buf_ptr = (struct lpfc_dmabuf *)cmdwqe->context3;
- lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
- kfree(buf_ptr);
- cmdwqe->context3 = NULL;
- }
- if (pnvme_lsreq->done)
- pnvme_lsreq->done(pnvme_lsreq, status);
- else
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC,
- "6046 nvme cmpl without done call back? "
- "Data %px DID %x Xri: %x status %x\n",
- pnvme_lsreq, ndlp ? ndlp->nlp_DID : 0,
- cmdwqe->sli4_xritag, status);
- if (ndlp) {
- lpfc_nlp_put(ndlp);
- cmdwqe->context1 = NULL;
- }
- lpfc_sli_release_iocbq(phba, cmdwqe);
+ __lpfc_nvme_ls_req_cmp(phba, vport, cmdwqe, wcqe);
}
static int
@@ -517,13 +638,6 @@
/* Issue GEN REQ WQE for NPORT <did> */
- lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
- "6050 Issue GEN REQ WQE to NPORT x%x "
- "Data: x%x x%x wq:x%px lsreq:x%px bmp:x%px "
- "xmit:%d 1st:%d\n",
- ndlp->nlp_DID, genwqe->iotag,
- vport->port_state,
- genwqe, pnvme_lsreq, bmp, xmit_len, first_len);
genwqe->wqe_cmpl = cmpl;
genwqe->iocb_cmpl = NULL;
genwqe->drvrTimeout = tmo + LPFC_DRVR_TIMEOUT;
@@ -535,105 +649,107 @@
rc = lpfc_sli4_issue_wqe(phba, &phba->sli4_hba.hdwq[0], genwqe);
if (rc) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6045 Issue GEN REQ WQE to NPORT x%x "
- "Data: x%x x%x\n",
+ "Data: x%x x%x rc x%x\n",
ndlp->nlp_DID, genwqe->iotag,
- vport->port_state);
+ vport->port_state, rc);
lpfc_sli_release_iocbq(phba, genwqe);
return 1;
}
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC | LOG_ELS,
+ "6050 Issue GEN REQ WQE to NPORT x%x "
+ "Data: oxid: x%x state: x%x wq:x%px lsreq:x%px "
+ "bmp:x%px xmit:%d 1st:%d\n",
+ ndlp->nlp_DID, genwqe->sli4_xritag,
+ vport->port_state,
+ genwqe, pnvme_lsreq, bmp, xmit_len, first_len);
return 0;
}
+
/**
- * lpfc_nvme_ls_req - Issue an Link Service request
- * @lpfc_pnvme: Pointer to the driver's nvme instance data
- * @lpfc_nvme_lport: Pointer to the driver's local port data
- * @lpfc_nvme_rport: Pointer to the rport getting the @lpfc_nvme_ereq
+ * __lpfc_nvme_ls_req - Generic service routine to issue an NVME LS request
+ * @vport: The local port issuing the LS
+ * @ndlp: The remote port to send the LS to
+ * @pnvme_lsreq: Pointer to LS request structure from the transport
+ * @gen_req_cmp: Completion call-back
*
- * Driver registers this routine to handle any link service request
- * from the nvme_fc transport to a remote nvme-aware port.
+ * Routine validates the ndlp, builds buffers and sends a GEN_REQUEST
+ * WQE to perform the LS operation.
*
* Return value :
* 0 - Success
- * TODO: What are the failure codes.
+ * non-zero: various error codes, in form of -Exxx
**/
-static int
-lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport,
- struct nvme_fc_remote_port *pnvme_rport,
- struct nvmefc_ls_req *pnvme_lsreq)
+int
+__lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ struct nvmefc_ls_req *pnvme_lsreq,
+ void (*gen_req_cmp)(struct lpfc_hba *phba,
+ struct lpfc_iocbq *cmdwqe,
+ struct lpfc_wcqe_complete *wcqe))
{
- int ret = 0;
- struct lpfc_nvme_lport *lport;
- struct lpfc_nvme_rport *rport;
- struct lpfc_vport *vport;
- struct lpfc_nodelist *ndlp;
- struct ulp_bde64 *bpl;
struct lpfc_dmabuf *bmp;
+ struct ulp_bde64 *bpl;
+ int ret;
uint16_t ntype, nstate;
- /* there are two dma buf in the request, actually there is one and
- * the second one is just the start address + cmd size.
- * Before calling lpfc_nvme_gen_req these buffers need to be wrapped
- * in a lpfc_dmabuf struct. When freeing we just free the wrapper
- * because the nvem layer owns the data bufs.
- * We do not have to break these packets open, we don't care what is in
- * them. And we do not have to look at the resonse data, we only care
- * that we got a response. All of the caring is going to happen in the
- * nvme-fc layer.
- */
-
- lport = (struct lpfc_nvme_lport *)pnvme_lport->private;
- rport = (struct lpfc_nvme_rport *)pnvme_rport->private;
- if (unlikely(!lport) || unlikely(!rport))
- return -EINVAL;
-
- vport = lport->vport;
-
- if (vport->load_flag & FC_UNLOADING)
- return -ENODEV;
-
- /* Need the ndlp. It is stored in the driver's rport. */
- ndlp = rport->ndlp;
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR,
- "6051 Remoteport x%px, rport has invalid ndlp. "
- "Failing LS Req\n", pnvme_rport);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "6051 NVMEx LS REQ: Bad NDLP x%px, Failing "
+ "LS Req\n",
+ ndlp);
return -ENODEV;
}
- /* The remote node has to be a mapped nvme target or an
- * unmapped nvme initiator or it's an error.
- */
ntype = ndlp->nlp_type;
nstate = ndlp->nlp_state;
if ((ntype & NLP_NVME_TARGET && nstate != NLP_STE_MAPPED_NODE) ||
(ntype & NLP_NVME_INITIATOR && nstate != NLP_STE_UNMAPPED_NODE)) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR,
- "6088 DID x%06x not ready for "
- "IO. State x%x, Type x%x\n",
- pnvme_rport->port_id,
- ndlp->nlp_state, ndlp->nlp_type);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "6088 NVMEx LS REQ: Fail DID x%06x not "
+ "ready for IO. Type x%x, State x%x\n",
+ ndlp->nlp_DID, ntype, nstate);
return -ENODEV;
}
- bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
- if (!bmp) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC,
- "6044 Could not find node for DID %x\n",
- pnvme_rport->port_id);
- return 2;
+ if (!vport->phba->sli4_hba.nvmels_wq)
+ return -ENOMEM;
+
+ /*
+ * there are two dma buf in the request, actually there is one and
+ * the second one is just the start address + cmd size.
+ * Before calling lpfc_nvme_gen_req these buffers need to be wrapped
+ * in a lpfc_dmabuf struct. When freeing we just free the wrapper
+ * because the nvem layer owns the data bufs.
+ * We do not have to break these packets open, we don't care what is
+ * in them. And we do not have to look at the resonse data, we only
+ * care that we got a response. All of the caring is going to happen
+ * in the nvme-fc layer.
+ */
+
+ bmp = kmalloc(sizeof(*bmp), GFP_KERNEL);
+ if (!bmp) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "6044 NVMEx LS REQ: Could not alloc LS buf "
+ "for DID %x\n",
+ ndlp->nlp_DID);
+ return -ENOMEM;
}
- INIT_LIST_HEAD(&bmp->list);
+
bmp->virt = lpfc_mbuf_alloc(vport->phba, MEM_PRI, &(bmp->phys));
if (!bmp->virt) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC,
- "6042 Could not find node for DID %x\n",
- pnvme_rport->port_id);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "6042 NVMEx LS REQ: Could not alloc mbuf "
+ "for DID %x\n",
+ ndlp->nlp_DID);
kfree(bmp);
- return 3;
+ return -ENOMEM;
}
+
+ INIT_LIST_HEAD(&bmp->list);
+
bpl = (struct ulp_bde64 *)bmp->virt;
bpl->addrHigh = le32_to_cpu(putPaddrHigh(pnvme_lsreq->rqstdma));
bpl->addrLow = le32_to_cpu(putPaddrLow(pnvme_lsreq->rqstdma));
@@ -648,52 +764,177 @@
bpl->tus.f.bdeSize = pnvme_lsreq->rsplen;
bpl->tus.w = le32_to_cpu(bpl->tus.w);
- /* Expand print to include key fields. */
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,
- "6149 Issue LS Req to DID 0x%06x lport x%px, "
- "rport x%px lsreq x%px rqstlen:%d rsplen:%d "
- "%pad %pad\n",
- ndlp->nlp_DID, pnvme_lport, pnvme_rport,
- pnvme_lsreq, pnvme_lsreq->rqstlen,
- pnvme_lsreq->rsplen, &pnvme_lsreq->rqstdma,
- &pnvme_lsreq->rspdma);
+ "6149 NVMEx LS REQ: Issue to DID 0x%06x lsreq x%px, "
+ "rqstlen:%d rsplen:%d %pad %pad\n",
+ ndlp->nlp_DID, pnvme_lsreq, pnvme_lsreq->rqstlen,
+ pnvme_lsreq->rsplen, &pnvme_lsreq->rqstdma,
+ &pnvme_lsreq->rspdma);
- atomic_inc(&lport->fc4NvmeLsRequests);
-
- /* Hardcode the wait to 30 seconds. Connections are failing otherwise.
- * This code allows it all to work.
- */
ret = lpfc_nvme_gen_req(vport, bmp, pnvme_lsreq->rqstaddr,
- pnvme_lsreq, lpfc_nvme_cmpl_gen_req,
- ndlp, 2, 30, 0);
+ pnvme_lsreq, gen_req_cmp, ndlp, 2,
+ LPFC_NVME_LS_TIMEOUT, 0);
if (ret != WQE_SUCCESS) {
- atomic_inc(&lport->xmt_ls_err);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC,
- "6052 EXIT. issue ls wqe failed lport x%px, "
- "rport x%px lsreq x%px Status %x DID %x\n",
- pnvme_lport, pnvme_rport, pnvme_lsreq,
- ret, ndlp->nlp_DID);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "6052 NVMEx REQ: EXIT. issue ls wqe failed "
+ "lsreq x%px Status %x DID %x\n",
+ pnvme_lsreq, ret, ndlp->nlp_DID);
lpfc_mbuf_free(vport->phba, bmp->virt, bmp->phys);
kfree(bmp);
- return ret;
+ return -EIO;
}
- /* Stub in routine and return 0 for now. */
- return ret;
+ return 0;
}
/**
- * lpfc_nvme_ls_abort - Issue an Link Service request
- * @lpfc_pnvme: Pointer to the driver's nvme instance data
- * @lpfc_nvme_lport: Pointer to the driver's local port data
- * @lpfc_nvme_rport: Pointer to the rport getting the @lpfc_nvme_ereq
+ * lpfc_nvme_ls_req - Issue an NVME Link Service request
+ * @pnvme_lport: Transport localport that LS is to be issued from.
+ * @nvme_rport: Transport remoteport that LS is to be sent to.
+ * @pnvme_lsreq: the transport nvme_ls_req structure for the LS
*
* Driver registers this routine to handle any link service request
* from the nvme_fc transport to a remote nvme-aware port.
*
* Return value :
* 0 - Success
- * TODO: What are the failure codes.
+ * non-zero: various error codes, in form of -Exxx
+ **/
+static int
+lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport,
+ struct nvme_fc_remote_port *pnvme_rport,
+ struct nvmefc_ls_req *pnvme_lsreq)
+{
+ struct lpfc_nvme_lport *lport;
+ struct lpfc_nvme_rport *rport;
+ struct lpfc_vport *vport;
+ int ret;
+
+ lport = (struct lpfc_nvme_lport *)pnvme_lport->private;
+ rport = (struct lpfc_nvme_rport *)pnvme_rport->private;
+ if (unlikely(!lport) || unlikely(!rport))
+ return -EINVAL;
+
+ vport = lport->vport;
+ if (vport->load_flag & FC_UNLOADING)
+ return -ENODEV;
+
+ atomic_inc(&lport->fc4NvmeLsRequests);
+
+ ret = __lpfc_nvme_ls_req(vport, rport->ndlp, pnvme_lsreq,
+ lpfc_nvme_ls_req_cmp);
+ if (ret)
+ atomic_inc(&lport->xmt_ls_err);
+
+ return ret;
+}
+
+/**
+ * __lpfc_nvme_ls_abort - Generic service routine to abort a prior
+ * NVME LS request
+ * @vport: The local port that issued the LS
+ * @ndlp: The remote port the LS was sent to
+ * @pnvme_lsreq: Pointer to LS request structure from the transport
+ *
+ * The driver validates the ndlp, looks for the LS, and aborts the
+ * LS if found.
+ *
+ * Returns:
+ * 0 : if LS found and aborted
+ * non-zero: various error conditions in form -Exxx
+ **/
+int
+__lpfc_nvme_ls_abort(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ struct nvmefc_ls_req *pnvme_lsreq)
+{
+ struct lpfc_hba *phba = vport->phba;
+ struct lpfc_sli_ring *pring;
+ struct lpfc_iocbq *wqe, *next_wqe;
+ bool foundit = false;
+
+ if (!ndlp) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "6049 NVMEx LS REQ Abort: Bad NDLP x%px DID "
+ "x%06x, Failing LS Req\n",
+ ndlp, ndlp ? ndlp->nlp_DID : 0);
+ return -EINVAL;
+ }
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC | LOG_NVME_ABTS,
+ "6040 NVMEx LS REQ Abort: Issue LS_ABORT for lsreq "
+ "x%p rqstlen:%d rsplen:%d %pad %pad\n",
+ pnvme_lsreq, pnvme_lsreq->rqstlen,
+ pnvme_lsreq->rsplen, &pnvme_lsreq->rqstdma,
+ &pnvme_lsreq->rspdma);
+
+ /*
+ * Lock the ELS ring txcmplq and look for the wqe that matches
+ * this ELS. If found, issue an abort on the wqe.
+ */
+ pring = phba->sli4_hba.nvmels_wq->pring;
+ spin_lock_irq(&phba->hbalock);
+ spin_lock(&pring->ring_lock);
+ list_for_each_entry_safe(wqe, next_wqe, &pring->txcmplq, list) {
+ if (wqe->context2 == pnvme_lsreq) {
+ wqe->iocb_flag |= LPFC_DRIVER_ABORTED;
+ foundit = true;
+ break;
+ }
+ }
+ spin_unlock(&pring->ring_lock);
+
+ if (foundit)
+ lpfc_sli_issue_abort_iotag(phba, pring, wqe);
+ spin_unlock_irq(&phba->hbalock);
+
+ if (foundit)
+ return 0;
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC | LOG_NVME_ABTS,
+ "6213 NVMEx LS REQ Abort: Unable to locate req x%p\n",
+ pnvme_lsreq);
+ return -EINVAL;
+}
+
+static int
+lpfc_nvme_xmt_ls_rsp(struct nvme_fc_local_port *localport,
+ struct nvme_fc_remote_port *remoteport,
+ struct nvmefc_ls_rsp *ls_rsp)
+{
+ struct lpfc_async_xchg_ctx *axchg =
+ container_of(ls_rsp, struct lpfc_async_xchg_ctx, ls_rsp);
+ struct lpfc_nvme_lport *lport;
+ int rc;
+
+ if (axchg->phba->pport->load_flag & FC_UNLOADING)
+ return -ENODEV;
+
+ lport = (struct lpfc_nvme_lport *)localport->private;
+
+ rc = __lpfc_nvme_xmt_ls_rsp(axchg, ls_rsp, __lpfc_nvme_xmt_ls_rsp_cmp);
+
+ if (rc) {
+ /*
+ * unless the failure is due to having already sent
+ * the response, an abort will be generated for the
+ * exchange if the rsp can't be sent.
+ */
+ if (rc != -EALREADY)
+ atomic_inc(&lport->xmt_ls_abort);
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * lpfc_nvme_ls_abort - Abort a prior NVME LS request
+ * @pnvme_lport: Transport localport that LS is to be issued from.
+ * @pnvme_rport: Transport remoteport that LS is to be sent to.
+ * @pnvme_lsreq: the transport nvme_ls_req structure for the LS
+ *
+ * Driver registers this routine to abort a NVME LS request that is
+ * in progress (from the transports perspective).
**/
static void
lpfc_nvme_ls_abort(struct nvme_fc_local_port *pnvme_lport,
@@ -704,9 +945,7 @@
struct lpfc_vport *vport;
struct lpfc_hba *phba;
struct lpfc_nodelist *ndlp;
- LIST_HEAD(abort_list);
- struct lpfc_sli_ring *pring;
- struct lpfc_iocbq *wqe, *next_wqe;
+ int ret;
lport = (struct lpfc_nvme_lport *)pnvme_lport->private;
if (unlikely(!lport))
@@ -718,48 +957,10 @@
return;
ndlp = lpfc_findnode_did(vport, pnvme_rport->port_id);
- if (!ndlp) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS,
- "6049 Could not find node for DID %x\n",
- pnvme_rport->port_id);
- return;
- }
- /* Expand print to include key fields. */
- lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_ABTS,
- "6040 ENTER. lport x%px, rport x%px lsreq x%px rqstlen:%d "
- "rsplen:%d %pad %pad\n",
- pnvme_lport, pnvme_rport,
- pnvme_lsreq, pnvme_lsreq->rqstlen,
- pnvme_lsreq->rsplen, &pnvme_lsreq->rqstdma,
- &pnvme_lsreq->rspdma);
-
- /*
- * Lock the ELS ring txcmplq and build a local list of all ELS IOs
- * that need an ABTS. The IOs need to stay on the txcmplq so that
- * the abort operation completes them successfully.
- */
- pring = phba->sli4_hba.nvmels_wq->pring;
- spin_lock_irq(&phba->hbalock);
- spin_lock(&pring->ring_lock);
- list_for_each_entry_safe(wqe, next_wqe, &pring->txcmplq, list) {
- /* Add to abort_list on on NDLP match. */
- if (lpfc_check_sli_ndlp(phba, pring, wqe, ndlp)) {
- wqe->iocb_flag |= LPFC_DRIVER_ABORTED;
- list_add_tail(&wqe->dlist, &abort_list);
- }
- }
- spin_unlock(&pring->ring_lock);
- spin_unlock_irq(&phba->hbalock);
-
- /* Abort the targeted IOs and remove them from the abort list. */
- list_for_each_entry_safe(wqe, next_wqe, &abort_list, dlist) {
+ ret = __lpfc_nvme_ls_abort(vport, ndlp, pnvme_lsreq);
+ if (!ret)
atomic_inc(&lport->xmt_ls_abort);
- spin_lock_irq(&phba->hbalock);
- list_del_init(&wqe->dlist);
- lpfc_sli_issue_abort_iotag(phba, pring, wqe);
- spin_unlock_irq(&phba->hbalock);
- }
}
/* Fix up the existing sgls for NVME IO. */
@@ -859,94 +1060,9 @@
sgl->sge_len = cpu_to_le32(nCmd->rsplen);
}
-#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
-static void
-lpfc_nvme_ktime(struct lpfc_hba *phba,
- struct lpfc_io_buf *lpfc_ncmd)
-{
- uint64_t seg1, seg2, seg3, seg4;
- uint64_t segsum;
- if (!lpfc_ncmd->ts_last_cmd ||
- !lpfc_ncmd->ts_cmd_start ||
- !lpfc_ncmd->ts_cmd_wqput ||
- !lpfc_ncmd->ts_isr_cmpl ||
- !lpfc_ncmd->ts_data_nvme)
- return;
-
- if (lpfc_ncmd->ts_data_nvme < lpfc_ncmd->ts_cmd_start)
- return;
- if (lpfc_ncmd->ts_cmd_start < lpfc_ncmd->ts_last_cmd)
- return;
- if (lpfc_ncmd->ts_cmd_wqput < lpfc_ncmd->ts_cmd_start)
- return;
- if (lpfc_ncmd->ts_isr_cmpl < lpfc_ncmd->ts_cmd_wqput)
- return;
- if (lpfc_ncmd->ts_data_nvme < lpfc_ncmd->ts_isr_cmpl)
- return;
- /*
- * Segment 1 - Time from Last FCP command cmpl is handed
- * off to NVME Layer to start of next command.
- * Segment 2 - Time from Driver receives a IO cmd start
- * from NVME Layer to WQ put is done on IO cmd.
- * Segment 3 - Time from Driver WQ put is done on IO cmd
- * to MSI-X ISR for IO cmpl.
- * Segment 4 - Time from MSI-X ISR for IO cmpl to when
- * cmpl is handled off to the NVME Layer.
- */
- seg1 = lpfc_ncmd->ts_cmd_start - lpfc_ncmd->ts_last_cmd;
- if (seg1 > 5000000) /* 5 ms - for sequential IOs only */
- seg1 = 0;
-
- /* Calculate times relative to start of IO */
- seg2 = (lpfc_ncmd->ts_cmd_wqput - lpfc_ncmd->ts_cmd_start);
- segsum = seg2;
- seg3 = lpfc_ncmd->ts_isr_cmpl - lpfc_ncmd->ts_cmd_start;
- if (segsum > seg3)
- return;
- seg3 -= segsum;
- segsum += seg3;
-
- seg4 = lpfc_ncmd->ts_data_nvme - lpfc_ncmd->ts_cmd_start;
- if (segsum > seg4)
- return;
- seg4 -= segsum;
-
- phba->ktime_data_samples++;
- phba->ktime_seg1_total += seg1;
- if (seg1 < phba->ktime_seg1_min)
- phba->ktime_seg1_min = seg1;
- else if (seg1 > phba->ktime_seg1_max)
- phba->ktime_seg1_max = seg1;
- phba->ktime_seg2_total += seg2;
- if (seg2 < phba->ktime_seg2_min)
- phba->ktime_seg2_min = seg2;
- else if (seg2 > phba->ktime_seg2_max)
- phba->ktime_seg2_max = seg2;
- phba->ktime_seg3_total += seg3;
- if (seg3 < phba->ktime_seg3_min)
- phba->ktime_seg3_min = seg3;
- else if (seg3 > phba->ktime_seg3_max)
- phba->ktime_seg3_max = seg3;
- phba->ktime_seg4_total += seg4;
- if (seg4 < phba->ktime_seg4_min)
- phba->ktime_seg4_min = seg4;
- else if (seg4 > phba->ktime_seg4_max)
- phba->ktime_seg4_max = seg4;
-
- lpfc_ncmd->ts_last_cmd = 0;
- lpfc_ncmd->ts_cmd_start = 0;
- lpfc_ncmd->ts_cmd_wqput = 0;
- lpfc_ncmd->ts_isr_cmpl = 0;
- lpfc_ncmd->ts_data_nvme = 0;
-}
-#endif
-
-/**
+/*
* lpfc_nvme_io_cmd_wqe_cmpl - Complete an NVME-over-FCP IO
- * @lpfc_pnvme: Pointer to the driver's nvme instance data
- * @lpfc_nvme_lport: Pointer to the driver's local port data
- * @lpfc_nvme_rport: Pointer to the rport getting the @lpfc_nvme_ereq
*
* Driver registers this routine as it io request handler. This
* routine issues an fcp WQE with data from the @lpfc_nvme_fcpreq
@@ -972,11 +1088,13 @@
uint32_t code, status, idx;
uint16_t cid, sqhd, data;
uint32_t *ptr;
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ int cpu;
+#endif
/* Sanity check on return of outstanding command */
if (!lpfc_ncmd) {
- lpfc_printf_vlog(vport, KERN_ERR,
- LOG_NODE | LOG_NVME_IOERR,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6071 Null lpfc_ncmd pointer. No "
"release, skip completion\n");
return;
@@ -987,7 +1105,7 @@
if (!lpfc_ncmd->nvmeCmd) {
spin_unlock(&lpfc_ncmd->buf_lock);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6066 Missing cmpl ptrs: lpfc_ncmd x%px, "
"nvmeCmd x%px\n",
lpfc_ncmd, lpfc_ncmd->nvmeCmd);
@@ -1020,7 +1138,7 @@
*/
ndlp = lpfc_ncmd->ndlp;
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6062 Ignoring NVME cmpl. No ndlp\n");
goto out_err;
}
@@ -1091,7 +1209,7 @@
/* Sanity check */
if (nCmd->rcv_rsplen == LPFC_NVME_ERSP_LEN)
break;
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6081 NVME Completion Protocol Error: "
"xri %x status x%x result x%x "
"placed x%x\n",
@@ -1110,7 +1228,7 @@
lpfc_ncmd, nCmd,
lpfc_ncmd->cur_iocbq.sli4_xritag,
bf_get(lpfc_wcqe_c_xb, wcqe));
- /* fall through */
+ fallthrough;
default:
out_err:
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
@@ -1140,23 +1258,19 @@
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (lpfc_ncmd->ts_cmd_start) {
lpfc_ncmd->ts_isr_cmpl = pwqeIn->isr_timestamp;
- lpfc_ncmd->ts_data_nvme = ktime_get_ns();
- phba->ktime_last_cmd = lpfc_ncmd->ts_data_nvme;
- lpfc_nvme_ktime(phba, lpfc_ncmd);
+ lpfc_ncmd->ts_data_io = ktime_get_ns();
+ phba->ktime_last_cmd = lpfc_ncmd->ts_data_io;
+ lpfc_io_ktime(phba, lpfc_ncmd);
}
- if (unlikely(phba->cpucheck_on & LPFC_CHECK_NVME_IO)) {
- uint32_t cpu;
- idx = lpfc_ncmd->cur_iocbq.hba_wqidx;
+ if (unlikely(phba->hdwqstat_on & LPFC_CHECK_NVME_IO)) {
cpu = raw_smp_processor_id();
- if (cpu < LPFC_CHECK_CPU_CNT) {
- if (lpfc_ncmd->cpu != cpu)
- lpfc_printf_vlog(vport,
- KERN_INFO, LOG_NVME_IOERR,
- "6701 CPU Check cmpl: "
- "cpu %d expect %d\n",
- cpu, lpfc_ncmd->cpu);
- phba->sli4_hba.hdwq[idx].cpucheck_cmpl_io[cpu]++;
- }
+ this_cpu_inc(phba->sli4_hba.c_stat->cmpl_io);
+ if (lpfc_ncmd->cpu != cpu)
+ lpfc_printf_vlog(vport,
+ KERN_INFO, LOG_NVME_IOERR,
+ "6701 CPU Check cmpl: "
+ "cpu %d expect %d\n",
+ cpu, lpfc_ncmd->cpu);
}
#endif
@@ -1180,11 +1294,10 @@
/**
* lpfc_nvme_prep_io_cmd - Issue an NVME-over-FCP IO
- * @lpfc_pnvme: Pointer to the driver's nvme instance data
- * @lpfc_nvme_lport: Pointer to the driver's local port data
- * @lpfc_nvme_rport: Pointer to the rport getting the @lpfc_nvme_ereq
- * @lpfc_nvme_fcreq: IO request from nvme fc to driver.
- * @hw_queue_handle: Driver-returned handle in lpfc_nvme_create_queue
+ * @vport: pointer to a host virtual N_Port data structure
+ * @lpfcn_cmd: Pointer to lpfc scsi command
+ * @pnode: pointer to a node-list data structure
+ * @cstat: pointer to the control status structure
*
* Driver registers this routine as it io request handler. This
* routine issues an fcp WQE with data from the @lpfc_nvme_fcpreq
@@ -1289,11 +1402,8 @@
/**
* lpfc_nvme_prep_io_dma - Issue an NVME-over-FCP IO
- * @lpfc_pnvme: Pointer to the driver's nvme instance data
- * @lpfc_nvme_lport: Pointer to the driver's local port data
- * @lpfc_nvme_rport: Pointer to the rport getting the @lpfc_nvme_ereq
- * @lpfc_nvme_fcreq: IO request from nvme fc to driver.
- * @hw_queue_handle: Driver-returned handle in lpfc_nvme_create_queue
+ * @vport: pointer to a host virtual N_Port data structure
+ * @lpfcn_cmd: Pointer to lpfc scsi command
*
* Driver registers this routine as it io request handler. This
* routine issues an fcp WQE with data from the @lpfc_nvme_fcpreq
@@ -1339,7 +1449,7 @@
first_data_sgl = sgl;
lpfc_ncmd->seg_cnt = nCmd->sg_cnt;
if (lpfc_ncmd->seg_cnt > lpfc_nvme_template.max_sgl_segments) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6058 Too many sg segments from "
"NVME Transport. Max %d, "
"nvmeIO sg_cnt %d\n",
@@ -1362,7 +1472,7 @@
j = 2;
for (i = 0; i < nseg; i++) {
if (data_sg == NULL) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6059 dptr err %d, nseg %d\n",
i, nseg);
lpfc_ncmd->seg_cnt = 0;
@@ -1463,7 +1573,7 @@
* and sg_cnt must zero.
*/
if (nCmd->payload_length != 0) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6063 NVME DMA Prep Err: sg_cnt %d "
"payload_length x%x\n",
nCmd->sg_cnt, nCmd->payload_length);
@@ -1534,11 +1644,6 @@
phba = vport->phba;
- if (vport->load_flag & FC_UNLOADING) {
- ret = -ENODEV;
- goto out_fail;
- }
-
if (unlikely(vport->load_flag & FC_UNLOADING)) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
"6124 Fail IO, Driver unload\n");
@@ -1705,19 +1810,17 @@
if (lpfc_ncmd->ts_cmd_start)
lpfc_ncmd->ts_cmd_wqput = ktime_get_ns();
- if (phba->cpucheck_on & LPFC_CHECK_NVME_IO) {
+ if (phba->hdwqstat_on & LPFC_CHECK_NVME_IO) {
cpu = raw_smp_processor_id();
- if (cpu < LPFC_CHECK_CPU_CNT) {
- lpfc_ncmd->cpu = cpu;
- if (idx != cpu)
- lpfc_printf_vlog(vport,
- KERN_INFO, LOG_NVME_IOERR,
- "6702 CPU Check cmd: "
- "cpu %d wq %d\n",
- lpfc_ncmd->cpu,
- lpfc_queue_info->index);
- phba->sli4_hba.hdwq[idx].cpucheck_xmt_io[cpu]++;
- }
+ this_cpu_inc(phba->sli4_hba.c_stat->xmt_io);
+ lpfc_ncmd->cpu = cpu;
+ if (idx != cpu)
+ lpfc_printf_vlog(vport,
+ KERN_INFO, LOG_NVME_IOERR,
+ "6702 CPU Check cmd: "
+ "cpu %d wq %d\n",
+ lpfc_ncmd->cpu,
+ lpfc_queue_info->index);
}
#endif
return 0;
@@ -1793,7 +1896,6 @@
struct lpfc_iocbq *abts_buf;
struct lpfc_iocbq *nvmereq_wqe;
struct lpfc_nvme_fcpreq_priv *freqpriv;
- union lpfc_wqe128 *abts_wqe;
unsigned long flags;
int ret_val;
@@ -1834,7 +1936,7 @@
/* driver queued commands are in process of being flushed */
if (phba->hba_flag & HBA_IOQ_FLUSH) {
spin_unlock_irqrestore(&phba->hbalock, flags);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6139 Driver in reset cleanup - flushing "
"NVME Req now. hba_flag x%x\n",
phba->hba_flag);
@@ -1844,13 +1946,13 @@
lpfc_nbuf = freqpriv->nvme_buf;
if (!lpfc_nbuf) {
spin_unlock_irqrestore(&phba->hbalock, flags);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6140 NVME IO req has no matching lpfc nvme "
"io buffer. Skipping abort req.\n");
return;
} else if (!lpfc_nbuf->nvmeCmd) {
spin_unlock_irqrestore(&phba->hbalock, flags);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6141 lpfc NVME IO req has no nvme_fcreq "
"io buffer. Skipping abort req.\n");
return;
@@ -1868,7 +1970,7 @@
* has not seen it yet.
*/
if (lpfc_nbuf->nvmeCmd != pnvme_fcreq) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6143 NVME req mismatch: "
"lpfc_nbuf x%px nvmeCmd x%px, "
"pnvme_fcreq x%px. Skipping Abort xri x%x\n",
@@ -1879,7 +1981,7 @@
/* Don't abort IOs no longer on the pending queue. */
if (!(nvmereq_wqe->iocb_flag & LPFC_IO_ON_TXCMPLQ)) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6142 NVME IO req x%px not queued - skipping "
"abort req xri x%x\n",
pnvme_fcreq, nvmereq_wqe->sli4_xritag);
@@ -1893,7 +1995,7 @@
/* Outstanding abort is in progress */
if (nvmereq_wqe->iocb_flag & LPFC_DRIVER_ABORTED) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6144 Outstanding NVME I/O Abort Request "
"still pending on nvme_fcreq x%px, "
"lpfc_ncmd %px xri x%x\n",
@@ -1904,7 +2006,7 @@
abts_buf = __lpfc_sli_get_iocbq(phba);
if (!abts_buf) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6136 No available abort wqes. Skipping "
"Abts req for nvme_fcreq x%px xri x%x\n",
pnvme_fcreq, nvmereq_wqe->sli4_xritag);
@@ -1914,37 +2016,7 @@
/* Ready - mark outstanding as aborted by driver. */
nvmereq_wqe->iocb_flag |= LPFC_DRIVER_ABORTED;
- /* Complete prepping the abort wqe and issue to the FW. */
- abts_wqe = &abts_buf->wqe;
-
- /* WQEs are reused. Clear stale data and set key fields to
- * zero like ia, iaab, iaar, xri_tag, and ctxt_tag.
- */
- memset(abts_wqe, 0, sizeof(*abts_wqe));
- bf_set(abort_cmd_criteria, &abts_wqe->abort_cmd, T_XRI_TAG);
-
- /* word 7 */
- bf_set(wqe_cmnd, &abts_wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX);
- bf_set(wqe_class, &abts_wqe->abort_cmd.wqe_com,
- nvmereq_wqe->iocb.ulpClass);
-
- /* word 8 - tell the FW to abort the IO associated with this
- * outstanding exchange ID.
- */
- abts_wqe->abort_cmd.wqe_com.abort_tag = nvmereq_wqe->sli4_xritag;
-
- /* word 9 - this is the iotag for the abts_wqe completion. */
- bf_set(wqe_reqtag, &abts_wqe->abort_cmd.wqe_com,
- abts_buf->iotag);
-
- /* word 10 */
- bf_set(wqe_qosd, &abts_wqe->abort_cmd.wqe_com, 1);
- bf_set(wqe_lenloc, &abts_wqe->abort_cmd.wqe_com, LPFC_WQE_LENLOC_NONE);
-
- /* word 11 */
- bf_set(wqe_cmd_type, &abts_wqe->abort_cmd.wqe_com, OTHER_COMMAND);
- bf_set(wqe_wqec, &abts_wqe->abort_cmd.wqe_com, 1);
- bf_set(wqe_cqid, &abts_wqe->abort_cmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
+ lpfc_nvme_prep_abort_wqe(abts_buf, nvmereq_wqe->sli4_xritag, 0);
/* ABTS WQE must go to the same WQ as the WQE to be aborted */
abts_buf->iocb_flag |= LPFC_IO_NVME;
@@ -1955,7 +2027,7 @@
spin_unlock(&lpfc_nbuf->buf_lock);
spin_unlock_irqrestore(&phba->hbalock, flags);
if (ret_val) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6137 Failed abts issue_wqe with status x%x "
"for nvme_fcreq x%px.\n",
ret_val, pnvme_fcreq);
@@ -1987,6 +2059,7 @@
.fcp_io = lpfc_nvme_fcp_io_submit,
.ls_abort = lpfc_nvme_ls_abort,
.fcp_abort = lpfc_nvme_fcp_abort,
+ .xmt_ls_rsp = lpfc_nvme_xmt_ls_rsp,
.max_hw_queues = 1,
.max_sgl_segments = LPFC_NVME_DEFAULT_SEGS,
@@ -2086,7 +2159,7 @@
lpfc_ncmd->flags &= ~LPFC_SBUF_BUMP_QDEPTH;
qp = lpfc_ncmd->hdwq;
- if (lpfc_ncmd->flags & LPFC_SBUF_XBUSY) {
+ if (unlikely(lpfc_ncmd->flags & LPFC_SBUF_XBUSY)) {
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
"6310 XB release deferred for "
"ox_id x%x on reqtag x%x\n",
@@ -2141,12 +2214,10 @@
*/
lpfc_nvme_template.max_sgl_segments = phba->cfg_nvme_seg_cnt + 1;
- /* Advertise how many hw queues we support based on fcp_io_sched */
- if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_HDWQ)
- lpfc_nvme_template.max_hw_queues = phba->cfg_hdw_queue;
- else
- lpfc_nvme_template.max_hw_queues =
- phba->sli4_hba.num_present_cpu;
+ /* Advertise how many hw queues we support based on cfg_hdw_queue,
+ * which will not exceed cpu count.
+ */
+ lpfc_nvme_template.max_hw_queues = phba->cfg_hdw_queue;
if (!IS_ENABLED(CONFIG_NVME_FC))
return ret;
@@ -2184,6 +2255,7 @@
atomic_set(&lport->cmpl_fcp_err, 0);
atomic_set(&lport->cmpl_ls_xb, 0);
atomic_set(&lport->cmpl_ls_err, 0);
+
atomic_set(&lport->fc4NvmeLsRequests, 0);
atomic_set(&lport->fc4NvmeLsCmpls, 0);
}
@@ -2211,6 +2283,8 @@
int ret, i, pending = 0;
struct lpfc_sli_ring *pring;
struct lpfc_hba *phba = vport->phba;
+ struct lpfc_sli4_hdw_queue *qp;
+ int abts_scsi, abts_nvme;
/* Host transport has to clean up and confirm requiring an indefinite
* wait. Print a message if a 10 second wait expires and renew the
@@ -2221,17 +2295,23 @@
ret = wait_for_completion_timeout(lport_unreg_cmp, wait_tmo);
if (unlikely(!ret)) {
pending = 0;
+ abts_scsi = 0;
+ abts_nvme = 0;
for (i = 0; i < phba->cfg_hdw_queue; i++) {
- pring = phba->sli4_hba.hdwq[i].io_wq->pring;
+ qp = &phba->sli4_hba.hdwq[i];
+ pring = qp->io_wq->pring;
if (!pring)
continue;
- if (pring->txcmplq_cnt)
- pending += pring->txcmplq_cnt;
+ pending += pring->txcmplq_cnt;
+ abts_scsi += qp->abts_scsi_io_bufs;
+ abts_nvme += qp->abts_nvme_io_bufs;
}
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6176 Lport x%px Localport x%px wait "
- "timed out. Pending %d. Renewing.\n",
- lport, vport->localport, pending);
+ "timed out. Pending %d [%d:%d]. "
+ "Renewing.\n",
+ lport, vport->localport, pending,
+ abts_scsi, abts_nvme);
continue;
}
break;
@@ -2350,6 +2430,7 @@
struct nvme_fc_remote_port *remote_port;
struct nvme_fc_port_info rpinfo;
struct lpfc_nodelist *prev_ndlp = NULL;
+ struct fc_rport *srport = ndlp->rport;
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NVME_DISC,
"6006 Register NVME PORT. DID x%06x nlptype x%x\n",
@@ -2379,6 +2460,10 @@
rpinfo.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
rpinfo.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
+ if (srport)
+ rpinfo.dev_loss_tmo = srport->dev_loss_tmo;
+ else
+ rpinfo.dev_loss_tmo = vport->cfg_devloss_tmo;
spin_lock_irq(&vport->phba->hbalock);
oldrport = lpfc_ndlp_get_nrport(ndlp);
@@ -2404,38 +2489,6 @@
spin_unlock_irq(&vport->phba->hbalock);
rport = remote_port->private;
if (oldrport) {
- /* New remoteport record does not guarantee valid
- * host private memory area.
- */
- if (oldrport == remote_port->private) {
- /* Same remoteport - ndlp should match.
- * Just reuse.
- */
- lpfc_printf_vlog(ndlp->vport, KERN_INFO,
- LOG_NVME_DISC,
- "6014 Rebind lport to current "
- "remoteport x%px wwpn 0x%llx, "
- "Data: x%x x%x x%px x%px x%x "
- " x%06x\n",
- remote_port,
- remote_port->port_name,
- remote_port->port_id,
- remote_port->port_role,
- oldrport->ndlp,
- ndlp,
- ndlp->nlp_type,
- ndlp->nlp_DID);
-
- /* It's a complete rebind only if the driver
- * is registering with the same ndlp. Otherwise
- * the driver likely executed a node swap
- * prior to this registration and the ndlp to
- * remoteport binding needs to be redone.
- */
- if (prev_ndlp == ndlp)
- return 0;
-
- }
/* Sever the ndlp<->rport association
* before dropping the ndlp ref from
@@ -2478,7 +2531,7 @@
ndlp, prev_ndlp);
} else {
lpfc_printf_vlog(vport, KERN_ERR,
- LOG_NVME_DISC | LOG_NODE,
+ LOG_TRACE_EVENT,
"6031 RemotePort Registration failed "
"err: %d, DID x%06x\n",
ret, ndlp->nlp_DID);
@@ -2524,7 +2577,7 @@
ndlp->nlp_state == NLP_STE_MAPPED_NODE) {
nvme_fc_rescan_remoteport(remoteport);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6172 NVME rescanned DID x%06x "
"port_state x%x\n",
ndlp->nlp_DID, remoteport->port_state);
@@ -2607,7 +2660,7 @@
ret = nvme_fc_unregister_remoteport(remoteport);
if (ret != 0) {
lpfc_nlp_put(ndlp);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6167 NVME unregister failed %d "
"port_state x%x\n",
ret, remoteport->port_state);
@@ -2617,7 +2670,7 @@
input_err:
#endif
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_DISC,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"6168 State error: lport x%px, rport x%px FCID x%06x\n",
vport->localport, ndlp->rport, ndlp->nlp_DID);
}
@@ -2702,7 +2755,7 @@
* dump a message. Something is wrong.
*/
if ((wait_cnt % 1000) == 0) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6178 NVME IO not empty, "
"cnt %d\n", wait_cnt);
}
diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h
index 593c48f..4a4c3f7 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.h
+++ b/drivers/scsi/lpfc/lpfc_nvme.h
@@ -21,6 +21,10 @@
* included with this package. *
********************************************************************/
+#include <linux/nvme.h>
+#include <linux/nvme-fc-driver.h>
+#include <linux/nvme-fc.h>
+
#define LPFC_NVME_DEFAULT_SEGS (64 + 1) /* 256K IOs */
#define LPFC_NVME_ERSP_LEN 0x20
@@ -74,3 +78,179 @@
struct lpfc_nvme_fcpreq_priv {
struct lpfc_io_buf *nvme_buf;
};
+
+/*
+ * set NVME LS request timeouts to 30s. It is larger than the 2*R_A_TOV
+ * set by the spec, which appears to have issues with some devices.
+ */
+#define LPFC_NVME_LS_TIMEOUT 30
+
+
+#define LPFC_NVMET_DEFAULT_SEGS (64 + 1) /* 256K IOs */
+#define LPFC_NVMET_RQE_MIN_POST 128
+#define LPFC_NVMET_RQE_DEF_POST 512
+#define LPFC_NVMET_RQE_DEF_COUNT 2048
+#define LPFC_NVMET_SUCCESS_LEN 12
+
+#define LPFC_NVMET_MRQ_AUTO 0
+#define LPFC_NVMET_MRQ_MAX 16
+
+#define LPFC_NVMET_WAIT_TMO (5 * MSEC_PER_SEC)
+
+/* Used for NVME Target */
+#define LPFC_NVMET_INV_HOST_ACTIVE 1
+
+struct lpfc_nvmet_tgtport {
+ struct lpfc_hba *phba;
+ struct completion *tport_unreg_cmp;
+ atomic_t state; /* tracks nvmet hosthandle invalidation */
+
+ /* Stats counters - lpfc_nvmet_unsol_ls_buffer */
+ atomic_t rcv_ls_req_in;
+ atomic_t rcv_ls_req_out;
+ atomic_t rcv_ls_req_drop;
+ atomic_t xmt_ls_abort;
+ atomic_t xmt_ls_abort_cmpl;
+
+ /* Stats counters - lpfc_nvmet_xmt_ls_rsp */
+ atomic_t xmt_ls_rsp;
+ atomic_t xmt_ls_drop;
+
+ /* Stats counters - lpfc_nvmet_xmt_ls_rsp_cmp */
+ atomic_t xmt_ls_rsp_error;
+ atomic_t xmt_ls_rsp_aborted;
+ atomic_t xmt_ls_rsp_xb_set;
+ atomic_t xmt_ls_rsp_cmpl;
+
+ /* Stats counters - lpfc_nvmet_unsol_fcp_buffer */
+ atomic_t rcv_fcp_cmd_in;
+ atomic_t rcv_fcp_cmd_out;
+ atomic_t rcv_fcp_cmd_drop;
+ atomic_t rcv_fcp_cmd_defer;
+ atomic_t xmt_fcp_release;
+
+ /* Stats counters - lpfc_nvmet_xmt_fcp_op */
+ atomic_t xmt_fcp_drop;
+ atomic_t xmt_fcp_read_rsp;
+ atomic_t xmt_fcp_read;
+ atomic_t xmt_fcp_write;
+ atomic_t xmt_fcp_rsp;
+
+ /* Stats counters - lpfc_nvmet_xmt_fcp_op_cmp */
+ atomic_t xmt_fcp_rsp_xb_set;
+ atomic_t xmt_fcp_rsp_cmpl;
+ atomic_t xmt_fcp_rsp_error;
+ atomic_t xmt_fcp_rsp_aborted;
+ atomic_t xmt_fcp_rsp_drop;
+
+ /* Stats counters - lpfc_nvmet_xmt_fcp_abort */
+ atomic_t xmt_fcp_xri_abort_cqe;
+ atomic_t xmt_fcp_abort;
+ atomic_t xmt_fcp_abort_cmpl;
+ atomic_t xmt_abort_sol;
+ atomic_t xmt_abort_unsol;
+ atomic_t xmt_abort_rsp;
+ atomic_t xmt_abort_rsp_error;
+
+ /* Stats counters - defer IO */
+ atomic_t defer_ctx;
+ atomic_t defer_fod;
+ atomic_t defer_wqfull;
+};
+
+struct lpfc_nvmet_ctx_info {
+ struct list_head nvmet_ctx_list;
+ spinlock_t nvmet_ctx_list_lock; /* lock per CPU */
+ struct lpfc_nvmet_ctx_info *nvmet_ctx_next_cpu;
+ struct lpfc_nvmet_ctx_info *nvmet_ctx_start_cpu;
+ uint16_t nvmet_ctx_list_cnt;
+ char pad[16]; /* pad to a cache-line */
+};
+
+/* This retrieves the context info associated with the specified cpu / mrq */
+#define lpfc_get_ctx_list(phba, cpu, mrq) \
+ (phba->sli4_hba.nvmet_ctx_info + ((cpu * phba->cfg_nvmet_mrq) + mrq))
+
+/* Values for state field of struct lpfc_async_xchg_ctx */
+#define LPFC_NVME_STE_LS_RCV 1
+#define LPFC_NVME_STE_LS_ABORT 2
+#define LPFC_NVME_STE_LS_RSP 3
+#define LPFC_NVME_STE_RCV 4
+#define LPFC_NVME_STE_DATA 5
+#define LPFC_NVME_STE_ABORT 6
+#define LPFC_NVME_STE_DONE 7
+#define LPFC_NVME_STE_FREE 0xff
+
+/* Values for flag field of struct lpfc_async_xchg_ctx */
+#define LPFC_NVME_IO_INP 0x1 /* IO is in progress on exchange */
+#define LPFC_NVME_ABORT_OP 0x2 /* Abort WQE issued on exchange */
+#define LPFC_NVME_XBUSY 0x4 /* XB bit set on IO cmpl */
+#define LPFC_NVME_CTX_RLS 0x8 /* ctx free requested */
+#define LPFC_NVME_ABTS_RCV 0x10 /* ABTS received on exchange */
+#define LPFC_NVME_CTX_REUSE_WQ 0x20 /* ctx reused via WQ */
+#define LPFC_NVME_DEFER_WQFULL 0x40 /* Waiting on a free WQE */
+#define LPFC_NVME_TNOTIFY 0x80 /* notify transport of abts */
+
+struct lpfc_async_xchg_ctx {
+ union {
+ struct nvmefc_tgt_fcp_req fcp_req;
+ } hdlrctx;
+ struct list_head list;
+ struct lpfc_hba *phba;
+ struct lpfc_nodelist *ndlp;
+ struct nvmefc_ls_req *ls_req;
+ struct nvmefc_ls_rsp ls_rsp;
+ struct lpfc_iocbq *wqeq;
+ struct lpfc_iocbq *abort_wqeq;
+ spinlock_t ctxlock; /* protect flag access */
+ uint32_t sid;
+ uint32_t offset;
+ uint16_t oxid;
+ uint16_t size;
+ uint16_t entry_cnt;
+ uint16_t cpu;
+ uint16_t idx;
+ uint16_t state;
+ uint16_t flag;
+ void *payload;
+ struct rqb_dmabuf *rqb_buffer;
+ struct lpfc_nvmet_ctxbuf *ctxbuf;
+ struct lpfc_sli4_hdw_queue *hdwq;
+
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ uint64_t ts_isr_cmd;
+ uint64_t ts_cmd_nvme;
+ uint64_t ts_nvme_data;
+ uint64_t ts_data_wqput;
+ uint64_t ts_isr_data;
+ uint64_t ts_data_nvme;
+ uint64_t ts_nvme_status;
+ uint64_t ts_status_wqput;
+ uint64_t ts_isr_status;
+ uint64_t ts_status_nvme;
+#endif
+};
+
+
+/* routines found in lpfc_nvme.c */
+int __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ struct nvmefc_ls_req *pnvme_lsreq,
+ void (*gen_req_cmp)(struct lpfc_hba *phba,
+ struct lpfc_iocbq *cmdwqe,
+ struct lpfc_wcqe_complete *wcqe));
+void __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport,
+ struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe);
+int __lpfc_nvme_ls_abort(struct lpfc_vport *vport,
+ struct lpfc_nodelist *ndlp, struct nvmefc_ls_req *pnvme_lsreq);
+
+/* routines found in lpfc_nvmet.c */
+int lpfc_nvme_unsol_ls_issue_abort(struct lpfc_hba *phba,
+ struct lpfc_async_xchg_ctx *ctxp, uint32_t sid,
+ uint16_t xri);
+int __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg,
+ struct nvmefc_ls_rsp *ls_rsp,
+ void (*xmt_ls_rsp_cmp)(struct lpfc_hba *phba,
+ struct lpfc_iocbq *cmdwqe,
+ struct lpfc_wcqe_complete *wcqe));
+void __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba,
+ struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe);
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
index ce2e2b5..deab893 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.c
+++ b/drivers/scsi/lpfc/lpfc_nvmet.c
@@ -36,10 +36,6 @@
#include <scsi/scsi_transport_fc.h>
#include <scsi/fc/fc_fs.h>
-#include <linux/nvme.h>
-#include <linux/nvme-fc-driver.h>
-#include <linux/nvme-fc.h>
-
#include "lpfc_version.h"
#include "lpfc_hw4.h"
#include "lpfc_hw.h"
@@ -50,29 +46,25 @@
#include "lpfc.h"
#include "lpfc_scsi.h"
#include "lpfc_nvme.h"
-#include "lpfc_nvmet.h"
#include "lpfc_logmsg.h"
#include "lpfc_crtn.h"
#include "lpfc_vport.h"
#include "lpfc_debugfs.h"
static struct lpfc_iocbq *lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *,
- struct lpfc_nvmet_rcv_ctx *,
+ struct lpfc_async_xchg_ctx *,
dma_addr_t rspbuf,
uint16_t rspsize);
static struct lpfc_iocbq *lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *,
- struct lpfc_nvmet_rcv_ctx *);
+ struct lpfc_async_xchg_ctx *);
static int lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *,
- struct lpfc_nvmet_rcv_ctx *,
+ struct lpfc_async_xchg_ctx *,
uint32_t, uint16_t);
static int lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *,
- struct lpfc_nvmet_rcv_ctx *,
+ struct lpfc_async_xchg_ctx *,
uint32_t, uint16_t);
-static int lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *,
- struct lpfc_nvmet_rcv_ctx *,
- uint32_t, uint16_t);
static void lpfc_nvmet_wqfull_flush(struct lpfc_hba *, struct lpfc_queue *,
- struct lpfc_nvmet_rcv_ctx *);
+ struct lpfc_async_xchg_ctx *);
static void lpfc_nvmet_fcp_rqst_defer_work(struct work_struct *);
static void lpfc_nvmet_process_rcv_fcp_req(struct lpfc_nvmet_ctxbuf *ctx_buf);
@@ -221,10 +213,10 @@
}
#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
-static struct lpfc_nvmet_rcv_ctx *
+static struct lpfc_async_xchg_ctx *
lpfc_nvmet_get_ctx_for_xri(struct lpfc_hba *phba, u16 xri)
{
- struct lpfc_nvmet_rcv_ctx *ctxp;
+ struct lpfc_async_xchg_ctx *ctxp;
unsigned long iflag;
bool found = false;
@@ -243,10 +235,10 @@
return NULL;
}
-static struct lpfc_nvmet_rcv_ctx *
+static struct lpfc_async_xchg_ctx *
lpfc_nvmet_get_ctx_for_oxid(struct lpfc_hba *phba, u16 oxid, u32 sid)
{
- struct lpfc_nvmet_rcv_ctx *ctxp;
+ struct lpfc_async_xchg_ctx *ctxp;
unsigned long iflag;
bool found = false;
@@ -267,7 +259,8 @@
#endif
static void
-lpfc_nvmet_defer_release(struct lpfc_hba *phba, struct lpfc_nvmet_rcv_ctx *ctxp)
+lpfc_nvmet_defer_release(struct lpfc_hba *phba,
+ struct lpfc_async_xchg_ctx *ctxp)
{
lockdep_assert_held(&ctxp->ctxlock);
@@ -275,10 +268,10 @@
"6313 NVMET Defer ctx release oxid x%x flg x%x\n",
ctxp->oxid, ctxp->flag);
- if (ctxp->flag & LPFC_NVMET_CTX_RLS)
+ if (ctxp->flag & LPFC_NVME_CTX_RLS)
return;
- ctxp->flag |= LPFC_NVMET_CTX_RLS;
+ ctxp->flag |= LPFC_NVME_CTX_RLS;
spin_lock(&phba->sli4_hba.t_active_list_lock);
list_del(&ctxp->list);
spin_unlock(&phba->sli4_hba.t_active_list_lock);
@@ -288,6 +281,53 @@
}
/**
+ * __lpfc_nvme_xmt_ls_rsp_cmp - Generic completion handler for the
+ * transmission of an NVME LS response.
+ * @phba: Pointer to HBA context object.
+ * @cmdwqe: Pointer to driver command WQE object.
+ * @wcqe: Pointer to driver response CQE object.
+ *
+ * The function is called from SLI ring event handler with no
+ * lock held. The function frees memory resources used for the command
+ * used to send the NVME LS RSP.
+ **/
+void
+__lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+ struct lpfc_wcqe_complete *wcqe)
+{
+ struct lpfc_async_xchg_ctx *axchg = cmdwqe->context2;
+ struct nvmefc_ls_rsp *ls_rsp = &axchg->ls_rsp;
+ uint32_t status, result;
+
+ status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK;
+ result = wcqe->parameter;
+
+ if (axchg->state != LPFC_NVME_STE_LS_RSP || axchg->entry_cnt != 2) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "6410 NVMEx LS cmpl state mismatch IO x%x: "
+ "%d %d\n",
+ axchg->oxid, axchg->state, axchg->entry_cnt);
+ }
+
+ lpfc_nvmeio_data(phba, "NVMEx LS CMPL: xri x%x stat x%x result x%x\n",
+ axchg->oxid, status, result);
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
+ "6038 NVMEx LS rsp cmpl: %d %d oxid x%x\n",
+ status, result, axchg->oxid);
+
+ lpfc_nlp_put(cmdwqe->context1);
+ cmdwqe->context2 = NULL;
+ cmdwqe->context3 = NULL;
+ lpfc_sli_release_iocbq(phba, cmdwqe);
+ ls_rsp->done(ls_rsp);
+ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
+ "6200 NVMEx LS rsp cmpl done status %d oxid x%x\n",
+ status, axchg->oxid);
+ kfree(axchg);
+}
+
+/**
* lpfc_nvmet_xmt_ls_rsp_cmp - Completion handler for LS Response
* @phba: Pointer to HBA context object.
* @cmdwqe: Pointer to driver command WQE object.
@@ -295,33 +335,23 @@
*
* The function is called from SLI ring event handler with no
* lock held. This function is the completion handler for NVME LS commands
- * The function frees memory resources used for the NVME commands.
+ * The function updates any states and statistics, then calls the
+ * generic completion handler to free resources.
**/
static void
lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
struct lpfc_wcqe_complete *wcqe)
{
struct lpfc_nvmet_tgtport *tgtp;
- struct nvmefc_tgt_ls_req *rsp;
- struct lpfc_nvmet_rcv_ctx *ctxp;
uint32_t status, result;
- status = bf_get(lpfc_wcqe_c_status, wcqe);
- result = wcqe->parameter;
- ctxp = cmdwqe->context2;
-
- if (ctxp->state != LPFC_NVMET_STE_LS_RSP || ctxp->entry_cnt != 2) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
- "6410 NVMET LS cmpl state mismatch IO x%x: "
- "%d %d\n",
- ctxp->oxid, ctxp->state, ctxp->entry_cnt);
- }
-
if (!phba->targetport)
- goto out;
+ goto finish;
+
+ status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK;
+ result = wcqe->parameter;
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
-
if (tgtp) {
if (status) {
atomic_inc(&tgtp->xmt_ls_rsp_error);
@@ -334,22 +364,8 @@
}
}
-out:
- rsp = &ctxp->ctx.ls_req;
-
- lpfc_nvmeio_data(phba, "NVMET LS CMPL: xri x%x stat x%x result x%x\n",
- ctxp->oxid, status, result);
-
- lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
- "6038 NVMET LS rsp cmpl: %d %d oxid x%x\n",
- status, result, ctxp->oxid);
-
- lpfc_nlp_put(cmdwqe->context1);
- cmdwqe->context2 = NULL;
- cmdwqe->context3 = NULL;
- lpfc_sli_release_iocbq(phba, cmdwqe);
- rsp->done(rsp);
- kfree(ctxp);
+finish:
+ __lpfc_nvme_xmt_ls_rsp_cmp(phba, cmdwqe, wcqe);
}
/**
@@ -369,7 +385,7 @@
lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf)
{
#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
- struct lpfc_nvmet_rcv_ctx *ctxp = ctx_buf->context;
+ struct lpfc_async_xchg_ctx *ctxp = ctx_buf->context;
struct lpfc_nvmet_tgtport *tgtp;
struct fc_frame_header *fc_hdr;
struct rqb_dmabuf *nvmebuf;
@@ -378,15 +394,8 @@
int cpu;
unsigned long iflag;
- if (ctxp->txrdy) {
- dma_pool_free(phba->txrdy_payload_pool, ctxp->txrdy,
- ctxp->txrdy_phys);
- ctxp->txrdy = NULL;
- ctxp->txrdy_phys = 0;
- }
-
- if (ctxp->state == LPFC_NVMET_STE_FREE) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ if (ctxp->state == LPFC_NVME_STE_FREE) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6411 NVMET free, already free IO x%x: %d %d\n",
ctxp->oxid, ctxp->state, ctxp->entry_cnt);
}
@@ -397,8 +406,8 @@
/* check if freed in another path whilst acquiring lock */
if (nvmebuf) {
ctxp->rqb_buffer = NULL;
- if (ctxp->flag & LPFC_NVMET_CTX_REUSE_WQ) {
- ctxp->flag &= ~LPFC_NVMET_CTX_REUSE_WQ;
+ if (ctxp->flag & LPFC_NVME_CTX_REUSE_WQ) {
+ ctxp->flag &= ~LPFC_NVME_CTX_REUSE_WQ;
spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
nvmebuf->hrq->rqbp->rqb_free_buffer(phba,
nvmebuf);
@@ -411,7 +420,7 @@
spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
}
}
- ctxp->state = LPFC_NVMET_STE_FREE;
+ ctxp->state = LPFC_NVME_STE_FREE;
spin_lock_irqsave(&phba->sli4_hba.nvmet_io_wait_lock, iflag);
if (phba->sli4_hba.nvmet_io_wait_cnt) {
@@ -428,15 +437,14 @@
size = nvmebuf->bytes_recv;
sid = sli4_sid_from_fc_hdr(fc_hdr);
- ctxp = (struct lpfc_nvmet_rcv_ctx *)ctx_buf->context;
+ ctxp = (struct lpfc_async_xchg_ctx *)ctx_buf->context;
ctxp->wqeq = NULL;
- ctxp->txrdy = NULL;
ctxp->offset = 0;
ctxp->phba = phba;
ctxp->size = size;
ctxp->oxid = oxid;
ctxp->sid = sid;
- ctxp->state = LPFC_NVMET_STE_RCV;
+ ctxp->state = LPFC_NVME_STE_RCV;
ctxp->entry_cnt = 1;
ctxp->flag = 0;
ctxp->ctxbuf = ctx_buf;
@@ -461,12 +469,12 @@
/* Indicate that a replacement buffer has been posted */
spin_lock_irqsave(&ctxp->ctxlock, iflag);
- ctxp->flag |= LPFC_NVMET_CTX_REUSE_WQ;
+ ctxp->flag |= LPFC_NVME_CTX_REUSE_WQ;
spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
if (!queue_work(phba->wq, &ctx_buf->defer_work)) {
atomic_inc(&tgtp->rcv_fcp_cmd_drop);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6181 Unable to queue deferred work "
"for oxid x%x. "
"FCP Drop IO [x%x x%x x%x]\n",
@@ -503,7 +511,7 @@
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
static void
lpfc_nvmet_ktime(struct lpfc_hba *phba,
- struct lpfc_nvmet_rcv_ctx *ctxp)
+ struct lpfc_async_xchg_ctx *ctxp)
{
uint64_t seg1, seg2, seg3, seg4, seg5;
uint64_t seg6, seg7, seg8, seg9, seg10;
@@ -712,16 +720,16 @@
{
struct lpfc_nvmet_tgtport *tgtp;
struct nvmefc_tgt_fcp_req *rsp;
- struct lpfc_nvmet_rcv_ctx *ctxp;
+ struct lpfc_async_xchg_ctx *ctxp;
uint32_t status, result, op, start_clean, logerr;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
- uint32_t id;
+ int id;
#endif
ctxp = cmdwqe->context2;
- ctxp->flag &= ~LPFC_NVMET_IO_INP;
+ ctxp->flag &= ~LPFC_NVME_IO_INP;
- rsp = &ctxp->ctx.fcp_req;
+ rsp = &ctxp->hdlrctx.fcp_req;
op = rsp->op;
status = bf_get(lpfc_wcqe_c_status, wcqe);
@@ -748,13 +756,13 @@
/* pick up SLI4 exhange busy condition */
if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
- ctxp->flag |= LPFC_NVMET_XBUSY;
+ ctxp->flag |= LPFC_NVME_XBUSY;
logerr |= LOG_NVME_ABTS;
if (tgtp)
atomic_inc(&tgtp->xmt_fcp_rsp_xb_set);
} else {
- ctxp->flag &= ~LPFC_NVMET_XBUSY;
+ ctxp->flag &= ~LPFC_NVME_XBUSY;
}
lpfc_printf_log(phba, KERN_INFO, logerr,
@@ -776,7 +784,7 @@
if ((op == NVMET_FCOP_READDATA_RSP) ||
(op == NVMET_FCOP_RSP)) {
/* Sanity check */
- ctxp->state = LPFC_NVMET_STE_DONE;
+ ctxp->state = LPFC_NVME_STE_DONE;
ctxp->entry_cnt++;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
@@ -822,31 +830,44 @@
rsp->done(rsp);
}
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
- if (phba->cpucheck_on & LPFC_CHECK_NVMET_IO) {
+ if (phba->hdwqstat_on & LPFC_CHECK_NVMET_IO) {
id = raw_smp_processor_id();
- if (id < LPFC_CHECK_CPU_CNT) {
- if (ctxp->cpu != id)
- lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR,
- "6704 CPU Check cmdcmpl: "
- "cpu %d expect %d\n",
- id, ctxp->cpu);
- phba->sli4_hba.hdwq[rsp->hwqid].cpucheck_cmpl_io[id]++;
- }
+ this_cpu_inc(phba->sli4_hba.c_stat->cmpl_io);
+ if (ctxp->cpu != id)
+ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR,
+ "6704 CPU Check cmdcmpl: "
+ "cpu %d expect %d\n",
+ id, ctxp->cpu);
}
#endif
}
-static int
-lpfc_nvmet_xmt_ls_rsp(struct nvmet_fc_target_port *tgtport,
- struct nvmefc_tgt_ls_req *rsp)
+/**
+ * __lpfc_nvme_xmt_ls_rsp - Generic service routine to issue transmit
+ * an NVME LS rsp for a prior NVME LS request that was received.
+ * @axchg: pointer to exchange context for the NVME LS request the response
+ * is for.
+ * @ls_rsp: pointer to the transport LS RSP that is to be sent
+ * @xmt_ls_rsp_cmp: completion routine to call upon RSP transmit done
+ *
+ * This routine is used to format and send a WQE to transmit a NVME LS
+ * Response. The response is for a prior NVME LS request that was
+ * received and posted to the transport.
+ *
+ * Returns:
+ * 0 : if response successfully transmit
+ * non-zero : if response failed to transmit, of the form -Exxx.
+ **/
+int
+__lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg,
+ struct nvmefc_ls_rsp *ls_rsp,
+ void (*xmt_ls_rsp_cmp)(struct lpfc_hba *phba,
+ struct lpfc_iocbq *cmdwqe,
+ struct lpfc_wcqe_complete *wcqe))
{
- struct lpfc_nvmet_rcv_ctx *ctxp =
- container_of(rsp, struct lpfc_nvmet_rcv_ctx, ctx.ls_req);
- struct lpfc_hba *phba = ctxp->phba;
- struct hbq_dmabuf *nvmebuf =
- (struct hbq_dmabuf *)ctxp->rqb_buffer;
+ struct lpfc_hba *phba = axchg->phba;
+ struct hbq_dmabuf *nvmebuf = (struct hbq_dmabuf *)axchg->rqb_buffer;
struct lpfc_iocbq *nvmewqeq;
- struct lpfc_nvmet_tgtport *nvmep = tgtport->private;
struct lpfc_dmabuf dmabuf;
struct ulp_bde64 bpl;
int rc;
@@ -854,34 +875,27 @@
if (phba->pport->load_flag & FC_UNLOADING)
return -ENODEV;
- if (phba->pport->load_flag & FC_UNLOADING)
- return -ENODEV;
-
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
- "6023 NVMET LS rsp oxid x%x\n", ctxp->oxid);
+ "6023 NVMEx LS rsp oxid x%x\n", axchg->oxid);
- if ((ctxp->state != LPFC_NVMET_STE_LS_RCV) ||
- (ctxp->entry_cnt != 1)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
- "6412 NVMET LS rsp state mismatch "
+ if (axchg->state != LPFC_NVME_STE_LS_RCV || axchg->entry_cnt != 1) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "6412 NVMEx LS rsp state mismatch "
"oxid x%x: %d %d\n",
- ctxp->oxid, ctxp->state, ctxp->entry_cnt);
+ axchg->oxid, axchg->state, axchg->entry_cnt);
+ return -EALREADY;
}
- ctxp->state = LPFC_NVMET_STE_LS_RSP;
- ctxp->entry_cnt++;
+ axchg->state = LPFC_NVME_STE_LS_RSP;
+ axchg->entry_cnt++;
- nvmewqeq = lpfc_nvmet_prep_ls_wqe(phba, ctxp, rsp->rspdma,
- rsp->rsplen);
+ nvmewqeq = lpfc_nvmet_prep_ls_wqe(phba, axchg, ls_rsp->rspdma,
+ ls_rsp->rsplen);
if (nvmewqeq == NULL) {
- atomic_inc(&nvmep->xmt_ls_drop);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
- "6150 LS Drop IO x%x: Prep\n",
- ctxp->oxid);
- lpfc_in_buf_free(phba, &nvmebuf->dbuf);
- atomic_inc(&nvmep->xmt_ls_abort);
- lpfc_nvmet_unsol_ls_issue_abort(phba, ctxp,
- ctxp->sid, ctxp->oxid);
- return -ENOMEM;
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "6150 NVMEx LS Drop Rsp x%x: Prep\n",
+ axchg->oxid);
+ rc = -ENOMEM;
+ goto out_free_buf;
}
/* Save numBdes for bpl2sgl */
@@ -891,39 +905,105 @@
dmabuf.virt = &bpl;
bpl.addrLow = nvmewqeq->wqe.xmit_sequence.bde.addrLow;
bpl.addrHigh = nvmewqeq->wqe.xmit_sequence.bde.addrHigh;
- bpl.tus.f.bdeSize = rsp->rsplen;
+ bpl.tus.f.bdeSize = ls_rsp->rsplen;
bpl.tus.f.bdeFlags = 0;
bpl.tus.w = le32_to_cpu(bpl.tus.w);
+ /*
+ * Note: although we're using stack space for the dmabuf, the
+ * call to lpfc_sli4_issue_wqe is synchronous, so it will not
+ * be referenced after it returns back to this routine.
+ */
- nvmewqeq->wqe_cmpl = lpfc_nvmet_xmt_ls_rsp_cmp;
+ nvmewqeq->wqe_cmpl = xmt_ls_rsp_cmp;
nvmewqeq->iocb_cmpl = NULL;
- nvmewqeq->context2 = ctxp;
+ nvmewqeq->context2 = axchg;
- lpfc_nvmeio_data(phba, "NVMET LS RESP: xri x%x wqidx x%x len x%x\n",
- ctxp->oxid, nvmewqeq->hba_wqidx, rsp->rsplen);
+ lpfc_nvmeio_data(phba, "NVMEx LS RSP: xri x%x wqidx x%x len x%x\n",
+ axchg->oxid, nvmewqeq->hba_wqidx, ls_rsp->rsplen);
- rc = lpfc_sli4_issue_wqe(phba, ctxp->hdwq, nvmewqeq);
+ rc = lpfc_sli4_issue_wqe(phba, axchg->hdwq, nvmewqeq);
+
+ /* clear to be sure there's no reference */
+ nvmewqeq->context3 = NULL;
+
if (rc == WQE_SUCCESS) {
/*
* Okay to repost buffer here, but wait till cmpl
* before freeing ctxp and iocbq.
*/
lpfc_in_buf_free(phba, &nvmebuf->dbuf);
- atomic_inc(&nvmep->xmt_ls_rsp);
return 0;
}
- /* Give back resources */
- atomic_inc(&nvmep->xmt_ls_drop);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
- "6151 LS Drop IO x%x: Issue %d\n",
- ctxp->oxid, rc);
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "6151 NVMEx LS RSP x%x: failed to transmit %d\n",
+ axchg->oxid, rc);
+
+ rc = -ENXIO;
lpfc_nlp_put(nvmewqeq->context1);
+out_free_buf:
+ /* Give back resources */
lpfc_in_buf_free(phba, &nvmebuf->dbuf);
- atomic_inc(&nvmep->xmt_ls_abort);
- lpfc_nvmet_unsol_ls_issue_abort(phba, ctxp, ctxp->sid, ctxp->oxid);
- return -ENXIO;
+
+ /*
+ * As transport doesn't track completions of responses, if the rsp
+ * fails to send, the transport will effectively ignore the rsp
+ * and consider the LS done. However, the driver has an active
+ * exchange open for the LS - so be sure to abort the exchange
+ * if the response isn't sent.
+ */
+ lpfc_nvme_unsol_ls_issue_abort(phba, axchg, axchg->sid, axchg->oxid);
+ return rc;
+}
+
+/**
+ * lpfc_nvmet_xmt_ls_rsp - Transmit NVME LS response
+ * @tgtport: pointer to target port that NVME LS is to be transmit from.
+ * @ls_rsp: pointer to the transport LS RSP that is to be sent
+ *
+ * Driver registers this routine to transmit responses for received NVME
+ * LS requests.
+ *
+ * This routine is used to format and send a WQE to transmit a NVME LS
+ * Response. The ls_rsp is used to reverse-map the LS to the original
+ * NVME LS request sequence, which provides addressing information for
+ * the remote port the LS to be sent to, as well as the exchange id
+ * that is the LS is bound to.
+ *
+ * Returns:
+ * 0 : if response successfully transmit
+ * non-zero : if response failed to transmit, of the form -Exxx.
+ **/
+static int
+lpfc_nvmet_xmt_ls_rsp(struct nvmet_fc_target_port *tgtport,
+ struct nvmefc_ls_rsp *ls_rsp)
+{
+ struct lpfc_async_xchg_ctx *axchg =
+ container_of(ls_rsp, struct lpfc_async_xchg_ctx, ls_rsp);
+ struct lpfc_nvmet_tgtport *nvmep = tgtport->private;
+ int rc;
+
+ if (axchg->phba->pport->load_flag & FC_UNLOADING)
+ return -ENODEV;
+
+ rc = __lpfc_nvme_xmt_ls_rsp(axchg, ls_rsp, lpfc_nvmet_xmt_ls_rsp_cmp);
+
+ if (rc) {
+ atomic_inc(&nvmep->xmt_ls_drop);
+ /*
+ * unless the failure is due to having already sent
+ * the response, an abort will be generated for the
+ * exchange if the rsp can't be sent.
+ */
+ if (rc != -EALREADY)
+ atomic_inc(&nvmep->xmt_ls_abort);
+ return rc;
+ }
+
+ atomic_inc(&nvmep->xmt_ls_rsp);
+ return 0;
}
static int
@@ -931,19 +1011,17 @@
struct nvmefc_tgt_fcp_req *rsp)
{
struct lpfc_nvmet_tgtport *lpfc_nvmep = tgtport->private;
- struct lpfc_nvmet_rcv_ctx *ctxp =
- container_of(rsp, struct lpfc_nvmet_rcv_ctx, ctx.fcp_req);
+ struct lpfc_async_xchg_ctx *ctxp =
+ container_of(rsp, struct lpfc_async_xchg_ctx, hdlrctx.fcp_req);
struct lpfc_hba *phba = ctxp->phba;
struct lpfc_queue *wq;
struct lpfc_iocbq *nvmewqeq;
struct lpfc_sli_ring *pring;
unsigned long iflags;
int rc;
-
- if (phba->pport->load_flag & FC_UNLOADING) {
- rc = -ENODEV;
- goto aerr;
- }
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ int id;
+#endif
if (phba->pport->load_flag & FC_UNLOADING) {
rc = -ENODEV;
@@ -962,25 +1040,23 @@
if (!ctxp->hdwq)
ctxp->hdwq = &phba->sli4_hba.hdwq[rsp->hwqid];
- if (phba->cpucheck_on & LPFC_CHECK_NVMET_IO) {
- int id = raw_smp_processor_id();
- if (id < LPFC_CHECK_CPU_CNT) {
- if (rsp->hwqid != id)
- lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR,
- "6705 CPU Check OP: "
- "cpu %d expect %d\n",
- id, rsp->hwqid);
- phba->sli4_hba.hdwq[rsp->hwqid].cpucheck_xmt_io[id]++;
- }
+ if (phba->hdwqstat_on & LPFC_CHECK_NVMET_IO) {
+ id = raw_smp_processor_id();
+ this_cpu_inc(phba->sli4_hba.c_stat->xmt_io);
+ if (rsp->hwqid != id)
+ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR,
+ "6705 CPU Check OP: "
+ "cpu %d expect %d\n",
+ id, rsp->hwqid);
ctxp->cpu = id; /* Setup cpu for cmpl check */
}
#endif
/* Sanity check */
- if ((ctxp->flag & LPFC_NVMET_ABTS_RCV) ||
- (ctxp->state == LPFC_NVMET_STE_ABORT)) {
+ if ((ctxp->flag & LPFC_NVME_ABTS_RCV) ||
+ (ctxp->state == LPFC_NVME_STE_ABORT)) {
atomic_inc(&lpfc_nvmep->xmt_fcp_drop);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6102 IO oxid x%x aborted\n",
ctxp->oxid);
rc = -ENXIO;
@@ -990,7 +1066,7 @@
nvmewqeq = lpfc_nvmet_prep_fcp_wqe(phba, ctxp);
if (nvmewqeq == NULL) {
atomic_inc(&lpfc_nvmep->xmt_fcp_drop);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6152 FCP Drop IO x%x: Prep\n",
ctxp->oxid);
rc = -ENXIO;
@@ -1006,7 +1082,7 @@
lpfc_nvmeio_data(phba, "NVMET FCP CMND: xri x%x op x%x len x%x\n",
ctxp->oxid, rsp->op, rsp->rsplen);
- ctxp->flag |= LPFC_NVMET_IO_INP;
+ ctxp->flag |= LPFC_NVME_IO_INP;
rc = lpfc_sli4_issue_wqe(phba, ctxp->hdwq, nvmewqeq);
if (rc == WQE_SUCCESS) {
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
@@ -1025,7 +1101,7 @@
* WQ was full, so queue nvmewqeq to be sent after
* WQE release CQE
*/
- ctxp->flag |= LPFC_NVMET_DEFER_WQFULL;
+ ctxp->flag |= LPFC_NVME_DEFER_WQFULL;
wq = ctxp->hdwq->io_wq;
pring = wq->pring;
spin_lock_irqsave(&pring->ring_lock, iflags);
@@ -1038,7 +1114,7 @@
/* Give back resources */
atomic_inc(&lpfc_nvmep->xmt_fcp_drop);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6153 FCP Drop IO x%x: Issue: %d\n",
ctxp->oxid, rc);
@@ -1065,8 +1141,8 @@
struct nvmefc_tgt_fcp_req *req)
{
struct lpfc_nvmet_tgtport *lpfc_nvmep = tgtport->private;
- struct lpfc_nvmet_rcv_ctx *ctxp =
- container_of(req, struct lpfc_nvmet_rcv_ctx, ctx.fcp_req);
+ struct lpfc_async_xchg_ctx *ctxp =
+ container_of(req, struct lpfc_async_xchg_ctx, hdlrctx.fcp_req);
struct lpfc_hba *phba = ctxp->phba;
struct lpfc_queue *wq;
unsigned long flags;
@@ -1074,9 +1150,6 @@
if (phba->pport->load_flag & FC_UNLOADING)
return;
- if (phba->pport->load_flag & FC_UNLOADING)
- return;
-
if (!ctxp->hdwq)
ctxp->hdwq = &phba->sli4_hba.hdwq[0];
@@ -1094,13 +1167,13 @@
/* Since iaab/iaar are NOT set, we need to check
* if the firmware is in process of aborting IO
*/
- if (ctxp->flag & (LPFC_NVMET_XBUSY | LPFC_NVMET_ABORT_OP)) {
+ if (ctxp->flag & (LPFC_NVME_XBUSY | LPFC_NVME_ABORT_OP)) {
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
return;
}
- ctxp->flag |= LPFC_NVMET_ABORT_OP;
+ ctxp->flag |= LPFC_NVME_ABORT_OP;
- if (ctxp->flag & LPFC_NVMET_DEFER_WQFULL) {
+ if (ctxp->flag & LPFC_NVME_DEFER_WQFULL) {
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
lpfc_nvmet_unsol_fcp_issue_abort(phba, ctxp, ctxp->sid,
ctxp->oxid);
@@ -1110,11 +1183,11 @@
}
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
- /* An state of LPFC_NVMET_STE_RCV means we have just received
+ /* A state of LPFC_NVME_STE_RCV means we have just received
* the NVME command and have not started processing it.
* (by issuing any IO WQEs on this exchange yet)
*/
- if (ctxp->state == LPFC_NVMET_STE_RCV)
+ if (ctxp->state == LPFC_NVME_STE_RCV)
lpfc_nvmet_unsol_fcp_issue_abort(phba, ctxp, ctxp->sid,
ctxp->oxid);
else
@@ -1127,26 +1200,26 @@
struct nvmefc_tgt_fcp_req *rsp)
{
struct lpfc_nvmet_tgtport *lpfc_nvmep = tgtport->private;
- struct lpfc_nvmet_rcv_ctx *ctxp =
- container_of(rsp, struct lpfc_nvmet_rcv_ctx, ctx.fcp_req);
+ struct lpfc_async_xchg_ctx *ctxp =
+ container_of(rsp, struct lpfc_async_xchg_ctx, hdlrctx.fcp_req);
struct lpfc_hba *phba = ctxp->phba;
unsigned long flags;
bool aborting = false;
spin_lock_irqsave(&ctxp->ctxlock, flags);
- if (ctxp->flag & LPFC_NVMET_XBUSY)
+ if (ctxp->flag & LPFC_NVME_XBUSY)
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR,
"6027 NVMET release with XBUSY flag x%x"
" oxid x%x\n",
ctxp->flag, ctxp->oxid);
- else if (ctxp->state != LPFC_NVMET_STE_DONE &&
- ctxp->state != LPFC_NVMET_STE_ABORT)
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ else if (ctxp->state != LPFC_NVME_STE_DONE &&
+ ctxp->state != LPFC_NVME_STE_ABORT)
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6413 NVMET release bad state %d %d oxid x%x\n",
ctxp->state, ctxp->entry_cnt, ctxp->oxid);
- if ((ctxp->flag & LPFC_NVMET_ABORT_OP) ||
- (ctxp->flag & LPFC_NVMET_XBUSY)) {
+ if ((ctxp->flag & LPFC_NVME_ABORT_OP) ||
+ (ctxp->flag & LPFC_NVME_XBUSY)) {
aborting = true;
/* let the abort path do the real release */
lpfc_nvmet_defer_release(phba, ctxp);
@@ -1157,7 +1230,7 @@
ctxp->state, aborting);
atomic_inc(&lpfc_nvmep->xmt_fcp_release);
- ctxp->flag &= ~LPFC_NVMET_TNOTIFY;
+ ctxp->flag &= ~LPFC_NVME_TNOTIFY;
if (aborting)
return;
@@ -1170,8 +1243,8 @@
struct nvmefc_tgt_fcp_req *rsp)
{
struct lpfc_nvmet_tgtport *tgtp;
- struct lpfc_nvmet_rcv_ctx *ctxp =
- container_of(rsp, struct lpfc_nvmet_rcv_ctx, ctx.fcp_req);
+ struct lpfc_async_xchg_ctx *ctxp =
+ container_of(rsp, struct lpfc_async_xchg_ctx, hdlrctx.fcp_req);
struct rqb_dmabuf *nvmebuf = ctxp->rqb_buffer;
struct lpfc_hba *phba = ctxp->phba;
unsigned long iflag;
@@ -1199,6 +1272,116 @@
spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
}
+/**
+ * lpfc_nvmet_ls_req_cmp - completion handler for a nvme ls request
+ * @phba: Pointer to HBA context object
+ * @cmdwqe: Pointer to driver command WQE object.
+ * @wcqe: Pointer to driver response CQE object.
+ *
+ * This function is the completion handler for NVME LS requests.
+ * The function updates any states and statistics, then calls the
+ * generic completion handler to finish completion of the request.
+ **/
+static void
+lpfc_nvmet_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+ struct lpfc_wcqe_complete *wcqe)
+{
+ __lpfc_nvme_ls_req_cmp(phba, cmdwqe->vport, cmdwqe, wcqe);
+}
+
+/**
+ * lpfc_nvmet_ls_req - Issue an Link Service request
+ * @targetport - pointer to target instance registered with nvmet transport.
+ * @hosthandle - hosthandle set by the driver in a prior ls_rqst_rcv.
+ * Driver sets this value to the ndlp pointer.
+ * @pnvme_lsreq - the transport nvme_ls_req structure for the LS
+ *
+ * Driver registers this routine to handle any link service request
+ * from the nvme_fc transport to a remote nvme-aware port.
+ *
+ * Return value :
+ * 0 - Success
+ * non-zero: various error codes, in form of -Exxx
+ **/
+static int
+lpfc_nvmet_ls_req(struct nvmet_fc_target_port *targetport,
+ void *hosthandle,
+ struct nvmefc_ls_req *pnvme_lsreq)
+{
+ struct lpfc_nvmet_tgtport *lpfc_nvmet = targetport->private;
+ struct lpfc_hba *phba;
+ struct lpfc_nodelist *ndlp;
+ int ret;
+ u32 hstate;
+
+ if (!lpfc_nvmet)
+ return -EINVAL;
+
+ phba = lpfc_nvmet->phba;
+ if (phba->pport->load_flag & FC_UNLOADING)
+ return -EINVAL;
+
+ hstate = atomic_read(&lpfc_nvmet->state);
+ if (hstate == LPFC_NVMET_INV_HOST_ACTIVE)
+ return -EACCES;
+
+ ndlp = (struct lpfc_nodelist *)hosthandle;
+
+ ret = __lpfc_nvme_ls_req(phba->pport, ndlp, pnvme_lsreq,
+ lpfc_nvmet_ls_req_cmp);
+
+ return ret;
+}
+
+/**
+ * lpfc_nvmet_ls_abort - Abort a prior NVME LS request
+ * @targetport: Transport targetport, that LS was issued from.
+ * @hosthandle - hosthandle set by the driver in a prior ls_rqst_rcv.
+ * Driver sets this value to the ndlp pointer.
+ * @pnvme_lsreq - the transport nvme_ls_req structure for LS to be aborted
+ *
+ * Driver registers this routine to abort an NVME LS request that is
+ * in progress (from the transports perspective).
+ **/
+static void
+lpfc_nvmet_ls_abort(struct nvmet_fc_target_port *targetport,
+ void *hosthandle,
+ struct nvmefc_ls_req *pnvme_lsreq)
+{
+ struct lpfc_nvmet_tgtport *lpfc_nvmet = targetport->private;
+ struct lpfc_hba *phba;
+ struct lpfc_nodelist *ndlp;
+ int ret;
+
+ phba = lpfc_nvmet->phba;
+ if (phba->pport->load_flag & FC_UNLOADING)
+ return;
+
+ ndlp = (struct lpfc_nodelist *)hosthandle;
+
+ ret = __lpfc_nvme_ls_abort(phba->pport, ndlp, pnvme_lsreq);
+ if (!ret)
+ atomic_inc(&lpfc_nvmet->xmt_ls_abort);
+}
+
+static void
+lpfc_nvmet_host_release(void *hosthandle)
+{
+ struct lpfc_nodelist *ndlp = hosthandle;
+ struct lpfc_hba *phba = NULL;
+ struct lpfc_nvmet_tgtport *tgtp;
+
+ phba = ndlp->phba;
+ if (!phba->targetport || !phba->targetport->private)
+ return;
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ "6202 NVMET XPT releasing hosthandle x%px\n",
+ hosthandle);
+ tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
+ atomic_set(&tgtp->state, 0);
+}
+
static void
lpfc_nvmet_discovery_event(struct nvmet_fc_target_port *tgtport)
{
@@ -1210,7 +1393,7 @@
phba = tgtp->phba;
rc = lpfc_issue_els_rscn(phba->pport, 0);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6420 NVMET subsystem change: Notification %s\n",
(rc) ? "Failed" : "Sent");
}
@@ -1223,6 +1406,9 @@
.fcp_req_release = lpfc_nvmet_xmt_fcp_release,
.defer_rcv = lpfc_nvmet_defer_rcv,
.discovery_event = lpfc_nvmet_discovery_event,
+ .ls_req = lpfc_nvmet_ls_req,
+ .ls_abort = lpfc_nvmet_ls_abort,
+ .host_release = lpfc_nvmet_host_release,
.max_hw_queues = 1,
.max_sgl_segments = LPFC_NVMET_DEFAULT_SEGS,
@@ -1233,6 +1419,7 @@
.target_features = 0,
/* sizes of additional private data for data structures */
.target_priv_sz = sizeof(struct lpfc_nvmet_tgtport),
+ .lsrqst_priv_sz = 0,
};
static void
@@ -1304,7 +1491,7 @@
phba->sli4_hba.num_possible_cpu * phba->cfg_nvmet_mrq,
sizeof(struct lpfc_nvmet_ctx_info), GFP_KERNEL);
if (!phba->sli4_hba.nvmet_ctx_info) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6419 Failed allocate memory for "
"nvmet context lists\n");
return -ENOMEM;
@@ -1362,7 +1549,7 @@
for (i = 0; i < phba->sli4_hba.nvmet_xri_cnt; i++) {
ctx_buf = kzalloc(sizeof(*ctx_buf), GFP_KERNEL);
if (!ctx_buf) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6404 Ran out of memory for NVMET\n");
return -ENOMEM;
}
@@ -1371,19 +1558,19 @@
GFP_KERNEL);
if (!ctx_buf->context) {
kfree(ctx_buf);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6405 Ran out of NVMET "
"context memory\n");
return -ENOMEM;
}
ctx_buf->context->ctxbuf = ctx_buf;
- ctx_buf->context->state = LPFC_NVMET_STE_FREE;
+ ctx_buf->context->state = LPFC_NVME_STE_FREE;
ctx_buf->iocbq = lpfc_sli_get_iocbq(phba);
if (!ctx_buf->iocbq) {
kfree(ctx_buf->context);
kfree(ctx_buf);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6406 Ran out of NVMET iocb/WQEs\n");
return -ENOMEM;
}
@@ -1402,7 +1589,7 @@
lpfc_sli_release_iocbq(phba, ctx_buf->iocbq);
kfree(ctx_buf->context);
kfree(ctx_buf);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6407 Ran out of NVMET XRIs\n");
return -ENOMEM;
}
@@ -1481,7 +1668,7 @@
error = -ENOENT;
#endif
if (error) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6025 Cannot register NVME targetport x%x: "
"portnm %llx nodenm %llx segs %d qs %d\n",
error,
@@ -1577,7 +1764,7 @@
#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri);
uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri);
- struct lpfc_nvmet_rcv_ctx *ctxp, *next_ctxp;
+ struct lpfc_async_xchg_ctx *ctxp, *next_ctxp;
struct lpfc_nvmet_tgtport *tgtp;
struct nvmefc_tgt_fcp_req *req = NULL;
struct lpfc_nodelist *ndlp;
@@ -1608,12 +1795,12 @@
/* Check if we already received a free context call
* and we have completed processing an abort situation.
*/
- if (ctxp->flag & LPFC_NVMET_CTX_RLS &&
- !(ctxp->flag & LPFC_NVMET_ABORT_OP)) {
+ if (ctxp->flag & LPFC_NVME_CTX_RLS &&
+ !(ctxp->flag & LPFC_NVME_ABORT_OP)) {
list_del_init(&ctxp->list);
released = true;
}
- ctxp->flag &= ~LPFC_NVMET_XBUSY;
+ ctxp->flag &= ~LPFC_NVME_XBUSY;
spin_unlock(&ctxp->ctxlock);
spin_unlock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
@@ -1655,15 +1842,15 @@
rxid);
spin_lock_irqsave(&ctxp->ctxlock, iflag);
- ctxp->flag |= LPFC_NVMET_ABTS_RCV;
- ctxp->state = LPFC_NVMET_STE_ABORT;
+ ctxp->flag |= LPFC_NVME_ABTS_RCV;
+ ctxp->state = LPFC_NVME_STE_ABORT;
spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
lpfc_nvmeio_data(phba,
"NVMET ABTS RCV: xri x%x CPU %02x rjt %d\n",
xri, raw_smp_processor_id(), 0);
- req = &ctxp->ctx.fcp_req;
+ req = &ctxp->hdlrctx.fcp_req;
if (req)
nvmet_fc_rcv_fcp_abort(phba->targetport, req);
}
@@ -1676,7 +1863,7 @@
{
#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
struct lpfc_hba *phba = vport->phba;
- struct lpfc_nvmet_rcv_ctx *ctxp, *next_ctxp;
+ struct lpfc_async_xchg_ctx *ctxp, *next_ctxp;
struct nvmefc_tgt_fcp_req *rsp;
uint32_t sid;
uint16_t oxid, xri;
@@ -1699,7 +1886,7 @@
spin_unlock_irqrestore(&phba->hbalock, iflag);
spin_lock_irqsave(&ctxp->ctxlock, iflag);
- ctxp->flag |= LPFC_NVMET_ABTS_RCV;
+ ctxp->flag |= LPFC_NVME_ABTS_RCV;
spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
lpfc_nvmeio_data(phba,
@@ -1709,7 +1896,7 @@
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
"6319 NVMET Rcv ABTS:acc xri x%x\n", xri);
- rsp = &ctxp->ctx.fcp_req;
+ rsp = &ctxp->hdlrctx.fcp_req;
nvmet_fc_rcv_fcp_abort(phba->targetport, rsp);
/* Respond with BA_ACC accordingly */
@@ -1768,7 +1955,7 @@
xri = ctxp->ctxbuf->sglq->sli4_xritag;
spin_lock_irqsave(&ctxp->ctxlock, iflag);
- ctxp->flag |= (LPFC_NVMET_ABTS_RCV | LPFC_NVMET_ABORT_OP);
+ ctxp->flag |= (LPFC_NVME_ABTS_RCV | LPFC_NVME_ABORT_OP);
spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
lpfc_nvmeio_data(phba,
@@ -1780,10 +1967,10 @@
"flag x%x state x%x\n",
ctxp->oxid, xri, ctxp->flag, ctxp->state);
- if (ctxp->flag & LPFC_NVMET_TNOTIFY) {
+ if (ctxp->flag & LPFC_NVME_TNOTIFY) {
/* Notify the transport */
nvmet_fc_rcv_fcp_abort(phba->targetport,
- &ctxp->ctx.fcp_req);
+ &ctxp->hdlrctx.fcp_req);
} else {
cancel_work_sync(&ctxp->ctxbuf->defer_work);
spin_lock_irqsave(&ctxp->ctxlock, iflag);
@@ -1811,7 +1998,7 @@
static void
lpfc_nvmet_wqfull_flush(struct lpfc_hba *phba, struct lpfc_queue *wq,
- struct lpfc_nvmet_rcv_ctx *ctxp)
+ struct lpfc_async_xchg_ctx *ctxp)
{
struct lpfc_sli_ring *pring;
struct lpfc_iocbq *nvmewqeq;
@@ -1862,7 +2049,7 @@
#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
struct lpfc_sli_ring *pring;
struct lpfc_iocbq *nvmewqeq;
- struct lpfc_nvmet_rcv_ctx *ctxp;
+ struct lpfc_async_xchg_ctx *ctxp;
unsigned long iflags;
int rc;
@@ -1876,7 +2063,7 @@
list_remove_head(&wq->wqfull_list, nvmewqeq, struct lpfc_iocbq,
list);
spin_unlock_irqrestore(&pring->ring_lock, iflags);
- ctxp = (struct lpfc_nvmet_rcv_ctx *)nvmewqeq->context2;
+ ctxp = (struct lpfc_async_xchg_ctx *)nvmewqeq->context2;
rc = lpfc_sli4_issue_wqe(phba, ctxp->hdwq, nvmewqeq);
spin_lock_irqsave(&pring->ring_lock, iflags);
if (rc == -EBUSY) {
@@ -1888,7 +2075,7 @@
if (rc == WQE_SUCCESS) {
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (ctxp->ts_cmd_nvme) {
- if (ctxp->ctx.fcp_req.op == NVMET_FCOP_RSP)
+ if (ctxp->hdlrctx.fcp_req.op == NVMET_FCOP_RSP)
ctxp->ts_status_wqput = ktime_get_ns();
else
ctxp->ts_data_wqput = ktime_get_ns();
@@ -1925,7 +2112,7 @@
nvmet_fc_unregister_targetport(phba->targetport);
if (!wait_for_completion_timeout(&tport_unreg_cmp,
msecs_to_jiffies(LPFC_NVMET_WAIT_TMO)))
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6179 Unreg targetport x%px timeout "
"reached.\n", phba->targetport);
lpfc_nvmet_cleanup_io_context(phba);
@@ -1935,113 +2122,61 @@
}
/**
- * lpfc_nvmet_unsol_ls_buffer - Process an unsolicited event data buffer
+ * lpfc_nvmet_handle_lsreq - Process an NVME LS request
* @phba: pointer to lpfc hba data structure.
- * @pring: pointer to a SLI ring.
- * @nvmebuf: pointer to lpfc nvme command HBQ data structure.
+ * @axchg: pointer to exchange context for the NVME LS request
*
- * This routine is used for processing the WQE associated with a unsolicited
- * event. It first determines whether there is an existing ndlp that matches
- * the DID from the unsolicited WQE. If not, it will create a new one with
- * the DID from the unsolicited WQE. The ELS command from the unsolicited
- * WQE is then used to invoke the proper routine and to set up proper state
- * of the discovery state machine.
- **/
-static void
-lpfc_nvmet_unsol_ls_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
- struct hbq_dmabuf *nvmebuf)
+ * This routine is used for processing an asychronously received NVME LS
+ * request. Any remaining validation is done and the LS is then forwarded
+ * to the nvmet-fc transport via nvmet_fc_rcv_ls_req().
+ *
+ * The calling sequence should be: nvmet_fc_rcv_ls_req() -> (processing)
+ * -> lpfc_nvmet_xmt_ls_rsp/cmp -> req->done.
+ * lpfc_nvme_xmt_ls_rsp_cmp should free the allocated axchg.
+ *
+ * Returns 0 if LS was handled and delivered to the transport
+ * Returns 1 if LS failed to be handled and should be dropped
+ */
+int
+lpfc_nvmet_handle_lsreq(struct lpfc_hba *phba,
+ struct lpfc_async_xchg_ctx *axchg)
{
#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
- struct lpfc_nvmet_tgtport *tgtp;
- struct fc_frame_header *fc_hdr;
- struct lpfc_nvmet_rcv_ctx *ctxp;
- uint32_t *payload;
- uint32_t size, oxid, sid, rc;
+ struct lpfc_nvmet_tgtport *tgtp = phba->targetport->private;
+ uint32_t *payload = axchg->payload;
+ int rc;
- fc_hdr = (struct fc_frame_header *)(nvmebuf->hbuf.virt);
- oxid = be16_to_cpu(fc_hdr->fh_ox_id);
-
- if (!phba->targetport) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
- "6154 LS Drop IO x%x\n", oxid);
- oxid = 0;
- size = 0;
- sid = 0;
- ctxp = NULL;
- goto dropit;
- }
-
- tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
- payload = (uint32_t *)(nvmebuf->dbuf.virt);
- size = bf_get(lpfc_rcqe_length, &nvmebuf->cq_event.cqe.rcqe_cmpl);
- sid = sli4_sid_from_fc_hdr(fc_hdr);
-
- ctxp = kzalloc(sizeof(struct lpfc_nvmet_rcv_ctx), GFP_ATOMIC);
- if (ctxp == NULL) {
- atomic_inc(&tgtp->rcv_ls_req_drop);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
- "6155 LS Drop IO x%x: Alloc\n",
- oxid);
-dropit:
- lpfc_nvmeio_data(phba, "NVMET LS DROP: "
- "xri x%x sz %d from %06x\n",
- oxid, size, sid);
- lpfc_in_buf_free(phba, &nvmebuf->dbuf);
- return;
- }
- ctxp->phba = phba;
- ctxp->size = size;
- ctxp->oxid = oxid;
- ctxp->sid = sid;
- ctxp->wqeq = NULL;
- ctxp->state = LPFC_NVMET_STE_LS_RCV;
- ctxp->entry_cnt = 1;
- ctxp->rqb_buffer = (void *)nvmebuf;
- ctxp->hdwq = &phba->sli4_hba.hdwq[0];
-
- lpfc_nvmeio_data(phba, "NVMET LS RCV: xri x%x sz %d from %06x\n",
- oxid, size, sid);
- /*
- * The calling sequence should be:
- * nvmet_fc_rcv_ls_req -> lpfc_nvmet_xmt_ls_rsp/cmp ->_req->done
- * lpfc_nvmet_xmt_ls_rsp_cmp should free the allocated ctxp.
- */
atomic_inc(&tgtp->rcv_ls_req_in);
- rc = nvmet_fc_rcv_ls_req(phba->targetport, &ctxp->ctx.ls_req,
- payload, size);
+
+ /*
+ * Driver passes the ndlp as the hosthandle argument allowing
+ * the transport to generate LS requests for any associateions
+ * that are created.
+ */
+ rc = nvmet_fc_rcv_ls_req(phba->targetport, axchg->ndlp, &axchg->ls_rsp,
+ axchg->payload, axchg->size);
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
"6037 NVMET Unsol rcv: sz %d rc %d: %08x %08x %08x "
- "%08x %08x %08x\n", size, rc,
+ "%08x %08x %08x\n", axchg->size, rc,
*payload, *(payload+1), *(payload+2),
*(payload+3), *(payload+4), *(payload+5));
- if (rc == 0) {
+ if (!rc) {
atomic_inc(&tgtp->rcv_ls_req_out);
- return;
+ return 0;
}
- lpfc_nvmeio_data(phba, "NVMET LS DROP: xri x%x sz %d from %06x\n",
- oxid, size, sid);
-
atomic_inc(&tgtp->rcv_ls_req_drop);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
- "6156 LS Drop IO x%x: nvmet_fc_rcv_ls_req %d\n",
- ctxp->oxid, rc);
-
- /* We assume a rcv'ed cmd ALWAYs fits into 1 buffer */
- lpfc_in_buf_free(phba, &nvmebuf->dbuf);
-
- atomic_inc(&tgtp->xmt_ls_abort);
- lpfc_nvmet_unsol_ls_issue_abort(phba, ctxp, sid, oxid);
#endif
+ return 1;
}
static void
lpfc_nvmet_process_rcv_fcp_req(struct lpfc_nvmet_ctxbuf *ctx_buf)
{
#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
- struct lpfc_nvmet_rcv_ctx *ctxp = ctx_buf->context;
+ struct lpfc_async_xchg_ctx *ctxp = ctx_buf->context;
struct lpfc_hba *phba = ctxp->phba;
struct rqb_dmabuf *nvmebuf = ctxp->rqb_buffer;
struct lpfc_nvmet_tgtport *tgtp;
@@ -2050,7 +2185,7 @@
unsigned long iflags;
if (!nvmebuf) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6159 process_rcv_fcp_req, nvmebuf is NULL, "
"oxid: x%x flg: x%x state: x%x\n",
ctxp->oxid, ctxp->flag, ctxp->state);
@@ -2062,8 +2197,8 @@
return;
}
- if (ctxp->flag & LPFC_NVMET_ABTS_RCV) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ if (ctxp->flag & LPFC_NVME_ABTS_RCV) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6324 IO oxid x%x aborted\n",
ctxp->oxid);
return;
@@ -2071,7 +2206,7 @@
payload = (uint32_t *)(nvmebuf->dbuf.virt);
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
- ctxp->flag |= LPFC_NVMET_TNOTIFY;
+ ctxp->flag |= LPFC_NVME_TNOTIFY;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
if (ctxp->ts_isr_cmd)
ctxp->ts_cmd_nvme = ktime_get_ns();
@@ -2085,13 +2220,13 @@
* A buffer has already been reposted for this IO, so just free
* the nvmebuf.
*/
- rc = nvmet_fc_rcv_fcp_req(phba->targetport, &ctxp->ctx.fcp_req,
+ rc = nvmet_fc_rcv_fcp_req(phba->targetport, &ctxp->hdlrctx.fcp_req,
payload, ctxp->size);
/* Process FCP command */
if (rc == 0) {
atomic_inc(&tgtp->rcv_fcp_cmd_out);
spin_lock_irqsave(&ctxp->ctxlock, iflags);
- if ((ctxp->flag & LPFC_NVMET_CTX_REUSE_WQ) ||
+ if ((ctxp->flag & LPFC_NVME_CTX_REUSE_WQ) ||
(nvmebuf != ctxp->rqb_buffer)) {
spin_unlock_irqrestore(&ctxp->ctxlock, iflags);
return;
@@ -2110,7 +2245,7 @@
atomic_inc(&tgtp->rcv_fcp_cmd_out);
atomic_inc(&tgtp->defer_fod);
spin_lock_irqsave(&ctxp->ctxlock, iflags);
- if (ctxp->flag & LPFC_NVMET_CTX_REUSE_WQ) {
+ if (ctxp->flag & LPFC_NVME_CTX_REUSE_WQ) {
spin_unlock_irqrestore(&ctxp->ctxlock, iflags);
return;
}
@@ -2125,9 +2260,9 @@
phba->sli4_hba.nvmet_mrq_data[qno], 1, qno);
return;
}
- ctxp->flag &= ~LPFC_NVMET_TNOTIFY;
+ ctxp->flag &= ~LPFC_NVME_TNOTIFY;
atomic_inc(&tgtp->rcv_fcp_cmd_drop);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2582 FCP Drop IO x%x: err x%x: x%x x%x x%x\n",
ctxp->oxid, rc,
atomic_read(&tgtp->rcv_fcp_cmd_in),
@@ -2232,7 +2367,7 @@
uint64_t isr_timestamp,
uint8_t cqflag)
{
- struct lpfc_nvmet_rcv_ctx *ctxp;
+ struct lpfc_async_xchg_ctx *ctxp;
struct lpfc_nvmet_tgtport *tgtp;
struct fc_frame_header *fc_hdr;
struct lpfc_nvmet_ctxbuf *ctx_buf;
@@ -2246,7 +2381,7 @@
ctx_buf = NULL;
if (!nvmebuf || !phba->targetport) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6157 NVMET FCP Drop IO\n");
if (nvmebuf)
lpfc_rq_buf_free(phba, &nvmebuf->hbuf);
@@ -2277,15 +2412,13 @@
size = nvmebuf->bytes_recv;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
- if (phba->cpucheck_on & LPFC_CHECK_NVMET_RCV) {
- if (current_cpu < LPFC_CHECK_CPU_CNT) {
- if (idx != current_cpu)
- lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR,
- "6703 CPU Check rcv: "
- "cpu %d expect %d\n",
- current_cpu, idx);
- phba->sli4_hba.hdwq[idx].cpucheck_rcv_io[current_cpu]++;
- }
+ if (phba->hdwqstat_on & LPFC_CHECK_NVMET_IO) {
+ this_cpu_inc(phba->sli4_hba.c_stat->rcv_io);
+ if (idx != current_cpu)
+ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR,
+ "6703 CPU Check rcv: "
+ "cpu %d expect %d\n",
+ current_cpu, idx);
}
#endif
@@ -2316,24 +2449,23 @@
sid = sli4_sid_from_fc_hdr(fc_hdr);
- ctxp = (struct lpfc_nvmet_rcv_ctx *)ctx_buf->context;
+ ctxp = (struct lpfc_async_xchg_ctx *)ctx_buf->context;
spin_lock_irqsave(&phba->sli4_hba.t_active_list_lock, iflag);
list_add_tail(&ctxp->list, &phba->sli4_hba.t_active_ctx_list);
spin_unlock_irqrestore(&phba->sli4_hba.t_active_list_lock, iflag);
- if (ctxp->state != LPFC_NVMET_STE_FREE) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ if (ctxp->state != LPFC_NVME_STE_FREE) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6414 NVMET Context corrupt %d %d oxid x%x\n",
ctxp->state, ctxp->entry_cnt, ctxp->oxid);
}
ctxp->wqeq = NULL;
- ctxp->txrdy = NULL;
ctxp->offset = 0;
ctxp->phba = phba;
ctxp->size = size;
ctxp->oxid = oxid;
ctxp->sid = sid;
ctxp->idx = idx;
- ctxp->state = LPFC_NVMET_STE_RCV;
+ ctxp->state = LPFC_NVME_STE_RCV;
ctxp->entry_cnt = 1;
ctxp->flag = 0;
ctxp->ctxbuf = ctx_buf;
@@ -2364,7 +2496,7 @@
if (!queue_work(phba->wq, &ctx_buf->defer_work)) {
atomic_inc(&tgtp->rcv_fcp_cmd_drop);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6325 Unable to queue work for oxid x%x. "
"FCP Drop IO [x%x x%x x%x]\n",
ctxp->oxid,
@@ -2380,35 +2512,6 @@
}
/**
- * lpfc_nvmet_unsol_ls_event - Process an unsolicited event from an nvme nport
- * @phba: pointer to lpfc hba data structure.
- * @pring: pointer to a SLI ring.
- * @nvmebuf: pointer to received nvme data structure.
- *
- * This routine is used to process an unsolicited event received from a SLI
- * (Service Level Interface) ring. The actual processing of the data buffer
- * associated with the unsolicited event is done by invoking the routine
- * lpfc_nvmet_unsol_ls_buffer() after properly set up the buffer from the
- * SLI RQ on which the unsolicited event was received.
- **/
-void
-lpfc_nvmet_unsol_ls_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
- struct lpfc_iocbq *piocb)
-{
- struct lpfc_dmabuf *d_buf;
- struct hbq_dmabuf *nvmebuf;
-
- d_buf = piocb->context2;
- nvmebuf = container_of(d_buf, struct hbq_dmabuf, dbuf);
-
- if (phba->nvmet_support == 0) {
- lpfc_in_buf_free(phba, &nvmebuf->dbuf);
- return;
- }
- lpfc_nvmet_unsol_ls_buffer(phba, pring, nvmebuf);
-}
-
-/**
* lpfc_nvmet_unsol_fcp_event - Process an unsolicited event from an nvme nport
* @phba: pointer to lpfc hba data structure.
* @idx: relative index of MRQ vector
@@ -2429,6 +2532,11 @@
uint64_t isr_timestamp,
uint8_t cqflag)
{
+ if (!nvmebuf) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "3167 NVMET FCP Drop IO\n");
+ return;
+ }
if (phba->nvmet_support == 0) {
lpfc_rq_buf_free(phba, &nvmebuf->hbuf);
return;
@@ -2463,7 +2571,7 @@
**/
static struct lpfc_iocbq *
lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *phba,
- struct lpfc_nvmet_rcv_ctx *ctxp,
+ struct lpfc_async_xchg_ctx *ctxp,
dma_addr_t rspbuf, uint16_t rspsize)
{
struct lpfc_nodelist *ndlp;
@@ -2471,7 +2579,7 @@
union lpfc_wqe128 *wqe;
if (!lpfc_is_link_up(phba)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6104 NVMET prep LS wqe: link err: "
"NPORT x%x oxid:x%x ste %d\n",
ctxp->sid, ctxp->oxid, ctxp->state);
@@ -2481,7 +2589,7 @@
/* Allocate buffer for command wqe */
nvmewqe = lpfc_sli_get_iocbq(phba);
if (nvmewqe == NULL) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6105 NVMET prep LS wqe: No WQE: "
"NPORT x%x oxid x%x ste %d\n",
ctxp->sid, ctxp->oxid, ctxp->state);
@@ -2492,7 +2600,7 @@
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) ||
((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
(ndlp->nlp_state != NLP_STE_MAPPED_NODE))) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6106 NVMET prep LS wqe: No ndlp: "
"NPORT x%x oxid x%x ste %d\n",
ctxp->sid, ctxp->oxid, ctxp->state);
@@ -2585,9 +2693,9 @@
static struct lpfc_iocbq *
lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
- struct lpfc_nvmet_rcv_ctx *ctxp)
+ struct lpfc_async_xchg_ctx *ctxp)
{
- struct nvmefc_tgt_fcp_req *rsp = &ctxp->ctx.fcp_req;
+ struct nvmefc_tgt_fcp_req *rsp = &ctxp->hdlrctx.fcp_req;
struct lpfc_nvmet_tgtport *tgtp;
struct sli4_sge *sgl;
struct lpfc_nodelist *ndlp;
@@ -2595,14 +2703,13 @@
struct scatterlist *sgel;
union lpfc_wqe128 *wqe;
struct ulp_bde64 *bde;
- uint32_t *txrdy;
dma_addr_t physaddr;
- int i, cnt;
+ int i, cnt, nsegs;
int do_pbde;
int xc = 1;
if (!lpfc_is_link_up(phba)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6107 NVMET prep FCP wqe: link err:"
"NPORT x%x oxid x%x ste %d\n",
ctxp->sid, ctxp->oxid, ctxp->state);
@@ -2613,7 +2720,7 @@
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) ||
((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
(ndlp->nlp_state != NLP_STE_MAPPED_NODE))) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6108 NVMET prep FCP wqe: no ndlp: "
"NPORT x%x oxid x%x ste %d\n",
ctxp->sid, ctxp->oxid, ctxp->state);
@@ -2621,13 +2728,14 @@
}
if (rsp->sg_cnt > lpfc_tgttemplate.max_sgl_segments) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6109 NVMET prep FCP wqe: seg cnt err: "
"NPORT x%x oxid x%x ste %d cnt %d\n",
ctxp->sid, ctxp->oxid, ctxp->state,
phba->cfg_nvme_seg_cnt);
return NULL;
}
+ nsegs = rsp->sg_cnt;
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
nvmewqe = ctxp->wqeq;
@@ -2635,7 +2743,7 @@
/* Allocate buffer for command wqe */
nvmewqe = ctxp->ctxbuf->iocbq;
if (nvmewqe == NULL) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6110 NVMET prep FCP wqe: No "
"WQE: NPORT x%x oxid x%x ste %d\n",
ctxp->sid, ctxp->oxid, ctxp->state);
@@ -2648,12 +2756,12 @@
}
/* Sanity check */
- if (((ctxp->state == LPFC_NVMET_STE_RCV) &&
+ if (((ctxp->state == LPFC_NVME_STE_RCV) &&
(ctxp->entry_cnt == 1)) ||
- (ctxp->state == LPFC_NVMET_STE_DATA)) {
+ (ctxp->state == LPFC_NVME_STE_DATA)) {
wqe = &nvmewqe->wqe;
} else {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6111 Wrong state NVMET FCP: %d cnt %d\n",
ctxp->state, ctxp->entry_cnt);
return NULL;
@@ -2757,23 +2865,11 @@
&lpfc_treceive_cmd_template.words[3],
sizeof(uint32_t) * 9);
- /* Words 0 - 2 : The first sg segment */
- txrdy = dma_pool_alloc(phba->txrdy_payload_pool,
- GFP_KERNEL, &physaddr);
- if (!txrdy) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
- "6041 Bad txrdy buffer: oxid x%x\n",
- ctxp->oxid);
- return NULL;
- }
- ctxp->txrdy = txrdy;
- ctxp->txrdy_phys = physaddr;
- wqe->fcp_treceive.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
- wqe->fcp_treceive.bde.tus.f.bdeSize = TXRDY_PAYLOAD_LEN;
- wqe->fcp_treceive.bde.addrLow =
- cpu_to_le32(putPaddrLow(physaddr));
- wqe->fcp_treceive.bde.addrHigh =
- cpu_to_le32(putPaddrHigh(physaddr));
+ /* Words 0 - 2 : First SGE is skipped, set invalid BDE type */
+ wqe->fcp_treceive.bde.tus.f.bdeFlags = LPFC_SGE_TYPE_SKIP;
+ wqe->fcp_treceive.bde.tus.f.bdeSize = 0;
+ wqe->fcp_treceive.bde.addrLow = 0;
+ wqe->fcp_treceive.bde.addrHigh = 0;
/* Word 4 */
wqe->fcp_treceive.relative_offset = ctxp->offset;
@@ -2808,17 +2904,13 @@
/* Word 12 */
wqe->fcp_tsend.fcp_data_len = rsp->transfer_length;
- /* Setup 1 TXRDY and 1 SKIP SGE */
- txrdy[0] = 0;
- txrdy[1] = cpu_to_be32(rsp->transfer_length);
- txrdy[2] = 0;
-
- sgl->addr_hi = putPaddrHigh(physaddr);
- sgl->addr_lo = putPaddrLow(physaddr);
+ /* Setup 2 SKIP SGEs */
+ sgl->addr_hi = 0;
+ sgl->addr_lo = 0;
sgl->word2 = 0;
- bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_DATA);
+ bf_set(lpfc_sli4_sge_type, sgl, LPFC_SGE_TYPE_SKIP);
sgl->word2 = cpu_to_le32(sgl->word2);
- sgl->sge_len = cpu_to_le32(TXRDY_PAYLOAD_LEN);
+ sgl->sge_len = 0;
sgl++;
sgl->addr_hi = 0;
sgl->addr_lo = 0;
@@ -2883,7 +2975,7 @@
wqe->fcp_trsp.rsvd_12_15[0] = 0;
/* Use rspbuf, NOT sg list */
- rsp->sg_cnt = 0;
+ nsegs = 0;
sgl->word2 = 0;
atomic_inc(&tgtp->xmt_fcp_rsp);
break;
@@ -2900,7 +2992,7 @@
nvmewqe->drvrTimeout = (phba->fc_ratov * 3) + LPFC_DRVR_TIMEOUT;
nvmewqe->context1 = ndlp;
- for_each_sg(rsp->sg, sgel, rsp->sg_cnt, i) {
+ for_each_sg(rsp->sg, sgel, nsegs, i) {
physaddr = sg_dma_address(sgel);
cnt = sg_dma_len(sgel);
sgl->addr_hi = putPaddrHigh(physaddr);
@@ -2929,7 +3021,7 @@
sgl++;
ctxp->offset += cnt;
}
- ctxp->state = LPFC_NVMET_STE_DATA;
+ ctxp->state = LPFC_NVME_STE_DATA;
ctxp->entry_cnt++;
return nvmewqe;
}
@@ -2948,7 +3040,7 @@
lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
struct lpfc_wcqe_complete *wcqe)
{
- struct lpfc_nvmet_rcv_ctx *ctxp;
+ struct lpfc_async_xchg_ctx *ctxp;
struct lpfc_nvmet_tgtport *tgtp;
uint32_t result;
unsigned long flags;
@@ -2958,23 +3050,23 @@
result = wcqe->parameter;
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
- if (ctxp->flag & LPFC_NVMET_ABORT_OP)
+ if (ctxp->flag & LPFC_NVME_ABORT_OP)
atomic_inc(&tgtp->xmt_fcp_abort_cmpl);
spin_lock_irqsave(&ctxp->ctxlock, flags);
- ctxp->state = LPFC_NVMET_STE_DONE;
+ ctxp->state = LPFC_NVME_STE_DONE;
/* Check if we already received a free context call
* and we have completed processing an abort situation.
*/
- if ((ctxp->flag & LPFC_NVMET_CTX_RLS) &&
- !(ctxp->flag & LPFC_NVMET_XBUSY)) {
+ if ((ctxp->flag & LPFC_NVME_CTX_RLS) &&
+ !(ctxp->flag & LPFC_NVME_XBUSY)) {
spin_lock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
list_del_init(&ctxp->list);
spin_unlock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
released = true;
}
- ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
+ ctxp->flag &= ~LPFC_NVME_ABORT_OP;
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
atomic_inc(&tgtp->xmt_abort_rsp);
@@ -2998,7 +3090,7 @@
lpfc_sli_release_iocbq(phba, cmdwqe);
/* Since iaab/iaar are NOT set, there is no work left.
- * For LPFC_NVMET_XBUSY, lpfc_sli4_nvmet_xri_aborted
+ * For LPFC_NVME_XBUSY, lpfc_sli4_nvmet_xri_aborted
* should have been called already.
*/
}
@@ -3017,7 +3109,7 @@
lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
struct lpfc_wcqe_complete *wcqe)
{
- struct lpfc_nvmet_rcv_ctx *ctxp;
+ struct lpfc_async_xchg_ctx *ctxp;
struct lpfc_nvmet_tgtport *tgtp;
unsigned long flags;
uint32_t result;
@@ -3037,12 +3129,12 @@
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
spin_lock_irqsave(&ctxp->ctxlock, flags);
- if (ctxp->flag & LPFC_NVMET_ABORT_OP)
+ if (ctxp->flag & LPFC_NVME_ABORT_OP)
atomic_inc(&tgtp->xmt_fcp_abort_cmpl);
/* Sanity check */
- if (ctxp->state != LPFC_NVMET_STE_ABORT) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
+ if (ctxp->state != LPFC_NVME_STE_ABORT) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6112 ABTS Wrong state:%d oxid x%x\n",
ctxp->state, ctxp->oxid);
}
@@ -3050,15 +3142,15 @@
/* Check if we already received a free context call
* and we have completed processing an abort situation.
*/
- ctxp->state = LPFC_NVMET_STE_DONE;
- if ((ctxp->flag & LPFC_NVMET_CTX_RLS) &&
- !(ctxp->flag & LPFC_NVMET_XBUSY)) {
+ ctxp->state = LPFC_NVME_STE_DONE;
+ if ((ctxp->flag & LPFC_NVME_CTX_RLS) &&
+ !(ctxp->flag & LPFC_NVME_XBUSY)) {
spin_lock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
list_del_init(&ctxp->list);
spin_unlock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
released = true;
}
- ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
+ ctxp->flag &= ~LPFC_NVME_ABORT_OP;
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
atomic_inc(&tgtp->xmt_abort_rsp);
@@ -3079,7 +3171,7 @@
lpfc_nvmet_ctxbuf_post(phba, ctxp->ctxbuf);
/* Since iaab/iaar are NOT set, there is no work left.
- * For LPFC_NVMET_XBUSY, lpfc_sli4_nvmet_xri_aborted
+ * For LPFC_NVME_XBUSY, lpfc_sli4_nvmet_xri_aborted
* should have been called already.
*/
}
@@ -3098,15 +3190,17 @@
lpfc_nvmet_xmt_ls_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
struct lpfc_wcqe_complete *wcqe)
{
- struct lpfc_nvmet_rcv_ctx *ctxp;
+ struct lpfc_async_xchg_ctx *ctxp;
struct lpfc_nvmet_tgtport *tgtp;
uint32_t result;
ctxp = cmdwqe->context2;
result = wcqe->parameter;
- tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
- atomic_inc(&tgtp->xmt_ls_abort_cmpl);
+ if (phba->nvmet_support) {
+ tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
+ atomic_inc(&tgtp->xmt_ls_abort_cmpl);
+ }
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
"6083 Abort cmpl: ctx x%px WCQE:%08x %08x %08x %08x\n",
@@ -3114,7 +3208,7 @@
result, wcqe->word3);
if (!ctxp) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6415 NVMET LS Abort No ctx: WCQE: "
"%08x %08x %08x %08x\n",
wcqe->word0, wcqe->total_data_placed,
@@ -3124,8 +3218,8 @@
return;
}
- if (ctxp->state != LPFC_NVMET_STE_LS_ABORT) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ if (ctxp->state != LPFC_NVME_STE_LS_ABORT) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6416 NVMET LS abort cmpl state mismatch: "
"oxid x%x: %d %d\n",
ctxp->oxid, ctxp->state, ctxp->entry_cnt);
@@ -3139,10 +3233,10 @@
static int
lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba,
- struct lpfc_nvmet_rcv_ctx *ctxp,
+ struct lpfc_async_xchg_ctx *ctxp,
uint32_t sid, uint16_t xri)
{
- struct lpfc_nvmet_tgtport *tgtp;
+ struct lpfc_nvmet_tgtport *tgtp = NULL;
struct lpfc_iocbq *abts_wqeq;
union lpfc_wqe128 *wqe_abts;
struct lpfc_nodelist *ndlp;
@@ -3151,14 +3245,16 @@
"6067 ABTS: sid %x xri x%x/x%x\n",
sid, xri, ctxp->wqeq->sli4_xritag);
- tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
+ if (phba->nvmet_support && phba->targetport)
+ tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
ndlp = lpfc_findnode_did(phba->pport, sid);
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) ||
((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
(ndlp->nlp_state != NLP_STE_MAPPED_NODE))) {
- atomic_inc(&tgtp->xmt_abort_rsp_error);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
+ if (tgtp)
+ atomic_inc(&tgtp->xmt_abort_rsp_error);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6134 Drop ABTS - wrong NDLP state x%x.\n",
(ndlp) ? ndlp->nlp_state : NLP_STE_MAX_STATE);
@@ -3233,14 +3329,14 @@
static int
lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
- struct lpfc_nvmet_rcv_ctx *ctxp,
+ struct lpfc_async_xchg_ctx *ctxp,
uint32_t sid, uint16_t xri)
{
struct lpfc_nvmet_tgtport *tgtp;
struct lpfc_iocbq *abts_wqeq;
- union lpfc_wqe128 *abts_wqe;
struct lpfc_nodelist *ndlp;
unsigned long flags;
+ u8 opt;
int rc;
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
@@ -3254,13 +3350,13 @@
((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
(ndlp->nlp_state != NLP_STE_MAPPED_NODE))) {
atomic_inc(&tgtp->xmt_abort_rsp_error);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6160 Drop ABORT - wrong NDLP state x%x.\n",
(ndlp) ? ndlp->nlp_state : NLP_STE_MAX_STATE);
/* No failure to an ABTS request. */
spin_lock_irqsave(&ctxp->ctxlock, flags);
- ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
+ ctxp->flag &= ~LPFC_NVME_ABORT_OP;
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
return 0;
}
@@ -3270,17 +3366,17 @@
spin_lock_irqsave(&ctxp->ctxlock, flags);
if (!ctxp->abort_wqeq) {
atomic_inc(&tgtp->xmt_abort_rsp_error);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6161 ABORT failed: No wqeqs: "
"xri: x%x\n", ctxp->oxid);
/* No failure to an ABTS request. */
- ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
+ ctxp->flag &= ~LPFC_NVME_ABORT_OP;
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
return 0;
}
abts_wqeq = ctxp->abort_wqeq;
- abts_wqe = &abts_wqeq->wqe;
- ctxp->state = LPFC_NVMET_STE_ABORT;
+ ctxp->state = LPFC_NVME_STE_ABORT;
+ opt = (ctxp->flag & LPFC_NVME_ABTS_RCV) ? INHIBIT_ABORT : 0;
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
/* Announce entry to new IO submit field. */
@@ -3297,13 +3393,13 @@
if (phba->hba_flag & HBA_IOQ_FLUSH) {
spin_unlock_irqrestore(&phba->hbalock, flags);
atomic_inc(&tgtp->xmt_abort_rsp_error);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6163 Driver in reset cleanup - flushing "
"NVME Req now. hba_flag x%x oxid x%x\n",
phba->hba_flag, ctxp->oxid);
lpfc_sli_release_iocbq(phba, abts_wqeq);
spin_lock_irqsave(&ctxp->ctxlock, flags);
- ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
+ ctxp->flag &= ~LPFC_NVME_ABORT_OP;
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
return 0;
}
@@ -3312,13 +3408,13 @@
if (abts_wqeq->iocb_flag & LPFC_DRIVER_ABORTED) {
spin_unlock_irqrestore(&phba->hbalock, flags);
atomic_inc(&tgtp->xmt_abort_rsp_error);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6164 Outstanding NVME I/O Abort Request "
"still pending on oxid x%x\n",
ctxp->oxid);
lpfc_sli_release_iocbq(phba, abts_wqeq);
spin_lock_irqsave(&ctxp->ctxlock, flags);
- ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
+ ctxp->flag &= ~LPFC_NVME_ABORT_OP;
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
return 0;
}
@@ -3326,40 +3422,12 @@
/* Ready - mark outstanding as aborted by driver. */
abts_wqeq->iocb_flag |= LPFC_DRIVER_ABORTED;
- /* WQEs are reused. Clear stale data and set key fields to
- * zero like ia, iaab, iaar, xri_tag, and ctxt_tag.
- */
- memset(abts_wqe, 0, sizeof(*abts_wqe));
-
- /* word 3 */
- bf_set(abort_cmd_criteria, &abts_wqe->abort_cmd, T_XRI_TAG);
-
- /* word 7 */
- bf_set(wqe_ct, &abts_wqe->abort_cmd.wqe_com, 0);
- bf_set(wqe_cmnd, &abts_wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX);
-
- /* word 8 - tell the FW to abort the IO associated with this
- * outstanding exchange ID.
- */
- abts_wqe->abort_cmd.wqe_com.abort_tag = ctxp->wqeq->sli4_xritag;
-
- /* word 9 - this is the iotag for the abts_wqe completion. */
- bf_set(wqe_reqtag, &abts_wqe->abort_cmd.wqe_com,
- abts_wqeq->iotag);
-
- /* word 10 */
- bf_set(wqe_qosd, &abts_wqe->abort_cmd.wqe_com, 1);
- bf_set(wqe_lenloc, &abts_wqe->abort_cmd.wqe_com, LPFC_WQE_LENLOC_NONE);
-
- /* word 11 */
- bf_set(wqe_cmd_type, &abts_wqe->abort_cmd.wqe_com, OTHER_COMMAND);
- bf_set(wqe_wqec, &abts_wqe->abort_cmd.wqe_com, 1);
- bf_set(wqe_cqid, &abts_wqe->abort_cmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT);
+ lpfc_nvme_prep_abort_wqe(abts_wqeq, ctxp->wqeq->sli4_xritag, opt);
/* ABTS WQE must go to the same WQ as the WQE to be aborted */
abts_wqeq->hba_wqidx = ctxp->wqeq->hba_wqidx;
abts_wqeq->wqe_cmpl = lpfc_nvmet_sol_fcp_abort_cmp;
- abts_wqeq->iocb_cmpl = 0;
+ abts_wqeq->iocb_cmpl = NULL;
abts_wqeq->iocb_flag |= LPFC_IO_NVME;
abts_wqeq->context2 = ctxp;
abts_wqeq->vport = phba->pport;
@@ -3375,10 +3443,10 @@
atomic_inc(&tgtp->xmt_abort_rsp_error);
spin_lock_irqsave(&ctxp->ctxlock, flags);
- ctxp->flag &= ~LPFC_NVMET_ABORT_OP;
+ ctxp->flag &= ~LPFC_NVME_ABORT_OP;
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
lpfc_sli_release_iocbq(phba, abts_wqeq);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6166 Failed ABORT issue_wqe with status x%x "
"for oxid x%x.\n",
rc, ctxp->oxid);
@@ -3387,7 +3455,7 @@
static int
lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *phba,
- struct lpfc_nvmet_rcv_ctx *ctxp,
+ struct lpfc_async_xchg_ctx *ctxp,
uint32_t sid, uint16_t xri)
{
struct lpfc_nvmet_tgtport *tgtp;
@@ -3402,14 +3470,14 @@
ctxp->wqeq->hba_wqidx = 0;
}
- if (ctxp->state == LPFC_NVMET_STE_FREE) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ if (ctxp->state == LPFC_NVME_STE_FREE) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6417 NVMET ABORT ctx freed %d %d oxid x%x\n",
ctxp->state, ctxp->entry_cnt, ctxp->oxid);
rc = WQE_BUSY;
goto aerr;
}
- ctxp->state = LPFC_NVMET_STE_ABORT;
+ ctxp->state = LPFC_NVME_STE_ABORT;
ctxp->entry_cnt++;
rc = lpfc_nvmet_unsol_issue_abort(phba, ctxp, sid, xri);
if (rc == 0)
@@ -3431,17 +3499,17 @@
aerr:
spin_lock_irqsave(&ctxp->ctxlock, flags);
- if (ctxp->flag & LPFC_NVMET_CTX_RLS) {
+ if (ctxp->flag & LPFC_NVME_CTX_RLS) {
spin_lock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
list_del_init(&ctxp->list);
spin_unlock(&phba->sli4_hba.abts_nvmet_buf_list_lock);
released = true;
}
- ctxp->flag &= ~(LPFC_NVMET_ABORT_OP | LPFC_NVMET_CTX_RLS);
+ ctxp->flag &= ~(LPFC_NVME_ABORT_OP | LPFC_NVME_CTX_RLS);
spin_unlock_irqrestore(&ctxp->ctxlock, flags);
atomic_inc(&tgtp->xmt_abort_rsp_error);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6135 Failed to Issue ABTS for oxid x%x. Status x%x "
"(%x)\n",
ctxp->oxid, rc, released);
@@ -3450,34 +3518,44 @@
return 1;
}
-static int
-lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *phba,
- struct lpfc_nvmet_rcv_ctx *ctxp,
+/**
+ * lpfc_nvme_unsol_ls_issue_abort - issue ABTS on an exchange received
+ * via async frame receive where the frame is not handled.
+ * @phba: pointer to adapter structure
+ * @ctxp: pointer to the asynchronously received received sequence
+ * @sid: address of the remote port to send the ABTS to
+ * @xri: oxid value to for the ABTS (other side's exchange id).
+ **/
+int
+lpfc_nvme_unsol_ls_issue_abort(struct lpfc_hba *phba,
+ struct lpfc_async_xchg_ctx *ctxp,
uint32_t sid, uint16_t xri)
{
- struct lpfc_nvmet_tgtport *tgtp;
+ struct lpfc_nvmet_tgtport *tgtp = NULL;
struct lpfc_iocbq *abts_wqeq;
unsigned long flags;
int rc;
- if ((ctxp->state == LPFC_NVMET_STE_LS_RCV && ctxp->entry_cnt == 1) ||
- (ctxp->state == LPFC_NVMET_STE_LS_RSP && ctxp->entry_cnt == 2)) {
- ctxp->state = LPFC_NVMET_STE_LS_ABORT;
+ if ((ctxp->state == LPFC_NVME_STE_LS_RCV && ctxp->entry_cnt == 1) ||
+ (ctxp->state == LPFC_NVME_STE_LS_RSP && ctxp->entry_cnt == 2)) {
+ ctxp->state = LPFC_NVME_STE_LS_ABORT;
ctxp->entry_cnt++;
} else {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6418 NVMET LS abort state mismatch "
"IO x%x: %d %d\n",
ctxp->oxid, ctxp->state, ctxp->entry_cnt);
- ctxp->state = LPFC_NVMET_STE_LS_ABORT;
+ ctxp->state = LPFC_NVME_STE_LS_ABORT;
}
- tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
+ if (phba->nvmet_support && phba->targetport)
+ tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
+
if (!ctxp->wqeq) {
/* Issue ABTS for this WQE based on iotag */
ctxp->wqeq = lpfc_sli_get_iocbq(phba);
if (!ctxp->wqeq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6068 Abort failed: No wqeqs: "
"xri: x%x\n", xri);
/* No failure to an ABTS request. */
@@ -3494,21 +3572,49 @@
spin_lock_irqsave(&phba->hbalock, flags);
abts_wqeq->wqe_cmpl = lpfc_nvmet_xmt_ls_abort_cmp;
- abts_wqeq->iocb_cmpl = 0;
+ abts_wqeq->iocb_cmpl = NULL;
abts_wqeq->iocb_flag |= LPFC_IO_NVME_LS;
rc = lpfc_sli4_issue_wqe(phba, ctxp->hdwq, abts_wqeq);
spin_unlock_irqrestore(&phba->hbalock, flags);
if (rc == WQE_SUCCESS) {
- atomic_inc(&tgtp->xmt_abort_unsol);
+ if (tgtp)
+ atomic_inc(&tgtp->xmt_abort_unsol);
return 0;
}
out:
- atomic_inc(&tgtp->xmt_abort_rsp_error);
+ if (tgtp)
+ atomic_inc(&tgtp->xmt_abort_rsp_error);
abts_wqeq->context2 = NULL;
abts_wqeq->context3 = NULL;
lpfc_sli_release_iocbq(phba, abts_wqeq);
- kfree(ctxp);
- lpfc_printf_log(phba, KERN_ERR, LOG_NVME_ABTS,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6056 Failed to Issue ABTS. Status x%x\n", rc);
- return 0;
+ return 1;
+}
+
+/**
+ * lpfc_nvmet_invalidate_host
+ *
+ * @phba - pointer to the driver instance bound to an adapter port.
+ * @ndlp - pointer to an lpfc_nodelist type
+ *
+ * This routine upcalls the nvmet transport to invalidate an NVME
+ * host to which this target instance had active connections.
+ */
+void
+lpfc_nvmet_invalidate_host(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
+{
+ struct lpfc_nvmet_tgtport *tgtp;
+
+ lpfc_printf_log(phba, KERN_INFO, LOG_NVME | LOG_NVME_ABTS,
+ "6203 Invalidating hosthandle x%px\n",
+ ndlp);
+
+ tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
+ atomic_set(&tgtp->state, LPFC_NVMET_INV_HOST_ACTIVE);
+
+#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
+ /* Need to get the nvmet_fc_target_port pointer here.*/
+ nvmet_fc_invalidate_host(phba->targetport, ndlp);
+#endif
}
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.h b/drivers/scsi/lpfc/lpfc_nvmet.h
deleted file mode 100644
index 8ff67de..0000000
--- a/drivers/scsi/lpfc/lpfc_nvmet.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*******************************************************************
- * This file is part of the Emulex Linux Device Driver for *
- * Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
- * Copyright (C) 2004-2016 Emulex. All rights reserved. *
- * EMULEX and SLI are trademarks of Emulex. *
- * www.broadcom.com *
- * Portions Copyright (C) 2004-2005 Christoph Hellwig *
- * *
- * This program is free software; you can redistribute it and/or *
- * modify it under the terms of version 2 of the GNU General *
- * Public License as published by the Free Software Foundation. *
- * This program is distributed in the hope that it will be useful. *
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
- * TO BE LEGALLY INVALID. See the GNU General Public License for *
- * more details, a copy of which can be found in the file COPYING *
- * included with this package. *
- ********************************************************************/
-
-#define LPFC_NVMET_DEFAULT_SEGS (64 + 1) /* 256K IOs */
-#define LPFC_NVMET_RQE_MIN_POST 128
-#define LPFC_NVMET_RQE_DEF_POST 512
-#define LPFC_NVMET_RQE_DEF_COUNT 2048
-#define LPFC_NVMET_SUCCESS_LEN 12
-
-#define LPFC_NVMET_MRQ_AUTO 0
-#define LPFC_NVMET_MRQ_MAX 16
-
-#define LPFC_NVMET_WAIT_TMO (5 * MSEC_PER_SEC)
-
-/* Used for NVME Target */
-struct lpfc_nvmet_tgtport {
- struct lpfc_hba *phba;
- struct completion *tport_unreg_cmp;
-
- /* Stats counters - lpfc_nvmet_unsol_ls_buffer */
- atomic_t rcv_ls_req_in;
- atomic_t rcv_ls_req_out;
- atomic_t rcv_ls_req_drop;
- atomic_t xmt_ls_abort;
- atomic_t xmt_ls_abort_cmpl;
-
- /* Stats counters - lpfc_nvmet_xmt_ls_rsp */
- atomic_t xmt_ls_rsp;
- atomic_t xmt_ls_drop;
-
- /* Stats counters - lpfc_nvmet_xmt_ls_rsp_cmp */
- atomic_t xmt_ls_rsp_error;
- atomic_t xmt_ls_rsp_aborted;
- atomic_t xmt_ls_rsp_xb_set;
- atomic_t xmt_ls_rsp_cmpl;
-
- /* Stats counters - lpfc_nvmet_unsol_fcp_buffer */
- atomic_t rcv_fcp_cmd_in;
- atomic_t rcv_fcp_cmd_out;
- atomic_t rcv_fcp_cmd_drop;
- atomic_t rcv_fcp_cmd_defer;
- atomic_t xmt_fcp_release;
-
- /* Stats counters - lpfc_nvmet_xmt_fcp_op */
- atomic_t xmt_fcp_drop;
- atomic_t xmt_fcp_read_rsp;
- atomic_t xmt_fcp_read;
- atomic_t xmt_fcp_write;
- atomic_t xmt_fcp_rsp;
-
- /* Stats counters - lpfc_nvmet_xmt_fcp_op_cmp */
- atomic_t xmt_fcp_rsp_xb_set;
- atomic_t xmt_fcp_rsp_cmpl;
- atomic_t xmt_fcp_rsp_error;
- atomic_t xmt_fcp_rsp_aborted;
- atomic_t xmt_fcp_rsp_drop;
-
- /* Stats counters - lpfc_nvmet_xmt_fcp_abort */
- atomic_t xmt_fcp_xri_abort_cqe;
- atomic_t xmt_fcp_abort;
- atomic_t xmt_fcp_abort_cmpl;
- atomic_t xmt_abort_sol;
- atomic_t xmt_abort_unsol;
- atomic_t xmt_abort_rsp;
- atomic_t xmt_abort_rsp_error;
-
- /* Stats counters - defer IO */
- atomic_t defer_ctx;
- atomic_t defer_fod;
- atomic_t defer_wqfull;
-};
-
-struct lpfc_nvmet_ctx_info {
- struct list_head nvmet_ctx_list;
- spinlock_t nvmet_ctx_list_lock; /* lock per CPU */
- struct lpfc_nvmet_ctx_info *nvmet_ctx_next_cpu;
- struct lpfc_nvmet_ctx_info *nvmet_ctx_start_cpu;
- uint16_t nvmet_ctx_list_cnt;
- char pad[16]; /* pad to a cache-line */
-};
-
-/* This retrieves the context info associated with the specified cpu / mrq */
-#define lpfc_get_ctx_list(phba, cpu, mrq) \
- (phba->sli4_hba.nvmet_ctx_info + ((cpu * phba->cfg_nvmet_mrq) + mrq))
-
-struct lpfc_nvmet_rcv_ctx {
- union {
- struct nvmefc_tgt_ls_req ls_req;
- struct nvmefc_tgt_fcp_req fcp_req;
- } ctx;
- struct list_head list;
- struct lpfc_hba *phba;
- struct lpfc_iocbq *wqeq;
- struct lpfc_iocbq *abort_wqeq;
- dma_addr_t txrdy_phys;
- spinlock_t ctxlock; /* protect flag access */
- uint32_t *txrdy;
- uint32_t sid;
- uint32_t offset;
- uint16_t oxid;
- uint16_t size;
- uint16_t entry_cnt;
- uint16_t cpu;
- uint16_t idx;
- uint16_t state;
- /* States */
-#define LPFC_NVMET_STE_LS_RCV 1
-#define LPFC_NVMET_STE_LS_ABORT 2
-#define LPFC_NVMET_STE_LS_RSP 3
-#define LPFC_NVMET_STE_RCV 4
-#define LPFC_NVMET_STE_DATA 5
-#define LPFC_NVMET_STE_ABORT 6
-#define LPFC_NVMET_STE_DONE 7
-#define LPFC_NVMET_STE_FREE 0xff
- uint16_t flag;
-#define LPFC_NVMET_IO_INP 0x1 /* IO is in progress on exchange */
-#define LPFC_NVMET_ABORT_OP 0x2 /* Abort WQE issued on exchange */
-#define LPFC_NVMET_XBUSY 0x4 /* XB bit set on IO cmpl */
-#define LPFC_NVMET_CTX_RLS 0x8 /* ctx free requested */
-#define LPFC_NVMET_ABTS_RCV 0x10 /* ABTS received on exchange */
-#define LPFC_NVMET_CTX_REUSE_WQ 0x20 /* ctx reused via WQ */
-#define LPFC_NVMET_DEFER_WQFULL 0x40 /* Waiting on a free WQE */
-#define LPFC_NVMET_TNOTIFY 0x80 /* notify transport of abts */
- struct rqb_dmabuf *rqb_buffer;
- struct lpfc_nvmet_ctxbuf *ctxbuf;
- struct lpfc_sli4_hdw_queue *hdwq;
-
-#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
- uint64_t ts_isr_cmd;
- uint64_t ts_cmd_nvme;
- uint64_t ts_nvme_data;
- uint64_t ts_data_wqput;
- uint64_t ts_isr_data;
- uint64_t ts_data_nvme;
- uint64_t ts_nvme_status;
- uint64_t ts_status_wqput;
- uint64_t ts_isr_status;
- uint64_t ts_status_nvme;
-#endif
-};
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index cbab15d..983eeb0 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -134,21 +134,21 @@
/**
* lpfc_update_stats - Update statistical data for the command completion
- * @phba: Pointer to HBA object.
+ * @vport: The virtual port on which this call is executing.
* @lpfc_cmd: lpfc scsi command object pointer.
*
* This function is called when there is a command completion and this
* function updates the statistical data for the command completion.
**/
static void
-lpfc_update_stats(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
+lpfc_update_stats(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd)
{
+ struct lpfc_hba *phba = vport->phba;
struct lpfc_rport_data *rdata;
struct lpfc_nodelist *pnode;
struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
unsigned long flags;
- struct Scsi_Host *shost = cmd->device->host;
- struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
unsigned long latency;
int i;
@@ -481,7 +481,7 @@
spin_lock(&qp->abts_io_buf_list_lock);
list_for_each_entry_safe(psb, next_psb,
&qp->lpfc_abts_io_buf_list, list) {
- if (psb->cur_iocbq.iocb_flag == LPFC_IO_NVME)
+ if (psb->cur_iocbq.iocb_flag & LPFC_IO_NVME)
continue;
if (psb->rdata && psb->rdata->pnode &&
@@ -528,7 +528,7 @@
list_del_init(&psb->list);
psb->flags &= ~LPFC_SBUF_XBUSY;
psb->status = IOSTAT_SUCCESS;
- if (psb->cur_iocbq.iocb_flag == LPFC_IO_NVME) {
+ if (psb->cur_iocbq.iocb_flag & LPFC_IO_NVME) {
qp->abts_nvme_io_bufs--;
spin_unlock(&qp->abts_io_buf_list_lock);
spin_unlock_irqrestore(&phba->hbalock, iflag);
@@ -721,7 +721,7 @@
iocb->ulpLe = 1;
iocb->ulpClass = CLASS3;
- if (lpfc_ndlp_check_qdepth(phba, ndlp) && lpfc_cmd) {
+ if (lpfc_ndlp_check_qdepth(phba, ndlp)) {
atomic_inc(&ndlp->cmd_pending);
lpfc_cmd->flags |= LPFC_SBUF_BUMP_QDEPTH;
}
@@ -867,11 +867,11 @@
lpfc_cmd->seg_cnt = nseg;
if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
- "9064 BLKGRD: %s: Too many sg segments from "
- "dma_map_sg. Config %d, seg_cnt %d\n",
- __func__, phba->cfg_sg_seg_cnt,
- lpfc_cmd->seg_cnt);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "9064 BLKGRD: %s: Too many sg segments"
+ " from dma_map_sg. Config %d, seg_cnt"
+ " %d\n", __func__, phba->cfg_sg_seg_cnt,
+ lpfc_cmd->seg_cnt);
WARN_ON_ONCE(lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt);
lpfc_cmd->seg_cnt = 0;
scsi_dma_unmap(scsi_cmnd);
@@ -1061,7 +1061,8 @@
* inserted in middle of the IO.
*/
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"9076 BLKGRD: Injecting reftag error: "
"write lba x%lx + x%x oldrefTag x%x\n",
(unsigned long)lba, blockoff,
@@ -1092,7 +1093,7 @@
break;
}
- /* fall through */
+ fallthrough;
case SCSI_PROT_WRITE_INSERT:
/*
* For WRITE_INSERT, force the error
@@ -1111,7 +1112,7 @@
}
rc = BG_ERR_TGT | BG_ERR_CHECK;
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9078 BLKGRD: Injecting reftag error: "
"write lba x%lx\n", (unsigned long)lba);
break;
@@ -1132,7 +1133,7 @@
}
rc = BG_ERR_INIT;
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9077 BLKGRD: Injecting reftag error: "
"write lba x%lx\n", (unsigned long)lba);
break;
@@ -1159,7 +1160,7 @@
}
rc = BG_ERR_INIT;
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9079 BLKGRD: Injecting reftag error: "
"read lba x%lx\n", (unsigned long)lba);
break;
@@ -1181,7 +1182,8 @@
* inserted in middle of the IO.
*/
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
"9080 BLKGRD: Injecting apptag error: "
"write lba x%lx + x%x oldappTag x%x\n",
(unsigned long)lba, blockoff,
@@ -1211,7 +1213,7 @@
rc = BG_ERR_TGT | BG_ERR_CHECK;
break;
}
- /* fall through */
+ fallthrough;
case SCSI_PROT_WRITE_INSERT:
/*
* For WRITE_INSERT, force the
@@ -1230,7 +1232,7 @@
}
rc = BG_ERR_TGT | BG_ERR_CHECK;
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0813 BLKGRD: Injecting apptag error: "
"write lba x%lx\n", (unsigned long)lba);
break;
@@ -1251,7 +1253,7 @@
}
rc = BG_ERR_INIT;
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0812 BLKGRD: Injecting apptag error: "
"write lba x%lx\n", (unsigned long)lba);
break;
@@ -1278,7 +1280,7 @@
}
rc = BG_ERR_INIT;
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0814 BLKGRD: Injecting apptag error: "
"read lba x%lx\n", (unsigned long)lba);
break;
@@ -1293,7 +1295,7 @@
switch (op) {
case SCSI_PROT_WRITE_PASS:
rc = BG_ERR_CHECK;
- /* fall through */
+ fallthrough;
case SCSI_PROT_WRITE_INSERT:
/*
@@ -1313,7 +1315,7 @@
rc |= BG_ERR_TGT | BG_ERR_SWAP;
/* Signals the caller to swap CRC->CSUM */
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0817 BLKGRD: Injecting guard error: "
"write lba x%lx\n", (unsigned long)lba);
break;
@@ -1335,7 +1337,7 @@
rc = BG_ERR_INIT | BG_ERR_SWAP;
/* Signals the caller to swap CRC->CSUM */
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0816 BLKGRD: Injecting guard error: "
"write lba x%lx\n", (unsigned long)lba);
break;
@@ -1363,7 +1365,7 @@
rc = BG_ERR_INIT | BG_ERR_SWAP;
/* Signals the caller to swap CRC->CSUM */
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0818 BLKGRD: Injecting guard error: "
"read lba x%lx\n", (unsigned long)lba);
}
@@ -1413,7 +1415,7 @@
case SCSI_PROT_NORMAL:
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9063 BLKGRD: Bad op/guard:%d/IP combination\n",
scsi_get_prot_op(sc));
ret = 1;
@@ -1442,7 +1444,7 @@
case SCSI_PROT_NORMAL:
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9075 BLKGRD: Bad op/guard:%d/CRC combination\n",
scsi_get_prot_op(sc));
ret = 1;
@@ -1728,7 +1730,7 @@
sgde = scsi_sglist(sc);
if (!sgpe || !sgde) {
- lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9020 Invalid s/g entry: data=x%px prot=x%px\n",
sgpe, sgde);
return 0;
@@ -1840,7 +1842,7 @@
return num_bde + 1;
if (!sgde) {
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9065 BLKGRD:%s Invalid data segment\n",
__func__);
return 0;
@@ -1903,8 +1905,8 @@
reftag += protgrp_blks;
} else {
/* if we're here, we have a bug */
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
- "9054 BLKGRD: bug in %s\n", __func__);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "9054 BLKGRD: bug in %s\n", __func__);
}
} while (!alldone);
@@ -2154,7 +2156,7 @@
sgde = scsi_sglist(sc);
if (!sgpe || !sgde) {
- lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9082 Invalid s/g entry: data=x%px prot=x%px\n",
sgpe, sgde);
return 0;
@@ -2307,7 +2309,7 @@
return num_sge + 1;
if (!sgde) {
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9086 BLKGRD:%s Invalid data segment\n",
__func__);
return 0;
@@ -2412,8 +2414,8 @@
reftag += protgrp_blks;
} else {
/* if we're here, we have a bug */
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
- "9085 BLKGRD: bug in %s\n", __func__);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "9085 BLKGRD: bug in %s\n", __func__);
}
} while (!alldone);
@@ -2453,7 +2455,7 @@
break;
default:
if (phba)
- lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9021 Unsupported protection op:%d\n",
op);
break;
@@ -2617,7 +2619,7 @@
scsi_dma_unmap(scsi_cmnd);
lpfc_cmd->seg_cnt = 0;
- lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9022 Unexpected protection group %i\n",
prot_group_type);
return 2;
@@ -2661,7 +2663,7 @@
scsi_prot_sg_count(scsi_cmnd),
scsi_cmnd->sc_data_direction);
- lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9023 Cannot setup S/G List for HBA"
"IO segs %d/%d BPL %d SCSI %d: %d %d\n",
lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt,
@@ -3085,11 +3087,12 @@
lpfc_cmd->seg_cnt = nseg;
if (!phba->cfg_xpsgl &&
lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
- lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9074 BLKGRD:"
- " %s: Too many sg segments from "
- "dma_map_sg. Config %d, seg_cnt %d\n",
- __func__, phba->cfg_sg_seg_cnt,
- lpfc_cmd->seg_cnt);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "9074 BLKGRD:"
+ " %s: Too many sg segments from "
+ "dma_map_sg. Config %d, seg_cnt %d\n",
+ __func__, phba->cfg_sg_seg_cnt,
+ lpfc_cmd->seg_cnt);
WARN_ON_ONCE(lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt);
lpfc_cmd->seg_cnt = 0;
scsi_dma_unmap(scsi_cmnd);
@@ -3366,7 +3369,7 @@
scsi_dma_unmap(scsi_cmnd);
lpfc_cmd->seg_cnt = 0;
- lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9083 Unexpected protection group %i\n",
prot_group_type);
return 2;
@@ -3422,7 +3425,7 @@
scsi_prot_sg_count(scsi_cmnd),
scsi_cmnd->sc_data_direction);
- lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9084 Cannot setup S/G List for HBA"
"IO segs %d/%d SGL %d SCSI %d: %d %d\n",
lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt,
@@ -3632,17 +3635,17 @@
if (resp_info & RSP_LEN_VALID) {
rsplen = be32_to_cpu(fcprsp->rspRspLen);
if (rsplen != 0 && rsplen != 4 && rsplen != 8) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
- "2719 Invalid response length: "
- "tgt x%x lun x%llx cmnd x%x rsplen x%x\n",
- cmnd->device->id,
- cmnd->device->lun, cmnd->cmnd[0],
- rsplen);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "2719 Invalid response length: "
+ "tgt x%x lun x%llx cmnd x%x rsplen "
+ "x%x\n", cmnd->device->id,
+ cmnd->device->lun, cmnd->cmnd[0],
+ rsplen);
host_status = DID_ERROR;
goto out;
}
if (fcprsp->rspInfo3 != RSP_NO_FAILURE) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"2757 Protocol failure detected during "
"processing of FCP I/O op: "
"tgt x%x lun x%llx cmnd x%x rspInfo3 x%x\n",
@@ -3805,17 +3808,14 @@
struct Scsi_Host *shost;
int idx;
uint32_t logit = LOG_FCP;
-#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
- int cpu;
-#endif
/* Guard against abort handler being called at same time */
spin_lock(&lpfc_cmd->buf_lock);
/* Sanity check on return of outstanding command */
cmd = lpfc_cmd->pCmd;
- if (!cmd) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+ if (!cmd || !phba) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"2621 IO completion: Not an active IO\n");
spin_unlock(&lpfc_cmd->buf_lock);
return;
@@ -3826,11 +3826,8 @@
phba->sli4_hba.hdwq[idx].scsi_cstat.io_cmpls++;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
- if (phba->cpucheck_on & LPFC_CHECK_SCSI_IO) {
- cpu = raw_smp_processor_id();
- if (cpu < LPFC_CHECK_CPU_CNT && phba->sli4_hba.hdwq)
- phba->sli4_hba.hdwq[idx].cpucheck_cmpl_io[cpu]++;
- }
+ if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO))
+ this_cpu_inc(phba->sli4_hba.c_stat->cmpl_io);
#endif
shost = cmd->device->host;
@@ -3874,7 +3871,7 @@
}
#endif
- if (lpfc_cmd->status) {
+ if (unlikely(lpfc_cmd->status)) {
if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT &&
(lpfc_cmd->result & IOERR_DRVR_MASK))
lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
@@ -3983,7 +3980,7 @@
lpfc_cmd->cur_iocbq.sli4_lxritag,
0, 0);
}
- /* fall through */
+ fallthrough;
default:
cmd->result = DID_ERROR << 16;
break;
@@ -4007,7 +4004,7 @@
scsi_get_resid(cmd));
}
- lpfc_update_stats(phba, lpfc_cmd);
+ lpfc_update_stats(vport, lpfc_cmd);
if (vport->cfg_max_scsicmpl_time &&
time_after(jiffies, lpfc_cmd->start_time +
msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
@@ -4031,6 +4028,14 @@
lpfc_cmd->pCmd = NULL;
spin_unlock(&lpfc_cmd->buf_lock);
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ if (lpfc_cmd->ts_cmd_start) {
+ lpfc_cmd->ts_isr_cmpl = pIocbIn->isr_timestamp;
+ lpfc_cmd->ts_data_io = ktime_get_ns();
+ phba->ktime_last_cmd = lpfc_cmd->ts_data_io;
+ lpfc_io_ktime(phba, lpfc_cmd);
+ }
+#endif
/* The sdev is not guaranteed to be valid post scsi_done upcall. */
cmd->scsi_done(cmd);
@@ -4275,7 +4280,7 @@
phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s4;
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1418 Invalid HBA PCI-device group: 0x%x\n",
dev_grp);
return -ENODEV;
@@ -4322,7 +4327,7 @@
* 0, successful
*/
int
-lpfc_check_pci_resettable(const struct lpfc_hba *phba)
+lpfc_check_pci_resettable(struct lpfc_hba *phba)
{
const struct pci_dev *pdev = phba->pcidev;
struct pci_dev *ptr = NULL;
@@ -4504,7 +4509,10 @@
struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
int err, idx;
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
- int cpu;
+ uint64_t start = 0L;
+
+ if (phba->ktime_on)
+ start = ktime_get_ns();
#endif
rdata = lpfc_rport_data_from_scsi_device(cmnd->device);
@@ -4523,7 +4531,7 @@
if ((scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) &&
(!(phba->sli3_options & LPFC_SLI3_BG_ENABLED))) {
- lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"9058 BLKGRD: ERROR: rcvd protected cmd:%02x"
" op:%02x str=%s without registering for"
" BlockGuard - Rejecting command\n",
@@ -4615,27 +4623,31 @@
err = lpfc_scsi_prep_dma_buf(phba, lpfc_cmd);
}
- if (err == 2) {
- cmnd->result = DID_ERROR << 16;
- goto out_fail_command_release_buf;
- } else if (err) {
+ if (unlikely(err)) {
+ if (err == 2) {
+ cmnd->result = DID_ERROR << 16;
+ goto out_fail_command_release_buf;
+ }
goto out_host_busy_free_buf;
}
lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp);
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
- if (phba->cpucheck_on & LPFC_CHECK_SCSI_IO) {
- cpu = raw_smp_processor_id();
- if (cpu < LPFC_CHECK_CPU_CNT) {
- struct lpfc_sli4_hdw_queue *hdwq =
- &phba->sli4_hba.hdwq[lpfc_cmd->hdwq_no];
- hdwq->cpucheck_xmt_io[cpu]++;
- }
- }
+ if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO))
+ this_cpu_inc(phba->sli4_hba.c_stat->xmt_io);
#endif
err = lpfc_sli_issue_iocb(phba, LPFC_FCP_RING,
&lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB);
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ if (start) {
+ lpfc_cmd->ts_cmd_start = start;
+ lpfc_cmd->ts_last_cmd = phba->ktime_last_cmd;
+ lpfc_cmd->ts_cmd_wqput = ktime_get_ns();
+ } else {
+ lpfc_cmd->ts_cmd_start = 0;
+ }
+#endif
if (err) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
"3376 FCP could not issue IOCB err %x"
@@ -4878,7 +4890,7 @@
if (lpfc_cmd->pCmd == cmnd) {
ret = FAILED;
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0748 abort handler timed out waiting "
"for aborting I/O (xri:x%x) to complete: "
"ret %#x, ID %d, LUN %llu\n",
@@ -5071,7 +5083,7 @@
(iocbqrsp->iocb.ulpStatus != IOSTAT_SUCCESS)) {
if (status != IOCB_SUCCESS ||
iocbqrsp->iocb.ulpStatus != IOSTAT_FCP_RSP_ERROR)
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0727 TMF %s to TGT %d LUN %llu "
"failed (%d, %d) iocb_flag x%x\n",
lpfc_taskmgmt_name(task_mgmt_cmd),
@@ -5186,7 +5198,7 @@
cnt = lpfc_sli_sum_iocb(vport, tgt_id, lun_id, context);
}
if (cnt) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0724 I/O flush failure for context %s : cnt x%x\n",
((context == LPFC_CTX_LUN) ? "LUN" :
((context == LPFC_CTX_TGT) ? "TGT" :
@@ -5222,7 +5234,7 @@
rdata = lpfc_rport_data_from_scsi_device(cmnd->device);
if (!rdata || !rdata->pnode) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0798 Device Reset rdata failure: rdata x%px\n",
rdata);
return FAILED;
@@ -5234,7 +5246,7 @@
status = lpfc_chk_tgt_mapped(vport, cmnd);
if (status == FAILED) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0721 Device Reset rport failure: rdata x%px\n", rdata);
return FAILED;
}
@@ -5251,7 +5263,7 @@
status = lpfc_send_taskmgmt(vport, cmnd, tgt_id, lun_id,
FCP_LUN_RESET);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0713 SCSI layer issued Device Reset (%d, %llu) "
"return x%x\n", tgt_id, lun_id, status);
@@ -5293,7 +5305,7 @@
rdata = lpfc_rport_data_from_scsi_device(cmnd->device);
if (!rdata || !rdata->pnode) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0799 Target Reset rdata failure: rdata x%px\n",
rdata);
return FAILED;
@@ -5305,7 +5317,7 @@
status = lpfc_chk_tgt_mapped(vport, cmnd);
if (status == FAILED) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0722 Target Reset rport failure: rdata x%px\n", rdata);
if (pnode) {
spin_lock_irq(shost->host_lock);
@@ -5330,7 +5342,7 @@
status = lpfc_send_taskmgmt(vport, cmnd, tgt_id, lun_id,
FCP_TARGET_RESET);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0723 SCSI layer issued Target Reset (%d, %llu) "
"return x%x\n", tgt_id, lun_id, status);
@@ -5411,7 +5423,7 @@
i, 0, FCP_TARGET_RESET);
if (status != SUCCESS) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0700 Bus Reset on target %d failed\n",
i);
ret = FAILED;
@@ -5428,7 +5440,7 @@
if (status != SUCCESS)
ret = FAILED;
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0714 SCSI layer issued Bus Reset Data: x%x\n", ret);
return ret;
}
@@ -5457,7 +5469,7 @@
struct lpfc_hba *phba = vport->phba;
int rc, ret = SUCCESS;
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"3172 SCSI layer issued Host Reset Data:\n");
lpfc_offline_prep(phba, LPFC_MBX_WAIT);
@@ -5474,7 +5486,7 @@
return ret;
error:
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"3323 Failed host reset\n");
lpfc_unblock_mgmt_io(phba);
return FAILED;
@@ -5585,7 +5597,7 @@
}
num_allocated = lpfc_new_scsi_buf_s3(vport, num_to_alloc);
if (num_to_alloc != num_allocated) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0708 Allocation request of %d "
"command buffers did not succeed. "
"Allocated %d buffers.\n",
@@ -6022,31 +6034,6 @@
.track_queue_depth = 0,
};
-struct scsi_host_template lpfc_template_no_hr = {
- .module = THIS_MODULE,
- .name = LPFC_DRIVER_NAME,
- .proc_name = LPFC_DRIVER_NAME,
- .info = lpfc_info,
- .queuecommand = lpfc_queuecommand,
- .eh_timed_out = fc_eh_timed_out,
- .eh_abort_handler = lpfc_abort_handler,
- .eh_device_reset_handler = lpfc_device_reset_handler,
- .eh_target_reset_handler = lpfc_target_reset_handler,
- .eh_bus_reset_handler = lpfc_bus_reset_handler,
- .slave_alloc = lpfc_slave_alloc,
- .slave_configure = lpfc_slave_configure,
- .slave_destroy = lpfc_slave_destroy,
- .scan_finished = lpfc_scan_finished,
- .this_id = -1,
- .sg_tablesize = LPFC_DEFAULT_SG_SEG_CNT,
- .cmd_per_lun = LPFC_CMD_PER_LUN,
- .shost_attrs = lpfc_hba_attrs,
- .max_sectors = 0xFFFFFFFF,
- .vendor_id = LPFC_NL_VENDOR_ID,
- .change_queue_depth = scsi_change_queue_depth,
- .track_queue_depth = 1,
-};
-
struct scsi_host_template lpfc_template = {
.module = THIS_MODULE,
.name = LPFC_DRIVER_NAME,
@@ -6072,26 +6059,3 @@
.change_queue_depth = scsi_change_queue_depth,
.track_queue_depth = 1,
};
-
-struct scsi_host_template lpfc_vport_template = {
- .module = THIS_MODULE,
- .name = LPFC_DRIVER_NAME,
- .proc_name = LPFC_DRIVER_NAME,
- .info = lpfc_info,
- .queuecommand = lpfc_queuecommand,
- .eh_timed_out = fc_eh_timed_out,
- .eh_abort_handler = lpfc_abort_handler,
- .eh_device_reset_handler = lpfc_device_reset_handler,
- .eh_target_reset_handler = lpfc_target_reset_handler,
- .slave_alloc = lpfc_slave_alloc,
- .slave_configure = lpfc_slave_configure,
- .slave_destroy = lpfc_slave_destroy,
- .scan_finished = lpfc_scan_finished,
- .this_id = -1,
- .sg_tablesize = LPFC_DEFAULT_SG_SEG_CNT,
- .cmd_per_lun = LPFC_CMD_PER_LUN,
- .shost_attrs = lpfc_vport_attrs,
- .max_sectors = 0xFFFF,
- .change_queue_depth = scsi_change_queue_depth,
- .track_queue_depth = 1,
-};
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 4a7ceaa..a50f870 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -35,12 +35,11 @@
#include <scsi/scsi_transport_fc.h>
#include <scsi/fc/fc_fs.h>
#include <linux/aer.h>
+#include <linux/crash_dump.h>
#ifdef CONFIG_X86
#include <asm/set_memory.h>
#endif
-#include <linux/nvme-fc-driver.h>
-
#include "lpfc_hw4.h"
#include "lpfc_hw.h"
#include "lpfc_sli.h"
@@ -50,7 +49,6 @@
#include "lpfc.h"
#include "lpfc_scsi.h"
#include "lpfc_nvme.h"
-#include "lpfc_nvmet.h"
#include "lpfc_crtn.h"
#include "lpfc_logmsg.h"
#include "lpfc_compat.h"
@@ -87,6 +85,10 @@
struct lpfc_eqe *eqe);
static bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba);
static bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba);
+static struct lpfc_cqe *lpfc_sli4_cq_get(struct lpfc_queue *q);
+static void __lpfc_sli4_consume_cqe(struct lpfc_hba *phba,
+ struct lpfc_queue *cq,
+ struct lpfc_cqe *cqe);
static IOCB_t *
lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq)
@@ -226,31 +228,22 @@
* This routine will update the HBA index of a queue to reflect consumption of
* Work Queue Entries by the HBA. When the HBA indicates that it has consumed
* an entry the host calls this function to update the queue's internal
- * pointers. This routine returns the number of entries that were consumed by
- * the HBA.
+ * pointers.
**/
-static uint32_t
+static void
lpfc_sli4_wq_release(struct lpfc_queue *q, uint32_t index)
{
- uint32_t released = 0;
-
/* sanity check on queue memory */
if (unlikely(!q))
- return 0;
+ return;
- if (q->hba_index == index)
- return 0;
- do {
- q->hba_index = ((q->hba_index + 1) % q->entry_count);
- released++;
- } while (q->hba_index != index);
- return released;
+ q->hba_index = index;
}
/**
* lpfc_sli4_mq_put - Put a Mailbox Queue Entry on an Mailbox Queue
* @q: The Mailbox Queue to operate on.
- * @wqe: The Mailbox Queue Entry to put on the Work queue.
+ * @mqe: The Mailbox Queue Entry to put on the Work queue.
*
* This routine will copy the contents of @mqe to the next available entry on
* the @q. This function will then ring the Work Queue Doorbell to signal the
@@ -467,21 +460,47 @@
}
static void
-lpfc_sli4_eq_flush(struct lpfc_hba *phba, struct lpfc_queue *eq)
+lpfc_sli4_eqcq_flush(struct lpfc_hba *phba, struct lpfc_queue *eq)
{
- struct lpfc_eqe *eqe;
- uint32_t count = 0;
+ struct lpfc_eqe *eqe = NULL;
+ u32 eq_count = 0, cq_count = 0;
+ struct lpfc_cqe *cqe = NULL;
+ struct lpfc_queue *cq = NULL, *childq = NULL;
+ int cqid = 0;
/* walk all the EQ entries and drop on the floor */
eqe = lpfc_sli4_eq_get(eq);
while (eqe) {
+ /* Get the reference to the corresponding CQ */
+ cqid = bf_get_le32(lpfc_eqe_resource_id, eqe);
+ cq = NULL;
+
+ list_for_each_entry(childq, &eq->child_list, list) {
+ if (childq->queue_id == cqid) {
+ cq = childq;
+ break;
+ }
+ }
+ /* If CQ is valid, iterate through it and drop all the CQEs */
+ if (cq) {
+ cqe = lpfc_sli4_cq_get(cq);
+ while (cqe) {
+ __lpfc_sli4_consume_cqe(phba, cq, cqe);
+ cq_count++;
+ cqe = lpfc_sli4_cq_get(cq);
+ }
+ /* Clear and re-arm the CQ */
+ phba->sli4_hba.sli4_write_cq_db(phba, cq, cq_count,
+ LPFC_QUEUE_REARM);
+ cq_count = 0;
+ }
__lpfc_sli4_consume_eqe(phba, eq, eqe);
- count++;
+ eq_count++;
eqe = lpfc_sli4_eq_get(eq);
}
/* Clear and re-arm the EQ */
- phba->sli4_hba.sli4_write_eq_db(phba, eq, count, LPFC_QUEUE_REARM);
+ phba->sli4_hba.sli4_write_eq_db(phba, eq, eq_count, LPFC_QUEUE_REARM);
}
static int
@@ -517,7 +536,7 @@
if (count > eq->EQ_max_eqe)
eq->EQ_max_eqe = count;
- eq->queue_claimed = 0;
+ xchg(&eq->queue_claimed, 0);
rearm_and_exit:
/* Always clear the EQ. */
@@ -638,10 +657,8 @@
writel(doorbell.word0, q->phba->sli4_hba.CQDBregaddr);
}
-/**
+/*
* lpfc_sli4_rq_put - Put a Receive Buffer Queue Entry on a Receive Queue
- * @q: The Header Receive Queue to operate on.
- * @wqe: The Receive Queue Entry to put on the Receive queue.
*
* This routine will copy the contents of @wqe to the next available entry on
* the @q. This function will then ring the Receive Queue Doorbell to signal the
@@ -704,9 +721,8 @@
return hq_put_index;
}
-/**
+/*
* lpfc_sli4_rq_release - Updates internal hba index for RQ
- * @q: The Header Receive Queue to operate on.
*
* This routine will update the HBA index of a queue to reflect consumption of
* one Receive Queue Entry by the HBA. When the HBA indicates that it has
@@ -990,7 +1006,7 @@
* lpfc_test_rrq_active - Test RRQ bit in xri_bitmap.
* @phba: Pointer to HBA context object.
* @ndlp: Targets nodelist pointer for this exchange.
- * @xritag the xri in the bitmap to test.
+ * @xritag: the xri in the bitmap to test.
*
* This function returns:
* 0 = rrq not active for this xri
@@ -1061,7 +1077,7 @@
goto out;
spin_unlock_irqrestore(&phba->hbalock, iflags);
- rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL);
+ rrq = mempool_alloc(phba->rrq_pool, GFP_ATOMIC);
if (!rrq) {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"3155 Unable to allocate RRQ xri:0x%x rxid:0x%x"
@@ -1100,7 +1116,7 @@
/**
* __lpfc_sli_get_els_sglq - Allocates an iocb object from sgl pool
* @phba: Pointer to HBA context object.
- * @piocb: Pointer to the iocbq.
+ * @piocbq: Pointer to the iocbq.
*
* The driver calls this function with either the nvme ls ring lock
* or the fc els ring lock held depending on the iocb usage. This function
@@ -1176,7 +1192,7 @@
/**
* __lpfc_sli_get_nvmet_sglq - Allocates an iocb object from sgl pool
* @phba: Pointer to HBA context object.
- * @piocb: Pointer to the iocbq.
+ * @piocbq: Pointer to the iocbq.
*
* This function is called with the sgl_list lock held. This function
* gets a new driver sglq object from the sglq list. If the
@@ -1227,8 +1243,8 @@
* @phba: Pointer to HBA context object.
* @iocbq: Pointer to driver iocb object.
*
- * This function is called with hbalock held to release driver
- * iocb object to the iocb pool. The iotag in the iocb object
+ * This function is called to release the driver iocb object
+ * to the iocb pool. The iotag in the iocb object
* does not change for each use of the iocb object. This function
* clears all other fields of the iocb object when it is freed.
* The sqlq structure that holds the xritag and phys and virtual
@@ -1238,7 +1254,8 @@
* this IO was aborted then the sglq entry it put on the
* lpfc_abts_els_sgl_list until the CQ_ABORTED_XRI is received. If the
* IO has good status or fails for any other reason then the sglq
- * entry is added to the free list (lpfc_els_sgl_list).
+ * entry is added to the free list (lpfc_els_sgl_list). The hbalock is
+ * asserted held in the code path calling this routine.
**/
static void
__lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
@@ -1248,8 +1265,6 @@
unsigned long iflag = 0;
struct lpfc_sli_ring *pring;
- lockdep_assert_held(&phba->hbalock);
-
if (iocbq->sli4_xritag == NO_XRI)
sglq = NULL;
else
@@ -1312,18 +1327,17 @@
* @phba: Pointer to HBA context object.
* @iocbq: Pointer to driver iocb object.
*
- * This function is called with hbalock held to release driver
- * iocb object to the iocb pool. The iotag in the iocb object
- * does not change for each use of the iocb object. This function
- * clears all other fields of the iocb object when it is freed.
+ * This function is called to release the driver iocb object to the
+ * iocb pool. The iotag in the iocb object does not change for each
+ * use of the iocb object. This function clears all other fields of
+ * the iocb object when it is freed. The hbalock is asserted held in
+ * the code path calling this routine.
**/
static void
__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.
*/
@@ -1475,6 +1489,7 @@
case DSSCMD_IWRITE64_CX:
case DSSCMD_IREAD64_CR:
case DSSCMD_IREAD64_CX:
+ case CMD_SEND_FRAME:
type = LPFC_SOL_IOCB;
break;
case CMD_ABORT_XRI_CN:
@@ -1549,7 +1564,7 @@
lpfc_config_ring(phba, i, pmb);
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
if (rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0446 Adapter failed to init (%d), "
"mbxCmd x%x CFG_RING, mbxStatus x%x, "
"ring %d\n",
@@ -1658,7 +1673,7 @@
pring->sli.sli3.local_getidx = le32_to_cpu(pgp->cmdGetInx);
if (unlikely(pring->sli.sli3.local_getidx >= max_cmd_idx)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0315 Ring %d issue: portCmdGet %d "
"is bigger than cmd ring %d\n",
pring->ringno,
@@ -1768,17 +1783,17 @@
* @nextiocb: Pointer to driver iocb object which need to be
* posted to firmware.
*
- * This function is called with hbalock held to post a new iocb to
- * the firmware. This function copies the new iocb to ring iocb slot and
- * updates the ring pointers. It adds the new iocb to txcmplq if there is
+ * This function is called to post a new iocb to the firmware. This
+ * function copies the new iocb to ring iocb slot and updates the
+ * ring pointers. It adds the new iocb to txcmplq if there is
* a completion call back for this iocb else the function will free the
- * iocb object.
+ * iocb object. The hbalock is asserted held in the code path calling
+ * this routine.
**/
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
*/
@@ -1944,8 +1959,7 @@
hbqp->local_hbqGetIdx = getidx;
if (unlikely(hbqp->local_hbqGetIdx >= hbqp->entry_count)) {
- lpfc_printf_log(phba, KERN_ERR,
- LOG_SLI | LOG_VPORT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1802 HBQ %d: local_hbqGetIdx "
"%u is > than hbqp->entry_count %u\n",
hbqno, hbqp->local_hbqGetIdx,
@@ -2213,10 +2227,8 @@
lpfc_hbq_defs[qno]->init_count);
}
-/**
+/*
* lpfc_sli_hbqbuf_get - Remove the first hbq off of an hbq list
- * @phba: Pointer to HBA context object.
- * @hbqno: HBQ number.
*
* This function removes the first hbq buffer on an hbq list and returns a
* pointer to that buffer. If it finds no buffers on the list it returns NULL.
@@ -2235,7 +2247,7 @@
/**
* lpfc_sli_rqbuf_get - Remove the first dma buffer off of an RQ list
* @phba: Pointer to HBA context object.
- * @hbqno: HBQ number.
+ * @hrq: HBQ number.
*
* This function removes the first RQ buffer on an RQ buffer list and returns a
* pointer to that buffer. If it finds no buffers on the list it returns NULL.
@@ -2284,7 +2296,7 @@
}
}
spin_unlock_irq(&phba->hbalock);
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_VPORT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1803 Bad hbq tag. Data: x%x x%x\n",
tag, phba->hbqs[tag >> 16].buffer_count);
return NULL;
@@ -2538,7 +2550,7 @@
/* Check security permission status on INIT_LINK mailbox command */
if ((pmb->u.mb.mbxCommand == MBX_INIT_LINK) &&
(pmb->u.mb.mbxStatus == MBXERR_SEC_NO_PERMISSION))
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2860 SLI authentication is required "
"for INIT_LINK but has not done yet\n");
@@ -2674,10 +2686,11 @@
if (lpfc_sli_chk_mbx_command(pmbox->mbxCommand) ==
MBX_SHUTDOWN) {
/* Unknown mailbox command compl */
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"(%d):0323 Unknown Mailbox command "
"x%x (x%x/x%x) Cmpl\n",
- pmb->vport ? pmb->vport->vpi : 0,
+ pmb->vport ? pmb->vport->vpi :
+ LPFC_VPORT_UNKNOWN,
pmbox->mbxCommand,
lpfc_sli_config_mbox_subsys_get(phba,
pmb),
@@ -2698,7 +2711,8 @@
"(%d):0305 Mbox cmd cmpl "
"error - RETRYing Data: x%x "
"(x%x/x%x) x%x x%x x%x\n",
- pmb->vport ? pmb->vport->vpi : 0,
+ pmb->vport ? pmb->vport->vpi :
+ LPFC_VPORT_UNKNOWN,
pmbox->mbxCommand,
lpfc_sli_config_mbox_subsys_get(phba,
pmb),
@@ -2706,7 +2720,8 @@
pmb),
pmbox->mbxStatus,
pmbox->un.varWords[0],
- pmb->vport->port_state);
+ pmb->vport ? pmb->vport->port_state :
+ LPFC_VPORT_UNKNOWN);
pmbox->mbxStatus = 0;
pmbox->mbxOwner = OWN_HOST;
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
@@ -2772,6 +2787,123 @@
}
/**
+ * lpfc_nvme_unsol_ls_handler - Process an unsolicited event data buffer
+ * containing a NVME LS request.
+ * @phba: pointer to lpfc hba data structure.
+ * @piocb: pointer to the iocbq struct representing the sequence starting
+ * frame.
+ *
+ * This routine initially validates the NVME LS, validates there is a login
+ * with the port that sent the LS, and then calls the appropriate nvme host
+ * or target LS request handler.
+ **/
+static void
+lpfc_nvme_unsol_ls_handler(struct lpfc_hba *phba, struct lpfc_iocbq *piocb)
+{
+ struct lpfc_nodelist *ndlp;
+ struct lpfc_dmabuf *d_buf;
+ struct hbq_dmabuf *nvmebuf;
+ struct fc_frame_header *fc_hdr;
+ struct lpfc_async_xchg_ctx *axchg = NULL;
+ char *failwhy = NULL;
+ uint32_t oxid, sid, did, fctl, size;
+ int ret = 1;
+
+ d_buf = piocb->context2;
+
+ nvmebuf = container_of(d_buf, struct hbq_dmabuf, dbuf);
+ fc_hdr = nvmebuf->hbuf.virt;
+ oxid = be16_to_cpu(fc_hdr->fh_ox_id);
+ sid = sli4_sid_from_fc_hdr(fc_hdr);
+ did = sli4_did_from_fc_hdr(fc_hdr);
+ fctl = (fc_hdr->fh_f_ctl[0] << 16 |
+ fc_hdr->fh_f_ctl[1] << 8 |
+ fc_hdr->fh_f_ctl[2]);
+ size = bf_get(lpfc_rcqe_length, &nvmebuf->cq_event.cqe.rcqe_cmpl);
+
+ lpfc_nvmeio_data(phba, "NVME LS RCV: xri x%x sz %d from %06x\n",
+ oxid, size, sid);
+
+ if (phba->pport->load_flag & FC_UNLOADING) {
+ failwhy = "Driver Unloading";
+ } else if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) {
+ failwhy = "NVME FC4 Disabled";
+ } else if (!phba->nvmet_support && !phba->pport->localport) {
+ failwhy = "No Localport";
+ } else if (phba->nvmet_support && !phba->targetport) {
+ failwhy = "No Targetport";
+ } else if (unlikely(fc_hdr->fh_r_ctl != FC_RCTL_ELS4_REQ)) {
+ failwhy = "Bad NVME LS R_CTL";
+ } else if (unlikely((fctl & 0x00FF0000) !=
+ (FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT))) {
+ failwhy = "Bad NVME LS F_CTL";
+ } else {
+ axchg = kzalloc(sizeof(*axchg), GFP_ATOMIC);
+ if (!axchg)
+ failwhy = "No CTX memory";
+ }
+
+ if (unlikely(failwhy)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "6154 Drop NVME LS: SID %06X OXID x%X: %s\n",
+ sid, oxid, failwhy);
+ goto out_fail;
+ }
+
+ /* validate the source of the LS is logged in */
+ ndlp = lpfc_findnode_did(phba->pport, sid);
+ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) ||
+ ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
+ (ndlp->nlp_state != NLP_STE_MAPPED_NODE))) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
+ "6216 NVME Unsol rcv: No ndlp: "
+ "NPort_ID x%x oxid x%x\n",
+ sid, oxid);
+ goto out_fail;
+ }
+
+ axchg->phba = phba;
+ axchg->ndlp = ndlp;
+ axchg->size = size;
+ axchg->oxid = oxid;
+ axchg->sid = sid;
+ axchg->wqeq = NULL;
+ axchg->state = LPFC_NVME_STE_LS_RCV;
+ axchg->entry_cnt = 1;
+ axchg->rqb_buffer = (void *)nvmebuf;
+ axchg->hdwq = &phba->sli4_hba.hdwq[0];
+ axchg->payload = nvmebuf->dbuf.virt;
+ INIT_LIST_HEAD(&axchg->list);
+
+ if (phba->nvmet_support)
+ ret = lpfc_nvmet_handle_lsreq(phba, axchg);
+ else
+ ret = lpfc_nvme_handle_lsreq(phba, axchg);
+
+ /* if zero, LS was successfully handled. If non-zero, LS not handled */
+ if (!ret)
+ return;
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "6155 Drop NVME LS from DID %06X: SID %06X OXID x%X "
+ "NVMe%s handler failed %d\n",
+ did, sid, oxid,
+ (phba->nvmet_support) ? "T" : "I", ret);
+
+out_fail:
+
+ /* recycle receive buffer */
+ lpfc_in_buf_free(phba, &nvmebuf->dbuf);
+
+ /* If start of new exchange, abort it */
+ if (axchg && (fctl & FC_FC_FIRST_SEQ && !(fctl & FC_FC_EX_CTX)))
+ ret = lpfc_nvme_unsol_ls_issue_abort(phba, axchg, sid, oxid);
+
+ if (ret)
+ kfree(axchg);
+}
+
+/**
* lpfc_complete_unsol_iocb - Complete an unsolicited sequence
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
@@ -2792,7 +2924,7 @@
switch (fch_type) {
case FC_TYPE_NVME:
- lpfc_nvmet_unsol_ls_event(phba, pring, saveq);
+ lpfc_nvme_unsol_ls_handler(phba, saveq);
return 1;
default:
break;
@@ -3035,7 +3167,7 @@
}
spin_unlock_irqrestore(temp_lock, iflag);
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0317 iotag x%x is out of "
"range: max iotag x%x wd0 x%x\n",
iotag, phba->sli.last_iotag,
@@ -3082,7 +3214,7 @@
}
spin_unlock_irqrestore(temp_lock, iflag);
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0372 iotag x%x lookup error: max iotag (x%x) "
"iocb_flag x%x\n",
iotag, phba->sli.last_iotag,
@@ -3258,7 +3390,7 @@
* Ring <ringno> handler: portRspPut <portRspPut> is bigger than
* rsp ring <portRspMax>
*/
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0312 Ring %d handler: portRspPut %d "
"is bigger than rsp ring %d\n",
pring->ringno, le32_to_cpu(pgp->rspPutInx),
@@ -3280,7 +3412,7 @@
/**
* lpfc_poll_eratt - Error attention polling timer timeout handler
- * @ptr: Pointer to address of HBA context object.
+ * @t: Context to fetch pointer to address of HBA context object from.
*
* This function is invoked by the Error Attention polling timer when the
* timer times out. It will check the SLI Error Attention register for
@@ -3477,7 +3609,7 @@
phba->brd_no, adaptermsg);
} else {
/* Unknown IOCB command */
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0334 Unknown IOCB command "
"Data: x%x, x%x x%x x%x x%x\n",
type, irsp->ulpCommand,
@@ -3675,7 +3807,7 @@
phba->brd_no, adaptermsg);
} else {
/* Unknown IOCB command */
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0335 Unknown IOCB "
"command Data: x%x "
"x%x x%x x%x\n",
@@ -3755,7 +3887,7 @@
* Ring <ringno> handler: portRspPut <portRspPut> is bigger than
* rsp ring <portRspMax>
*/
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0303 Ring %d handler: portRspPut %d "
"is bigger than rsp ring %d\n",
pring->ringno, portRspPut, portRspMax);
@@ -3966,7 +4098,6 @@
/**
* lpfc_sli_abort_fcp_rings - Abort all iocbs in all FCP rings
* @phba: Pointer to HBA context object.
- * @pring: Pointer to driver SLI ring object.
*
* This function aborts all iocbs in FCP rings and frees all the iocb
* objects in txq. This function issues an abort iocb for all the iocb commands
@@ -4127,7 +4258,7 @@
/* Check to see if any errors occurred during init */
if ((status & HS_FFERM) || (i >= 20)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2751 Adapter failed to restart, "
"status reg x%x, FW Data: A8 x%x AC x%x\n",
status,
@@ -4349,7 +4480,7 @@
if (retval != MBX_SUCCESS) {
if (retval != MBX_BUSY)
mempool_free(pmb, phba->mbox_mem_pool);
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2752 KILL_BOARD command failed retval %d\n",
retval);
spin_lock_irq(&phba->hbalock);
@@ -4498,12 +4629,6 @@
phba->fcf.fcf_flag = 0;
spin_unlock_irq(&phba->hbalock);
- /* SLI4 INTF 2: if FW dump is being taken skip INIT_PORT */
- if (phba->hba_flag & HBA_FW_DUMP_OP) {
- phba->hba_flag &= ~HBA_FW_DUMP_OP;
- return rc;
- }
-
/* Now physically reset the device */
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"0389 Performing PCI function reset!\n");
@@ -4701,7 +4826,7 @@
if (i++ >= 200) {
/* Adapter failed to init, timeout, status reg
<status> */
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0436 Adapter failed to init, "
"timeout, status reg x%x, "
"FW Data: A8 x%x AC x%x\n", status,
@@ -4716,7 +4841,7 @@
/* ERROR: During chipset initialization */
/* Adapter failed to init, chipset, status reg
<status> */
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0437 Adapter failed to init, "
"chipset, status reg x%x, "
"FW Data: A8 x%x AC x%x\n", status,
@@ -4747,7 +4872,7 @@
if (status & HS_FFERM) {
/* ERROR: During chipset initialization */
/* Adapter failed to init, chipset, status reg <status> */
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0438 Adapter failed to init, chipset, "
"status reg x%x, "
"FW Data: A8 x%x AC x%x\n", status,
@@ -4892,8 +5017,17 @@
lpfc_sli4_rb_setup(struct lpfc_hba *phba)
{
phba->hbq_in_use = 1;
- phba->hbqs[LPFC_ELS_HBQ].entry_count =
- lpfc_hbq_defs[LPFC_ELS_HBQ]->entry_count;
+ /**
+ * Specific case when the MDS diagnostics is enabled and supported.
+ * The receive buffer count is truncated to manage the incoming
+ * traffic.
+ **/
+ if (phba->cfg_enable_mds_diags && phba->mds_diags_support)
+ phba->hbqs[LPFC_ELS_HBQ].entry_count =
+ lpfc_hbq_defs[LPFC_ELS_HBQ]->entry_count >> 1;
+ else
+ phba->hbqs[LPFC_ELS_HBQ].entry_count =
+ lpfc_hbq_defs[LPFC_ELS_HBQ]->entry_count;
phba->hbq_count = 1;
lpfc_sli_hbqbuf_init_hbqs(phba, LPFC_ELS_HBQ);
/* Initially populate or replenish the HBQs */
@@ -4961,7 +5095,7 @@
LPFC_SLI3_CRP_ENABLED |
LPFC_SLI3_DSS_ENABLED);
if (rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0442 Adapter failed to init, mbxCmd x%x "
"CONFIG_PORT, mbxStatus x%x Data: x%x\n",
pmb->u.mb.mbxCommand, pmb->u.mb.mbxStatus, 0);
@@ -4999,23 +5133,6 @@
} else
phba->max_vpi = 0;
- phba->fips_level = 0;
- phba->fips_spec_rev = 0;
- if (pmb->u.mb.un.varCfgPort.gdss) {
- phba->sli3_options |= LPFC_SLI3_DSS_ENABLED;
- phba->fips_level = pmb->u.mb.un.varCfgPort.fips_level;
- phba->fips_spec_rev = pmb->u.mb.un.varCfgPort.fips_rev;
- lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "2850 Security Crypto Active. FIPS x%d "
- "(Spec Rev: x%d)",
- phba->fips_level, phba->fips_spec_rev);
- }
- if (pmb->u.mb.un.varCfgPort.sec_err) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "2856 Config Port Security Crypto "
- "Error: x%x ",
- pmb->u.mb.un.varCfgPort.sec_err);
- }
if (pmb->u.mb.un.varCfgPort.gerbm)
phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED;
if (pmb->u.mb.un.varCfgPort.gcrp)
@@ -5028,7 +5145,7 @@
if (pmb->u.mb.un.varCfgPort.gbg == 0) {
phba->cfg_enable_bg = 0;
phba->sli3_options &= ~LPFC_SLI3_BG_ENABLED;
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0443 Adapter did not grant "
"BlockGuard\n");
}
@@ -5067,7 +5184,7 @@
switch (phba->cfg_sli_mode) {
case 2:
if (phba->cfg_enable_npiv) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1824 NPIV enabled: Override sli_mode "
"parameter (%d) to auto (0).\n",
phba->cfg_sli_mode);
@@ -5079,7 +5196,7 @@
case 3:
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1819 Unrecognized sli_mode parameter: %d.\n",
phba->cfg_sli_mode);
@@ -5090,7 +5207,7 @@
rc = lpfc_sli_config_port(phba, mode);
if (rc && phba->cfg_sli_mode == 3)
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1820 Unable to select SLI-3. "
"Not supported by adapter.\n");
if (rc && mode != 2)
@@ -5184,7 +5301,7 @@
lpfc_sli_hba_setup_error:
phba->link_state = LPFC_HBA_ERROR;
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0445 Firmware initialization failed\n");
return rc;
}
@@ -5192,7 +5309,7 @@
/**
* lpfc_sli4_read_fcoe_params - Read fcoe params from conf region
* @phba: Pointer to HBA context object.
- * @mboxq: mailbox pointer.
+ *
* This function issue a dump mailbox command to read config region
* 23 and parse the records in the region and populate driver
* data structure.
@@ -5381,7 +5498,7 @@
LPFC_SLI4_MBX_NEMBED);
if (alloclen < reqlen) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3084 Allocated DMA memory size (%d) is "
"less than the requested DMA memory size "
"(%d)\n", alloclen, reqlen);
@@ -5637,7 +5754,7 @@
rsrc_info = &mbox->u.mqe.un.rsrc_extent_info;
if (bf_get(lpfc_mbox_hdr_status,
&rsrc_info->header.cfg_shdr.response)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2930 Failed to get resource extents "
"Status 0x%x Add'l Status 0x%x\n",
bf_get(lpfc_mbox_hdr_status,
@@ -5726,10 +5843,10 @@
/**
* lpfc_sli4_cfg_post_extnts -
* @phba: Pointer to HBA context object.
- * @extnt_cnt - number of available extents.
- * @type - the extent type (rpi, xri, vfi, vpi).
- * @emb - buffer to hold either MBX_EMBED or MBX_NEMBED operation.
- * @mbox - pointer to the caller's allocated mailbox structure.
+ * @extnt_cnt: number of available extents.
+ * @type: the extent type (rpi, xri, vfi, vpi).
+ * @emb: buffer to hold either MBX_EMBED or MBX_NEMBED operation.
+ * @mbox: pointer to the caller's allocated mailbox structure.
*
* This function executes the extents allocation request. It also
* takes care of the amount of memory needed to allocate or get the
@@ -5775,7 +5892,7 @@
LPFC_MBOX_OPCODE_ALLOC_RSRC_EXTENT,
req_len, *emb);
if (alloc_len < req_len) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2982 Allocated DMA memory size (x%x) is "
"less than the requested DMA memory "
"size (x%x)\n", alloc_len, req_len);
@@ -5831,7 +5948,7 @@
return -EIO;
if ((rsrc_cnt == 0) || (rsrc_size == 0)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3009 No available Resource Extents "
"for resource type 0x%x: Count: 0x%x, "
"Size 0x%x\n", type, rsrc_cnt,
@@ -6082,7 +6199,7 @@
dealloc_rsrc = &mbox->u.mqe.un.dealloc_rsrc_extents;
if (bf_get(lpfc_mbox_hdr_status,
&dealloc_rsrc->header.cfg_shdr.response)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2919 Failed to release resource extents "
"for type %d - Status 0x%x Add'l Status 0x%x. "
"Resource memory not released.\n",
@@ -6173,6 +6290,14 @@
mbox->u.mqe.un.set_feature.feature = LPFC_SET_MDS_DIAGS;
mbox->u.mqe.un.set_feature.param_len = 8;
break;
+ case LPFC_SET_DUAL_DUMP:
+ bf_set(lpfc_mbx_set_feature_dd,
+ &mbox->u.mqe.un.set_feature, LPFC_ENABLE_DUAL_DUMP);
+ bf_set(lpfc_mbx_set_feature_ddquery,
+ &mbox->u.mqe.un.set_feature, 0);
+ mbox->u.mqe.un.set_feature.feature = LPFC_SET_DUAL_DUMP;
+ mbox->u.mqe.un.set_feature.param_len = 4;
+ break;
}
return;
@@ -6190,11 +6315,16 @@
{
struct lpfc_ras_fwlog *ras_fwlog = &phba->ras_fwlog;
- ras_fwlog->ras_active = false;
+ spin_lock_irq(&phba->hbalock);
+ ras_fwlog->state = INACTIVE;
+ spin_unlock_irq(&phba->hbalock);
/* Disable FW logging to host memory */
writel(LPFC_CTL_PDEV_CTL_DDL_RAS,
phba->sli4_hba.conf_regs_memmap_p + LPFC_CTL_PDEV_CTL_OFFSET);
+
+ /* Wait 10ms for firmware to stop using DMA buffer */
+ usleep_range(10 * 1000, 20 * 1000);
}
/**
@@ -6230,7 +6360,9 @@
ras_fwlog->lwpd.virt = NULL;
}
- ras_fwlog->ras_active = false;
+ spin_lock_irq(&phba->hbalock);
+ ras_fwlog->state = INACTIVE;
+ spin_unlock_irq(&phba->hbalock);
}
/**
@@ -6261,7 +6393,7 @@
&ras_fwlog->lwpd.phys,
GFP_KERNEL);
if (!ras_fwlog->lwpd.virt) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6185 LWPD Memory Alloc Failed\n");
return -ENOMEM;
@@ -6302,7 +6434,7 @@
/**
* lpfc_sli4_ras_mbox_cmpl: Completion handler for RAS MBX command
* @phba: pointer to lpfc hba data structure.
- * @pmboxq: pointer to the driver internal queue element for mailbox command.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
*
* Completion handler for driver's RAS MBX command to the device.
**/
@@ -6322,7 +6454,7 @@
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (mb->mbxStatus != MBX_SUCCESS || shdr_status) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6188 FW LOG mailbox "
"completed with status x%x add_status x%x,"
" mbx status x%x\n",
@@ -6332,7 +6464,9 @@
goto disable_ras;
}
- ras_fwlog->ras_active = true;
+ spin_lock_irq(&phba->hbalock);
+ ras_fwlog->state = ACTIVE;
+ spin_unlock_irq(&phba->hbalock);
mempool_free(pmb, phba->mbox_mem_pool);
return;
@@ -6364,6 +6498,10 @@
uint32_t len = 0, fwlog_buffsize, fwlog_entry_count;
int rc = 0;
+ spin_lock_irq(&phba->hbalock);
+ ras_fwlog->state = INACTIVE;
+ spin_unlock_irq(&phba->hbalock);
+
fwlog_buffsize = (LPFC_RAS_MIN_BUFF_POST_SIZE *
phba->cfg_ras_fwlog_buffsize);
fwlog_entry_count = (fwlog_buffsize/LPFC_RAS_MAX_ENTRY_SIZE);
@@ -6384,7 +6522,7 @@
/* Setup Mailbox command */
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6190 RAS MBX Alloc Failed");
rc = -ENOMEM;
goto mem_free;
@@ -6423,13 +6561,16 @@
mbx_fwlog->u.request.lwpd.addr_lo = putPaddrLow(ras_fwlog->lwpd.phys);
mbx_fwlog->u.request.lwpd.addr_hi = putPaddrHigh(ras_fwlog->lwpd.phys);
+ spin_lock_irq(&phba->hbalock);
+ ras_fwlog->state = REG_INPROGRESS;
+ spin_unlock_irq(&phba->hbalock);
mbox->vport = phba->pport;
mbox->mbox_cmpl = lpfc_sli4_ras_mbox_cmpl;
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6191 FW-Log Mailbox failed. "
"status %d mbxStatus : x%x", rc,
bf_get(lpfc_mqe_status, &mbox->u.mqe));
@@ -6565,7 +6706,7 @@
/* RPIs. */
count = phba->sli4_hba.max_cfg_param.max_rpi;
if (count <= 0) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3279 Invalid provisioning of "
"rpi:%d\n", count);
rc = -EINVAL;
@@ -6593,7 +6734,7 @@
/* VPIs. */
count = phba->sli4_hba.max_cfg_param.max_vpi;
if (count <= 0) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3280 Invalid provisioning of "
"vpi:%d\n", count);
rc = -EINVAL;
@@ -6620,7 +6761,7 @@
/* XRIs. */
count = phba->sli4_hba.max_cfg_param.max_xri;
if (count <= 0) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3281 Invalid provisioning of "
"xri:%d\n", count);
rc = -EINVAL;
@@ -6649,7 +6790,7 @@
/* VFIs. */
count = phba->sli4_hba.max_cfg_param.max_vfi;
if (count <= 0) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3282 Invalid provisioning of "
"vfi:%d\n", count);
rc = -EINVAL;
@@ -6743,7 +6884,7 @@
* lpfc_sli4_get_allocated_extnts - Get the port's allocated extents.
* @phba: Pointer to HBA context object.
* @type: The resource extent type.
- * @extnt_count: buffer to hold port extent count response
+ * @extnt_cnt: buffer to hold port extent count response
* @extnt_size: buffer to hold port extent size response.
*
* This function calls the port to read the host allocated extents
@@ -6827,7 +6968,7 @@
LPFC_MBOX_OPCODE_GET_ALLOC_RSRC_EXTENT,
req_len, emb);
if (alloc_len < req_len) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2983 Allocated DMA memory size (x%x) is "
"less than the requested DMA memory "
"size (x%x)\n", alloc_len, req_len);
@@ -6870,7 +7011,7 @@
}
if (bf_get(lpfc_mbox_hdr_status, &shdr->response)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2984 Failed to read allocated resources "
"for type %d - Status 0x%x Add'l Status 0x%x.\n",
type,
@@ -6887,7 +7028,6 @@
/**
* lpfc_sli4_repost_sgl_list - Repost the buffers sgl pages as block
* @phba: pointer to lpfc hba data structure.
- * @pring: Pointer to driver SLI ring object.
* @sgl_list: linked link of sgl buffers to post
* @cnt: number of linked list buffers
*
@@ -7025,7 +7165,7 @@
spin_unlock(&phba->sli4_hba.sgl_list_lock);
spin_unlock_irq(&phba->hbalock);
} else {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3161 Failure to post sgl to port.\n");
return -EIO;
}
@@ -7128,7 +7268,7 @@
drqe.address_hi = putPaddrHigh(rqb_buffer->dbuf.phys);
rc = lpfc_sli4_rq_put(hrq, drq, &hrqe, &drqe);
if (rc < 0) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6421 Cannot post to HRQ %d: %x %x %x "
"DRQ %x %x\n",
hrq->queue_id,
@@ -7149,6 +7289,68 @@
}
/**
+ * lpfc_init_idle_stat_hb - Initialize idle_stat tracking
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine initializes the per-cq idle_stat to dynamically dictate
+ * polling decisions.
+ *
+ * Return codes:
+ * None
+ **/
+static void lpfc_init_idle_stat_hb(struct lpfc_hba *phba)
+{
+ int i;
+ struct lpfc_sli4_hdw_queue *hdwq;
+ struct lpfc_queue *cq;
+ struct lpfc_idle_stat *idle_stat;
+ u64 wall;
+
+ for_each_present_cpu(i) {
+ hdwq = &phba->sli4_hba.hdwq[phba->sli4_hba.cpu_map[i].hdwq];
+ cq = hdwq->io_cq;
+
+ /* Skip if we've already handled this cq's primary CPU */
+ if (cq->chann != i)
+ continue;
+
+ idle_stat = &phba->sli4_hba.idle_stat[i];
+
+ idle_stat->prev_idle = get_cpu_idle_time(i, &wall, 1);
+ idle_stat->prev_wall = wall;
+
+ if (phba->nvmet_support)
+ cq->poll_mode = LPFC_QUEUE_WORK;
+ else
+ cq->poll_mode = LPFC_IRQ_POLL;
+ }
+
+ if (!phba->nvmet_support)
+ schedule_delayed_work(&phba->idle_stat_delay_work,
+ msecs_to_jiffies(LPFC_IDLE_STAT_DELAY));
+}
+
+static void lpfc_sli4_dip(struct lpfc_hba *phba)
+{
+ uint32_t if_type;
+
+ if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
+ if (if_type == LPFC_SLI_INTF_IF_TYPE_2 ||
+ if_type == LPFC_SLI_INTF_IF_TYPE_6) {
+ struct lpfc_register reg_data;
+
+ if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
+ ®_data.word0))
+ return;
+
+ if (bf_get(lpfc_sliport_status_dip, ®_data))
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2904 Firmware Dump Image Present"
+ " on Adapter");
+ }
+}
+
+/**
* lpfc_sli4_hba_setup - SLI4 device initialization PCI function
* @phba: Pointer to HBA context object.
*
@@ -7160,7 +7362,7 @@
int
lpfc_sli4_hba_setup(struct lpfc_hba *phba)
{
- int rc, i, cnt, len;
+ int rc, i, cnt, len, dd;
LPFC_MBOXQ_t *mboxq;
struct lpfc_mqe *mqe;
uint8_t *vpd;
@@ -7170,6 +7372,7 @@
struct lpfc_vport *vport = phba->pport;
struct lpfc_dmabuf *mp;
struct lpfc_rqb *rqbp;
+ u32 flg;
/* Perform a PCI function reset to start from clean */
rc = lpfc_pci_function_reset(phba);
@@ -7183,9 +7386,21 @@
else {
spin_lock_irq(&phba->hbalock);
phba->sli.sli_flag |= LPFC_SLI_ACTIVE;
+ flg = phba->sli.sli_flag;
spin_unlock_irq(&phba->hbalock);
+ /* Allow a little time after setting SLI_ACTIVE for any polled
+ * MBX commands to complete via BSG.
+ */
+ for (i = 0; i < 50 && (flg & LPFC_SLI_MBOX_ACTIVE); i++) {
+ msleep(20);
+ spin_lock_irq(&phba->hbalock);
+ flg = phba->sli.sli_flag;
+ spin_unlock_irq(&phba->hbalock);
+ }
}
+ lpfc_sli4_dip(phba);
+
/*
* Allocate a single mailbox container for initializing the
* port.
@@ -7226,7 +7441,7 @@
phba->hba_flag &= ~HBA_IOQ_FLUSH;
if (phba->sli_rev != LPFC_SLI_REV4) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0376 READ_REV Error. SLI Level %d "
"FCoE enabled %d\n",
phba->sli_rev, phba->hba_flag & HBA_FCOE_MODE);
@@ -7268,7 +7483,7 @@
*/
rc = lpfc_parse_vpd(phba, vpd, vpd_size);
if (unlikely(!rc)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0377 Error %d parsing vpd. "
"Using defaults.\n", rc);
rc = 0;
@@ -7314,15 +7529,6 @@
phba->vpd.rev.fcphHigh, phba->vpd.rev.fcphLow,
phba->vpd.rev.feaLevelHigh, phba->vpd.rev.feaLevelLow);
- /* Reset the DFT_LUN_Q_DEPTH to (max xri >> 3) */
- rc = (phba->sli4_hba.max_cfg_param.max_xri >> 3);
- if (phba->pport->cfg_lun_queue_depth > rc) {
- lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
- "3362 LUN queue depth changed from %d to %d\n",
- phba->pport->cfg_lun_queue_depth, rc);
- phba->pport->cfg_lun_queue_depth = rc;
- }
-
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
LPFC_SLI_INTF_IF_TYPE_0) {
lpfc_set_features(phba, mboxq, LPFC_SET_UE_RECOVERY);
@@ -7411,13 +7617,30 @@
phba->sli3_options |= (LPFC_SLI3_NPIV_ENABLED | LPFC_SLI3_HBQ_ENABLED);
spin_unlock_irq(&phba->hbalock);
+ /* Always try to enable dual dump feature if we can */
+ lpfc_set_features(phba, mboxq, LPFC_SET_DUAL_DUMP);
+ rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+ dd = bf_get(lpfc_mbx_set_feature_dd, &mboxq->u.mqe.un.set_feature);
+ if ((rc == MBX_SUCCESS) && (dd == LPFC_ENABLE_DUAL_DUMP))
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "6448 Dual Dump is enabled\n");
+ else
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI | LOG_INIT,
+ "6447 Dual Dump Mailbox x%x (x%x/x%x) failed, "
+ "rc:x%x dd:x%x\n",
+ bf_get(lpfc_mqe_command, &mboxq->u.mqe),
+ lpfc_sli_config_mbox_subsys_get(
+ phba, mboxq),
+ lpfc_sli_config_mbox_opcode_get(
+ phba, mboxq),
+ rc, dd);
/*
* Allocate all resources (xri,rpi,vpi,vfi) now. Subsequent
* calls depends on these resources to complete port setup.
*/
rc = lpfc_sli4_alloc_resource_identifiers(phba);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2920 Failed to alloc Resource IDs "
"rc = x%x\n", rc);
goto out_free_mbox;
@@ -7456,7 +7679,7 @@
kfree(mp);
mboxq->ctx_buf = NULL;
if (unlikely(rc)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0382 READ_SPARAM command failed "
"status %d, mbxStatus x%x\n",
rc, bf_get(lpfc_mqe_status, mqe));
@@ -7474,7 +7697,7 @@
/* Create all the SLI4 queues */
rc = lpfc_sli4_queue_create(phba);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3089 Failed to allocate queues\n");
rc = -ENODEV;
goto out_free_mbox;
@@ -7482,7 +7705,7 @@
/* Set up all the queues to the device */
rc = lpfc_sli4_queue_setup(phba);
if (unlikely(rc)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0381 Error %d during queue setup.\n ", rc);
goto out_stop_timers;
}
@@ -7493,7 +7716,7 @@
/* update host els xri-sgl sizes and mappings */
rc = lpfc_sli4_els_sgl_update(phba);
if (unlikely(rc)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1400 Failed to update xri-sgl size and "
"mapping: %d\n", rc);
goto out_destroy_queue;
@@ -7503,7 +7726,7 @@
rc = lpfc_sli4_repost_sgl_list(phba, &phba->sli4_hba.lpfc_els_sgl_list,
phba->sli4_hba.els_xri_cnt);
if (unlikely(rc < 0)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0582 Error %d during els sgl post "
"operation\n", rc);
rc = -ENODEV;
@@ -7515,7 +7738,7 @@
/* update host nvmet xri-sgl sizes and mappings */
rc = lpfc_sli4_nvmet_sgl_update(phba);
if (unlikely(rc)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6308 Failed to update nvmet-sgl size "
"and mapping: %d\n", rc);
goto out_destroy_queue;
@@ -7527,7 +7750,7 @@
&phba->sli4_hba.lpfc_nvmet_sgl_list,
phba->sli4_hba.nvmet_xri_cnt);
if (unlikely(rc < 0)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3117 Error %d during nvmet "
"sgl post\n", rc);
rc = -ENODEV;
@@ -7535,14 +7758,16 @@
}
phba->sli4_hba.nvmet_xri_cnt = rc;
- cnt = phba->cfg_iocb_cnt * 1024;
- /* We need 1 iocbq for every SGL, for IO processing */
- cnt += phba->sli4_hba.nvmet_xri_cnt;
+ /* We allocate an iocbq for every receive context SGL.
+ * The additional allocation is for abort and ls handling.
+ */
+ cnt = phba->sli4_hba.nvmet_xri_cnt +
+ phba->sli4_hba.max_cfg_param.max_xri;
} else {
/* update host common xri-sgl sizes and mappings */
rc = lpfc_sli4_io_sgl_update(phba);
if (unlikely(rc)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6082 Failed to update nvme-sgl size "
"and mapping: %d\n", rc);
goto out_destroy_queue;
@@ -7551,7 +7776,7 @@
/* register the allocated common sgl pool to the port */
rc = lpfc_sli4_repost_io_sgl_list(phba);
if (unlikely(rc)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6116 Error %d during nvme sgl post "
"operation\n", rc);
/* Some NVME buffers were moved to abort nvme list */
@@ -7559,17 +7784,20 @@
rc = -ENODEV;
goto out_destroy_queue;
}
- cnt = phba->cfg_iocb_cnt * 1024;
+ /* Each lpfc_io_buf job structure has an iocbq element.
+ * This cnt provides for abort, els, ct and ls requests.
+ */
+ cnt = phba->sli4_hba.max_cfg_param.max_xri;
}
if (!phba->sli.iocbq_lookup) {
/* Initialize and populate the iocb list per host */
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
- "2821 initialize iocb list %d total %d\n",
- phba->cfg_iocb_cnt, cnt);
+ "2821 initialize iocb list with %d entries\n",
+ cnt);
rc = lpfc_init_iocb_list(phba, cnt);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1413 Failed to init iocb list.\n");
goto out_destroy_queue;
}
@@ -7598,7 +7826,7 @@
/* Post the rpi header region to the device. */
rc = lpfc_sli4_post_all_rpi_hdrs(phba);
if (unlikely(rc)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0393 Error %d during rpi post operation\n",
rc);
rc = -ENODEV;
@@ -7690,6 +7918,9 @@
queue_delayed_work(phba->wq, &phba->eq_delay_work,
msecs_to_jiffies(LPFC_EQ_DELAY_MSECS));
+ /* start per phba idle_stat_delay heartbeat */
+ lpfc_init_idle_stat_hb(phba);
+
/* Start error attention (ERATT) polling timer */
mod_timer(&phba->eratt_poll,
jiffies + msecs_to_jiffies(1000 * phba->eratt_poll_interval));
@@ -7739,12 +7970,12 @@
if (!(phba->hba_flag & HBA_FCOE_MODE) &&
(phba->hba_flag & LINK_DISABLED)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3103 Adapter Link is disabled.\n");
lpfc_down_link(phba, mboxq);
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
if (rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3104 Adapter failed to issue "
"DOWN_LINK mbox cmd, rc:x%x\n", rc);
goto out_io_buff_free;
@@ -7778,7 +8009,7 @@
/**
* lpfc_mbox_timeout - Timeout call back function for mbox timer
- * @ptr: context object - pointer to hba structure.
+ * @t: Context to fetch pointer to hba structure from.
*
* This is the callback function for mailbox timer. The mailbox
* timer is armed when a new mailbox command is issued and the timer
@@ -7952,7 +8183,7 @@
}
/* Mbox cmd <mbxCommand> timeout */
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0310 Mailbox command x%x timeout Data: x%x x%x x%px\n",
mb->mbxCommand,
phba->pport->port_state,
@@ -7974,7 +8205,7 @@
lpfc_sli_abort_fcp_rings(phba);
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0345 Resetting board due to mailbox timeout\n");
/* Reset the HBA device */
@@ -8072,7 +8303,7 @@
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
/* Mbox command <mbxCommand> cannot issue */
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"(%d):0311 Mailbox command x%x cannot "
"issue Data: x%x x%x\n",
pmbox->vport ? pmbox->vport->vpi : 0,
@@ -8084,7 +8315,7 @@
if (lpfc_readl(phba->HCregaddr, &hc_copy) ||
!(hc_copy & HC_MBINT_ENA)) {
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"(%d):2528 Mailbox command x%x cannot "
"issue Data: x%x x%x\n",
pmbox->vport ? pmbox->vport->vpi : 0,
@@ -8103,7 +8334,7 @@
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
/* Mbox command <mbxCommand> cannot issue */
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"(%d):2529 Mailbox command x%x "
"cannot issue Data: x%x x%x\n",
pmbox->vport ? pmbox->vport->vpi : 0,
@@ -8115,7 +8346,7 @@
if (!(psli->sli_flag & LPFC_SLI_ACTIVE)) {
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
/* Mbox command <mbxCommand> cannot issue */
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"(%d):2530 Mailbox command x%x "
"cannot issue Data: x%x x%x\n",
pmbox->vport ? pmbox->vport->vpi : 0,
@@ -8168,7 +8399,7 @@
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
/* Mbox command <mbxCommand> cannot issue */
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"(%d):2531 Mailbox command x%x "
"cannot issue Data: x%x x%x\n",
pmbox->vport ? pmbox->vport->vpi : 0,
@@ -8486,7 +8717,7 @@
psli->sli_flag &= ~LPFC_SLI_ASYNC_MBX_BLK;
spin_unlock_irq(&phba->hbalock);
- /* wake up worker thread to post asynchronlous mailbox command */
+ /* wake up worker thread to post asynchronous mailbox command */
lpfc_worker_wake_up(phba);
}
@@ -8559,7 +8790,7 @@
spin_lock_irqsave(&phba->hbalock, iflag);
if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
spin_unlock_irqrestore(&phba->hbalock, iflag);
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"(%d):2532 Mailbox command x%x (x%x/x%x) "
"cannot issue Data: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
@@ -8658,7 +8889,7 @@
/**
* lpfc_sli_issue_mbox_s4 - Issue an SLI4 mailbox command to firmware
* @phba: Pointer to HBA context object.
- * @pmbox: Pointer to mailbox object.
+ * @mboxq: Pointer to mailbox object.
* @flag: Flag indicating how the mailbox need to be processed.
*
* This function is called by discovery code and HBA management code to submit
@@ -8680,7 +8911,7 @@
rc = lpfc_mbox_dev_check(phba);
if (unlikely(rc)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"(%d):2544 Mailbox command x%x (x%x/x%x) "
"cannot issue Data: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
@@ -8702,7 +8933,7 @@
"(%d):2541 Mailbox command x%x "
"(x%x/x%x) failure: "
"mqe_sta: x%x mcqe_sta: x%x/x%x "
- "Data: x%x x%x\n,",
+ "Data: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
lpfc_sli_config_mbox_subsys_get(phba,
@@ -8736,7 +8967,7 @@
"(%d):2597 Sync Mailbox command "
"x%x (x%x/x%x) failure: "
"mqe_sta: x%x mcqe_sta: x%x/x%x "
- "Data: x%x x%x\n,",
+ "Data: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
mboxq->u.mb.mbxCommand,
lpfc_sli_config_mbox_subsys_get(phba,
@@ -8754,10 +8985,10 @@
return rc;
}
- /* Now, interrupt mode asynchrous mailbox command */
+ /* Now, interrupt mode asynchronous mailbox command */
rc = lpfc_mbox_cmd_check(phba, mboxq);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"(%d):2543 Mailbox command x%x (x%x/x%x) "
"cannot issue Data: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
@@ -8825,7 +9056,7 @@
}
if (unlikely(phba->sli.mbox_active)) {
spin_unlock_irqrestore(&phba->hbalock, iflags);
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0384 There is pending active mailbox cmd\n");
return MBX_NOT_FINISHED;
}
@@ -8886,7 +9117,7 @@
/* Post the mailbox command to the port */
rc = lpfc_sli4_mq_put(phba->sli4_hba.mbx_wq, mqe);
if (rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"(%d):2533 Mailbox command x%x (x%x/x%x) "
"cannot issue Data: x%x x%x\n",
mboxq->vport ? mboxq->vport->vpi : 0,
@@ -8962,7 +9193,7 @@
phba->lpfc_sli_brdready = lpfc_sli_brdready_s4;
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1420 Invalid HBA PCI-device group: 0x%x\n",
dev_grp);
return -ENODEV;
@@ -8977,7 +9208,8 @@
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to address of newly added command iocb.
*
- * This function is called with hbalock held to add a command
+ * This function is called with hbalock held for SLI3 ports or
+ * the ring lock held for SLI4 ports to add a command
* iocb to the txq when SLI layer cannot submit the command iocb
* to the ring.
**/
@@ -8985,7 +9217,10 @@
__lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_iocbq *piocb)
{
- lockdep_assert_held(&phba->hbalock);
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ lockdep_assert_held(&pring->ring_lock);
+ else
+ lockdep_assert_held(&phba->hbalock);
/* Insert the caller's iocb in the txq tail for later processing. */
list_add_tail(&piocb->list, &pring->txq);
}
@@ -9059,8 +9294,7 @@
if (piocb->iocb_cmpl && (!piocb->vport) &&
(piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) &&
(piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) {
- lpfc_printf_log(phba, KERN_ERR,
- LOG_SLI | LOG_VPORT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1807 IOCB x%x failed. No vport\n",
piocb->iocb.ulpCommand);
dump_stack();
@@ -9113,7 +9347,7 @@
*/
if (piocb->iocb_cmpl)
piocb->iocb_cmpl = NULL;
- /*FALLTHROUGH*/
+ fallthrough;
case CMD_CREATE_XRI_CR:
case CMD_CLOSE_XRI_CN:
case CMD_CLOSE_XRI_CX:
@@ -9161,7 +9395,7 @@
/**
* lpfc_sli4_bpl2sgl - Convert the bpl/bde to a sgl.
* @phba: Pointer to HBA context object.
- * @piocb: Pointer to command iocb.
+ * @piocbq: Pointer to command iocb.
* @sglq: Pointer to the scatter gather queue object.
*
* This routine converts the bpl or bde that is in the IOCB
@@ -9269,7 +9503,7 @@
/**
* lpfc_sli_iocb2wqe - Convert the IOCB to a work queue entry.
* @phba: Pointer to HBA context object.
- * @piocb: Pointer to command iocb.
+ * @iocbq: Pointer to command iocb.
* @wqe: Pointer to the work queue entry.
*
* This routine converts the iocb command to its Work Queue Entry
@@ -9355,7 +9589,7 @@
else
ndlp = (struct lpfc_nodelist *)iocbq->context1;
if (!iocbq->iocb.ulpLe) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2007 Only Limited Edition cmd Format"
" supported 0x%x\n",
iocbq->iocb.ulpCommand);
@@ -9386,6 +9620,7 @@
if (if_type >= LPFC_SLI_INTF_IF_TYPE_2) {
if (pcmd && (*pcmd == ELS_CMD_FLOGI ||
*pcmd == ELS_CMD_SCR ||
+ *pcmd == ELS_CMD_RDF ||
*pcmd == ELS_CMD_RSCN_XMT ||
*pcmd == ELS_CMD_FDISC ||
*pcmd == ELS_CMD_LOGO ||
@@ -9426,7 +9661,7 @@
cmnd = CMD_XMIT_SEQUENCE64_CR;
if (phba->link_flag & LS_LOOPBACK_MODE)
bf_set(wqe_xo, &wqe->xmit_sequence.wge_ctl, 1);
- /* fall through */
+ fallthrough;
case CMD_XMIT_SEQUENCE64_CR:
/* word3 iocb=io_tag32 wqe=reserved */
wqe->xmit_sequence.rsvd3 = 0;
@@ -9662,7 +9897,7 @@
/* word6 context tag copied in memcpy */
if (iocbq->iocb.ulpCt_h || iocbq->iocb.ulpCt_l) {
ct = ((iocbq->iocb.ulpCt_h << 1) | iocbq->iocb.ulpCt_l);
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2015 Invalid CT %x command 0x%x\n",
ct, iocbq->iocb.ulpCommand);
return IOCB_ERROR;
@@ -9841,7 +10076,7 @@
case CMD_FCP_TRSP64_CX: /* Target mode rcv */
case CMD_FCP_AUTO_TRSP_CX: /* Auto target rsp */
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2014 Invalid command 0x%x\n",
iocbq->iocb.ulpCommand);
return IOCB_ERROR;
@@ -9876,7 +10111,7 @@
* __lpfc_sli_issue_iocb_s4 is used by other functions in the driver to issue
* an iocb command to an HBA with SLI-4 interface spec.
*
- * This function is called with hbalock held. The function will return success
+ * This function is called with ringlock held. The function will return success
* after it successfully submit the iocb to firmware or after adding to the
* txq.
**/
@@ -9962,7 +10197,7 @@
return 0;
}
-/**
+/*
* __lpfc_sli_issue_iocb - Wrapper func of lockless version for issuing iocb
*
* This routine wraps the actual lockless version for issusing IOCB function
@@ -10003,7 +10238,7 @@
phba->__lpfc_sli_release_iocbq = __lpfc_sli_release_iocbq_s4;
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1419 Invalid HBA PCI-device group: 0x%x\n",
dev_grp);
return -ENODEV;
@@ -10051,7 +10286,7 @@
/**
* lpfc_sli_issue_iocb - Wrapper function for __lpfc_sli_issue_iocb
* @phba: Pointer to HBA context object.
- * @pring: Pointer to driver SLI ring object.
+ * @ring_number: Ring number
* @piocb: Pointer to command iocb.
* @flag: Flag indicating if this command can be put into txq.
*
@@ -10137,6 +10372,32 @@
return 0;
}
+static void
+lpfc_sli_post_recovery_event(struct lpfc_hba *phba,
+ struct lpfc_nodelist *ndlp)
+{
+ unsigned long iflags;
+ struct lpfc_work_evt *evtp = &ndlp->recovery_evt;
+
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ if (!list_empty(&evtp->evt_listp)) {
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ return;
+ }
+
+ /* Incrementing the reference count until the queued work is done. */
+ evtp->evt_arg1 = lpfc_nlp_get(ndlp);
+ if (!evtp->evt_arg1) {
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ return;
+ }
+ evtp->evt = LPFC_EVT_RECOVER_PORT;
+ list_add_tail(&evtp->evt_listp, &phba->work_list);
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+
+ lpfc_worker_wake_up(phba);
+}
+
/* lpfc_sli_abts_err_handler - handle a failed ABTS request from an SLI3 port.
* @phba: Pointer to HBA context object.
* @iocbq: Pointer to iocb object.
@@ -10200,7 +10461,6 @@
struct lpfc_nodelist *ndlp,
struct sli4_wcqe_xri_aborted *axri)
{
- struct lpfc_vport *vport;
uint32_t ext_status = 0;
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
@@ -10210,7 +10470,6 @@
return;
}
- vport = ndlp->vport;
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
"3116 Port generated FCP XRI ABORT event on "
"vpi %d rpi %d xri x%x status 0x%x parameter x%x\n",
@@ -10227,7 +10486,7 @@
ext_status = axri->parameter & IOERR_PARAM_MASK;
if ((bf_get(lpfc_wcqe_xa_status, axri) == IOSTAT_LOCAL_REJECT) &&
((ext_status == IOERR_SEQUENCE_TIMEOUT) || (ext_status == 0)))
- lpfc_sli_abts_recover_port(vport, ndlp);
+ lpfc_sli_post_recovery_event(phba, ndlp);
}
/**
@@ -10263,13 +10522,13 @@
temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT;
if (evt_code == ASYNC_TEMP_WARN) {
temp_event_data.event_code = LPFC_THRESHOLD_TEMP;
- lpfc_printf_log(phba, KERN_ERR, LOG_TEMP,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0347 Adapter is very hot, please take "
"corrective action. temperature : %d Celsius\n",
(uint32_t) icmd->ulpContext);
} else {
temp_event_data.event_code = LPFC_NORMAL_TEMP;
- lpfc_printf_log(phba, KERN_ERR, LOG_TEMP,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0340 Adapter temperature is OK now. "
"temperature : %d Celsius\n",
(uint32_t) icmd->ulpContext);
@@ -10286,7 +10545,7 @@
break;
default:
iocb_w = (uint32_t *) icmd;
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0346 Ring %d handler: unexpected ASYNC_STATUS"
" evt_code 0x%x\n"
"W0 0x%08x W1 0x%08x W2 0x%08x W3 0x%08x\n"
@@ -10696,14 +10955,14 @@
set_bit(LPFC_DATA_READY, &phba->data_flags);
}
prev_pring_flag = pring->flag;
- spin_lock_irq(&pring->ring_lock);
+ spin_lock(&pring->ring_lock);
list_for_each_entry_safe(iocb, next_iocb,
&pring->txq, list) {
if (iocb->vport != vport)
continue;
list_move_tail(&iocb->list, &completions);
}
- spin_unlock_irq(&pring->ring_lock);
+ spin_unlock(&pring->ring_lock);
list_for_each_entry_safe(iocb, next_iocb,
&pring->txcmplq, list) {
if (iocb->vport != vport)
@@ -10960,7 +11219,7 @@
}
spin_unlock_irq(&phba->hbalock);
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0402 Cannot find virtual addr for buffer tag on "
"ring %d Data x%lx x%px x%px x%x\n",
pring->ringno, (unsigned long) tag,
@@ -11004,7 +11263,7 @@
}
spin_unlock_irq(&phba->hbalock);
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0410 Cannot find virtual addr for mapped buf on "
"ring %d Data x%llx x%px x%px x%x\n",
pring->ringno, (unsigned long long)phys,
@@ -11115,6 +11374,7 @@
* request, this function issues abort out unconditionally. This function is
* called with hbalock held. The function returns 0 when it fails due to
* memory allocation failure or when the command iocb is an abort request.
+ * The hbalock is asserted held in the code path calling this routine.
**/
static int
lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
@@ -11128,8 +11388,6 @@
unsigned long iflags;
struct lpfc_nodelist *ndlp;
- 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
@@ -11560,7 +11818,7 @@
* @pring: Pointer to driver SLI ring object.
* @tgt_id: SCSI ID of the target.
* @lun_id: LUN ID of the scsi device.
- * @taskmgmt_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST.
+ * @cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST.
*
* This function sends an abort command for every SCSI command
* associated with the given virtual port pending on the ring
@@ -11800,7 +12058,7 @@
/**
* lpfc_sli_issue_iocb_wait - Synchronous function to issue iocb commands
* @phba: Pointer to HBA context object..
- * @pring: Pointer to sli ring.
+ * @ring_number: Ring number
* @piocb: Pointer to command iocb.
* @prspiocbq: Pointer to response iocb.
* @timeout: Timeout in number of seconds.
@@ -11906,12 +12164,12 @@
* completed. Not that it completed successfully.
* */
} else if (timeleft == 0) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0338 IOCB wait timeout error - no "
"wake response Data x%x\n", timeout);
retval = IOCB_TIMEDOUT;
} else {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0330 IOCB wake NOT set, "
"Data x%x x%lx\n",
timeout, (timeleft / jiffies));
@@ -12020,6 +12278,7 @@
/**
* lpfc_sli_mbox_sys_shutdown - shutdown mailbox command sub-system
* @phba: Pointer to HBA context.
+ * @mbx_action: Mailbox shutdown options.
*
* This function is called to shutdown the driver's mailbox sub-system.
* It first marks the mailbox sub-system is in a block state to prevent
@@ -12154,6 +12413,7 @@
uint32_t uerr_sta_hi, uerr_sta_lo;
uint32_t if_type, portsmphr;
struct lpfc_register portstat_reg;
+ u32 logmask;
/*
* For now, use the SLI4 device internal unrecoverable error
@@ -12173,7 +12433,7 @@
}
if ((~phba->sli4_hba.ue_mask_lo & uerr_sta_lo) ||
(~phba->sli4_hba.ue_mask_hi & uerr_sta_hi)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1423 HBA Unrecoverable error: "
"uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, "
"ue_mask_lo_reg=0x%x, "
@@ -12204,7 +12464,12 @@
readl(phba->sli4_hba.u.if_type2.ERR1regaddr);
phba->work_status[1] =
readl(phba->sli4_hba.u.if_type2.ERR2regaddr);
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ logmask = LOG_TRACE_EVENT;
+ if (phba->work_status[0] ==
+ SLIPORT_ERR1_REG_ERR_CODE_2 &&
+ phba->work_status[1] == SLIPORT_ERR2_REG_FW_RESTART)
+ logmask = LOG_SLI;
+ lpfc_printf_log(phba, KERN_ERR, logmask,
"2885 Port Status Event: "
"port status reg 0x%x, "
"port smphr reg 0x%x, "
@@ -12220,7 +12485,7 @@
break;
case LPFC_SLI_INTF_IF_TYPE_1:
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2886 HBA Error Attention on unsupported "
"if type %d.", if_type);
return 1;
@@ -12284,7 +12549,7 @@
ha_copy = lpfc_sli4_eratt_read(phba);
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0299 Invalid SLI revision (%d)\n",
phba->sli_rev);
ha_copy = 0;
@@ -12517,8 +12782,7 @@
* Stray Mailbox Interrupt, mbxCommand <cmd>
* mbxStatus <status>
*/
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX |
- LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"(%d):0304 Stray Mailbox "
"Interrupt mbxCommand x%x "
"mbxStatus x%x\n",
@@ -12578,7 +12842,7 @@
if (rc != MBX_BUSY)
lpfc_printf_log(phba,
KERN_ERR,
- LOG_MBOX | LOG_SLI,
+ LOG_TRACE_EVENT,
"0350 rc should have"
"been MBX_BUSY\n");
if (rc != MBX_NOT_FINISHED)
@@ -12607,8 +12871,9 @@
MBX_NOWAIT);
} while (rc == MBX_NOT_FINISHED);
if (rc != MBX_SUCCESS)
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX |
- LOG_SLI, "0349 rc should be "
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
+ "0349 rc should be "
"MBX_SUCCESS\n");
}
@@ -12842,23 +13107,30 @@
void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba)
{
struct lpfc_cq_event *cq_event;
+ unsigned long iflags;
/* First, declare the els xri abort event has been handled */
- spin_lock_irq(&phba->hbalock);
+ spin_lock_irqsave(&phba->hbalock, iflags);
phba->hba_flag &= ~ELS_XRI_ABORT_EVENT;
- spin_unlock_irq(&phba->hbalock);
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+
/* Now, handle all the els xri abort events */
+ spin_lock_irqsave(&phba->sli4_hba.els_xri_abrt_list_lock, iflags);
while (!list_empty(&phba->sli4_hba.sp_els_xri_aborted_work_queue)) {
/* Get the first event from the head of the event queue */
- spin_lock_irq(&phba->hbalock);
list_remove_head(&phba->sli4_hba.sp_els_xri_aborted_work_queue,
cq_event, struct lpfc_cq_event, list);
- spin_unlock_irq(&phba->hbalock);
+ spin_unlock_irqrestore(&phba->sli4_hba.els_xri_abrt_list_lock,
+ iflags);
/* Notify aborted XRI for ELS work queue */
lpfc_sli4_els_xri_aborted(phba, &cq_event->cqe.wcqe_axri);
+
/* Free the event processed back to the free pool */
lpfc_sli4_cq_event_release(phba, cq_event);
+ spin_lock_irqsave(&phba->sli4_hba.els_xri_abrt_list_lock,
+ iflags);
}
+ spin_unlock_irqrestore(&phba->sli4_hba.els_xri_abrt_list_lock, iflags);
}
/**
@@ -12980,7 +13252,7 @@
/**
* lpfc_sli4_els_wcqe_to_rspiocbq - Get response iocbq from els wcqe
* @phba: Pointer to HBA context object.
- * @wcqe: Pointer to work-queue completion queue entry.
+ * @irspiocbq: Pointer to work-queue completion queue entry.
*
* This routine handles an ELS work-queue completion event and construct
* a pseudo response ELS IODBQ from the SLI4 ELS WCQE for the common
@@ -13035,7 +13307,7 @@
/* Allocate a new internal CQ_EVENT entry */
cq_event = lpfc_sli4_cq_event_alloc(phba);
if (!cq_event) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0602 Failed to alloc CQ_EVENT entry\n");
return NULL;
}
@@ -13046,11 +13318,11 @@
}
/**
- * lpfc_sli4_sp_handle_async_event - Handle an asynchroous event
+ * lpfc_sli4_sp_handle_async_event - Handle an asynchronous event
* @phba: Pointer to HBA context object.
- * @cqe: Pointer to mailbox completion queue entry.
+ * @mcqe: Pointer to mailbox completion queue entry.
*
- * This routine process a mailbox completion queue entry with asynchrous
+ * This routine process a mailbox completion queue entry with asynchronous
* event.
*
* Return: true if work posted to worker thread, otherwise false.
@@ -13069,9 +13341,13 @@
cq_event = lpfc_cq_event_setup(phba, mcqe, sizeof(struct lpfc_mcqe));
if (!cq_event)
return false;
- spin_lock_irqsave(&phba->hbalock, iflags);
+
+ spin_lock_irqsave(&phba->sli4_hba.asynce_list_lock, iflags);
list_add_tail(&cq_event->list, &phba->sli4_hba.sp_asynce_work_queue);
+ spin_unlock_irqrestore(&phba->sli4_hba.asynce_list_lock, iflags);
+
/* Set the async event flag */
+ spin_lock_irqsave(&phba->hbalock, iflags);
phba->hba_flag |= ASYNC_EVENT;
spin_unlock_irqrestore(&phba->hbalock, iflags);
@@ -13081,7 +13357,7 @@
/**
* lpfc_sli4_sp_handle_mbox_event - Handle a mailbox completion event
* @phba: Pointer to HBA context object.
- * @cqe: Pointer to mailbox completion queue entry.
+ * @mcqe: Pointer to mailbox completion queue entry.
*
* This routine process a mailbox completion queue entry with mailbox
* completion event.
@@ -13110,7 +13386,7 @@
spin_lock_irqsave(&phba->hbalock, iflags);
pmb = phba->sli.mbox_active;
if (unlikely(!pmb)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1832 No pending MBOX command to handle\n");
spin_unlock_irqrestore(&phba->hbalock, iflags);
goto out_no_mqe_complete;
@@ -13159,8 +13435,9 @@
pmb->vport = vport;
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
if (rc != MBX_BUSY)
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX |
- LOG_SLI, "0385 rc should "
+ lpfc_printf_log(phba, KERN_ERR,
+ LOG_TRACE_EVENT,
+ "0385 rc should "
"have been MBX_BUSY\n");
if (rc != MBX_NOT_FINISHED)
goto send_current_mbox;
@@ -13201,10 +13478,11 @@
/**
* lpfc_sli4_sp_handle_mcqe - Process a mailbox completion queue entry
* @phba: Pointer to HBA context object.
+ * @cq: Pointer to associated CQ
* @cqe: Pointer to mailbox completion queue entry.
*
* This routine process a mailbox completion queue entry, it invokes the
- * proper mailbox complete handling or asynchrous event handling routine
+ * proper mailbox complete handling or asynchronous event handling routine
* according to the MCQE's async bit.
*
* Return: true if work posted to worker thread, otherwise false.
@@ -13248,7 +13526,6 @@
struct lpfc_sli_ring *pring = cq->pring;
int txq_cnt = 0;
int txcmplq_cnt = 0;
- int fcp_txcmplq_cnt = 0;
/* Check for response status */
if (unlikely(bf_get(lpfc_wcqe_c_status, wcqe))) {
@@ -13268,11 +13545,10 @@
txq_cnt++;
if (!list_empty(&pring->txcmplq))
txcmplq_cnt++;
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0387 NO IOCBQ data: txq_cnt=%d iocb_cnt=%d "
- "fcp_txcmplq_cnt=%d, els_txcmplq_cnt=%d\n",
+ "els_txcmplq_cnt=%d\n",
txq_cnt, phba->iocb_cnt,
- fcp_txcmplq_cnt,
txcmplq_cnt);
return false;
}
@@ -13346,21 +13622,24 @@
break;
case LPFC_NVME_LS: /* NVME LS uses ELS resources */
case LPFC_ELS:
- cq_event = lpfc_cq_event_setup(
- phba, wcqe, sizeof(struct sli4_wcqe_xri_aborted));
- if (!cq_event)
- return false;
+ cq_event = lpfc_cq_event_setup(phba, wcqe, sizeof(*wcqe));
+ if (!cq_event) {
+ workposted = false;
+ break;
+ }
cq_event->hdwq = cq->hdwq;
- spin_lock_irqsave(&phba->hbalock, iflags);
+ spin_lock_irqsave(&phba->sli4_hba.els_xri_abrt_list_lock,
+ iflags);
list_add_tail(&cq_event->list,
&phba->sli4_hba.sp_els_xri_aborted_work_queue);
/* Set the els xri abort event flag */
phba->hba_flag |= ELS_XRI_ABORT_EVENT;
- spin_unlock_irqrestore(&phba->hbalock, iflags);
+ spin_unlock_irqrestore(&phba->sli4_hba.els_xri_abrt_list_lock,
+ iflags);
workposted = true;
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0603 Invalid CQ subtype %d: "
"%08x %08x %08x %08x\n",
cq->subtype, wcqe->word0, wcqe->parameter,
@@ -13408,9 +13687,9 @@
status = bf_get(lpfc_rcqe_status, rcqe);
switch (status) {
case FC_STATUS_RQ_BUF_LEN_EXCEEDED:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2537 Receive Frame Truncated!!\n");
- /* fall through */
+ fallthrough;
case FC_STATUS_RQ_SUCCESS:
spin_lock_irqsave(&phba->hbalock, iflags);
lpfc_sli4_rq_release(hrq, drq);
@@ -13430,7 +13709,11 @@
fc_hdr->fh_r_ctl == FC_RCTL_DD_UNSOL_DATA) {
spin_unlock_irqrestore(&phba->hbalock, iflags);
/* Handle MDS Loopback frames */
- lpfc_sli4_handle_mds_loopback(phba->pport, dma_buf);
+ if (!(phba->pport->load_flag & FC_UNLOADING))
+ lpfc_sli4_handle_mds_loopback(phba->pport,
+ dma_buf);
+ else
+ lpfc_in_buf_free(phba, &dma_buf->dbuf);
break;
}
@@ -13445,7 +13728,7 @@
case FC_STATUS_INSUFF_BUF_FRM_DISC:
if (phba->nvmet_support) {
tgtp = phba->targetport->private;
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_NVME,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6402 RQE Error x%x, posted %d err_cnt "
"%d: %x %x %x\n",
status, hrq->RQ_buf_posted,
@@ -13454,7 +13737,7 @@
atomic_read(&tgtp->rcv_fcp_cmd_out),
atomic_read(&tgtp->xmt_fcp_release));
}
- /* fallthrough */
+ fallthrough;
case FC_STATUS_INSUFF_BUF_NEED_BUF:
hrq->RQ_no_posted_buf++;
@@ -13517,7 +13800,7 @@
(struct lpfc_rcqe *)&cqevt);
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0388 Not a valid WCQE code: x%x\n",
bf_get(lpfc_cqe_code, &cqevt));
break;
@@ -13529,6 +13812,7 @@
* lpfc_sli4_sp_handle_eqe - Process a slow-path event queue entry
* @phba: Pointer to HBA context object.
* @eqe: Pointer to fast-path event queue entry.
+ * @speq: Pointer to slow-path event queue.
*
* This routine process a event queue entry from the slow-path event queue.
* It will check the MajorCode and MinorCode to determine this is for a
@@ -13544,6 +13828,7 @@
{
struct lpfc_queue *cq = NULL, *childq;
uint16_t cqid;
+ int ret = 0;
/* Get the reference to the corresponding CQ */
cqid = bf_get_le32(lpfc_eqe_resource_id, eqe);
@@ -13556,7 +13841,7 @@
}
if (unlikely(!cq)) {
if (phba->sli.sli_flag & LPFC_SLI_ACTIVE)
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0365 Slow-path CQ identifier "
"(%d) does not exist\n", cqid);
return;
@@ -13565,9 +13850,14 @@
/* Save EQ associated with this CQ */
cq->assoc_qp = speq;
- if (!queue_work_on(cq->chann, phba->wq, &cq->spwork))
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "0390 Cannot schedule soft IRQ "
+ if (is_kdump_kernel())
+ ret = queue_work(phba->wq, &cq->spwork);
+ else
+ ret = queue_work_on(cq->chann, phba->wq, &cq->spwork);
+
+ if (!ret)
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0390 Cannot schedule queue work "
"for CQ eqcqid=%d, cqid=%d on CPU %d\n",
cqid, cq->queue_id, raw_smp_processor_id());
}
@@ -13578,6 +13868,7 @@
* @cq: Pointer to CQ to be processed
* @handler: Routine to process each cqe
* @delay: Pointer to usdelay to set in case of rescheduling of the handler
+ * @poll_mode: Polling mode we were called from
*
* This routine processes completion queue entries in a CQ. While a valid
* queue element is found, the handler is called. During processing checks
@@ -13595,7 +13886,8 @@
static bool
__lpfc_sli4_process_cq(struct lpfc_hba *phba, struct lpfc_queue *cq,
bool (*handler)(struct lpfc_hba *, struct lpfc_queue *,
- struct lpfc_cqe *), unsigned long *delay)
+ struct lpfc_cqe *), unsigned long *delay,
+ enum lpfc_poll_mode poll_mode)
{
struct lpfc_cqe *cqe;
bool workposted = false;
@@ -13623,6 +13915,7 @@
phba->sli4_hba.sli4_write_cq_db(phba, cq, consumed,
LPFC_QUEUE_NOARM);
consumed = 0;
+ cq->assoc_qp->q_flag |= HBA_EQ_DELAY_CHK;
}
if (count == LPFC_NVMET_CQ_NOTIFY)
@@ -13635,6 +13928,10 @@
arm = false;
}
+ /* Note: complete the irq_poll softirq before rearming CQ */
+ if (poll_mode == LPFC_IRQ_POLL)
+ irq_poll_complete(&cq->iop);
+
/* Track the max number of CQEs processed in 1 EQ */
if (count > cq->CQ_max_cqe)
cq->CQ_max_cqe = count;
@@ -13647,7 +13944,7 @@
"0369 No entry from completion queue "
"qid=%d\n", cq->queue_id);
- cq->queue_claimed = 0;
+ xchg(&cq->queue_claimed, 0);
rearm_and_exit:
phba->sli4_hba.sli4_write_cq_db(phba, cq, consumed,
@@ -13677,36 +13974,42 @@
struct lpfc_hba *phba = cq->phba;
unsigned long delay;
bool workposted = false;
+ int ret = 0;
/* Process and rearm the CQ */
switch (cq->type) {
case LPFC_MCQ:
workposted |= __lpfc_sli4_process_cq(phba, cq,
lpfc_sli4_sp_handle_mcqe,
- &delay);
+ &delay, LPFC_QUEUE_WORK);
break;
case LPFC_WCQ:
if (cq->subtype == LPFC_IO)
workposted |= __lpfc_sli4_process_cq(phba, cq,
lpfc_sli4_fp_handle_cqe,
- &delay);
+ &delay, LPFC_QUEUE_WORK);
else
workposted |= __lpfc_sli4_process_cq(phba, cq,
lpfc_sli4_sp_handle_cqe,
- &delay);
+ &delay, LPFC_QUEUE_WORK);
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0370 Invalid completion queue type (%d)\n",
cq->type);
return;
}
if (delay) {
- if (!queue_delayed_work_on(cq->chann, phba->wq,
- &cq->sched_spwork, delay))
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "0394 Cannot schedule soft IRQ "
+ if (is_kdump_kernel())
+ ret = queue_delayed_work(phba->wq, &cq->sched_spwork,
+ delay);
+ else
+ ret = queue_delayed_work_on(cq->chann, phba->wq,
+ &cq->sched_spwork, delay);
+ if (!ret)
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0394 Cannot schedule queue work "
"for cqid=%d on CPU %d\n",
cq->queue_id, cq->chann);
}
@@ -13775,9 +14078,9 @@
IOERR_NO_RESOURCES))
phba->lpfc_rampdown_queue_depth(phba);
- /* Log the error status */
+ /* Log the cmpl status */
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- "0373 FCP CQE error: status=x%x: "
+ "0373 FCP CQE cmpl: status=x%x: "
"CQE: %08x %08x %08x %08x\n",
bf_get(lpfc_wcqe_c_status, wcqe),
wcqe->word0, wcqe->total_data_placed,
@@ -13871,6 +14174,7 @@
/**
* lpfc_sli4_nvmet_handle_rcqe - Process a receive-queue completion queue entry
* @phba: Pointer to HBA context object.
+ * @cq: Pointer to completion queue.
* @rcqe: Pointer to receive-queue completion queue entry.
*
* This routine process a receive-queue completion queue entry.
@@ -13915,9 +14219,9 @@
status = bf_get(lpfc_rcqe_status, rcqe);
switch (status) {
case FC_STATUS_RQ_BUF_LEN_EXCEEDED:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6126 Receive Frame Truncated!!\n");
- /* fall through */
+ fallthrough;
case FC_STATUS_RQ_SUCCESS:
spin_lock_irqsave(&phba->hbalock, iflags);
lpfc_sli4_rq_release(hrq, drq);
@@ -13934,8 +14238,8 @@
/* Just some basic sanity checks on FCP Command frame */
fctl = (fc_hdr->fh_f_ctl[0] << 16 |
- fc_hdr->fh_f_ctl[1] << 8 |
- fc_hdr->fh_f_ctl[2]);
+ fc_hdr->fh_f_ctl[1] << 8 |
+ fc_hdr->fh_f_ctl[2]);
if (((fctl &
(FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT)) !=
(FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT)) ||
@@ -13955,7 +14259,7 @@
case FC_STATUS_INSUFF_BUF_FRM_DISC:
if (phba->nvmet_support) {
tgtp = phba->targetport->private;
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_NVME,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6401 RQE Error x%x, posted %d err_cnt "
"%d: %x %x %x\n",
status, hrq->RQ_buf_posted,
@@ -13964,7 +14268,7 @@
atomic_read(&tgtp->rcv_fcp_cmd_out),
atomic_read(&tgtp->xmt_fcp_release));
}
- /* fallthrough */
+ fallthrough;
case FC_STATUS_INSUFF_BUF_NEED_BUF:
hrq->RQ_no_posted_buf++;
@@ -13979,7 +14283,7 @@
* lpfc_sli4_fp_handle_cqe - Process fast-path work queue completion entry
* @phba: adapter with cq
* @cq: Pointer to the completion queue.
- * @eqe: Pointer to fast-path completion queue entry.
+ * @cqe: Pointer to fast-path completion queue entry.
*
* This routine process a fast-path work queue completion entry from fast-path
* event queue for FCP command response completion.
@@ -14029,7 +14333,7 @@
}
break;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0144 Not a valid CQE code: x%x\n",
bf_get(lpfc_wcqe_c_code, &wcqe));
break;
@@ -14038,8 +14342,47 @@
}
/**
+ * lpfc_sli4_sched_cq_work - Schedules cq work
+ * @phba: Pointer to HBA context object.
+ * @cq: Pointer to CQ
+ * @cqid: CQ ID
+ *
+ * This routine checks the poll mode of the CQ corresponding to
+ * cq->chann, then either schedules a softirq or queue_work to complete
+ * cq work.
+ *
+ * queue_work path is taken if in NVMET mode, or if poll_mode is in
+ * LPFC_QUEUE_WORK mode. Otherwise, softirq path is taken.
+ *
+ **/
+static void lpfc_sli4_sched_cq_work(struct lpfc_hba *phba,
+ struct lpfc_queue *cq, uint16_t cqid)
+{
+ int ret = 0;
+
+ switch (cq->poll_mode) {
+ case LPFC_IRQ_POLL:
+ irq_poll_sched(&cq->iop);
+ break;
+ case LPFC_QUEUE_WORK:
+ default:
+ if (is_kdump_kernel())
+ ret = queue_work(phba->wq, &cq->irqwork);
+ else
+ ret = queue_work_on(cq->chann, phba->wq, &cq->irqwork);
+ if (!ret)
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0383 Cannot schedule queue work "
+ "for CQ eqcqid=%d, cqid=%d on CPU %d\n",
+ cqid, cq->queue_id,
+ raw_smp_processor_id());
+ }
+}
+
+/**
* lpfc_sli4_hba_handle_eqe - Process a fast-path event queue entry
* @phba: Pointer to HBA context object.
+ * @eq: Pointer to the queue structure.
* @eqe: Pointer to fast-path event queue entry.
*
* This routine process a event queue entry from the fast-path event queue.
@@ -14058,7 +14401,7 @@
uint16_t cqid, id;
if (unlikely(bf_get_le32(lpfc_eqe_major_code, eqe) != 0)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0366 Not a valid completion "
"event: majorcode=x%x, minorcode=x%x\n",
bf_get_le32(lpfc_eqe_major_code, eqe),
@@ -14101,7 +14444,7 @@
process_cq:
if (unlikely(cqid != cq->queue_id)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0368 Miss-matched fast-path completion "
"queue identifier: eqcqid=%d, fcpcqid=%d\n",
cqid, cq->queue_id);
@@ -14115,16 +14458,13 @@
else
cq->isr_timestamp = 0;
#endif
- if (!queue_work_on(cq->chann, phba->wq, &cq->irqwork))
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "0363 Cannot schedule soft IRQ "
- "for CQ eqcqid=%d, cqid=%d on CPU %d\n",
- cqid, cq->queue_id, raw_smp_processor_id());
+ lpfc_sli4_sched_cq_work(phba, cq, cqid);
}
/**
* __lpfc_sli4_hba_process_cq - Process a fast-path event queue entry
* @cq: Pointer to CQ to be processed
+ * @poll_mode: Enum lpfc_poll_state to determine poll mode
*
* This routine calls the cq processing routine with the handler for
* fast path CQEs.
@@ -14138,23 +14478,30 @@
* the delay indicates when to reschedule it.
**/
static void
-__lpfc_sli4_hba_process_cq(struct lpfc_queue *cq)
+__lpfc_sli4_hba_process_cq(struct lpfc_queue *cq,
+ enum lpfc_poll_mode poll_mode)
{
struct lpfc_hba *phba = cq->phba;
unsigned long delay;
bool workposted = false;
+ int ret = 0;
/* process and rearm the CQ */
workposted |= __lpfc_sli4_process_cq(phba, cq, lpfc_sli4_fp_handle_cqe,
- &delay);
+ &delay, poll_mode);
if (delay) {
- if (!queue_delayed_work_on(cq->chann, phba->wq,
- &cq->sched_irqwork, delay))
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "0367 Cannot schedule soft IRQ "
- "for cqid=%d on CPU %d\n",
- cq->queue_id, cq->chann);
+ if (is_kdump_kernel())
+ ret = queue_delayed_work(phba->wq, &cq->sched_irqwork,
+ delay);
+ else
+ ret = queue_delayed_work_on(cq->chann, phba->wq,
+ &cq->sched_irqwork, delay);
+ if (!ret)
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0367 Cannot schedule queue work "
+ "for cqid=%d on CPU %d\n",
+ cq->queue_id, cq->chann);
}
/* wake up worker thread if there are works to be done */
@@ -14174,7 +14521,7 @@
{
struct lpfc_queue *cq = container_of(work, struct lpfc_queue, irqwork);
- __lpfc_sli4_hba_process_cq(cq);
+ __lpfc_sli4_hba_process_cq(cq, LPFC_QUEUE_WORK);
}
/**
@@ -14189,7 +14536,7 @@
struct lpfc_queue *cq = container_of(to_delayed_work(work),
struct lpfc_queue, sched_irqwork);
- __lpfc_sli4_hba_process_cq(cq);
+ __lpfc_sli4_hba_process_cq(cq, LPFC_QUEUE_WORK);
}
/**
@@ -14228,7 +14575,6 @@
int ecount = 0;
int hba_eqidx;
struct lpfc_eq_intr_info *eqi;
- uint32_t icnt;
/* Get the driver's phba structure from the dev_id */
hba_eq_hdl = (struct lpfc_hba_eq_hdl *)dev_id;
@@ -14251,17 +14597,18 @@
spin_lock_irqsave(&phba->hbalock, iflag);
if (phba->link_state < LPFC_LINK_DOWN)
/* Flush, clear interrupt, and rearm the EQ */
- lpfc_sli4_eq_flush(phba, fpeq);
+ lpfc_sli4_eqcq_flush(phba, fpeq);
spin_unlock_irqrestore(&phba->hbalock, iflag);
return IRQ_NONE;
}
- eqi = phba->sli4_hba.eq_info;
- icnt = this_cpu_inc_return(eqi->icnt);
+ eqi = this_cpu_ptr(phba->sli4_hba.eq_info);
+ eqi->icnt++;
+
fpeq->last_cpu = raw_smp_processor_id();
- if (icnt > LPFC_EQD_ISR_TRIGGER &&
- phba->cfg_irq_chann == 1 &&
+ if (eqi->icnt > LPFC_EQD_ISR_TRIGGER &&
+ fpeq->q_flag & HBA_EQ_DELAY_CHK &&
phba->cfg_auto_imax &&
fpeq->q_mode != LPFC_MAX_AUTO_EQ_DELAY &&
phba->sli.sli_flag & LPFC_SLI_USE_EQDR)
@@ -14376,12 +14723,10 @@
{
struct lpfc_hba *phba = eq->phba;
- if (list_empty(&phba->poll_list)) {
- timer_setup(&phba->cpuhp_poll_timer, lpfc_sli4_poll_hbtimer, 0);
- /* kickstart slowpath processing for this eq */
+ /* kickstart slowpath processing if needed */
+ if (list_empty(&phba->poll_list))
mod_timer(&phba->cpuhp_poll_timer,
jiffies + msecs_to_jiffies(LPFC_POLL_HB));
- }
list_add_rcu(&eq->_poll_list, &phba->poll_list);
synchronize_rcu();
@@ -14512,7 +14857,7 @@
* @phba: The HBA that this queue is being created on.
* @page_size: The size of a queue page
* @entry_size: The size of each queue entry for this queue.
- * @entry count: The number of entries that this queue will handle.
+ * @entry_count: The number of entries that this queue will handle.
* @cpu: The cpu that will primarily utilize this queue.
*
* This function allocates a queue structure and the DMAable memory used for
@@ -14684,7 +15029,7 @@
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_FCP | LOG_NVME,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6428 Failed allocating mailbox cmd buffer."
" EQ delay was not set.\n");
return;
@@ -14726,7 +15071,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2512 MODIFY_EQ_DELAY mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -14803,14 +15148,14 @@
dmult);
switch (eq->entry_count) {
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0360 Unsupported EQ count. (%d)\n",
eq->entry_count);
if (eq->entry_count < 256) {
status = -EINVAL;
goto out;
}
- /* fall through - otherwise default to smallest count */
+ fallthrough; /* otherwise default to smallest count */
case 256:
bf_set(lpfc_eq_context_count, &eq_create->u.request.context,
LPFC_EQ_CNT_256);
@@ -14847,7 +15192,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2500 EQ_CREATE mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -14866,11 +15211,22 @@
return status;
}
+static int lpfc_cq_poll_hdler(struct irq_poll *iop, int budget)
+{
+ struct lpfc_queue *cq = container_of(iop, struct lpfc_queue, iop);
+
+ __lpfc_sli4_hba_process_cq(cq, LPFC_IRQ_POLL);
+
+ return 1;
+}
+
/**
* lpfc_cq_create - Create a Completion Queue on the HBA
* @phba: HBA structure that indicates port to create a queue on.
* @cq: The queue structure to use to create the completion queue.
* @eq: The event queue to bind this completion queue to.
+ * @type: Type of queue (EQ, GCQ, MCQ, WCQ, etc).
+ * @subtype: Functional purpose of the queue (MBOX, IO, ELS, NVMET, etc).
*
* This function creates a completion queue, as detailed in @wq, on a port,
* described by @phba by sending a CQ_CREATE mailbox command to the HBA.
@@ -14941,9 +15297,9 @@
LPFC_CQ_CNT_WORD7);
break;
}
- /* fall through */
+ fallthrough;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0361 Unsupported CQ count: "
"entry cnt %d sz %d pg cnt %d\n",
cq->entry_count, cq->entry_size,
@@ -14952,7 +15308,7 @@
status = -EINVAL;
goto out;
}
- /* fall through - otherwise default to smallest count */
+ fallthrough; /* otherwise default to smallest count */
case 256:
bf_set(lpfc_cq_context_count, &cq_create->u.request.context,
LPFC_CQ_CNT_256);
@@ -14979,7 +15335,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2501 CQ_CREATE mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -15005,6 +15361,8 @@
if (cq->queue_id > phba->sli4_hba.cq_max)
phba->sli4_hba.cq_max = cq->queue_id;
+
+ irq_poll_init(&cq->iop, LPFC_IRQ_POLL_WEIGHT, lpfc_cq_poll_hdler);
out:
mempool_free(mbox, phba->mbox_mem_pool);
return status;
@@ -15015,6 +15373,8 @@
* @phba: HBA structure that indicates port to create a queue on.
* @cqp: The queue structure array to use to create the completion queues.
* @hdwq: The hardware queue array with the EQ to bind completion queues to.
+ * @type: Type of queue (EQ, GCQ, MCQ, WCQ, etc).
+ * @subtype: Functional purpose of the queue (MBOX, IO, ELS, NVMET, etc).
*
* This function creates a set of completion queue, s to support MRQ
* as detailed in @cqp, on a port,
@@ -15064,7 +15424,7 @@
LPFC_MBOX_OPCODE_FCOE_CQ_CREATE_SET, length,
LPFC_SLI4_MBX_NEMBED);
if (alloclen < length) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3098 Allocated DMA memory size (%d) is "
"less than the requested DMA memory size "
"(%d)\n", alloclen, length);
@@ -15116,16 +15476,16 @@
LPFC_CQ_CNT_WORD7);
break;
}
- /* fall through */
+ fallthrough;
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3118 Bad CQ count. (%d)\n",
cq->entry_count);
if (cq->entry_count < 256) {
status = -EINVAL;
goto out;
}
- /* fall through - otherwise default to smallest */
+ fallthrough; /* otherwise default to smallest */
case 256:
bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
&cq_set->u.request, LPFC_CQ_CNT_256);
@@ -15236,7 +15596,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3119 CQ_CREATE_SET mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -15394,14 +15754,14 @@
cq->queue_id);
switch (mq->entry_count) {
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0362 Unsupported MQ count. (%d)\n",
mq->entry_count);
if (mq->entry_count < 16) {
status = -EINVAL;
goto out;
}
- /* fall through - otherwise default to smallest count */
+ fallthrough; /* otherwise default to smallest count */
case 16:
bf_set(lpfc_mq_context_ring_size,
&mq_create_ext->u.request.context,
@@ -15450,7 +15810,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2502 MQ_CREATE mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -15513,8 +15873,10 @@
uint16_t pci_barset;
uint8_t dpp_barset;
uint32_t dpp_offset;
- unsigned long pg_addr;
uint8_t wq_create_version;
+#ifdef CONFIG_X86
+ unsigned long pg_addr;
+#endif
/* sanity check on queue memory */
if (!wq || !cq)
@@ -15599,7 +15961,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2503 WQ_CREATE mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -15626,7 +15988,7 @@
&wq_create->u.response);
if ((wq->db_format != LPFC_DB_LIST_FORMAT) &&
(wq->db_format != LPFC_DB_RING_FORMAT)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3265 WQ[%d] doorbell format "
"not supported: x%x\n",
wq->queue_id, wq->db_format);
@@ -15638,7 +16000,7 @@
bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba,
pci_barset);
if (!bar_memmap_p) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3263 WQ[%d] failed to memmap "
"pci barset:x%x\n",
wq->queue_id, pci_barset);
@@ -15648,7 +16010,7 @@
db_offset = wq_create->u.response.doorbell_offset;
if ((db_offset != LPFC_ULP0_WQ_DOORBELL) &&
(db_offset != LPFC_ULP1_WQ_DOORBELL)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3252 WQ[%d] doorbell offset "
"not supported: x%x\n",
wq->queue_id, db_offset);
@@ -15672,7 +16034,7 @@
bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba,
pci_barset);
if (!bar_memmap_p) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3267 WQ[%d] failed to memmap "
"pci barset:x%x\n",
wq->queue_id, pci_barset);
@@ -15688,7 +16050,7 @@
bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba,
dpp_barset);
if (!bar_memmap_p) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3268 WQ[%d] failed to memmap "
"pci barset:x%x\n",
wq->queue_id, dpp_barset);
@@ -15704,9 +16066,9 @@
wq->queue_id, pci_barset, db_offset,
wq->dpp_id, dpp_barset, dpp_offset);
+#ifdef CONFIG_X86
/* Enable combined writes for DPP aperture */
pg_addr = (unsigned long)(wq->dpp_regaddr) & PAGE_MASK;
-#ifdef CONFIG_X86
rc = set_memory_wc(pg_addr, 1);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -15746,6 +16108,7 @@
* @hrq: The queue structure to use to create the header receive queue.
* @drq: The queue structure to use to create the data receive queue.
* @cq: The completion queue to bind this work queue to.
+ * @subtype: The subtype of the work queue indicating its functionality.
*
* This function creates a receive buffer queue pair , as detailed in @hrq and
* @drq, on a port, described by @phba by sending a RQ_CREATE mailbox command
@@ -15812,14 +16175,14 @@
} else {
switch (hrq->entry_count) {
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2535 Unsupported RQ count. (%d)\n",
hrq->entry_count);
if (hrq->entry_count < 512) {
status = -EINVAL;
goto out;
}
- /* fall through - otherwise default to smallest count */
+ fallthrough; /* otherwise default to smallest count */
case 512:
bf_set(lpfc_rq_context_rqe_count,
&rq_create->u.request.context,
@@ -15863,7 +16226,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2504 RQ_CREATE mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -15881,7 +16244,7 @@
&rq_create->u.response);
if ((hrq->db_format != LPFC_DB_LIST_FORMAT) &&
(hrq->db_format != LPFC_DB_RING_FORMAT)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3262 RQ [%d] doorbell format not "
"supported: x%x\n", hrq->queue_id,
hrq->db_format);
@@ -15893,7 +16256,7 @@
&rq_create->u.response);
bar_memmap_p = lpfc_dual_chute_pci_bar_map(phba, pci_barset);
if (!bar_memmap_p) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3269 RQ[%d] failed to memmap pci "
"barset:x%x\n", hrq->queue_id,
pci_barset);
@@ -15904,7 +16267,7 @@
db_offset = rq_create->u.response.doorbell_offset;
if ((db_offset != LPFC_ULP0_RQ_DOORBELL) &&
(db_offset != LPFC_ULP1_RQ_DOORBELL)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3270 RQ[%d] doorbell offset not "
"supported: x%x\n", hrq->queue_id,
db_offset);
@@ -15949,14 +16312,14 @@
} else {
switch (drq->entry_count) {
default:
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2536 Unsupported RQ count. (%d)\n",
drq->entry_count);
if (drq->entry_count < 512) {
status = -EINVAL;
goto out;
}
- /* fall through - otherwise default to smallest count */
+ fallthrough; /* otherwise default to smallest count */
case 512:
bf_set(lpfc_rq_context_rqe_count,
&rq_create->u.request.context,
@@ -16035,6 +16398,7 @@
* @hrqp: The queue structure array to use to create the header receive queues.
* @drqp: The queue structure array to use to create the data receive queues.
* @cqp: The completion queue array to bind these receive queues to.
+ * @subtype: Functional purpose of the queue (MBOX, IO, ELS, NVMET, etc).
*
* This function creates a receive buffer queue pair , as detailed in @hrq and
* @drq, on a port, described by @phba by sending a RQ_CREATE mailbox command
@@ -16086,7 +16450,7 @@
LPFC_MBOX_OPCODE_FCOE_RQ_CREATE, length,
LPFC_SLI4_MBX_NEMBED);
if (alloclen < length) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3099 Allocated DMA memory size (%d) is "
"less than the requested DMA memory size "
"(%d)\n", alloclen, length);
@@ -16196,7 +16560,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3120 RQ_CREATE mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -16224,6 +16588,7 @@
/**
* lpfc_eq_destroy - Destroy an event Queue on the HBA
+ * @phba: HBA structure that indicates port to destroy a queue on.
* @eq: The queue structure associated with the queue to destroy.
*
* This function destroys a queue, as detailed in @eq by sending an mailbox
@@ -16266,7 +16631,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2505 EQ_DESTROY mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -16281,6 +16646,7 @@
/**
* lpfc_cq_destroy - Destroy a Completion Queue on the HBA
+ * @phba: HBA structure that indicates port to destroy a queue on.
* @cq: The queue structure associated with the queue to destroy.
*
* This function destroys a queue, as detailed in @cq by sending an mailbox
@@ -16321,7 +16687,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2506 CQ_DESTROY mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -16335,7 +16701,8 @@
/**
* lpfc_mq_destroy - Destroy a Mailbox Queue on the HBA
- * @qm: The queue structure associated with the queue to destroy.
+ * @phba: HBA structure that indicates port to destroy a queue on.
+ * @mq: The queue structure associated with the queue to destroy.
*
* This function destroys a queue, as detailed in @mq by sending an mailbox
* command, specific to the type of queue, to the HBA.
@@ -16375,7 +16742,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2507 MQ_DESTROY mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -16389,6 +16756,7 @@
/**
* lpfc_wq_destroy - Destroy a Work Queue on the HBA
+ * @phba: HBA structure that indicates port to destroy a queue on.
* @wq: The queue structure associated with the queue to destroy.
*
* This function destroys a queue, as detailed in @wq by sending an mailbox
@@ -16428,7 +16796,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2508 WQ_DESTROY mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -16444,7 +16812,9 @@
/**
* lpfc_rq_destroy - Destroy a Receive Queue on the HBA
- * @rq: The queue structure associated with the queue to destroy.
+ * @phba: HBA structure that indicates port to destroy a queue on.
+ * @hrq: The queue structure associated with the queue to destroy.
+ * @drq: The queue structure associated with the queue to destroy.
*
* This function destroys a queue, as detailed in @rq by sending an mailbox
* command, specific to the type of queue, to the HBA.
@@ -16485,7 +16855,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2509 RQ_DESTROY mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -16500,7 +16870,7 @@
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2510 RQ_DESTROY mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -16548,7 +16918,7 @@
union lpfc_sli4_cfg_shdr *shdr;
if (xritag == NO_XRI) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0364 Invalid param:\n");
return -EINVAL;
}
@@ -16591,7 +16961,7 @@
else if (rc != MBX_TIMEOUT)
mempool_free(mbox, phba->mbox_mem_pool);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2511 POST_SGL mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -16638,6 +17008,7 @@
/**
* lpfc_sli4_free_xri - Release an xri for reuse.
* @phba: pointer to lpfc hba data structure.
+ * @xri: xri to release.
*
* This routine is invoked to release an xri to the pool of
* available rpis maintained by the driver.
@@ -16653,6 +17024,7 @@
/**
* lpfc_sli4_free_xri - Release an xri for reuse.
* @phba: pointer to lpfc hba data structure.
+ * @xri: xri to release.
*
* This routine is invoked to release an xri to the pool of
* available rpis maintained by the driver.
@@ -16695,7 +17067,7 @@
* lpfc_sli4_post_sgl_list - post a block of ELS sgls to the port.
* @phba: pointer to lpfc hba data structure.
* @post_sgl_list: pointer to els sgl entry list.
- * @count: number of els sgl entries on the list.
+ * @post_cnt: number of els sgl entries on the list.
*
* This routine is invoked to post a block of driver's sgl pages to the
* HBA using non-embedded mailbox command. No Lock is held. This routine
@@ -16722,7 +17094,7 @@
reqlen = post_cnt * sizeof(struct sgl_page_pairs) +
sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t);
if (reqlen > SLI4_PAGE_SIZE) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2559 Block sgl registration required DMA "
"size (%d) great than a page\n", reqlen);
return -ENOMEM;
@@ -16738,7 +17110,7 @@
LPFC_SLI4_MBX_NEMBED);
if (alloclen < reqlen) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"0285 Allocated DMA memory size (%d) is "
"less than the requested DMA memory "
"size (%d)\n", alloclen, reqlen);
@@ -16788,7 +17160,7 @@
else if (rc != MBX_TIMEOUT)
lpfc_sli4_mbox_cmd_free(phba, mbox);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2513 POST_SGL_BLOCK mailbox command failed "
"status x%x add_status x%x mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -16836,7 +17208,7 @@
}
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6119 Failed to allocate mbox cmd memory\n");
return -ENOMEM;
}
@@ -16847,7 +17219,7 @@
reqlen, LPFC_SLI4_MBX_NEMBED);
if (alloclen < reqlen) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6120 Allocated DMA memory size (%d) is "
"less than the requested DMA memory "
"size (%d)\n", alloclen, reqlen);
@@ -16903,7 +17275,7 @@
else if (rc != MBX_TIMEOUT)
lpfc_sli4_mbox_cmd_free(phba, mbox);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"6125 POST_SGL_BLOCK mailbox command failed "
"status x%x add_status x%x mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -16916,6 +17288,7 @@
* lpfc_sli4_post_io_sgl_list - Post blocks of nvme buffer sgls from a list
* @phba: pointer to lpfc hba data structure.
* @post_nblist: pointer to the nvme buffer list.
+ * @sb_count: number of nvme buffers.
*
* This routine walks a list of nvme buffers that was passed in. It attempts
* to construct blocks of nvme buffer sgls which contains contiguous xris and
@@ -17149,6 +17522,7 @@
* @phba: Pointer to the HBA structure to search for the vport on
* @fc_hdr: A pointer to the FC Header data (In Big Endian Format)
* @fcfi: The FC Fabric ID that the frame came from
+ * @did: Destination ID to match against
*
* This function searches the @phba for a vport that matches the content of the
* @fc_hdr passed in and the @fcfi. This function uses the @fc_hdr to fetch the
@@ -17286,6 +17660,7 @@
/**
* lpfc_fc_frame_add - Adds a frame to the vport's list of received sequences
+ * @vport: pointer to a vitural port
* @dmabuf: pointer to a dmabuf that describes the hdr and data of the FC frame
*
* This function searches through the existing incomplete sequences that have
@@ -17486,7 +17861,7 @@
/* Failure means BLS ABORT RSP did not get delivered to remote node*/
if (rsp_iocbq && rsp_iocbq->iocb.ulpStatus)
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3154 BLS ABORT RSP failed, data: x%x/x%x\n",
rsp_iocbq->iocb.ulpStatus,
rsp_iocbq->iocb.un.ulpWord[4]);
@@ -17515,8 +17890,9 @@
/**
* lpfc_sli4_seq_abort_rsp - bls rsp to sequence abort
- * @phba: Pointer to HBA context object.
+ * @vport: pointer to a vitural port.
* @fc_hdr: pointer to a FC frame header.
+ * @aborted: was the partially assembled receive sequence successfully aborted
*
* This function sends a basic response to a previous unsol sequence abort
* event after aborting the sequence handling.
@@ -17648,7 +18024,7 @@
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0);
if (rc == IOCB_ERROR) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"2925 Failed to issue CT ABTS RSP x%x on "
"xri x%x, Data x%x\n",
icmd->un.xseq64.w5.hcsw.Rctl, oxid,
@@ -17668,7 +18044,7 @@
* receive sequence is only partially assembed by the driver, it shall abort
* the partially assembled frames for the sequence. Otherwise, if the
* unsolicited receive sequence has been completely assembled and passed to
- * the Upper Layer Protocol (UPL), it then mark the per oxid status for the
+ * the Upper Layer Protocol (ULP), it then mark the per oxid status for the
* unsolicited sequence has been aborted. After that, it will issue a basic
* accept to accept the abort.
**/
@@ -17755,7 +18131,7 @@
/**
* lpfc_prep_seq - Prep sequence for ULP processing
* @vport: Pointer to the vport on which this sequence was received
- * @dmabuf: pointer to a dmabuf that describes the FC sequence
+ * @seq_dmabuf: pointer to a dmabuf that describes the FC sequence
*
* This function takes a sequence, described by a list of frames, and creates
* a list of iocbq structures to describe the sequence. This iocbq list will be
@@ -17898,7 +18274,7 @@
fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt;
iocbq = lpfc_prep_seq(vport, seq_dmabuf);
if (!iocbq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2707 Ring %d handler: Failed to allocate "
"iocb Rctl x%x Type x%x received\n",
LPFC_ELS_RING,
@@ -17909,7 +18285,7 @@
phba->sli4_hba.els_wq->pring,
iocbq, fc_hdr->fh_r_ctl,
fc_hdr->fh_type))
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2540 Ring %d handler: unexpected Rctl "
"x%x Type x%x received\n",
LPFC_ELS_RING,
@@ -18028,6 +18404,7 @@
/**
* lpfc_sli4_handle_received_buffer - Handle received buffers from firmware
* @phba: Pointer to HBA context object.
+ * @dmabuf: Pointer to a dmabuf that describes the FC sequence.
*
* This function is called with no lock held. This function processes all
* the received buffers and gives it to upper layers when a received buffer
@@ -18053,7 +18430,10 @@
fc_hdr->fh_r_ctl == FC_RCTL_DD_UNSOL_DATA) {
vport = phba->pport;
/* Handle MDS Loopback frames */
- lpfc_sli4_handle_mds_loopback(vport, dmabuf);
+ if (!(phba->pport->load_flag & FC_UNLOADING))
+ lpfc_sli4_handle_mds_loopback(vport, dmabuf);
+ else
+ lpfc_in_buf_free(phba, &dmabuf->dbuf);
return;
}
@@ -18174,7 +18554,7 @@
rc = lpfc_sli4_post_rpi_hdr(phba, rpi_page);
if (rc != MBX_SUCCESS) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2008 Error %d posting all rpi "
"headers\n", rc);
rc = -EIO;
@@ -18220,7 +18600,7 @@
/* The port is notified of the header region via a mailbox command. */
mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mboxq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2001 Unable to allocate memory for issuing "
"SLI_CONFIG_SPECIAL mailbox command\n");
return -ENOMEM;
@@ -18249,7 +18629,7 @@
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
mempool_free(mboxq, phba->mbox_mem_pool);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2514 POST_RPI_HDR mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -18304,8 +18684,9 @@
phba->sli4_hba.max_cfg_param.rpi_used++;
phba->sli4_hba.rpi_count++;
}
- lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- "0001 rpi:%x max:%x lim:%x\n",
+ lpfc_printf_log(phba, KERN_INFO,
+ LOG_NODE | LOG_DISCOVERY,
+ "0001 Allocated rpi:x%x max:x%x lim:x%x\n",
(int) rpi, max_rpi, rpi_limit);
/*
@@ -18338,7 +18719,7 @@
if (rpi_remaining < LPFC_RPI_LOW_WATER_MARK) {
rpi_hdr = lpfc_sli4_create_rpi_hdr(phba);
if (!rpi_hdr) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2002 Error Could not grow rpi "
"count\n");
} else {
@@ -18354,6 +18735,7 @@
/**
* lpfc_sli4_free_rpi - Release an rpi for reuse.
* @phba: pointer to lpfc hba data structure.
+ * @rpi: rpi to free
*
* This routine is invoked to release an rpi to the pool of
* available rpis maintained by the driver.
@@ -18372,7 +18754,8 @@
phba->sli4_hba.rpi_count--;
phba->sli4_hba.max_cfg_param.rpi_used--;
} else {
- lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ lpfc_printf_log(phba, KERN_INFO,
+ LOG_NODE | LOG_DISCOVERY,
"2016 rpi %x not inuse\n",
rpi);
}
@@ -18381,6 +18764,7 @@
/**
* lpfc_sli4_free_rpi - Release an rpi for reuse.
* @phba: pointer to lpfc hba data structure.
+ * @rpi: rpi to free
*
* This routine is invoked to release an rpi to the pool of
* available rpis maintained by the driver.
@@ -18410,7 +18794,9 @@
/**
* lpfc_sli4_resume_rpi - Remove the rpi bitmask region
- * @phba: pointer to lpfc hba data structure.
+ * @ndlp: pointer to lpfc nodelist data structure.
+ * @cmpl: completion call-back.
+ * @arg: data to load as MBox 'caller buffer information'
*
* This routine is invoked to remove the memory region that
* provided rpi via a bitmask.
@@ -18439,7 +18825,7 @@
mboxq->vport = ndlp->vport;
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2010 Resume RPI Mailbox failed "
"status %d, mbxStatus x%x\n", rc,
bf_get(lpfc_mqe_status, &mboxq->u.mqe));
@@ -18474,7 +18860,7 @@
mbox_tmo = lpfc_mbox_tmo_val(phba, mboxq);
rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo);
if (rc != MBX_SUCCESS) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_SLI,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"2022 INIT VPI Mailbox failed "
"status %d, mbxStatus x%x\n", rc,
bf_get(lpfc_mqe_status, &mboxq->u.mqe));
@@ -18510,7 +18896,7 @@
if ((shdr_status || shdr_add_status) &&
(shdr_status != STATUS_FCF_IN_USE))
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2558 ADD_FCF_RECORD mailbox failed with "
"status x%x add_status x%x\n",
shdr_status, shdr_add_status);
@@ -18540,7 +18926,7 @@
mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mboxq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2009 Failed to allocate mbox for ADD_FCF cmd\n");
return -ENOMEM;
}
@@ -18553,7 +18939,7 @@
LPFC_MBOX_OPCODE_FCOE_ADD_FCF,
req_len, LPFC_SLI4_MBX_NEMBED);
if (alloc_len < req_len) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2523 Allocated DMA memory size (x%x) is "
"less than the requested DMA memory "
"size (x%x)\n", alloc_len, req_len);
@@ -18586,7 +18972,7 @@
mboxq->mbox_cmpl = lpfc_mbx_cmpl_add_fcf_record;
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2515 ADD_FCF_RECORD mailbox failed with "
"status 0x%x\n", rc);
lpfc_sli4_mbox_cmd_free(phba, mboxq);
@@ -18659,7 +19045,7 @@
phba->fcoe_cvl_eventtag_attn = phba->fcoe_cvl_eventtag;
mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mboxq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2000 Failed to allocate mbox for "
"READ_FCF cmd\n");
error = -ENOMEM;
@@ -18794,7 +19180,7 @@
/**
* lpfc_check_next_fcf_pri_level
- * phba pointer to the lpfc_hba struct for this port.
+ * @phba: pointer to the lpfc_hba struct for this port.
* This routine is called from the lpfc_sli4_fcf_rr_next_index_get
* routine when the rr_bmask is empty. The FCF indecies are put into the
* rr_bmask based on their priority level. Starting from the highest priority
@@ -18959,6 +19345,7 @@
/**
* lpfc_sli4_fcf_rr_index_set - Set bmask with eligible fcf record index
* @phba: pointer to lpfc hba data structure.
+ * @fcf_index: index into the FCF table to 'set'
*
* This routine sets the FCF record index in to the eligible bmask for
* roundrobin failover search. It checks to make sure that the index
@@ -18991,6 +19378,7 @@
/**
* lpfc_sli4_fcf_rr_index_clear - Clear bmask from eligible fcf record index
* @phba: pointer to lpfc hba data structure.
+ * @fcf_index: index into the FCF table to 'clear'
*
* This routine clears the FCF record index from the eligible bmask for
* roundrobin failover search. It checks to make sure that the index
@@ -19028,6 +19416,7 @@
/**
* lpfc_mbx_cmpl_redisc_fcf_table - completion routine for rediscover FCF table
* @phba: pointer to lpfc hba data structure.
+ * @mbox: An allocated pointer to type LPFC_MBOXQ_t
*
* This routine is the completion routine for the rediscover FCF table mailbox
* command. If the mailbox command returned failure, it will try to stop the
@@ -19102,7 +19491,7 @@
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox) {
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2745 Failed to allocate mbox for "
"requesting FCF rediscover.\n");
return -ENOMEM;
@@ -19170,14 +19559,14 @@
LPFC_MBOXQ_t *pmb = NULL;
MAILBOX_t *mb;
uint32_t offset = 0;
- int rc;
+ int i, rc;
if (!rgn23_data)
return 0;
pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!pmb) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2600 failed to allocate mailbox memory\n");
return 0;
}
@@ -19200,14 +19589,14 @@
*/
if (mb->un.varDmp.word_cnt == 0)
break;
- if (mb->un.varDmp.word_cnt > DMP_RGN23_SIZE - offset)
- mb->un.varDmp.word_cnt = DMP_RGN23_SIZE - offset;
+ i = mb->un.varDmp.word_cnt * sizeof(uint32_t);
+ if (offset + i > DMP_RGN23_SIZE)
+ i = DMP_RGN23_SIZE - offset;
lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
- rgn23_data + offset,
- mb->un.varDmp.word_cnt);
- offset += mb->un.varDmp.word_cnt;
- } while (mb->un.varDmp.word_cnt && offset < DMP_RGN23_SIZE);
+ rgn23_data + offset, i);
+ offset += i;
+ } while (offset < DMP_RGN23_SIZE);
mempool_free(pmb, phba->mbox_mem_pool);
return offset;
@@ -19236,7 +19625,7 @@
mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mboxq) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3105 failed to allocate mailbox memory\n");
return 0;
}
@@ -19300,7 +19689,7 @@
/* Check the region signature first */
if (memcmp(&rgn23_data[offset], LPFC_REGION23_SIGNATURE, 4)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2619 Config region 23 has bad signature\n");
goto out;
}
@@ -19308,7 +19697,7 @@
/* Check the data structure version */
if (rgn23_data[offset] != LPFC_REGION23_VERSION) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2620 Config region 23 has bad version\n");
goto out;
}
@@ -19389,7 +19778,7 @@
struct lpfc_mbx_wr_object *wr_object;
LPFC_MBOXQ_t *mbox;
int rc = 0, i = 0;
- uint32_t shdr_status, shdr_add_status, shdr_change_status;
+ uint32_t shdr_status, shdr_add_status, shdr_change_status, shdr_csf;
uint32_t mbox_tmo;
struct lpfc_dmabuf *dmabuf;
uint32_t written = 0;
@@ -19446,6 +19835,16 @@
if (check_change_status) {
shdr_change_status = bf_get(lpfc_wr_object_change_status,
&wr_object->u.response);
+
+ if (shdr_change_status == LPFC_CHANGE_STATUS_FW_RESET ||
+ shdr_change_status == LPFC_CHANGE_STATUS_PORT_MIGRATION) {
+ shdr_csf = bf_get(lpfc_wr_object_csf,
+ &wr_object->u.response);
+ if (shdr_csf)
+ shdr_change_status =
+ LPFC_CHANGE_STATUS_PCI_RESET;
+ }
+
switch (shdr_change_status) {
case (LPFC_CHANGE_STATUS_PHYS_DEV_RESET):
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
@@ -19477,7 +19876,7 @@
else if (rc != MBX_TIMEOUT)
mempool_free(mbox, phba->mbox_mem_pool);
if (shdr_status || shdr_add_status || rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3025 Write Object mailbox failed with "
"status x%x add_status x%x, mbx status x%x\n",
shdr_status, shdr_add_status, rc);
@@ -19657,7 +20056,7 @@
piocbq = lpfc_sli_ringtx_get(phba, pring);
if (!piocbq) {
spin_unlock_irqrestore(&pring->ring_lock, iflags);
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2823 txq empty and txq_cnt is %d\n ",
txq_cnt);
break;
@@ -19686,12 +20085,13 @@
if (fail_msg) {
/* Failed means we can't issue and need to cancel */
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"2822 IOCB failed %s iotag 0x%x "
"xri 0x%x\n",
fail_msg,
piocbq->iotag, piocbq->sli4_xritag);
list_add_tail(&piocbq->list, &completions);
+ fail_msg = NULL;
}
spin_unlock_irqrestore(&pring->ring_lock, iflags);
}
@@ -19706,7 +20106,7 @@
/**
* lpfc_wqe_bpl2sgl - Convert the bpl/bde to a sgl.
* @phba: Pointer to HBA context object.
- * @pwqe: Pointer to command WQE.
+ * @pwqeq: Pointer to command WQE.
* @sglq: Pointer to the scatter gather queue object.
*
* This routine converts the bpl or bde that is in the WQE
@@ -19831,7 +20231,7 @@
/**
* lpfc_sli4_issue_wqe - Issue an SLI4 Work Queue Entry (WQE)
* @phba: Pointer to HBA context object.
- * @ring_number: Base sli ring number
+ * @qp: Pointer to HDW queue.
* @pwqe: Pointer to command WQE.
**/
int
@@ -19839,7 +20239,7 @@
struct lpfc_iocbq *pwqe)
{
union lpfc_wqe128 *wqe = &pwqe->wqe;
- struct lpfc_nvmet_rcv_ctx *ctxp;
+ struct lpfc_async_xchg_ctx *ctxp;
struct lpfc_queue *wq;
struct lpfc_sglq *sglq;
struct lpfc_sli_ring *pring;
@@ -20113,6 +20513,7 @@
/**
* _lpfc_move_xri_pbl_to_pvt - Move some XRIs from public to private pool
* @phba: pointer to lpfc hba data structure
+ * @qp: pointer to HDW queue
* @pbl_pool: specified public free XRI pool
* @pvt_pool: specified private free XRI pool
* @count: number of XRIs to move
@@ -20242,7 +20643,7 @@
/**
* lpfc_keep_pvt_pool_above_lowwm - Keep pvt_pool above low watermark
* @phba: pointer to lpfc hba data structure.
- * @qp: belong to which HWQ.
+ * @hwqid: belong to which HWQ.
*
* This routine get a batch of XRIs from pbl_pool if pvt_pool is less than
* low watermark.
@@ -20364,6 +20765,7 @@
/**
* lpfc_get_io_buf_from_private_pool - Get one free IO buf from private pool
* @phba: pointer to lpfc hba data structure.
+ * @qp: pointer to HDW queue
* @pvt_pool: pointer to private pool data structure.
* @ndlp: pointer to lpfc nodelist data structure.
*
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index 7bcf922..93d976e 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -446,6 +446,6 @@
uint64_t ts_last_cmd;
uint64_t ts_cmd_wqput;
uint64_t ts_isr_cmpl;
- uint64_t ts_data_nvme;
+ uint64_t ts_data_io;
#endif
};
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index c60a636..100cb1a 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -20,6 +20,9 @@
* included with this package. *
*******************************************************************/
+#include <linux/irq_poll.h>
+#include <linux/cpufreq.h>
+
#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_SCSI_LPFC_DEBUG_FS)
#define CONFIG_SCSI_LPFC_DEBUG_FS
#endif
@@ -41,8 +44,13 @@
/* Multi-queue arrangement for FCP EQ/CQ/WQ tuples */
#define LPFC_HBA_HDWQ_MIN 0
-#define LPFC_HBA_HDWQ_MAX 128
-#define LPFC_HBA_HDWQ_DEF 0
+#define LPFC_HBA_HDWQ_MAX 256
+#define LPFC_HBA_HDWQ_DEF LPFC_HBA_HDWQ_MIN
+
+/* irq_chann range, values */
+#define LPFC_IRQ_CHANN_MIN 0
+#define LPFC_IRQ_CHANN_MAX 256
+#define LPFC_IRQ_CHANN_DEF LPFC_IRQ_CHANN_MIN
/* FCP MQ queue count limiting */
#define LPFC_FCP_MQ_THRESHOLD_MIN 0
@@ -130,6 +138,16 @@
struct rqb_dmabuf *);
};
+enum lpfc_poll_mode {
+ LPFC_QUEUE_WORK,
+ LPFC_IRQ_POLL
+};
+
+struct lpfc_idle_stat {
+ u64 prev_idle;
+ u64 prev_wall;
+};
+
struct lpfc_queue {
struct list_head list;
struct list_head wq_list;
@@ -216,6 +234,7 @@
uint8_t q_flag;
#define HBA_NVMET_WQFULL 0x1 /* We hit WQ Full condition for NVMET */
#define HBA_NVMET_CQ_NOTIFY 0x1 /* LPFC_NVMET_CQ_NOTIFY CQEs this EQE */
+#define HBA_EQ_DELAY_CHK 0x2 /* EQ is a candidate for coalescing */
#define LPFC_NVMET_CQ_NOTIFY 4
void __iomem *db_regaddr;
uint16_t dpp_enable;
@@ -259,6 +278,10 @@
struct lpfc_queue *assoc_qp;
struct list_head _poll_list;
void **q_pgs; /* array to index entries per page */
+
+#define LPFC_IRQ_POLL_WEIGHT 256
+ struct irq_poll iop;
+ enum lpfc_poll_mode poll_mode;
};
struct lpfc_sli4_link {
@@ -466,11 +489,17 @@
#define LPFC_SLI4_HANDLER_NAME_SZ 16
struct lpfc_hba_eq_hdl {
uint32_t idx;
+ uint16_t irq;
char handler_name[LPFC_SLI4_HANDLER_NAME_SZ];
struct lpfc_hba *phba;
struct lpfc_queue *eq;
+ struct cpumask aff_mask;
};
+#define lpfc_get_eq_hdl(eqidx) (&phba->sli4_hba.hba_eq_hdl[eqidx])
+#define lpfc_get_aff_mask(eqidx) (&phba->sli4_hba.hba_eq_hdl[eqidx].aff_mask)
+#define lpfc_get_irq(eqidx) (phba->sli4_hba.hba_eq_hdl[eqidx].irq)
+
/*BB Credit recovery value*/
struct lpfc_bbscn_params {
uint32_t word0;
@@ -528,6 +557,7 @@
uint8_t cqav;
uint8_t wqsize;
uint8_t bv1s;
+ uint8_t pls;
#define LPFC_WQ_SZ64_SUPPORT 1
#define LPFC_WQ_SZ128_SUPPORT 2
uint8_t wqpcnt;
@@ -559,11 +589,10 @@
#define LPFC_SLI4_HANDLER_CNT (LPFC_HBA_IO_CHAN_MAX+ \
LPFC_FOF_IO_CHAN_NUM)
-/* Used for IRQ vector to CPU mapping */
+/* Used for tracking CPU mapping attributes */
struct lpfc_vector_map_info {
uint16_t phys_id;
uint16_t core_id;
- uint16_t irq;
uint16_t eq;
uint16_t hdwq;
uint16_t flag;
@@ -685,13 +714,6 @@
struct lpfc_lock_stat lock_conflict;
#endif
-#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
-#define LPFC_CHECK_CPU_CNT 128
- uint32_t cpucheck_rcv_io[LPFC_CHECK_CPU_CNT];
- uint32_t cpucheck_xmt_io[LPFC_CHECK_CPU_CNT];
- uint32_t cpucheck_cmpl_io[LPFC_CHECK_CPU_CNT];
-#endif
-
/* Per HDWQ pool resources */
struct list_head sgl_list;
struct list_head cmd_rsp_buf_list;
@@ -728,6 +750,15 @@
#define lpfc_qp_spin_lock(lock, qp, lstat) spin_lock(lock)
#endif
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+struct lpfc_hdwq_stat {
+ u32 hdwq_no;
+ u32 rcv_io;
+ u32 xmt_io;
+ u32 cmpl_io;
+};
+#endif
+
struct lpfc_sli4_hba {
void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for
* config space registers
@@ -889,8 +920,9 @@
struct list_head sp_queue_event;
struct list_head sp_cqe_event_pool;
struct list_head sp_asynce_work_queue;
- struct list_head sp_fcp_xri_aborted_work_queue;
+ spinlock_t asynce_list_lock; /* protect sp_asynce_work_queue list */
struct list_head sp_els_xri_aborted_work_queue;
+ spinlock_t els_xri_abrt_list_lock; /* protect els_xri_aborted list */
struct list_head sp_unsol_work_queue;
struct lpfc_sli4_link link_state;
struct lpfc_sli4_lnk_info lnk_info;
@@ -906,8 +938,13 @@
struct lpfc_vector_map_info *cpu_map;
uint16_t num_possible_cpu;
uint16_t num_present_cpu;
+ struct cpumask irq_aff_mask;
uint16_t curr_disp_cpu;
struct lpfc_eq_intr_info __percpu *eq_info;
+#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ struct lpfc_hdwq_stat __percpu *c_stat;
+#endif
+ struct lpfc_idle_stat *idle_stat;
uint32_t conf_trunk;
#define lpfc_conf_trunk_port0_WORD conf_trunk
#define lpfc_conf_trunk_port0_SHIFT 0
@@ -1067,8 +1104,7 @@
void lpfc_sli4_fcf_redisc_event_proc(struct lpfc_hba *);
int lpfc_sli4_resume_rpi(struct lpfc_nodelist *,
void (*)(struct lpfc_hba *, LPFC_MBOXQ_t *), void *);
-void lpfc_sli4_fcp_xri_abort_event_proc(struct lpfc_hba *);
-void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *);
+void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba);
void lpfc_sli4_nvme_xri_aborted(struct lpfc_hba *phba,
struct sli4_wcqe_xri_aborted *axri,
struct lpfc_io_buf *lpfc_ncmd);
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index b8aae31..c657abf 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -20,7 +20,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "12.4.0.0"
+#define LPFC_DRIVER_VERSION "12.8.0.4"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index d0296f7..aa4e451 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -145,7 +145,7 @@
rc = lpfc_sli_issue_mbox_wait(phba, pmb, phba->fc_ratov * 2);
if (rc != MBX_SUCCESS) {
if (signal_pending(current)) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT | LOG_VPORT,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1830 Signal aborted mbxCmd x%x\n",
mb->mbxCommand);
lpfc_mbuf_free(phba, mp->virt, mp->phys);
@@ -154,7 +154,7 @@
mempool_free(pmb, phba->mbox_mem_pool);
return -EINTR;
} else {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT | LOG_VPORT,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1818 VPort failed init, mbxCmd x%x "
"READ_SPARM mbxStatus x%x, rc = x%x\n",
mb->mbxCommand, mb->mbxStatus, rc);
@@ -190,7 +190,7 @@
((wwn->u.wwn[0] & 0xf) != 0 || (wwn->u.wwn[1] & 0xf) != 0)))
return 1;
- lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1822 Invalid %s: %02x:%02x:%02x:%02x:"
"%02x:%02x:%02x:%02x\n",
name_type,
@@ -284,11 +284,11 @@
}
if (time_after(jiffies, wait_time_max))
- lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
- "1835 Vport discovery quiesce failed:"
- " state x%x fc_flags x%x wait msecs x%x\n",
- vport->port_state, vport->fc_flag,
- jiffies_to_msecs(jiffies - start_time));
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "1835 Vport discovery quiesce failed:"
+ " state x%x fc_flags x%x wait msecs x%x\n",
+ vport->port_state, vport->fc_flag,
+ jiffies_to_msecs(jiffies - start_time));
}
int
@@ -305,7 +305,7 @@
int status;
if ((phba->sli_rev < 3) || !(phba->cfg_enable_npiv)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1808 Create VPORT failed: "
"NPIV is not enabled: SLImode:%d\n",
phba->sli_rev);
@@ -315,7 +315,7 @@
/* NPIV is not supported if HBA has NVME Target enabled */
if (phba->nvmet_support) {
- lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"3189 Create VPORT failed: "
"NPIV is not supported on NVME Target\n");
rc = VPORT_INVAL;
@@ -324,7 +324,7 @@
vpi = lpfc_alloc_vpi(phba);
if (vpi == 0) {
- lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1809 Create VPORT failed: "
"Max VPORTs (%d) exceeded\n",
phba->max_vpi);
@@ -334,7 +334,7 @@
/* Assign an unused board number */
if ((instance = lpfc_get_instance()) < 0) {
- lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1810 Create VPORT failed: Cannot get "
"instance number\n");
lpfc_free_vpi(phba, vpi);
@@ -344,7 +344,7 @@
vport = lpfc_create_port(phba, instance, &fc_vport->dev);
if (!vport) {
- lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1811 Create VPORT failed: vpi x%x\n", vpi);
lpfc_free_vpi(phba, vpi);
rc = VPORT_NORESOURCES;
@@ -356,11 +356,11 @@
if ((status = lpfc_vport_sparm(phba, vport))) {
if (status == -EINTR) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1831 Create VPORT Interrupted.\n");
rc = VPORT_ERROR;
} else {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1813 Create VPORT failed. "
"Cannot get sparam\n");
rc = VPORT_NORESOURCES;
@@ -378,7 +378,7 @@
if (!lpfc_valid_wwn_format(phba, &vport->fc_sparam.nodeName, "WWNN") ||
!lpfc_valid_wwn_format(phba, &vport->fc_sparam.portName, "WWPN")) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1821 Create VPORT failed. "
"Invalid WWN format\n");
lpfc_free_vpi(phba, vpi);
@@ -388,7 +388,7 @@
}
if (!lpfc_unique_wwpn(phba, vport)) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1823 Create VPORT failed. "
"Duplicate WWN on HBA\n");
lpfc_free_vpi(phba, vpi);
@@ -426,7 +426,7 @@
(pport->fc_flag & FC_VFI_REGISTERED)) {
rc = lpfc_sli4_init_vpi(vport);
if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
"1838 Failed to INIT_VPI on vpi %d "
"status %d\n", vpi, rc);
rc = VPORT_NORESOURCES;
@@ -469,7 +469,7 @@
lpfc_initial_fdisc(vport);
} else {
lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0262 No NPIV Fabric support\n");
}
} else {
@@ -478,8 +478,8 @@
rc = VPORT_OK;
out:
- lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
- "1825 Vport Created.\n");
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "1825 Vport Created.\n");
lpfc_host_attrib_init(lpfc_shost_from_vport(vport));
error_out:
return rc;
@@ -534,7 +534,7 @@
}
lpfc_vport_set_state(vport, FC_VPORT_DISABLED);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1826 Vport Disabled.\n");
return VPORT_OK;
}
@@ -575,7 +575,7 @@
lpfc_initial_fdisc(vport);
} else {
lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"0264 No NPIV Fabric support\n");
}
} else {
@@ -583,7 +583,7 @@
}
out:
- lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1827 Vport Enabled.\n");
return VPORT_OK;
}
@@ -609,7 +609,7 @@
bool ns_ndlp_referenced = false;
if (vport->port_type == LPFC_PHYSICAL_PORT) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1812 vport_delete failed: Cannot delete "
"physical host\n");
return VPORT_ERROR;
@@ -618,7 +618,7 @@
/* If the vport is a static vport fail the deletion. */
if ((vport->vport_flag & STATIC_VPORT) &&
!(phba->pport->load_flag & FC_UNLOADING)) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1837 vport_delete failed: Cannot delete "
"static vport.\n");
return VPORT_ERROR;
@@ -807,7 +807,7 @@
spin_lock_irq(&phba->port_list_lock);
list_del_init(&vport->listentry);
spin_unlock_irq(&phba->port_list_lock);
- lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
"1828 Vport Deleted.\n");
scsi_host_put(shost);
return VPORT_OK;
@@ -828,7 +828,8 @@
if (port_iterator->load_flag & FC_UNLOADING)
continue;
if (!scsi_host_get(lpfc_shost_from_vport(port_iterator))) {
- lpfc_printf_vlog(port_iterator, KERN_ERR, LOG_VPORT,
+ lpfc_printf_vlog(port_iterator, KERN_ERR,
+ LOG_TRACE_EVENT,
"1801 Create vport work array FAILED: "
"cannot do scsi_host_get\n");
continue;
@@ -898,7 +899,8 @@
GFP_ATOMIC);
if (!ndlp->lat_data)
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_TRACE_EVENT,
"0287 lpfc_alloc_bucket failed to "
"allocate statistical data buffer DID "
"0x%x\n", ndlp->nlp_DID);
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 35d3e32..43edf83 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -20,9 +20,9 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/pgtable.h>
#include <asm/dbdma.h>
#include <asm/io.h>
-#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/macio.h>
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
index 1c78bc1..6d23ab5 100644
--- a/drivers/scsi/mac_esp.c
+++ b/drivers/scsi/mac_esp.c
@@ -439,22 +439,10 @@
.name = DRV_MODULE_NAME,
},
};
-
-static int __init mac_esp_init(void)
-{
- return platform_driver_register(&esp_mac_driver);
-}
-
-static void __exit mac_esp_exit(void)
-{
- platform_driver_unregister(&esp_mac_driver);
-}
+module_platform_driver(esp_mac_driver);
MODULE_DESCRIPTION("Mac ESP SCSI driver");
MODULE_AUTHOR("Finn Thain");
MODULE_LICENSE("GPL v2");
MODULE_VERSION(DRV_VERSION);
MODULE_ALIAS("platform:" DRV_MODULE_NAME);
-
-module_init(mac_esp_init);
-module_exit(mac_esp_exit);
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index ff6d4aa..80f5469 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -124,7 +124,7 @@
/**
* mega_setup_mailbox()
- * @adapter - pointer to our soft state
+ * @adapter: pointer to our soft state
*
* Allocates a 8 byte aligned memory for the handshake mailbox.
*/
@@ -133,8 +133,10 @@
{
unsigned long align;
- adapter->una_mbox64 = pci_alloc_consistent(adapter->dev,
- sizeof(mbox64_t), &adapter->una_mbox64_dma);
+ adapter->una_mbox64 = dma_alloc_coherent(&adapter->dev->dev,
+ sizeof(mbox64_t),
+ &adapter->una_mbox64_dma,
+ GFP_KERNEL);
if( !adapter->una_mbox64 ) return -1;
@@ -222,8 +224,9 @@
mraid_inquiry *inq;
dma_addr_t dma_handle;
- ext_inq = pci_alloc_consistent(adapter->dev,
- sizeof(mraid_ext_inquiry), &dma_handle);
+ ext_inq = dma_alloc_coherent(&adapter->dev->dev,
+ sizeof(mraid_ext_inquiry),
+ &dma_handle, GFP_KERNEL);
if( ext_inq == NULL ) return -1;
@@ -243,8 +246,9 @@
mega_8_to_40ld(inq, inquiry3,
(mega_product_info *)&adapter->product_info);
- pci_free_consistent(adapter->dev, sizeof(mraid_ext_inquiry),
- ext_inq, dma_handle);
+ dma_free_coherent(&adapter->dev->dev,
+ sizeof(mraid_ext_inquiry), ext_inq,
+ dma_handle);
} else { /*adapter supports 40ld */
adapter->flag |= BOARD_40LD;
@@ -253,9 +257,10 @@
* get product_info, which is static information and will be
* unchanged
*/
- prod_info_dma_handle = pci_map_single(adapter->dev, (void *)
- &adapter->product_info,
- sizeof(mega_product_info), PCI_DMA_FROMDEVICE);
+ prod_info_dma_handle = dma_map_single(&adapter->dev->dev,
+ (void *)&adapter->product_info,
+ sizeof(mega_product_info),
+ DMA_FROM_DEVICE);
mbox->m_out.xferaddr = prod_info_dma_handle;
@@ -267,8 +272,8 @@
"Product_info cmd failed with error: %d\n",
retval);
- pci_unmap_single(adapter->dev, prod_info_dma_handle,
- sizeof(mega_product_info), PCI_DMA_FROMDEVICE);
+ dma_unmap_single(&adapter->dev->dev, prod_info_dma_handle,
+ sizeof(mega_product_info), DMA_FROM_DEVICE);
}
@@ -347,7 +352,7 @@
/**
* mega_runpendq()
- * @adapter - pointer to our soft state
+ * @adapter: pointer to our soft state
*
* Runs through the list of pending requests.
*/
@@ -413,8 +418,8 @@
/**
* mega_allocate_scb()
- * @adapter - pointer to our soft state
- * @cmd - scsi command from the mid-layer
+ * @adapter: pointer to our soft state
+ * @cmd: scsi command from the mid-layer
*
* Allocate a SCB structure. This is the central structure for controller
* commands.
@@ -444,9 +449,9 @@
/**
* mega_get_ldrv_num()
- * @adapter - pointer to our soft state
- * @cmd - scsi mid layer command
- * @channel - channel on the controller
+ * @adapter: pointer to our soft state
+ * @cmd: scsi mid layer command
+ * @channel: channel on the controller
*
* Calculate the logical drive number based on the information in scsi command
* and the channel number.
@@ -491,9 +496,9 @@
if (adapter->support_random_del && adapter->read_ldidmap )
switch (cmd->cmnd[0]) {
- case READ_6: /* fall through */
- case WRITE_6: /* fall through */
- case READ_10: /* fall through */
+ case READ_6:
+ case WRITE_6:
+ case READ_10:
case WRITE_10:
ldrv_num += 0x80;
}
@@ -503,9 +508,9 @@
/**
* mega_build_cmd()
- * @adapter - pointer to our soft state
- * @cmd - Prepare using this scsi command
- * @busy - busy flag if no resources
+ * @adapter: pointer to our soft state
+ * @cmd: Prepare using this scsi command
+ * @busy: busy flag if no resources
*
* Prepares a command and scatter gather list for the controller. This routine
* also finds out if the commands is intended for a logical drive or a
@@ -517,7 +522,6 @@
static scb_t *
mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd, int *busy)
{
- mega_ext_passthru *epthru;
mega_passthru *pthru;
scb_t *scb;
mbox_t *mbox;
@@ -646,7 +650,7 @@
scb->raw_mbox[2] = MEGA_RESERVATION_STATUS;
scb->raw_mbox[3] = ldrv_num;
- scb->dma_direction = PCI_DMA_NONE;
+ scb->dma_direction = DMA_NONE;
return scb;
#else
@@ -710,7 +714,7 @@
mbox->m_out.cmd = MEGA_MBOXCMD_PASSTHRU;
}
- scb->dma_direction = PCI_DMA_FROMDEVICE;
+ scb->dma_direction = DMA_FROM_DEVICE;
pthru->numsgelements = mega_build_sglist(adapter, scb,
&pthru->dataxferaddr, &pthru->dataxferlen);
@@ -840,10 +844,10 @@
* If it is a read command
*/
if( (*cmd->cmnd & 0x0F) == 0x08 ) {
- scb->dma_direction = PCI_DMA_FROMDEVICE;
+ scb->dma_direction = DMA_FROM_DEVICE;
}
else {
- scb->dma_direction = PCI_DMA_TODEVICE;
+ scb->dma_direction = DMA_TO_DEVICE;
}
/* Calculate Scatter-Gather info */
@@ -853,7 +857,7 @@
return scb;
#if MEGA_HAVE_CLUSTERING
- case RESERVE: /* Fall through */
+ case RESERVE:
case RELEASE:
/*
@@ -878,7 +882,7 @@
scb->raw_mbox[3] = ldrv_num;
- scb->dma_direction = PCI_DMA_NONE;
+ scb->dma_direction = DMA_NONE;
return scb;
#endif
@@ -905,7 +909,7 @@
if( adapter->support_ext_cdb ) {
- epthru = mega_prepare_extpassthru(adapter, scb, cmd,
+ mega_prepare_extpassthru(adapter, scb, cmd,
channel, target);
mbox->m_out.cmd = MEGA_MBOXCMD_EXTPTHRU;
@@ -937,11 +941,11 @@
/**
* mega_prepare_passthru()
- * @adapter - pointer to our soft state
- * @scb - our scsi control block
- * @cmd - scsi command from the mid-layer
- * @channel - actual channel on the controller
- * @target - actual id on the controller.
+ * @adapter: pointer to our soft state
+ * @scb: our scsi control block
+ * @cmd: scsi command from the mid-layer
+ * @channel: actual channel on the controller
+ * @target: actual id on the controller.
*
* prepare a command for the scsi physical devices.
*/
@@ -972,7 +976,7 @@
memcpy(pthru->cdb, cmd->cmnd, cmd->cmd_len);
/* Not sure about the direction */
- scb->dma_direction = PCI_DMA_BIDIRECTIONAL;
+ scb->dma_direction = DMA_BIDIRECTIONAL;
/* Special Code for Handling READ_CAPA/ INQ using bounce buffers */
switch (cmd->cmnd[0]) {
@@ -988,7 +992,7 @@
adapter->flag |= (1L << cmd->device->channel);
}
- /* Fall through */
+ fallthrough;
default:
pthru->numsgelements = mega_build_sglist(adapter, scb,
&pthru->dataxferaddr, &pthru->dataxferlen);
@@ -1000,11 +1004,11 @@
/**
* mega_prepare_extpassthru()
- * @adapter - pointer to our soft state
- * @scb - our scsi control block
- * @cmd - scsi command from the mid-layer
- * @channel - actual channel on the controller
- * @target - actual id on the controller.
+ * @adapter: pointer to our soft state
+ * @scb: our scsi control block
+ * @cmd: scsi command from the mid-layer
+ * @channel: actual channel on the controller
+ * @target: actual id on the controller.
*
* prepare a command for the scsi physical devices. This rountine prepares
* commands for devices which can take extended CDBs (>10 bytes)
@@ -1036,7 +1040,7 @@
memcpy(epthru->cdb, cmd->cmnd, cmd->cmd_len);
/* Not sure about the direction */
- scb->dma_direction = PCI_DMA_BIDIRECTIONAL;
+ scb->dma_direction = DMA_BIDIRECTIONAL;
switch(cmd->cmnd[0]) {
case INQUIRY:
@@ -1051,7 +1055,7 @@
adapter->flag |= (1L << cmd->device->channel);
}
- /* Fall through */
+ fallthrough;
default:
epthru->numsgelements = mega_build_sglist(adapter, scb,
&epthru->dataxferaddr, &epthru->dataxferlen);
@@ -1085,8 +1089,8 @@
/**
* issue_scb()
- * @adapter - pointer to our soft state
- * @scb - scsi control block
+ * @adapter: pointer to our soft state
+ * @scb: scsi control block
*
* Post a command to the card if the mailbox is available, otherwise return
* busy. We also take the scb from the pending list if the mailbox is
@@ -1166,8 +1170,8 @@
/**
* issue_scb_block()
- * @adapter - pointer to our soft state
- * @raw_mbox - the mailbox
+ * @adapter: pointer to our soft state
+ * @raw_mbox: the mailbox
*
* Issue a scb in synchronous and non-interrupt mode
*/
@@ -1247,8 +1251,8 @@
/**
* megaraid_isr_iomapped()
- * @irq - irq
- * @devp - pointer to our soft state
+ * @irq: irq
+ * @devp: pointer to our soft state
*
* Interrupt service routine for io-mapped controllers.
* Find out if our device is interrupting. If yes, acknowledge the interrupt
@@ -1323,8 +1327,8 @@
/**
* megaraid_isr_memmapped()
- * @irq - irq
- * @devp - pointer to our soft state
+ * @irq: irq
+ * @devp: pointer to our soft state
*
* Interrupt service routine for memory-mapped controllers.
* Find out if our device is interrupting. If yes, acknowledge the interrupt
@@ -1401,10 +1405,10 @@
}
/**
* mega_cmd_done()
- * @adapter - pointer to our soft state
- * @completed - array of ids of completed commands
- * @nstatus - number of completed commands
- * @status - status of the last command completed
+ * @adapter: pointer to our soft state
+ * @completed: array of ids of completed commands
+ * @nstatus: number of completed commands
+ * @status: status of the last command completed
*
* Complete the commands and call the scsi mid-layer callback hooks.
*/
@@ -1814,25 +1818,25 @@
scb = &adapter->scb_list[i];
if( scb->sgl64 ) {
- pci_free_consistent(adapter->dev,
- sizeof(mega_sgl64) * adapter->sglen,
- scb->sgl64,
- scb->sgl_dma_addr);
+ dma_free_coherent(&adapter->dev->dev,
+ sizeof(mega_sgl64) * adapter->sglen,
+ scb->sgl64, scb->sgl_dma_addr);
scb->sgl64 = NULL;
}
if( scb->pthru ) {
- pci_free_consistent(adapter->dev, sizeof(mega_passthru),
- scb->pthru, scb->pthru_dma_addr);
+ dma_free_coherent(&adapter->dev->dev,
+ sizeof(mega_passthru), scb->pthru,
+ scb->pthru_dma_addr);
scb->pthru = NULL;
}
if( scb->epthru ) {
- pci_free_consistent(adapter->dev,
- sizeof(mega_ext_passthru),
- scb->epthru, scb->epthru_dma_addr);
+ dma_free_coherent(&adapter->dev->dev,
+ sizeof(mega_ext_passthru),
+ scb->epthru, scb->epthru_dma_addr);
scb->epthru = NULL;
}
@@ -1921,9 +1925,9 @@
/**
* megaraid_abort_and_reset()
- * @adapter - megaraid soft state
- * @cmd - scsi command to be aborted or reset
- * @aor - abort or reset flag
+ * @adapter: megaraid soft state
+ * @cmd: scsi command to be aborted or reset
+ * @aor: abort or reset flag
*
* Try to locate the scsi command in the pending queue. If found and is not
* issued to the controller, abort/reset it. Otherwise return failure
@@ -2005,7 +2009,7 @@
memcpy(*pdev, adapter->dev, sizeof(struct pci_dev));
- if( pci_set_dma_mask(*pdev, DMA_BIT_MASK(32)) != 0 ) {
+ if (dma_set_mask(&(*pdev)->dev, DMA_BIT_MASK(32)) != 0) {
kfree(*pdev);
return -1;
}
@@ -2021,22 +2025,24 @@
/**
* mega_allocate_inquiry()
- * @dma_handle - handle returned for dma address
- * @pdev - handle to pci device
+ * @dma_handle: handle returned for dma address
+ * @pdev: handle to pci device
*
* allocates memory for inquiry structure
*/
static inline void *
mega_allocate_inquiry(dma_addr_t *dma_handle, struct pci_dev *pdev)
{
- return pci_alloc_consistent(pdev, sizeof(mega_inquiry3), dma_handle);
+ return dma_alloc_coherent(&pdev->dev, sizeof(mega_inquiry3),
+ dma_handle, GFP_KERNEL);
}
static inline void
mega_free_inquiry(void *inquiry, dma_addr_t dma_handle, struct pci_dev *pdev)
{
- pci_free_consistent(pdev, sizeof(mega_inquiry3), inquiry, dma_handle);
+ dma_free_coherent(&pdev->dev, sizeof(mega_inquiry3), inquiry,
+ dma_handle);
}
@@ -2045,8 +2051,8 @@
/**
* proc_show_config()
- * @m - Synthetic file construction data
- * @v - File iterator
+ * @m: Synthetic file construction data
+ * @v: File iterator
*
* Display configuration information about the controller.
*/
@@ -2109,8 +2115,8 @@
/**
* proc_show_stat()
- * @m - Synthetic file construction data
- * @v - File iterator
+ * @m: Synthetic file construction data
+ * @v: File iterator
*
* Display statistical information about the I/O activity.
*/
@@ -2143,8 +2149,8 @@
/**
* proc_show_mbox()
- * @m - Synthetic file construction data
- * @v - File iterator
+ * @m: Synthetic file construction data
+ * @v: File iterator
*
* Display mailbox information for the last command issued. This information
* is good for debugging.
@@ -2171,8 +2177,8 @@
/**
* proc_show_rebuild_rate()
- * @m - Synthetic file construction data
- * @v - File iterator
+ * @m: Synthetic file construction data
+ * @v: File iterator
*
* Display current rebuild rate
*/
@@ -2214,8 +2220,8 @@
/**
* proc_show_battery()
- * @m - Synthetic file construction data
- * @v - File iterator
+ * @m: Synthetic file construction data
+ * @v: File iterator
*
* Display information about the battery module on the controller.
*/
@@ -2317,9 +2323,9 @@
/**
* proc_show_pdrv()
- * @m - Synthetic file construction data
- * @page - buffer to write the data in
- * @adapter - pointer to our soft state
+ * @m: Synthetic file construction data
+ * @adapter: pointer to our soft state
+ * @channel: channel
*
* Display information about the physical drives.
*/
@@ -2350,7 +2356,8 @@
}
- scsi_inq = pci_alloc_consistent(pdev, 256, &scsi_inq_dma_handle);
+ scsi_inq = dma_alloc_coherent(&pdev->dev, 256, &scsi_inq_dma_handle,
+ GFP_KERNEL);
if( scsi_inq == NULL ) {
seq_puts(m, "memory not available for scsi inq.\n");
goto free_inquiry;
@@ -2423,7 +2430,7 @@
}
free_pci:
- pci_free_consistent(pdev, 256, scsi_inq, scsi_inq_dma_handle);
+ dma_free_coherent(&pdev->dev, 256, scsi_inq, scsi_inq_dma_handle);
free_inquiry:
mega_free_inquiry(inquiry, dma_handle, pdev);
free_pdev:
@@ -2433,8 +2440,8 @@
/**
* proc_show_pdrv_ch0()
- * @m - Synthetic file construction data
- * @v - File iterator
+ * @m: Synthetic file construction data
+ * @v: File iterator
*
* Display information about the physical drives on physical channel 0.
*/
@@ -2447,8 +2454,8 @@
/**
* proc_show_pdrv_ch1()
- * @m - Synthetic file construction data
- * @v - File iterator
+ * @m: Synthetic file construction data
+ * @v: File iterator
*
* Display information about the physical drives on physical channel 1.
*/
@@ -2461,8 +2468,8 @@
/**
* proc_show_pdrv_ch2()
- * @m - Synthetic file construction data
- * @v - File iterator
+ * @m: Synthetic file construction data
+ * @v: File iterator
*
* Display information about the physical drives on physical channel 2.
*/
@@ -2475,8 +2482,8 @@
/**
* proc_show_pdrv_ch3()
- * @m - Synthetic file construction data
- * @v - File iterator
+ * @m: Synthetic file construction data
+ * @v: File iterator
*
* Display information about the physical drives on physical channel 3.
*/
@@ -2489,10 +2496,10 @@
/**
* proc_show_rdrv()
- * @m - Synthetic file construction data
- * @adapter - pointer to our soft state
- * @start - starting logical drive to display
- * @end - ending logical drive to display
+ * @m: Synthetic file construction data
+ * @adapter: pointer to our soft state
+ * @start: starting logical drive to display
+ * @end: ending logical drive to display
*
* We do not print the inquiry information since its already available through
* /proc/scsi/scsi interface
@@ -2543,8 +2550,8 @@
raid_inq.logdrv_info.num_ldrv;
}
- disk_array = pci_alloc_consistent(pdev, array_sz,
- &disk_array_dma_handle);
+ disk_array = dma_alloc_coherent(&pdev->dev, array_sz,
+ &disk_array_dma_handle, GFP_KERNEL);
if( disk_array == NULL ) {
seq_puts(m, "memory not available.\n");
@@ -2663,8 +2670,8 @@
}
free_pci:
- pci_free_consistent(pdev, array_sz, disk_array,
- disk_array_dma_handle);
+ dma_free_coherent(&pdev->dev, array_sz, disk_array,
+ disk_array_dma_handle);
free_inquiry:
mega_free_inquiry(inquiry, dma_handle, pdev);
free_pdev:
@@ -2674,8 +2681,8 @@
/**
* proc_show_rdrv_10()
- * @m - Synthetic file construction data
- * @v - File iterator
+ * @m: Synthetic file construction data
+ * @v: File iterator
*
* Display real time information about the logical drives 0 through 9.
*/
@@ -2688,8 +2695,8 @@
/**
* proc_show_rdrv_20()
- * @m - Synthetic file construction data
- * @v - File iterator
+ * @m: Synthetic file construction data
+ * @v: File iterator
*
* Display real time information about the logical drives 0 through 9.
*/
@@ -2702,8 +2709,8 @@
/**
* proc_show_rdrv_30()
- * @m - Synthetic file construction data
- * @v - File iterator
+ * @m: Synthetic file construction data
+ * @v: File iterator
*
* Display real time information about the logical drives 0 through 9.
*/
@@ -2716,8 +2723,8 @@
/**
* proc_show_rdrv_40()
- * @m - Synthetic file construction data
- * @v - File iterator
+ * @m: Synthetic file construction data
+ * @v: File iterator
*
* Display real time information about the logical drives 0 through 9.
*/
@@ -2729,8 +2736,8 @@
/**
* mega_create_proc_entry()
- * @index - index in soft state array
- * @parent - parent node for this /proc entry
+ * @index: index in soft state array
+ * @parent: parent node for this /proc entry
*
* Creates /proc entries for our controllers.
*/
@@ -2785,7 +2792,7 @@
#endif
-/**
+/*
* megaraid_biosparam()
*
* Return the disk geometry for a particular disk
@@ -2795,11 +2802,9 @@
sector_t capacity, int geom[])
{
adapter_t *adapter;
- unsigned char *bh;
int heads;
int sectors;
int cylinders;
- int rval;
/* Get pointer to host config structure */
adapter = (adapter_t *)sdev->host->hostdata;
@@ -2826,15 +2831,8 @@
geom[2] = cylinders;
}
else {
- bh = scsi_bios_ptable(bdev);
-
- if( bh ) {
- rval = scsi_partsize(bh, capacity,
- &geom[2], &geom[0], &geom[1]);
- kfree(bh);
- if( rval != -1 )
- return rval;
- }
+ if (scsi_partsize(bdev, capacity, geom))
+ return 0;
dev_info(&adapter->dev->dev,
"invalid partition on this disk on channel %d\n",
@@ -2863,7 +2861,7 @@
/**
* mega_init_scb()
- * @adapter - pointer to our soft state
+ * @adapter: pointer to our soft state
*
* Allocate memory for the various pointers in the scb structures:
* scatter-gather list pointer, passthru and extended passthru structure
@@ -2891,9 +2889,9 @@
scb->idx = i;
- scb->sgl64 = pci_alloc_consistent(adapter->dev,
- sizeof(mega_sgl64) * adapter->sglen,
- &scb->sgl_dma_addr);
+ scb->sgl64 = dma_alloc_coherent(&adapter->dev->dev,
+ sizeof(mega_sgl64) * adapter->sglen,
+ &scb->sgl_dma_addr, GFP_KERNEL);
scb->sgl = (mega_sglist *)scb->sgl64;
@@ -2903,9 +2901,9 @@
return -1;
}
- scb->pthru = pci_alloc_consistent(adapter->dev,
- sizeof(mega_passthru),
- &scb->pthru_dma_addr);
+ scb->pthru = dma_alloc_coherent(&adapter->dev->dev,
+ sizeof(mega_passthru),
+ &scb->pthru_dma_addr, GFP_KERNEL);
if( !scb->pthru ) {
dev_warn(&adapter->dev->dev, "RAID: Can't allocate passthru\n");
@@ -2913,9 +2911,9 @@
return -1;
}
- scb->epthru = pci_alloc_consistent(adapter->dev,
- sizeof(mega_ext_passthru),
- &scb->epthru_dma_addr);
+ scb->epthru = dma_alloc_coherent(&adapter->dev->dev,
+ sizeof(mega_ext_passthru),
+ &scb->epthru_dma_addr, GFP_KERNEL);
if( !scb->epthru ) {
dev_warn(&adapter->dev->dev,
@@ -2943,8 +2941,8 @@
/**
* megadev_open()
- * @inode - unused
- * @filep - unused
+ * @inode: unused
+ * @filep: unused
*
* Routines for the character/ioctl interface to the driver. Find out if this
* is a valid open.
@@ -2963,10 +2961,9 @@
/**
* megadev_ioctl()
- * @inode - Our device inode
- * @filep - unused
- * @cmd - ioctl command
- * @arg - user buffer
+ * @filep: Our device file
+ * @cmd: ioctl command
+ * @arg: user buffer
*
* ioctl entry point for our private ioctl interface. We move the data in from
* the user space, prepare the command (if necessary, convert the old MIMD
@@ -2986,14 +2983,13 @@
void *data = NULL; /* data to be transferred */
dma_addr_t data_dma_hndl; /* dma handle for data xfer area */
megacmd_t mc;
- megastat_t __user *ustats;
- int num_ldrv;
+#if MEGA_HAVE_STATS
+ megastat_t __user *ustats = NULL;
+ int num_ldrv = 0;
+#endif
u32 uxferaddr = 0;
struct pci_dev *pdev;
- ustats = NULL; /* avoid compilation warnings */
- num_ldrv = 0;
-
/*
* Make sure only USCSICMD are issued through this interface.
* MIMD application would still fire different command.
@@ -3157,9 +3153,9 @@
if( uioc.uioc_rmbox[0] == MEGA_MBOXCMD_PASSTHRU ) {
/* Passthru commands */
- pthru = pci_alloc_consistent(pdev,
- sizeof(mega_passthru),
- &pthru_dma_hndl);
+ pthru = dma_alloc_coherent(&pdev->dev,
+ sizeof(mega_passthru),
+ &pthru_dma_hndl, GFP_KERNEL);
if( pthru == NULL ) {
free_local_pdev(pdev);
@@ -3177,9 +3173,9 @@
if( copy_from_user(pthru, upthru,
sizeof(mega_passthru)) ) {
- pci_free_consistent(pdev,
- sizeof(mega_passthru), pthru,
- pthru_dma_hndl);
+ dma_free_coherent(&pdev->dev,
+ sizeof(mega_passthru),
+ pthru, pthru_dma_hndl);
free_local_pdev(pdev);
@@ -3190,15 +3186,16 @@
* Is there a data transfer
*/
if( pthru->dataxferlen ) {
- data = pci_alloc_consistent(pdev,
- pthru->dataxferlen,
- &data_dma_hndl);
+ data = dma_alloc_coherent(&pdev->dev,
+ pthru->dataxferlen,
+ &data_dma_hndl,
+ GFP_KERNEL);
if( data == NULL ) {
- pci_free_consistent(pdev,
- sizeof(mega_passthru),
- pthru,
- pthru_dma_hndl);
+ dma_free_coherent(&pdev->dev,
+ sizeof(mega_passthru),
+ pthru,
+ pthru_dma_hndl);
free_local_pdev(pdev);
@@ -3263,13 +3260,13 @@
freemem_and_return:
if( pthru->dataxferlen ) {
- pci_free_consistent(pdev,
- pthru->dataxferlen, data,
- data_dma_hndl);
+ dma_free_coherent(&pdev->dev,
+ pthru->dataxferlen, data,
+ data_dma_hndl);
}
- pci_free_consistent(pdev, sizeof(mega_passthru),
- pthru, pthru_dma_hndl);
+ dma_free_coherent(&pdev->dev, sizeof(mega_passthru),
+ pthru, pthru_dma_hndl);
free_local_pdev(pdev);
@@ -3282,8 +3279,10 @@
* Is there a data transfer
*/
if( uioc.xferlen ) {
- data = pci_alloc_consistent(pdev,
- uioc.xferlen, &data_dma_hndl);
+ data = dma_alloc_coherent(&pdev->dev,
+ uioc.xferlen,
+ &data_dma_hndl,
+ GFP_KERNEL);
if( data == NULL ) {
free_local_pdev(pdev);
@@ -3303,9 +3302,9 @@
if( copy_from_user(data, (char __user *)(unsigned long) uxferaddr,
uioc.xferlen) ) {
- pci_free_consistent(pdev,
- uioc.xferlen,
- data, data_dma_hndl);
+ dma_free_coherent(&pdev->dev,
+ uioc.xferlen, data,
+ data_dma_hndl);
free_local_pdev(pdev);
@@ -3326,9 +3325,9 @@
if( rval ) {
if( uioc.xferlen ) {
- pci_free_consistent(pdev,
- uioc.xferlen, data,
- data_dma_hndl);
+ dma_free_coherent(&pdev->dev,
+ uioc.xferlen, data,
+ data_dma_hndl);
}
free_local_pdev(pdev);
@@ -3348,9 +3347,8 @@
}
if( uioc.xferlen ) {
- pci_free_consistent(pdev,
- uioc.xferlen, data,
- data_dma_hndl);
+ dma_free_coherent(&pdev->dev, uioc.xferlen,
+ data, data_dma_hndl);
}
free_local_pdev(pdev);
@@ -3379,8 +3377,8 @@
/**
* mega_m_to_n()
- * @arg - user address
- * @uioc - new ioctl structure
+ * @arg: user address
+ * @uioc: new ioctl structure
*
* A thin layer to convert older mimd interface ioctl structure to NIT ioctl
* structure
@@ -3507,8 +3505,8 @@
/*
* mega_n_to_m()
- * @arg - user address
- * @mc - mailbox command
+ * @arg: user address
+ * @mc: mailbox command
*
* Updates the status information to the application, depending on application
* conforms to older mimd ioctl interface or newer NIT ioctl interface
@@ -3574,7 +3572,7 @@
/**
* mega_is_bios_enabled()
- * @adapter - pointer to our soft state
+ * @adapter: pointer to our soft state
*
* issue command to find out if the BIOS is enabled for this controller
*/
@@ -3583,7 +3581,6 @@
{
unsigned char raw_mbox[sizeof(struct mbox_out)];
mbox_t *mbox;
- int ret;
mbox = (mbox_t *)raw_mbox;
@@ -3596,8 +3593,7 @@
raw_mbox[0] = IS_BIOS_ENABLED;
raw_mbox[2] = GET_BIOS;
-
- ret = issue_scb_block(adapter, raw_mbox);
+ issue_scb_block(adapter, raw_mbox);
return *(char *)adapter->mega_buffer;
}
@@ -3605,7 +3601,7 @@
/**
* mega_enum_raid_scsi()
- * @adapter - pointer to our soft state
+ * @adapter: pointer to our soft state
*
* Find out what channels are RAID/SCSI. This information is used to
* differentiate the virtual channels and physical channels and to support
@@ -3660,7 +3656,7 @@
/**
* mega_get_boot_drv()
- * @adapter - pointer to our soft state
+ * @adapter: pointer to our soft state
*
* Find out which device is the boot device. Note, any logical drive or any
* phyical device (e.g., a CDROM) can be designated as a boot device.
@@ -3727,7 +3723,7 @@
/**
* mega_support_random_del()
- * @adapter - pointer to our soft state
+ * @adapter: pointer to our soft state
*
* Find out if this controller supports random deletion and addition of
* logical drives
@@ -3757,7 +3753,7 @@
/**
* mega_support_ext_cdb()
- * @adapter - pointer to our soft state
+ * @adapter: pointer to our soft state
*
* Find out if this firmware support cdblen > 10
*/
@@ -3785,8 +3781,8 @@
/**
* mega_del_logdrv()
- * @adapter - pointer to our soft state
- * @logdrv - logical drive to be deleted
+ * @adapter: pointer to our soft state
+ * @logdrv: logical drive to be deleted
*
* Delete the specified logical drive. It is the responsibility of the user
* app to let the OS know about this operation.
@@ -3871,7 +3867,7 @@
/**
* mega_get_max_sgl()
- * @adapter - pointer to our soft state
+ * @adapter: pointer to our soft state
*
* Find out the maximum number of scatter-gather elements supported by this
* version of the firmware
@@ -3917,7 +3913,7 @@
/**
* mega_support_cluster()
- * @adapter - pointer to our soft state
+ * @adapter: pointer to our soft state
*
* Find out if this firmware support cluster calls.
*/
@@ -3959,8 +3955,8 @@
#ifdef CONFIG_PROC_FS
/**
* mega_adapinq()
- * @adapter - pointer to our soft state
- * @dma_handle - DMA address of the buffer
+ * @adapter: pointer to our soft state
+ * @dma_handle: DMA address of the buffer
*
* Issue internal commands while interrupts are available.
* We only issue direct mailbox commands from within the driver. ioctl()
@@ -3992,11 +3988,12 @@
}
-/** mega_internal_dev_inquiry()
- * @adapter - pointer to our soft state
- * @ch - channel for this device
- * @tgt - ID of this device
- * @buf_dma_handle - DMA address of the buffer
+/**
+ * mega_internal_dev_inquiry()
+ * @adapter: pointer to our soft state
+ * @ch: channel for this device
+ * @tgt: ID of this device
+ * @buf_dma_handle: DMA address of the buffer
*
* Issue the scsi inquiry for the specified device.
*/
@@ -4017,8 +4014,8 @@
*/
if( make_local_pdev(adapter, &pdev) != 0 ) return -1;
- pthru = pci_alloc_consistent(pdev, sizeof(mega_passthru),
- &pthru_dma_handle);
+ pthru = dma_alloc_coherent(&pdev->dev, sizeof(mega_passthru),
+ &pthru_dma_handle, GFP_KERNEL);
if( pthru == NULL ) {
free_local_pdev(pdev);
@@ -4054,8 +4051,8 @@
rval = mega_internal_command(adapter, &mc, pthru);
- pci_free_consistent(pdev, sizeof(mega_passthru), pthru,
- pthru_dma_handle);
+ dma_free_coherent(&pdev->dev, sizeof(mega_passthru), pthru,
+ pthru_dma_handle);
free_local_pdev(pdev);
@@ -4065,9 +4062,9 @@
/**
* mega_internal_command()
- * @adapter - pointer to our soft state
- * @mc - the mailbox command
- * @pthru - Passthru structure for DCDB commands
+ * @adapter: pointer to our soft state
+ * @mc: the mailbox command
+ * @pthru: Passthru structure for DCDB commands
*
* Issue the internal commands in interrupt mode.
* The last argument is the address of the passthru structure if the command
@@ -4280,8 +4277,10 @@
/*
* Allocate buffer to issue internal commands.
*/
- adapter->mega_buffer = pci_alloc_consistent(adapter->dev,
- MEGA_BUFFER_SIZE, &adapter->buf_dma_handle);
+ adapter->mega_buffer = dma_alloc_coherent(&adapter->dev->dev,
+ MEGA_BUFFER_SIZE,
+ &adapter->buf_dma_handle,
+ GFP_KERNEL);
if (!adapter->mega_buffer) {
dev_warn(&pdev->dev, "out of RAM\n");
goto out_host_put;
@@ -4440,10 +4439,10 @@
/* Set the Mode of addressing to 64 bit if we can */
if ((adapter->flag & BOARD_64BIT) && (sizeof(dma_addr_t) == 8)) {
- pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
adapter->has_64bit_addr = 1;
} else {
- pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
adapter->has_64bit_addr = 0;
}
@@ -4482,15 +4481,15 @@
return 0;
out_free_mbox:
- pci_free_consistent(adapter->dev, sizeof(mbox64_t),
- adapter->una_mbox64, adapter->una_mbox64_dma);
+ dma_free_coherent(&adapter->dev->dev, sizeof(mbox64_t),
+ adapter->una_mbox64, adapter->una_mbox64_dma);
out_free_irq:
free_irq(adapter->host->irq, adapter);
out_free_scb_list:
kfree(adapter->scb_list);
out_free_cmd_buffer:
- pci_free_consistent(adapter->dev, MEGA_BUFFER_SIZE,
- adapter->mega_buffer, adapter->buf_dma_handle);
+ dma_free_coherent(&adapter->dev->dev, MEGA_BUFFER_SIZE,
+ adapter->mega_buffer, adapter->buf_dma_handle);
out_host_put:
scsi_host_put(host);
out_iounmap:
@@ -4564,11 +4563,11 @@
sprintf(buf, "hba%d", adapter->host->host_no);
remove_proc_subtree(buf, mega_proc_dir_entry);
- pci_free_consistent(adapter->dev, MEGA_BUFFER_SIZE,
- adapter->mega_buffer, adapter->buf_dma_handle);
+ dma_free_coherent(&adapter->dev->dev, MEGA_BUFFER_SIZE,
+ adapter->mega_buffer, adapter->buf_dma_handle);
kfree(adapter->scb_list);
- pci_free_consistent(adapter->dev, sizeof(mbox64_t),
- adapter->una_mbox64, adapter->una_mbox64_dma);
+ dma_free_coherent(&adapter->dev->dev, sizeof(mbox64_t),
+ adapter->una_mbox64, adapter->una_mbox64_dma);
scsi_host_put(host);
pci_disable_device(pdev);
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index f6ac819..4a27ac8 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -302,8 +302,8 @@
// definitions for the device attributes for exporting logical drive number
// for a scsi address (Host, Channel, Id, Lun)
-DEVICE_ATTR(megaraid_mbox_app_hndl, S_IRUSR, megaraid_sysfs_show_app_hndl,
- NULL);
+static DEVICE_ATTR(megaraid_mbox_app_hndl, S_IRUSR, megaraid_sysfs_show_app_hndl,
+ NULL);
// Host template initializer for megaraid mbox sysfs device attributes
static struct device_attribute *megaraid_shost_attrs[] = {
@@ -312,7 +312,7 @@
};
-DEVICE_ATTR(megaraid_mbox_ld, S_IRUSR, megaraid_sysfs_show_ldnum, NULL);
+static DEVICE_ATTR(megaraid_mbox_ld, S_IRUSR, megaraid_sysfs_show_ldnum, NULL);
// Host template initializer for megaraid mbox sysfs device attributes
static struct device_attribute *megaraid_sdev_attrs[] = {
@@ -731,7 +731,7 @@
goto out_free_raid_dev;
}
- raid_dev->baseaddr = ioremap_nocache(raid_dev->baseport, 128);
+ raid_dev->baseaddr = ioremap(raid_dev->baseport, 128);
if (!raid_dev->baseaddr) {
@@ -1581,7 +1581,7 @@
return NULL;
}
- /* Fall through */
+ fallthrough;
case READ_CAPACITY:
/*
@@ -3304,7 +3304,6 @@
* megaraid_mbox_display_scb - display SCB information, mostly debug purposes
* @adapter : controller's soft state
* @scb : SCB to be displayed
- * @level : debug level for console print
*
* Diplay information about the given SCB iff the current debug level is
* verbose.
@@ -3972,7 +3971,8 @@
/**
* megaraid_sysfs_show_app_hndl - display application handle for this adapter
- * @cdev : class device object representation for the host
+ * @dev : class device object representation for the host
+ * @attr : device attribute (unused)
* @buf : buffer to send data to
*
* Display the handle used by the applications while executing management
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index fcfbf33..422b726 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -41,10 +41,6 @@
static void mraid_mm_free_adp_resources(mraid_mmadp_t *);
static void mraid_mm_teardown_dma_pools(mraid_mmadp_t *);
-#ifdef CONFIG_COMPAT
-static long mraid_mm_compat_ioctl(struct file *, unsigned int, unsigned long);
-#endif
-
MODULE_AUTHOR("LSI Logic Corporation");
MODULE_DESCRIPTION("LSI Logic Management Module");
MODULE_LICENSE("GPL");
@@ -68,9 +64,7 @@
static const struct file_operations lsi_fops = {
.open = mraid_mm_open,
.unlocked_ioctl = mraid_mm_unlocked_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = mraid_mm_compat_ioctl,
-#endif
+ .compat_ioctl = compat_ptr_ioctl,
.owner = THIS_MODULE,
.llseek = noop_llseek,
};
@@ -101,7 +95,6 @@
/**
* mraid_mm_ioctl - module entry-point for ioctls
- * @inode : inode (ignored)
* @filep : file operations pointer (ignored)
* @cmd : ioctl command
* @arg : user ioctl packet
@@ -224,7 +217,6 @@
{
int err;
- /* inconsistent: mraid_mm_compat_ioctl doesn't take the BKL */
mutex_lock(&mraid_mm_mutex);
err = mraid_mm_ioctl(filep, cmd, arg);
mutex_unlock(&mraid_mm_mutex);
@@ -1237,25 +1229,6 @@
}
-#ifdef CONFIG_COMPAT
-/**
- * mraid_mm_compat_ioctl - 32bit to 64bit ioctl conversion routine
- * @filep : file operations pointer (ignored)
- * @cmd : ioctl command
- * @arg : user ioctl packet
- */
-static long
-mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd,
- unsigned long arg)
-{
- int err;
-
- err = mraid_mm_ioctl(filep, cmd, arg);
-
- return err;
-}
-#endif
-
/**
* mraid_mm_exit - Module exit point
*/
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 3d43ac9..6b8ec57 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -21,8 +21,10 @@
/*
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "07.710.50.00-rc1"
-#define MEGASAS_RELDATE "June 28, 2019"
+#define MEGASAS_VERSION "07.714.04.00-rc1"
+#define MEGASAS_RELDATE "Apr 14, 2020"
+
+#define MEGASAS_MSIX_NAME_LEN 32
/*
* Device IDs
@@ -509,7 +511,7 @@
*/
struct MR_PD_PROGRESS {
struct {
-#ifndef MFI_BIG_ENDIAN
+#ifndef __BIG_ENDIAN_BITFIELD
u32 rbld:1;
u32 patrol:1;
u32 clear:1;
@@ -535,7 +537,7 @@
};
struct {
-#ifndef MFI_BIG_ENDIAN
+#ifndef __BIG_ENDIAN_BITFIELD
u32 rbld:1;
u32 patrol:1;
u32 clear:1;
@@ -2203,6 +2205,7 @@
};
struct megasas_irq_context {
+ char name[MEGASAS_MSIX_NAME_LEN];
struct megasas_instance *instance;
u32 MSIxIndex;
u32 os_irq;
@@ -2230,9 +2233,9 @@
/* JBOD Queue depth definitions */
#define MEGASAS_SATA_QD 32
-#define MEGASAS_SAS_QD 64
+#define MEGASAS_SAS_QD 256
#define MEGASAS_DEFAULT_PD_QD 64
-#define MEGASAS_NVME_QD 32
+#define MEGASAS_NVME_QD 64
#define MR_DEFAULT_NVME_PAGE_SIZE 4096
#define MR_DEFAULT_NVME_PAGE_SHIFT 12
@@ -2649,10 +2652,11 @@
};
enum DCMD_RETURN_STATUS {
- DCMD_SUCCESS = 0,
- DCMD_TIMEOUT = 1,
- DCMD_FAILED = 2,
- DCMD_NOT_FIRED = 3,
+ DCMD_SUCCESS = 0x00,
+ DCMD_TIMEOUT = 0x01,
+ DCMD_FAILED = 0x02,
+ DCMD_BUSY = 0x03,
+ DCMD_INIT = 0xff,
};
u8
@@ -2717,4 +2721,24 @@
int ocr_context);
int megasas_irqpoll(struct irq_poll *irqpoll, int budget);
void megasas_dump_fusion_io(struct scsi_cmnd *scmd);
+u32 megasas_readl(struct megasas_instance *instance,
+ const volatile void __iomem *addr);
+struct megasas_cmd *megasas_get_cmd(struct megasas_instance *instance);
+void megasas_return_cmd(struct megasas_instance *instance,
+ struct megasas_cmd *cmd);
+int megasas_issue_polled(struct megasas_instance *instance,
+ struct megasas_cmd *cmd);
+void megaraid_sas_kill_hba(struct megasas_instance *instance);
+void megasas_check_and_restore_queue_depth(struct megasas_instance *instance);
+void megasas_start_timer(struct megasas_instance *instance);
+int megasas_sriov_start_heartbeat(struct megasas_instance *instance,
+ int initial);
+int megasas_alloc_cmds(struct megasas_instance *instance);
+void megasas_free_cmds(struct megasas_instance *instance);
+
+void megasas_init_debugfs(void);
+void megasas_exit_debugfs(void);
+void megasas_setup_debugfs(struct megasas_instance *instance);
+void megasas_destroy_debugfs(struct megasas_instance *instance);
+
#endif /*LSI_MEGARAID_SAS_H */
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 6700d43..1a70cc9 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -77,11 +77,11 @@
module_param(resetwaittime, int, 0444);
MODULE_PARM_DESC(resetwaittime, "Wait time in (1-180s) after I/O timeout before resetting adapter. Default: 180s");
-int smp_affinity_enable = 1;
+static int smp_affinity_enable = 1;
module_param(smp_affinity_enable, int, 0444);
MODULE_PARM_DESC(smp_affinity_enable, "SMP affinity feature enable/disable Default: enable(1)");
-int rdpq_enable = 1;
+static int rdpq_enable = 1;
module_param(rdpq_enable, int, 0444);
MODULE_PARM_DESC(rdpq_enable, "Allocate reply queue in chunks for large queue depth enable/disable Default: enable(1)");
@@ -89,7 +89,7 @@
module_param(dual_qdepth_disable, int, 0444);
MODULE_PARM_DESC(dual_qdepth_disable, "Disable dual queue depth feature. Default: 0");
-unsigned int scmd_timeout = MEGASAS_DEFAULT_CMD_TIMEOUT;
+static unsigned int scmd_timeout = MEGASAS_DEFAULT_CMD_TIMEOUT;
module_param(scmd_timeout, int, 0444);
MODULE_PARM_DESC(scmd_timeout, "scsi command timeout (10-90s), default 90s. See megasas_reset_timer.");
@@ -201,13 +201,9 @@
static bool support_pci_lane_margining;
/* define lock for aen poll */
-spinlock_t poll_aen_lock;
+static spinlock_t poll_aen_lock;
extern struct dentry *megasas_debugfs_root;
-extern void megasas_init_debugfs(void);
-extern void megasas_exit_debugfs(void);
-extern void megasas_setup_debugfs(struct megasas_instance *instance);
-extern void megasas_destroy_debugfs(struct megasas_instance *instance);
void
megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
@@ -435,14 +431,14 @@
}
-/**
-* The following functions are defined for xscale
-* (deviceid : 1064R, PERC5) controllers
-*/
+/*
+ * The following functions are defined for xscale
+ * (deviceid : 1064R, PERC5) controllers
+ */
/**
* megasas_enable_intr_xscale - Enables interrupts
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static inline void
megasas_enable_intr_xscale(struct megasas_instance *instance)
@@ -458,7 +454,7 @@
/**
* megasas_disable_intr_xscale -Disables interrupt
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static inline void
megasas_disable_intr_xscale(struct megasas_instance *instance)
@@ -474,7 +470,7 @@
/**
* megasas_read_fw_status_reg_xscale - returns the current FW status value
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static u32
megasas_read_fw_status_reg_xscale(struct megasas_instance *instance)
@@ -483,7 +479,7 @@
}
/**
* megasas_clear_interrupt_xscale - Check & clear interrupt
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static int
megasas_clear_intr_xscale(struct megasas_instance *instance)
@@ -517,9 +513,10 @@
/**
* megasas_fire_cmd_xscale - Sends command to the FW
- * @frame_phys_addr : Physical address of cmd
- * @frame_count : Number of frames for the command
- * @regs : MFI register set
+ * @instance: Adapter soft state
+ * @frame_phys_addr : Physical address of cmd
+ * @frame_count : Number of frames for the command
+ * @regs : MFI register set
*/
static inline void
megasas_fire_cmd_xscale(struct megasas_instance *instance,
@@ -537,7 +534,8 @@
/**
* megasas_adp_reset_xscale - For controller reset
- * @regs: MFI register set
+ * @instance: Adapter soft state
+ * @regs: MFI register set
*/
static int
megasas_adp_reset_xscale(struct megasas_instance *instance,
@@ -578,7 +576,8 @@
/**
* megasas_check_reset_xscale - For controller reset check
- * @regs: MFI register set
+ * @instance: Adapter soft state
+ * @regs: MFI register set
*/
static int
megasas_check_reset_xscale(struct megasas_instance *instance,
@@ -607,19 +606,19 @@
.issue_dcmd = megasas_issue_dcmd,
};
-/**
-* This is the end of set of functions & definitions specific
-* to xscale (deviceid : 1064R, PERC5) controllers
-*/
+/*
+ * This is the end of set of functions & definitions specific
+ * to xscale (deviceid : 1064R, PERC5) controllers
+ */
-/**
-* The following functions are defined for ppc (deviceid : 0x60)
-* controllers
-*/
+/*
+ * The following functions are defined for ppc (deviceid : 0x60)
+ * controllers
+ */
/**
* megasas_enable_intr_ppc - Enables interrupts
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static inline void
megasas_enable_intr_ppc(struct megasas_instance *instance)
@@ -637,7 +636,7 @@
/**
* megasas_disable_intr_ppc - Disable interrupt
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static inline void
megasas_disable_intr_ppc(struct megasas_instance *instance)
@@ -653,7 +652,7 @@
/**
* megasas_read_fw_status_reg_ppc - returns the current FW status value
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static u32
megasas_read_fw_status_reg_ppc(struct megasas_instance *instance)
@@ -663,7 +662,7 @@
/**
* megasas_clear_interrupt_ppc - Check & clear interrupt
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static int
megasas_clear_intr_ppc(struct megasas_instance *instance)
@@ -696,9 +695,10 @@
/**
* megasas_fire_cmd_ppc - Sends command to the FW
- * @frame_phys_addr : Physical address of cmd
- * @frame_count : Number of frames for the command
- * @regs : MFI register set
+ * @instance: Adapter soft state
+ * @frame_phys_addr: Physical address of cmd
+ * @frame_count: Number of frames for the command
+ * @regs: MFI register set
*/
static inline void
megasas_fire_cmd_ppc(struct megasas_instance *instance,
@@ -716,7 +716,8 @@
/**
* megasas_check_reset_ppc - For controller reset check
- * @regs: MFI register set
+ * @instance: Adapter soft state
+ * @regs: MFI register set
*/
static int
megasas_check_reset_ppc(struct megasas_instance *instance,
@@ -746,7 +747,7 @@
/**
* megasas_enable_intr_skinny - Enables interrupts
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static inline void
megasas_enable_intr_skinny(struct megasas_instance *instance)
@@ -764,7 +765,7 @@
/**
* megasas_disable_intr_skinny - Disables interrupt
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static inline void
megasas_disable_intr_skinny(struct megasas_instance *instance)
@@ -780,7 +781,7 @@
/**
* megasas_read_fw_status_reg_skinny - returns the current FW status value
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static u32
megasas_read_fw_status_reg_skinny(struct megasas_instance *instance)
@@ -790,7 +791,7 @@
/**
* megasas_clear_interrupt_skinny - Check & clear interrupt
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static int
megasas_clear_intr_skinny(struct megasas_instance *instance)
@@ -833,9 +834,10 @@
/**
* megasas_fire_cmd_skinny - Sends command to the FW
- * @frame_phys_addr : Physical address of cmd
- * @frame_count : Number of frames for the command
- * @regs : MFI register set
+ * @instance: Adapter soft state
+ * @frame_phys_addr: Physical address of cmd
+ * @frame_count: Number of frames for the command
+ * @regs: MFI register set
*/
static inline void
megasas_fire_cmd_skinny(struct megasas_instance *instance,
@@ -855,7 +857,8 @@
/**
* megasas_check_reset_skinny - For controller reset check
- * @regs: MFI register set
+ * @instance: Adapter soft state
+ * @regs: MFI register set
*/
static int
megasas_check_reset_skinny(struct megasas_instance *instance,
@@ -884,14 +887,14 @@
};
-/**
-* The following functions are defined for gen2 (deviceid : 0x78 0x79)
-* controllers
-*/
+/*
+ * The following functions are defined for gen2 (deviceid : 0x78 0x79)
+ * controllers
+ */
/**
* megasas_enable_intr_gen2 - Enables interrupts
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static inline void
megasas_enable_intr_gen2(struct megasas_instance *instance)
@@ -910,7 +913,7 @@
/**
* megasas_disable_intr_gen2 - Disables interrupt
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static inline void
megasas_disable_intr_gen2(struct megasas_instance *instance)
@@ -926,7 +929,7 @@
/**
* megasas_read_fw_status_reg_gen2 - returns the current FW status value
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static u32
megasas_read_fw_status_reg_gen2(struct megasas_instance *instance)
@@ -936,7 +939,7 @@
/**
* megasas_clear_interrupt_gen2 - Check & clear interrupt
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static int
megasas_clear_intr_gen2(struct megasas_instance *instance)
@@ -969,11 +972,13 @@
return mfiStatus;
}
+
/**
* megasas_fire_cmd_gen2 - Sends command to the FW
- * @frame_phys_addr : Physical address of cmd
- * @frame_count : Number of frames for the command
- * @regs : MFI register set
+ * @instance: Adapter soft state
+ * @frame_phys_addr: Physical address of cmd
+ * @frame_count: Number of frames for the command
+ * @regs: MFI register set
*/
static inline void
megasas_fire_cmd_gen2(struct megasas_instance *instance,
@@ -991,7 +996,8 @@
/**
* megasas_adp_reset_gen2 - For controller reset
- * @regs: MFI register set
+ * @instance: Adapter soft state
+ * @reg_set: MFI register set
*/
static int
megasas_adp_reset_gen2(struct megasas_instance *instance,
@@ -1051,7 +1057,8 @@
/**
* megasas_check_reset_gen2 - For controller reset check
- * @regs: MFI register set
+ * @instance: Adapter soft state
+ * @regs: MFI register set
*/
static int
megasas_check_reset_gen2(struct megasas_instance *instance,
@@ -1079,10 +1086,10 @@
.issue_dcmd = megasas_issue_dcmd,
};
-/**
-* This is the end of set of functions & definitions
-* specific to gen2 (deviceid : 0x78, 0x79) controllers
-*/
+/*
+ * This is the end of set of functions & definitions
+ * specific to gen2 (deviceid : 0x78, 0x79) controllers
+ */
/*
* Template added for TB (Fusion)
@@ -1107,7 +1114,7 @@
if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) {
dev_err(&instance->pdev->dev, "Failed from %s %d\n",
__func__, __LINE__);
- return DCMD_NOT_FIRED;
+ return DCMD_INIT;
}
instance->instancet->issue_dcmd(instance, cmd);
@@ -1131,19 +1138,19 @@
struct megasas_cmd *cmd, int timeout)
{
int ret = 0;
- cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS;
+ cmd->cmd_status_drv = DCMD_INIT;
if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) {
dev_err(&instance->pdev->dev, "Failed from %s %d\n",
__func__, __LINE__);
- return DCMD_NOT_FIRED;
+ return DCMD_INIT;
}
instance->instancet->issue_dcmd(instance, cmd);
if (timeout) {
ret = wait_event_timeout(instance->int_cmd_wait_q,
- cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS, timeout * HZ);
+ cmd->cmd_status_drv != DCMD_INIT, timeout * HZ);
if (!ret) {
dev_err(&instance->pdev->dev,
"DCMD(opcode: 0x%x) is timed out, func:%s\n",
@@ -1152,10 +1159,9 @@
}
} else
wait_event(instance->int_cmd_wait_q,
- cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS);
+ cmd->cmd_status_drv != DCMD_INIT);
- return (cmd->cmd_status_drv == MFI_STAT_OK) ?
- DCMD_SUCCESS : DCMD_FAILED;
+ return cmd->cmd_status_drv;
}
/**
@@ -1198,19 +1204,19 @@
cpu_to_le32(upper_32_bits(cmd_to_abort->frame_phys_addr));
cmd->sync_cmd = 1;
- cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS;
+ cmd->cmd_status_drv = DCMD_INIT;
if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) {
dev_err(&instance->pdev->dev, "Failed from %s %d\n",
__func__, __LINE__);
- return DCMD_NOT_FIRED;
+ return DCMD_INIT;
}
instance->instancet->issue_dcmd(instance, cmd);
if (timeout) {
ret = wait_event_timeout(instance->abort_cmd_wait_q,
- cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS, timeout * HZ);
+ cmd->cmd_status_drv != DCMD_INIT, timeout * HZ);
if (!ret) {
opcode = cmd_to_abort->frame->dcmd.opcode;
dev_err(&instance->pdev->dev,
@@ -1220,13 +1226,12 @@
}
} else
wait_event(instance->abort_cmd_wait_q,
- cmd->cmd_status_drv != MFI_STAT_INVALID_STATUS);
+ cmd->cmd_status_drv != DCMD_INIT);
cmd->sync_cmd = 0;
megasas_return_cmd(instance, cmd);
- return (cmd->cmd_status_drv == MFI_STAT_OK) ?
- DCMD_SUCCESS : DCMD_FAILED;
+ return cmd->cmd_status_drv;
}
/**
@@ -1619,7 +1624,7 @@
/**
* megasas_cmd_type - Checks if the cmd is for logical drive/sysPD
* and whether it's RW or non RW
- * @scmd: SCSI command
+ * @cmd: SCSI command
*
*/
inline int megasas_cmd_type(struct scsi_cmnd *cmd)
@@ -1759,8 +1764,8 @@
/**
* megasas_queue_command - Queue entry point
+ * @shost: adapter SCSI host
* @scmd: SCSI command to be queued
- * @done: Callback entry point
*/
static int
megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
@@ -1900,6 +1905,10 @@
mr_device_priv_data->is_tm_capable =
raid->capability.tmCapable;
+
+ if (!raid->flags.isEPD)
+ sdev->no_write_same = 1;
+
} else if (instance->use_seqnum_jbod_fp) {
pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) +
sdev->id;
@@ -1993,9 +2002,9 @@
if (is_target_prop) {
tgt_device_qd = le32_to_cpu(instance->tgt_prop->device_qdepth);
- if (tgt_device_qd &&
- (tgt_device_qd <= instance->host->can_queue))
- device_qd = tgt_device_qd;
+ if (tgt_device_qd)
+ device_qd = min(instance->host->can_queue,
+ (int)tgt_device_qd);
}
if (instance->enable_sdev_max_qd && interface_type != UNKNOWN_DRIVE)
@@ -2184,6 +2193,12 @@
void megaraid_sas_kill_hba(struct megasas_instance *instance)
{
+ if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) {
+ dev_warn(&instance->pdev->dev,
+ "Adapter already dead, skipping kill HBA\n");
+ return;
+ }
+
/* Set critical error to block I/O & ioctls in case caller didn't */
atomic_set(&instance->adprecovery, MEGASAS_HW_CRITICAL_ERROR);
/* Wait 1 second to ensure IO or ioctls in build have posted */
@@ -2760,7 +2775,7 @@
"reset queue\n",
reset_cmd);
- reset_cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS;
+ reset_cmd->cmd_status_drv = DCMD_INIT;
instance->instancet->fire_cmd(instance,
reset_cmd->frame_phys_addr,
0, instance->reg_set);
@@ -2942,11 +2957,7 @@
/**
* megasas_dump_reg_set - This function will print hexdump of register set
- * @buf: Buffer to be dumped
- * @sz: Size in bytes
- * @format: Different formats of dumping e.g. format=n will
- * cause only 'n' 32 bit words to be dumped in a
- * single line.
+ * @reg_set: Register set to be dumped
*/
inline void
megasas_dump_reg_set(void __iomem *reg_set)
@@ -3013,15 +3024,17 @@
u32 __iomem *reg = (u32 __iomem *)reg_set;
for (i = 0; i < sz / sizeof(u32); i++) {
- bytes_wrote += snprintf(loc + bytes_wrote, PAGE_SIZE,
- "%08x: %08x\n", (i * 4),
- readl(®[i]));
+ bytes_wrote += scnprintf(loc + bytes_wrote,
+ PAGE_SIZE - bytes_wrote,
+ "%08x: %08x\n", (i * 4),
+ readl(®[i]));
}
return bytes_wrote;
}
/**
* megasas_reset_bus_host - Bus & host reset handler entry point
+ * @scmd: Mid-layer SCSI command
*/
static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
{
@@ -3450,7 +3463,6 @@
.bios_param = megasas_bios_param,
.change_queue_depth = scsi_change_queue_depth,
.max_segment_size = 0xffffffff,
- .no_write_same = 1,
};
/**
@@ -3466,7 +3478,11 @@
megasas_complete_int_cmd(struct megasas_instance *instance,
struct megasas_cmd *cmd)
{
- cmd->cmd_status_drv = cmd->frame->io.cmd_status;
+ if (cmd->cmd_status_drv == DCMD_INIT)
+ cmd->cmd_status_drv =
+ (cmd->frame->io.cmd_status == MFI_STAT_OK) ?
+ DCMD_SUCCESS : DCMD_FAILED;
+
wake_up(&instance->int_cmd_wait_q);
}
@@ -3485,7 +3501,7 @@
{
if (cmd->sync_cmd) {
cmd->sync_cmd = 0;
- cmd->cmd_status_drv = 0;
+ cmd->cmd_status_drv = DCMD_SUCCESS;
wake_up(&instance->abort_cmd_wait_q);
}
}
@@ -3556,7 +3572,7 @@
megasas_complete_int_cmd(instance, cmd);
break;
}
- /* fall through */
+ fallthrough;
case MFI_CMD_LD_READ:
case MFI_CMD_LD_WRITE:
@@ -3781,7 +3797,7 @@
dev_notice(&instance->pdev->dev, "%p synchronous cmd"
"on the internal reset queue,"
"issue it again.\n", cmd);
- cmd->cmd_status_drv = MFI_STAT_INVALID_STATUS;
+ cmd->cmd_status_drv = DCMD_INIT;
instance->instancet->fire_cmd(instance,
cmd->frame_phys_addr,
0, instance->reg_set);
@@ -3819,7 +3835,7 @@
megasas_register_aen(instance, seq_num, class_locale.word);
}
-/**
+/*
* Move the internal reset pending commands to a deferred queue.
*
* We move the commands pending at internal reset time to a
@@ -3827,7 +3843,7 @@
* completion of the internal reset sequence. if the internal reset
* did not complete in time, the kernel reset handler would flush
* these commands.
- **/
+ */
static void
megasas_internal_reset_defer_cmds(struct megasas_instance *instance)
{
@@ -4005,8 +4021,11 @@
tasklet_schedule(&instance->isr_tasklet);
return IRQ_HANDLED;
}
+
/**
* megasas_isr - isr entry point
+ * @irq: IRQ number
+ * @devp: IRQ context address
*/
static irqreturn_t megasas_isr(int irq, void *devp)
{
@@ -4028,6 +4047,7 @@
/**
* megasas_transition_to_ready - Move the FW to READY state
* @instance: Adapter soft state
+ * @ocr: Adapter reset state
*
* During the initialization, FW passes can potentially be in any one of
* several possible states. If the FW in operational, waiting-for-handshake
@@ -4785,7 +4805,7 @@
/**
* megasas_ld_list_query - Returns FW's ld_list structure
* @instance: Adapter soft state
- * @ld_list: ld_list structure
+ * @query_type: ld_list structure type
*
* Issues an internal command (DCMD) to get the FW's controller PD
* list structure. This information is mainly used to find out SYSTEM
@@ -5601,9 +5621,11 @@
pdev = instance->pdev;
instance->irq_context[0].instance = instance;
instance->irq_context[0].MSIxIndex = 0;
+ snprintf(instance->irq_context->name, MEGASAS_MSIX_NAME_LEN, "%s%u",
+ "megasas", instance->host->host_no);
if (request_irq(pci_irq_vector(pdev, 0),
instance->instancet->service_isr, IRQF_SHARED,
- "megasas", &instance->irq_context[0])) {
+ instance->irq_context->name, &instance->irq_context[0])) {
dev_err(&instance->pdev->dev,
"Failed to register IRQ from %s %d\n",
__func__, __LINE__);
@@ -5635,8 +5657,10 @@
for (i = 0; i < instance->msix_vectors; i++) {
instance->irq_context[i].instance = instance;
instance->irq_context[i].MSIxIndex = i;
+ snprintf(instance->irq_context[i].name, MEGASAS_MSIX_NAME_LEN, "%s%u-msix%u",
+ "megasas", instance->host->host_no, i);
if (request_irq(pci_irq_vector(pdev, i),
- instance->instancet->service_isr, 0, "megasas",
+ instance->instancet->service_isr, 0, instance->irq_context[i].name,
&instance->irq_context[i])) {
dev_err(&instance->pdev->dev,
"Failed to register IRQ for vector %d.\n", i);
@@ -5698,7 +5722,6 @@
/**
* megasas_setup_jbod_map - setup jbod map for FP seq_number.
* @instance: Adapter soft state
- * @is_probe: Driver probe check
*
* Return 0 on success.
*/
@@ -5933,7 +5956,7 @@
}
base_addr = pci_resource_start(instance->pdev, instance->bar);
- instance->reg_set = ioremap_nocache(base_addr, 8192);
+ instance->reg_set = ioremap(base_addr, 8192);
if (!instance->reg_set) {
dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to map IO mem\n");
@@ -6539,7 +6562,7 @@
* megasas_register_aen - Registers for asynchronous event notification
* @instance: Adapter soft state
* @seq_num: The starting sequence number
- * @class_locale: Class of the event
+ * @class_locale_word: Class of the event
*
* This function subscribes for AEN for events beyond the @seq_num. It requests
* to be notified if and only if the event is of type @class_locale
@@ -7059,8 +7082,9 @@
* megasas_alloc_ctrl_dma_buffers - Allocate consistent DMA buffers during
* driver load time
*
- * @instance- Adapter soft instance
- * @return- O for SUCCESS
+ * @instance: Adapter soft instance
+ *
+ * @return: O for SUCCESS
*/
static inline
int megasas_alloc_ctrl_dma_buffers(struct megasas_instance *instance)
@@ -7663,7 +7687,7 @@
int rval;
struct Scsi_Host *host;
struct megasas_instance *instance;
- int irq_flags = PCI_IRQ_LEGACY;
+ u32 status_reg;
instance = pci_get_drvdata(pdev);
@@ -7691,9 +7715,35 @@
/*
* We expect the FW state to be READY
*/
- if (megasas_transition_to_ready(instance, 0))
- goto fail_ready_state;
+ if (megasas_transition_to_ready(instance, 0)) {
+ dev_info(&instance->pdev->dev,
+ "Failed to transition controller to ready from %s!\n",
+ __func__);
+ if (instance->adapter_type != MFI_SERIES) {
+ status_reg =
+ instance->instancet->read_fw_status_reg(instance);
+ if (!(status_reg & MFI_RESET_ADAPTER) ||
+ ((megasas_adp_reset_wait_for_ready
+ (instance, true, 0)) == FAILED))
+ goto fail_ready_state;
+ } else {
+ atomic_set(&instance->fw_reset_no_pci_access, 1);
+ instance->instancet->adp_reset
+ (instance, instance->reg_set);
+ atomic_set(&instance->fw_reset_no_pci_access, 0);
+
+ /* waiting for about 30 seconds before retry */
+ ssleep(30);
+
+ if (megasas_transition_to_ready(instance, 0))
+ goto fail_ready_state;
+ }
+
+ dev_info(&instance->pdev->dev,
+ "FW restarted successfully from %s!\n",
+ __func__);
+ }
if (megasas_set_dma_mask(instance))
goto fail_set_dma_mask;
@@ -7705,16 +7755,15 @@
atomic_set(&instance->ldio_outstanding, 0);
/* Now re-enable MSI-X */
- if (instance->msix_vectors) {
- irq_flags = PCI_IRQ_MSIX;
- if (instance->smp_affinity_enable)
- irq_flags |= PCI_IRQ_AFFINITY;
+ if (instance->msix_vectors)
+ megasas_alloc_irq_vectors(instance);
+
+ if (!instance->msix_vectors) {
+ rval = pci_alloc_irq_vectors(instance->pdev, 1, 1,
+ PCI_IRQ_LEGACY);
+ if (rval < 0)
+ goto fail_reenable_msix;
}
- rval = pci_alloc_irq_vectors(instance->pdev, 1,
- instance->msix_vectors ?
- instance->msix_vectors : 1, irq_flags);
- if (rval < 0)
- goto fail_reenable_msix;
megasas_setup_reply_map(instance);
@@ -7964,7 +8013,7 @@
/**
* megasas_shutdown - Shutdown entry point
- * @device: Generic device structure
+ * @pdev: Generic device structure
*/
static void megasas_shutdown(struct pci_dev *pdev)
{
@@ -7989,8 +8038,10 @@
pci_free_irq_vectors(instance->pdev);
}
-/**
+/*
* megasas_mgmt_open - char node "open" entry point
+ * @inode: char node inode
+ * @filep: char node file
*/
static int megasas_mgmt_open(struct inode *inode, struct file *filep)
{
@@ -8003,8 +8054,11 @@
return 0;
}
-/**
+/*
* megasas_mgmt_fasync - Async notifier registration from applications
+ * @fd: char node file descriptor number
+ * @filep: char node file
+ * @mode: notifier on/off
*
* This function adds the calling process to a driver global queue. When an
* event occurs, SIGIO will be sent to all processes in this queue.
@@ -8030,9 +8084,11 @@
return rc;
}
-/**
+/*
* megasas_mgmt_poll - char node "poll" entry point
- * */
+ * @filep: char node file
+ * @wait: Events to poll for
+ */
static __poll_t megasas_mgmt_poll(struct file *file, poll_table *wait)
{
__poll_t mask;
@@ -8090,7 +8146,8 @@
/**
* megasas_mgmt_fw_ioctl - Issues management ioctls to FW
* @instance: Adapter soft state
- * @argp: User's ioctl packet
+ * @user_ioc: User's ioctl packet
+ * @ioc: ioctl packet
*/
static int
megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
@@ -8107,6 +8164,7 @@
dma_addr_t sense_handle;
void *sense_ptr;
u32 opcode = 0;
+ int ret = DCMD_SUCCESS;
memset(kbuff_arr, 0, sizeof(kbuff_arr));
@@ -8251,13 +8309,18 @@
* cmd to the SCSI mid-layer
*/
cmd->sync_cmd = 1;
- if (megasas_issue_blocked_cmd(instance, cmd, 0) == DCMD_NOT_FIRED) {
+
+ ret = megasas_issue_blocked_cmd(instance, cmd, 0);
+ switch (ret) {
+ case DCMD_INIT:
+ case DCMD_BUSY:
cmd->sync_cmd = 0;
dev_err(&instance->pdev->dev,
"return -EBUSY from %s %d cmd 0x%x opcode 0x%x cmd->cmd_status_drv 0x%x\n",
- __func__, __LINE__, cmd->frame->hdr.cmd, opcode,
- cmd->cmd_status_drv);
- return -EBUSY;
+ __func__, __LINE__, cmd->frame->hdr.cmd, opcode,
+ cmd->cmd_status_drv);
+ error = -EBUSY;
+ goto out;
}
cmd->sync_cmd = 0;
@@ -8428,6 +8491,9 @@
/**
* megasas_mgmt_ioctl - char node ioctl entry point
+ * @file: char device file pointer
+ * @cmd: ioctl command
+ * @arg: ioctl command arguments address
*/
static long
megasas_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index 8bfb46d..83f69c3 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -80,21 +80,20 @@
}
/**
- * @param dividend : Dividend
- * @param divisor : Divisor
+ * mega_div64_32 - Do a 64-bit division
+ * @dividend: Dividend
+ * @divisor: Divisor
*
* @return quotient
**/
-u64 mega_div64_32(uint64_t dividend, uint32_t divisor)
+static u64 mega_div64_32(uint64_t dividend, uint32_t divisor)
{
- u32 remainder;
- u64 d;
+ u64 d = dividend;
if (!divisor)
printk(KERN_ERR "megasas : DIVISOR is zero in mod fn\n");
- d = dividend;
- remainder = do_div(d, divisor);
+ do_div(d, divisor);
return d;
}
@@ -371,7 +370,7 @@
return 1;
}
-u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
+static u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk,
struct MR_DRV_RAID_MAP_ALL *map)
{
struct MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map);
@@ -390,9 +389,8 @@
le64_to_cpu(quad->logEnd) && (mega_mod64(row - le64_to_cpu(quad->logStart),
le32_to_cpu(quad->diff))) == 0) {
if (span_blk != NULL) {
- u64 blk, debugBlk;
+ u64 blk;
blk = mega_div64_32((row-le64_to_cpu(quad->logStart)), le32_to_cpu(quad->diff));
- debugBlk = blk;
blk = (blk + le64_to_cpu(quad->offsetInSpan)) << raid->stripeShift;
*span_blk = blk;
@@ -422,7 +420,7 @@
* div_error - Devide error code.
*/
-u32 mr_spanset_get_span_block(struct megasas_instance *instance,
+static u32 mr_spanset_get_span_block(struct megasas_instance *instance,
u32 ld, u64 row, u64 *span_blk, struct MR_DRV_RAID_MAP_ALL *map)
{
struct fusion_context *fusion = instance->ctrl_context;
@@ -647,7 +645,7 @@
}
/* This Function will return Phys arm */
-u8 get_arm(struct megasas_instance *instance, u32 ld, u8 span, u64 stripe,
+static u8 get_arm(struct megasas_instance *instance, u32 ld, u8 span, u64 stripe,
struct MR_DRV_RAID_MAP_ALL *map)
{
struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map);
@@ -703,9 +701,7 @@
__le16 *pDevHandle = &io_info->devHandle;
u8 *pPdInterface = &io_info->pd_interface;
u32 logArm, rowMod, armQ, arm;
- struct fusion_context *fusion;
- fusion = instance->ctrl_context;
*pDevHandle = cpu_to_le16(MR_DEVHANDLE_INVALID);
/*Get row and span from io_info for Uneven Span IO.*/
@@ -792,7 +788,7 @@
* span - Span number
* block - Absolute Block number in the physical disk
*/
-u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
+static u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
u16 stripRef, struct IO_REQUEST_INFO *io_info,
struct RAID_CONTEXT *pRAID_Context,
struct MR_DRV_RAID_MAP_ALL *map)
@@ -805,9 +801,7 @@
u64 *pdBlock = &io_info->pdBlock;
__le16 *pDevHandle = &io_info->devHandle;
u8 *pPdInterface = &io_info->pd_interface;
- struct fusion_context *fusion;
- fusion = instance->ctrl_context;
*pDevHandle = cpu_to_le16(MR_DEVHANDLE_INVALID);
row = mega_div64_32(stripRow, raid->rowDataSize);
@@ -1351,7 +1345,7 @@
}
}
-u8 megasas_get_best_arm_pd(struct megasas_instance *instance,
+static u8 megasas_get_best_arm_pd(struct megasas_instance *instance,
struct LD_LOAD_BALANCE_INFO *lbInfo,
struct IO_REQUEST_INFO *io_info,
struct MR_DRV_RAID_MAP_ALL *drv_map)
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index a78a702..13022a4 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -48,9 +48,6 @@
#include "megaraid_sas.h"
-extern void megasas_free_cmds(struct megasas_instance *instance);
-extern struct megasas_cmd *megasas_get_cmd(struct megasas_instance
- *instance);
extern void
megasas_complete_cmd(struct megasas_instance *instance,
struct megasas_cmd *cmd, u8 alt_status);
@@ -58,24 +55,14 @@
wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd,
int seconds);
-void
-megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd);
-int megasas_alloc_cmds(struct megasas_instance *instance);
int
megasas_clear_intr_fusion(struct megasas_instance *instance);
-int
-megasas_issue_polled(struct megasas_instance *instance,
- struct megasas_cmd *cmd);
-void
-megasas_check_and_restore_queue_depth(struct megasas_instance *instance);
int megasas_transition_to_ready(struct megasas_instance *instance, int ocr);
-void megaraid_sas_kill_hba(struct megasas_instance *instance);
extern u32 megasas_dbg_lvl;
int megasas_sriov_start_heartbeat(struct megasas_instance *instance,
int initial);
-void megasas_start_timer(struct megasas_instance *instance);
extern struct megasas_mgmt_info megasas_mgmt_info;
extern unsigned int resetwaittime;
extern unsigned int dual_qdepth_disable;
@@ -84,15 +71,13 @@
static inline
void megasas_configure_queue_sizes(struct megasas_instance *instance);
static void megasas_fusion_crash_dump(struct megasas_instance *instance);
-extern u32 megasas_readl(struct megasas_instance *instance,
- const volatile void __iomem *addr);
/**
* megasas_adp_reset_wait_for_ready - initiate chip reset and wait for
* controller to come to ready state
- * @instance - adapter's soft state
- * @do_adp_reset - If true, do a chip reset
- * @ocr_context - If called from OCR context this will
+ * @instance: adapter's soft state
+ * @do_adp_reset: If true, do a chip reset
+ * @ocr_context: If called from OCR context this will
* be set to 1, else 0
*
* This function initates a chip reset followed by a wait for controller to
@@ -146,10 +131,10 @@
/**
* megasas_check_same_4gb_region - check if allocation
* crosses same 4GB boundary or not
- * @instance - adapter's soft instance
- * start_addr - start address of DMA allocation
- * size - size of allocation in bytes
- * return - true : allocation does not cross same
+ * @instance: adapter's soft instance
+ * @start_addr: start address of DMA allocation
+ * @size: size of allocation in bytes
+ * @return: true : allocation does not cross same
* 4GB boundary
* false: allocation crosses same
* 4GB boundary
@@ -174,9 +159,9 @@
/**
* megasas_enable_intr_fusion - Enables interrupts
- * @regs: MFI register set
+ * @instance: adapter's soft instance
*/
-void
+static void
megasas_enable_intr_fusion(struct megasas_instance *instance)
{
struct megasas_register_set __iomem *regs;
@@ -196,9 +181,9 @@
/**
* megasas_disable_intr_fusion - Disables interrupt
- * @regs: MFI register set
+ * @instance: adapter's soft instance
*/
-void
+static void
megasas_disable_intr_fusion(struct megasas_instance *instance)
{
u32 mask = 0xFFFFFFFF;
@@ -238,6 +223,7 @@
/**
* megasas_get_cmd_fusion - Get a command from the free pool
* @instance: Adapter soft state
+ * @blk_tag: Command tag
*
* Returns a blk_tag indexed mpt frame
*/
@@ -309,8 +295,8 @@
/**
* megasas_fusion_update_can_queue - Do all Adapter Queue depth related calculations here
- * @instance: Adapter soft state
- * fw_boot_context: Whether this function called during probe or after OCR
+ * @instance: Adapter soft state
+ * @fw_boot_context: Whether this function called during probe or after OCR
*
* This function is only for fusion controllers.
* Update host can queue, if firmware downgrade max supported firmware commands.
@@ -364,6 +350,35 @@
instance->max_fw_cmds = instance->max_fw_cmds-1;
}
}
+
+static inline void
+megasas_get_msix_index(struct megasas_instance *instance,
+ struct scsi_cmnd *scmd,
+ struct megasas_cmd_fusion *cmd,
+ u8 data_arms)
+{
+ int sdev_busy;
+
+ /* nr_hw_queue = 1 for MegaRAID */
+ struct blk_mq_hw_ctx *hctx =
+ scmd->device->request_queue->queue_hw_ctx[0];
+
+ sdev_busy = atomic_read(&hctx->nr_active);
+
+ if (instance->perf_mode == MR_BALANCED_PERF_MODE &&
+ sdev_busy > (data_arms * MR_DEVICE_HIGH_IOPS_DEPTH))
+ cmd->request_desc->SCSIIO.MSIxIndex =
+ mega_mod64((atomic64_add_return(1, &instance->high_iops_outstanding) /
+ MR_HIGH_IOPS_BATCH_COUNT), instance->low_latency_index_start);
+ else if (instance->msix_load_balance)
+ cmd->request_desc->SCSIIO.MSIxIndex =
+ (mega_mod64(atomic64_add_return(1, &instance->total_io_count),
+ instance->msix_vectors));
+ else
+ cmd->request_desc->SCSIIO.MSIxIndex =
+ instance->reply_map[raw_smp_processor_id()];
+}
+
/**
* megasas_free_cmds_fusion - Free all the cmds in the free cmd pool
* @instance: Adapter soft state
@@ -987,6 +1002,7 @@
* wait_and_poll - Issues a polling command
* @instance: Adapter soft state
* @cmd: Command packet to be issued
+ * @seconds: Maximum poll time
*
* For polling, MFI requires the cmd_status to be set to 0xFF before posting.
*/
@@ -1313,7 +1329,9 @@
}
if (ret == DCMD_TIMEOUT)
- megaraid_sas_kill_hba(instance);
+ dev_warn(&instance->pdev->dev,
+ "%s DCMD timed out, continue without JBOD sequence map\n",
+ __func__);
if (ret == DCMD_SUCCESS)
instance->pd_seq_map_id++;
@@ -1395,7 +1413,9 @@
ret = megasas_issue_polled(instance, cmd);
if (ret == DCMD_TIMEOUT)
- megaraid_sas_kill_hba(instance);
+ dev_warn(&instance->pdev->dev,
+ "%s DCMD timed out, RAID map is disabled\n",
+ __func__);
megasas_return_cmd(instance, cmd);
@@ -1873,6 +1893,7 @@
/**
* megasas_fault_detect_work - Worker function of
* FW fault handling workqueue.
+ * @work: FW fault work struct
*/
static void
megasas_fault_detect_work(struct work_struct *work)
@@ -1956,11 +1977,13 @@
/**
* map_cmd_status - Maps FW cmd status to OS cmd status
- * @cmd : Pointer to cmd
- * @status : status of cmd returned by FW
- * @ext_status : ext status of cmd returned by FW
+ * @fusion: fusion context
+ * @scmd: Pointer to cmd
+ * @status: status of cmd returned by FW
+ * @ext_status: ext status of cmd returned by FW
+ * @data_length: command data length
+ * @sense: command sense data
*/
-
static void
map_cmd_status(struct fusion_context *fusion,
struct scsi_cmnd *scmd, u8 status, u8 ext_status,
@@ -2037,7 +2060,6 @@
megasas_is_prp_possible(struct megasas_instance *instance,
struct scsi_cmnd *scmd, int sge_count)
{
- int i;
u32 data_length = 0;
struct scatterlist *sg_scmd;
bool build_prp = false;
@@ -2066,63 +2088,6 @@
build_prp = true;
}
-/*
- * Below code detects gaps/holes in IO data buffers.
- * What does holes/gaps mean?
- * Any SGE except first one in a SGL starts at non NVME page size
- * aligned address OR Any SGE except last one in a SGL ends at
- * non NVME page size boundary.
- *
- * Driver has already informed block layer by setting boundary rules for
- * bio merging done at NVME page size boundary calling kernel API
- * blk_queue_virt_boundary inside slave_config.
- * Still there is possibility of IO coming with holes to driver because of
- * IO merging done by IO scheduler.
- *
- * With SCSI BLK MQ enabled, there will be no IO with holes as there is no
- * IO scheduling so no IO merging.
- *
- * With SCSI BLK MQ disabled, IO scheduler may attempt to merge IOs and
- * then sending IOs with holes.
- *
- * Though driver can request block layer to disable IO merging by calling-
- * blk_queue_flag_set(QUEUE_FLAG_NOMERGES, sdev->request_queue) but
- * user may tune sysfs parameter- nomerges again to 0 or 1.
- *
- * If in future IO scheduling is enabled with SCSI BLK MQ,
- * this algorithm to detect holes will be required in driver
- * for SCSI BLK MQ enabled case as well.
- *
- *
- */
- scsi_for_each_sg(scmd, sg_scmd, sge_count, i) {
- if ((i != 0) && (i != (sge_count - 1))) {
- if (mega_mod64(sg_dma_len(sg_scmd), mr_nvme_pg_size) ||
- mega_mod64(sg_dma_address(sg_scmd),
- mr_nvme_pg_size)) {
- build_prp = false;
- break;
- }
- }
-
- if ((sge_count > 1) && (i == 0)) {
- if ((mega_mod64((sg_dma_address(sg_scmd) +
- sg_dma_len(sg_scmd)),
- mr_nvme_pg_size))) {
- build_prp = false;
- break;
- }
- }
-
- if ((sge_count > 1) && (i == (sge_count - 1))) {
- if (mega_mod64(sg_dma_address(sg_scmd),
- mr_nvme_pg_size)) {
- build_prp = false;
- break;
- }
- }
- }
-
return build_prp;
}
@@ -2259,7 +2224,7 @@
* @scp: SCSI command from the mid-layer
* @sgl_ptr: SGL to be filled in
* @cmd: cmd we are working on
- * @sge_count sge count
+ * @sge_count: sge count
*
*/
static void
@@ -2368,9 +2333,12 @@
/**
* megasas_set_pd_lba - Sets PD LBA
- * @cdb: CDB
+ * @io_request: IO request
* @cdb_len: cdb length
- * @start_blk: Start block of IO
+ * @io_info: IO information
+ * @scp: SCSI command
+ * @local_map_ptr: Raid map
+ * @ref_tag: Primary reference tag
*
* Used to set the PD LBA in CDB for FP IOs
*/
@@ -2628,10 +2596,12 @@
* affinity (cpu of the controller) and raid_flags in the raid context
* based on IO type.
*
+ * @fusion: Fusion context
* @praid_context: IO RAID context
* @raid: LD raid map
* @fp_possible: Is fast path possible?
* @is_read: Is read IO?
+ * @scsi_buff_len: SCSI command buffer length
*
*/
static void
@@ -2826,19 +2796,7 @@
fp_possible = (io_info.fpOkForIo > 0) ? true : false;
}
- if ((instance->perf_mode == MR_BALANCED_PERF_MODE) &&
- atomic_read(&scp->device->device_busy) >
- (io_info.data_arms * MR_DEVICE_HIGH_IOPS_DEPTH))
- cmd->request_desc->SCSIIO.MSIxIndex =
- mega_mod64((atomic64_add_return(1, &instance->high_iops_outstanding) /
- MR_HIGH_IOPS_BATCH_COUNT), instance->low_latency_index_start);
- else if (instance->msix_load_balance)
- cmd->request_desc->SCSIIO.MSIxIndex =
- (mega_mod64(atomic64_add_return(1, &instance->total_io_count),
- instance->msix_vectors));
- else
- cmd->request_desc->SCSIIO.MSIxIndex =
- instance->reply_map[raw_smp_processor_id()];
+ megasas_get_msix_index(instance, scp, cmd, io_info.data_arms);
if (instance->adapter_type >= VENTURA_SERIES) {
/* FP for Optimal raid level 1.
@@ -2977,7 +2935,7 @@
/**
* megasas_build_ld_nonrw_fusion - prepares non rw ios for virtual disk
* @instance: Adapter soft state
- * @scp: SCSI command
+ * @scmd: SCSI command
* @cmd: Command to be prepared
*
* Prepares the io_request frame for non-rw io cmds for vd.
@@ -3065,7 +3023,7 @@
/**
* megasas_build_syspd_fusion - prepares rw/non-rw ios for syspd
* @instance: Adapter soft state
- * @scp: SCSI command
+ * @scmd: SCSI command
* @cmd: Command to be prepared
* @fp_possible: parameter to detect fast path or firmware path io.
*
@@ -3159,18 +3117,7 @@
cmd->request_desc->SCSIIO.DevHandle = io_request->DevHandle;
- if ((instance->perf_mode == MR_BALANCED_PERF_MODE) &&
- atomic_read(&scmd->device->device_busy) > MR_DEVICE_HIGH_IOPS_DEPTH)
- cmd->request_desc->SCSIIO.MSIxIndex =
- mega_mod64((atomic64_add_return(1, &instance->high_iops_outstanding) /
- MR_HIGH_IOPS_BATCH_COUNT), instance->low_latency_index_start);
- else if (instance->msix_load_balance)
- cmd->request_desc->SCSIIO.MSIxIndex =
- (mega_mod64(atomic64_add_return(1, &instance->total_io_count),
- instance->msix_vectors));
- else
- cmd->request_desc->SCSIIO.MSIxIndex =
- instance->reply_map[raw_smp_processor_id()];
+ megasas_get_msix_index(instance, scmd, cmd, 1);
if (!fp_possible) {
/* system pd firmware path */
@@ -3453,7 +3400,7 @@
* megasas_complete_r1_command -
* completes R1 FP write commands which has valid peer smid
* @instance: Adapter soft state
- * @cmd_fusion: MPT command frame
+ * @cmd: MPT command frame
*
*/
static inline void
@@ -3507,6 +3454,9 @@
/**
* complete_cmd_fusion - Completes command
* @instance: Adapter soft state
+ * @MSIxIndex: MSI number
+ * @irq_context: IRQ context
+ *
* Completes all commands that is in reply descriptor queue
*/
static int
@@ -3584,7 +3534,7 @@
atomic_dec(&lbinfo->scsi_pending_cmds[cmd_fusion->pd_r1_lb]);
cmd_fusion->scmd->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG;
}
- /* Fall through - and complete IO */
+ fallthrough; /* and complete IO */
case MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST: /* LD-IO Path */
atomic_dec(&instance->fw_outstanding);
if (cmd_fusion->r1_alt_dev_handle == MR_DEVHANDLE_INVALID) {
@@ -3682,6 +3632,7 @@
/**
* megasas_enable_irq_poll() - enable irqpoll
+ * @instance: Adapter soft state
*/
static void megasas_enable_irq_poll(struct megasas_instance *instance)
{
@@ -3698,7 +3649,7 @@
/**
* megasas_sync_irqs - Synchronizes all IRQs owned by adapter
- * @instance: Adapter soft state
+ * @instance_addr: Adapter soft state address
*/
static void megasas_sync_irqs(unsigned long instance_addr)
{
@@ -3756,7 +3707,7 @@
/**
* megasas_complete_cmd_dpc_fusion - Completes command
- * @instance: Adapter soft state
+ * @instance_addr: Adapter soft state address
*
* Tasklet to complete cmds
*/
@@ -3782,6 +3733,8 @@
/**
* megasas_isr_fusion - isr entry point
+ * @irq: IRQ number
+ * @devp: IRQ context
*/
static irqreturn_t megasas_isr_fusion(int irq, void *devp)
{
@@ -3814,7 +3767,7 @@
/**
* build_mpt_mfi_pass_thru - builds a cmd fo MFI Pass thru
* @instance: Adapter soft state
- * mfi_cmd: megasas_cmd pointer
+ * @mfi_cmd: megasas_cmd pointer
*
*/
static void
@@ -3931,7 +3884,7 @@
/**
* megasas_read_fw_status_reg_fusion - returns the current FW status value
- * @regs: MFI register set
+ * @instance: Adapter soft state
*/
static u32
megasas_read_fw_status_reg_fusion(struct megasas_instance *instance)
@@ -3942,7 +3895,7 @@
/**
* megasas_alloc_host_crash_buffer - Host buffers for Crash dump collection from Firmware
* @instance: Controller's soft instance
- * return: Number of allocated host crash buffers
+ * @return: Number of allocated host crash buffers
*/
static void
megasas_alloc_host_crash_buffer(struct megasas_instance *instance)
@@ -3980,6 +3933,7 @@
/**
* megasas_adp_reset_fusion - For controller reset
+ * @instance: Controller's soft instance
* @regs: MFI register set
*/
static int
@@ -4057,6 +4011,7 @@
/**
* megasas_check_reset_fusion - For controller reset check
+ * @instance: Controller's soft instance
* @regs: MFI register set
*/
static int
@@ -4223,7 +4178,8 @@
* megasas_refire_mgmt_cmd : Re-fire management commands
* @instance: Controller's soft instance
*/
-static void megasas_refire_mgmt_cmd(struct megasas_instance *instance)
+static void megasas_refire_mgmt_cmd(struct megasas_instance *instance,
+ bool return_ioctl)
{
int j;
struct megasas_cmd_fusion *cmd_fusion;
@@ -4232,7 +4188,7 @@
union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc;
struct MPI2_RAID_SCSI_IO_REQUEST *scsi_io_req;
u16 smid;
- bool refire_cmd = 0;
+ bool refire_cmd = false;
u8 result;
u32 opcode = 0;
@@ -4288,6 +4244,16 @@
break;
}
+ if (return_ioctl && cmd_mfi->sync_cmd &&
+ cmd_mfi->frame->hdr.cmd != MFI_CMD_ABORT) {
+ dev_err(&instance->pdev->dev,
+ "return -EBUSY from %s %d cmd 0x%x opcode 0x%x\n",
+ __func__, __LINE__, cmd_mfi->frame->hdr.cmd,
+ le32_to_cpu(cmd_mfi->frame->dcmd.opcode));
+ cmd_mfi->cmd_status_drv = DCMD_BUSY;
+ result = COMPLETE_CMD;
+ }
+
scsi_io_req = (struct MPI2_RAID_SCSI_IO_REQUEST *)
cmd_fusion->io_request;
if (scsi_io_req->Function == MPI2_FUNCTION_SCSI_TASK_MGMT)
@@ -4308,6 +4274,37 @@
}
/*
+ * megasas_return_polled_cmds: Return polled mode commands back to the pool
+ * before initiating an OCR.
+ * @instance: Controller's soft instance
+ */
+static void
+megasas_return_polled_cmds(struct megasas_instance *instance)
+{
+ int i;
+ struct megasas_cmd_fusion *cmd_fusion;
+ struct fusion_context *fusion;
+ struct megasas_cmd *cmd_mfi;
+
+ fusion = instance->ctrl_context;
+
+ for (i = instance->max_scsi_cmds; i < instance->max_fw_cmds; i++) {
+ cmd_fusion = fusion->cmd_list[i];
+ cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
+
+ if (cmd_mfi->flags & DRV_DCMD_POLLED_MODE) {
+ if (megasas_dbg_lvl & OCR_DEBUG)
+ dev_info(&instance->pdev->dev,
+ "%s %d return cmd 0x%x opcode 0x%x\n",
+ __func__, __LINE__, cmd_mfi->frame->hdr.cmd,
+ le32_to_cpu(cmd_mfi->frame->dcmd.opcode));
+ cmd_mfi->flags &= ~DRV_DCMD_POLLED_MODE;
+ megasas_return_cmd(instance, cmd_mfi);
+ }
+ }
+}
+
+/*
* megasas_track_scsiio : Track SCSI IOs outstanding to a SCSI device
* @instance: per adapter struct
* @channel: the channel assigned by the OS
@@ -4344,8 +4341,8 @@
/**
* megasas_tm_response_code - translation of device response code
- * @ioc: per adapter object
- * @mpi_reply: MPI reply returned by firmware
+ * @instance: Controller's soft instance
+ * @mpi_reply: MPI reply returned by firmware
*
* Return nothing.
*/
@@ -4400,9 +4397,9 @@
* @device_handle: device handle
* @channel: the channel assigned by the OS
* @id: the id assigned by the OS
- * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in megaraid_sas_fusion.c)
* @smid_task: smid assigned to the task
- * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
+ * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in megaraid_sas_fusion.c)
+ * @mr_device_priv_data: private data
* Context: user
*
* MegaRaid use MPT interface for Task Magement request.
@@ -4669,12 +4666,12 @@
"attempting task abort! scmd(0x%p) tm_dev_handle 0x%x\n",
scmd, devhandle);
- mr_device_priv_data->tm_busy = 1;
+ mr_device_priv_data->tm_busy = true;
ret = megasas_issue_tm(instance, devhandle,
scmd->device->channel, scmd->device->id, smid,
MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
mr_device_priv_data);
- mr_device_priv_data->tm_busy = 0;
+ mr_device_priv_data->tm_busy = false;
mutex_unlock(&instance->reset_mutex);
scmd_printk(KERN_INFO, scmd, "task abort %s!! scmd(0x%p)\n",
@@ -4739,12 +4736,12 @@
sdev_printk(KERN_INFO, scmd->device,
"attempting target reset! scmd(0x%p) tm_dev_handle: 0x%x\n",
scmd, devhandle);
- mr_device_priv_data->tm_busy = 1;
+ mr_device_priv_data->tm_busy = true;
ret = megasas_issue_tm(instance, devhandle,
scmd->device->channel, scmd->device->id, 0,
MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
mr_device_priv_data);
- mr_device_priv_data->tm_busy = 0;
+ mr_device_priv_data->tm_busy = false;
mutex_unlock(&instance->reset_mutex);
scmd_printk(KERN_NOTICE, scmd, "target reset %s!!\n",
(ret == SUCCESS) ? "SUCCESS" : "FAILED");
@@ -4961,7 +4958,9 @@
goto kill_hba;
}
- megasas_refire_mgmt_cmd(instance);
+ megasas_refire_mgmt_cmd(instance,
+ (i == (MEGASAS_FUSION_MAX_RESET_TRIES - 1)
+ ? 1 : 0));
/* Reset load balance info */
if (fusion->load_balance_info)
@@ -4969,8 +4968,16 @@
(sizeof(struct LD_LOAD_BALANCE_INFO) *
MAX_LOGICAL_DRIVES_EXT));
- if (!megasas_get_map_info(instance))
+ if (!megasas_get_map_info(instance)) {
megasas_sync_map_info(instance);
+ } else {
+ /*
+ * Return pending polled mode cmds before
+ * retrying OCR
+ */
+ megasas_return_polled_cmds(instance);
+ continue;
+ }
megasas_setup_jbod_map(instance);
@@ -4997,6 +5004,15 @@
megasas_set_dynamic_target_properties(sdev, is_target_prop);
}
+ status_reg = instance->instancet->read_fw_status_reg
+ (instance);
+ abs_state = status_reg & MFI_STATE_MASK;
+ if (abs_state != MFI_STATE_OPERATIONAL) {
+ dev_info(&instance->pdev->dev,
+ "Adapter is not OPERATIONAL, state 0x%x for scsi:%d\n",
+ abs_state, instance->host->host_no);
+ goto out;
+ }
atomic_set(&instance->adprecovery, MEGASAS_HBA_OPERATIONAL);
dev_info(&instance->pdev->dev,
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.h b/drivers/scsi/megaraid/megaraid_sas_fusion.h
index dd2e37e..30de4b0 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.h
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.h
@@ -774,7 +774,7 @@
struct MR_CPU_AFFINITY_MASK {
union {
struct {
-#ifndef MFI_BIG_ENDIAN
+#ifndef __BIG_ENDIAN_BITFIELD
u8 hw_path:1;
u8 cpu0:1;
u8 cpu1:1;
@@ -865,9 +865,20 @@
u8 regTypeReqOnRead;
__le16 seqNum;
- struct {
- u32 ldSyncRequired:1;
- u32 reserved:31;
+struct {
+#ifndef __BIG_ENDIAN_BITFIELD
+ u32 ldSyncRequired:1;
+ u32 regTypeReqOnReadIsValid:1;
+ u32 isEPD:1;
+ u32 enableSLDOnAllRWIOs:1;
+ u32 reserved:28;
+#else
+ u32 reserved:28;
+ u32 enableSLDOnAllRWIOs:1;
+ u32 isEPD:1;
+ u32 regTypeReqOnReadIsValid:1;
+ u32 ldSyncRequired:1;
+#endif
} flags;
u8 LUN[8]; /* 0x24 8 byte LUN field used for SCSI IO's */
@@ -878,7 +889,7 @@
/* 0x30 - 0x33, Logical block size for the LD */
u32 logical_block_length;
struct {
-#ifndef MFI_BIG_ENDIAN
+#ifndef __BIG_ENDIAN_BITFIELD
/* 0x34, P_I_EXPONENT from READ CAPACITY 16 */
u32 ld_pi_exp:4;
/* 0x34, LOGICAL BLOCKS PER PHYSICAL
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index 4dd50db..0a9f4e4 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -31,9 +31,9 @@
#include <linux/reboot.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
+#include <linux/pgtable.h>
#include <asm/dbdma.h>
#include <asm/io.h>
-#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/irq.h>
#include <asm/hydra.h>
@@ -1457,7 +1457,7 @@
/* huh? we expected a phase mismatch */
ms->n_msgin = 0;
ms->msgphase = msg_in;
- /* fall through */
+ fallthrough;
case msg_in:
/* should have some message bytes in fifo */
diff --git a/drivers/scsi/mpt3sas/Kconfig b/drivers/scsi/mpt3sas/Kconfig
index a072187..8620945 100644
--- a/drivers/scsi/mpt3sas/Kconfig
+++ b/drivers/scsi/mpt3sas/Kconfig
@@ -46,7 +46,7 @@
select SCSI_SAS_ATTRS
select RAID_ATTRS
select IRQ_POLL
- ---help---
+ help
This driver supports PCI-Express SAS 12Gb/s Host Adapters.
config SCSI_MPT2SAS_MAX_SGE
@@ -54,7 +54,7 @@
depends on PCI && SCSI && SCSI_MPT3SAS
default "128"
range 16 256
- ---help---
+ help
This option allows you to specify the maximum number of scatter-
gather entries per I/O. The driver default is 128, which matches
MAX_PHYS_SEGMENTS in most kernels. However in SuSE kernels this
@@ -66,7 +66,7 @@
depends on PCI && SCSI && SCSI_MPT3SAS
default "128"
range 16 256
- ---help---
+ help
This option allows you to specify the maximum number of scatter-
gather entries per I/O. The driver default is 128, which matches
MAX_PHYS_SEGMENTS in most kernels. However in SuSE kernels this
@@ -78,6 +78,6 @@
default n
select SCSI_MPT3SAS
depends on PCI && SCSI
- ---help---
+ help
Dummy config option for backwards compatiblity: configure the MPT3SAS
driver instead.
diff --git a/drivers/scsi/mpt3sas/Makefile b/drivers/scsi/mpt3sas/Makefile
index 84fb3fb..e76d994 100644
--- a/drivers/scsi/mpt3sas/Makefile
+++ b/drivers/scsi/mpt3sas/Makefile
@@ -7,4 +7,5 @@
mpt3sas_transport.o \
mpt3sas_ctl.o \
mpt3sas_trigger_diag.o \
- mpt3sas_warpdrive.o
+ mpt3sas_warpdrive.o \
+ mpt3sas_debugfs.o \
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2.h b/drivers/scsi/mpt3sas/mpi/mpi2.h
index 18b1e31..ed3923f 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2.h
@@ -122,6 +122,9 @@
* 08-28-18 02.00.53 Bumped MPI2_HEADER_VERSION_UNIT.
* Added MPI2_IOCSTATUS_FAILURE
* 12-17-18 02.00.54 Bumped MPI2_HEADER_VERSION_UNIT
+ * 06-24-19 02.00.55 Bumped MPI2_HEADER_VERSION_UNIT
+ * 08-01-19 02.00.56 Bumped MPI2_HEADER_VERSION_UNIT
+ * 10-02-19 02.00.57 Bumped MPI2_HEADER_VERSION_UNIT
* --------------------------------------------------------------------------
*/
@@ -162,7 +165,7 @@
/* Unit and Dev versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT (0x36)
+#define MPI2_HEADER_VERSION_UNIT (0x39)
#define MPI2_HEADER_VERSION_DEV (0x00)
#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
@@ -181,6 +184,7 @@
#define MPI2_IOC_STATE_READY (0x10000000)
#define MPI2_IOC_STATE_OPERATIONAL (0x20000000)
#define MPI2_IOC_STATE_FAULT (0x40000000)
+#define MPI2_IOC_STATE_COREDUMP (0x50000000)
#define MPI2_IOC_STATE_MASK (0xF0000000)
#define MPI2_IOC_STATE_SHIFT (28)
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
index 3a6871a..43a3bf8 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
@@ -249,6 +249,8 @@
* 08-28-18 02.00.46 Added NVMs Write Cache flag to IOUnitPage1
* Added DMDReport Delay Time defines to PCIeIOUnitPage1
* 12-17-18 02.00.47 Swap locations of Slotx2 and Slotx4 in ManPage 7.
+ * 08-01-19 02.00.49 Add MPI26_MANPAGE7_FLAG_X2_X4_SLOT_INFO_VALID
+ * Add MPI26_IOUNITPAGE1_NVME_WRCACHE_SHIFT
*/
#ifndef MPI2_CNFG_H
@@ -891,6 +893,8 @@
#define MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER (0x00000002)
#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001)
+#define MPI26_MANPAGE7_FLAG_CONN_LANE_USE_PINOUT (0x00000020)
+#define MPI26_MANPAGE7_FLAG_X2_X4_SLOT_INFO_VALID (0x00000010)
/*
*Generic structure to use for product-specific manufacturing pages
@@ -962,9 +966,10 @@
/* IO Unit Page 1 Flags defines */
#define MPI26_IOUNITPAGE1_NVME_WRCACHE_MASK (0x00030000)
-#define MPI26_IOUNITPAGE1_NVME_WRCACHE_ENABLE (0x00000000)
-#define MPI26_IOUNITPAGE1_NVME_WRCACHE_DISABLE (0x00010000)
-#define MPI26_IOUNITPAGE1_NVME_WRCACHE_NO_CHANGE (0x00020000)
+#define MPI26_IOUNITPAGE1_NVME_WRCACHE_SHIFT (16)
+#define MPI26_IOUNITPAGE1_NVME_WRCACHE_NO_CHANGE (0x00000000)
+#define MPI26_IOUNITPAGE1_NVME_WRCACHE_ENABLE (0x00010000)
+#define MPI26_IOUNITPAGE1_NVME_WRCACHE_DISABLE (0x00020000)
#define MPI2_IOUNITPAGE1_ATA_SECURITY_FREEZE_LOCK (0x00004000)
#define MPI25_IOUNITPAGE1_NEW_DEVICE_FAST_PATH_DISABLE (0x00002000)
#define MPI25_IOUNITPAGE1_DISABLE_FAST_PATH (0x00001000)
@@ -3931,7 +3936,13 @@
U32 MaximumDataTransferSize; /*0x0C */
U32 Capabilities; /*0x10 */
U16 NOIOB; /* 0x14 */
- U16 Reserved2; /* 0x16 */
+ U16 ShutdownLatency; /* 0x16 */
+ U16 VendorID; /* 0x18 */
+ U16 DeviceID; /* 0x1A */
+ U16 SubsystemVendorID; /* 0x1C */
+ U16 SubsystemID; /* 0x1E */
+ U8 RevisionID; /* 0x20 */
+ U8 Reserved21[3]; /* 0x21 */
} MPI26_CONFIG_PAGE_PCIEDEV_2, *PTR_MPI26_CONFIG_PAGE_PCIEDEV_2,
Mpi26PCIeDevicePage2_t, *pMpi26PCIeDevicePage2_t;
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_image.h b/drivers/scsi/mpt3sas/mpi/mpi2_image.h
index a3f6778..33b9c3a 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_image.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_image.h
@@ -19,6 +19,10 @@
* 09-07-18 02.06.03 Added MPI26_EVENT_PCIE_TOPO_PI_16_LANES
* 12-17-18 02.06.04 Addd MPI2_EXT_IMAGE_TYPE_PBLP
* Shorten some defines to be compatible with DOS
+ * 06-24-19 02.06.05 Whitespace adjustments to help with identifier
+ * checking tool.
+ * 10-02-19 02.06.06 Added MPI26_IMAGE_HEADER_SIG1_COREDUMP
+ * Added MPI2_FLASH_REGION_COREDUMP
*/
#ifndef MPI2_IMAGE_H
#define MPI2_IMAGE_H
@@ -213,6 +217,8 @@
#define MPI26_IMAGE_HEADER_SIG1_NVDATA (0x5444564E)
#define MPI26_IMAGE_HEADER_SIG1_GAS_GAUGE (0x20534147)
#define MPI26_IMAGE_HEADER_SIG1_PBLP (0x504C4250)
+/* little-endian "DUMP" */
+#define MPI26_IMAGE_HEADER_SIG1_COREDUMP (0x504D5544)
/**** Definitions for Signature2 field ****/
#define MPI26_IMAGE_HEADER_SIGNATURE2_VALUE (0x50584546)
@@ -359,6 +365,7 @@
#define MPI2_FLASH_REGION_MR_NVDATA (0x14)
#define MPI2_FLASH_REGION_CPLD (0x15)
#define MPI2_FLASH_REGION_PSOC (0x16)
+#define MPI2_FLASH_REGION_COREDUMP (0x17)
/*ImageRevision */
#define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00)
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
index 68ea408..e83c7c5 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
@@ -175,6 +175,10 @@
* Moved FW image definitions ionto new mpi2_image,h
* 08-14-18 02.00.36 Fixed definition of MPI2_FW_DOWNLOAD_ITYPE_PSOC (0x16)
* 09-07-18 02.00.37 Added MPI26_EVENT_PCIE_TOPO_PI_16_LANES
+ * 10-02-19 02.00.38 Added MPI26_IOCINIT_CFGFLAGS_COREDUMP_ENABLE
+ * Added MPI26_IOCFACTS_CAPABILITY_COREDUMP_ENABLED
+ * Added MPI2_FW_DOWNLOAD_ITYPE_COREDUMP
+ * Added MPI2_FW_UPLOAD_ITYPE_COREDUMP
* --------------------------------------------------------------------------
*/
@@ -248,6 +252,7 @@
/*ConfigurationFlags */
#define MPI26_IOCINIT_CFGFLAGS_NVME_SGL_FORMAT (0x0001)
+#define MPI26_IOCINIT_CFGFLAGS_COREDUMP_ENABLE (0x0002)
/*minimum depth for a Reply Descriptor Post Queue */
#define MPI2_RDPQ_DEPTH_MIN (16)
@@ -377,6 +382,7 @@
/*ProductID field uses MPI2_FW_HEADER_PID_ */
/*IOCCapabilities */
+#define MPI26_IOCFACTS_CAPABILITY_COREDUMP_ENABLED (0x00200000)
#define MPI26_IOCFACTS_CAPABILITY_PCIE_SRIOV (0x00100000)
#define MPI26_IOCFACTS_CAPABILITY_ATOMIC_REQ (0x00080000)
#define MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE (0x00040000)
@@ -1458,8 +1464,8 @@
/*MPI v2.6 and newer */
#define MPI2_FW_DOWNLOAD_ITYPE_CPLD (0x15)
#define MPI2_FW_DOWNLOAD_ITYPE_PSOC (0x16)
+#define MPI2_FW_DOWNLOAD_ITYPE_COREDUMP (0x17)
#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0)
-#define MPI2_FW_DOWNLOAD_ITYPE_TERMINATE (0xFF)
/*MPI v2.0 FWDownload TransactionContext Element */
typedef struct _MPI2_FW_DOWNLOAD_TCSGE {
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index e72f1db..3153f16 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -124,7 +124,12 @@
};
static int
+_base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc,
+ u32 ioc_state, int timeout);
+static int
_base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc);
+static void
+_base_clear_outstanding_commands(struct MPT3SAS_ADAPTER *ioc);
/**
* mpt3sas_base_check_cmd_timeout - Function
@@ -183,7 +188,7 @@
/**
* _base_readl_aero - retry readl for max three times.
- * @addr - MPT Fusion system interface register address
+ * @addr: MPT Fusion system interface register address
*
* Retry the readl() for max three times if it gets zero value
* while reading the system interface register.
@@ -406,7 +411,7 @@
{
Mpi2SGESimple32_t *sgel, *sgel_next;
u32 sgl_flags, sge_chain_count = 0;
- bool is_write = 0;
+ bool is_write = false;
u16 i = 0;
void __iomem *buffer_iomem;
phys_addr_t buffer_iomem_phys;
@@ -475,7 +480,7 @@
if (le32_to_cpu(sgel->FlagsLength) &
(MPI2_SGE_FLAGS_HOST_TO_IOC << MPI2_SGE_FLAGS_SHIFT))
- is_write = 1;
+ is_write = true;
for (i = 0; i < MPT_MIN_PHYS_SEGMENTS + ioc->facts.MaxChainDepth; i++) {
@@ -609,7 +614,8 @@
spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->shost_recovery || ioc->pci_error_recovery)
+ if ((ioc->shost_recovery && (ioc->ioc_coredump_loop == 0)) ||
+ ioc->pci_error_recovery)
goto rearm_timer;
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
@@ -656,20 +662,64 @@
return; /* don't rearm timer */
}
- ioc->non_operational_loop = 0;
+ if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_COREDUMP) {
+ u8 timeout = (ioc->manu_pg11.CoreDumpTOSec) ?
+ ioc->manu_pg11.CoreDumpTOSec :
+ MPT3SAS_DEFAULT_COREDUMP_TIMEOUT_SECONDS;
+ timeout /= (FAULT_POLLING_INTERVAL/1000);
+
+ if (ioc->ioc_coredump_loop == 0) {
+ mpt3sas_print_coredump_info(ioc,
+ doorbell & MPI2_DOORBELL_DATA_MASK);
+ /* do not accept any IOs and disable the interrupts */
+ spin_lock_irqsave(
+ &ioc->ioc_reset_in_progress_lock, flags);
+ ioc->shost_recovery = 1;
+ spin_unlock_irqrestore(
+ &ioc->ioc_reset_in_progress_lock, flags);
+ mpt3sas_base_mask_interrupts(ioc);
+ _base_clear_outstanding_commands(ioc);
+ }
+
+ ioc_info(ioc, "%s: CoreDump loop %d.",
+ __func__, ioc->ioc_coredump_loop);
+
+ /* Wait until CoreDump completes or times out */
+ if (ioc->ioc_coredump_loop++ < timeout) {
+ spin_lock_irqsave(
+ &ioc->ioc_reset_in_progress_lock, flags);
+ goto rearm_timer;
+ }
+ }
+
+ if (ioc->ioc_coredump_loop) {
+ if ((doorbell & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_COREDUMP)
+ ioc_err(ioc, "%s: CoreDump completed. LoopCount: %d",
+ __func__, ioc->ioc_coredump_loop);
+ else
+ ioc_err(ioc, "%s: CoreDump Timed out. LoopCount: %d",
+ __func__, ioc->ioc_coredump_loop);
+ ioc->ioc_coredump_loop = MPT3SAS_COREDUMP_LOOP_DONE;
+ }
+ ioc->non_operational_loop = 0;
if ((doorbell & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) {
rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
ioc_warn(ioc, "%s: hard reset: %s\n",
__func__, rc == 0 ? "success" : "failed");
doorbell = mpt3sas_base_get_iocstate(ioc, 0);
- if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
- mpt3sas_base_fault_info(ioc, doorbell &
+ if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
+ mpt3sas_print_fault_code(ioc, doorbell &
+ MPI2_DOORBELL_DATA_MASK);
+ } else if ((doorbell & MPI2_IOC_STATE_MASK) ==
+ MPI2_IOC_STATE_COREDUMP)
+ mpt3sas_print_coredump_info(ioc, doorbell &
MPI2_DOORBELL_DATA_MASK);
if (rc && (doorbell & MPI2_IOC_STATE_MASK) !=
MPI2_IOC_STATE_OPERATIONAL)
return; /* don't rearm timer */
}
+ ioc->ioc_coredump_loop = 0;
spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
rearm_timer:
@@ -749,6 +799,50 @@
}
/**
+ * mpt3sas_base_coredump_info - verbose translation of firmware CoreDump state
+ * @ioc: per adapter object
+ * @fault_code: fault code
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_base_coredump_info(struct MPT3SAS_ADAPTER *ioc, u16 fault_code)
+{
+ ioc_err(ioc, "coredump_state(0x%04x)!\n", fault_code);
+}
+
+/**
+ * mpt3sas_base_wait_for_coredump_completion - Wait until coredump
+ * completes or times out
+ * @ioc: per adapter object
+ * @caller: caller function name
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_base_wait_for_coredump_completion(struct MPT3SAS_ADAPTER *ioc,
+ const char *caller)
+{
+ u8 timeout = (ioc->manu_pg11.CoreDumpTOSec) ?
+ ioc->manu_pg11.CoreDumpTOSec :
+ MPT3SAS_DEFAULT_COREDUMP_TIMEOUT_SECONDS;
+
+ int ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_FAULT,
+ timeout);
+
+ if (ioc_state)
+ ioc_err(ioc,
+ "%s: CoreDump timed out. (ioc_state=0x%x)\n",
+ caller, ioc_state);
+ else
+ ioc_info(ioc,
+ "%s: CoreDump completed. (ioc_state=0x%x)\n",
+ caller, ioc_state);
+
+ return ioc_state;
+}
+
+/**
* mpt3sas_halt_firmware - halt's mpt controller firmware
* @ioc: per adapter object
*
@@ -768,9 +862,14 @@
dump_stack();
doorbell = ioc->base_readl(&ioc->chip->Doorbell);
- if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
- mpt3sas_base_fault_info(ioc , doorbell);
- else {
+ if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
+ mpt3sas_print_fault_code(ioc, doorbell &
+ MPI2_DOORBELL_DATA_MASK);
+ } else if ((doorbell & MPI2_IOC_STATE_MASK) ==
+ MPI2_IOC_STATE_COREDUMP) {
+ mpt3sas_print_coredump_info(ioc, doorbell &
+ MPI2_DOORBELL_DATA_MASK);
+ } else {
writel(0xC0FFEE00, &ioc->chip->Doorbell);
ioc_err(ioc, "Firmware is halted due to command timeout\n");
}
@@ -1365,13 +1464,13 @@
}
/**
- * _base_mask_interrupts - disable interrupts
+ * mpt3sas_base_mask_interrupts - disable interrupts
* @ioc: per adapter object
*
* Disabling ResetIRQ, Reply and Doorbell Interrupts
*/
-static void
-_base_mask_interrupts(struct MPT3SAS_ADAPTER *ioc)
+void
+mpt3sas_base_mask_interrupts(struct MPT3SAS_ADAPTER *ioc)
{
u32 him_register;
@@ -1383,13 +1482,13 @@
}
/**
- * _base_unmask_interrupts - enable interrupts
+ * mpt3sas_base_unmask_interrupts - enable interrupts
* @ioc: per adapter object
*
* Enabling only Reply Interrupts
*/
-static void
-_base_unmask_interrupts(struct MPT3SAS_ADAPTER *ioc)
+void
+mpt3sas_base_unmask_interrupts(struct MPT3SAS_ADAPTER *ioc)
{
u32 him_register;
@@ -1527,7 +1626,7 @@
* So that FW can find enough entries to post the Reply
* Descriptors in the reply descriptor post queue.
*/
- if (!base_mod64(completed_cmds, ioc->thresh_hold)) {
+ if (completed_cmds >= ioc->thresh_hold) {
if (ioc->combined_reply_queue) {
writel(reply_q->reply_post_host_index |
((msix_index & 7) <<
@@ -1618,8 +1717,8 @@
/**
* _base_irqpoll - IRQ poll callback handler
- * @irqpoll - irq_poll object
- * @budget - irq poll weight
+ * @irqpoll: irq_poll object
+ * @budget: irq poll weight
*
* returns number of reply descriptors processed
*/
@@ -1693,12 +1792,14 @@
/**
* mpt3sas_base_sync_reply_irqs - flush pending MSIX interrupts
* @ioc: per adapter object
+ * @poll: poll over reply descriptor pools incase interrupt for
+ * timed-out SCSI command got delayed
* Context: non ISR conext
*
* Called when a Task Management request has completed.
*/
void
-mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc)
+mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc, u8 poll)
{
struct adapter_reply_queue *reply_q;
@@ -1731,6 +1832,9 @@
enable_irq(reply_q->os_irq);
}
}
+
+ if (poll)
+ _base_process_reply_queue(reply_q);
}
}
@@ -2717,58 +2821,38 @@
static int
_base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
{
- u64 required_mask, coherent_mask;
struct sysinfo s;
+ int dma_mask;
+
+ if (ioc->is_mcpu_endpoint ||
+ sizeof(dma_addr_t) == 4 || ioc->use_32bit_dma ||
+ dma_get_required_mask(&pdev->dev) <= 32)
+ dma_mask = 32;
/* Set 63 bit DMA mask for all SAS3 and SAS35 controllers */
- int dma_mask = (ioc->hba_mpi_version_belonged > MPI2_VERSION) ? 63 : 64;
-
- if (ioc->is_mcpu_endpoint)
- goto try_32bit;
-
- required_mask = dma_get_required_mask(&pdev->dev);
- if (sizeof(dma_addr_t) == 4 || required_mask == 32)
- goto try_32bit;
-
- if (ioc->dma_mask)
- coherent_mask = DMA_BIT_MASK(dma_mask);
+ else if (ioc->hba_mpi_version_belonged > MPI2_VERSION)
+ dma_mask = 63;
else
- coherent_mask = DMA_BIT_MASK(32);
+ dma_mask = 64;
if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(dma_mask)) ||
- dma_set_coherent_mask(&pdev->dev, coherent_mask))
- goto try_32bit;
-
- ioc->base_add_sg_single = &_base_add_sg_single_64;
- ioc->sge_size = sizeof(Mpi2SGESimple64_t);
- ioc->dma_mask = dma_mask;
- goto out;
-
- try_32bit:
- if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)))
+ dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(dma_mask)))
return -ENODEV;
- ioc->base_add_sg_single = &_base_add_sg_single_32;
- ioc->sge_size = sizeof(Mpi2SGESimple32_t);
- ioc->dma_mask = 32;
- out:
+ if (dma_mask > 32) {
+ ioc->base_add_sg_single = &_base_add_sg_single_64;
+ ioc->sge_size = sizeof(Mpi2SGESimple64_t);
+ } else {
+ ioc->base_add_sg_single = &_base_add_sg_single_32;
+ ioc->sge_size = sizeof(Mpi2SGESimple32_t);
+ }
+
si_meminfo(&s);
ioc_info(ioc, "%d BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (%ld kB)\n",
- ioc->dma_mask, convert_to_kb(s.totalram));
+ dma_mask, convert_to_kb(s.totalram));
return 0;
}
-static int
-_base_change_consistent_dma_mask(struct MPT3SAS_ADAPTER *ioc,
- struct pci_dev *pdev)
-{
- if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(ioc->dma_mask))) {
- if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))
- return -ENODEV;
- }
- return 0;
-}
-
/**
* _base_check_enable_msix - checks MSIX capabable.
* @ioc: per adapter object
@@ -2979,8 +3063,8 @@
/**
* _base_check_and_enable_high_iops_queues - enable high iops mode
- * @ ioc - per adapter object
- * @ hba_msix_vector_count - msix vectors supported by HBA
+ * @ioc: per adapter object
+ * @hba_msix_vector_count: msix vectors supported by HBA
*
* Enable high iops queues only if
* - HBA is a SEA/AERO controller and
@@ -3055,11 +3139,11 @@
descp = NULL;
ioc_info(ioc, " %d %d\n", ioc->high_iops_queues,
- ioc->msix_vector_count);
+ ioc->reply_queue_count);
i = pci_alloc_irq_vectors_affinity(ioc->pdev,
ioc->high_iops_queues,
- ioc->msix_vector_count, irq_flags, descp);
+ ioc->reply_queue_count, irq_flags, descp);
return i;
}
@@ -3114,6 +3198,8 @@
*/
if (!ioc->combined_reply_queue &&
ioc->hba_mpi_version_belonged != MPI2_VERSION) {
+ ioc_info(ioc,
+ "combined ReplyQueue is off, Enabling msix load balance\n");
ioc->msix_load_balance = true;
}
@@ -3126,9 +3212,7 @@
r = _base_alloc_irq_vectors(ioc);
if (r < 0) {
- dfailprintk(ioc,
- ioc_info(ioc, "pci_alloc_irq_vectors failed (r=%d) !!!\n",
- r));
+ ioc_info(ioc, "pci_alloc_irq_vectors failed (r=%d) !!!\n", r);
goto try_ioapic;
}
@@ -3217,9 +3301,15 @@
dhsprintk(ioc, pr_info("%s: ioc_state(0x%08x)\n", __func__, ioc_state));
if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
- mpt3sas_base_fault_info(ioc, ioc_state &
+ mpt3sas_print_fault_code(ioc, ioc_state &
MPI2_DOORBELL_DATA_MASK);
rc = _base_diag_reset(ioc);
+ } else if ((ioc_state & MPI2_IOC_STATE_MASK) ==
+ MPI2_IOC_STATE_COREDUMP) {
+ mpt3sas_print_coredump_info(ioc, ioc_state &
+ MPI2_DOORBELL_DATA_MASK);
+ mpt3sas_base_wait_for_coredump_completion(ioc, __func__);
+ rc = _base_diag_reset(ioc);
}
return rc;
@@ -3290,12 +3380,13 @@
}
if (ioc->chip == NULL) {
- ioc_err(ioc, "unable to map adapter memory! or resource not found\n");
+ ioc_err(ioc,
+ "unable to map adapter memory! or resource not found\n");
r = -EINVAL;
goto out_fail;
}
- _base_mask_interrupts(ioc);
+ mpt3sas_base_mask_interrupts(ioc);
r = _base_get_ioc_facts(ioc);
if (r) {
@@ -3329,8 +3420,8 @@
ioc->combined_reply_index_count,
sizeof(resource_size_t *), GFP_KERNEL);
if (!ioc->replyPostRegisterIndex) {
- dfailprintk(ioc,
- ioc_warn(ioc, "allocation for reply Post Register Index failed!!!\n"));
+ ioc_err(ioc,
+ "allocation for replyPostRegisterIndex failed!\n");
r = -ENOMEM;
goto out_fail;
}
@@ -3478,6 +3569,22 @@
}
/**
+ * _base_sdev_nr_inflight_request -get number of inflight requests
+ * of a request queue.
+ * @q: request_queue object
+ *
+ * returns number of inflight request of a request queue.
+ */
+inline unsigned long
+_base_sdev_nr_inflight_request(struct request_queue *q)
+{
+ struct blk_mq_hw_ctx *hctx = q->queue_hw_ctx[0];
+
+ return atomic_read(&hctx->nr_active);
+}
+
+
+/**
* _base_get_high_iops_msix_index - get the msix index of
* high iops queues
* @ioc: per adapter object
@@ -3496,7 +3603,7 @@
* reply queues in terms of batch count 16 when outstanding
* IOs on the target device is >=8.
*/
- if (atomic_read(&scmd->device->device_busy) >
+ if (_base_sdev_nr_inflight_request(scmd->device->request_queue) >
MPT3SAS_DEVICE_HIGH_IOPS_DEPTH)
return base_mod64((
atomic64_add_return(1, &ioc->high_iops_outstanding) /
@@ -4253,10 +4360,12 @@
static int
_base_display_fwpkg_version(struct MPT3SAS_ADAPTER *ioc)
{
- Mpi2FWImageHeader_t *FWImgHdr;
+ Mpi2FWImageHeader_t *fw_img_hdr;
+ Mpi26ComponentImageHeader_t *cmp_img_hdr;
Mpi25FWUploadRequest_t *mpi_request;
Mpi2FWUploadReply_t mpi_reply;
int r = 0;
+ u32 package_version = 0;
void *fwpkg_data = NULL;
dma_addr_t fwpkg_data_dma;
u16 smid, ioc_status;
@@ -4273,7 +4382,8 @@
fwpkg_data = dma_alloc_coherent(&ioc->pdev->dev, data_length,
&fwpkg_data_dma, GFP_KERNEL);
if (!fwpkg_data) {
- ioc_err(ioc, "failure at %s:%d/%s()!\n",
+ ioc_err(ioc,
+ "Memory allocation for fwpkg data failed at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
return -ENOMEM;
}
@@ -4313,14 +4423,26 @@
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
MPI2_IOCSTATUS_MASK;
if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
- FWImgHdr = (Mpi2FWImageHeader_t *)fwpkg_data;
- if (FWImgHdr->PackageVersion.Word) {
- ioc_info(ioc, "FW Package Version (%02d.%02d.%02d.%02d)\n",
- FWImgHdr->PackageVersion.Struct.Major,
- FWImgHdr->PackageVersion.Struct.Minor,
- FWImgHdr->PackageVersion.Struct.Unit,
- FWImgHdr->PackageVersion.Struct.Dev);
- }
+ fw_img_hdr = (Mpi2FWImageHeader_t *)fwpkg_data;
+ if (le32_to_cpu(fw_img_hdr->Signature) ==
+ MPI26_IMAGE_HEADER_SIGNATURE0_MPI26) {
+ cmp_img_hdr =
+ (Mpi26ComponentImageHeader_t *)
+ (fwpkg_data);
+ package_version =
+ le32_to_cpu(
+ cmp_img_hdr->ApplicationSpecific);
+ } else
+ package_version =
+ le32_to_cpu(
+ fw_img_hdr->PackageVersion.Word);
+ if (package_version)
+ ioc_info(ioc,
+ "FW Package Ver(%02d.%02d.%02d.%02d)\n",
+ ((package_version) & 0xFF000000) >> 24,
+ ((package_version) & 0x00FF0000) >> 16,
+ ((package_version) & 0x0000FF00) >> 8,
+ (package_version) & 0x000000FF);
} else {
_debug_dump_mf(&mpi_reply,
sizeof(Mpi2FWUploadReply_t)/4);
@@ -4573,7 +4695,7 @@
ioc_info(ioc, "performance mode: balanced\n");
return;
}
- /* Fall through */
+ fallthrough;
case MPT_PERF_MODE_LATENCY:
/*
* Enable interrupt coalescing on all reply queues
@@ -4700,8 +4822,9 @@
{
int i = 0;
int j = 0;
+ int dma_alloc_count = 0;
struct chain_tracker *ct;
- struct reply_post_struct *rps;
+ int count = ioc->rdpq_array_enable ? ioc->reply_queue_count : 1;
dexitprintk(ioc, ioc_info(ioc, "%s\n", __func__));
@@ -4743,29 +4866,34 @@
}
if (ioc->reply_post) {
- do {
- rps = &ioc->reply_post[i];
- if (rps->reply_post_free) {
- dma_pool_free(
- ioc->reply_post_free_dma_pool,
- rps->reply_post_free,
- rps->reply_post_free_dma);
- dexitprintk(ioc,
- ioc_info(ioc, "reply_post_free_pool(0x%p): free\n",
- rps->reply_post_free));
- rps->reply_post_free = NULL;
+ dma_alloc_count = DIV_ROUND_UP(count,
+ RDPQ_MAX_INDEX_IN_ONE_CHUNK);
+ for (i = 0; i < count; i++) {
+ if (i % RDPQ_MAX_INDEX_IN_ONE_CHUNK == 0
+ && dma_alloc_count) {
+ if (ioc->reply_post[i].reply_post_free) {
+ dma_pool_free(
+ ioc->reply_post_free_dma_pool,
+ ioc->reply_post[i].reply_post_free,
+ ioc->reply_post[i].reply_post_free_dma);
+ dexitprintk(ioc, ioc_info(ioc,
+ "reply_post_free_pool(0x%p): free\n",
+ ioc->reply_post[i].reply_post_free));
+ ioc->reply_post[i].reply_post_free =
+ NULL;
+ }
+ --dma_alloc_count;
}
- } while (ioc->rdpq_array_enable &&
- (++i < ioc->reply_queue_count));
+ }
+ dma_pool_destroy(ioc->reply_post_free_dma_pool);
if (ioc->reply_post_free_array &&
ioc->rdpq_array_enable) {
dma_pool_free(ioc->reply_post_free_array_dma_pool,
- ioc->reply_post_free_array,
- ioc->reply_post_free_array_dma);
+ ioc->reply_post_free_array,
+ ioc->reply_post_free_array_dma);
ioc->reply_post_free_array = NULL;
}
dma_pool_destroy(ioc->reply_post_free_array_dma_pool);
- dma_pool_destroy(ioc->reply_post_free_dma_pool);
kfree(ioc->reply_post);
}
@@ -4775,8 +4903,7 @@
ioc->pcie_sg_lookup[i].pcie_sgl,
ioc->pcie_sg_lookup[i].pcie_sgl_dma);
}
- if (ioc->pcie_sgl_dma_pool)
- dma_pool_destroy(ioc->pcie_sgl_dma_pool);
+ dma_pool_destroy(ioc->pcie_sgl_dma_pool);
}
if (ioc->config_page) {
@@ -4810,7 +4937,7 @@
}
/**
- * is_MSB_are_same - checks whether all reply queues in a set are
+ * mpt3sas_check_same_4gb_region - checks whether all reply queues in a set are
* having same upper 32bits in their base memory address.
* @reply_pool_start_address: Base address of a reply queue set
* @pool_sz: Size of single Reply Descriptor Post Queues pool size
@@ -4820,7 +4947,7 @@
*/
static int
-is_MSB_are_same(long reply_pool_start_address, u32 pool_sz)
+mpt3sas_check_same_4gb_region(long reply_pool_start_address, u32 pool_sz)
{
long reply_pool_end_address;
@@ -4834,6 +4961,85 @@
}
/**
+ * base_alloc_rdpq_dma_pool - Allocating DMA'able memory
+ * for reply queues.
+ * @ioc: per adapter object
+ * @sz: DMA Pool size
+ * Return: 0 for success, non-zero for failure.
+ */
+static int
+base_alloc_rdpq_dma_pool(struct MPT3SAS_ADAPTER *ioc, int sz)
+{
+ int i = 0;
+ u32 dma_alloc_count = 0;
+ int reply_post_free_sz = ioc->reply_post_queue_depth *
+ sizeof(Mpi2DefaultReplyDescriptor_t);
+ int count = ioc->rdpq_array_enable ? ioc->reply_queue_count : 1;
+
+ ioc->reply_post = kcalloc(count, sizeof(struct reply_post_struct),
+ GFP_KERNEL);
+ if (!ioc->reply_post)
+ return -ENOMEM;
+ /*
+ * For INVADER_SERIES each set of 8 reply queues(0-7, 8-15, ..) and
+ * VENTURA_SERIES each set of 16 reply queues(0-15, 16-31, ..) should
+ * be within 4GB boundary i.e reply queues in a set must have same
+ * upper 32-bits in their memory address. so here driver is allocating
+ * the DMA'able memory for reply queues according.
+ * Driver uses limitation of
+ * VENTURA_SERIES to manage INVADER_SERIES as well.
+ */
+ dma_alloc_count = DIV_ROUND_UP(count,
+ RDPQ_MAX_INDEX_IN_ONE_CHUNK);
+ ioc->reply_post_free_dma_pool =
+ dma_pool_create("reply_post_free pool",
+ &ioc->pdev->dev, sz, 16, 0);
+ if (!ioc->reply_post_free_dma_pool)
+ return -ENOMEM;
+ for (i = 0; i < count; i++) {
+ if ((i % RDPQ_MAX_INDEX_IN_ONE_CHUNK == 0) && dma_alloc_count) {
+ ioc->reply_post[i].reply_post_free =
+ dma_pool_zalloc(ioc->reply_post_free_dma_pool,
+ GFP_KERNEL,
+ &ioc->reply_post[i].reply_post_free_dma);
+ if (!ioc->reply_post[i].reply_post_free)
+ return -ENOMEM;
+ /*
+ * Each set of RDPQ pool must satisfy 4gb boundary
+ * restriction.
+ * 1) Check if allocated resources for RDPQ pool are in
+ * the same 4GB range.
+ * 2) If #1 is true, continue with 64 bit DMA.
+ * 3) If #1 is false, return 1. which means free all the
+ * resources and set DMA mask to 32 and allocate.
+ */
+ if (!mpt3sas_check_same_4gb_region(
+ (long)ioc->reply_post[i].reply_post_free, sz)) {
+ dinitprintk(ioc,
+ ioc_err(ioc, "bad Replypost free pool(0x%p)"
+ "reply_post_free_dma = (0x%llx)\n",
+ ioc->reply_post[i].reply_post_free,
+ (unsigned long long)
+ ioc->reply_post[i].reply_post_free_dma));
+ return -EAGAIN;
+ }
+ dma_alloc_count--;
+
+ } else {
+ ioc->reply_post[i].reply_post_free =
+ (Mpi2ReplyDescriptorsUnion_t *)
+ ((long)ioc->reply_post[i-1].reply_post_free
+ + reply_post_free_sz);
+ ioc->reply_post[i].reply_post_free_dma =
+ (dma_addr_t)
+ (ioc->reply_post[i-1].reply_post_free_dma +
+ reply_post_free_sz);
+ }
+ }
+ return 0;
+}
+
+/**
* _base_allocate_memory_pools - allocate start of day memory pools
* @ioc: per adapter object
*
@@ -4847,10 +5053,12 @@
u16 chains_needed_per_io;
u32 sz, total_sz, reply_post_free_sz, reply_post_free_array_sz;
u32 retry_sz;
+ u32 rdpq_sz = 0;
u16 max_request_credit, nvme_blocks_needed;
unsigned short sg_tablesize;
u16 sge_size;
int i, j;
+ int ret = 0;
struct chain_tracker *ct;
dinitprintk(ioc, ioc_info(ioc, "%s\n", __func__));
@@ -4993,64 +5201,39 @@
ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
}
- dinitprintk(ioc,
- ioc_info(ioc, "scatter gather: sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), chains_per_io(%d)\n",
- ioc->max_sges_in_main_message,
- ioc->max_sges_in_chain_message,
- ioc->shost->sg_tablesize,
- ioc->chains_needed_per_io));
+ ioc_info(ioc,
+ "scatter gather: sge_in_main_msg(%d), sge_per_chain(%d), "
+ "sge_per_io(%d), chains_per_io(%d)\n",
+ ioc->max_sges_in_main_message,
+ ioc->max_sges_in_chain_message,
+ ioc->shost->sg_tablesize,
+ ioc->chains_needed_per_io);
/* reply post queue, 16 byte align */
reply_post_free_sz = ioc->reply_post_queue_depth *
sizeof(Mpi2DefaultReplyDescriptor_t);
-
- sz = reply_post_free_sz;
+ rdpq_sz = reply_post_free_sz * RDPQ_MAX_INDEX_IN_ONE_CHUNK;
if (_base_is_controller_msix_enabled(ioc) && !ioc->rdpq_array_enable)
- sz *= ioc->reply_queue_count;
-
- ioc->reply_post = kcalloc((ioc->rdpq_array_enable) ?
- (ioc->reply_queue_count):1,
- sizeof(struct reply_post_struct), GFP_KERNEL);
-
- if (!ioc->reply_post) {
- ioc_err(ioc, "reply_post_free pool: kcalloc failed\n");
- goto out;
- }
- ioc->reply_post_free_dma_pool = dma_pool_create("reply_post_free pool",
- &ioc->pdev->dev, sz, 16, 0);
- if (!ioc->reply_post_free_dma_pool) {
- ioc_err(ioc, "reply_post_free pool: dma_pool_create failed\n");
- goto out;
- }
- i = 0;
- do {
- ioc->reply_post[i].reply_post_free =
- dma_pool_zalloc(ioc->reply_post_free_dma_pool,
- GFP_KERNEL,
- &ioc->reply_post[i].reply_post_free_dma);
- if (!ioc->reply_post[i].reply_post_free) {
- ioc_err(ioc, "reply_post_free pool: dma_pool_alloc failed\n");
- goto out;
+ rdpq_sz = reply_post_free_sz * ioc->reply_queue_count;
+ ret = base_alloc_rdpq_dma_pool(ioc, rdpq_sz);
+ if (ret == -EAGAIN) {
+ /*
+ * Free allocated bad RDPQ memory pools.
+ * Change dma coherent mask to 32 bit and reallocate RDPQ
+ */
+ _base_release_memory_pools(ioc);
+ ioc->use_32bit_dma = true;
+ if (_base_config_dma_addressing(ioc, ioc->pdev) != 0) {
+ ioc_err(ioc,
+ "32 DMA mask failed %s\n", pci_name(ioc->pdev));
+ return -ENODEV;
}
- dinitprintk(ioc,
- ioc_info(ioc, "reply post free pool (0x%p): depth(%d), element_size(%d), pool_size(%d kB)\n",
- ioc->reply_post[i].reply_post_free,
- ioc->reply_post_queue_depth,
- 8, sz / 1024));
- dinitprintk(ioc,
- ioc_info(ioc, "reply_post_free_dma = (0x%llx)\n",
- (u64)ioc->reply_post[i].reply_post_free_dma));
- total_sz += sz;
- } while (ioc->rdpq_array_enable && (++i < ioc->reply_queue_count));
-
- if (ioc->dma_mask > 32) {
- if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) {
- ioc_warn(ioc, "no suitable consistent DMA mask for %s\n",
- pci_name(ioc->pdev));
- goto out;
- }
- }
-
+ if (base_alloc_rdpq_dma_pool(ioc, rdpq_sz))
+ return -ENOMEM;
+ } else if (ret == -ENOMEM)
+ return -ENOMEM;
+ total_sz = rdpq_sz * (!ioc->rdpq_array_enable ? 1 :
+ DIV_ROUND_UP(ioc->reply_queue_count, RDPQ_MAX_INDEX_IN_ONE_CHUNK));
ioc->scsiio_depth = ioc->hba_queue_depth -
ioc->hi_priority_depth - ioc->internal_depth;
@@ -5062,7 +5245,6 @@
ioc_info(ioc, "scsi host: can_queue depth (%d)\n",
ioc->shost->can_queue));
-
/* contiguous pool for request and chains, 16 byte align, one extra "
* "frame for smid=0
*/
@@ -5089,7 +5271,6 @@
_base_release_memory_pools(ioc);
goto retry_allocation;
}
- memset(ioc->request, 0, sz);
if (retry_sz)
ioc_err(ioc, "request pool: dma_alloc_coherent succeed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), total(%d kb)\n",
@@ -5108,15 +5289,13 @@
ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth *
ioc->request_sz);
- dinitprintk(ioc,
- ioc_info(ioc, "request pool(0x%p): depth(%d), frame_size(%d), pool_size(%d kB)\n",
- ioc->request, ioc->hba_queue_depth,
- ioc->request_sz,
- (ioc->hba_queue_depth * ioc->request_sz) / 1024));
+ ioc_info(ioc,
+ "request pool(0x%p) - dma(0x%llx): "
+ "depth(%d), frame_size(%d), pool_size(%d kB)\n",
+ ioc->request, (unsigned long long) ioc->request_dma,
+ ioc->hba_queue_depth, ioc->request_sz,
+ (ioc->hba_queue_depth * ioc->request_sz) / 1024);
- dinitprintk(ioc,
- ioc_info(ioc, "request pool: dma(0x%llx)\n",
- (unsigned long long)ioc->request_dma));
total_sz += sz;
dinitprintk(ioc,
@@ -5281,7 +5460,7 @@
* Actual requirement is not alignment, but we need start and end of
* DMA address must have same upper 32 bit address.
*/
- if (!is_MSB_are_same((long)ioc->sense, sz)) {
+ if (!mpt3sas_check_same_4gb_region((long)ioc->sense, sz)) {
//Release Sense pool & Reallocate
dma_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma);
dma_pool_destroy(ioc->sense_dma_pool);
@@ -5301,13 +5480,12 @@
goto out;
}
}
- dinitprintk(ioc,
- ioc_info(ioc, "sense pool(0x%p): depth(%d), element_size(%d), pool_size(%d kB)\n",
- ioc->sense, ioc->scsiio_depth,
- SCSI_SENSE_BUFFERSIZE, sz / 1024));
- dinitprintk(ioc,
- ioc_info(ioc, "sense_dma(0x%llx)\n",
- (unsigned long long)ioc->sense_dma));
+ ioc_info(ioc,
+ "sense pool(0x%p)- dma(0x%llx): depth(%d),"
+ "element_size(%d), pool_size(%d kB)\n",
+ ioc->sense, (unsigned long long)ioc->sense_dma, ioc->scsiio_depth,
+ SCSI_SENSE_BUFFERSIZE, sz / 1024);
+
total_sz += sz;
/* reply pool, 4 byte align */
@@ -5385,12 +5563,10 @@
ioc_err(ioc, "config page: dma_pool_alloc failed\n");
goto out;
}
- dinitprintk(ioc,
- ioc_info(ioc, "config page(0x%p): size(%d)\n",
- ioc->config_page, ioc->config_page_sz));
- dinitprintk(ioc,
- ioc_info(ioc, "config_page_dma(0x%llx)\n",
- (unsigned long long)ioc->config_page_dma));
+
+ ioc_info(ioc, "config page(0x%p) - dma(0x%llx): size(%d)\n",
+ ioc->config_page, (unsigned long long)ioc->config_page_dma,
+ ioc->config_page_sz);
total_sz += ioc->config_page_sz;
ioc_info(ioc, "Allocated physical memory: size(%d kB)\n",
@@ -5445,6 +5621,8 @@
return 0;
if (count && current_state == MPI2_IOC_STATE_FAULT)
break;
+ if (count && current_state == MPI2_IOC_STATE_COREDUMP)
+ break;
usleep_range(1000, 1500);
count++;
@@ -5454,9 +5632,27 @@
}
/**
+ * _base_dump_reg_set - This function will print hexdump of register set.
+ * @ioc: per adapter object
+ *
+ * Returns nothing.
+ */
+static inline void
+_base_dump_reg_set(struct MPT3SAS_ADAPTER *ioc)
+{
+ unsigned int i, sz = 256;
+ u32 __iomem *reg = (u32 __iomem *)ioc->chip;
+
+ ioc_info(ioc, "System Register set:\n");
+ for (i = 0; i < (sz / sizeof(u32)); i++)
+ pr_info("%08x: %08x\n", (i * 4), readl(®[i]));
+}
+
+/**
* _base_wait_for_doorbell_int - waiting for controller interrupt(generated by
* a write to the doorbell)
* @ioc: per adapter object
+ * @timeout: timeout in seconds
*
* Return: 0 for success, non-zero for failure.
*
@@ -5546,7 +5742,12 @@
doorbell = ioc->base_readl(&ioc->chip->Doorbell);
if ((doorbell & MPI2_IOC_STATE_MASK) ==
MPI2_IOC_STATE_FAULT) {
- mpt3sas_base_fault_info(ioc , doorbell);
+ mpt3sas_print_fault_code(ioc, doorbell);
+ return -EFAULT;
+ }
+ if ((doorbell & MPI2_IOC_STATE_MASK) ==
+ MPI2_IOC_STATE_COREDUMP) {
+ mpt3sas_print_coredump_info(ioc, doorbell);
return -EFAULT;
}
} else if (int_status == 0xFFFFFFFF)
@@ -5608,6 +5809,7 @@
{
u32 ioc_state;
int r = 0;
+ unsigned long flags;
if (reset_type != MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET) {
ioc_err(ioc, "%s: unknown reset_type\n", __func__);
@@ -5626,6 +5828,7 @@
r = -EFAULT;
goto out;
}
+
ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, timeout);
if (ioc_state) {
ioc_err(ioc, "%s: failed going to ready state (ioc_state=0x%x)\n",
@@ -5634,6 +5837,26 @@
goto out;
}
out:
+ if (r != 0) {
+ ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ /*
+ * Wait for IOC state CoreDump to clear only during
+ * HBA initialization & release time.
+ */
+ if ((ioc_state & MPI2_IOC_STATE_MASK) ==
+ MPI2_IOC_STATE_COREDUMP && (ioc->is_driver_loading == 1 ||
+ ioc->fault_reset_work_q == NULL)) {
+ spin_unlock_irqrestore(
+ &ioc->ioc_reset_in_progress_lock, flags);
+ mpt3sas_print_coredump_info(ioc, ioc_state);
+ mpt3sas_base_wait_for_coredump_completion(ioc,
+ __func__);
+ spin_lock_irqsave(
+ &ioc->ioc_reset_in_progress_lock, flags);
+ }
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ }
ioc_info(ioc, "message unit reset: %s\n",
r == 0 ? "SUCCESS" : "FAILED");
return r;
@@ -5642,7 +5865,7 @@
/**
* mpt3sas_wait_for_ioc - IOC's operational state is checked here.
* @ioc: per adapter object
- * @wait_count: timeout in seconds
+ * @timeout: timeout in seconds
*
* Return: Waits up to timeout seconds for the IOC to
* become operational. Returns 0 if IOC is present
@@ -5781,7 +6004,7 @@
mfp = (__le32 *)reply;
pr_info("\toffset:data\n");
for (i = 0; i < reply_bytes/4; i++)
- pr_info("\t[0x%02x]:%08x\n", i*4,
+ ioc_info(ioc, "\t[0x%02x]:%08x\n", i*4,
le32_to_cpu(mfp[i]));
}
return 0;
@@ -5849,10 +6072,9 @@
ioc->ioc_link_reset_in_progress)
ioc->ioc_link_reset_in_progress = 0;
if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) {
- issue_reset =
- mpt3sas_base_check_cmd_timeout(ioc,
- ioc->base_cmds.status, mpi_request,
- sizeof(Mpi2SasIoUnitControlRequest_t)/4);
+ mpt3sas_check_cmd_timeout(ioc, ioc->base_cmds.status,
+ mpi_request, sizeof(Mpi2SasIoUnitControlRequest_t)/4,
+ issue_reset);
goto issue_host_reset;
}
if (ioc->base_cmds.status & MPT3_CMD_REPLY_VALID)
@@ -5925,10 +6147,9 @@
wait_for_completion_timeout(&ioc->base_cmds.done,
msecs_to_jiffies(10000));
if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) {
- issue_reset =
- mpt3sas_base_check_cmd_timeout(ioc,
- ioc->base_cmds.status, mpi_request,
- sizeof(Mpi2SepRequest_t)/4);
+ mpt3sas_check_cmd_timeout(ioc,
+ ioc->base_cmds.status, mpi_request,
+ sizeof(Mpi2SepRequest_t)/4, issue_reset);
goto issue_host_reset;
}
if (ioc->base_cmds.status & MPT3_CMD_REPLY_VALID)
@@ -6027,9 +6248,15 @@
}
if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
- mpt3sas_base_fault_info(ioc, ioc_state &
+ mpt3sas_print_fault_code(ioc, ioc_state &
MPI2_DOORBELL_DATA_MASK);
goto issue_diag_reset;
+ } else if ((ioc_state & MPI2_IOC_STATE_MASK) ==
+ MPI2_IOC_STATE_COREDUMP) {
+ ioc_info(ioc,
+ "%s: Skipping the diag reset here. (ioc_state=0x%x)\n",
+ __func__, ioc_state);
+ return -EFAULT;
}
ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, timeout);
@@ -6208,6 +6435,12 @@
cpu_to_le64((u64)ioc->reply_post[0].reply_post_free_dma);
}
+ /*
+ * Set the flag to enable CoreDump state feature in IOC firmware.
+ */
+ mpi_request.ConfigurationFlags |=
+ cpu_to_le16(MPI26_IOCINIT_CFGFLAGS_COREDUMP_ENABLE);
+
/* This time stamp specifies number of milliseconds
* since epoch ~ midnight January 1, 1970.
*/
@@ -6219,9 +6452,9 @@
int i;
mfp = (__le32 *)&mpi_request;
- pr_info("\toffset:data\n");
+ ioc_info(ioc, "\toffset:data\n");
for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++)
- pr_info("\t[0x%02x]:%08x\n", i*4,
+ ioc_info(ioc, "\t[0x%02x]:%08x\n", i*4,
le32_to_cpu(mfp[i]));
}
@@ -6593,8 +6826,12 @@
/* wait 100 msec */
msleep(100);
- if (count++ > 20)
+ if (count++ > 20) {
+ ioc_info(ioc,
+ "Stop writing magic sequence after 20 retries\n");
+ _base_dump_reg_set(ioc);
goto out;
+ }
host_diagnostic = ioc->base_readl(&ioc->chip->HostDiagnostic);
drsprintk(ioc,
@@ -6618,8 +6855,12 @@
host_diagnostic = ioc->base_readl(&ioc->chip->HostDiagnostic);
- if (host_diagnostic == 0xFFFFFFFF)
+ if (host_diagnostic == 0xFFFFFFFF) {
+ ioc_info(ioc,
+ "Invalid host diagnostic register value\n");
+ _base_dump_reg_set(ioc);
goto out;
+ }
if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER))
break;
@@ -6652,6 +6893,7 @@
if (ioc_state) {
ioc_err(ioc, "%s: failed going to ready state (ioc_state=0x%x)\n",
__func__, ioc_state);
+ _base_dump_reg_set(ioc);
goto out;
}
@@ -6708,16 +6950,33 @@
return 0;
if (ioc_state & MPI2_DOORBELL_USED) {
- dhsprintk(ioc, ioc_info(ioc, "unexpected doorbell active!\n"));
+ ioc_info(ioc, "unexpected doorbell active!\n");
goto issue_diag_reset;
}
if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
- mpt3sas_base_fault_info(ioc, ioc_state &
+ mpt3sas_print_fault_code(ioc, ioc_state &
MPI2_DOORBELL_DATA_MASK);
goto issue_diag_reset;
}
+ if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_COREDUMP) {
+ /*
+ * if host reset is invoked while watch dog thread is waiting
+ * for IOC state to be changed to Fault state then driver has
+ * to wait here for CoreDump state to clear otherwise reset
+ * will be issued to the FW and FW move the IOC state to
+ * reset state without copying the FW logs to coredump region.
+ */
+ if (ioc->ioc_coredump_loop != MPT3SAS_COREDUMP_LOOP_DONE) {
+ mpt3sas_print_coredump_info(ioc, ioc_state &
+ MPI2_DOORBELL_DATA_MASK);
+ mpt3sas_base_wait_for_coredump_completion(ioc,
+ __func__);
+ }
+ goto issue_diag_reset;
+ }
+
if (type == FORCE_BIG_HAMMER)
goto issue_diag_reset;
@@ -6879,7 +7138,7 @@
skip_init_reply_post_host_index:
- _base_unmask_interrupts(ioc);
+ mpt3sas_base_unmask_interrupts(ioc);
if (ioc->hba_mpi_version_belonged != MPI2_VERSION) {
r = _base_display_fwpkg_version(ioc);
@@ -6928,7 +7187,7 @@
/* synchronizing freeing resource with pci_access_mutex lock */
mutex_lock(&ioc->pci_access_mutex);
if (ioc->chip_phys && ioc->chip) {
- _base_mask_interrupts(ioc);
+ mpt3sas_base_mask_interrupts(ioc);
ioc->shost_recovery = 1;
_base_make_ioc_ready(ioc, SOFT_RESET);
ioc->shost_recovery = 0;
@@ -6961,8 +7220,7 @@
ioc->cpu_msix_table = kzalloc(ioc->cpu_msix_table_sz, GFP_KERNEL);
ioc->reply_queue_count = 1;
if (!ioc->cpu_msix_table) {
- dfailprintk(ioc,
- ioc_info(ioc, "allocation for cpu_msix_table failed!!!\n"));
+ ioc_info(ioc, "Allocation for cpu_msix_table failed!!!\n");
r = -ENOMEM;
goto out_free_resources;
}
@@ -6971,8 +7229,7 @@
ioc->reply_post_host_index = kcalloc(ioc->cpu_msix_table_sz,
sizeof(resource_size_t *), GFP_KERNEL);
if (!ioc->reply_post_host_index) {
- dfailprintk(ioc,
- ioc_info(ioc, "allocation for reply_post_host_index failed!!!\n"));
+ ioc_info(ioc, "Allocation for reply_post_host_index failed!!!\n");
r = -ENOMEM;
goto out_free_resources;
}
@@ -6981,7 +7238,7 @@
ioc->smp_affinity_enable = smp_affinity_enable;
ioc->rdpq_array_enable_assigned = 0;
- ioc->dma_mask = 0;
+ ioc->use_32bit_dma = false;
if (ioc->is_aero_ioc)
ioc->base_readl = &_base_readl_aero;
else
@@ -7202,6 +7459,7 @@
sizeof(struct mpt3sas_facts));
ioc->non_operational_loop = 0;
+ ioc->ioc_coredump_loop = 0;
ioc->got_task_abort_from_ioctl = 0;
return 0;
@@ -7283,14 +7541,14 @@
}
/**
- * _base_after_reset_handler - after reset handler
+ * _base_clear_outstanding_mpt_commands - clears outstanding mpt commands
* @ioc: per adapter object
*/
-static void _base_after_reset_handler(struct MPT3SAS_ADAPTER *ioc)
+static void
+_base_clear_outstanding_mpt_commands(struct MPT3SAS_ADAPTER *ioc)
{
- mpt3sas_scsih_after_reset_handler(ioc);
- mpt3sas_ctl_after_reset_handler(ioc);
- dtmprintk(ioc, ioc_info(ioc, "%s: MPT3_IOC_AFTER_RESET\n", __func__));
+ dtmprintk(ioc,
+ ioc_info(ioc, "%s: clear outstanding mpt cmds\n", __func__));
if (ioc->transport_cmds.status & MPT3_CMD_PENDING) {
ioc->transport_cmds.status |= MPT3_CMD_RESET;
mpt3sas_base_free_smid(ioc, ioc->transport_cmds.smid);
@@ -7324,6 +7582,17 @@
}
/**
+ * _base_clear_outstanding_commands - clear all outstanding commands
+ * @ioc: per adapter object
+ */
+static void _base_clear_outstanding_commands(struct MPT3SAS_ADAPTER *ioc)
+{
+ mpt3sas_scsih_clear_outstanding_scsi_tm_commands(ioc);
+ mpt3sas_ctl_clear_outstanding_ioctls(ioc);
+ _base_clear_outstanding_mpt_commands(ioc);
+}
+
+/**
* _base_reset_done_handler - reset done handler
* @ioc: per adapter object
*/
@@ -7481,16 +7750,18 @@
MPT3_DIAG_BUFFER_IS_RELEASED))) {
is_trigger = 1;
ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
- if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
+ if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT ||
+ (ioc_state & MPI2_IOC_STATE_MASK) ==
+ MPI2_IOC_STATE_COREDUMP)
is_fault = 1;
}
_base_pre_reset_handler(ioc);
mpt3sas_wait_for_commands_to_complete(ioc);
- _base_mask_interrupts(ioc);
+ mpt3sas_base_mask_interrupts(ioc);
r = _base_make_ioc_ready(ioc, type);
if (r)
goto out;
- _base_after_reset_handler(ioc);
+ _base_clear_outstanding_commands(ioc);
/* If this hard reset is called while port enable is active, then
* there is no reason to call make_ioc_operational
@@ -7521,9 +7792,7 @@
_base_reset_done_handler(ioc);
out:
- dtmprintk(ioc,
- ioc_info(ioc, "%s: %s\n",
- __func__, r == 0 ? "SUCCESS" : "FAILED"));
+ ioc_info(ioc, "%s: %s\n", __func__, r == 0 ? "SUCCESS" : "FAILED");
spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
ioc->shost_recovery = 0;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index faca0a5..bc8beb1 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -76,8 +76,8 @@
#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 "31.100.00.00"
-#define MPT3SAS_MAJOR_VERSION 31
+#define MPT3SAS_DRIVER_VERSION "35.100.00.00"
+#define MPT3SAS_MAJOR_VERSION 35
#define MPT3SAS_MINOR_VERSION 100
#define MPT3SAS_BUILD_VERSION 0
#define MPT3SAS_RELEASE_VERSION 00
@@ -90,6 +90,10 @@
#define MPT2SAS_BUILD_VERSION 0
#define MPT2SAS_RELEASE_VERSION 00
+/* CoreDump: Default timeout */
+#define MPT3SAS_DEFAULT_COREDUMP_TIMEOUT_SECONDS (15) /*15 seconds*/
+#define MPT3SAS_COREDUMP_LOOP_DONE (0xFF)
+
/*
* Set MPT3SAS_SG_DEPTH value based on user input.
*/
@@ -140,6 +144,7 @@
#define MAX_CHAIN_ELEMT_SZ 16
#define DEFAULT_NUM_FWCHAIN_ELEMTS 8
+#define IO_UNIT_CONTROL_SHUTDOWN_TIMEOUT 6
#define FW_IMG_HDR_READ_TIMEOUT 15
#define IOC_OPERATIONAL_WAIT_COUNT 10
@@ -303,6 +308,8 @@
#define MPT3_DIAG_BUFFER_IS_REGISTERED (0x01)
#define MPT3_DIAG_BUFFER_IS_RELEASED (0x02)
#define MPT3_DIAG_BUFFER_IS_DIAG_RESET (0x04)
+#define MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED (0x08)
+#define MPT3_DIAG_BUFFER_IS_APP_OWNED (0x10)
/*
* HP HBA branding
@@ -360,6 +367,7 @@
#define MPT3SAS_HIGH_IOPS_REPLY_QUEUES 8
#define MPT3SAS_HIGH_IOPS_BATCH_COUNT 16
#define MPT3SAS_GEN35_MAX_MSIX_QUEUES 128
+#define RDPQ_MAX_INDEX_IN_ONE_CHUNK 16
/* OEM Specific Flags will come from OEM specific header files */
struct Mpi2ManufacturingPage10_t {
@@ -391,9 +399,15 @@
u8 Reserved6; /* 2Fh */
__le32 Reserved7[7]; /* 30h - 4Bh */
u8 NVMeAbortTO; /* 4Ch */
- u8 Reserved8; /* 4Dh */
- u16 Reserved9; /* 4Eh */
- __le32 Reserved10[4]; /* 50h - 60h */
+ u8 NumPerDevEvents; /* 4Dh */
+ u8 HostTraceBufferDecrementSizeKB; /* 4Eh */
+ u8 HostTraceBufferFlags; /* 4Fh */
+ u16 HostTraceBufferMaxSizeKB; /* 50h */
+ u16 HostTraceBufferMinSizeKB; /* 52h */
+ u8 CoreDumpTOSec; /* 54h */
+ u8 Reserved8; /* 55h */
+ u16 Reserved9; /* 56h */
+ __le32 Reserved10; /* 58h */
};
/**
@@ -584,6 +598,7 @@
* @connector_name: ASCII value of the Connector's name
* @serial_number: pointer of serial number string allocated runtime
* @access_status: Device's Access Status
+ * @shutdown_latency: NVMe device's RTD3 Entry Latency
* @refcount: reference count for deletion
*/
struct _pcie_device {
@@ -606,6 +621,7 @@
u8 *serial_number;
u8 reset_timeout;
u8 access_status;
+ u16 shutdown_latency;
struct kref refcount;
};
/**
@@ -1011,7 +1027,6 @@
* @ir_firmware: IR firmware present
* @bars: bitmask of BAR's that must be configured
* @mask_interrupts: ignore interrupt
- * @dma_mask: used to set the consistent dma mask
* @pci_access_mutex: Mutex to synchronize ioctl, sysfs show path and
* pci resource handling
* @fault_reset_work_q_name: fw fault work queue
@@ -1021,6 +1036,8 @@
* @firmware_event_thread: ""
* @fw_event_lock:
* @fw_event_list: list of fw events
+ * @current_evet: current processing firmware event
+ * @fw_event_cleanup: set to one while cleaning up the fw events
* @aen_event_read_flag: event log was read
* @broadcast_aen_busy: broadcast aen waiting to be serviced
* @shost_recovery: host reset in progress
@@ -1040,6 +1057,7 @@
* @cpu_msix_table: table for mapping cpus to msix index
* @cpu_msix_table_sz: table size
* @total_io_cnt: Gives total IO count, used to load balance the interrupts
+ * @ioc_coredump_loop: will have non-zero value when FW is in CoreDump state
* @high_iops_outstanding: used to load balance the interrupts
* within high iops reply queues
* @msix_load_balance: Enables load balancing of interrupts across
@@ -1048,6 +1066,7 @@
* @thresh_hold: Max number of reply descriptors processed
* before updating Host Index
* @drv_support_bitmap: driver's supported feature bit map
+ * @use_32bit_dma: Flag to use 32 bit consistent dma mask
* @scsi_io_cb_idx: shost generated commands
* @tm_cb_idx: task management commands
* @scsih_cb_idx: scsih internal commands
@@ -1068,6 +1087,10 @@
* @event_context: unique id for each logged event
* @event_log: event log pointer
* @event_masks: events that are masked
+ * @max_shutdown_latency: timeout value for NVMe shutdown operation,
+ * which is equal that NVMe drive's RTD3 Entry Latency
+ * which has reported maximum RTD3 Entry Latency value
+ * among attached NVMe drives.
* @facts: static facts data
* @prev_fw_facts: previous fw facts data
* @pfacts: static port facts data
@@ -1185,7 +1208,6 @@
u8 ir_firmware;
int bars;
u8 mask_interrupts;
- int dma_mask;
/* fw fault handler */
char fault_reset_work_q_name[20];
@@ -1197,6 +1219,8 @@
struct workqueue_struct *firmware_event_thread;
spinlock_t fw_event_lock;
struct list_head fw_event_list;
+ struct fw_event_work *current_event;
+ u8 fw_events_cleanup;
/* misc flags */
int aen_event_read_flag;
@@ -1226,6 +1250,7 @@
u32 ioc_reset_count;
MPT3SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds;
u32 non_operational_loop;
+ u8 ioc_coredump_loop;
atomic64_t total_io_cnt;
atomic64_t high_iops_outstanding;
bool msix_load_balance;
@@ -1233,6 +1258,7 @@
u8 high_iops_queues;
u32 drv_support_bitmap;
bool enable_sdev_max_qd;
+ bool use_32bit_dma;
/* internal commands, callback index */
u8 scsi_io_cb_idx;
@@ -1278,7 +1304,7 @@
u8 tm_custom_handling;
u8 nvme_abort_timeout;
-
+ u16 max_shutdown_latency;
/* static config pages */
struct mpt3sas_facts facts;
@@ -1450,6 +1476,8 @@
u16 device_remove_in_progress_sz;
u8 is_gen35_ioc;
u8 is_aero_ioc;
+ struct dentry *debugfs_root;
+ struct dentry *ioc_dump;
PUT_SMID_IO_FP_HIP put_smid_scsi_io;
PUT_SMID_IO_FP_HIP put_smid_fast_path;
PUT_SMID_IO_FP_HIP put_smid_hi_priority;
@@ -1457,6 +1485,11 @@
GET_MSIX_INDEX get_msix_index_for_smlio;
};
+struct mpt3sas_debugfs_buffer {
+ void *buf;
+ u32 len;
+};
+
#define MPT_DRV_SUPPORT_BITMAP_MEMMOVE 0x00000001
typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
@@ -1495,7 +1528,9 @@
u16 smid);
void *mpt3sas_base_get_pcie_sgl(struct MPT3SAS_ADAPTER *ioc, u16 smid);
dma_addr_t mpt3sas_base_get_pcie_sgl_dma(struct MPT3SAS_ADAPTER *ioc, u16 smid);
-void mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc);
+void mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER *ioc, u8 poll);
+void mpt3sas_base_mask_interrupts(struct MPT3SAS_ADAPTER *ioc);
+void mpt3sas_base_unmask_interrupts(struct MPT3SAS_ADAPTER *ioc);
void mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid,
u16 handle);
@@ -1526,6 +1561,17 @@
u32 mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, int cooked);
void mpt3sas_base_fault_info(struct MPT3SAS_ADAPTER *ioc , u16 fault_code);
+#define mpt3sas_print_fault_code(ioc, fault_code) \
+do { pr_err("%s fault info from func: %s\n", ioc->name, __func__); \
+ mpt3sas_base_fault_info(ioc, fault_code); } while (0)
+
+void mpt3sas_base_coredump_info(struct MPT3SAS_ADAPTER *ioc, u16 fault_code);
+#define mpt3sas_print_coredump_info(ioc, fault_code) \
+do { pr_err("%s fault info from func: %s\n", ioc->name, __func__); \
+ mpt3sas_base_coredump_info(ioc, fault_code); } while (0)
+
+int mpt3sas_base_wait_for_coredump_completion(struct MPT3SAS_ADAPTER *ioc,
+ const char *caller);
int mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc,
Mpi2SasIoUnitControlReply_t *mpi_reply,
Mpi2SasIoUnitControlRequest_t *mpi_request);
@@ -1547,6 +1593,11 @@
u8 mpt3sas_base_check_cmd_timeout(struct MPT3SAS_ADAPTER *ioc,
u8 status, void *mpi_request, int sz);
+#define mpt3sas_check_cmd_timeout(ioc, status, mpi_request, sz, issue_reset) \
+do { ioc_err(ioc, "In func: %s\n", __func__); \
+ issue_reset = mpt3sas_base_check_cmd_timeout(ioc, \
+ status, mpi_request, sz); } while (0)
+
int mpt3sas_wait_for_ioc(struct MPT3SAS_ADAPTER *ioc, int wait_count);
/* scsih shared API */
@@ -1555,14 +1606,16 @@
u8 mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
u32 reply);
void mpt3sas_scsih_pre_reset_handler(struct MPT3SAS_ADAPTER *ioc);
-void mpt3sas_scsih_after_reset_handler(struct MPT3SAS_ADAPTER *ioc);
+void mpt3sas_scsih_clear_outstanding_scsi_tm_commands(
+ struct MPT3SAS_ADAPTER *ioc);
void mpt3sas_scsih_reset_done_handler(struct MPT3SAS_ADAPTER *ioc);
-int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, u64 lun,
- u8 type, u16 smid_task, u16 msix_task, u8 timeout, u8 tr_method);
+int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+ uint channel, uint id, u64 lun, u8 type, u16 smid_task,
+ u16 msix_task, u8 timeout, u8 tr_method);
int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
- u64 lun, u8 type, u16 smid_task, u16 msix_task,
- u8 timeout, u8 tr_method);
+ uint channel, uint id, u64 lun, u8 type, u16 smid_task,
+ u16 msix_task, u8 timeout, u8 tr_method);
void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
@@ -1689,7 +1742,7 @@
u8 mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
u32 reply);
void mpt3sas_ctl_pre_reset_handler(struct MPT3SAS_ADAPTER *ioc);
-void mpt3sas_ctl_after_reset_handler(struct MPT3SAS_ADAPTER *ioc);
+void mpt3sas_ctl_clear_outstanding_ioctls(struct MPT3SAS_ADAPTER *ioc);
void mpt3sas_ctl_reset_done_handler(struct MPT3SAS_ADAPTER *ioc);
u8 mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc,
u8 msix_index, u32 reply);
@@ -1724,7 +1777,7 @@
void mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc,
struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data);
void mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc,
- u32 tigger_bitmask);
+ u32 trigger_bitmask);
void mpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event,
u16 log_entry_qualifier);
void mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key,
@@ -1743,6 +1796,11 @@
/* NCQ Prio Handling Check */
bool scsih_ncq_prio_supp(struct scsi_device *sdev);
+void mpt3sas_setup_debugfs(struct MPT3SAS_ADAPTER *ioc);
+void mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER *ioc);
+void mpt3sas_init_debugfs(void);
+void mpt3sas_exit_debugfs(void);
+
/**
* _scsih_is_pcie_scsi_device - determines if device is an pcie scsi device
* @device_info: bitfield providing information about the device.
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c
index 14a1a27..4a0ddc7 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_config.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_config.c
@@ -101,9 +101,6 @@
Mpi2ConfigRequest_t *mpi_request;
char *desc = NULL;
- if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
- return;
-
mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
case MPI2_CONFIG_PAGETYPE_IO_UNIT:
@@ -269,7 +266,8 @@
mpi_reply->MsgLength*4);
}
ioc->config_cmds.status &= ~MPT3_CMD_PENDING;
- _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
+ if (ioc->logging_level & MPT_DEBUG_CONFIG)
+ _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
ioc->config_cmds.smid = USHRT_MAX;
complete(&ioc->config_cmds.done);
return 1;
@@ -373,19 +371,23 @@
}
r = 0;
- memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
+ memset(ioc->config_cmds.reply, 0, sizeof(Mpi2ConfigReply_t));
ioc->config_cmds.status = MPT3_CMD_PENDING;
config_request = mpt3sas_base_get_msg_frame(ioc, smid);
ioc->config_cmds.smid = smid;
memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
- _config_display_some_debug(ioc, smid, "config_request", NULL);
+ if (ioc->logging_level & MPT_DEBUG_CONFIG)
+ _config_display_some_debug(ioc, smid, "config_request", NULL);
init_completion(&ioc->config_cmds.done);
ioc->put_smid_default(ioc, smid);
wait_for_completion_timeout(&ioc->config_cmds.done, timeout*HZ);
if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) {
- mpt3sas_base_check_cmd_timeout(ioc,
- ioc->config_cmds.status, mpi_request,
- sizeof(Mpi2ConfigRequest_t)/4);
+ if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
+ _config_display_some_debug(ioc,
+ smid, "config_request", NULL);
+ ioc_err(ioc, "%s: command timeout\n", __func__);
+ mpt3sas_base_check_cmd_timeout(ioc, ioc->config_cmds.status,
+ mpi_request, sizeof(Mpi2ConfigRequest_t) / 4);
retry_count++;
if (ioc->config_cmds.smid == smid)
mpt3sas_base_free_smid(ioc, smid);
@@ -404,8 +406,11 @@
/* Reply Frame Sanity Checks to workaround FW issues */
if ((mpi_request->Header.PageType & 0xF) !=
(mpi_reply->Header.PageType & 0xF)) {
+ if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
+ _config_display_some_debug(ioc,
+ smid, "config_request", NULL);
_debug_dump_mf(mpi_request, ioc->request_sz/4);
- _debug_dump_reply(mpi_reply, ioc->request_sz/4);
+ _debug_dump_reply(mpi_reply, ioc->reply_sz/4);
panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
ioc->name, __func__,
mpi_request->Header.PageType & 0xF,
@@ -415,8 +420,11 @@
if (((mpi_request->Header.PageType & 0xF) ==
MPI2_CONFIG_PAGETYPE_EXTENDED) &&
mpi_request->ExtPageType != mpi_reply->ExtPageType) {
+ if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
+ _config_display_some_debug(ioc,
+ smid, "config_request", NULL);
_debug_dump_mf(mpi_request, ioc->request_sz/4);
- _debug_dump_reply(mpi_reply, ioc->request_sz/4);
+ _debug_dump_reply(mpi_reply, ioc->reply_sz/4);
panic("%s: %s: Firmware BUG: mpi_reply mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
ioc->name, __func__,
mpi_request->ExtPageType,
@@ -439,8 +447,11 @@
if (p) {
if ((mpi_request->Header.PageType & 0xF) !=
(p[3] & 0xF)) {
+ if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
+ _config_display_some_debug(ioc,
+ smid, "config_request", NULL);
_debug_dump_mf(mpi_request, ioc->request_sz/4);
- _debug_dump_reply(mpi_reply, ioc->request_sz/4);
+ _debug_dump_reply(mpi_reply, ioc->reply_sz/4);
_debug_dump_config(p, min_t(u16, mem.sz,
config_page_sz)/4);
panic("%s: %s: Firmware BUG: config page mismatch: Requested PageType(0x%02x) Reply PageType(0x%02x)\n",
@@ -452,8 +463,11 @@
if (((mpi_request->Header.PageType & 0xF) ==
MPI2_CONFIG_PAGETYPE_EXTENDED) &&
(mpi_request->ExtPageType != p[6])) {
+ if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
+ _config_display_some_debug(ioc,
+ smid, "config_request", NULL);
_debug_dump_mf(mpi_request, ioc->request_sz/4);
- _debug_dump_reply(mpi_reply, ioc->request_sz/4);
+ _debug_dump_reply(mpi_reply, ioc->reply_sz/4);
_debug_dump_config(p, min_t(u16, mem.sz,
config_page_sz)/4);
panic("%s: %s: Firmware BUG: config page mismatch: Requested ExtPageType(0x%02x) Reply ExtPageType(0x%02x)\n",
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index 1c5c172..edd26a2 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -180,6 +180,12 @@
case MPI2_FUNCTION_SMP_PASSTHROUGH:
desc = "smp_passthrough";
break;
+ case MPI2_FUNCTION_TOOLBOX:
+ desc = "toolbox";
+ break;
+ case MPI2_FUNCTION_NVME_ENCAPSULATED:
+ desc = "nvme_encapsulated";
+ break;
}
if (!desc)
@@ -466,19 +472,27 @@
if ((ioc->diag_buffer_status[i] &
MPT3_DIAG_BUFFER_IS_RELEASED))
continue;
+
+ /*
+ * add a log message to indicate the release
+ */
+ ioc_info(ioc,
+ "%s: Releasing the trace buffer due to adapter reset.",
+ __func__);
mpt3sas_send_diag_release(ioc, i, &issue_reset);
}
}
/**
- * mpt3sas_ctl_reset_handler - reset callback handler (for ctl)
+ * mpt3sas_ctl_reset_handler - clears outstanding ioctl cmd.
* @ioc: per adapter object
*
* The handler for doing any required cleanup or initialization.
*/
-void mpt3sas_ctl_after_reset_handler(struct MPT3SAS_ADAPTER *ioc)
+void mpt3sas_ctl_clear_outstanding_ioctls(struct MPT3SAS_ADAPTER *ioc)
{
- dtmprintk(ioc, ioc_info(ioc, "%s: MPT3_IOC_AFTER_RESET\n", __func__));
+ dtmprintk(ioc,
+ ioc_info(ioc, "%s: clear outstanding ioctl cmd\n", __func__));
if (ioc->ctl_cmds.status & MPT3_CMD_PENDING) {
ioc->ctl_cmds.status |= MPT3_CMD_RESET;
mpt3sas_base_free_smid(ioc, ioc->ctl_cmds.smid);
@@ -988,7 +1002,7 @@
}
/* drop to default case for posting the request */
}
- /* fall through */
+ fallthrough;
default:
ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz,
data_in_dma, data_in_sz);
@@ -1014,10 +1028,9 @@
ioc->ignore_loginfos = 0;
}
if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
- issue_reset =
- mpt3sas_base_check_cmd_timeout(ioc,
- ioc->ctl_cmds.status, mpi_request,
- karg.data_sge_offset);
+ mpt3sas_check_cmd_timeout(ioc,
+ ioc->ctl_cmds.status, mpi_request,
+ karg.data_sge_offset, issue_reset);
goto issue_host_reset;
}
@@ -1096,13 +1109,15 @@
pcie_device->device_info))))
mpt3sas_scsih_issue_locked_tm(ioc,
le16_to_cpu(mpi_request->FunctionDependent1),
- 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
+ 0, 0, 0,
+ MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
0, pcie_device->reset_timeout,
MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE);
else
mpt3sas_scsih_issue_locked_tm(ioc,
le16_to_cpu(mpi_request->FunctionDependent1),
- 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
+ 0, 0, 0,
+ MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
0, 30, MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET);
} else
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
@@ -1318,7 +1333,8 @@
__func__));
retval = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
- ioc_info(ioc, "host reset: %s\n", ((!retval) ? "SUCCESS" : "FAILED"));
+ ioc_info(ioc,
+ "Ioctl: host reset: %s\n", ((!retval) ? "SUCCESS" : "FAILED"));
return 0;
}
@@ -1496,6 +1512,26 @@
return rc;
}
+/**
+ * _ctl_diag_get_bufftype - return diag buffer type
+ * either TRACE, SNAPSHOT, or EXTENDED
+ * @ioc: per adapter object
+ * @unique_id: specifies the unique_id for the buffer
+ *
+ * returns MPT3_DIAG_UID_NOT_FOUND if the id not found
+ */
+static u8
+_ctl_diag_get_bufftype(struct MPT3SAS_ADAPTER *ioc, u32 unique_id)
+{
+ u8 index;
+
+ for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) {
+ if (ioc->unique_id[index] == unique_id)
+ return index;
+ }
+
+ return MPT3_DIAG_UID_NOT_FOUND;
+}
/**
* _ctl_diag_register_2 - wrapper for registering diag buffer support
@@ -1543,11 +1579,88 @@
return -EPERM;
}
+ if (diag_register->unique_id == 0) {
+ ioc_err(ioc,
+ "%s: Invalid UID(0x%08x), buffer_type(0x%02x)\n", __func__,
+ diag_register->unique_id, buffer_type);
+ return -EINVAL;
+ }
+
+ if ((ioc->diag_buffer_status[buffer_type] &
+ MPT3_DIAG_BUFFER_IS_APP_OWNED) &&
+ !(ioc->diag_buffer_status[buffer_type] &
+ MPT3_DIAG_BUFFER_IS_RELEASED)) {
+ ioc_err(ioc,
+ "%s: buffer_type(0x%02x) is already registered by application with UID(0x%08x)\n",
+ __func__, buffer_type, ioc->unique_id[buffer_type]);
+ return -EINVAL;
+ }
+
if (ioc->diag_buffer_status[buffer_type] &
MPT3_DIAG_BUFFER_IS_REGISTERED) {
- ioc_err(ioc, "%s: already has a registered buffer for buffer_type(0x%02x)\n",
- __func__, buffer_type);
- return -EINVAL;
+ /*
+ * If driver posts buffer initially, then an application wants
+ * to Register that buffer (own it) without Releasing first,
+ * the application Register command MUST have the same buffer
+ * type and size in the Register command (obtained from the
+ * Query command). Otherwise that Register command will be
+ * failed. If the application has released the buffer but wants
+ * to re-register it, it should be allowed as long as the
+ * Unique-Id/Size match.
+ */
+
+ if (ioc->unique_id[buffer_type] == MPT3DIAGBUFFUNIQUEID &&
+ ioc->diag_buffer_sz[buffer_type] ==
+ diag_register->requested_buffer_size) {
+
+ if (!(ioc->diag_buffer_status[buffer_type] &
+ MPT3_DIAG_BUFFER_IS_RELEASED)) {
+ dctlprintk(ioc, ioc_info(ioc,
+ "%s: diag_buffer (%d) ownership changed. old-ID(0x%08x), new-ID(0x%08x)\n",
+ __func__, buffer_type,
+ ioc->unique_id[buffer_type],
+ diag_register->unique_id));
+
+ /*
+ * Application wants to own the buffer with
+ * the same size.
+ */
+ ioc->unique_id[buffer_type] =
+ diag_register->unique_id;
+ rc = 0; /* success */
+ goto out;
+ }
+ } else if (ioc->unique_id[buffer_type] !=
+ MPT3DIAGBUFFUNIQUEID) {
+ if (ioc->unique_id[buffer_type] !=
+ diag_register->unique_id ||
+ ioc->diag_buffer_sz[buffer_type] !=
+ diag_register->requested_buffer_size ||
+ !(ioc->diag_buffer_status[buffer_type] &
+ MPT3_DIAG_BUFFER_IS_RELEASED)) {
+ ioc_err(ioc,
+ "%s: already has a registered buffer for buffer_type(0x%02x)\n",
+ __func__, buffer_type);
+ return -EINVAL;
+ }
+ } else {
+ ioc_err(ioc, "%s: already has a registered buffer for buffer_type(0x%02x)\n",
+ __func__, buffer_type);
+ return -EINVAL;
+ }
+ } else if (ioc->diag_buffer_status[buffer_type] &
+ MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED) {
+
+ if (ioc->unique_id[buffer_type] != MPT3DIAGBUFFUNIQUEID ||
+ ioc->diag_buffer_sz[buffer_type] !=
+ diag_register->requested_buffer_size) {
+
+ ioc_err(ioc,
+ "%s: already a buffer is allocated for buffer_type(0x%02x) of size %d bytes, so please try registering again with same size\n",
+ __func__, buffer_type,
+ ioc->diag_buffer_sz[buffer_type]);
+ return -EINVAL;
+ }
}
if (diag_register->requested_buffer_size % 4) {
@@ -1572,7 +1685,8 @@
request_data = ioc->diag_buffer[buffer_type];
request_data_sz = diag_register->requested_buffer_size;
ioc->unique_id[buffer_type] = diag_register->unique_id;
- ioc->diag_buffer_status[buffer_type] = 0;
+ ioc->diag_buffer_status[buffer_type] &=
+ MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED;
memcpy(ioc->product_specific[buffer_type],
diag_register->product_specific, MPT3_PRODUCT_SPECIFIC_DWORDS);
ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags;
@@ -1628,10 +1742,9 @@
MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
- issue_reset =
- mpt3sas_base_check_cmd_timeout(ioc,
- ioc->ctl_cmds.status, mpi_request,
- sizeof(Mpi2DiagBufferPostRequest_t)/4);
+ mpt3sas_check_cmd_timeout(ioc,
+ ioc->ctl_cmds.status, mpi_request,
+ sizeof(Mpi2DiagBufferPostRequest_t)/4, issue_reset);
goto issue_host_reset;
}
@@ -1662,9 +1775,12 @@
out:
- if (rc && request_data)
+ if (rc && request_data) {
dma_free_coherent(&ioc->pdev->dev, request_data_sz,
request_data, request_data_dma);
+ ioc->diag_buffer_status[buffer_type] &=
+ ~MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED;
+ }
ioc->ctl_cmds.status = MPT3_CMD_NOT_USED;
return rc;
@@ -1682,6 +1798,10 @@
mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc, u8 bits_to_register)
{
struct mpt3_diag_register diag_register;
+ u32 ret_val;
+ u32 trace_buff_size = ioc->manu_pg11.HostTraceBufferMaxSizeKB<<10;
+ u32 min_trace_buff_size = 0;
+ u32 decr_trace_buff_size = 0;
memset(&diag_register, 0, sizeof(struct mpt3_diag_register));
@@ -1690,10 +1810,68 @@
ioc->diag_trigger_master.MasterData =
(MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET);
diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
- /* register for 2MB buffers */
- diag_register.requested_buffer_size = 2 * (1024 * 1024);
- diag_register.unique_id = 0x7075900;
- _ctl_diag_register_2(ioc, &diag_register);
+ diag_register.unique_id =
+ (ioc->hba_mpi_version_belonged == MPI2_VERSION) ?
+ (MPT2DIAGBUFFUNIQUEID):(MPT3DIAGBUFFUNIQUEID);
+
+ if (trace_buff_size != 0) {
+ diag_register.requested_buffer_size = trace_buff_size;
+ min_trace_buff_size =
+ ioc->manu_pg11.HostTraceBufferMinSizeKB<<10;
+ decr_trace_buff_size =
+ ioc->manu_pg11.HostTraceBufferDecrementSizeKB<<10;
+
+ if (min_trace_buff_size > trace_buff_size) {
+ /* The buff size is not set correctly */
+ ioc_err(ioc,
+ "Min Trace Buff size (%d KB) greater than Max Trace Buff size (%d KB)\n",
+ min_trace_buff_size>>10,
+ trace_buff_size>>10);
+ ioc_err(ioc,
+ "Using zero Min Trace Buff Size\n");
+ min_trace_buff_size = 0;
+ }
+
+ if (decr_trace_buff_size == 0) {
+ /*
+ * retry the min size if decrement
+ * is not available.
+ */
+ decr_trace_buff_size =
+ trace_buff_size - min_trace_buff_size;
+ }
+ } else {
+ /* register for 2MB buffers */
+ diag_register.requested_buffer_size = 2 * (1024 * 1024);
+ }
+
+ do {
+ ret_val = _ctl_diag_register_2(ioc, &diag_register);
+
+ if (ret_val == -ENOMEM && min_trace_buff_size &&
+ (trace_buff_size - decr_trace_buff_size) >=
+ min_trace_buff_size) {
+ /* adjust the buffer size */
+ trace_buff_size -= decr_trace_buff_size;
+ diag_register.requested_buffer_size =
+ trace_buff_size;
+ } else
+ break;
+ } while (true);
+
+ if (ret_val == -ENOMEM)
+ ioc_err(ioc,
+ "Cannot allocate trace buffer memory. Last memory tried = %d KB\n",
+ diag_register.requested_buffer_size>>10);
+ else if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE]
+ & MPT3_DIAG_BUFFER_IS_REGISTERED) {
+ ioc_err(ioc, "Trace buffer memory %d KB allocated\n",
+ diag_register.requested_buffer_size>>10);
+ if (ioc->hba_mpi_version_belonged != MPI2_VERSION)
+ ioc->diag_buffer_status[
+ MPI2_DIAG_BUF_TYPE_TRACE] |=
+ MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED;
+ }
}
if (bits_to_register & 2) {
@@ -1736,6 +1914,12 @@
}
rc = _ctl_diag_register_2(ioc, &karg);
+
+ if (!rc && (ioc->diag_buffer_status[karg.buffer_type] &
+ MPT3_DIAG_BUFFER_IS_REGISTERED))
+ ioc->diag_buffer_status[karg.buffer_type] |=
+ MPT3_DIAG_BUFFER_IS_APP_OWNED;
+
return rc;
}
@@ -1765,7 +1949,13 @@
dctlprintk(ioc, ioc_info(ioc, "%s\n",
__func__));
- buffer_type = karg.unique_id & 0x000000ff;
+ buffer_type = _ctl_diag_get_bufftype(ioc, karg.unique_id);
+ if (buffer_type == MPT3_DIAG_UID_NOT_FOUND) {
+ ioc_err(ioc, "%s: buffer with unique_id(0x%08x) not found\n",
+ __func__, karg.unique_id);
+ return -EINVAL;
+ }
+
if (!_ctl_diag_capability(ioc, buffer_type)) {
ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
__func__, buffer_type);
@@ -1798,12 +1988,21 @@
return -ENOMEM;
}
- request_data_sz = ioc->diag_buffer_sz[buffer_type];
- request_data_dma = ioc->diag_buffer_dma[buffer_type];
- dma_free_coherent(&ioc->pdev->dev, request_data_sz,
- request_data, request_data_dma);
- ioc->diag_buffer[buffer_type] = NULL;
- ioc->diag_buffer_status[buffer_type] = 0;
+ if (ioc->diag_buffer_status[buffer_type] &
+ MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED) {
+ ioc->unique_id[buffer_type] = MPT3DIAGBUFFUNIQUEID;
+ ioc->diag_buffer_status[buffer_type] &=
+ ~MPT3_DIAG_BUFFER_IS_APP_OWNED;
+ ioc->diag_buffer_status[buffer_type] &=
+ ~MPT3_DIAG_BUFFER_IS_REGISTERED;
+ } else {
+ request_data_sz = ioc->diag_buffer_sz[buffer_type];
+ request_data_dma = ioc->diag_buffer_dma[buffer_type];
+ dma_free_coherent(&ioc->pdev->dev, request_data_sz,
+ request_data, request_data_dma);
+ ioc->diag_buffer[buffer_type] = NULL;
+ ioc->diag_buffer_status[buffer_type] = 0;
+ }
return 0;
}
@@ -1842,14 +2041,17 @@
return -EPERM;
}
- if ((ioc->diag_buffer_status[buffer_type] &
- MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
- ioc_err(ioc, "%s: buffer_type(0x%02x) is not registered\n",
- __func__, buffer_type);
- return -EINVAL;
+ if (!(ioc->diag_buffer_status[buffer_type] &
+ MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED)) {
+ if ((ioc->diag_buffer_status[buffer_type] &
+ MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) {
+ ioc_err(ioc, "%s: buffer_type(0x%02x) is not registered\n",
+ __func__, buffer_type);
+ return -EINVAL;
+ }
}
- if (karg.unique_id & 0xffffff00) {
+ if (karg.unique_id) {
if (karg.unique_id != ioc->unique_id[buffer_type]) {
ioc_err(ioc, "%s: unique_id(0x%08x) is not registered\n",
__func__, karg.unique_id);
@@ -1864,13 +2066,21 @@
return -ENOMEM;
}
- if (ioc->diag_buffer_status[buffer_type] & MPT3_DIAG_BUFFER_IS_RELEASED)
- karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED |
- MPT3_APP_FLAGS_BUFFER_VALID);
- else
- karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED |
- MPT3_APP_FLAGS_BUFFER_VALID |
- MPT3_APP_FLAGS_FW_BUFFER_ACCESS);
+ if ((ioc->diag_buffer_status[buffer_type] &
+ MPT3_DIAG_BUFFER_IS_REGISTERED))
+ karg.application_flags |= MPT3_APP_FLAGS_BUFFER_VALID;
+
+ if (!(ioc->diag_buffer_status[buffer_type] &
+ MPT3_DIAG_BUFFER_IS_RELEASED))
+ karg.application_flags |= MPT3_APP_FLAGS_FW_BUFFER_ACCESS;
+
+ if (!(ioc->diag_buffer_status[buffer_type] &
+ MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED))
+ karg.application_flags |= MPT3_APP_FLAGS_DYNAMIC_BUFFER_ALLOC;
+
+ if ((ioc->diag_buffer_status[buffer_type] &
+ MPT3_DIAG_BUFFER_IS_APP_OWNED))
+ karg.application_flags |= MPT3_APP_FLAGS_APP_OWNED;
for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++)
karg.product_specific[i] =
@@ -1906,6 +2116,7 @@
u16 ioc_status;
u32 ioc_state;
int rc;
+ u8 reset_needed = 0;
dctlprintk(ioc, ioc_info(ioc, "%s\n",
__func__));
@@ -1913,6 +2124,7 @@
rc = 0;
*issue_reset = 0;
+
ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
if (ioc->diag_buffer_status[buffer_type] &
@@ -1955,9 +2167,10 @@
MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
- *issue_reset = mpt3sas_base_check_cmd_timeout(ioc,
- ioc->ctl_cmds.status, mpi_request,
- sizeof(Mpi2DiagReleaseRequest_t)/4);
+ mpt3sas_check_cmd_timeout(ioc,
+ ioc->ctl_cmds.status, mpi_request,
+ sizeof(Mpi2DiagReleaseRequest_t)/4, reset_needed);
+ *issue_reset = reset_needed;
rc = -EFAULT;
goto out;
}
@@ -2015,7 +2228,13 @@
dctlprintk(ioc, ioc_info(ioc, "%s\n",
__func__));
- buffer_type = karg.unique_id & 0x000000ff;
+ buffer_type = _ctl_diag_get_bufftype(ioc, karg.unique_id);
+ if (buffer_type == MPT3_DIAG_UID_NOT_FOUND) {
+ ioc_err(ioc, "%s: buffer with unique_id(0x%08x) not found\n",
+ __func__, karg.unique_id);
+ return -EINVAL;
+ }
+
if (!_ctl_diag_capability(ioc, buffer_type)) {
ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
__func__, buffer_type);
@@ -2039,7 +2258,7 @@
MPT3_DIAG_BUFFER_IS_RELEASED) {
ioc_err(ioc, "%s: buffer_type(0x%02x) is already released\n",
__func__, buffer_type);
- return 0;
+ return -EINVAL;
}
request_data = ioc->diag_buffer[buffer_type];
@@ -2099,7 +2318,13 @@
dctlprintk(ioc, ioc_info(ioc, "%s\n",
__func__));
- buffer_type = karg.unique_id & 0x000000ff;
+ buffer_type = _ctl_diag_get_bufftype(ioc, karg.unique_id);
+ if (buffer_type == MPT3_DIAG_UID_NOT_FOUND) {
+ ioc_err(ioc, "%s: buffer with unique_id(0x%08x) not found\n",
+ __func__, karg.unique_id);
+ return -EINVAL;
+ }
+
if (!_ctl_diag_capability(ioc, buffer_type)) {
ioc_err(ioc, "%s: doesn't have capability for buffer_type(0x%02x)\n",
__func__, buffer_type);
@@ -2203,10 +2428,9 @@
MPT3_IOCTL_DEFAULT_TIMEOUT*HZ);
if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) {
- issue_reset =
- mpt3sas_base_check_cmd_timeout(ioc,
- ioc->ctl_cmds.status, mpi_request,
- sizeof(Mpi2DiagBufferPostRequest_t)/4);
+ mpt3sas_check_cmd_timeout(ioc,
+ ioc->ctl_cmds.status, mpi_request,
+ sizeof(Mpi2DiagBufferPostRequest_t)/4, issue_reset);
goto issue_host_reset;
}
@@ -2223,6 +2447,8 @@
if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
ioc->diag_buffer_status[buffer_type] |=
MPT3_DIAG_BUFFER_IS_REGISTERED;
+ ioc->diag_buffer_status[buffer_type] &=
+ ~MPT3_DIAG_BUFFER_IS_RELEASED;
dctlprintk(ioc, ioc_info(ioc, "%s: success\n", __func__));
} else {
ioc_info(ioc, "%s: ioc_status(0x%04x) log_info(0x%08x)\n",
@@ -3145,10 +3371,47 @@
memset(&diag_register, 0, sizeof(struct mpt3_diag_register));
ioc_info(ioc, "posting host trace buffers\n");
diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
- diag_register.requested_buffer_size = (1024 * 1024);
- diag_register.unique_id = 0x7075900;
+
+ if (ioc->manu_pg11.HostTraceBufferMaxSizeKB != 0 &&
+ ioc->diag_buffer_sz[MPI2_DIAG_BUF_TYPE_TRACE] != 0) {
+ /* post the same buffer allocated previously */
+ diag_register.requested_buffer_size =
+ ioc->diag_buffer_sz[MPI2_DIAG_BUF_TYPE_TRACE];
+ } else {
+ /*
+ * Free the diag buffer memory which was previously
+ * allocated by an application.
+ */
+ if ((ioc->diag_buffer_sz[MPI2_DIAG_BUF_TYPE_TRACE] != 0)
+ &&
+ (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+ MPT3_DIAG_BUFFER_IS_APP_OWNED)) {
+ dma_free_coherent(&ioc->pdev->dev,
+ ioc->diag_buffer_sz[MPI2_DIAG_BUF_TYPE_TRACE],
+ ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE],
+ ioc->diag_buffer_dma[MPI2_DIAG_BUF_TYPE_TRACE]);
+ ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE] =
+ NULL;
+ }
+
+ diag_register.requested_buffer_size = (1024 * 1024);
+ }
+
+ diag_register.unique_id =
+ (ioc->hba_mpi_version_belonged == MPI2_VERSION) ?
+ (MPT2DIAGBUFFUNIQUEID):(MPT3DIAGBUFFUNIQUEID);
ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0;
_ctl_diag_register_2(ioc, &diag_register);
+ if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+ MPT3_DIAG_BUFFER_IS_REGISTERED) {
+ ioc_info(ioc,
+ "Trace buffer %d KB allocated through sysfs\n",
+ diag_register.requested_buffer_size>>10);
+ if (ioc->hba_mpi_version_belonged != MPI2_VERSION)
+ ioc->diag_buffer_status[
+ MPI2_DIAG_BUF_TYPE_TRACE] |=
+ MPT3_DIAG_BUFFER_IS_DRIVER_ALLOCATED;
+ }
} else if (!strcmp(str, "release")) {
/* exit out if host buffers are already released */
if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE])
@@ -3399,8 +3662,9 @@
/**
* drv_support_bitmap_show - driver supported feature bitmap
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
+ * @cdev: pointer to embedded class device
+ * @attr: unused
+ * @buf: the buffer returned
*
* A sysfs 'read-only' shost attribute.
*/
@@ -3417,8 +3681,9 @@
/**
* enable_sdev_max_qd_show - display whether sdev max qd is enabled/disabled
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
+ * @cdev: pointer to embedded class device
+ * @attr: unused
+ * @buf: the buffer returned
*
* A sysfs read/write shost attribute. This attribute is used to set the
* targets queue depth to HBA IO queue depth if this attribute is enabled.
@@ -3435,8 +3700,10 @@
/**
* enable_sdev_max_qd_store - Enable/disable sdev max qd
- * @cdev - pointer to embedded class device
- * @buf - the buffer returned
+ * @cdev: pointer to embedded class device
+ * @attr: unused
+ * @buf: the buffer returned
+ * @count: unused
*
* A sysfs read/write shost attribute. This attribute is used to set the
* targets queue depth to HBA IO queue depth if this attribute is enabled.
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.h b/drivers/scsi/mpt3sas/mpt3sas_ctl.h
index 18b46fa..0f7aa4d 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.h
@@ -95,6 +95,14 @@
#define MPT3DIAGREADBUFFER _IOWR(MPT3_MAGIC_NUMBER, 30, \
struct mpt3_diag_read_buffer)
+/* Trace Buffer default UniqueId */
+#define MPT2DIAGBUFFUNIQUEID (0x07075900)
+#define MPT3DIAGBUFFUNIQUEID (0x4252434D)
+
+/* UID not found */
+#define MPT3_DIAG_UID_NOT_FOUND (0xFF)
+
+
/**
* struct mpt3_ioctl_header - main header structure
* @ioc_number - IOC unit number
@@ -310,6 +318,7 @@
#define MPT3_APP_FLAGS_APP_OWNED (0x0001)
#define MPT3_APP_FLAGS_BUFFER_VALID (0x0002)
#define MPT3_APP_FLAGS_FW_BUFFER_ACCESS (0x0004)
+#define MPT3_APP_FLAGS_DYNAMIC_BUFFER_ALLOC (0x0008)
/* flags for mpt3_diag_read_buffer */
#define MPT3_FLAGS_REREGISTER (0x0001)
diff --git a/drivers/scsi/mpt3sas/mpt3sas_debugfs.c b/drivers/scsi/mpt3sas/mpt3sas_debugfs.c
new file mode 100644
index 0000000..a6ab1db
--- /dev/null
+++ b/drivers/scsi/mpt3sas/mpt3sas_debugfs.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Debugfs interface Support for MPT (Message Passing Technology) based
+ * controllers.
+ *
+ * Copyright (C) 2020 Broadcom Inc.
+ *
+ * Authors: Broadcom Inc.
+ * Sreekanth Reddy <sreekanth.reddy@broadcom.com>
+ * Suganath Prabu <suganath-prabu.subramani@broadcom.com>
+ *
+ * Send feedback to : MPT-FusionLinux.pdl@broadcom.com)
+ *
+ **/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/compat.h>
+#include <linux/uio.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include "mpt3sas_base.h"
+#include <linux/debugfs.h>
+
+static struct dentry *mpt3sas_debugfs_root;
+
+/*
+ * _debugfs_iocdump_read - copy ioc dump from debugfs buffer
+ * @filep: File Pointer
+ * @ubuf: Buffer to fill data
+ * @cnt: Length of the buffer
+ * @ppos: Offset in the file
+ */
+
+static ssize_t
+_debugfs_iocdump_read(struct file *filp, char __user *ubuf, size_t cnt,
+ loff_t *ppos)
+
+{
+ struct mpt3sas_debugfs_buffer *debug = filp->private_data;
+
+ if (!debug || !debug->buf)
+ return 0;
+
+ return simple_read_from_buffer(ubuf, cnt, ppos, debug->buf, debug->len);
+}
+
+/*
+ * _debugfs_iocdump_open : open the ioc_dump debugfs attribute file
+ */
+static int
+_debugfs_iocdump_open(struct inode *inode, struct file *file)
+{
+ struct MPT3SAS_ADAPTER *ioc = inode->i_private;
+ struct mpt3sas_debugfs_buffer *debug;
+
+ debug = kzalloc(sizeof(struct mpt3sas_debugfs_buffer), GFP_KERNEL);
+ if (!debug)
+ return -ENOMEM;
+
+ debug->buf = (void *)ioc;
+ debug->len = sizeof(struct MPT3SAS_ADAPTER);
+ file->private_data = debug;
+ return 0;
+}
+
+/*
+ * _debugfs_iocdump_release : release the ioc_dump debugfs attribute
+ * @inode: inode structure to the corresponds device
+ * @file: File pointer
+ */
+static int
+_debugfs_iocdump_release(struct inode *inode, struct file *file)
+{
+ struct mpt3sas_debugfs_buffer *debug = file->private_data;
+
+ if (!debug)
+ return 0;
+
+ file->private_data = NULL;
+ kfree(debug);
+ return 0;
+}
+
+static const struct file_operations mpt3sas_debugfs_iocdump_fops = {
+ .owner = THIS_MODULE,
+ .open = _debugfs_iocdump_open,
+ .read = _debugfs_iocdump_read,
+ .release = _debugfs_iocdump_release,
+};
+
+/*
+ * mpt3sas_init_debugfs : Create debugfs root for mpt3sas driver
+ */
+void mpt3sas_init_debugfs(void)
+{
+ mpt3sas_debugfs_root = debugfs_create_dir("mpt3sas", NULL);
+ if (!mpt3sas_debugfs_root)
+ pr_info("mpt3sas: Cannot create debugfs root\n");
+}
+
+/*
+ * mpt3sas_exit_debugfs : Remove debugfs root for mpt3sas driver
+ */
+void mpt3sas_exit_debugfs(void)
+{
+ debugfs_remove_recursive(mpt3sas_debugfs_root);
+}
+
+/*
+ * mpt3sas_setup_debugfs : Setup debugfs per HBA adapter
+ * ioc: MPT3SAS_ADAPTER object
+ */
+void
+mpt3sas_setup_debugfs(struct MPT3SAS_ADAPTER *ioc)
+{
+ char name[64];
+
+ snprintf(name, sizeof(name), "scsi_host%d", ioc->shost->host_no);
+ if (!ioc->debugfs_root) {
+ ioc->debugfs_root =
+ debugfs_create_dir(name, mpt3sas_debugfs_root);
+ if (!ioc->debugfs_root) {
+ dev_err(&ioc->pdev->dev,
+ "Cannot create per adapter debugfs directory\n");
+ return;
+ }
+ }
+
+ snprintf(name, sizeof(name), "ioc_dump");
+ ioc->ioc_dump = debugfs_create_file(name, 0444,
+ ioc->debugfs_root, ioc, &mpt3sas_debugfs_iocdump_fops);
+ if (!ioc->ioc_dump) {
+ dev_err(&ioc->pdev->dev,
+ "Cannot create ioc_dump debugfs file\n");
+ debugfs_remove(ioc->debugfs_root);
+ return;
+ }
+
+ snprintf(name, sizeof(name), "host_recovery");
+ debugfs_create_u8(name, 0444, ioc->debugfs_root, &ioc->shost_recovery);
+
+}
+
+/*
+ * mpt3sas_destroy_debugfs : Destroy debugfs per HBA adapter
+ * @ioc: MPT3SAS_ADAPTER object
+ */
+void mpt3sas_destroy_debugfs(struct MPT3SAS_ADAPTER *ioc)
+{
+ debugfs_remove_recursive(ioc->debugfs_root);
+}
+
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 3654cfc..8418b59 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -207,7 +207,7 @@
u8 ignore;
u16 event;
struct kref refcount;
- char event_data[0] __aligned(4);
+ char event_data[] __aligned(4);
};
static void fw_event_work_free(struct kref *r)
@@ -1050,6 +1050,34 @@
}
/**
+ * _scsih_set_nvme_max_shutdown_latency - Update max_shutdown_latency.
+ * @ioc: per adapter object
+ * Context: This function will acquire ioc->pcie_device_lock
+ *
+ * Update ioc->max_shutdown_latency to that NVMe drives RTD3 Entry Latency
+ * which has reported maximum among all available NVMe drives.
+ * Minimum max_shutdown_latency will be six seconds.
+ */
+static void
+_scsih_set_nvme_max_shutdown_latency(struct MPT3SAS_ADAPTER *ioc)
+{
+ struct _pcie_device *pcie_device;
+ unsigned long flags;
+ u16 shutdown_latency = IO_UNIT_CONTROL_SHUTDOWN_TIMEOUT;
+
+ spin_lock_irqsave(&ioc->pcie_device_lock, flags);
+ list_for_each_entry(pcie_device, &ioc->pcie_device_list, list) {
+ if (pcie_device->shutdown_latency) {
+ if (shutdown_latency < pcie_device->shutdown_latency)
+ shutdown_latency =
+ pcie_device->shutdown_latency;
+ }
+ }
+ ioc->max_shutdown_latency = shutdown_latency;
+ spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
+}
+
+/**
* _scsih_pcie_device_remove - remove pcie_device from list.
* @ioc: per adapter object
* @pcie_device: the pcie_device object
@@ -1063,6 +1091,7 @@
{
unsigned long flags;
int was_on_pcie_device_list = 0;
+ u8 update_latency = 0;
if (!pcie_device)
return;
@@ -1082,11 +1111,21 @@
list_del_init(&pcie_device->list);
was_on_pcie_device_list = 1;
}
+ if (pcie_device->shutdown_latency == ioc->max_shutdown_latency)
+ update_latency = 1;
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
if (was_on_pcie_device_list) {
kfree(pcie_device->serial_number);
pcie_device_put(pcie_device);
}
+
+ /*
+ * This device's RTD3 Entry Latency matches IOC's
+ * max_shutdown_latency. Recalculate IOC's max_shutdown_latency
+ * from the available drives as current drive is getting removed.
+ */
+ if (update_latency)
+ _scsih_set_nvme_max_shutdown_latency(ioc);
}
@@ -1101,6 +1140,7 @@
struct _pcie_device *pcie_device;
unsigned long flags;
int was_on_pcie_device_list = 0;
+ u8 update_latency = 0;
if (ioc->shost_recovery)
return;
@@ -1113,12 +1153,22 @@
was_on_pcie_device_list = 1;
pcie_device_put(pcie_device);
}
+ if (pcie_device->shutdown_latency == ioc->max_shutdown_latency)
+ update_latency = 1;
}
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
if (was_on_pcie_device_list) {
_scsih_pcie_device_remove_from_sml(ioc, pcie_device);
pcie_device_put(pcie_device);
}
+
+ /*
+ * This device's RTD3 Entry Latency matches IOC's
+ * max_shutdown_latency. Recalculate IOC's max_shutdown_latency
+ * from the available drives as current drive is getting removed.
+ */
+ if (update_latency)
+ _scsih_set_nvme_max_shutdown_latency(ioc);
}
/**
@@ -1463,6 +1513,66 @@
}
/**
+ * _scsih_scsi_lookup_find_by_target - search for matching channel:id
+ * @ioc: per adapter object
+ * @id: target id
+ * @channel: channel
+ * Context: This function will acquire ioc->scsi_lookup_lock.
+ *
+ * This will search for a matching channel:id in the scsi_lookup array,
+ * returning 1 if found.
+ */
+static u8
+_scsih_scsi_lookup_find_by_target(struct MPT3SAS_ADAPTER *ioc, int id,
+ int channel)
+{
+ int smid;
+ struct scsi_cmnd *scmd;
+
+ for (smid = 1;
+ smid <= ioc->shost->can_queue; smid++) {
+ scmd = mpt3sas_scsih_scsi_lookup_get(ioc, smid);
+ if (!scmd)
+ continue;
+ if (scmd->device->id == id &&
+ scmd->device->channel == channel)
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun
+ * @ioc: per adapter object
+ * @id: target id
+ * @lun: lun number
+ * @channel: channel
+ * Context: This function will acquire ioc->scsi_lookup_lock.
+ *
+ * This will search for a matching channel:id:lun in the scsi_lookup array,
+ * returning 1 if found.
+ */
+static u8
+_scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
+ unsigned int lun, int channel)
+{
+ int smid;
+ struct scsi_cmnd *scmd;
+
+ for (smid = 1; smid <= ioc->shost->can_queue; smid++) {
+
+ scmd = mpt3sas_scsih_scsi_lookup_get(ioc, smid);
+ if (!scmd)
+ continue;
+ if (scmd->device->id == id &&
+ scmd->device->channel == channel &&
+ scmd->device->lun == lun)
+ return 1;
+ }
+ return 0;
+}
+
+/**
* mpt3sas_scsih_scsi_lookup_get - returns scmd entry
* @ioc: per adapter object
* @smid: system request message index
@@ -1554,7 +1664,12 @@
max_depth = 1;
if (qdepth > max_depth)
qdepth = max_depth;
- return scsi_change_queue_depth(sdev, qdepth);
+ scsi_change_queue_depth(sdev, qdepth);
+ sdev_printk(KERN_INFO, sdev,
+ "qdepth(%d), tagged(%d), scsi_level(%d), cmd_que(%d)\n",
+ sdev->queue_depth, sdev->tagged_supported,
+ sdev->scsi_level, ((sdev->inquiry[7] & 2) >> 1));
+ return sdev->queue_depth;
}
/**
@@ -2646,9 +2761,101 @@
}
/**
+ * scsih_tm_cmd_map_status - map the target reset & LUN reset TM status
+ * @ioc - per adapter object
+ * @channel - the channel assigned by the OS
+ * @id: the id assigned by the OS
+ * @lun: lun number
+ * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
+ * @smid_task: smid assigned to the task
+ *
+ * Look whether TM has aborted the timed out SCSI command, if
+ * TM has aborted the IO then return SUCCESS else return FAILED.
+ */
+static int
+scsih_tm_cmd_map_status(struct MPT3SAS_ADAPTER *ioc, uint channel,
+ uint id, uint lun, u8 type, u16 smid_task)
+{
+
+ if (smid_task <= ioc->shost->can_queue) {
+ switch (type) {
+ case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
+ if (!(_scsih_scsi_lookup_find_by_target(ioc,
+ id, channel)))
+ return SUCCESS;
+ break;
+ case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
+ case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
+ if (!(_scsih_scsi_lookup_find_by_lun(ioc, id,
+ lun, channel)))
+ return SUCCESS;
+ break;
+ default:
+ return SUCCESS;
+ }
+ } else if (smid_task == ioc->scsih_cmds.smid) {
+ if ((ioc->scsih_cmds.status & MPT3_CMD_COMPLETE) ||
+ (ioc->scsih_cmds.status & MPT3_CMD_NOT_USED))
+ return SUCCESS;
+ } else if (smid_task == ioc->ctl_cmds.smid) {
+ if ((ioc->ctl_cmds.status & MPT3_CMD_COMPLETE) ||
+ (ioc->ctl_cmds.status & MPT3_CMD_NOT_USED))
+ return SUCCESS;
+ }
+
+ return FAILED;
+}
+
+/**
+ * scsih_tm_post_processing - post processing of target & LUN reset
+ * @ioc - per adapter object
+ * @handle: device handle
+ * @channel - the channel assigned by the OS
+ * @id: the id assigned by the OS
+ * @lun: lun number
+ * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
+ * @smid_task: smid assigned to the task
+ *
+ * Post processing of target & LUN reset. Due to interrupt latency
+ * issue it possible that interrupt for aborted IO might not be
+ * received yet. So before returning failure status, poll the
+ * reply descriptor pools for the reply of timed out SCSI command.
+ * Return FAILED status if reply for timed out is not received
+ * otherwise return SUCCESS.
+ */
+static int
+scsih_tm_post_processing(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+ uint channel, uint id, uint lun, u8 type, u16 smid_task)
+{
+ int rc;
+
+ rc = scsih_tm_cmd_map_status(ioc, channel, id, lun, type, smid_task);
+ if (rc == SUCCESS)
+ return rc;
+
+ ioc_info(ioc,
+ "Poll ReplyDescriptor queues for completion of"
+ " smid(%d), task_type(0x%02x), handle(0x%04x)\n",
+ smid_task, type, handle);
+
+ /*
+ * Due to interrupt latency issues, driver may receive interrupt for
+ * TM first and then for aborted SCSI IO command. So, poll all the
+ * ReplyDescriptor pools before returning the FAILED status to SML.
+ */
+ mpt3sas_base_mask_interrupts(ioc);
+ mpt3sas_base_sync_reply_irqs(ioc, 1);
+ mpt3sas_base_unmask_interrupts(ioc);
+
+ return scsih_tm_cmd_map_status(ioc, channel, id, lun, type, smid_task);
+}
+
+/**
* mpt3sas_scsih_issue_tm - main routine for sending tm requests
* @ioc: per adapter struct
* @handle: device handle
+ * @channel: the channel assigned by the OS
+ * @id: the id assigned by the OS
* @lun: lun number
* @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
* @smid_task: smid assigned to the task
@@ -2665,14 +2872,17 @@
* Return: SUCCESS or FAILED.
*/
int
-mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, u64 lun,
- u8 type, u16 smid_task, u16 msix_task, u8 timeout, u8 tr_method)
+mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel,
+ uint id, u64 lun, u8 type, u16 smid_task, u16 msix_task,
+ u8 timeout, u8 tr_method)
{
Mpi2SCSITaskManagementRequest_t *mpi_request;
Mpi2SCSITaskManagementReply_t *mpi_reply;
+ Mpi25SCSIIORequest_t *request;
u16 smid = 0;
u32 ioc_state;
int rc;
+ u8 issue_reset = 0;
lockdep_assert_held(&ioc->tm_cmds.mutex);
@@ -2695,7 +2905,13 @@
}
if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
- mpt3sas_base_fault_info(ioc, ioc_state &
+ mpt3sas_print_fault_code(ioc, ioc_state &
+ MPI2_DOORBELL_DATA_MASK);
+ rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
+ return (!rc) ? SUCCESS : FAILED;
+ } else if ((ioc_state & MPI2_IOC_STATE_MASK) ==
+ MPI2_IOC_STATE_COREDUMP) {
+ mpt3sas_print_coredump_info(ioc, ioc_state &
MPI2_DOORBELL_DATA_MASK);
rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
return (!rc) ? SUCCESS : FAILED;
@@ -2718,7 +2934,9 @@
mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
mpi_request->DevHandle = cpu_to_le16(handle);
mpi_request->TaskType = type;
- mpi_request->MsgFlags = tr_method;
+ if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK ||
+ type == MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK)
+ mpi_request->MsgFlags = tr_method;
mpi_request->TaskMID = cpu_to_le16(smid_task);
int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
mpt3sas_scsih_set_tm_flag(ioc, handle);
@@ -2726,9 +2944,10 @@
ioc->put_smid_hi_priority(ioc, smid, msix_task);
wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) {
- if (mpt3sas_base_check_cmd_timeout(ioc,
- ioc->tm_cmds.status, mpi_request,
- sizeof(Mpi2SCSITaskManagementRequest_t)/4)) {
+ mpt3sas_check_cmd_timeout(ioc,
+ ioc->tm_cmds.status, mpi_request,
+ sizeof(Mpi2SCSITaskManagementRequest_t)/4, issue_reset);
+ if (issue_reset) {
rc = mpt3sas_base_hard_reset_handler(ioc,
FORCE_BIG_HAMMER);
rc = (!rc) ? SUCCESS : FAILED;
@@ -2737,7 +2956,7 @@
}
/* sync IRQs in case those were busy during flush. */
- mpt3sas_base_sync_reply_irqs(ioc);
+ mpt3sas_base_sync_reply_irqs(ioc, 0);
if (ioc->tm_cmds.status & MPT3_CMD_REPLY_VALID) {
mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT);
@@ -2754,7 +2973,44 @@
sizeof(Mpi2SCSITaskManagementRequest_t)/4);
}
}
- rc = SUCCESS;
+
+ switch (type) {
+ case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
+ rc = SUCCESS;
+ /*
+ * If DevHandle filed in smid_task's entry of request pool
+ * doesn't match with device handle on which this task abort
+ * TM is received then it means that TM has successfully
+ * aborted the timed out command. Since smid_task's entry in
+ * request pool will be memset to zero once the timed out
+ * command is returned to the SML. If the command is not
+ * aborted then smid_task’s entry won’t be cleared and it
+ * will have same DevHandle value on which this task abort TM
+ * is received and driver will return the TM status as FAILED.
+ */
+ request = mpt3sas_base_get_msg_frame(ioc, smid_task);
+ if (le16_to_cpu(request->DevHandle) != handle)
+ break;
+
+ ioc_info(ioc, "Task abort tm failed: handle(0x%04x),"
+ "timeout(%d) tr_method(0x%x) smid(%d) msix_index(%d)\n",
+ handle, timeout, tr_method, smid_task, msix_task);
+ rc = FAILED;
+ break;
+
+ case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
+ case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
+ case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
+ rc = scsih_tm_post_processing(ioc, handle, channel, id, lun,
+ type, smid_task);
+ break;
+ case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
+ rc = SUCCESS;
+ break;
+ default:
+ rc = FAILED;
+ break;
+ }
out:
mpt3sas_scsih_clear_tm_flag(ioc, handle);
@@ -2763,14 +3019,14 @@
}
int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
- u64 lun, u8 type, u16 smid_task, u16 msix_task,
- u8 timeout, u8 tr_method)
+ uint channel, uint id, u64 lun, u8 type, u16 smid_task,
+ u16 msix_task, u8 timeout, u8 tr_method)
{
int ret;
mutex_lock(&ioc->tm_cmds.mutex);
- ret = mpt3sas_scsih_issue_tm(ioc, handle, lun, type, smid_task,
- msix_task, timeout, tr_method);
+ ret = mpt3sas_scsih_issue_tm(ioc, handle, channel, id, lun, type,
+ smid_task, msix_task, timeout, tr_method);
mutex_unlock(&ioc->tm_cmds.mutex);
return ret;
@@ -2875,15 +3131,17 @@
u8 timeout = 30;
struct _pcie_device *pcie_device = NULL;
- sdev_printk(KERN_INFO, scmd->device,
- "attempting task abort! scmd(%p)\n", scmd);
+ sdev_printk(KERN_INFO, scmd->device, "attempting task abort!"
+ "scmd(0x%p), outstanding for %u ms & timeout %u ms\n",
+ scmd, jiffies_to_msecs(jiffies - scmd->jiffies_at_alloc),
+ (scmd->request->timeout / HZ) * 1000);
_scsih_tm_display_info(ioc, scmd);
sas_device_priv_data = scmd->device->hostdata;
if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
ioc->remove_host) {
sdev_printk(KERN_INFO, scmd->device,
- "device been deleted! scmd(%p)\n", scmd);
+ "device been deleted! scmd(0x%p)\n", scmd);
scmd->result = DID_NO_CONNECT << 16;
scmd->scsi_done(scmd);
r = SUCCESS;
@@ -2892,6 +3150,8 @@
/* check for completed command */
if (st == NULL || st->cb_idx == 0xFF) {
+ sdev_printk(KERN_INFO, scmd->device, "No reference found at "
+ "driver, assuming scmd(0x%p) might have completed\n", scmd);
scmd->result = DID_RESET << 16;
r = SUCCESS;
goto out;
@@ -2913,14 +3173,15 @@
if (pcie_device && (!ioc->tm_custom_handling) &&
(!(mpt3sas_scsih_is_pcie_scsi_device(pcie_device->device_info))))
timeout = ioc->nvme_abort_timeout;
- r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->lun,
+ r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel,
+ scmd->device->id, scmd->device->lun,
MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
st->smid, st->msix_io, timeout, 0);
/* Command must be cleared after abort */
if (r == SUCCESS && st->cb_idx != 0xFF)
r = FAILED;
out:
- sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
+ sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(0x%p)\n",
((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
if (pcie_device)
pcie_device_put(pcie_device);
@@ -2949,14 +3210,14 @@
struct MPT3SAS_TARGET *target_priv_data = starget->hostdata;
sdev_printk(KERN_INFO, scmd->device,
- "attempting device reset! scmd(%p)\n", scmd);
+ "attempting device reset! scmd(0x%p)\n", scmd);
_scsih_tm_display_info(ioc, scmd);
sas_device_priv_data = scmd->device->hostdata;
if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
ioc->remove_host) {
sdev_printk(KERN_INFO, scmd->device,
- "device been deleted! scmd(%p)\n", scmd);
+ "device been deleted! scmd(0x%p)\n", scmd);
scmd->result = DID_NO_CONNECT << 16;
scmd->scsi_done(scmd);
r = SUCCESS;
@@ -2989,14 +3250,15 @@
} else
tr_method = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
- r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->lun,
+ r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel,
+ scmd->device->id, scmd->device->lun,
MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 0,
tr_timeout, tr_method);
/* Check for busy commands after reset */
if (r == SUCCESS && atomic_read(&scmd->device->device_busy))
r = FAILED;
out:
- sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
+ sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(0x%p)\n",
((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
if (sas_device)
@@ -3027,15 +3289,15 @@
struct scsi_target *starget = scmd->device->sdev_target;
struct MPT3SAS_TARGET *target_priv_data = starget->hostdata;
- starget_printk(KERN_INFO, starget, "attempting target reset! scmd(%p)\n",
- scmd);
+ starget_printk(KERN_INFO, starget,
+ "attempting target reset! scmd(0x%p)\n", scmd);
_scsih_tm_display_info(ioc, scmd);
sas_device_priv_data = scmd->device->hostdata;
if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
ioc->remove_host) {
- starget_printk(KERN_INFO, starget, "target been deleted! scmd(%p)\n",
- scmd);
+ starget_printk(KERN_INFO, starget,
+ "target been deleted! scmd(0x%p)\n", scmd);
scmd->result = DID_NO_CONNECT << 16;
scmd->scsi_done(scmd);
r = SUCCESS;
@@ -3067,14 +3329,15 @@
tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
} else
tr_method = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
- r = mpt3sas_scsih_issue_locked_tm(ioc, handle, 0,
+ r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel,
+ scmd->device->id, 0,
MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 0,
tr_timeout, tr_method);
/* Check for busy commands after reset */
if (r == SUCCESS && atomic_read(&starget->target_busy))
r = FAILED;
out:
- starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
+ starget_printk(KERN_INFO, starget, "target reset: %s scmd(0x%p)\n",
((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
if (sas_device)
@@ -3097,7 +3360,7 @@
struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
int r, retval;
- ioc_info(ioc, "attempting host reset! scmd(%p)\n", scmd);
+ ioc_info(ioc, "attempting host reset! scmd(0x%p)\n", scmd);
scsi_print_command(scmd);
if (ioc->is_driver_loading || ioc->remove_host) {
@@ -3109,7 +3372,7 @@
retval = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
r = (retval < 0) ? FAILED : SUCCESS;
out:
- ioc_info(ioc, "host reset: %s scmd(%p)\n",
+ ioc_info(ioc, "host reset: %s scmd(0x%p)\n",
r == SUCCESS ? "SUCCESS" : "FAILED", scmd);
return r;
@@ -3256,11 +3519,35 @@
{
struct fw_event_work *fw_event;
- if (list_empty(&ioc->fw_event_list) ||
+ if ((list_empty(&ioc->fw_event_list) && !ioc->current_event) ||
!ioc->firmware_event_thread || in_interrupt())
return;
- while ((fw_event = dequeue_next_fw_event(ioc))) {
+ ioc->fw_events_cleanup = 1;
+ while ((fw_event = dequeue_next_fw_event(ioc)) ||
+ (fw_event = ioc->current_event)) {
+
+ /*
+ * Don't call cancel_work_sync() for current_event
+ * other than MPT3SAS_REMOVE_UNRESPONDING_DEVICES;
+ * otherwise we may observe deadlock if current
+ * hard reset issued as part of processing the current_event.
+ *
+ * Orginal logic of cleaning the current_event is added
+ * for handling the back to back host reset issued by the user.
+ * i.e. during back to back host reset, driver use to process
+ * the two instances of MPT3SAS_REMOVE_UNRESPONDING_DEVICES
+ * event back to back and this made the drives to unregister
+ * the devices from SML.
+ */
+
+ if (fw_event == ioc->current_event &&
+ ioc->current_event->event !=
+ MPT3SAS_REMOVE_UNRESPONDING_DEVICES) {
+ ioc->current_event = NULL;
+ continue;
+ }
+
/*
* Wait on the fw_event to complete. If this returns 1, then
* the event was never executed, and we need a put for the
@@ -3274,6 +3561,7 @@
fw_event_work_put(fw_event);
}
+ ioc->fw_events_cleanup = 0;
}
/**
@@ -3387,7 +3675,7 @@
shost_for_each_device(sdev, ioc->shost) {
sas_device_priv_data = sdev->hostdata;
- if (!sas_device_priv_data)
+ if (!sas_device_priv_data || !sas_device_priv_data->sas_target)
continue;
if (sas_device_priv_data->sas_target->sas_address
!= sas_address)
@@ -4475,6 +4763,7 @@
_scsih_temp_threshold_events(struct MPT3SAS_ADAPTER *ioc,
Mpi2EventDataTemperature_t *event_data)
{
+ u32 doorbell;
if (ioc->temp_sensors_count >= event_data->SensorNum) {
ioc_err(ioc, "Temperature Threshold flags %s%s%s%s exceeded for Sensor: %d !!!\n",
le16_to_cpu(event_data->Status) & 0x1 ? "0 " : " ",
@@ -4484,6 +4773,18 @@
event_data->SensorNum);
ioc_err(ioc, "Current Temp In Celsius: %d\n",
event_data->CurrentTemperature);
+ if (ioc->hba_mpi_version_belonged != MPI2_VERSION) {
+ doorbell = mpt3sas_base_get_iocstate(ioc, 0);
+ if ((doorbell & MPI2_IOC_STATE_MASK) ==
+ MPI2_IOC_STATE_FAULT) {
+ mpt3sas_print_fault_code(ioc,
+ doorbell & MPI2_DOORBELL_DATA_MASK);
+ } else if ((doorbell & MPI2_IOC_STATE_MASK) ==
+ MPI2_IOC_STATE_COREDUMP) {
+ mpt3sas_print_coredump_info(ioc,
+ doorbell & MPI2_DOORBELL_DATA_MASK);
+ }
+ }
}
}
@@ -5161,7 +5462,7 @@
/* insert into event log */
sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
sizeof(Mpi2EventDataSasDeviceStatusChange_t);
- event_reply = kzalloc(sz, GFP_KERNEL);
+ event_reply = kzalloc(sz, GFP_ATOMIC);
if (!event_reply) {
ioc_err(ioc, "failure at %s:%d/%s()!\n",
__FILE__, __LINE__, __func__);
@@ -5390,7 +5691,7 @@
case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
scsi_set_resid(scmd, 0);
- /* fall through */
+ fallthrough;
case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
case MPI2_IOCSTATUS_SUCCESS:
scmd->result = (DID_OK << 16) | scsi_status;
@@ -6402,7 +6703,7 @@
if (!test_bit(handle, ioc->pend_os_device_add))
break;
- /* fall through */
+ fallthrough;
case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
@@ -6935,6 +7236,16 @@
le32_to_cpu(pcie_device_pg0.DeviceInfo)))) {
pcie_device->nvme_mdts =
le32_to_cpu(pcie_device_pg2.MaximumDataTransferSize);
+ pcie_device->shutdown_latency =
+ le16_to_cpu(pcie_device_pg2.ShutdownLatency);
+ /*
+ * Set IOC's max_shutdown_latency to drive's RTD3 Entry Latency
+ * if drive's RTD3 Entry Latency is greater then IOC's
+ * max_shutdown_latency.
+ */
+ if (pcie_device->shutdown_latency > ioc->max_shutdown_latency)
+ ioc->max_shutdown_latency =
+ pcie_device->shutdown_latency;
if (pcie_device_pg2.ControllerResetTO)
pcie_device->reset_timeout =
pcie_device_pg2.ControllerResetTO;
@@ -7120,7 +7431,7 @@
event_data->PortEntry[i].PortStatus &= 0xF0;
event_data->PortEntry[i].PortStatus |=
MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED;
- /* fall through */
+ fallthrough;
case MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED:
if (ioc->shost_recovery)
break;
@@ -7439,7 +7750,7 @@
goto out;
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- r = mpt3sas_scsih_issue_tm(ioc, handle, lun,
+ r = mpt3sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, st->smid,
st->msix_io, 30, 0);
if (r == FAILED) {
@@ -7480,9 +7791,9 @@
if (ioc->shost_recovery)
goto out_no_lock;
- r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->lun,
- MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, st->smid,
- st->msix_io, 30, 0);
+ r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
+ sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
+ st->smid, st->msix_io, 30, 0);
if (r == FAILED || st->cb_idx != 0xFF) {
sdev_printk(KERN_WARNING, sdev,
"mpt3sas_scsih_issue_tm: ABORT_TASK: FAILED : "
@@ -7671,10 +7982,9 @@
wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
- issue_reset =
- mpt3sas_base_check_cmd_timeout(ioc,
- ioc->scsih_cmds.status, mpi_request,
- sizeof(Mpi2RaidActionRequest_t)/4);
+ mpt3sas_check_cmd_timeout(ioc,
+ ioc->scsih_cmds.status, mpi_request,
+ sizeof(Mpi2RaidActionRequest_t)/4, issue_reset);
rc = -EFAULT;
goto out;
}
@@ -9274,15 +9584,17 @@
}
/**
- * mpt3sas_scsih_after_reset_handler - reset callback handler (for scsih)
+ * mpt3sas_scsih_clear_outstanding_scsi_tm_commands - clears outstanding
+ * scsi & tm cmds.
* @ioc: per adapter object
*
* The handler for doing any required cleanup or initialization.
*/
void
-mpt3sas_scsih_after_reset_handler(struct MPT3SAS_ADAPTER *ioc)
+mpt3sas_scsih_clear_outstanding_scsi_tm_commands(struct MPT3SAS_ADAPTER *ioc)
{
- dtmprintk(ioc, ioc_info(ioc, "%s: MPT3_IOC_AFTER_RESET\n", __func__));
+ dtmprintk(ioc,
+ ioc_info(ioc, "%s: clear outstanding scsi & tm cmds\n", __func__));
if (ioc->scsih_cmds.status & MPT3_CMD_PENDING) {
ioc->scsih_cmds.status |= MPT3_CMD_RESET;
mpt3sas_base_free_smid(ioc, ioc->scsih_cmds.smid);
@@ -9332,11 +9644,13 @@
static void
_mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
{
+ ioc->current_event = fw_event;
_scsih_fw_event_del_from_list(ioc, fw_event);
/* the queue is being flushed so ignore this event */
if (ioc->remove_host || ioc->pci_error_recovery) {
fw_event_work_put(fw_event);
+ ioc->current_event = NULL;
return;
}
@@ -9350,15 +9664,16 @@
while (scsi_host_in_recovery(ioc->shost) ||
ioc->shost_recovery) {
/*
- * If we're unloading, bail. Otherwise, this can become
- * an infinite loop.
+ * If we're unloading or cancelling the work, bail.
+ * Otherwise, this can become an infinite loop.
*/
- if (ioc->remove_host)
+ if (ioc->remove_host || ioc->fw_events_cleanup)
goto out;
ssleep(1);
}
_scsih_remove_unresponding_devices(ioc);
_scsih_scan_for_devices_after_reset(ioc);
+ _scsih_set_nvme_max_shutdown_latency(ioc);
break;
case MPT3SAS_PORT_ENABLE_COMPLETE:
ioc->start_scan = 0;
@@ -9413,11 +9728,13 @@
break;
case MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST:
_scsih_pcie_topology_change_event(ioc, fw_event);
+ ioc->current_event = NULL;
return;
break;
}
out:
fw_event_work_put(fw_event);
+ ioc->current_event = NULL;
}
/**
@@ -9662,6 +9979,75 @@
}
/**
+ * _scsih_nvme_shutdown - NVMe shutdown notification
+ * @ioc: per adapter object
+ *
+ * Sending IoUnitControl request with shutdown operation code to alert IOC that
+ * the host system is shutting down so that IOC can issue NVMe shutdown to
+ * NVMe drives attached to it.
+ */
+static void
+_scsih_nvme_shutdown(struct MPT3SAS_ADAPTER *ioc)
+{
+ Mpi26IoUnitControlRequest_t *mpi_request;
+ Mpi26IoUnitControlReply_t *mpi_reply;
+ u16 smid;
+
+ /* are there any NVMe devices ? */
+ if (list_empty(&ioc->pcie_device_list))
+ return;
+
+ mutex_lock(&ioc->scsih_cmds.mutex);
+
+ if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) {
+ ioc_err(ioc, "%s: scsih_cmd in use\n", __func__);
+ goto out;
+ }
+
+ ioc->scsih_cmds.status = MPT3_CMD_PENDING;
+
+ smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx);
+ if (!smid) {
+ ioc_err(ioc,
+ "%s: failed obtaining a smid\n", __func__);
+ ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
+ goto out;
+ }
+
+ mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+ ioc->scsih_cmds.smid = smid;
+ memset(mpi_request, 0, sizeof(Mpi26IoUnitControlRequest_t));
+ mpi_request->Function = MPI2_FUNCTION_IO_UNIT_CONTROL;
+ mpi_request->Operation = MPI26_CTRL_OP_SHUTDOWN;
+
+ init_completion(&ioc->scsih_cmds.done);
+ ioc->put_smid_default(ioc, smid);
+ /* Wait for max_shutdown_latency seconds */
+ ioc_info(ioc,
+ "Io Unit Control shutdown (sending), Shutdown latency %d sec\n",
+ ioc->max_shutdown_latency);
+ wait_for_completion_timeout(&ioc->scsih_cmds.done,
+ ioc->max_shutdown_latency*HZ);
+
+ if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
+ ioc_err(ioc, "%s: timeout\n", __func__);
+ goto out;
+ }
+
+ if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
+ mpi_reply = ioc->scsih_cmds.reply;
+ ioc_info(ioc, "Io Unit Control shutdown (complete):"
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
+ le16_to_cpu(mpi_reply->IOCStatus),
+ le32_to_cpu(mpi_reply->IOCLogInfo));
+ }
+ out:
+ ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
+ mutex_unlock(&ioc->scsih_cmds.mutex);
+}
+
+
+/**
* _scsih_ir_shutdown - IR shutdown notification
* @ioc: per adapter object
*
@@ -9730,6 +10116,34 @@
}
/**
+ * _scsih_get_shost_and_ioc - get shost and ioc
+ * and verify whether they are NULL or not
+ * @pdev: PCI device struct
+ * @shost: address of scsi host pointer
+ * @ioc: address of HBA adapter pointer
+ *
+ * Return zero if *shost and *ioc are not NULL otherwise return error number.
+ */
+static int
+_scsih_get_shost_and_ioc(struct pci_dev *pdev,
+ struct Scsi_Host **shost, struct MPT3SAS_ADAPTER **ioc)
+{
+ *shost = pci_get_drvdata(pdev);
+ if (*shost == NULL) {
+ dev_err(&pdev->dev, "pdev's driver data is null\n");
+ return -ENXIO;
+ }
+
+ *ioc = shost_priv(*shost);
+ if (*ioc == NULL) {
+ dev_err(&pdev->dev, "shost's private data is null\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+/**
* scsih_remove - detach and remove add host
* @pdev: PCI device struct
*
@@ -9737,8 +10151,8 @@
*/
static void scsih_remove(struct pci_dev *pdev)
{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+ struct Scsi_Host *shost;
+ struct MPT3SAS_ADAPTER *ioc;
struct _sas_port *mpt3sas_port, *next_port;
struct _raid_device *raid_device, *next;
struct MPT3SAS_TARGET *sas_target_priv_data;
@@ -9747,6 +10161,9 @@
unsigned long flags;
Mpi2ConfigReply_t mpi_reply;
+ if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
+ return;
+
ioc->remove_host = 1;
if (!pci_device_is_present(pdev))
@@ -9769,6 +10186,7 @@
&ioc->ioc_pg1_copy);
/* release all the volumes */
_scsih_ir_shutdown(ioc);
+ mpt3sas_destroy_debugfs(ioc);
sas_remove_host(shost);
list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
list) {
@@ -9825,12 +10243,15 @@
static void
scsih_shutdown(struct pci_dev *pdev)
{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+ struct Scsi_Host *shost;
+ struct MPT3SAS_ADAPTER *ioc;
struct workqueue_struct *wq;
unsigned long flags;
Mpi2ConfigReply_t mpi_reply;
+ if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
+ return;
+
ioc->remove_host = 1;
if (!pci_device_is_present(pdev))
@@ -9853,6 +10274,7 @@
&ioc->ioc_pg1_copy);
_scsih_ir_shutdown(ioc);
+ _scsih_nvme_shutdown(ioc);
mpt3sas_base_detach(ioc);
}
@@ -10195,6 +10617,8 @@
int rc;
if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
mpt3sas_enable_diag_buffer(ioc, diag_buffer_enable);
+ else if (ioc->manu_pg11.HostTraceBufferMaxSizeKB != 0)
+ mpt3sas_enable_diag_buffer(ioc, 1);
if (disable_discovery > 0)
return;
@@ -10397,6 +10821,10 @@
case MPI26_MFGPAGE_DEVID_HARD_SEC_3916:
case MPI26_MFGPAGE_DEVID_CFG_SEC_3816:
case MPI26_MFGPAGE_DEVID_HARD_SEC_3816:
+ case MPI26_MFGPAGE_DEVID_INVALID0_3916:
+ case MPI26_MFGPAGE_DEVID_INVALID1_3916:
+ case MPI26_MFGPAGE_DEVID_INVALID0_3816:
+ case MPI26_MFGPAGE_DEVID_INVALID1_3816:
return MPI26_VERSION;
}
return 0;
@@ -10486,11 +10914,25 @@
case MPI26_ATLAS_PCIe_SWITCH_DEVID:
ioc->is_gen35_ioc = 1;
break;
+ case MPI26_MFGPAGE_DEVID_INVALID0_3816:
+ case MPI26_MFGPAGE_DEVID_INVALID0_3916:
+ dev_err(&pdev->dev,
+ "HBA with DeviceId 0x%04x, sub VendorId 0x%04x, sub DeviceId 0x%04x is Invalid",
+ pdev->device, pdev->subsystem_vendor,
+ pdev->subsystem_device);
+ return 1;
+ case MPI26_MFGPAGE_DEVID_INVALID1_3816:
+ case MPI26_MFGPAGE_DEVID_INVALID1_3916:
+ dev_err(&pdev->dev,
+ "HBA with DeviceId 0x%04x, sub VendorId 0x%04x, sub DeviceId 0x%04x is Tampered",
+ pdev->device, pdev->subsystem_vendor,
+ pdev->subsystem_device);
+ return 1;
case MPI26_MFGPAGE_DEVID_CFG_SEC_3816:
case MPI26_MFGPAGE_DEVID_CFG_SEC_3916:
dev_info(&pdev->dev,
"HBA is in Configurable Secure mode\n");
- /* fall through */
+ fallthrough;
case MPI26_MFGPAGE_DEVID_HARD_SEC_3816:
case MPI26_MFGPAGE_DEVID_HARD_SEC_3916:
ioc->is_aero_ioc = ioc->is_gen35_ioc = 1;
@@ -10533,6 +10975,8 @@
ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
ioc->logging_level = logging_level;
ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds;
+ /* Host waits for minimum of six seconds */
+ ioc->max_shutdown_latency = IO_UNIT_CONTROL_SHUTDOWN_TIMEOUT;
/*
* Enable MEMORY MOVE support flag.
*/
@@ -10599,8 +11043,8 @@
}
}
/* register EEDP capabilities with SCSI layer */
- if (prot_mask > 0)
- scsi_host_set_prot(shost, prot_mask);
+ if (prot_mask >= 0)
+ scsi_host_set_prot(shost, (prot_mask & 0x07));
else
scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION
| SHOST_DIF_TYPE2_PROTECTION
@@ -10650,6 +11094,7 @@
}
scsi_scan_host(shost);
+ mpt3sas_setup_debugfs(ioc);
return 0;
out_add_shost_fail:
mpt3sas_base_detach(ioc);
@@ -10674,13 +11119,19 @@
static int
scsih_suspend(struct pci_dev *pdev, pm_message_t state)
{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+ struct Scsi_Host *shost;
+ struct MPT3SAS_ADAPTER *ioc;
pci_power_t device_state;
+ int rc;
+
+ rc = _scsih_get_shost_and_ioc(pdev, &shost, &ioc);
+ if (rc)
+ return rc;
mpt3sas_base_stop_watchdog(ioc);
flush_scheduled_work();
scsi_block_requests(shost);
+ _scsih_nvme_shutdown(ioc);
device_state = pci_choose_state(pdev, state);
ioc_info(ioc, "pdev=0x%p, slot=%s, entering operating state [D%d]\n",
pdev, pci_name(pdev), device_state);
@@ -10700,11 +11151,15 @@
static int
scsih_resume(struct pci_dev *pdev)
{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+ struct Scsi_Host *shost;
+ struct MPT3SAS_ADAPTER *ioc;
pci_power_t device_state = pdev->current_state;
int r;
+ r = _scsih_get_shost_and_ioc(pdev, &shost, &ioc);
+ if (r)
+ return r;
+
ioc_info(ioc, "pdev=0x%p, slot=%s, previous operating state [D%d]\n",
pdev, pci_name(pdev), device_state);
@@ -10715,7 +11170,7 @@
r = mpt3sas_base_map_resources(ioc);
if (r)
return r;
-
+ ioc_info(ioc, "Issuing Hard Reset as part of OS Resume\n");
mpt3sas_base_hard_reset_handler(ioc, SOFT_RESET);
scsi_unblock_requests(shost);
mpt3sas_base_start_watchdog(ioc);
@@ -10735,8 +11190,11 @@
static pci_ers_result_t
scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+ struct Scsi_Host *shost;
+ struct MPT3SAS_ADAPTER *ioc;
+
+ if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
+ return PCI_ERS_RESULT_DISCONNECT;
ioc_info(ioc, "PCI error: detected callback, state(%d)!!\n", state);
@@ -10771,10 +11229,13 @@
static pci_ers_result_t
scsih_pci_slot_reset(struct pci_dev *pdev)
{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+ struct Scsi_Host *shost;
+ struct MPT3SAS_ADAPTER *ioc;
int rc;
+ if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
+ return PCI_ERS_RESULT_DISCONNECT;
+
ioc_info(ioc, "PCI error: slot reset callback!!\n");
ioc->pci_error_recovery = 0;
@@ -10784,6 +11245,7 @@
if (rc)
return PCI_ERS_RESULT_DISCONNECT;
+ ioc_info(ioc, "Issuing Hard Reset as part of PCI Slot Reset\n");
rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
ioc_warn(ioc, "hard reset: %s\n",
@@ -10806,8 +11268,11 @@
static void
scsih_pci_resume(struct pci_dev *pdev)
{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+ struct Scsi_Host *shost;
+ struct MPT3SAS_ADAPTER *ioc;
+
+ if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
+ return;
ioc_info(ioc, "PCI error: resume callback!!\n");
@@ -10822,8 +11287,11 @@
static pci_ers_result_t
scsih_pci_mmio_enabled(struct pci_dev *pdev)
{
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+ struct Scsi_Host *shost;
+ struct MPT3SAS_ADAPTER *ioc;
+
+ if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
+ return PCI_ERS_RESULT_DISCONNECT;
ioc_info(ioc, "PCI error: mmio enabled callback!!\n");
@@ -10971,6 +11439,14 @@
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_HARD_SEC_3916,
PCI_ANY_ID, PCI_ANY_ID },
+ /*
+ * Aero SI –> 0x00E0 Invalid, 0x00E3 Tampered
+ */
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_INVALID0_3916,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_INVALID1_3916,
+ PCI_ANY_ID, PCI_ANY_ID },
+
/* Atlas PCIe Switch Management Port */
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_ATLAS_PCIe_SWITCH_DEVID,
PCI_ANY_ID, PCI_ANY_ID },
@@ -10983,6 +11459,14 @@
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_HARD_SEC_3816,
PCI_ANY_ID, PCI_ANY_ID },
+ /*
+ * Sea SI –> 0x00E4 Invalid, 0x00E7 Tampered
+ */
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_INVALID0_3816,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_INVALID1_3816,
+ PCI_ANY_ID, PCI_ANY_ID },
+
{0} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, mpt3sas_pci_table);
@@ -11054,6 +11538,7 @@
tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler(
_scsih_sas_control_complete);
+ mpt3sas_init_debugfs();
return 0;
}
@@ -11085,6 +11570,7 @@
if (hbas_to_enumerate != 2)
raid_class_release(mpt2sas_raid_template);
sas_release_transport(mpt3sas_transport_template);
+ mpt3sas_exit_debugfs();
}
/**
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index 5324662..6ec5b7f 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -719,11 +719,10 @@
sas_device_put(sas_device);
}
- if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
- dev_printk(KERN_INFO, &rphy->dev,
- "add: handle(0x%04x), sas_addr(0x%016llx)\n",
- handle, (unsigned long long)
- mpt3sas_port->remote_identify.sas_address);
+ dev_info(&rphy->dev,
+ "add: handle(0x%04x), sas_addr(0x%016llx)\n", handle,
+ (unsigned long long)mpt3sas_port->remote_identify.sas_address);
+
mpt3sas_port->rphy = rphy;
spin_lock_irqsave(&ioc->sas_node_lock, flags);
list_add_tail(&mpt3sas_port->port_list, &sas_node->sas_port_list);
@@ -813,6 +812,8 @@
}
if (!ioc->remove_host)
sas_port_delete(mpt3sas_port->port);
+ ioc_info(ioc, "%s: removed: sas_addr(0x%016llx)\n",
+ __func__, (unsigned long long)sas_address);
kfree(mpt3sas_port);
}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c
index 6ac453f..8ec9bab 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c
@@ -113,15 +113,21 @@
struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
{
u8 issue_reset = 0;
+ u32 *trig_data = (u32 *)&event_data->u.master;
dTriggerDiagPrintk(ioc, ioc_info(ioc, "%s: enter\n", __func__));
/* release the diag buffer trace */
if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
MPT3_DIAG_BUFFER_IS_RELEASED) == 0) {
- dTriggerDiagPrintk(ioc,
- ioc_info(ioc, "%s: release trace diag buffer\n",
- __func__));
+ /*
+ * add a log message so that user knows which event caused
+ * the release
+ */
+ ioc_info(ioc,
+ "%s: Releasing the trace buffer. Trigger_Type 0x%08x, Data[0] 0x%08x, Data[1] 0x%08x\n",
+ __func__, event_data->trigger_type,
+ trig_data[0], trig_data[1]);
mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE,
&issue_reset);
}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h
index 6586a46..405eada 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_trigger_diag.h
@@ -69,7 +69,7 @@
#define MASTER_TRIGGER_TASK_MANAGMENT (0x00000004)
#define MASTER_TRIGGER_DEVICE_REMOVAL (0x00000008)
-/* fake firmware event for tigger */
+/* fake firmware event for trigger */
#define MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED (0x6E)
/**
diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
index ca96d6d..869b8b0 100644
--- a/drivers/scsi/mvme147.c
+++ b/drivers/scsi/mvme147.c
@@ -8,7 +8,6 @@
#include <linux/module.h>
#include <asm/page.h>
-#include <asm/pgtable.h>
#include <asm/mvme147hw.h>
#include <asm/irq.h>
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
index 52405ce..b03c0f3 100644
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -25,7 +25,7 @@
[chip_1320] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, },
};
-struct device_attribute *mvst_host_attrs[];
+static struct device_attribute *mvst_host_attrs[];
#define SOC_SAS_NUM 2
@@ -33,6 +33,7 @@
.module = THIS_MODULE,
.name = DRV_NAME,
.queuecommand = sas_queuecommand,
+ .dma_need_drain = ata_scsi_dma_need_drain,
.target_alloc = sas_target_alloc,
.slave_configure = sas_slave_configure,
.scan_finished = mvs_scan_finished,
@@ -48,6 +49,9 @@
.slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = sas_ioctl,
+#endif
.shost_attrs = mvst_host_attrs,
.track_queue_depth = 1,
};
@@ -174,15 +178,16 @@
static irqreturn_t mvs_interrupt(int irq, void *opaque)
{
- u32 core_nr;
u32 stat;
struct mvs_info *mvi;
struct sas_ha_struct *sha = opaque;
#ifndef CONFIG_SCSI_MVSAS_TASKLET
u32 i;
-#endif
+ u32 core_nr;
core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
+#endif
+
mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];
if (unlikely(!mvi))
@@ -242,19 +247,16 @@
&mvi->tx_dma, GFP_KERNEL);
if (!mvi->tx)
goto err_out;
- memset(mvi->tx, 0, sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ);
mvi->rx_fis = dma_alloc_coherent(mvi->dev, MVS_RX_FISL_SZ,
&mvi->rx_fis_dma, GFP_KERNEL);
if (!mvi->rx_fis)
goto err_out;
- memset(mvi->rx_fis, 0, MVS_RX_FISL_SZ);
mvi->rx = dma_alloc_coherent(mvi->dev,
sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1),
&mvi->rx_dma, GFP_KERNEL);
if (!mvi->rx)
goto err_out;
- memset(mvi->rx, 0, sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1));
mvi->rx[0] = cpu_to_le32(0xfff);
mvi->rx_cons = 0xfff;
@@ -263,7 +265,6 @@
&mvi->slot_dma, GFP_KERNEL);
if (!mvi->slot)
goto err_out;
- memset(mvi->slot, 0, sizeof(*mvi->slot) * slot_nr);
mvi->bulk_buffer = dma_alloc_coherent(mvi->dev,
TRASH_BUCKET_SIZE,
@@ -296,7 +297,7 @@
int mvs_ioremap(struct mvs_info *mvi, int bar, int bar_ex)
{
- unsigned long res_start, res_len, res_flag, res_flag_ex = 0;
+ unsigned long res_start, res_len, res_flag_ex = 0;
struct pci_dev *pdev = mvi->pdev;
if (bar_ex != -1) {
/*
@@ -324,7 +325,6 @@
goto err_out;
}
- res_flag = pci_resource_flags(pdev, bar);
mvi->regs = ioremap(res_start, res_len);
if (!mvi->regs) {
@@ -757,8 +757,6 @@
mvs_show_interrupt_coalescing,
mvs_store_interrupt_coalescing);
-/* task handler */
-struct task_struct *mvs_th;
static int __init mvs_init(void)
{
int rc;
@@ -783,7 +781,7 @@
sas_release_transport(mvs_stt);
}
-struct device_attribute *mvst_host_attrs[] = {
+static struct device_attribute *mvst_host_attrs[] = {
&dev_attr_driver_version,
&dev_attr_interrupt_coalescing,
NULL,
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index 3e0b8eb..484e014 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -216,11 +216,11 @@
MVS_CHIP_DISP->write_port_cfg_data(mvi, port_id, hi);
}
-static void mvs_bytes_dmaed(struct mvs_info *mvi, int i)
+static void mvs_bytes_dmaed(struct mvs_info *mvi, int i, gfp_t gfp_flags)
{
struct mvs_phy *phy = &mvi->phy[i];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
- struct sas_ha_struct *sas_ha;
+
if (!phy->phy_attached)
return;
@@ -229,8 +229,7 @@
return;
}
- sas_ha = mvi->sas;
- sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE);
+ sas_notify_phy_event_gfp(sas_phy, PHYE_OOB_DONE, gfp_flags);
if (sas_phy->phy) {
struct sas_phy *sphy = sas_phy->phy;
@@ -262,8 +261,7 @@
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
- mvi->sas->notify_port_event(sas_phy,
- PORTE_BYTES_DMAED);
+ sas_notify_port_event_gfp(sas_phy, PORTE_BYTES_DMAED, gfp_flags);
}
void mvs_scan_start(struct Scsi_Host *shost)
@@ -279,7 +277,7 @@
for (j = 0; j < core_nr; j++) {
mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[j];
for (i = 0; i < mvi->chip->n_phy; ++i)
- mvs_bytes_dmaed(mvi, i);
+ mvs_bytes_dmaed(mvi, i, GFP_KERNEL);
}
mvs_prv->scan_finished = 1;
}
@@ -1541,7 +1539,7 @@
int mvs_abort_task_set(struct domain_device *dev, u8 *lun)
{
- int rc = TMF_RESP_FUNC_FAILED;
+ int rc;
struct mvs_tmf_task tmf_task;
tmf_task.tmf = TMF_ABORT_TASK_SET;
@@ -1880,7 +1878,6 @@
struct mvs_info *mvi = mwq->mvi;
unsigned long flags;
u32 phy_no = (unsigned long) mwq->data;
- struct sas_ha_struct *sas_ha = mvi->sas;
struct mvs_phy *phy = &mvi->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
@@ -1895,21 +1892,21 @@
if (!(tmp & PHY_READY_MASK)) {
sas_phy_disconnected(sas_phy);
mvs_phy_disconnected(phy);
- sas_ha->notify_phy_event(sas_phy,
- PHYE_LOSS_OF_SIGNAL);
+ sas_notify_phy_event_gfp(sas_phy,
+ PHYE_LOSS_OF_SIGNAL, GFP_ATOMIC);
mv_dprintk("phy%d Removed Device\n", phy_no);
} else {
MVS_CHIP_DISP->detect_porttype(mvi, phy_no);
mvs_update_phyinfo(mvi, phy_no, 1);
- mvs_bytes_dmaed(mvi, phy_no);
+ mvs_bytes_dmaed(mvi, phy_no, GFP_ATOMIC);
mvs_port_notify_formed(sas_phy, 0);
mv_dprintk("phy%d Attached Device\n", phy_no);
}
}
} else if (mwq->handler & EXP_BRCT_CHG) {
phy->phy_event &= ~EXP_BRCT_CHG;
- sas_ha->notify_port_event(sas_phy,
- PORTE_BROADCAST_RCVD);
+ sas_notify_port_event_gfp(sas_phy,
+ PORTE_BROADCAST_RCVD, GFP_ATOMIC);
mv_dprintk("phy%d Got Broadcast Change\n", phy_no);
}
list_del(&mwq->entry);
@@ -2026,7 +2023,7 @@
mdelay(10);
}
- mvs_bytes_dmaed(mvi, phy_no);
+ mvs_bytes_dmaed(mvi, phy_no, GFP_ATOMIC);
/* whether driver is going to handle hot plug */
if (phy->phy_event & PHY_PLUG_OUT) {
mvs_port_notify_formed(&phy->sas_phy, 0);
diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h
index 519edc7..327fdd5 100644
--- a/drivers/scsi/mvsas/mv_sas.h
+++ b/drivers/scsi/mvsas/mv_sas.h
@@ -394,7 +394,7 @@
dma_addr_t bulk_buffer_dma1;
#define TRASH_BUCKET_SIZE 0x20000
void *dma_pool;
- struct mvs_slot_info slot_info[0];
+ struct mvs_slot_info slot_info[];
};
struct mvs_prv_info{
diff --git a/drivers/scsi/mvumi.h b/drivers/scsi/mvumi.h
index ec8cc22..60d5691 100644
--- a/drivers/scsi/mvumi.h
+++ b/drivers/scsi/mvumi.h
@@ -130,7 +130,7 @@
struct mvumi_hotplug_event {
u16 size;
u8 dummy[2];
- u8 bitmap[0];
+ u8 bitmap[];
};
struct mvumi_driver_event {
@@ -290,7 +290,7 @@
struct mvumi_ob_data {
struct list_head list;
- unsigned char data[0];
+ unsigned char data[];
};
struct version_info {
diff --git a/drivers/scsi/myrb.c b/drivers/scsi/myrb.c
index 539ac8c..5fa0f4e 100644
--- a/drivers/scsi/myrb.c
+++ b/drivers/scsi/myrb.c
@@ -650,7 +650,7 @@
if (sdev && cb->bgi_status.status == MYRB_BGI_INPROGRESS)
sdev_printk(KERN_INFO, sdev,
"Background Initialization Aborted\n");
- /* Fallthrough */
+ fallthrough;
case MYRB_STATUS_NO_BGI_INPROGRESS:
cb->bgi_status.status = MYRB_BGI_INVALID;
break;
@@ -1050,7 +1050,7 @@
enquiry2->fw.turn_id = 0;
}
snprintf(cb->fw_version, sizeof(cb->fw_version),
- "%d.%02d-%c-%02d",
+ "%u.%02u-%c-%02u",
enquiry2->fw.major_version,
enquiry2->fw.minor_version,
enquiry2->fw.firmware_type,
@@ -1528,7 +1528,7 @@
scmd->scsi_done(scmd);
return 0;
}
- /* fall through */
+ fallthrough;
case WRITE_6:
lba = (((scmd->cmnd[1] & 0x1F) << 16) |
(scmd->cmnd[2] << 8) |
@@ -1545,7 +1545,7 @@
scmd->scsi_done(scmd);
return 0;
}
- /* fall through */
+ fallthrough;
case WRITE_10:
case VERIFY: /* 0x2F */
case WRITE_VERIFY: /* 0x2E */
@@ -1562,7 +1562,7 @@
scmd->scsi_done(scmd);
return 0;
}
- /* fall through */
+ fallthrough;
case WRITE_12:
case VERIFY_12: /* 0xAF */
case WRITE_VERIFY_12: /* 0xAE */
@@ -2167,7 +2167,7 @@
struct Scsi_Host *shost = class_to_shost(dev);
struct myrb_hba *cb = shost_priv(shost);
- return snprintf(buf, 20, "%d\n", cb->ctlr_num);
+ return snprintf(buf, 20, "%u\n", cb->ctlr_num);
}
static DEVICE_ATTR_RO(ctlr_num);
@@ -2226,7 +2226,7 @@
NULL,
};
-struct scsi_host_template myrb_template = {
+static struct scsi_host_template myrb_template = {
.module = THIS_MODULE,
.name = "DAC960",
.proc_name = "myrb",
@@ -2315,7 +2315,7 @@
raid_set_state(myrb_raid_template, dev, state);
}
-struct raid_function_template myrb_raid_functions = {
+static struct raid_function_template myrb_raid_functions = {
.cookie = &myrb_template,
.is_raid = myrb_is_raid,
.get_resync = myrb_get_resync,
@@ -2489,7 +2489,7 @@
*
* Return: true for fatal errors and false otherwise.
*/
-bool myrb_err_status(struct myrb_hba *cb, unsigned char error,
+static bool myrb_err_status(struct myrb_hba *cb, unsigned char error,
unsigned char parm0, unsigned char parm1)
{
struct pci_dev *pdev = cb->pdev;
@@ -2732,7 +2732,6 @@
DAC960_LA_disable_intr(base);
DAC960_LA_ack_hw_mbox_status(base);
udelay(1000);
- timeout = 0;
while (DAC960_LA_init_in_progress(base) &&
timeout < MYRB_MAILBOX_TIMEOUT) {
if (DAC960_LA_read_error_status(base, &error,
@@ -3531,7 +3530,7 @@
spin_lock_init(&cb->queue_lock);
if (mmio_size < PAGE_SIZE)
mmio_size = PAGE_SIZE;
- cb->mmio_base = ioremap_nocache(cb->pci_addr & PAGE_MASK, mmio_size);
+ cb->mmio_base = ioremap(cb->pci_addr & PAGE_MASK, mmio_size);
if (cb->mmio_base == NULL) {
dev_err(&pdev->dev,
"Unable to map Controller Register Window\n");
diff --git a/drivers/scsi/myrb.h b/drivers/scsi/myrb.h
index 9289c19..fb8eacf 100644
--- a/drivers/scsi/myrb.h
+++ b/drivers/scsi/myrb.h
@@ -1,5 +1,5 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
* Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers
*
* Copyright 2017 Hannes Reinecke, SUSE Linux GmbH <hare@suse.com>
diff --git a/drivers/scsi/myrs.c b/drivers/scsi/myrs.c
index cfc3f8b..e6a6678 100644
--- a/drivers/scsi/myrs.c
+++ b/drivers/scsi/myrs.c
@@ -87,7 +87,7 @@
return NULL;
}
-/**
+/*
* myrs_reset_cmd - clears critical fields in struct myrs_cmdblk
*/
static inline void myrs_reset_cmd(struct myrs_cmdblk *cmd_blk)
@@ -98,7 +98,7 @@
cmd_blk->status = 0;
}
-/**
+/*
* myrs_qcmd - queues Command for DAC960 V2 Series Controllers.
*/
static void myrs_qcmd(struct myrs_hba *cs, struct myrs_cmdblk *cmd_blk)
@@ -122,7 +122,7 @@
cs->next_cmd_mbox = next_mbox;
}
-/**
+/*
* myrs_exec_cmd - executes V2 Command and waits for completion.
*/
static void myrs_exec_cmd(struct myrs_hba *cs,
@@ -140,7 +140,7 @@
wait_for_completion(&complete);
}
-/**
+/*
* myrs_report_progress - prints progress message
*/
static void myrs_report_progress(struct myrs_hba *cs, unsigned short ldev_num,
@@ -153,7 +153,7 @@
(100 * (int)(blocks >> 7)) / (int)(size >> 7));
}
-/**
+/*
* myrs_get_ctlr_info - executes a Controller Information IOCTL Command
*/
static unsigned char myrs_get_ctlr_info(struct myrs_hba *cs)
@@ -214,7 +214,7 @@
return status;
}
-/**
+/*
* myrs_get_ldev_info - executes a Logical Device Information IOCTL Command
*/
static unsigned char myrs_get_ldev_info(struct myrs_hba *cs,
@@ -301,7 +301,7 @@
return status;
}
-/**
+/*
* myrs_get_pdev_info - executes a "Read Physical Device Information" Command
*/
static unsigned char myrs_get_pdev_info(struct myrs_hba *cs,
@@ -345,7 +345,7 @@
return status;
}
-/**
+/*
* myrs_dev_op - executes a "Device Operation" Command
*/
static unsigned char myrs_dev_op(struct myrs_hba *cs,
@@ -369,7 +369,7 @@
return status;
}
-/**
+/*
* myrs_translate_pdev - translates a Physical Device Channel and
* TargetID into a Logical Device.
*/
@@ -414,7 +414,7 @@
return status;
}
-/**
+/*
* myrs_get_event - executes a Get Event Command
*/
static unsigned char myrs_get_event(struct myrs_hba *cs,
@@ -476,7 +476,7 @@
return status;
}
-/**
+/*
* myrs_enable_mmio_mbox - enables the Memory Mailbox Interface
*/
static bool myrs_enable_mmio_mbox(struct myrs_hba *cs,
@@ -577,7 +577,7 @@
return (status == MYRS_STATUS_SUCCESS);
}
-/**
+/*
* myrs_get_config - reads the Configuration Information
*/
static int myrs_get_config(struct myrs_hba *cs)
@@ -682,7 +682,7 @@
return 0;
}
-/**
+/*
* myrs_log_event - prints a Controller Event message
*/
static struct {
@@ -1529,7 +1529,7 @@
/*
* SCSI midlayer interface
*/
-int myrs_host_reset(struct scsi_cmnd *scmd)
+static int myrs_host_reset(struct scsi_cmnd *scmd)
{
struct Scsi_Host *shost = scmd->device->host;
struct myrs_hba *cs = shost_priv(shost);
@@ -1919,7 +1919,7 @@
kfree(sdev->hostdata);
}
-struct scsi_host_template myrs_template = {
+static struct scsi_host_template myrs_template = {
.module = THIS_MODULE,
.name = "DAC960",
.proc_name = "myrs",
@@ -2033,7 +2033,7 @@
raid_set_state(myrs_raid_template, dev, state);
}
-struct raid_function_template myrs_raid_functions = {
+static struct raid_function_template myrs_raid_functions = {
.cookie = &myrs_template,
.is_raid = myrs_is_raid,
.get_resync = myrs_get_resync,
@@ -2043,7 +2043,7 @@
/*
* PCI interface functions
*/
-void myrs_flush_cache(struct myrs_hba *cs)
+static void myrs_flush_cache(struct myrs_hba *cs)
{
myrs_dev_op(cs, MYRS_IOCTL_FLUSH_DEVICE_DATA, MYRS_RAID_CONTROLLER);
}
@@ -2272,7 +2272,8 @@
myrs_unmap(cs);
if (cs->mmio_base) {
- cs->disable_intr(cs);
+ if (cs->disable_intr)
+ cs->disable_intr(cs);
iounmap(cs->mmio_base);
cs->mmio_base = NULL;
}
@@ -2311,7 +2312,7 @@
/* Map the Controller Register Window. */
if (mmio_size < PAGE_SIZE)
mmio_size = PAGE_SIZE;
- cs->mmio_base = ioremap_nocache(cs->pci_addr & PAGE_MASK, mmio_size);
+ cs->mmio_base = ioremap(cs->pci_addr & PAGE_MASK, mmio_size);
if (cs->mmio_base == NULL) {
dev_err(&pdev->dev,
"Unable to map Controller Register Window\n");
@@ -2338,11 +2339,11 @@
return NULL;
}
-/**
+/*
* myrs_err_status reports Controller BIOS Messages passed through
- the Error Status Register when the driver performs the BIOS handshaking.
- It returns true for fatal errors and false otherwise.
-*/
+ * the Error Status Register when the driver performs the BIOS handshaking.
+ * It returns true for fatal errors and false otherwise.
+ */
static bool myrs_err_status(struct myrs_hba *cs, unsigned char status,
unsigned char parm0, unsigned char parm1)
diff --git a/drivers/scsi/myrs.h b/drivers/scsi/myrs.h
index e6702ee..9f6696d 100644
--- a/drivers/scsi/myrs.h
+++ b/drivers/scsi/myrs.h
@@ -1,5 +1,5 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
* Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers
*
* This driver supports the newer, SCSI-based firmware interface only.
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index e0b427f..03d7013 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -1722,7 +1722,7 @@
** Miscellaneous configuration and status parameters.
**----------------------------------------------------------------
*/
- u_char disc; /* Diconnection allowed */
+ u_char disc; /* Disconnection allowed */
u_char scsi_mode; /* Current SCSI BUS mode */
u_char order; /* Tag order to use */
u_char verbose; /* Verbosity for this controller*/
@@ -2203,7 +2203,7 @@
** Possible data corruption during Memory Write and Invalidate.
** This work-around resets the addressing logic prior to the
** start of the first MOVE of a DATA IN phase.
- ** (See Documentation/scsi/ncr53c8xx.txt for more information)
+ ** (See Documentation/scsi/ncr53c8xx.rst for more information)
*/
SCR_JUMPR ^ IFFALSE (IF (SCR_DATA_IN)),
20,
@@ -3640,7 +3640,7 @@
new = old;
break;
}
- /* fall through */
+ fallthrough;
default:
panic("ncr_script_copy_and_bind: weird relocation %x\n", old);
break;
@@ -3910,14 +3910,14 @@
np->scsi_mode = SMODE_HVD;
break;
}
- /* fall through */
+ fallthrough;
case 3: /* SYMBIOS controllers report HVD through GPIO3 */
if (INB(nc_gpreg) & 0x08)
break;
- /* fall through */
+ fallthrough;
case 2: /* Set HVD unconditionally */
np->scsi_mode = SMODE_HVD;
- /* fall through */
+ fallthrough;
case 1: /* Trust previous settings for HVD */
if (np->sv_stest2 & 0x20)
np->scsi_mode = SMODE_HVD;
@@ -4296,7 +4296,7 @@
break;
cp->phys.header.wgoalp = cpu_to_scr(goalp);
cp->phys.header.wlastp = cpu_to_scr(lastp);
- /* fall through */
+ fallthrough;
case DMA_FROM_DEVICE:
goalp = NCB_SCRIPT_PHYS (np, data_in2) + 8;
if (segments <= MAX_SCATTERL)
@@ -6717,7 +6717,7 @@
OUTL_DSP (scr_to_cpu(tp->lp[0]->jump_ccb[0]));
return;
}
- /* fall through */
+ fallthrough;
case SIR_RESEL_BAD_TARGET: /* Will send a TARGET RESET message */
case SIR_RESEL_BAD_LUN: /* Will send a TARGET RESET message */
case SIR_RESEL_BAD_I_T_L_Q: /* Will send an ABORT TAG message */
@@ -6825,7 +6825,7 @@
*/
OUTB (HS_PRT, HS_BUSY);
- /* fall through */
+ fallthrough;
case SIR_NEGO_PROTO:
/*-------------------------------------------------------
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index 70db792..da814c2 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -1247,7 +1247,7 @@
* ---> AutoSCSI with MSGOUTreg is processed.
*/
data->msgout_len = 0;
- };
+ }
nsp32_dbg(NSP32_DEBUG_INTR, "MsgOut phase processed");
}
@@ -1542,7 +1542,7 @@
* with ACK reply when below condition is matched:
* MsgIn 00: Command Complete.
* MsgIn 02: Save Data Pointer.
- * MsgIn 04: Diconnect.
+ * MsgIn 04: Disconnect.
* In other case, unexpected BUSFREE is detected.
*/
static int nsp32_busfree_occur(struct scsi_cmnd *SCpnt, unsigned short execph)
@@ -1839,7 +1839,7 @@
nsp32_dbg(NSP32_DEBUG_MSGOUTOCCUR, "bus: 0x%x\n",
nsp32_read1(base, SCSI_BUS_MONITOR));
- };
+ }
data->msgout_len = 0;
diff --git a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig
index 2368f34..9696b6b 100644
--- a/drivers/scsi/pcmcia/Kconfig
+++ b/drivers/scsi/pcmcia/Kconfig
@@ -32,11 +32,11 @@
config PCMCIA_NINJA_SCSI
tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support"
- depends on !64BIT
+ depends on !64BIT || COMPILE_TEST
help
If you intend to attach this type of PCMCIA SCSI host adapter to
your computer, say Y here and read
- <file:Documentation/scsi/NinjaSCSI.txt>.
+ <file:Documentation/scsi/NinjaSCSI.rst>.
Supported cards:
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 97416e1..bc5a623 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -56,9 +56,7 @@
MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>");
MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module");
MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
-#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
-#endif
#include "nsp_io.h"
@@ -136,6 +134,7 @@
scsi_set_resid(SCpnt, scsi_get_resid(SCpnt) + residInc);
}
+__printf(4, 5)
static void nsp_cs_message(const char *func, int line, char *type, char *fmt, ...)
{
va_list args;
@@ -691,14 +690,14 @@
{
unsigned int base = SCpnt->device->host->io_port;
unsigned int count;
- unsigned int l, m, h, dummy;
+ unsigned int l, m, h;
nsp_index_write(base, POINTERCLR, POINTER_CLEAR | ACK_COUNTER);
l = nsp_index_read(base, TRANSFERCOUNT);
m = nsp_index_read(base, TRANSFERCOUNT);
h = nsp_index_read(base, TRANSFERCOUNT);
- dummy = nsp_index_read(base, TRANSFERCOUNT); /* required this! */
+ nsp_index_read(base, TRANSFERCOUNT); /* required this! */
count = (h << 16) | (m << 8) | (l << 0);
@@ -1114,7 +1113,7 @@
nsp_scsi_done(tmpSC);
return IRQ_HANDLED;
}
- /* fall thru */
+ fallthrough;
default:
if ((irq_status & (IRQSTATUS_SCSI | IRQSTATUS_FIFO)) == 0) {
return IRQ_HANDLED;
@@ -1562,7 +1561,7 @@
goto next_entry;
data->MmioAddress = (unsigned long)
- ioremap_nocache(p_dev->resource[2]->start,
+ ioremap(p_dev->resource[2]->start,
resource_size(p_dev->resource[2]));
data->MmioLength = resource_size(p_dev->resource[2]);
}
diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 6b85016..12035ba 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -47,6 +47,7 @@
/**
* pm8001_ctl_mpi_interface_rev_show - MPI interface revision number
* @cdev: pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
*
* A sysfs 'read-only' shost attribute.
@@ -70,8 +71,29 @@
DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL);
/**
+ * controller_fatal_error_show - check controller is under fatal err
+ * @cdev: pointer to embedded class device
+ * @attr: device attribute (unused)
+ * @buf: the buffer returned
+ *
+ * A sysfs 'read only' shost attribute.
+ */
+static ssize_t controller_fatal_error_show(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+ struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ pm8001_ha->controller_fatal_error);
+}
+static DEVICE_ATTR_RO(controller_fatal_error);
+
+/**
* pm8001_ctl_fw_version_show - firmware version
* @cdev: pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
*
* A sysfs 'read-only' shost attribute.
@@ -102,6 +124,7 @@
/**
* pm8001_ctl_ila_version_show - ila version
* @cdev: pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
*
* A sysfs 'read-only' shost attribute.
@@ -127,6 +150,7 @@
/**
* pm8001_ctl_inactive_fw_version_show - Inacative firmware version number
* @cdev: pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
*
* A sysfs 'read-only' shost attribute.
@@ -153,6 +177,7 @@
/**
* pm8001_ctl_max_out_io_show - max outstanding io supported
* @cdev: pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
*
* A sysfs 'read-only' shost attribute.
@@ -176,6 +201,7 @@
/**
* pm8001_ctl_max_devices_show - max devices support
* @cdev: pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
*
* A sysfs 'read-only' shost attribute.
@@ -202,6 +228,7 @@
* pm8001_ctl_max_sg_list_show - max sg list supported iff not 0.0 for no
* hardware limitation
* @cdev: pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
*
* A sysfs 'read-only' shost attribute.
@@ -246,6 +273,7 @@
/**
* pm8001_ctl_sas_spec_support_show - sas spec supported
* @cdev: pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
*
* A sysfs 'read-only' shost attribute.
@@ -273,6 +301,7 @@
/**
* pm8001_ctl_sas_address_show - sas address
* @cdev: pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
*
* This is the controller sas address
@@ -294,6 +323,7 @@
/**
* pm8001_ctl_logging_level_show - logging level
* @cdev: pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
*
* A sysfs 'read/write' shost attribute.
@@ -307,6 +337,7 @@
return snprintf(buf, PAGE_SIZE, "%08xh\n", pm8001_ha->logging_level);
}
+
static ssize_t pm8001_ctl_logging_level_store(struct device *cdev,
struct device_attribute *attr, const char *buf, size_t count)
{
@@ -327,6 +358,7 @@
/**
* pm8001_ctl_aap_log_show - aap1 event log
* @cdev: pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
*
* A sysfs 'read-only' shost attribute.
@@ -363,6 +395,7 @@
/**
* pm8001_ctl_ib_queue_log_show - Out bound Queue log
* @cdev:pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
* A sysfs 'read-only' shost attribute.
*/
@@ -375,9 +408,10 @@
int offset;
char *str = buf;
int start = 0;
+ u32 ib_offset = pm8001_ha->ib_offset;
#define IB_MEMMAP(c) \
(*(u32 *)((u8 *)pm8001_ha-> \
- memoryMap.region[IB].virt_ptr + \
+ memoryMap.region[ib_offset].virt_ptr + \
pm8001_ha->evtlog_ib_offset + (c)))
for (offset = 0; offset < IB_OB_READ_TIMES; offset++) {
@@ -395,6 +429,7 @@
/**
* pm8001_ctl_ob_queue_log_show - Out bound Queue log
* @cdev:pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
* A sysfs 'read-only' shost attribute.
*/
@@ -408,9 +443,10 @@
int offset;
char *str = buf;
int start = 0;
+ u32 ob_offset = pm8001_ha->ob_offset;
#define OB_MEMMAP(c) \
(*(u32 *)((u8 *)pm8001_ha-> \
- memoryMap.region[OB].virt_ptr + \
+ memoryMap.region[ob_offset].virt_ptr + \
pm8001_ha->evtlog_ob_offset + (c)))
for (offset = 0; offset < IB_OB_READ_TIMES; offset++) {
@@ -427,6 +463,7 @@
/**
* pm8001_ctl_bios_version_show - Bios version Display
* @cdev:pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf:the buffer returned
* A sysfs 'read-only' shost attribute.
*/
@@ -444,7 +481,7 @@
pm8001_ha->nvmd_completion = &completion;
payload.minor_function = 7;
payload.offset = 0;
- payload.length = 4096;
+ payload.rd_length = 4096;
payload.func_specific = kzalloc(4096, GFP_KERNEL);
if (!payload.func_specific)
return -ENOMEM;
@@ -464,6 +501,7 @@
/**
* event_log_size_show - event log size
* @cdev: pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
*
* A sysfs read shost attribute.
@@ -482,6 +520,7 @@
/**
* pm8001_ctl_aap_log_show - IOP event log
* @cdev: pointer to embedded class device
+ * @attr: device attribute (unused)
* @buf: the buffer returned
*
* A sysfs 'read-only' shost attribute.
@@ -519,6 +558,7 @@
/**
** pm8001_ctl_fatal_log_show - fatal error logging
** @cdev:pointer to embedded class device
+ ** @attr: device attribute
** @buf: the buffer returned
**
** A sysfs 'read-only' shost attribute.
@@ -535,12 +575,57 @@
static DEVICE_ATTR(fatal_log, S_IRUGO, pm8001_ctl_fatal_log_show, NULL);
+/**
+ ** non_fatal_log_show - non fatal error logging
+ ** @cdev:pointer to embedded class device
+ ** @attr: device attribute
+ ** @buf: the buffer returned
+ **
+ ** A sysfs 'read-only' shost attribute.
+ **/
+static ssize_t non_fatal_log_show(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+{
+ u32 count;
+
+ count = pm80xx_get_non_fatal_dump(cdev, attr, buf);
+ return count;
+}
+static DEVICE_ATTR_RO(non_fatal_log);
+
+static ssize_t non_fatal_count_show(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+ struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+
+ return snprintf(buf, PAGE_SIZE, "%08x",
+ pm8001_ha->non_fatal_count);
+}
+
+static ssize_t non_fatal_count_store(struct device *cdev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+ struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+ int val = 0;
+
+ if (kstrtoint(buf, 16, &val) != 0)
+ return -EINVAL;
+
+ pm8001_ha->non_fatal_count = val;
+ return strlen(buf);
+}
+static DEVICE_ATTR_RW(non_fatal_count);
/**
** pm8001_ctl_gsm_log_show - gsm dump collection
** @cdev:pointer to embedded class device
+ ** @attr: device attribute (unused)
** @buf: the buffer returned
- **A sysfs 'read-only' shost attribute.
+ ** A sysfs 'read-only' shost attribute.
**/
static ssize_t pm8001_ctl_gsm_log_show(struct device *cdev,
struct device_attribute *attr, char *buf)
@@ -612,7 +697,7 @@
payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
pm8001_ha->fw_image->size);
- payload->length = pm8001_ha->fw_image->size;
+ payload->wr_length = pm8001_ha->fw_image->size;
payload->id = 0;
payload->minor_function = 0x1;
pm8001_ha->nvmd_completion = &completion;
@@ -658,7 +743,7 @@
IOCTL_BUF_SIZE);
for (loopNumber = 0; loopNumber < loopcount; loopNumber++) {
payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
- payload->length = 1024*16;
+ payload->wr_length = 1024*16;
payload->id = 0;
fwControl =
(struct fw_control_info *)&payload->func_specific;
@@ -756,10 +841,9 @@
pm8001_ha->dev);
if (ret) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk(
- "Failed to load firmware image file %s, error %d\n",
- filename_ptr, ret));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "Failed to load firmware image file %s, error %d\n",
+ filename_ptr, ret);
pm8001_ha->fw_status = FAIL_OPEN_BIOS_FILE;
goto out;
}
@@ -804,11 +888,14 @@
pm8001_show_update_fw, pm8001_store_update_fw);
struct device_attribute *pm8001_host_attrs[] = {
&dev_attr_interface_rev,
+ &dev_attr_controller_fatal_error,
&dev_attr_fw_version,
&dev_attr_update_fw,
&dev_attr_aap_log,
&dev_attr_iop_log,
&dev_attr_fatal_log,
+ &dev_attr_non_fatal_log,
+ &dev_attr_non_fatal_count,
&dev_attr_gsm_log,
&dev_attr_max_out_io,
&dev_attr_max_devices,
diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h
index 48e0624..501b574 100644
--- a/drivers/scsi/pm8001/pm8001_defs.h
+++ b/drivers/scsi/pm8001/pm8001_defs.h
@@ -75,12 +75,10 @@
};
/* driver compile-time configuration */
-#define PM8001_MAX_CCB 512 /* max ccbs supported */
+#define PM8001_MAX_CCB 1024 /* max ccbs supported */
#define PM8001_MPI_QUEUE 1024 /* maximum mpi queue entries */
-#define PM8001_MAX_INB_NUM 1
-#define PM8001_MAX_OUTB_NUM 1
-#define PM8001_MAX_SPCV_INB_NUM 1
-#define PM8001_MAX_SPCV_OUTB_NUM 4
+#define PM8001_MAX_INB_NUM 64
+#define PM8001_MAX_OUTB_NUM 64
#define PM8001_CAN_QUEUE 508 /* SCSI Queue depth */
/* Inbound/Outbound queue size */
@@ -92,25 +90,27 @@
#define PM8001_MAX_PORTS 16 /* max. possible ports */
#define PM8001_MAX_DEVICES 2048 /* max supported device */
#define PM8001_MAX_MSIX_VEC 64 /* max msi-x int for spcv/ve */
+#define PM8001_RESERVE_SLOT 8
-#define USI_MAX_MEMCNT_BASE 5
-#define IB (USI_MAX_MEMCNT_BASE + 1)
-#define CI (IB + PM8001_MAX_SPCV_INB_NUM)
-#define OB (CI + PM8001_MAX_SPCV_INB_NUM)
-#define PI (OB + PM8001_MAX_SPCV_OUTB_NUM)
-#define USI_MAX_MEMCNT (PI + PM8001_MAX_SPCV_OUTB_NUM)
-#define PM8001_MAX_DMA_SG SG_ALL
+#define CONFIG_SCSI_PM8001_MAX_DMA_SG 528
+#define PM8001_MAX_DMA_SG CONFIG_SCSI_PM8001_MAX_DMA_SG
+
enum memory_region_num {
AAP1 = 0x0, /* application acceleration processor */
IOP, /* IO processor */
NVMD, /* NVM device */
- DEV_MEM, /* memory for devices */
- CCB_MEM, /* memory for command control block */
FW_FLASH, /* memory for fw flash update */
- FORENSIC_MEM /* memory for fw forensic data */
+ FORENSIC_MEM, /* memory for fw forensic data */
+ USI_MAX_MEMCNT_BASE
};
#define PM8001_EVENT_LOG_SIZE (128 * 1024)
+/**
+ * maximum DMA memory regions(number of IBQ + number of IBQ CI
+ * + number of OBQ + number of OBQ PI)
+ */
+#define USI_MAX_MEMCNT (USI_MAX_MEMCNT_BASE + ((2 * PM8001_MAX_INB_NUM) \
+ + (2 * PM8001_MAX_OUTB_NUM)))
/*error code*/
enum mpi_err {
MPI_IO_STATUS_SUCCESS = 0x0,
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 68a8217..9b31895 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -189,6 +189,10 @@
u32 offsetib, offsetob;
void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr;
void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr;
+ u32 ib_offset = pm8001_ha->ib_offset;
+ u32 ob_offset = pm8001_ha->ob_offset;
+ u32 ci_offset = pm8001_ha->ci_offset;
+ u32 pi_offset = pm8001_ha->pi_offset;
pm8001_ha->main_cfg_tbl.pm8001_tbl.inbound_q_nppd_hppd = 0;
pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid0_3 = 0;
@@ -219,23 +223,23 @@
PM8001_EVENT_LOG_SIZE;
pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_option = 0x01;
pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_interrupt = 0x01;
- for (i = 0; i < PM8001_MAX_INB_NUM; i++) {
+ for (i = 0; i < pm8001_ha->max_q_num; i++) {
pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt =
PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30);
pm8001_ha->inbnd_q_tbl[i].upper_base_addr =
- pm8001_ha->memoryMap.region[IB + i].phys_addr_hi;
+ pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_hi;
pm8001_ha->inbnd_q_tbl[i].lower_base_addr =
- pm8001_ha->memoryMap.region[IB + i].phys_addr_lo;
+ pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_lo;
pm8001_ha->inbnd_q_tbl[i].base_virt =
- (u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr;
+ (u8 *)pm8001_ha->memoryMap.region[ib_offset + i].virt_ptr;
pm8001_ha->inbnd_q_tbl[i].total_length =
- pm8001_ha->memoryMap.region[IB + i].total_len;
+ pm8001_ha->memoryMap.region[ib_offset + i].total_len;
pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr =
- pm8001_ha->memoryMap.region[CI + i].phys_addr_hi;
+ pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_hi;
pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr =
- pm8001_ha->memoryMap.region[CI + i].phys_addr_lo;
+ pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_lo;
pm8001_ha->inbnd_q_tbl[i].ci_virt =
- pm8001_ha->memoryMap.region[CI + i].virt_ptr;
+ pm8001_ha->memoryMap.region[ci_offset + i].virt_ptr;
offsetib = i * 0x20;
pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =
get_pci_bar_index(pm8001_mr32(addressib,
@@ -245,25 +249,25 @@
pm8001_ha->inbnd_q_tbl[i].producer_idx = 0;
pm8001_ha->inbnd_q_tbl[i].consumer_index = 0;
}
- for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) {
+ for (i = 0; i < pm8001_ha->max_q_num; i++) {
pm8001_ha->outbnd_q_tbl[i].element_size_cnt =
PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30);
pm8001_ha->outbnd_q_tbl[i].upper_base_addr =
- pm8001_ha->memoryMap.region[OB + i].phys_addr_hi;
+ pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_hi;
pm8001_ha->outbnd_q_tbl[i].lower_base_addr =
- pm8001_ha->memoryMap.region[OB + i].phys_addr_lo;
+ pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_lo;
pm8001_ha->outbnd_q_tbl[i].base_virt =
- (u8 *)pm8001_ha->memoryMap.region[OB + i].virt_ptr;
+ (u8 *)pm8001_ha->memoryMap.region[ob_offset + i].virt_ptr;
pm8001_ha->outbnd_q_tbl[i].total_length =
- pm8001_ha->memoryMap.region[OB + i].total_len;
+ pm8001_ha->memoryMap.region[ob_offset + i].total_len;
pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr =
- pm8001_ha->memoryMap.region[PI + i].phys_addr_hi;
+ pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_hi;
pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr =
- pm8001_ha->memoryMap.region[PI + i].phys_addr_lo;
+ pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_lo;
pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay =
0 | (10 << 16) | (i << 24);
pm8001_ha->outbnd_q_tbl[i].pi_virt =
- pm8001_ha->memoryMap.region[PI + i].virt_ptr;
+ pm8001_ha->memoryMap.region[pi_offset + i].virt_ptr;
offsetob = i * 0x24;
pm8001_ha->outbnd_q_tbl[i].ci_pci_bar =
get_pci_bar_index(pm8001_mr32(addressob,
@@ -333,6 +337,7 @@
/**
* update_inbnd_queue_table - update the inbound queue table to the HBA.
* @pm8001_ha: our hba card information
+ * @number: entry in the queue
*/
static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
int number)
@@ -354,6 +359,7 @@
/**
* update_outbnd_queue_table - update the outbound queue table to the HBA.
* @pm8001_ha: our hba card information
+ * @number: entry in the queue
*/
static void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
int number)
@@ -394,9 +400,9 @@
} while ((regVal != shiftValue) && time_before(jiffies, start));
if (regVal != shiftValue) {
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("TIMEOUT:SPC_IBW_AXI_TRANSLATION_LOW"
- " = 0x%x\n", regVal));
+ pm8001_dbg(pm8001_ha, INIT,
+ "TIMEOUT:SPC_IBW_AXI_TRANSLATION_LOW = 0x%x\n",
+ regVal);
return -1;
}
return 0;
@@ -473,7 +479,7 @@
/**
* mpi_set_open_retry_interval_reg
* @pm8001_ha: our hba card information
- * @interval - interval time for each OPEN_REJECT (RETRY). The units are in 1us.
+ * @interval: interval time for each OPEN_REJECT (RETRY). The units are in 1us.
*/
static void mpi_set_open_retry_interval_reg(struct pm8001_hba_info *pm8001_ha,
u32 interval)
@@ -617,12 +623,10 @@
value = pm8001_cr32(pm8001_ha, 0, 0x44);
offset = value & 0x03FFFFFF;
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Scratchpad 0 Offset: %x\n", offset));
+ pm8001_dbg(pm8001_ha, INIT, "Scratchpad 0 Offset: %x\n", offset);
pcilogic = (value & 0xFC000000) >> 26;
pcibar = get_pci_bar_index(pcilogic);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Scratchpad 0 PCI BAR: %d\n", pcibar));
+ pm8001_dbg(pm8001_ha, INIT, "Scratchpad 0 PCI BAR: %d\n", pcibar);
pm8001_ha->main_cfg_tbl_addr = base_addr =
pm8001_ha->io_mem[pcibar].memvirtaddr + offset;
pm8001_ha->general_stat_tbl_addr =
@@ -639,23 +643,22 @@
*/
static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha)
{
- u8 i = 0;
+ u32 i = 0;
u16 deviceid;
pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
/* 8081 controllers need BAR shift to access MPI space
* as this is shared with BIOS data */
if (deviceid == 0x8081 || deviceid == 0x0042) {
if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_SM_BASE)) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Shift Bar4 to 0x%x failed\n",
- GSM_SM_BASE));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "Shift Bar4 to 0x%x failed\n",
+ GSM_SM_BASE);
return -1;
}
}
/* check the firmware status */
if (-1 == check_fw_ready(pm8001_ha)) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Firmware is not ready!\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "Firmware is not ready!\n");
return -EBUSY;
}
@@ -668,9 +671,9 @@
read_outbnd_queue_table(pm8001_ha);
/* update main config table ,inbound table and outbound table */
update_main_config_table(pm8001_ha);
- for (i = 0; i < PM8001_MAX_INB_NUM; i++)
+ for (i = 0; i < pm8001_ha->max_q_num; i++)
update_inbnd_queue_table(pm8001_ha, i);
- for (i = 0; i < PM8001_MAX_OUTB_NUM; i++)
+ for (i = 0; i < pm8001_ha->max_q_num; i++)
update_outbnd_queue_table(pm8001_ha, i);
/* 8081 controller donot require these operations */
if (deviceid != 0x8081 && deviceid != 0x0042) {
@@ -680,8 +683,7 @@
}
/* notify firmware update finished and check initialization status */
if (0 == mpi_init_check(pm8001_ha)) {
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("MPI initialize successful!\n"));
+ pm8001_dbg(pm8001_ha, INIT, "MPI initialize successful!\n");
} else
return -EBUSY;
/*This register is a 16-bit timer with a resolution of 1us. This is the
@@ -703,9 +705,9 @@
pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid);
if (deviceid == 0x8081 || deviceid == 0x0042) {
if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_SM_BASE)) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Shift Bar4 to 0x%x failed\n",
- GSM_SM_BASE));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "Shift Bar4 to 0x%x failed\n",
+ GSM_SM_BASE);
return -1;
}
}
@@ -723,8 +725,8 @@
} while ((value != 0) && (--max_wait_count));
if (!max_wait_count) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("TIMEOUT:IBDB value/=0x%x\n", value));
+ pm8001_dbg(pm8001_ha, FAIL, "TIMEOUT:IBDB value/=0x%x\n",
+ value);
return -1;
}
@@ -741,9 +743,8 @@
break;
} while (--max_wait_count);
if (!max_wait_count) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk(" TIME OUT MPI State = 0x%x\n",
- gst_len_mpistate & GST_MPI_STATE_MASK));
+ pm8001_dbg(pm8001_ha, FAIL, " TIME OUT MPI State = 0x%x\n",
+ gst_len_mpistate & GST_MPI_STATE_MASK);
return -1;
}
return 0;
@@ -757,25 +758,23 @@
{
u32 regVal, regVal1, regVal2;
if (mpi_uninit_check(pm8001_ha) != 0) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("MPI state is not ready\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "MPI state is not ready\n");
return -1;
}
/* read the scratch pad 2 register bit 2 */
regVal = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2)
& SCRATCH_PAD2_FWRDY_RST;
if (regVal == SCRATCH_PAD2_FWRDY_RST) {
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Firmware is ready for reset .\n"));
+ pm8001_dbg(pm8001_ha, INIT, "Firmware is ready for reset.\n");
} else {
unsigned long flags;
/* Trigger NMI twice via RB6 */
spin_lock_irqsave(&pm8001_ha->lock, flags);
if (-1 == pm8001_bar4_shift(pm8001_ha, RB6_ACCESS_REG)) {
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Shift Bar4 to 0x%x failed\n",
- RB6_ACCESS_REG));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "Shift Bar4 to 0x%x failed\n",
+ RB6_ACCESS_REG);
return -1;
}
pm8001_cw32(pm8001_ha, 2, SPC_RB6_OFFSET,
@@ -788,16 +787,14 @@
if (regVal != SCRATCH_PAD2_FWRDY_RST) {
regVal1 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
regVal2 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("TIMEOUT:MSGU_SCRATCH_PAD1"
- "=0x%x, MSGU_SCRATCH_PAD2=0x%x\n",
- regVal1, regVal2));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SCRATCH_PAD0 value = 0x%x\n",
- pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0)));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SCRATCH_PAD3 value = 0x%x\n",
- pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3)));
+ pm8001_dbg(pm8001_ha, FAIL, "TIMEOUT:MSGU_SCRATCH_PAD1=0x%x, MSGU_SCRATCH_PAD2=0x%x\n",
+ regVal1, regVal2);
+ pm8001_dbg(pm8001_ha, FAIL,
+ "SCRATCH_PAD0 value = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "SCRATCH_PAD3 value = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3));
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
return -1;
}
@@ -822,7 +819,7 @@
/* step1: Check FW is ready for soft reset */
if (soft_reset_ready_check(pm8001_ha) != 0) {
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("FW is not ready\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "FW is not ready\n");
return -1;
}
@@ -832,46 +829,43 @@
spin_lock_irqsave(&pm8001_ha->lock, flags);
if (-1 == pm8001_bar4_shift(pm8001_ha, MBIC_AAP1_ADDR_BASE)) {
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Shift Bar4 to 0x%x failed\n",
- MBIC_AAP1_ADDR_BASE));
+ pm8001_dbg(pm8001_ha, FAIL, "Shift Bar4 to 0x%x failed\n",
+ MBIC_AAP1_ADDR_BASE);
return -1;
}
regVal = pm8001_cr32(pm8001_ha, 2, MBIC_NMI_ENABLE_VPE0_IOP);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("MBIC - NMI Enable VPE0 (IOP)= 0x%x\n", regVal));
+ pm8001_dbg(pm8001_ha, INIT, "MBIC - NMI Enable VPE0 (IOP)= 0x%x\n",
+ regVal);
pm8001_cw32(pm8001_ha, 2, MBIC_NMI_ENABLE_VPE0_IOP, 0x0);
/* map 0x70000 to BAR4(0x20), BAR2(win) */
if (-1 == pm8001_bar4_shift(pm8001_ha, MBIC_IOP_ADDR_BASE)) {
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Shift Bar4 to 0x%x failed\n",
- MBIC_IOP_ADDR_BASE));
+ pm8001_dbg(pm8001_ha, FAIL, "Shift Bar4 to 0x%x failed\n",
+ MBIC_IOP_ADDR_BASE);
return -1;
}
regVal = pm8001_cr32(pm8001_ha, 2, MBIC_NMI_ENABLE_VPE0_AAP1);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("MBIC - NMI Enable VPE0 (AAP1)= 0x%x\n", regVal));
+ pm8001_dbg(pm8001_ha, INIT, "MBIC - NMI Enable VPE0 (AAP1)= 0x%x\n",
+ regVal);
pm8001_cw32(pm8001_ha, 2, MBIC_NMI_ENABLE_VPE0_AAP1, 0x0);
regVal = pm8001_cr32(pm8001_ha, 1, PCIE_EVENT_INTERRUPT_ENABLE);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("PCIE -Event Interrupt Enable = 0x%x\n", regVal));
+ pm8001_dbg(pm8001_ha, INIT, "PCIE -Event Interrupt Enable = 0x%x\n",
+ regVal);
pm8001_cw32(pm8001_ha, 1, PCIE_EVENT_INTERRUPT_ENABLE, 0x0);
regVal = pm8001_cr32(pm8001_ha, 1, PCIE_EVENT_INTERRUPT);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("PCIE - Event Interrupt = 0x%x\n", regVal));
+ pm8001_dbg(pm8001_ha, INIT, "PCIE - Event Interrupt = 0x%x\n",
+ regVal);
pm8001_cw32(pm8001_ha, 1, PCIE_EVENT_INTERRUPT, regVal);
regVal = pm8001_cr32(pm8001_ha, 1, PCIE_ERROR_INTERRUPT_ENABLE);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("PCIE -Error Interrupt Enable = 0x%x\n", regVal));
+ pm8001_dbg(pm8001_ha, INIT, "PCIE -Error Interrupt Enable = 0x%x\n",
+ regVal);
pm8001_cw32(pm8001_ha, 1, PCIE_ERROR_INTERRUPT_ENABLE, 0x0);
regVal = pm8001_cr32(pm8001_ha, 1, PCIE_ERROR_INTERRUPT);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("PCIE - Error Interrupt = 0x%x\n", regVal));
+ pm8001_dbg(pm8001_ha, INIT, "PCIE - Error Interrupt = 0x%x\n", regVal);
pm8001_cw32(pm8001_ha, 1, PCIE_ERROR_INTERRUPT, regVal);
/* read the scratch pad 1 register bit 2 */
@@ -887,15 +881,13 @@
/* map 0x0700000 to BAR4(0x20), BAR2(win) */
if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_ADDR_BASE)) {
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Shift Bar4 to 0x%x failed\n",
- GSM_ADDR_BASE));
+ pm8001_dbg(pm8001_ha, FAIL, "Shift Bar4 to 0x%x failed\n",
+ GSM_ADDR_BASE);
return -1;
}
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GSM 0x0(0x00007b88)-GSM Configuration and"
- " Reset = 0x%x\n",
- pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET)));
+ pm8001_dbg(pm8001_ha, INIT,
+ "GSM 0x0(0x00007b88)-GSM Configuration and Reset = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET));
/* step 3: host read GSM Configuration and Reset register */
regVal = pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET);
@@ -910,59 +902,52 @@
regVal &= ~(0x00003b00);
/* host write GSM Configuration and Reset register */
pm8001_cw32(pm8001_ha, 2, GSM_CONFIG_RESET, regVal);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GSM 0x0 (0x00007b88 ==> 0x00004088) - GSM "
- "Configuration and Reset is set to = 0x%x\n",
- pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET)));
+ pm8001_dbg(pm8001_ha, INIT,
+ "GSM 0x0 (0x00007b88 ==> 0x00004088) - GSM Configuration and Reset is set to = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET));
/* step 4: */
/* disable GSM - Read Address Parity Check */
regVal1 = pm8001_cr32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GSM 0x700038 - Read Address Parity Check "
- "Enable = 0x%x\n", regVal1));
+ pm8001_dbg(pm8001_ha, INIT,
+ "GSM 0x700038 - Read Address Parity Check Enable = 0x%x\n",
+ regVal1);
pm8001_cw32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK, 0x0);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GSM 0x700038 - Read Address Parity Check Enable"
- "is set to = 0x%x\n",
- pm8001_cr32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK)));
+ pm8001_dbg(pm8001_ha, INIT,
+ "GSM 0x700038 - Read Address Parity Check Enable is set to = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK));
/* disable GSM - Write Address Parity Check */
regVal2 = pm8001_cr32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GSM 0x700040 - Write Address Parity Check"
- " Enable = 0x%x\n", regVal2));
+ pm8001_dbg(pm8001_ha, INIT,
+ "GSM 0x700040 - Write Address Parity Check Enable = 0x%x\n",
+ regVal2);
pm8001_cw32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK, 0x0);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GSM 0x700040 - Write Address Parity Check "
- "Enable is set to = 0x%x\n",
- pm8001_cr32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK)));
+ pm8001_dbg(pm8001_ha, INIT,
+ "GSM 0x700040 - Write Address Parity Check Enable is set to = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK));
/* disable GSM - Write Data Parity Check */
regVal3 = pm8001_cr32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GSM 0x300048 - Write Data Parity Check"
- " Enable = 0x%x\n", regVal3));
+ pm8001_dbg(pm8001_ha, INIT, "GSM 0x300048 - Write Data Parity Check Enable = 0x%x\n",
+ regVal3);
pm8001_cw32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK, 0x0);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GSM 0x300048 - Write Data Parity Check Enable"
- "is set to = 0x%x\n",
- pm8001_cr32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK)));
+ pm8001_dbg(pm8001_ha, INIT,
+ "GSM 0x300048 - Write Data Parity Check Enable is set to = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK));
/* step 5: delay 10 usec */
udelay(10);
/* step 5-b: set GPIO-0 output control to tristate anyway */
if (-1 == pm8001_bar4_shift(pm8001_ha, GPIO_ADDR_BASE)) {
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Shift Bar4 to 0x%x failed\n",
- GPIO_ADDR_BASE));
+ pm8001_dbg(pm8001_ha, INIT, "Shift Bar4 to 0x%x failed\n",
+ GPIO_ADDR_BASE);
return -1;
}
regVal = pm8001_cr32(pm8001_ha, 2, GPIO_GPIO_0_0UTPUT_CTL_OFFSET);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GPIO Output Control Register:"
- " = 0x%x\n", regVal));
+ pm8001_dbg(pm8001_ha, INIT, "GPIO Output Control Register: = 0x%x\n",
+ regVal);
/* set GPIO-0 output control to tri-state */
regVal &= 0xFFFFFFFC;
pm8001_cw32(pm8001_ha, 2, GPIO_GPIO_0_0UTPUT_CTL_OFFSET, regVal);
@@ -971,23 +956,20 @@
/* map 0x00000 to BAR4(0x20), BAR2(win) */
if (-1 == pm8001_bar4_shift(pm8001_ha, SPC_TOP_LEVEL_ADDR_BASE)) {
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SPC Shift Bar4 to 0x%x failed\n",
- SPC_TOP_LEVEL_ADDR_BASE));
+ pm8001_dbg(pm8001_ha, FAIL, "SPC Shift Bar4 to 0x%x failed\n",
+ SPC_TOP_LEVEL_ADDR_BASE);
return -1;
}
regVal = pm8001_cr32(pm8001_ha, 2, SPC_REG_RESET);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Top Register before resetting IOP/AAP1"
- ":= 0x%x\n", regVal));
+ pm8001_dbg(pm8001_ha, INIT, "Top Register before resetting IOP/AAP1:= 0x%x\n",
+ regVal);
regVal &= ~(SPC_REG_RESET_PCS_IOP_SS | SPC_REG_RESET_PCS_AAP1_SS);
pm8001_cw32(pm8001_ha, 2, SPC_REG_RESET, regVal);
/* step 7: Reset the BDMA/OSSP */
regVal = pm8001_cr32(pm8001_ha, 2, SPC_REG_RESET);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Top Register before resetting BDMA/OSSP"
- ": = 0x%x\n", regVal));
+ pm8001_dbg(pm8001_ha, INIT, "Top Register before resetting BDMA/OSSP: = 0x%x\n",
+ regVal);
regVal &= ~(SPC_REG_RESET_BDMA_CORE | SPC_REG_RESET_OSSP);
pm8001_cw32(pm8001_ha, 2, SPC_REG_RESET, regVal);
@@ -996,9 +978,9 @@
/* step 9: bring the BDMA and OSSP out of reset */
regVal = pm8001_cr32(pm8001_ha, 2, SPC_REG_RESET);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Top Register before bringing up BDMA/OSSP"
- ":= 0x%x\n", regVal));
+ pm8001_dbg(pm8001_ha, INIT,
+ "Top Register before bringing up BDMA/OSSP:= 0x%x\n",
+ regVal);
regVal |= (SPC_REG_RESET_BDMA_CORE | SPC_REG_RESET_OSSP);
pm8001_cw32(pm8001_ha, 2, SPC_REG_RESET, regVal);
@@ -1009,14 +991,13 @@
/* map 0x0700000 to BAR4(0x20), BAR2(win) */
if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_ADDR_BASE)) {
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SPC Shift Bar4 to 0x%x failed\n",
- GSM_ADDR_BASE));
+ pm8001_dbg(pm8001_ha, FAIL, "SPC Shift Bar4 to 0x%x failed\n",
+ GSM_ADDR_BASE);
return -1;
}
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GSM 0x0 (0x00007b88)-GSM Configuration and "
- "Reset = 0x%x\n", pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET)));
+ pm8001_dbg(pm8001_ha, INIT,
+ "GSM 0x0 (0x00007b88)-GSM Configuration and Reset = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET));
regVal = pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET);
/* Put those bits to high */
/* GSM XCBI offset = 0x70 0000
@@ -1028,44 +1009,37 @@
*/
regVal |= (GSM_CONFIG_RESET_VALUE);
pm8001_cw32(pm8001_ha, 2, GSM_CONFIG_RESET, regVal);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GSM (0x00004088 ==> 0x00007b88) - GSM"
- " Configuration and Reset is set to = 0x%x\n",
- pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET)));
+ pm8001_dbg(pm8001_ha, INIT, "GSM (0x00004088 ==> 0x00007b88) - GSM Configuration and Reset is set to = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET));
/* step 12: Restore GSM - Read Address Parity Check */
regVal = pm8001_cr32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK);
/* just for debugging */
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GSM 0x700038 - Read Address Parity Check Enable"
- " = 0x%x\n", regVal));
+ pm8001_dbg(pm8001_ha, INIT,
+ "GSM 0x700038 - Read Address Parity Check Enable = 0x%x\n",
+ regVal);
pm8001_cw32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK, regVal1);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GSM 0x700038 - Read Address Parity"
- " Check Enable is set to = 0x%x\n",
- pm8001_cr32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK)));
+ pm8001_dbg(pm8001_ha, INIT, "GSM 0x700038 - Read Address Parity Check Enable is set to = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK));
/* Restore GSM - Write Address Parity Check */
regVal = pm8001_cr32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK);
pm8001_cw32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK, regVal2);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GSM 0x700040 - Write Address Parity Check"
- " Enable is set to = 0x%x\n",
- pm8001_cr32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK)));
+ pm8001_dbg(pm8001_ha, INIT,
+ "GSM 0x700040 - Write Address Parity Check Enable is set to = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK));
/* Restore GSM - Write Data Parity Check */
regVal = pm8001_cr32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK);
pm8001_cw32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK, regVal3);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GSM 0x700048 - Write Data Parity Check Enable"
- "is set to = 0x%x\n",
- pm8001_cr32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK)));
+ pm8001_dbg(pm8001_ha, INIT,
+ "GSM 0x700048 - Write Data Parity Check Enableis set to = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK));
/* step 13: bring the IOP and AAP1 out of reset */
/* map 0x00000 to BAR4(0x20), BAR2(win) */
if (-1 == pm8001_bar4_shift(pm8001_ha, SPC_TOP_LEVEL_ADDR_BASE)) {
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Shift Bar4 to 0x%x failed\n",
- SPC_TOP_LEVEL_ADDR_BASE));
+ pm8001_dbg(pm8001_ha, FAIL, "Shift Bar4 to 0x%x failed\n",
+ SPC_TOP_LEVEL_ADDR_BASE);
return -1;
}
regVal = pm8001_cr32(pm8001_ha, 2, SPC_REG_RESET);
@@ -1088,22 +1062,20 @@
if (!max_wait_count) {
regVal = pm8001_cr32(pm8001_ha, 0,
MSGU_SCRATCH_PAD_1);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("TIMEOUT : ToggleVal 0x%x,"
- "MSGU_SCRATCH_PAD1 = 0x%x\n",
- toggleVal, regVal));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SCRATCH_PAD0 value = 0x%x\n",
- pm8001_cr32(pm8001_ha, 0,
- MSGU_SCRATCH_PAD_0)));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SCRATCH_PAD2 value = 0x%x\n",
- pm8001_cr32(pm8001_ha, 0,
- MSGU_SCRATCH_PAD_2)));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SCRATCH_PAD3 value = 0x%x\n",
- pm8001_cr32(pm8001_ha, 0,
- MSGU_SCRATCH_PAD_3)));
+ pm8001_dbg(pm8001_ha, FAIL, "TIMEOUT : ToggleVal 0x%x,MSGU_SCRATCH_PAD1 = 0x%x\n",
+ toggleVal, regVal);
+ pm8001_dbg(pm8001_ha, FAIL,
+ "SCRATCH_PAD0 value = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0,
+ MSGU_SCRATCH_PAD_0));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "SCRATCH_PAD2 value = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0,
+ MSGU_SCRATCH_PAD_2));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "SCRATCH_PAD3 value = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0,
+ MSGU_SCRATCH_PAD_3));
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
return -1;
}
@@ -1118,22 +1090,22 @@
if (check_fw_ready(pm8001_ha) == -1) {
regVal = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
/* return error if MPI Configuration Table not ready */
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("FW not ready SCRATCH_PAD1"
- " = 0x%x\n", regVal));
+ pm8001_dbg(pm8001_ha, INIT,
+ "FW not ready SCRATCH_PAD1 = 0x%x\n",
+ regVal);
regVal = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2);
/* return error if MPI Configuration Table not ready */
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("FW not ready SCRATCH_PAD2"
- " = 0x%x\n", regVal));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("SCRATCH_PAD0 value = 0x%x\n",
- pm8001_cr32(pm8001_ha, 0,
- MSGU_SCRATCH_PAD_0)));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("SCRATCH_PAD3 value = 0x%x\n",
- pm8001_cr32(pm8001_ha, 0,
- MSGU_SCRATCH_PAD_3)));
+ pm8001_dbg(pm8001_ha, INIT,
+ "FW not ready SCRATCH_PAD2 = 0x%x\n",
+ regVal);
+ pm8001_dbg(pm8001_ha, INIT,
+ "SCRATCH_PAD0 value = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0,
+ MSGU_SCRATCH_PAD_0));
+ pm8001_dbg(pm8001_ha, INIT,
+ "SCRATCH_PAD3 value = 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0,
+ MSGU_SCRATCH_PAD_3));
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
return -1;
}
@@ -1141,8 +1113,7 @@
pm8001_bar4_shift(pm8001_ha, 0);
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("SPC soft reset Complete\n"));
+ pm8001_dbg(pm8001_ha, INIT, "SPC soft reset Complete\n");
return 0;
}
@@ -1150,8 +1121,7 @@
{
u32 i;
u32 regVal;
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("chip reset start\n"));
+ pm8001_dbg(pm8001_ha, INIT, "chip reset start\n");
/* do SPC chip reset. */
regVal = pm8001_cr32(pm8001_ha, 1, SPC_REG_RESET);
@@ -1175,8 +1145,7 @@
mdelay(1);
} while ((--i) != 0);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("chip reset finished\n"));
+ pm8001_dbg(pm8001_ha, INIT, "chip reset finished\n");
}
/**
@@ -1186,7 +1155,7 @@
void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha)
{
s8 bar, logical = 0;
- for (bar = 0; bar < 6; bar++) {
+ for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
/*
** logical BARs for SPC:
** bar 0 and 1 - logical BAR0
@@ -1231,6 +1200,7 @@
/**
* pm8001_chip_msix_interrupt_enable - enable PM8001 chip interrupt
* @pm8001_ha: our hba card information
+ * @int_vec_idx: interrupt number to enable
*/
static void
pm8001_chip_msix_interrupt_enable(struct pm8001_hba_info *pm8001_ha,
@@ -1249,6 +1219,7 @@
/**
* pm8001_chip_msix_interrupt_disable - disable PM8001 chip interrupt
* @pm8001_ha: our hba card information
+ * @int_vec_idx: interrupt number to disable
*/
static void
pm8001_chip_msix_interrupt_disable(struct pm8001_hba_info *pm8001_ha,
@@ -1264,6 +1235,7 @@
/**
* pm8001_chip_interrupt_enable - enable PM8001 chip interrupt
* @pm8001_ha: our hba card information
+ * @vec: unused
*/
static void
pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec)
@@ -1278,6 +1250,7 @@
/**
* pm8001_chip_intx_interrupt_disable- disable PM8001 chip interrupt
* @pm8001_ha: our hba card information
+ * @vec: unused
*/
static void
pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec)
@@ -1336,24 +1309,38 @@
* @circularQ: the inbound queue we want to transfer to HBA.
* @opCode: the operation code represents commands which LLDD and fw recognized.
* @payload: the command payload of each operation command.
+ * @nb: size in bytes of the command payload
+ * @responseQueue: queue to interrupt on w/ command response (if any)
*/
int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
struct inbound_queue_table *circularQ,
- u32 opCode, void *payload, u32 responseQueue)
+ u32 opCode, void *payload, size_t nb,
+ u32 responseQueue)
{
u32 Header = 0, hpriority = 0, bc = 1, category = 0x02;
void *pMessage;
+ unsigned long flags;
+ int q_index = circularQ - pm8001_ha->inbnd_q_tbl;
+ int rv = -1;
- if (pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size,
- &pMessage) < 0) {
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("No free mpi buffer\n"));
- return -ENOMEM;
+ if (WARN_ON(q_index >= pm8001_ha->max_q_num))
+ return -EINVAL;
+
+ spin_lock_irqsave(&circularQ->iq_lock, flags);
+ rv = pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size,
+ &pMessage);
+ if (rv < 0) {
+ pm8001_dbg(pm8001_ha, IO, "No free mpi buffer\n");
+ rv = -ENOMEM;
+ goto done;
}
- BUG_ON(!payload);
- /*Copy to the payload*/
- memcpy(pMessage, payload, (pm8001_ha->iomb_size -
- sizeof(struct mpi_msg_hdr)));
+
+ if (nb > (pm8001_ha->iomb_size - sizeof(struct mpi_msg_hdr)))
+ nb = pm8001_ha->iomb_size - sizeof(struct mpi_msg_hdr);
+ memcpy(pMessage, payload, nb);
+ if (nb + sizeof(struct mpi_msg_hdr) < pm8001_ha->iomb_size)
+ memset(pMessage + nb, 0, pm8001_ha->iomb_size -
+ (nb + sizeof(struct mpi_msg_hdr)));
/*Build the header*/
Header = ((1 << 31) | (hpriority << 30) | ((bc & 0x1f) << 24)
@@ -1364,11 +1351,13 @@
/*Update the PI to the firmware*/
pm8001_cw32(pm8001_ha, circularQ->pi_pci_bar,
circularQ->pi_offset, circularQ->producer_idx);
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n",
- responseQueue, opCode, circularQ->producer_idx,
- circularQ->consumer_index));
- return 0;
+ pm8001_dbg(pm8001_ha, DEVIO,
+ "INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n",
+ responseQueue, opCode, circularQ->producer_idx,
+ circularQ->consumer_index);
+done:
+ spin_unlock_irqrestore(&circularQ->iq_lock, flags);
+ return rv;
}
u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
@@ -1382,17 +1371,17 @@
pOutBoundMsgHeader = (struct mpi_msg_hdr *)(circularQ->base_virt +
circularQ->consumer_idx * pm8001_ha->iomb_size);
if (pOutBoundMsgHeader != msgHeader) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("consumer_idx = %d msgHeader = %p\n",
- circularQ->consumer_idx, msgHeader));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "consumer_idx = %d msgHeader = %p\n",
+ circularQ->consumer_idx, msgHeader);
/* Update the producer index from SPC */
producer_index = pm8001_read_32(circularQ->pi_virt);
circularQ->producer_index = cpu_to_le32(producer_index);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("consumer_idx = %d producer_index = %d"
- "msgHeader = %p\n", circularQ->consumer_idx,
- circularQ->producer_index, msgHeader));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "consumer_idx = %d producer_index = %dmsgHeader = %p\n",
+ circularQ->consumer_idx,
+ circularQ->producer_index, msgHeader);
return 0;
}
/* free the circular queue buffer elements associated with the message*/
@@ -1404,9 +1393,8 @@
/* Update the producer index from SPC*/
producer_index = pm8001_read_32(circularQ->pi_virt);
circularQ->producer_index = cpu_to_le32(producer_index);
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk(" CI=%d PI=%d\n", circularQ->consumer_idx,
- circularQ->producer_index));
+ pm8001_dbg(pm8001_ha, IO, " CI=%d PI=%d\n",
+ circularQ->consumer_idx, circularQ->producer_index);
return 0;
}
@@ -1436,6 +1424,10 @@
/* read header */
header_tmp = pm8001_read_32(msgHeader);
msgHeader_tmp = cpu_to_le32(header_tmp);
+ pm8001_dbg(pm8001_ha, DEVIO,
+ "outbound opcode msgheader:%x ci=%d pi=%d\n",
+ msgHeader_tmp, circularQ->consumer_idx,
+ circularQ->producer_index);
if (0 != (le32_to_cpu(msgHeader_tmp) & 0x80000000)) {
if (OPC_OUB_SKIP_ENTRY !=
(le32_to_cpu(msgHeader_tmp) & 0xfff)) {
@@ -1444,12 +1436,11 @@
sizeof(struct mpi_msg_hdr);
*pBC = (u8)((le32_to_cpu(msgHeader_tmp)
>> 24) & 0x1f);
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk(": CI=%d PI=%d "
- "msgHeader=%x\n",
- circularQ->consumer_idx,
- circularQ->producer_index,
- msgHeader_tmp));
+ pm8001_dbg(pm8001_ha, IO,
+ ": CI=%d PI=%d msgHeader=%x\n",
+ circularQ->consumer_idx,
+ circularQ->producer_index,
+ msgHeader_tmp);
return MPI_IO_STATUS_SUCCESS;
} else {
circularQ->consumer_idx =
@@ -1558,17 +1549,15 @@
ts->stat = SAS_QUEUE_FULL;
pm8001_dev = ccb->device;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
spin_lock_irqsave(&t->task_state_lock, flags1);
t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
t->task_state_flags |= SAS_TASK_STATE_DONE;
if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
spin_unlock_irqrestore(&t->task_state_lock, flags1);
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("task 0x%p"
- " done with event 0x%x resp 0x%x stat 0x%x but"
- " aborted by upper layer!\n",
- t, pw->handler, ts->resp, ts->stat));
+ pm8001_dbg(pm8001_ha, FAIL, "task 0x%p done with event 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
+ t, pw->handler, ts->resp, ts->stat);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
} else {
@@ -1588,25 +1577,16 @@
unsigned long flags, flags1;
int i, ret = 0;
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
ret = pm8001_query_task(t);
- PM8001_IO_DBG(pm8001_ha,
- switch (ret) {
- case TMF_RESP_FUNC_SUCC:
- pm8001_printk("...Task on lu\n");
- break;
-
- case TMF_RESP_FUNC_COMPLETE:
- pm8001_printk("...Task NOT on lu\n");
- break;
-
- default:
- pm8001_printk("...query task failed!!!\n");
- break;
- });
+ if (ret == TMF_RESP_FUNC_SUCC)
+ pm8001_dbg(pm8001_ha, IO, "...Task on lu\n");
+ else if (ret == TMF_RESP_FUNC_COMPLETE)
+ pm8001_dbg(pm8001_ha, IO, "...Task NOT on lu\n");
+ else
+ pm8001_dbg(pm8001_ha, DEVIO, "...query task failed!!!\n");
spin_lock_irqsave(&pm8001_ha->lock, flags);
@@ -1651,8 +1631,7 @@
break;
default: /* device misbehavior */
ret = TMF_RESP_FUNC_FAILED;
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("...Reset phy\n"));
+ pm8001_dbg(pm8001_ha, IO, "...Reset phy\n");
pm8001_I_T_nexus_reset(dev);
break;
}
@@ -1666,15 +1645,14 @@
default: /* device misbehavior */
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
ret = TMF_RESP_FUNC_FAILED;
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("...Reset phy\n"));
+ pm8001_dbg(pm8001_ha, IO, "...Reset phy\n");
pm8001_I_T_nexus_reset(dev);
}
if (ret == TMF_RESP_FUNC_FAILED)
t = NULL;
pm8001_open_reject_retry(pm8001_ha, t, pm8001_dev);
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("...Complete\n"));
+ pm8001_dbg(pm8001_ha, IO, "...Complete\n");
} break;
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
dev = pm8001_dev->sas_device;
@@ -1728,15 +1706,14 @@
int ret;
if (!pm8001_ha_dev) {
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "dev is null\n");
return;
}
task = sas_alloc_slow_task(GFP_ATOMIC);
if (!task) {
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot "
- "allocate task\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task\n");
return;
}
@@ -1758,7 +1735,8 @@
task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
task_abort.tag = cpu_to_le32(ccb_tag);
- ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
+ sizeof(task_abort), 0);
if (ret)
pm8001_tag_free(pm8001_ha, ccb_tag);
@@ -1780,8 +1758,7 @@
task = sas_alloc_slow_task(GFP_ATOMIC);
if (!task) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("cannot allocate task !!!\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task !!!\n");
return;
}
task->task_done = pm8001_task_done;
@@ -1789,8 +1766,7 @@
res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
if (res) {
sas_free_task(task);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("cannot allocate tag !!!\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "cannot allocate tag !!!\n");
return;
}
@@ -1801,8 +1777,8 @@
if (!dev) {
sas_free_task(task);
pm8001_tag_free(pm8001_ha, ccb_tag);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Domain device cannot be allocated\n"));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "Domain device cannot be allocated\n");
return;
}
task->dev = dev;
@@ -1831,7 +1807,8 @@
sata_cmd.ncqtag_atap_dir_m |= ((0x1 << 7) | (0x5 << 9));
memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
- res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
+ res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
+ sizeof(sata_cmd), 0);
if (res) {
sas_free_task(task);
pm8001_tag_free(pm8001_ha, ccb_tag);
@@ -1878,22 +1855,25 @@
t = ccb->task;
if (status && status != IO_UNDERFLOW)
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("sas IO status 0x%x\n", status));
+ pm8001_dbg(pm8001_ha, FAIL, "sas IO status 0x%x\n", status);
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
ts = &t->task_status;
/* Print sas address of IO failed device */
if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) &&
(status != IO_UNDERFLOW))
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SAS Address of IO Failure Drive:"
- "%016llx", SAS_ADDR(t->dev->sas_addr)));
+ pm8001_dbg(pm8001_ha, FAIL, "SAS Address of IO Failure Drive:%016llx\n",
+ SAS_ADDR(t->dev->sas_addr));
+
+ if (status)
+ pm8001_dbg(pm8001_ha, IOERR,
+ "status:0x%x, tag:0x%x, task:0x%p\n",
+ status, tag, t);
switch (status) {
case IO_SUCCESS:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS"
- ",param = %d\n", param));
+ pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS,param = %d\n",
+ param);
if (param == 0) {
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_GOOD;
@@ -1905,69 +1885,63 @@
sas_ssp_task_response(pm8001_ha->dev, t, iu);
}
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_ABORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_ABORTED IOMB Tag\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB Tag\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_ABORTED_TASK;
break;
case IO_UNDERFLOW:
/* SSP Completion with error */
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW"
- ",param = %d\n", param));
+ pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW,param = %d\n",
+ param);
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_UNDERRUN;
ts->residual = param;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_NO_DEVICE:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_NO_DEVICE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n");
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_PHY_DOWN;
break;
case IO_XFER_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
/* Force the midlayer to retry */
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_XFER_ERROR_PHY_NOT_READY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_EPROTO;
break;
case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
break;
case IO_OPEN_CNX_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
@@ -1977,68 +1951,59 @@
IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
break;
case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_BAD_DEST;
break;
case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_CONNECTION_RATE_"
- "NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_CONN_RATE;
break;
case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
break;
case IO_XFER_ERROR_NAK_RECEIVED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_NAK_R_ERR;
break;
case IO_XFER_ERROR_DMA:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_DMA\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_DMA\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
break;
case IO_XFER_OPEN_RETRY_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_XFER_ERROR_OFFSET_MISMATCH:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
break;
case IO_PORT_IN_RESET:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_PORT_IN_RESET\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
break;
case IO_DS_NON_OPERATIONAL:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_DS_NON_OPERATIONAL\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
if (!t->uldd_task)
@@ -2047,51 +2012,44 @@
IO_DS_NON_OPERATIONAL);
break;
case IO_DS_IN_RECOVERY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_DS_IN_RECOVERY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
break;
case IO_TM_TAG_NOT_FOUND:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_TM_TAG_NOT_FOUND\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_TM_TAG_NOT_FOUND\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
break;
case IO_SSP_EXT_IU_ZERO_LEN_ERROR:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_SSP_EXT_IU_ZERO_LEN_ERROR\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_SSP_EXT_IU_ZERO_LEN_ERROR\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
break;
case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
default:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("Unknown status 0x%x\n", status));
+ pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status);
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
break;
}
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("scsi_status = %x\n ",
- psspPayload->ssp_resp_iu.status));
+ pm8001_dbg(pm8001_ha, IO, "scsi_status = %x\n",
+ psspPayload->ssp_resp_iu.status);
spin_lock_irqsave(&t->task_state_lock, flags);
t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
t->task_state_flags |= SAS_TASK_STATE_DONE;
if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
spin_unlock_irqrestore(&t->task_state_lock, flags);
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("task 0x%p done with"
- " io_status 0x%x resp 0x%x "
- "stat 0x%x but aborted by upper layer!\n",
- t, status, ts->resp, ts->stat));
+ pm8001_dbg(pm8001_ha, FAIL, "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
+ t, status, ts->resp, ts->stat);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
} else {
spin_unlock_irqrestore(&t->task_state_lock, flags);
@@ -2120,60 +2078,52 @@
t = ccb->task;
pm8001_dev = ccb->device;
if (event)
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("sas IO status 0x%x\n", event));
+ pm8001_dbg(pm8001_ha, FAIL, "sas IO status 0x%x\n", event);
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
ts = &t->task_status;
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("port_id = %x,device_id = %x\n",
- port_id, dev_id));
+ pm8001_dbg(pm8001_ha, DEVIO, "port_id = %x,device_id = %x\n",
+ port_id, dev_id);
switch (event) {
case IO_OVERFLOW:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n");)
+ pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
ts->residual = 0;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
pm8001_handle_event(pm8001_ha, t, IO_XFER_ERROR_BREAK);
return;
case IO_XFER_ERROR_PHY_NOT_READY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT"
- "_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_EPROTO;
break;
case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
break;
case IO_OPEN_CNX_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
@@ -2183,88 +2133,78 @@
IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
break;
case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_BAD_DEST;
break;
case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_CONNECTION_RATE_"
- "NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_CONN_RATE;
break;
case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
break;
case IO_XFER_ERROR_NAK_RECEIVED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_NAK_R_ERR;
break;
case IO_XFER_OPEN_RETRY_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
pm8001_handle_event(pm8001_ha, t, IO_XFER_OPEN_RETRY_TIMEOUT);
return;
case IO_XFER_ERROR_UNEXPECTED_PHASE:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_UNEXPECTED_PHASE\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
break;
case IO_XFER_ERROR_XFER_RDY_OVERRUN:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_XFER_RDY_OVERRUN\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_XFER_RDY_OVERRUN\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
break;
case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
break;
case IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
break;
case IO_XFER_ERROR_OFFSET_MISMATCH:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
break;
case IO_XFER_ERROR_XFER_ZERO_DATA_LEN:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
break;
case IO_XFER_CMD_FRAME_ISSUED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk(" IO_XFER_CMD_FRAME_ISSUED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_CMD_FRAME_ISSUED\n");
return;
default:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("Unknown status 0x%x\n", event));
+ pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", event);
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
@@ -2276,10 +2216,8 @@
t->task_state_flags |= SAS_TASK_STATE_DONE;
if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
spin_unlock_irqrestore(&t->task_state_lock, flags);
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("task 0x%p done with"
- " event 0x%x resp 0x%x "
- "stat 0x%x but aborted by upper layer!\n",
- t, event, ts->resp, ts->stat));
+ pm8001_dbg(pm8001_ha, FAIL, "task 0x%p done with event 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
+ t, event, ts->resp, ts->stat);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
} else {
spin_unlock_irqrestore(&t->task_state_lock, flags);
@@ -2315,8 +2253,7 @@
tag = le32_to_cpu(psataPayload->tag);
if (!tag) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("tag null\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "tag null\n");
return;
}
ccb = &pm8001_ha->ccb_info[tag];
@@ -2325,8 +2262,7 @@
t = ccb->task;
pm8001_dev = ccb->device;
} else {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("ccb null\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "ccb null\n");
return;
}
@@ -2334,24 +2270,27 @@
if (t->dev && (t->dev->lldd_dev))
pm8001_dev = t->dev->lldd_dev;
} else {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("task null\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "task null\n");
return;
}
if ((pm8001_dev && !(pm8001_dev->id & NCQ_READ_LOG_FLAG))
&& unlikely(!t || !t->lldd_task || !t->dev)) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("task or dev null\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "task or dev null\n");
return;
}
ts = &t->task_status;
if (!ts) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("ts null\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "ts null\n");
return;
}
+
+ if (status)
+ pm8001_dbg(pm8001_ha, IOERR,
+ "status:0x%x, tag:0x%x, task::0x%p\n",
+ status, tag, t);
+
/* Print sas address of IO failed device */
if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) &&
(status != IO_UNDERFLOW)) {
@@ -2382,19 +2321,19 @@
& 0xff000000)) +
pm8001_dev->attached_phy +
0x10);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SAS Address of IO Failure Drive:"
- "%08x%08x", temp_sata_addr_hi,
- temp_sata_addr_low));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "SAS Address of IO Failure Drive:%08x%08x\n",
+ temp_sata_addr_hi,
+ temp_sata_addr_low);
} else {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SAS Address of IO Failure Drive:"
- "%016llx", SAS_ADDR(t->dev->sas_addr)));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "SAS Address of IO Failure Drive:%016llx\n",
+ SAS_ADDR(t->dev->sas_addr));
}
}
switch (status) {
case IO_SUCCESS:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS\n");
if (param == 0) {
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_GOOD;
@@ -2416,99 +2355,102 @@
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_PROTO_RESPONSE;
ts->residual = param;
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("SAS_PROTO_RESPONSE len = %d\n",
- param));
+ pm8001_dbg(pm8001_ha, IO,
+ "SAS_PROTO_RESPONSE len = %d\n",
+ param);
sata_resp = &psataPayload->sata_resp[0];
resp = (struct ata_task_resp *)ts->buf;
if (t->ata_task.dma_xfer == 0 &&
t->data_dir == DMA_FROM_DEVICE) {
len = sizeof(struct pio_setup_fis);
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("PIO read len = %d\n", len));
+ pm8001_dbg(pm8001_ha, IO,
+ "PIO read len = %d\n", len);
} else if (t->ata_task.use_ncq) {
len = sizeof(struct set_dev_bits_fis);
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("FPDMA len = %d\n", len));
+ pm8001_dbg(pm8001_ha, IO, "FPDMA len = %d\n",
+ len);
} else {
len = sizeof(struct dev_to_host_fis);
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("other len = %d\n", len));
+ pm8001_dbg(pm8001_ha, IO, "other len = %d\n",
+ len);
}
if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) {
resp->frame_len = len;
memcpy(&resp->ending_fis[0], sata_resp, len);
ts->buf_valid_size = sizeof(*resp);
} else
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("response to large\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "response too large\n");
}
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_ABORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_ABORTED IOMB Tag\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB Tag\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_ABORTED_TASK;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
/* following cases are to do cases */
case IO_UNDERFLOW:
/* SATA Completion with error */
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_UNDERFLOW param = %d\n", param));
+ pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW param = %d\n", param);
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_UNDERRUN;
ts->residual = param;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_NO_DEVICE:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_NO_DEVICE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n");
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_PHY_DOWN;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_INTERRUPTED;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_PHY_NOT_READY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT"
- "_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_EPROTO;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
if (!t->uldd_task) {
@@ -2522,8 +2464,8 @@
}
break;
case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_BAD_DEST;
@@ -2538,17 +2480,15 @@
}
break;
case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_CONNECTION_RATE_"
- "NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_STP_RESOURCES"
- "_BUSY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
if (!t->uldd_task) {
@@ -2562,57 +2502,65 @@
}
break;
case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_NAK_RECEIVED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_NAK_R_ERR;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_NAK_R_ERR;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_DMA:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_DMA\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_DMA\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_ABORTED_TASK;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_SATA_LINK_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_SATA_LINK_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_SATA_LINK_TIMEOUT\n");
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_DEV_NO_RESPONSE;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_REJECTED_NCQ_MODE:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_REJECTED_NCQ_MODE\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_UNDERRUN;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_OPEN_RETRY_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_PORT_IN_RESET:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_PORT_IN_RESET\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_DS_NON_OPERATIONAL:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_DS_NON_OPERATIONAL\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
if (!t->uldd_task) {
@@ -2625,14 +2573,14 @@
}
break;
case IO_DS_IN_RECOVERY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk(" IO_DS_IN_RECOVERY\n"));
+ pm8001_dbg(pm8001_ha, IO, " IO_DS_IN_RECOVERY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_DS_IN_ERROR:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_DS_IN_ERROR\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_ERROR\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
if (!t->uldd_task) {
@@ -2645,18 +2593,21 @@
}
break;
case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
default:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("Unknown status 0x%x\n", status));
+ pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status);
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
}
spin_lock_irqsave(&t->task_state_lock, flags);
@@ -2665,10 +2616,9 @@
t->task_state_flags |= SAS_TASK_STATE_DONE;
if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
spin_unlock_irqrestore(&t->task_state_lock, flags);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("task 0x%p done with io_status 0x%x"
- " resp 0x%x stat 0x%x but aborted by upper layer!\n",
- t, status, ts->resp, ts->stat));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
+ t, status, ts->resp, ts->stat);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
} else {
spin_unlock_irqrestore(&t->task_state_lock, flags);
@@ -2697,12 +2647,10 @@
t = ccb->task;
pm8001_dev = ccb->device;
} else {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("No CCB !!!. returning\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "No CCB !!!. returning\n");
}
if (event)
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SATA EVENT 0x%x\n", event));
+ pm8001_dbg(pm8001_ha, FAIL, "SATA EVENT 0x%x\n", event);
/* Check if this is NCQ error */
if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) {
@@ -2718,61 +2666,54 @@
t = ccb->task;
pm8001_dev = ccb->device;
if (event)
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("sata IO status 0x%x\n", event));
+ pm8001_dbg(pm8001_ha, FAIL, "sata IO status 0x%x\n", event);
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
ts = &t->task_status;
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n",
- port_id, dev_id, tag, event));
+ pm8001_dbg(pm8001_ha, DEVIO,
+ "port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n",
+ port_id, dev_id, tag, event);
switch (event) {
case IO_OVERFLOW:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
ts->residual = 0;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_INTERRUPTED;
break;
case IO_XFER_ERROR_PHY_NOT_READY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT"
- "_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_EPROTO;
break;
case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
break;
case IO_OPEN_CNX_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
break;
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_DEV_NO_RESPONSE;
if (!t->uldd_task) {
@@ -2786,94 +2727,82 @@
}
break;
case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_BAD_DEST;
break;
case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_CONNECTION_RATE_"
- "NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_CONN_RATE;
break;
case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
break;
case IO_XFER_ERROR_NAK_RECEIVED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_NAK_R_ERR;
break;
case IO_XFER_ERROR_PEER_ABORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_PEER_ABORTED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PEER_ABORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_NAK_R_ERR;
break;
case IO_XFER_ERROR_REJECTED_NCQ_MODE:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_REJECTED_NCQ_MODE\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_UNDERRUN;
break;
case IO_XFER_OPEN_RETRY_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
case IO_XFER_ERROR_UNEXPECTED_PHASE:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_UNEXPECTED_PHASE\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
case IO_XFER_ERROR_XFER_RDY_OVERRUN:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_XFER_RDY_OVERRUN\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_XFER_RDY_OVERRUN\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
case IO_XFER_ERROR_OFFSET_MISMATCH:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
case IO_XFER_ERROR_XFER_ZERO_DATA_LEN:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
case IO_XFER_CMD_FRAME_ISSUED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_CMD_FRAME_ISSUED\n");
break;
case IO_XFER_PIO_SETUP_ERROR:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_PIO_SETUP_ERROR\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_PIO_SETUP_ERROR\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
default:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("Unknown status 0x%x\n", event));
+ pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", event);
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
@@ -2885,10 +2814,9 @@
t->task_state_flags |= SAS_TASK_STATE_DONE;
if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
spin_unlock_irqrestore(&t->task_state_lock, flags);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("task 0x%p done with io_status 0x%x"
- " resp 0x%x stat 0x%x but aborted by upper layer!\n",
- t, event, ts->resp, ts->stat));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
+ t, event, ts->resp, ts->stat);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
} else {
spin_unlock_irqrestore(&t->task_state_lock, flags);
@@ -2917,83 +2845,80 @@
t = ccb->task;
ts = &t->task_status;
pm8001_dev = ccb->device;
- if (status)
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("smp IO status 0x%x\n", status));
+ if (status) {
+ pm8001_dbg(pm8001_ha, FAIL, "smp IO status 0x%x\n", status);
+ pm8001_dbg(pm8001_ha, IOERR,
+ "status:0x%x, tag:0x%x, task:0x%p\n",
+ status, tag, t);
+ }
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
switch (status) {
case IO_SUCCESS:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_GOOD;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_ABORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_ABORTED IOMB\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_ABORTED_TASK;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OVERFLOW:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
ts->residual = 0;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_NO_DEVICE:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_PHY_DOWN;
break;
case IO_ERROR_HW_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_ERROR_HW_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_ERROR_HW_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_BUSY;
break;
case IO_XFER_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_BUSY;
break;
case IO_XFER_ERROR_PHY_NOT_READY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_BUSY;
break;
case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
break;
case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
break;
case IO_OPEN_CNX_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
break;
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
@@ -3002,76 +2927,67 @@
IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
break;
case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_BAD_DEST;
break;
case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_CONNECTION_RATE_"
- "NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_CONN_RATE;
break;
case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
break;
case IO_XFER_ERROR_RX_FRAME:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_RX_FRAME\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_RX_FRAME\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
break;
case IO_XFER_OPEN_RETRY_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_ERROR_INTERNAL_SMP_RESOURCE:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_ERROR_INTERNAL_SMP_RESOURCE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_ERROR_INTERNAL_SMP_RESOURCE\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_QUEUE_FULL;
break;
case IO_PORT_IN_RESET:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_PORT_IN_RESET\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_DS_NON_OPERATIONAL:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_DS_NON_OPERATIONAL\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
break;
case IO_DS_IN_RECOVERY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_DS_IN_RECOVERY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
default:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("Unknown status 0x%x\n", status));
+ pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status);
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
/* not allowed case. Therefore, return failed status */
@@ -3083,10 +2999,8 @@
t->task_state_flags |= SAS_TASK_STATE_DONE;
if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
spin_unlock_irqrestore(&t->task_state_lock, flags);
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("task 0x%p done with"
- " io_status 0x%x resp 0x%x "
- "stat 0x%x but aborted by upper layer!\n",
- t, status, ts->resp, ts->stat));
+ pm8001_dbg(pm8001_ha, FAIL, "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
+ t, status, ts->resp, ts->stat);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
} else {
spin_unlock_irqrestore(&t->task_state_lock, flags);
@@ -3108,9 +3022,8 @@
u32 device_id = le32_to_cpu(pPayload->device_id);
u8 pds = le32_to_cpu(pPayload->pds_nds) & PDS_BITS;
u8 nds = le32_to_cpu(pPayload->pds_nds) & NDS_BITS;
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Set device id = 0x%x state "
- "from 0x%x to 0x%x status = 0x%x!\n",
- device_id, pds, nds, status));
+ pm8001_dbg(pm8001_ha, MSG, "Set device id = 0x%x state from 0x%x to 0x%x status = 0x%x!\n",
+ device_id, pds, nds, status);
complete(pm8001_dev->setds_completion);
ccb->task = NULL;
ccb->ccb_tag = 0xFFFFFFFF;
@@ -3125,10 +3038,9 @@
struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[tag];
u32 dlen_status = le32_to_cpu(pPayload->dlen_status);
complete(pm8001_ha->nvmd_completion);
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Set nvm data complete!\n"));
+ pm8001_dbg(pm8001_ha, MSG, "Set nvm data complete!\n");
if ((dlen_status & NVMD_STAT) != 0) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Set nvm data error!\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "Set nvm data error!\n");
return;
}
ccb->task = NULL;
@@ -3150,26 +3062,22 @@
void *virt_addr = pm8001_ha->memoryMap.region[NVMD].virt_ptr;
fw_control_context = ccb->fw_control_context;
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Get nvm data complete!\n"));
+ pm8001_dbg(pm8001_ha, MSG, "Get nvm data complete!\n");
if ((dlen_status & NVMD_STAT) != 0) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Get nvm data error!\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "Get nvm data error!\n");
complete(pm8001_ha->nvmd_completion);
return;
}
if (ir_tds_bn_dps_das_nvm & IPMode) {
/* indirect mode - IR bit set */
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("Get NVMD success, IR=1\n"));
+ pm8001_dbg(pm8001_ha, MSG, "Get NVMD success, IR=1\n");
if ((ir_tds_bn_dps_das_nvm & NVMD_TYPE) == TWI_DEVICE) {
if (ir_tds_bn_dps_das_nvm == 0x80a80200) {
memcpy(pm8001_ha->sas_addr,
((u8 *)virt_addr + 4),
SAS_ADDR_SIZE);
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("Get SAS address"
- " from VPD successfully!\n"));
+ pm8001_dbg(pm8001_ha, MSG, "Get SAS address from VPD successfully!\n");
}
} else if (((ir_tds_bn_dps_das_nvm & NVMD_TYPE) == C_SEEPROM)
|| ((ir_tds_bn_dps_das_nvm & NVMD_TYPE) == VPD_FLASH) ||
@@ -3180,14 +3088,14 @@
;
} else {
/* Should not be happened*/
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("(IR=1)Wrong Device type 0x%x\n",
- ir_tds_bn_dps_das_nvm));
+ pm8001_dbg(pm8001_ha, MSG,
+ "(IR=1)Wrong Device type 0x%x\n",
+ ir_tds_bn_dps_das_nvm);
}
} else /* direct mode */{
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("Get NVMD success, IR=0, dataLen=%d\n",
- (dlen_status & NVMD_LEN) >> 24));
+ pm8001_dbg(pm8001_ha, MSG,
+ "Get NVMD success, IR=0, dataLen=%d\n",
+ (dlen_status & NVMD_LEN) >> 24);
}
/* Though fw_control_context is freed below, usrAddr still needs
* to be updated as this holds the response to the request function
@@ -3196,10 +3104,15 @@
pm8001_ha->memoryMap.region[NVMD].virt_ptr,
fw_control_context->len);
kfree(ccb->fw_control_context);
+ /* To avoid race condition, complete should be
+ * called after the message is copied to
+ * fw_control_context->usrAddr
+ */
+ complete(pm8001_ha->nvmd_completion);
+ pm8001_dbg(pm8001_ha, MSG, "Get nvmd data complete!\n");
ccb->task = NULL;
ccb->ccb_tag = 0xFFFFFFFF;
pm8001_tag_free(pm8001_ha, tag);
- complete(pm8001_ha->nvmd_completion);
}
int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
@@ -3212,13 +3125,13 @@
u32 phy_op = le32_to_cpu(pPayload->phyop_phyid) & OP_BITS;
tag = le32_to_cpu(pPayload->tag);
if (status != 0) {
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("%x phy execute %x phy op failed!\n",
- phy_id, phy_op));
+ pm8001_dbg(pm8001_ha, MSG,
+ "%x phy execute %x phy op failed!\n",
+ phy_id, phy_op);
} else {
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("%x phy execute %x phy op success!\n",
- phy_id, phy_op));
+ pm8001_dbg(pm8001_ha, MSG,
+ "%x phy execute %x phy op success!\n",
+ phy_id, phy_op);
pm8001_ha->phy[phy_id].reset_success = true;
}
if (pm8001_ha->phy[phy_id].enable_completion) {
@@ -3265,10 +3178,10 @@
} else if (phy->phy_type & PORT_TYPE_SATA) {
/*Nothing*/
}
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk("phy %d byte dmaded.\n", i));
+ pm8001_dbg(pm8001_ha, MSG, "phy %d byte dmaded.\n", i);
sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
- pm8001_ha->sas->notify_port_event(sas_phy, PORTE_BYTES_DMAED);
+ sas_notify_port_event(sas_phy, PORTE_BYTES_DMAED);
}
/* Get the link rate speed */
@@ -3355,7 +3268,8 @@
((phyId & 0x0F) << 4) | (port_id & 0x0F));
payload.param0 = cpu_to_le32(param0);
payload.param1 = cpu_to_le32(param1);
- pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
}
static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
@@ -3381,43 +3295,39 @@
u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
u8 portstate = (u8)(npip_portstate & 0x0000000F);
struct pm8001_port *port = &pm8001_ha->port[port_id];
- struct sas_ha_struct *sas_ha = pm8001_ha->sas;
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
unsigned long flags;
u8 deviceType = pPayload->sas_identify.dev_type;
port->port_state = portstate;
phy->phy_state = PHY_STATE_LINK_UP_SPC;
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_SAS_PHY_UP port id = %d, phy id = %d\n",
- port_id, phy_id));
+ pm8001_dbg(pm8001_ha, MSG,
+ "HW_EVENT_SAS_PHY_UP port id = %d, phy id = %d\n",
+ port_id, phy_id);
switch (deviceType) {
case SAS_PHY_UNUSED:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("device type no device.\n"));
+ pm8001_dbg(pm8001_ha, MSG, "device type no device.\n");
break;
case SAS_END_DEVICE:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk("end device.\n"));
+ pm8001_dbg(pm8001_ha, MSG, "end device.\n");
pm8001_chip_phy_ctl_req(pm8001_ha, phy_id,
PHY_NOTIFY_ENABLE_SPINUP);
port->port_attached = 1;
pm8001_get_lrate_mode(phy, link_rate);
break;
case SAS_EDGE_EXPANDER_DEVICE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("expander device.\n"));
+ pm8001_dbg(pm8001_ha, MSG, "expander device.\n");
port->port_attached = 1;
pm8001_get_lrate_mode(phy, link_rate);
break;
case SAS_FANOUT_EXPANDER_DEVICE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("fanout expander device.\n"));
+ pm8001_dbg(pm8001_ha, MSG, "fanout expander device.\n");
port->port_attached = 1;
pm8001_get_lrate_mode(phy, link_rate);
break;
default:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("unknown device type(%x)\n", deviceType));
+ pm8001_dbg(pm8001_ha, DEVIO, "unknown device type(%x)\n",
+ deviceType);
break;
}
phy->phy_type |= PORT_TYPE_SAS;
@@ -3428,7 +3338,7 @@
else if (phy->identify.device_type != SAS_PHY_UNUSED)
phy->identify.target_port_protocols = SAS_PROTOCOL_SMP;
phy->sas_phy.oob_mode = SAS_OOB_MODE;
- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
+ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);
memcpy(phy->frame_rcvd, &pPayload->sas_identify,
sizeof(struct sas_identify_frame)-4);
@@ -3460,12 +3370,10 @@
u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
u8 portstate = (u8)(npip_portstate & 0x0000000F);
struct pm8001_port *port = &pm8001_ha->port[port_id];
- struct sas_ha_struct *sas_ha = pm8001_ha->sas;
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
unsigned long flags;
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_SATA_PHY_UP port id = %d,"
- " phy id = %d\n", port_id, phy_id));
+ pm8001_dbg(pm8001_ha, DEVIO, "HW_EVENT_SATA_PHY_UP port id = %d, phy id = %d\n",
+ port_id, phy_id);
port->port_state = portstate;
phy->phy_state = PHY_STATE_LINK_UP_SPC;
port->port_attached = 1;
@@ -3473,7 +3381,7 @@
phy->phy_type |= PORT_TYPE_SATA;
phy->phy_attached = 1;
phy->sas_phy.oob_mode = SATA_OOB_MODE;
- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
+ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);
memcpy(phy->frame_rcvd, ((u8 *)&pPayload->sata_fis - 4),
sizeof(struct dev_to_host_fis));
@@ -3513,37 +3421,35 @@
case PORT_VALID:
break;
case PORT_INVALID:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" PortInvalid portID %d\n", port_id));
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" Last phy Down and port invalid\n"));
+ pm8001_dbg(pm8001_ha, MSG, " PortInvalid portID %d\n",
+ port_id);
+ pm8001_dbg(pm8001_ha, MSG,
+ " Last phy Down and port invalid\n");
port->port_attached = 0;
pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
port_id, phy_id, 0, 0);
break;
case PORT_IN_RESET:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" Port In Reset portID %d\n", port_id));
+ pm8001_dbg(pm8001_ha, MSG, " Port In Reset portID %d\n",
+ port_id);
break;
case PORT_NOT_ESTABLISHED:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" phy Down and PORT_NOT_ESTABLISHED\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ " phy Down and PORT_NOT_ESTABLISHED\n");
port->port_attached = 0;
break;
case PORT_LOSTCOMM:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" phy Down and PORT_LOSTCOMM\n"));
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" Last phy Down and port invalid\n"));
+ pm8001_dbg(pm8001_ha, MSG, " phy Down and PORT_LOSTCOMM\n");
+ pm8001_dbg(pm8001_ha, MSG,
+ " Last phy Down and port invalid\n");
port->port_attached = 0;
pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
port_id, phy_id, 0, 0);
break;
default:
port->port_attached = 0;
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" phy Down and(default) = %x\n",
- portstate));
+ pm8001_dbg(pm8001_ha, DEVIO, " phy Down and(default) = %x\n",
+ portstate);
break;
}
@@ -3574,44 +3480,42 @@
pm8001_dev = ccb->device;
status = le32_to_cpu(registerRespPayload->status);
device_id = le32_to_cpu(registerRespPayload->device_id);
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" register device is status = %d\n", status));
+ pm8001_dbg(pm8001_ha, MSG, " register device is status = %d\n",
+ status);
switch (status) {
case DEVREG_SUCCESS:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk("DEVREG_SUCCESS\n"));
+ pm8001_dbg(pm8001_ha, MSG, "DEVREG_SUCCESS\n");
pm8001_dev->device_id = device_id;
break;
case DEVREG_FAILURE_OUT_OF_RESOURCE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("DEVREG_FAILURE_OUT_OF_RESOURCE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "DEVREG_FAILURE_OUT_OF_RESOURCE\n");
break;
case DEVREG_FAILURE_DEVICE_ALREADY_REGISTERED:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("DEVREG_FAILURE_DEVICE_ALREADY_REGISTERED\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "DEVREG_FAILURE_DEVICE_ALREADY_REGISTERED\n");
break;
case DEVREG_FAILURE_INVALID_PHY_ID:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("DEVREG_FAILURE_INVALID_PHY_ID\n"));
+ pm8001_dbg(pm8001_ha, MSG, "DEVREG_FAILURE_INVALID_PHY_ID\n");
break;
case DEVREG_FAILURE_PHY_ID_ALREADY_REGISTERED:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("DEVREG_FAILURE_PHY_ID_ALREADY_REGISTERED\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "DEVREG_FAILURE_PHY_ID_ALREADY_REGISTERED\n");
break;
case DEVREG_FAILURE_PORT_ID_OUT_OF_RANGE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("DEVREG_FAILURE_PORT_ID_OUT_OF_RANGE\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "DEVREG_FAILURE_PORT_ID_OUT_OF_RANGE\n");
break;
case DEVREG_FAILURE_PORT_NOT_VALID_STATE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("DEVREG_FAILURE_PORT_NOT_VALID_STATE\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "DEVREG_FAILURE_PORT_NOT_VALID_STATE\n");
break;
case DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID\n");
break;
default:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("DEVREG_FAILURE_DEVICE_TYPE_NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "DEVREG_FAILURE_DEVICE_TYPE_NOT_SUPPORTED\n");
break;
}
complete(pm8001_dev->dcompletion);
@@ -3631,9 +3535,9 @@
status = le32_to_cpu(registerRespPayload->status);
device_id = le32_to_cpu(registerRespPayload->device_id);
if (status != 0)
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" deregister device failed ,status = %x"
- ", device_id = %x\n", status, device_id));
+ pm8001_dbg(pm8001_ha, MSG,
+ " deregister device failed ,status = %x, device_id = %x\n",
+ status, device_id);
return 0;
}
@@ -3653,44 +3557,37 @@
status = le32_to_cpu(ppayload->status);
switch (status) {
case FLASH_UPDATE_COMPLETE_PENDING_REBOOT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(": FLASH_UPDATE_COMPLETE_PENDING_REBOOT\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ ": FLASH_UPDATE_COMPLETE_PENDING_REBOOT\n");
break;
case FLASH_UPDATE_IN_PROGRESS:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(": FLASH_UPDATE_IN_PROGRESS\n"));
+ pm8001_dbg(pm8001_ha, MSG, ": FLASH_UPDATE_IN_PROGRESS\n");
break;
case FLASH_UPDATE_HDR_ERR:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(": FLASH_UPDATE_HDR_ERR\n"));
+ pm8001_dbg(pm8001_ha, MSG, ": FLASH_UPDATE_HDR_ERR\n");
break;
case FLASH_UPDATE_OFFSET_ERR:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(": FLASH_UPDATE_OFFSET_ERR\n"));
+ pm8001_dbg(pm8001_ha, MSG, ": FLASH_UPDATE_OFFSET_ERR\n");
break;
case FLASH_UPDATE_CRC_ERR:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(": FLASH_UPDATE_CRC_ERR\n"));
+ pm8001_dbg(pm8001_ha, MSG, ": FLASH_UPDATE_CRC_ERR\n");
break;
case FLASH_UPDATE_LENGTH_ERR:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(": FLASH_UPDATE_LENGTH_ERR\n"));
+ pm8001_dbg(pm8001_ha, MSG, ": FLASH_UPDATE_LENGTH_ERR\n");
break;
case FLASH_UPDATE_HW_ERR:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(": FLASH_UPDATE_HW_ERR\n"));
+ pm8001_dbg(pm8001_ha, MSG, ": FLASH_UPDATE_HW_ERR\n");
break;
case FLASH_UPDATE_DNLD_NOT_SUPPORTED:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(": FLASH_UPDATE_DNLD_NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ ": FLASH_UPDATE_DNLD_NOT_SUPPORTED\n");
break;
case FLASH_UPDATE_DISABLED:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(": FLASH_UPDATE_DISABLED\n"));
+ pm8001_dbg(pm8001_ha, MSG, ": FLASH_UPDATE_DISABLED\n");
break;
default:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("No matched status = %d\n", status));
+ pm8001_dbg(pm8001_ha, DEVIO, "No matched status = %d\n",
+ status);
break;
}
kfree(ccb->fw_control_context);
@@ -3708,12 +3605,11 @@
struct general_event_resp *pPayload =
(struct general_event_resp *)(piomb + 4);
status = le32_to_cpu(pPayload->status);
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" status = 0x%x\n", status));
+ pm8001_dbg(pm8001_ha, MSG, " status = 0x%x\n", status);
for (i = 0; i < GENERAL_EVENT_PAYLOAD; i++)
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("inb_IOMB_payload[0x%x] 0x%x,\n", i,
- pPayload->inb_IOMB_payload[i]));
+ pm8001_dbg(pm8001_ha, MSG, "inb_IOMB_payload[0x%x] 0x%x,\n",
+ i,
+ pPayload->inb_IOMB_payload[i]);
return 0;
}
@@ -3733,8 +3629,7 @@
status = le32_to_cpu(pPayload->status);
tag = le32_to_cpu(pPayload->tag);
if (!tag) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk(" TAG NULL. RETURNING !!!"));
+ pm8001_dbg(pm8001_ha, FAIL, " TAG NULL. RETURNING !!!\n");
return -1;
}
@@ -3744,23 +3639,21 @@
pm8001_dev = ccb->device; /* retrieve device */
if (!t) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk(" TASK NULL. RETURNING !!!"));
+ pm8001_dbg(pm8001_ha, FAIL, " TASK NULL. RETURNING !!!\n");
return -1;
}
ts = &t->task_status;
if (status != 0)
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("task abort failed status 0x%x ,"
- "tag = 0x%x, scp= 0x%x\n", status, tag, scp));
+ pm8001_dbg(pm8001_ha, FAIL, "task abort failed status 0x%x ,tag = 0x%x, scp= 0x%x\n",
+ status, tag, scp);
switch (status) {
case IO_SUCCESS:
- PM8001_EH_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n"));
+ pm8001_dbg(pm8001_ha, EH, "IO_SUCCESS\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_GOOD;
break;
case IO_NOT_VALID:
- PM8001_EH_DBG(pm8001_ha, pm8001_printk("IO_NOT_VALID\n"));
+ pm8001_dbg(pm8001_ha, EH, "IO_NOT_VALID\n");
ts->resp = TMF_RESP_FUNC_FAILED;
break;
}
@@ -3805,193 +3698,177 @@
struct sas_ha_struct *sas_ha = pm8001_ha->sas;
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("outbound queue HW event & event type : "));
+ pm8001_dbg(pm8001_ha, DEVIO,
+ "SPC HW event for portid:%d, phyid:%d, event:%x, status:%x\n",
+ port_id, phy_id, eventType, status);
switch (eventType) {
case HW_EVENT_PHY_START_STATUS:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PHY_START_STATUS"
- " status = %x\n", status));
- if (status == 0) {
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_START_STATUS status = %x\n",
+ status);
+ if (status == 0)
phy->phy_state = 1;
- if (pm8001_ha->flags == PM8001F_RUN_TIME &&
- phy->enable_completion != NULL)
- complete(phy->enable_completion);
+
+ if (pm8001_ha->flags == PM8001F_RUN_TIME &&
+ phy->enable_completion != NULL) {
+ complete(phy->enable_completion);
+ phy->enable_completion = NULL;
}
break;
case HW_EVENT_SAS_PHY_UP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PHY_START_STATUS\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_START_STATUS\n");
hw_event_sas_phy_up(pm8001_ha, piomb);
break;
case HW_EVENT_SATA_PHY_UP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_SATA_PHY_UP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_PHY_UP\n");
hw_event_sata_phy_up(pm8001_ha, piomb);
break;
case HW_EVENT_PHY_STOP_STATUS:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PHY_STOP_STATUS "
- "status = %x\n", status));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_STOP_STATUS status = %x\n",
+ status);
if (status == 0)
phy->phy_state = 0;
break;
case HW_EVENT_SATA_SPINUP_HOLD:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD\n"));
- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD);
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_SPINUP_HOLD\n");
+ sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD);
break;
case HW_EVENT_PHY_DOWN:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PHY_DOWN\n"));
- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_DOWN\n");
+ sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
phy->phy_attached = 0;
phy->phy_state = 0;
hw_event_phy_down(pm8001_ha, piomb);
break;
case HW_EVENT_PORT_INVALID:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_INVALID\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_INVALID\n");
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
/* the broadcast change primitive received, tell the LIBSAS this event
to revalidate the sas domain*/
case HW_EVENT_BROADCAST_CHANGE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_BROADCAST_CHANGE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_CHANGE\n");
pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_BROADCAST_CHANGE,
port_id, phy_id, 1, 0);
spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE;
spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
break;
case HW_EVENT_PHY_ERROR:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PHY_ERROR\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_ERROR\n");
sas_phy_disconnected(&phy->sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR);
+ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR);
break;
case HW_EVENT_BROADCAST_EXP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_BROADCAST_EXP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_EXP\n");
spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP;
spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
break;
case HW_EVENT_LINK_ERR_INVALID_DWORD:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_LINK_ERR_INVALID_DWORD\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "HW_EVENT_LINK_ERR_INVALID_DWORD\n");
pm8001_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0);
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
case HW_EVENT_LINK_ERR_DISPARITY_ERROR:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_LINK_ERR_DISPARITY_ERROR\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "HW_EVENT_LINK_ERR_DISPARITY_ERROR\n");
pm8001_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_DISPARITY_ERROR,
port_id, phy_id, 0, 0);
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
case HW_EVENT_LINK_ERR_CODE_VIOLATION:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_LINK_ERR_CODE_VIOLATION\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "HW_EVENT_LINK_ERR_CODE_VIOLATION\n");
pm8001_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_CODE_VIOLATION,
port_id, phy_id, 0, 0);
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n");
pm8001_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH,
port_id, phy_id, 0, 0);
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
case HW_EVENT_MALFUNCTION:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_MALFUNCTION\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_MALFUNCTION\n");
break;
case HW_EVENT_BROADCAST_SES:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_BROADCAST_SES\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_SES\n");
spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
sas_phy->sas_prim = HW_EVENT_BROADCAST_SES;
spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
break;
case HW_EVENT_INBOUND_CRC_ERROR:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_INBOUND_CRC_ERROR\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_INBOUND_CRC_ERROR\n");
pm8001_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_INBOUND_CRC_ERROR,
port_id, phy_id, 0, 0);
break;
case HW_EVENT_HARD_RESET_RECEIVED:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_HARD_RESET_RECEIVED\n"));
- sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET);
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_HARD_RESET_RECEIVED\n");
+ sas_notify_port_event(sas_phy, PORTE_HARD_RESET);
break;
case HW_EVENT_ID_FRAME_TIMEOUT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_ID_FRAME_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_ID_FRAME_TIMEOUT\n");
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
case HW_EVENT_LINK_ERR_PHY_RESET_FAILED:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n");
pm8001_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_PHY_RESET_FAILED,
port_id, phy_id, 0, 0);
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
case HW_EVENT_PORT_RESET_TIMER_TMO:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RESET_TIMER_TMO\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_TIMER_TMO\n");
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
case HW_EVENT_PORT_RECOVERY_TIMER_TMO:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "HW_EVENT_PORT_RECOVERY_TIMER_TMO\n");
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
case HW_EVENT_PORT_RECOVER:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RECOVER\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RECOVER\n");
break;
case HW_EVENT_PORT_RESET_COMPLETE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RESET_COMPLETE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_COMPLETE\n");
break;
case EVENT_BROADCAST_ASYNCH_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("EVENT_BROADCAST_ASYNCH_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "EVENT_BROADCAST_ASYNCH_EVENT\n");
break;
default:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("Unknown event type = %x\n", eventType));
+ pm8001_dbg(pm8001_ha, DEVIO, "Unknown event type = %x\n",
+ eventType);
break;
}
return 0;
@@ -4007,163 +3884,132 @@
__le32 pHeader = *(__le32 *)piomb;
u8 opc = (u8)((le32_to_cpu(pHeader)) & 0xFFF);
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk("process_one_iomb:"));
+ pm8001_dbg(pm8001_ha, MSG, "process_one_iomb:\n");
switch (opc) {
case OPC_OUB_ECHO:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk("OPC_OUB_ECHO\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_ECHO\n");
break;
case OPC_OUB_HW_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_HW_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_HW_EVENT\n");
mpi_hw_event(pm8001_ha, piomb);
break;
case OPC_OUB_SSP_COMP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SSP_COMP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_COMP\n");
mpi_ssp_completion(pm8001_ha, piomb);
break;
case OPC_OUB_SMP_COMP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SMP_COMP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SMP_COMP\n");
mpi_smp_completion(pm8001_ha, piomb);
break;
case OPC_OUB_LOCAL_PHY_CNTRL:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_LOCAL_PHY_CNTRL\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_LOCAL_PHY_CNTRL\n");
pm8001_mpi_local_phy_ctl(pm8001_ha, piomb);
break;
case OPC_OUB_DEV_REGIST:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_DEV_REGIST\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEV_REGIST\n");
pm8001_mpi_reg_resp(pm8001_ha, piomb);
break;
case OPC_OUB_DEREG_DEV:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("unregister the device\n"));
+ pm8001_dbg(pm8001_ha, MSG, "unregister the device\n");
pm8001_mpi_dereg_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GET_DEV_HANDLE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GET_DEV_HANDLE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_DEV_HANDLE\n");
break;
case OPC_OUB_SATA_COMP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SATA_COMP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_COMP\n");
mpi_sata_completion(pm8001_ha, piomb);
break;
case OPC_OUB_SATA_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SATA_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_EVENT\n");
mpi_sata_event(pm8001_ha, piomb);
break;
case OPC_OUB_SSP_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SSP_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_EVENT\n");
mpi_ssp_event(pm8001_ha, piomb);
break;
case OPC_OUB_DEV_HANDLE_ARRIV:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_DEV_HANDLE_ARRIV\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEV_HANDLE_ARRIV\n");
/*This is for target*/
break;
case OPC_OUB_SSP_RECV_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SSP_RECV_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_RECV_EVENT\n");
/*This is for target*/
break;
case OPC_OUB_DEV_INFO:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_DEV_INFO\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEV_INFO\n");
break;
case OPC_OUB_FW_FLASH_UPDATE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_FW_FLASH_UPDATE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_FW_FLASH_UPDATE\n");
pm8001_mpi_fw_flash_update_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GPIO_RESPONSE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GPIO_RESPONSE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GPIO_RESPONSE\n");
break;
case OPC_OUB_GPIO_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GPIO_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GPIO_EVENT\n");
break;
case OPC_OUB_GENERAL_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GENERAL_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GENERAL_EVENT\n");
pm8001_mpi_general_event(pm8001_ha, piomb);
break;
case OPC_OUB_SSP_ABORT_RSP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SSP_ABORT_RSP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_ABORT_RSP\n");
pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
break;
case OPC_OUB_SATA_ABORT_RSP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SATA_ABORT_RSP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_ABORT_RSP\n");
pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
break;
case OPC_OUB_SAS_DIAG_MODE_START_END:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SAS_DIAG_MODE_START_END\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "OPC_OUB_SAS_DIAG_MODE_START_END\n");
break;
case OPC_OUB_SAS_DIAG_EXECUTE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SAS_DIAG_EXECUTE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SAS_DIAG_EXECUTE\n");
break;
case OPC_OUB_GET_TIME_STAMP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GET_TIME_STAMP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_TIME_STAMP\n");
break;
case OPC_OUB_SAS_HW_EVENT_ACK:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SAS_HW_EVENT_ACK\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SAS_HW_EVENT_ACK\n");
break;
case OPC_OUB_PORT_CONTROL:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_PORT_CONTROL\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_PORT_CONTROL\n");
break;
case OPC_OUB_SMP_ABORT_RSP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SMP_ABORT_RSP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SMP_ABORT_RSP\n");
pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GET_NVMD_DATA:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GET_NVMD_DATA\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_NVMD_DATA\n");
pm8001_mpi_get_nvmd_resp(pm8001_ha, piomb);
break;
case OPC_OUB_SET_NVMD_DATA:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SET_NVMD_DATA\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_NVMD_DATA\n");
pm8001_mpi_set_nvmd_resp(pm8001_ha, piomb);
break;
case OPC_OUB_DEVICE_HANDLE_REMOVAL:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_DEVICE_HANDLE_REMOVAL\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEVICE_HANDLE_REMOVAL\n");
break;
case OPC_OUB_SET_DEVICE_STATE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SET_DEVICE_STATE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_DEVICE_STATE\n");
pm8001_mpi_set_dev_state_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GET_DEVICE_STATE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GET_DEVICE_STATE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_DEVICE_STATE\n");
break;
case OPC_OUB_SET_DEV_INFO:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SET_DEV_INFO\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_DEV_INFO\n");
break;
case OPC_OUB_SAS_RE_INITIALIZE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SAS_RE_INITIALIZE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SAS_RE_INITIALIZE\n");
break;
default:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("Unknown outbound Queue IOMB OPC = %x\n",
- opc));
+ pm8001_dbg(pm8001_ha, DEVIO,
+ "Unknown outbound Queue IOMB OPC = %x\n",
+ opc);
break;
}
}
@@ -4172,7 +4018,7 @@
{
struct outbound_queue_table *circularQ;
void *pMsg1 = NULL;
- u8 uninitialized_var(bc);
+ u8 bc;
u32 ret = MPI_IO_STATUS_FAIL;
unsigned long flags;
@@ -4284,7 +4130,7 @@
cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_resp)-4);
build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
- (u32 *)&smp_cmd, 0);
+ &smp_cmd, sizeof(smp_cmd), 0);
if (rc)
goto err_out_2;
@@ -4335,8 +4181,7 @@
/* fill in PRD (scatter/gather) table, if any */
if (task->num_scatter > 1) {
pm8001_chip_make_sg(task->scatter, ccb->n_elem, ccb->buf_prd);
- phys_addr = ccb->ccb_dma_handle +
- offsetof(struct pm8001_ccb_info, buf_prd[0]);
+ phys_addr = ccb->ccb_dma_handle;
ssp_cmd.addr_low = cpu_to_le32(lower_32_bits(phys_addr));
ssp_cmd.addr_high = cpu_to_le32(upper_32_bits(phys_addr));
ssp_cmd.esgl = cpu_to_le32(1<<31);
@@ -4352,7 +4197,8 @@
ssp_cmd.len = cpu_to_le32(task->total_xfer_len);
ssp_cmd.esgl = 0;
}
- ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, 0);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd,
+ sizeof(ssp_cmd), 0);
return ret;
}
@@ -4376,19 +4222,19 @@
circularQ = &pm8001_ha->inbnd_q_tbl[0];
if (task->data_dir == DMA_NONE) {
ATAP = 0x04; /* no data*/
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("no data\n"));
+ pm8001_dbg(pm8001_ha, IO, "no data\n");
} else if (likely(!task->ata_task.device_control_reg_update)) {
if (task->ata_task.dma_xfer) {
ATAP = 0x06; /* DMA */
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("DMA\n"));
+ pm8001_dbg(pm8001_ha, IO, "DMA\n");
} else {
ATAP = 0x05; /* PIO*/
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("PIO\n"));
+ pm8001_dbg(pm8001_ha, IO, "PIO\n");
}
if (task->ata_task.use_ncq &&
dev->sata_dev.class != ATA_DEV_ATAPI) {
ATAP = 0x07; /* FPDMA */
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n"));
+ pm8001_dbg(pm8001_ha, IO, "FPDMA\n");
}
}
if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) {
@@ -4408,8 +4254,7 @@
/* fill in PRD (scatter/gather) table, if any */
if (task->num_scatter > 1) {
pm8001_chip_make_sg(task->scatter, ccb->n_elem, ccb->buf_prd);
- phys_addr = ccb->ccb_dma_handle +
- offsetof(struct pm8001_ccb_info, buf_prd[0]);
+ phys_addr = ccb->ccb_dma_handle;
sata_cmd.addr_low = lower_32_bits(phys_addr);
sata_cmd.addr_high = upper_32_bits(phys_addr);
sata_cmd.esgl = cpu_to_le32(1 << 31);
@@ -4446,10 +4291,10 @@
SAS_TASK_STATE_ABORTED))) {
spin_unlock_irqrestore(&task->task_state_lock,
flags);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("task 0x%p resp 0x%x "
- " stat 0x%x but aborted by upper layer "
- "\n", task, ts->resp, ts->stat));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "task 0x%p resp 0x%x stat 0x%x but aborted by upper layer\n",
+ task, ts->resp,
+ ts->stat);
pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
} else {
spin_unlock_irqrestore(&task->task_state_lock,
@@ -4461,14 +4306,14 @@
}
}
- ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
+ sizeof(sata_cmd), 0);
return ret;
}
/**
* pm8001_chip_phy_start_req - start phy via PHY_START COMMAND
* @pm8001_ha: our hba card information.
- * @num: the inbound queue number
* @phy_id: the phy id which we wanted to start up.
*/
static int
@@ -4496,14 +4341,14 @@
memcpy(payload.sas_identify.sas_addr,
pm8001_ha->sas_addr, SAS_ADDR_SIZE);
payload.sas_identify.phy_id = phy_id;
- ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
+ sizeof(payload), 0);
return ret;
}
/**
* pm8001_chip_phy_stop_req - start phy via PHY_STOP COMMAND
* @pm8001_ha: our hba card information.
- * @num: the inbound queue number
* @phy_id: the phy id which we wanted to start up.
*/
static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
@@ -4518,11 +4363,12 @@
memset(&payload, 0, sizeof(payload));
payload.tag = cpu_to_le32(tag);
payload.phy_id = cpu_to_le32(phy_id);
- ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
+ sizeof(payload), 0);
return ret;
}
-/**
+/*
* see comments on pm8001_mpi_reg_resp.
*/
static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
@@ -4577,11 +4423,12 @@
cpu_to_le32(ITNT | (firstBurstSize * 0x10000));
memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
SAS_ADDR_SIZE);
- rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
return rc;
}
-/**
+/*
* see comments on pm8001_mpi_reg_resp.
*/
int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha,
@@ -4596,18 +4443,18 @@
memset(&payload, 0, sizeof(payload));
payload.tag = cpu_to_le32(1);
payload.device_id = cpu_to_le32(device_id);
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("unregister device device_id = %d\n", device_id));
- ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ pm8001_dbg(pm8001_ha, MSG, "unregister device device_id = %d\n",
+ device_id);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
return ret;
}
/**
* pm8001_chip_phy_ctl_req - support the local phy operation
* @pm8001_ha: our hba card information.
- * @num: the inbound queue number
- * @phy_id: the phy id which we wanted to operate
- * @phy_op:
+ * @phyId: the phy id which we wanted to operate
+ * @phy_op: the phy operation to request
*/
static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
u32 phyId, u32 phy_op)
@@ -4621,7 +4468,8 @@
payload.tag = cpu_to_le32(1);
payload.phyop_phyid =
cpu_to_le32(((phy_op & 0xff) << 8) | (phyId & 0x0F));
- ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
return ret;
}
@@ -4642,13 +4490,15 @@
/**
* pm8001_chip_isr - PM8001 isr handler.
* @pm8001_ha: our hba card information.
- * @irq: irq number.
- * @stat: stat.
+ * @vec: IRQ number
*/
static irqreturn_t
pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)
{
pm8001_chip_interrupt_disable(pm8001_ha, vec);
+ pm8001_dbg(pm8001_ha, DEVIO,
+ "irq vec %d, ODMR:0x%x\n",
+ vec, pm8001_cr32(pm8001_ha, 0, 0x30));
process_oq(pm8001_ha, vec);
pm8001_chip_interrupt_enable(pm8001_ha, vec);
return IRQ_HANDLED;
@@ -4672,23 +4522,21 @@
task_abort.device_id = cpu_to_le32(dev_id);
task_abort.tag = cpu_to_le32(cmd_tag);
}
- ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
+ sizeof(task_abort), 0);
return ret;
}
-/**
+/*
* pm8001_chip_abort_task - SAS abort task when error or exception happened.
- * @task: the task we wanted to aborted.
- * @flag: the abort flag.
*/
int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha,
struct pm8001_device *pm8001_dev, u8 flag, u32 task_tag, u32 cmd_tag)
{
u32 opc, device_id;
int rc = TMF_RESP_FUNC_FAILED;
- PM8001_EH_DBG(pm8001_ha,
- pm8001_printk("cmd_tag = %x, abort task tag = 0x%x",
- cmd_tag, task_tag));
+ pm8001_dbg(pm8001_ha, EH, "cmd_tag = %x, abort task tag = 0x%x\n",
+ cmd_tag, task_tag);
if (pm8001_dev->dev_type == SAS_END_DEVICE)
opc = OPC_INB_SSP_ABORT;
else if (pm8001_dev->dev_type == SAS_SATA_DEV)
@@ -4699,7 +4547,7 @@
rc = send_task_abort(pm8001_ha, opc, device_id, flag,
task_tag, cmd_tag);
if (rc != TMF_RESP_FUNC_COMPLETE)
- PM8001_EH_DBG(pm8001_ha, pm8001_printk("rc= %d\n", rc));
+ pm8001_dbg(pm8001_ha, EH, "rc= %d\n", rc);
return rc;
}
@@ -4729,7 +4577,8 @@
if (pm8001_ha->chip_id != chip_8001)
sspTMCmd.ds_ads_m = 0x08;
circularQ = &pm8001_ha->inbnd_q_tbl[0];
- ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd, 0);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd,
+ sizeof(sspTMCmd), 0);
return ret;
}
@@ -4751,7 +4600,7 @@
if (!fw_control_context)
return -ENOMEM;
fw_control_context->usrAddr = (u8 *)ioctl_payload->func_specific;
- fw_control_context->len = ioctl_payload->length;
+ fw_control_context->len = ioctl_payload->rd_length;
circularQ = &pm8001_ha->inbnd_q_tbl[0];
memset(&nvmd_req, 0, sizeof(nvmd_req));
rc = pm8001_tag_alloc(pm8001_ha, &tag);
@@ -4772,7 +4621,7 @@
nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | twi_addr << 16 |
twi_page_size << 8 | TWI_DEVICE);
- nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+ nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
nvmd_req.resp_addr_hi =
cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
nvmd_req.resp_addr_lo =
@@ -4781,7 +4630,7 @@
}
case C_SEEPROM: {
nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | C_SEEPROM);
- nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+ nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
nvmd_req.resp_addr_hi =
cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
nvmd_req.resp_addr_lo =
@@ -4790,7 +4639,7 @@
}
case VPD_FLASH: {
nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | VPD_FLASH);
- nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+ nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
nvmd_req.resp_addr_hi =
cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
nvmd_req.resp_addr_lo =
@@ -4799,7 +4648,7 @@
}
case EXPAN_ROM: {
nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | EXPAN_ROM);
- nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+ nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
nvmd_req.resp_addr_hi =
cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
nvmd_req.resp_addr_lo =
@@ -4808,7 +4657,7 @@
}
case IOP_RDUMP: {
nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | IOP_RDUMP);
- nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+ nvmd_req.resp_len = cpu_to_le32(ioctl_payload->rd_length);
nvmd_req.vpd_offset = cpu_to_le32(ioctl_payload->offset);
nvmd_req.resp_addr_hi =
cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
@@ -4819,7 +4668,8 @@
default:
break;
}
- rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req,
+ sizeof(nvmd_req), 0);
if (rc) {
kfree(fw_control_context);
pm8001_tag_free(pm8001_ha, tag);
@@ -4847,7 +4697,7 @@
circularQ = &pm8001_ha->inbnd_q_tbl[0];
memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr,
&ioctl_payload->func_specific,
- ioctl_payload->length);
+ ioctl_payload->wr_length);
memset(&nvmd_req, 0, sizeof(nvmd_req));
rc = pm8001_tag_alloc(pm8001_ha, &tag);
if (rc) {
@@ -4866,7 +4716,7 @@
nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98);
nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | twi_addr << 16 |
twi_page_size << 8 | TWI_DEVICE);
- nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+ nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length);
nvmd_req.resp_addr_hi =
cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
nvmd_req.resp_addr_lo =
@@ -4875,7 +4725,7 @@
}
case C_SEEPROM:
nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | C_SEEPROM);
- nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+ nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length);
nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98);
nvmd_req.resp_addr_hi =
cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
@@ -4884,7 +4734,7 @@
break;
case VPD_FLASH:
nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | VPD_FLASH);
- nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+ nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length);
nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98);
nvmd_req.resp_addr_hi =
cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
@@ -4893,7 +4743,7 @@
break;
case EXPAN_ROM:
nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | EXPAN_ROM);
- nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
+ nvmd_req.resp_len = cpu_to_le32(ioctl_payload->wr_length);
nvmd_req.reserved[0] = cpu_to_le32(0xFEDCBA98);
nvmd_req.resp_addr_hi =
cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
@@ -4903,7 +4753,8 @@
default:
break;
}
- rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req,
+ sizeof(nvmd_req), 0);
if (rc) {
kfree(fw_control_context);
pm8001_tag_free(pm8001_ha, tag);
@@ -4915,6 +4766,7 @@
* pm8001_chip_fw_flash_update_build - support the firmware update operation
* @pm8001_ha: our hba card information.
* @fw_flash_updata_info: firmware flash update param
+ * @tag: Tag to apply to the payload
*/
int
pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha,
@@ -4938,7 +4790,8 @@
cpu_to_le32(lower_32_bits(le64_to_cpu(info->sgl.addr)));
payload.sgl_addr_hi =
cpu_to_le32(upper_32_bits(le64_to_cpu(info->sgl.addr)));
- ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
return ret;
}
@@ -4960,6 +4813,9 @@
if (!fw_control_context)
return -ENOMEM;
fw_control = (struct fw_control_info *)&ioctl_payload->func_specific;
+ pm8001_dbg(pm8001_ha, DEVIO,
+ "dma fw_control context input length :%x\n",
+ fw_control->len);
memcpy(buffer, fw_control->buffer, fw_control->len);
flash_update_info.sgl.addr = cpu_to_le64(phys_addr);
flash_update_info.sgl.im_len.len = cpu_to_le32(fw_control->len);
@@ -5083,7 +4939,8 @@
payload.tag = cpu_to_le32(tag);
payload.device_id = cpu_to_le32(pm8001_dev->device_id);
payload.nds = cpu_to_le32(state);
- rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
return rc;
}
@@ -5108,7 +4965,8 @@
payload.SSAHOLT = cpu_to_le32(0xd << 25);
payload.sata_hol_tmo = cpu_to_le32(80);
payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff);
- rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
if (rc)
pm8001_tag_free(pm8001_ha, tag);
return rc;
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 1f41537..01eb2ad 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -41,10 +41,24 @@
#include <linux/slab.h>
#include "pm8001_sas.h"
#include "pm8001_chips.h"
+#include "pm80xx_hwi.h"
+
+static ulong logging_level = PM8001_FAIL_LOGGING | PM8001_IOERR_LOGGING;
+module_param(logging_level, ulong, 0644);
+MODULE_PARM_DESC(logging_level, " bits for enabling logging info.");
+
+static ulong link_rate = LINKRATE_15 | LINKRATE_30 | LINKRATE_60 | LINKRATE_120;
+module_param(link_rate, ulong, 0644);
+MODULE_PARM_DESC(link_rate, "Enable link rate.\n"
+ " 1: Link rate 1.5G\n"
+ " 2: Link rate 3.0G\n"
+ " 4: Link rate 6.0G\n"
+ " 8: Link rate 12.0G\n");
static struct scsi_transport_template *pm8001_stt;
+static int pm8001_init_ccb_tag(struct pm8001_hba_info *, struct Scsi_Host *, struct pci_dev *);
-/**
+/*
* chip info structure to identify chip key functionality as
* encryption available/not, no of ports, hw specific function ref
*/
@@ -67,13 +81,14 @@
struct workqueue_struct *pm8001_wq;
-/**
+/*
* The main structure which LLDD must register for scsi core.
*/
static struct scsi_host_template pm8001_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
.queuecommand = sas_queuecommand,
+ .dma_need_drain = ata_scsi_dma_need_drain,
.target_alloc = sas_target_alloc,
.slave_configure = sas_slave_configure,
.scan_finished = pm8001_scan_finished,
@@ -82,18 +97,21 @@
.bios_param = sas_bios_param,
.can_queue = 1,
.this_id = -1,
- .sg_tablesize = SG_ALL,
+ .sg_tablesize = PM8001_MAX_DMA_SG,
.max_sectors = SCSI_DEFAULT_MAX_SECTORS,
.eh_device_reset_handler = sas_eh_device_reset_handler,
.eh_target_reset_handler = sas_eh_target_reset_handler,
.slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = sas_ioctl,
+#endif
.shost_attrs = pm8001_host_attrs,
.track_queue_depth = 1,
};
-/**
+/*
* Sas layer call this function to execute specific task.
*/
static struct sas_domain_function_template pm8001_transport_ops = {
@@ -113,9 +131,9 @@
};
/**
- *pm8001_phy_init - initiate our adapter phys
- *@pm8001_ha: our hba structure.
- *@phy_id: phy id.
+ * pm8001_phy_init - initiate our adapter phys
+ * @pm8001_ha: our hba structure.
+ * @phy_id: phy id.
*/
static void pm8001_phy_init(struct pm8001_hba_info *pm8001_ha, int phy_id)
{
@@ -139,9 +157,8 @@
}
/**
- *pm8001_free - free hba
- *@pm8001_ha: our hba structure.
- *
+ * pm8001_free - free hba
+ * @pm8001_ha: our hba structure.
*/
static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
{
@@ -189,6 +206,7 @@
* pm8001_interrupt_handler_msix - main MSIX interrupt handler.
* It obtains the vector number and calls the equivalent bottom
* half or services directly.
+ * @irq: interrupt number
* @opaque: the passed outbound queue/vector. Host structure is
* retrieved from the same.
*/
@@ -214,6 +232,7 @@
/**
* pm8001_interrupt_handler_intx - main INTx interrupt handler.
+ * @irq: interrupt number
* @dev_id: sas_ha structure. The HBA is retrieved from sas_has structure.
*/
@@ -236,20 +255,46 @@
return ret;
}
+static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha);
+static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha);
+
/**
* pm8001_alloc - initiate our hba structure and 6 DMAs area.
- * @pm8001_ha:our hba structure.
- *
+ * @pm8001_ha: our hba structure.
+ * @ent: PCI device ID structure to match on
*/
static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
const struct pci_device_id *ent)
{
- int i;
+ int i, count = 0, rc = 0;
+ u32 ci_offset, ib_offset, ob_offset, pi_offset;
+ struct inbound_queue_table *circularQ;
+
spin_lock_init(&pm8001_ha->lock);
spin_lock_init(&pm8001_ha->bitmap_lock);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("pm8001_alloc: PHY:%x\n",
- pm8001_ha->chip->n_phy));
+ pm8001_dbg(pm8001_ha, INIT, "pm8001_alloc: PHY:%x\n",
+ pm8001_ha->chip->n_phy);
+
+ /* Setup Interrupt */
+ rc = pm8001_setup_irq(pm8001_ha);
+ if (rc) {
+ pm8001_dbg(pm8001_ha, FAIL,
+ "pm8001_setup_irq failed [ret: %d]\n", rc);
+ goto err_out;
+ }
+ /* Request Interrupt */
+ rc = pm8001_request_irq(pm8001_ha);
+ if (rc)
+ goto err_out;
+
+ count = pm8001_ha->max_q_num;
+ /* Queues are chosen based on the number of cores/msix availability */
+ ib_offset = pm8001_ha->ib_offset = USI_MAX_MEMCNT_BASE;
+ ci_offset = pm8001_ha->ci_offset = ib_offset + count;
+ ob_offset = pm8001_ha->ob_offset = ci_offset + count;
+ pi_offset = pm8001_ha->pi_offset = ob_offset + count;
+ pm8001_ha->max_memcnt = pi_offset + count;
+
for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
pm8001_phy_init(pm8001_ha, i);
pm8001_ha->port[i].wide_port_phymap = 0;
@@ -258,9 +303,6 @@
INIT_LIST_HEAD(&pm8001_ha->port[i].list);
}
- pm8001_ha->tags = kzalloc(PM8001_MAX_CCB, GFP_KERNEL);
- if (!pm8001_ha->tags)
- goto err_out;
/* MPI Memory region 1 for AAP Event Log for fw */
pm8001_ha->memoryMap.region[AAP1].num_elements = 1;
pm8001_ha->memoryMap.region[AAP1].element_size = PM8001_EVENT_LOG_SIZE;
@@ -273,54 +315,62 @@
pm8001_ha->memoryMap.region[IOP].total_len = PM8001_EVENT_LOG_SIZE;
pm8001_ha->memoryMap.region[IOP].alignment = 32;
- for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) {
+ for (i = 0; i < count; i++) {
+ circularQ = &pm8001_ha->inbnd_q_tbl[i];
+ spin_lock_init(&circularQ->iq_lock);
/* MPI Memory region 3 for consumer Index of inbound queues */
- pm8001_ha->memoryMap.region[CI+i].num_elements = 1;
- pm8001_ha->memoryMap.region[CI+i].element_size = 4;
- pm8001_ha->memoryMap.region[CI+i].total_len = 4;
- pm8001_ha->memoryMap.region[CI+i].alignment = 4;
+ pm8001_ha->memoryMap.region[ci_offset+i].num_elements = 1;
+ pm8001_ha->memoryMap.region[ci_offset+i].element_size = 4;
+ pm8001_ha->memoryMap.region[ci_offset+i].total_len = 4;
+ pm8001_ha->memoryMap.region[ci_offset+i].alignment = 4;
if ((ent->driver_data) != chip_8001) {
/* MPI Memory region 5 inbound queues */
- pm8001_ha->memoryMap.region[IB+i].num_elements =
+ pm8001_ha->memoryMap.region[ib_offset+i].num_elements =
PM8001_MPI_QUEUE;
- pm8001_ha->memoryMap.region[IB+i].element_size = 128;
- pm8001_ha->memoryMap.region[IB+i].total_len =
+ pm8001_ha->memoryMap.region[ib_offset+i].element_size
+ = 128;
+ pm8001_ha->memoryMap.region[ib_offset+i].total_len =
PM8001_MPI_QUEUE * 128;
- pm8001_ha->memoryMap.region[IB+i].alignment = 128;
+ pm8001_ha->memoryMap.region[ib_offset+i].alignment
+ = 128;
} else {
- pm8001_ha->memoryMap.region[IB+i].num_elements =
+ pm8001_ha->memoryMap.region[ib_offset+i].num_elements =
PM8001_MPI_QUEUE;
- pm8001_ha->memoryMap.region[IB+i].element_size = 64;
- pm8001_ha->memoryMap.region[IB+i].total_len =
+ pm8001_ha->memoryMap.region[ib_offset+i].element_size
+ = 64;
+ pm8001_ha->memoryMap.region[ib_offset+i].total_len =
PM8001_MPI_QUEUE * 64;
- pm8001_ha->memoryMap.region[IB+i].alignment = 64;
+ pm8001_ha->memoryMap.region[ib_offset+i].alignment = 64;
}
}
- for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
+ for (i = 0; i < count; i++) {
/* MPI Memory region 4 for producer Index of outbound queues */
- pm8001_ha->memoryMap.region[PI+i].num_elements = 1;
- pm8001_ha->memoryMap.region[PI+i].element_size = 4;
- pm8001_ha->memoryMap.region[PI+i].total_len = 4;
- pm8001_ha->memoryMap.region[PI+i].alignment = 4;
+ pm8001_ha->memoryMap.region[pi_offset+i].num_elements = 1;
+ pm8001_ha->memoryMap.region[pi_offset+i].element_size = 4;
+ pm8001_ha->memoryMap.region[pi_offset+i].total_len = 4;
+ pm8001_ha->memoryMap.region[pi_offset+i].alignment = 4;
if (ent->driver_data != chip_8001) {
/* MPI Memory region 6 Outbound queues */
- pm8001_ha->memoryMap.region[OB+i].num_elements =
+ pm8001_ha->memoryMap.region[ob_offset+i].num_elements =
PM8001_MPI_QUEUE;
- pm8001_ha->memoryMap.region[OB+i].element_size = 128;
- pm8001_ha->memoryMap.region[OB+i].total_len =
+ pm8001_ha->memoryMap.region[ob_offset+i].element_size
+ = 128;
+ pm8001_ha->memoryMap.region[ob_offset+i].total_len =
PM8001_MPI_QUEUE * 128;
- pm8001_ha->memoryMap.region[OB+i].alignment = 128;
+ pm8001_ha->memoryMap.region[ob_offset+i].alignment
+ = 128;
} else {
/* MPI Memory region 6 Outbound queues */
- pm8001_ha->memoryMap.region[OB+i].num_elements =
+ pm8001_ha->memoryMap.region[ob_offset+i].num_elements =
PM8001_MPI_QUEUE;
- pm8001_ha->memoryMap.region[OB+i].element_size = 64;
- pm8001_ha->memoryMap.region[OB+i].total_len =
+ pm8001_ha->memoryMap.region[ob_offset+i].element_size
+ = 64;
+ pm8001_ha->memoryMap.region[ob_offset+i].total_len =
PM8001_MPI_QUEUE * 64;
- pm8001_ha->memoryMap.region[OB+i].alignment = 64;
+ pm8001_ha->memoryMap.region[ob_offset+i].alignment = 64;
}
}
@@ -328,19 +378,6 @@
pm8001_ha->memoryMap.region[NVMD].num_elements = 1;
pm8001_ha->memoryMap.region[NVMD].element_size = 4096;
pm8001_ha->memoryMap.region[NVMD].total_len = 4096;
- /* Memory region for devices*/
- pm8001_ha->memoryMap.region[DEV_MEM].num_elements = 1;
- pm8001_ha->memoryMap.region[DEV_MEM].element_size = PM8001_MAX_DEVICES *
- sizeof(struct pm8001_device);
- pm8001_ha->memoryMap.region[DEV_MEM].total_len = PM8001_MAX_DEVICES *
- sizeof(struct pm8001_device);
-
- /* Memory region for ccb_info*/
- pm8001_ha->memoryMap.region[CCB_MEM].num_elements = 1;
- pm8001_ha->memoryMap.region[CCB_MEM].element_size = PM8001_MAX_CCB *
- sizeof(struct pm8001_ccb_info);
- pm8001_ha->memoryMap.region[CCB_MEM].total_len = PM8001_MAX_CCB *
- sizeof(struct pm8001_ccb_info);
/* Memory region for fw flash */
pm8001_ha->memoryMap.region[FW_FLASH].total_len = 4096;
@@ -349,7 +386,7 @@
pm8001_ha->memoryMap.region[FORENSIC_MEM].total_len = 0x10000;
pm8001_ha->memoryMap.region[FORENSIC_MEM].element_size = 0x10000;
pm8001_ha->memoryMap.region[FORENSIC_MEM].alignment = 0x10000;
- for (i = 0; i < USI_MAX_MEMCNT; i++) {
+ for (i = 0; i < pm8001_ha->max_memcnt; i++) {
if (pm8001_mem_alloc(pm8001_ha->pdev,
&pm8001_ha->memoryMap.region[i].virt_ptr,
&pm8001_ha->memoryMap.region[i].phys_addr,
@@ -357,34 +394,41 @@
&pm8001_ha->memoryMap.region[i].phys_addr_lo,
pm8001_ha->memoryMap.region[i].total_len,
pm8001_ha->memoryMap.region[i].alignment) != 0) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Mem%d alloc failed\n",
- i));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "Mem%d alloc failed\n",
+ i);
goto err_out;
}
}
- pm8001_ha->devices = pm8001_ha->memoryMap.region[DEV_MEM].virt_ptr;
+ /* Memory region for devices*/
+ pm8001_ha->devices = kzalloc(PM8001_MAX_DEVICES
+ * sizeof(struct pm8001_device), GFP_KERNEL);
+ if (!pm8001_ha->devices) {
+ rc = -ENOMEM;
+ goto err_out_nodev;
+ }
for (i = 0; i < PM8001_MAX_DEVICES; i++) {
pm8001_ha->devices[i].dev_type = SAS_PHY_UNUSED;
pm8001_ha->devices[i].id = i;
pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES;
- pm8001_ha->devices[i].running_req = 0;
- }
- pm8001_ha->ccb_info = pm8001_ha->memoryMap.region[CCB_MEM].virt_ptr;
- for (i = 0; i < PM8001_MAX_CCB; i++) {
- pm8001_ha->ccb_info[i].ccb_dma_handle =
- pm8001_ha->memoryMap.region[CCB_MEM].phys_addr +
- i * sizeof(struct pm8001_ccb_info);
- pm8001_ha->ccb_info[i].task = NULL;
- pm8001_ha->ccb_info[i].ccb_tag = 0xffffffff;
- pm8001_ha->ccb_info[i].device = NULL;
- ++pm8001_ha->tags_num;
+ atomic_set(&pm8001_ha->devices[i].running_req, 0);
}
pm8001_ha->flags = PM8001F_INIT_TIME;
/* Initialize tags */
pm8001_tag_init(pm8001_ha);
return 0;
+
+err_out_nodev:
+ for (i = 0; i < pm8001_ha->max_memcnt; i++) {
+ if (pm8001_ha->memoryMap.region[i].virt_ptr != NULL) {
+ pci_free_consistent(pm8001_ha->pdev,
+ (pm8001_ha->memoryMap.region[i].total_len +
+ pm8001_ha->memoryMap.region[i].alignment),
+ pm8001_ha->memoryMap.region[i].virt_ptr,
+ pm8001_ha->memoryMap.region[i].phys_addr);
+ }
+ }
err_out:
return 1;
}
@@ -402,7 +446,7 @@
pdev = pm8001_ha->pdev;
/* map pci mem (PMC pci base 0-3)*/
- for (bar = 0; bar < 6; bar++) {
+ for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
/*
** logical BARs for SPC:
** bar 0 and 1 - logical BAR0
@@ -421,19 +465,19 @@
pm8001_ha->io_mem[logicalBar].memvirtaddr =
ioremap(pm8001_ha->io_mem[logicalBar].membase,
pm8001_ha->io_mem[logicalBar].memsize);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("PCI: bar %d, logicalBar %d ",
- bar, logicalBar));
- PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
- "base addr %llx virt_addr=%llx len=%d\n",
- (u64)pm8001_ha->io_mem[logicalBar].membase,
- (u64)(unsigned long)
- pm8001_ha->io_mem[logicalBar].memvirtaddr,
- pm8001_ha->io_mem[logicalBar].memsize));
+ pm8001_dbg(pm8001_ha, INIT,
+ "PCI: bar %d, logicalBar %d\n",
+ bar, logicalBar);
+ pm8001_dbg(pm8001_ha, INIT,
+ "base addr %llx virt_addr=%llx len=%d\n",
+ (u64)pm8001_ha->io_mem[logicalBar].membase,
+ (u64)(unsigned long)
+ pm8001_ha->io_mem[logicalBar].memvirtaddr,
+ pm8001_ha->io_mem[logicalBar].memsize);
} else {
pm8001_ha->io_mem[logicalBar].membase = 0;
pm8001_ha->io_mem[logicalBar].memsize = 0;
- pm8001_ha->io_mem[logicalBar].memvirtaddr = 0;
+ pm8001_ha->io_mem[logicalBar].memvirtaddr = NULL;
}
logicalBar++;
}
@@ -467,7 +511,16 @@
pm8001_ha->sas = sha;
pm8001_ha->shost = shost;
pm8001_ha->id = pm8001_id++;
- pm8001_ha->logging_level = 0x01;
+ pm8001_ha->logging_level = logging_level;
+ pm8001_ha->non_fatal_count = 0;
+ if (link_rate >= 1 && link_rate <= 15)
+ pm8001_ha->link_rate = (link_rate << 8);
+ else {
+ pm8001_ha->link_rate = LINKRATE_15 | LINKRATE_30 |
+ LINKRATE_60 | LINKRATE_120;
+ pm8001_dbg(pm8001_ha, FAIL,
+ "Setting link rate to default value\n");
+ }
sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id);
/* IOMB size is 128 for 8088/89 controllers */
if (pm8001_ha->chip_id != chip_8001)
@@ -587,7 +640,7 @@
/**
* pm8001_init_sas_add - initialize sas address
- * @chip_info: our ha struct.
+ * @pm8001_ha: our ha struct.
*
* Currently we just set the fixed SAS address to our HBA,for manufacture,
* it should read from the EEPROM
@@ -612,30 +665,30 @@
if (pm8001_ha->chip_id == chip_8001) {
if (deviceid == 0x8081 || deviceid == 0x0042) {
payload.minor_function = 4;
- payload.length = 4096;
+ payload.rd_length = 4096;
} else {
payload.minor_function = 0;
- payload.length = 128;
+ payload.rd_length = 128;
}
} else if ((pm8001_ha->chip_id == chip_8070 ||
pm8001_ha->chip_id == chip_8072) &&
pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ATTO) {
payload.minor_function = 4;
- payload.length = 4096;
+ payload.rd_length = 4096;
} else {
payload.minor_function = 1;
- payload.length = 4096;
+ payload.rd_length = 4096;
}
payload.offset = 0;
- payload.func_specific = kzalloc(payload.length, GFP_KERNEL);
+ payload.func_specific = kzalloc(payload.rd_length, GFP_KERNEL);
if (!payload.func_specific) {
- PM8001_INIT_DBG(pm8001_ha, pm8001_printk("mem alloc fail\n"));
+ pm8001_dbg(pm8001_ha, INIT, "mem alloc fail\n");
return;
}
rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
if (rc) {
kfree(payload.func_specific);
- PM8001_INIT_DBG(pm8001_ha, pm8001_printk("nvmd failed\n"));
+ pm8001_dbg(pm8001_ha, INIT, "nvmd failed\n");
return;
}
wait_for_completion(&completion);
@@ -663,9 +716,8 @@
sas_add[7] = sas_add[7] + 4;
memcpy(&pm8001_ha->phy[i].dev_sas_addr,
sas_add, SAS_ADDR_SIZE);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("phy %d sas_addr = %016llx\n", i,
- pm8001_ha->phy[i].dev_sas_addr));
+ pm8001_dbg(pm8001_ha, INIT, "phy %d sas_addr = %016llx\n", i,
+ pm8001_ha->phy[i].dev_sas_addr);
}
kfree(payload.func_specific);
#else
@@ -697,7 +749,7 @@
/* SAS ADDRESS read from flash / EEPROM */
payload.minor_function = 6;
payload.offset = 0;
- payload.length = 4096;
+ payload.rd_length = 4096;
payload.func_specific = kzalloc(4096, GFP_KERNEL);
if (!payload.func_specific)
return -ENOMEM;
@@ -705,7 +757,7 @@
rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
if (rc) {
kfree(payload.func_specific);
- PM8001_INIT_DBG(pm8001_ha, pm8001_printk("nvmd failed\n"));
+ pm8001_dbg(pm8001_ha, INIT, "nvmd failed\n");
return -ENOMEM;
}
wait_for_completion(&completion);
@@ -799,9 +851,9 @@
break;
default:
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Unknown subsystem device=0x%.04x",
- pm8001_ha->pdev->subsystem_device));
+ pm8001_dbg(pm8001_ha, INIT,
+ "Unknown subsystem device=0x%.04x\n",
+ pm8001_ha->pdev->subsystem_device);
}
}
@@ -865,44 +917,65 @@
#ifdef PM8001_USE_MSIX
/**
* pm8001_setup_msix - enable MSI-X interrupt
- * @chip_info: our ha struct.
- * @irq_handler: irq_handler
+ * @pm8001_ha: our ha struct.
*/
static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha)
{
- u32 i = 0, j = 0;
u32 number_of_intr;
- int flag = 0;
- int rc;
- static char intr_drvname[PM8001_MAX_MSIX_VEC][sizeof(DRV_NAME)+3];
+ int rc, cpu_online_count;
+ unsigned int allocated_irq_vectors;
/* SPCv controllers supports 64 msi-x */
if (pm8001_ha->chip_id == chip_8001) {
number_of_intr = 1;
} else {
number_of_intr = PM8001_MAX_MSIX_VEC;
- flag &= ~IRQF_SHARED;
}
+ cpu_online_count = num_online_cpus();
+ number_of_intr = min_t(int, cpu_online_count, number_of_intr);
rc = pci_alloc_irq_vectors(pm8001_ha->pdev, number_of_intr,
number_of_intr, PCI_IRQ_MSIX);
+ allocated_irq_vectors = rc;
if (rc < 0)
return rc;
+
+ /* Assigns the number of interrupts */
+ number_of_intr = min_t(int, allocated_irq_vectors, number_of_intr);
pm8001_ha->number_of_intr = number_of_intr;
- PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
- "pci_alloc_irq_vectors request ret:%d no of intr %d\n",
- rc, pm8001_ha->number_of_intr));
+ /* Maximum queue number updating in HBA structure */
+ pm8001_ha->max_q_num = number_of_intr;
- for (i = 0; i < number_of_intr; i++) {
- snprintf(intr_drvname[i], sizeof(intr_drvname[0]),
- DRV_NAME"%d", i);
+ pm8001_dbg(pm8001_ha, INIT,
+ "pci_alloc_irq_vectors request ret:%d no of intr %d\n",
+ rc, pm8001_ha->number_of_intr);
+ return 0;
+}
+
+static u32 pm8001_request_msix(struct pm8001_hba_info *pm8001_ha)
+{
+ u32 i = 0, j = 0;
+ int flag = 0, rc = 0;
+
+ if (pm8001_ha->chip_id != chip_8001)
+ flag &= ~IRQF_SHARED;
+
+ pm8001_dbg(pm8001_ha, INIT,
+ "pci_enable_msix request number of intr %d\n",
+ pm8001_ha->number_of_intr);
+
+ for (i = 0; i < pm8001_ha->number_of_intr; i++) {
+ snprintf(pm8001_ha->intr_drvname[i],
+ sizeof(pm8001_ha->intr_drvname[0]),
+ "%s-%d", pm8001_ha->name, i);
pm8001_ha->irq_vector[i].irq_id = i;
pm8001_ha->irq_vector[i].drv_inst = pm8001_ha;
rc = request_irq(pci_irq_vector(pm8001_ha->pdev, i),
pm8001_interrupt_handler_msix, flag,
- intr_drvname[i], &(pm8001_ha->irq_vector[i]));
+ pm8001_ha->intr_drvname[i],
+ &(pm8001_ha->irq_vector[i]));
if (rc) {
for (j = 0; j < i; j++) {
free_irq(pci_irq_vector(pm8001_ha->pdev, i),
@@ -917,9 +990,23 @@
}
#endif
+static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha)
+{
+ struct pci_dev *pdev;
+
+ pdev = pm8001_ha->pdev;
+
+#ifdef PM8001_USE_MSIX
+ if (pci_find_capability(pdev, PCI_CAP_ID_MSIX))
+ return pm8001_setup_msix(pm8001_ha);
+ pm8001_dbg(pm8001_ha, INIT, "MSIX not supported!!!\n");
+#endif
+ return 0;
+}
+
/**
* pm8001_request_irq - register interrupt
- * @chip_info: our ha struct.
+ * @pm8001_ha: our ha struct.
*/
static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha)
{
@@ -930,10 +1017,9 @@
#ifdef PM8001_USE_MSIX
if (pdev->msix_cap && pci_msi_enabled())
- return pm8001_setup_msix(pm8001_ha);
+ return pm8001_request_msix(pm8001_ha);
else {
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("MSIX not supported!!!\n"));
+ pm8001_dbg(pm8001_ha, INIT, "MSIX not supported!!!\n");
goto intx;
}
#endif
@@ -943,7 +1029,7 @@
pm8001_ha->irq_vector[0].irq_id = 0;
pm8001_ha->irq_vector[0].drv_inst = pm8001_ha;
rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED,
- DRV_NAME, SHOST_TO_SAS_HA(pm8001_ha->shost));
+ pm8001_ha->name, SHOST_TO_SAS_HA(pm8001_ha->shost));
return rc;
}
@@ -965,6 +1051,7 @@
struct pm8001_hba_info *pm8001_ha;
struct Scsi_Host *shost = NULL;
const struct pm8001_chip_info *chip;
+ struct sas_ha_struct *sha;
dev_printk(KERN_INFO, &pdev->dev,
"pm80xx: driver version %s\n", DRV_VERSION);
@@ -993,12 +1080,12 @@
goto err_out_regions;
}
chip = &pm8001_chips[ent->driver_data];
- SHOST_TO_SAS_HA(shost) =
- kzalloc(sizeof(struct sas_ha_struct), GFP_KERNEL);
- if (!SHOST_TO_SAS_HA(shost)) {
+ sha = kzalloc(sizeof(struct sas_ha_struct), GFP_KERNEL);
+ if (!sha) {
rc = -ENOMEM;
goto err_out_free_host;
}
+ SHOST_TO_SAS_HA(shost) = sha;
rc = pm8001_prep_sas_ha_init(shost, chip);
if (rc) {
@@ -1012,24 +1099,22 @@
rc = -ENOMEM;
goto err_out_free;
}
- list_add_tail(&pm8001_ha->list, &hba_list);
+
PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
if (rc) {
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
- "chip_init failed [ret: %d]\n", rc));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "chip_init failed [ret: %d]\n", rc);
goto err_out_ha_free;
}
+ rc = pm8001_init_ccb_tag(pm8001_ha, shost, pdev);
+ if (rc)
+ goto err_out_enable;
+
rc = scsi_add_host(shost, &pdev->dev);
if (rc)
goto err_out_ha_free;
- rc = pm8001_request_irq(pm8001_ha);
- if (rc) {
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
- "pm8001_request_irq failed [ret: %d]\n", rc));
- goto err_out_shost;
- }
PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0);
if (pm8001_ha->chip_id != chip_8001) {
@@ -1047,10 +1132,14 @@
pm8001_post_sas_ha_init(shost, chip);
rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
- if (rc)
+ if (rc) {
+ pm8001_dbg(pm8001_ha, FAIL,
+ "sas_register_ha failed [ret: %d]\n", rc);
goto err_out_shost;
- scsi_scan_host(pm8001_ha->shost);
+ }
+ list_add_tail(&pm8001_ha->list, &hba_list);
pm8001_ha->flags = PM8001F_RUN_TIME;
+ scsi_scan_host(pm8001_ha->shost);
return 0;
err_out_shost:
@@ -1058,7 +1147,7 @@
err_out_ha_free:
pm8001_free(pm8001_ha);
err_out_free:
- kfree(SHOST_TO_SAS_HA(shost));
+ kfree(sha);
err_out_free_host:
scsi_host_put(shost);
err_out_regions:
@@ -1069,6 +1158,60 @@
return rc;
}
+/*
+ * pm8001_init_ccb_tag - allocate memory to CCB and tag.
+ * @pm8001_ha: our hba card information.
+ * @shost: scsi host which has been allocated outside.
+ */
+static int
+pm8001_init_ccb_tag(struct pm8001_hba_info *pm8001_ha, struct Scsi_Host *shost,
+ struct pci_dev *pdev)
+{
+ int i = 0;
+ u32 max_out_io, ccb_count;
+ u32 can_queue;
+
+ max_out_io = pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io;
+ ccb_count = min_t(int, PM8001_MAX_CCB, max_out_io);
+
+ /* Update to the scsi host*/
+ can_queue = ccb_count - PM8001_RESERVE_SLOT;
+ shost->can_queue = can_queue;
+
+ pm8001_ha->tags = kzalloc(ccb_count, GFP_KERNEL);
+ if (!pm8001_ha->tags)
+ goto err_out;
+
+ /* Memory region for ccb_info*/
+ pm8001_ha->ccb_info = (struct pm8001_ccb_info *)
+ kcalloc(ccb_count, sizeof(struct pm8001_ccb_info), GFP_KERNEL);
+ if (!pm8001_ha->ccb_info) {
+ pm8001_dbg(pm8001_ha, FAIL,
+ "Unable to allocate memory for ccb\n");
+ goto err_out_noccb;
+ }
+ for (i = 0; i < ccb_count; i++) {
+ pm8001_ha->ccb_info[i].buf_prd = pci_alloc_consistent(pdev,
+ sizeof(struct pm8001_prd) * PM8001_MAX_DMA_SG,
+ &pm8001_ha->ccb_info[i].ccb_dma_handle);
+ if (!pm8001_ha->ccb_info[i].buf_prd) {
+ pm8001_dbg(pm8001_ha, FAIL,
+ "pm80xx: ccb prd memory allocation error\n");
+ goto err_out;
+ }
+ pm8001_ha->ccb_info[i].task = NULL;
+ pm8001_ha->ccb_info[i].ccb_tag = 0xffffffff;
+ pm8001_ha->ccb_info[i].device = NULL;
+ ++pm8001_ha->tags_num;
+ }
+ return 0;
+
+err_out_noccb:
+ kfree(pm8001_ha->devices);
+err_out:
+ return -ENOMEM;
+}
+
static void pm8001_pci_remove(struct pci_dev *pdev)
{
struct sas_ha_struct *sha = pci_get_drvdata(pdev);
@@ -1197,8 +1340,7 @@
/* chip soft rst only for spc */
if (pm8001_ha->chip_id == chip_8001) {
PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("chip soft reset successful\n"));
+ pm8001_dbg(pm8001_ha, INIT, "chip soft reset successful\n");
}
rc = PM8001_CHIP_DISP->chip_init(pm8001_ha);
if (rc)
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 36f5bab..75ac4d8 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -119,7 +119,7 @@
mem_virt_alloc = dma_alloc_coherent(&pdev->dev, mem_size + align,
&mem_dma_handle, GFP_KERNEL);
if (!mem_virt_alloc) {
- pm8001_printk("memory allocation error\n");
+ pr_err("pm80xx: memory allocation error\n");
return -1;
}
*pphys_addr = mem_dma_handle;
@@ -129,6 +129,7 @@
*pphys_addr_lo = lower_32_bits(phys_align);
return 0;
}
+
/**
* pm8001_find_ha_by_dev - from domain device which come from sas layer to
* find out our hba struct.
@@ -157,7 +158,6 @@
int rc = 0, phy_id = sas_phy->id;
struct pm8001_hba_info *pm8001_ha = NULL;
struct sas_phy_linkrates *rates;
- struct sas_ha_struct *sas_ha;
struct pm8001_phy *phy;
DECLARE_COMPLETION_ONSTACK(completion);
unsigned long flags;
@@ -206,18 +206,16 @@
if (pm8001_ha->chip_id != chip_8001) {
if (pm8001_ha->phy[phy_id].phy_state ==
PHY_STATE_LINK_UP_SPCV) {
- sas_ha = pm8001_ha->sas;
sas_phy_disconnected(&phy->sas_phy);
- sas_ha->notify_phy_event(&phy->sas_phy,
+ sas_notify_phy_event(&phy->sas_phy,
PHYE_LOSS_OF_SIGNAL);
phy->phy_attached = 0;
}
} else {
if (pm8001_ha->phy[phy_id].phy_state ==
PHY_STATE_LINK_UP_SPC) {
- sas_ha = pm8001_ha->sas;
sas_phy_disconnected(&phy->sas_phy);
- sas_ha->notify_phy_event(&phy->sas_phy,
+ sas_notify_phy_event(&phy->sas_phy,
PHYE_LOSS_OF_SIGNAL);
phy->phy_attached = 0;
}
@@ -249,6 +247,7 @@
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
return 0;
default:
+ pm8001_dbg(pm8001_ha, DEVIO, "func 0x%x\n", func);
rc = -EOPNOTSUPP;
}
msleep(300);
@@ -265,12 +264,17 @@
int i;
struct pm8001_hba_info *pm8001_ha;
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+ DECLARE_COMPLETION_ONSTACK(completion);
pm8001_ha = sha->lldd_ha;
/* SAS_RE_INITIALIZATION not available in SPCv/ve */
if (pm8001_ha->chip_id == chip_8001)
PM8001_CHIP_DISP->sas_re_init_req(pm8001_ha);
- for (i = 0; i < pm8001_ha->chip->n_phy; ++i)
+ for (i = 0; i < pm8001_ha->chip->n_phy; ++i) {
+ pm8001_ha->phy[i].enable_completion = &completion;
PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i);
+ wait_for_completion(&completion);
+ msleep(300);
+ }
}
int pm8001_scan_finished(struct Scsi_Host *shost, unsigned long time)
@@ -364,17 +368,15 @@
return 0;
}
+#define DEV_IS_GONE(pm8001_dev) \
+ ((!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED)))
/**
* pm8001_task_exec - queue the task(ssp, smp && ata) to the hardware.
* @task: the task to be execute.
- * @num: if can_queue great than 1, the task can be queued up. for SMP task,
- * we always execute one one time.
* @gfp_flags: gfp_flags.
* @is_tmf: if it is task management task.
* @tmf: the task management IU
*/
-#define DEV_IS_GONE(pm8001_dev) \
- ((!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED)))
static int pm8001_task_exec(struct sas_task *task,
gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf)
{
@@ -384,8 +386,9 @@
struct pm8001_port *port = NULL;
struct sas_task *t = task;
struct pm8001_ccb_info *ccb;
- u32 tag = 0xdeadbeef, rc, n_elem = 0;
+ u32 tag = 0xdeadbeef, rc = 0, n_elem = 0;
unsigned long flags = 0;
+ enum sas_protocol task_proto = t->task_proto;
if (!dev->port) {
struct task_status_struct *tsm = &t->task_status;
@@ -403,14 +406,14 @@
t->task_done(t);
return 0;
}
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("pm8001_task_exec device \n "));
+ pm8001_dbg(pm8001_ha, IO, "pm8001_task_exec device\n");
spin_lock_irqsave(&pm8001_ha->lock, flags);
do {
dev = t->dev;
pm8001_dev = dev->lldd_dev;
port = &pm8001_ha->port[sas_find_local_port_id(dev)];
if (DEV_IS_GONE(pm8001_dev) || !port->port_attached) {
- if (sas_protocol_ata(t->task_proto)) {
+ if (sas_protocol_ata(task_proto)) {
struct task_status_struct *ts = &t->task_status;
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_PHY_DOWN;
@@ -432,7 +435,7 @@
goto err_out;
ccb = &pm8001_ha->ccb_info[tag];
- if (!sas_protocol_ata(t->task_proto)) {
+ if (!sas_protocol_ata(task_proto)) {
if (t->num_scatter) {
n_elem = dma_map_sg(pm8001_ha->dev,
t->scatter,
@@ -452,11 +455,13 @@
ccb->ccb_tag = tag;
ccb->task = t;
ccb->device = pm8001_dev;
- switch (t->task_proto) {
+ switch (task_proto) {
case SAS_PROTOCOL_SMP:
+ atomic_inc(&pm8001_dev->running_req);
rc = pm8001_task_prep_smp(pm8001_ha, ccb);
break;
case SAS_PROTOCOL_SSP:
+ atomic_inc(&pm8001_dev->running_req);
if (is_tmf)
rc = pm8001_task_prep_ssp_tm(pm8001_ha,
ccb, tmf);
@@ -465,26 +470,25 @@
break;
case SAS_PROTOCOL_SATA:
case SAS_PROTOCOL_STP:
+ atomic_inc(&pm8001_dev->running_req);
rc = pm8001_task_prep_ata(pm8001_ha, ccb);
break;
default:
dev_printk(KERN_ERR, pm8001_ha->dev,
- "unknown sas_task proto: 0x%x\n",
- t->task_proto);
+ "unknown sas_task proto: 0x%x\n", task_proto);
rc = -EINVAL;
break;
}
if (rc) {
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("rc is %x\n", rc));
+ pm8001_dbg(pm8001_ha, IO, "rc is %x\n", rc);
+ atomic_dec(&pm8001_dev->running_req);
goto err_out_tag;
}
/* TODO: select normal or high priority */
spin_lock(&t->task_state_lock);
t->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock(&t->task_state_lock);
- pm8001_dev->running_req++;
} while (0);
rc = 0;
goto out_done;
@@ -493,7 +497,7 @@
pm8001_tag_free(pm8001_ha, tag);
err_out:
dev_printk(KERN_ERR, pm8001_ha->dev, "pm8001 exec failed[%d]!\n", rc);
- if (!sas_protocol_ata(t->task_proto))
+ if (!sas_protocol_ata(task_proto))
if (n_elem)
dma_unmap_sg(pm8001_ha->dev, t->scatter, t->num_scatter,
t->data_dir);
@@ -566,15 +570,16 @@
}
}
if (dev == PM8001_MAX_DEVICES) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("max support %d devices, ignore ..\n",
- PM8001_MAX_DEVICES));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "max support %d devices, ignore ..\n",
+ PM8001_MAX_DEVICES);
}
return NULL;
}
/**
* pm8001_find_dev - find a matching pm8001_device
* @pm8001_ha: our hba card information
+ * @device_id: device ID to match against
*/
struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha,
u32 device_id)
@@ -585,8 +590,7 @@
return &pm8001_ha->devices[dev];
}
if (dev == PM8001_MAX_DEVICES) {
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("NO MATCHING "
- "DEVICE FOUND !!!\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "NO MATCHING DEVICE FOUND !!!\n");
}
return NULL;
}
@@ -647,10 +651,10 @@
}
}
if (phy_id == parent_dev->ex_dev.num_phys) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Error: no attached dev:%016llx"
- " at ex:%016llx.\n", SAS_ADDR(dev->sas_addr),
- SAS_ADDR(parent_dev->sas_addr)));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "Error: no attached dev:%016llx at ex:%016llx.\n",
+ SAS_ADDR(dev->sas_addr),
+ SAS_ADDR(parent_dev->sas_addr));
res = -1;
}
} else {
@@ -660,7 +664,7 @@
flag = 1; /* directly sata */
}
} /*register this device to HBA*/
- PM8001_DISC_DBG(pm8001_ha, pm8001_printk("Found device\n"));
+ pm8001_dbg(pm8001_ha, DISC, "Found device\n");
PM8001_CHIP_DISP->reg_dev_req(pm8001_ha, pm8001_device, flag);
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
wait_for_completion(&completion);
@@ -680,8 +684,7 @@
void pm8001_task_done(struct sas_task *task)
{
- if (!del_timer(&task->slow_task->timer))
- return;
+ del_timer(&task->slow_task->timer);
complete(&task->slow_task->completion);
}
@@ -689,9 +692,14 @@
{
struct sas_task_slow *slow = from_timer(slow, t, timer);
struct sas_task *task = slow->task;
+ unsigned long flags;
- task->task_state_flags |= SAS_TASK_STATE_ABORTED;
- complete(&task->slow_task->completion);
+ spin_lock_irqsave(&task->task_state_lock, flags);
+ if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
+ task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+ complete(&task->slow_task->completion);
+ }
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
}
#define PM8001_TASK_TIMEOUT 20
@@ -732,9 +740,7 @@
if (res) {
del_timer(&task->slow_task->timer);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Executing internal task "
- "failed\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "Executing internal task failed\n");
goto ex_err;
}
wait_for_completion(&task->slow_task->completion);
@@ -746,13 +752,15 @@
}
res = -TMF_RESP_FUNC_FAILED;
/* Even TMF timed out, return direct. */
- if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
- if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("TMF task[%x]timeout.\n",
- tmf->tmf));
- goto ex_err;
- }
+ if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
+ struct pm8001_ccb_info *ccb = task->lldd_task;
+
+ pm8001_dbg(pm8001_ha, FAIL, "TMF task[%x]timeout.\n",
+ tmf->tmf);
+
+ if (ccb)
+ ccb->task = NULL;
+ goto ex_err;
}
if (task->task_status.resp == SAS_TASK_COMPLETE &&
@@ -771,17 +779,15 @@
if (task->task_status.resp == SAS_TASK_COMPLETE &&
task->task_status.stat == SAS_DATA_OVERRUN) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Blocked task error.\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "Blocked task error.\n");
res = -EMSGSIZE;
break;
} else {
- PM8001_EH_DBG(pm8001_ha,
- pm8001_printk(" Task to dev %016llx response:"
- "0x%x status 0x%x\n",
- SAS_ADDR(dev->sas_addr),
- task->task_status.resp,
- task->task_status.stat));
+ pm8001_dbg(pm8001_ha, EH,
+ " Task to dev %016llx response:0x%x status 0x%x\n",
+ SAS_ADDR(dev->sas_addr),
+ task->task_status.resp,
+ task->task_status.stat);
sas_free_task(task);
task = NULL;
}
@@ -828,20 +834,15 @@
if (res) {
del_timer(&task->slow_task->timer);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Executing internal task "
- "failed\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "Executing internal task failed\n");
goto ex_err;
}
wait_for_completion(&task->slow_task->completion);
res = TMF_RESP_FUNC_FAILED;
/* Even TMF timed out, return direct. */
- if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
- if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("TMF task timeout.\n"));
- goto ex_err;
- }
+ if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
+ pm8001_dbg(pm8001_ha, FAIL, "TMF task timeout.\n");
+ goto ex_err;
}
if (task->task_status.resp == SAS_TASK_COMPLETE &&
@@ -850,12 +851,11 @@
break;
} else {
- PM8001_EH_DBG(pm8001_ha,
- pm8001_printk(" Task to dev %016llx response: "
- "0x%x status 0x%x\n",
- SAS_ADDR(dev->sas_addr),
- task->task_status.resp,
- task->task_status.stat));
+ pm8001_dbg(pm8001_ha, EH,
+ " Task to dev %016llx response: 0x%x status 0x%x\n",
+ SAS_ADDR(dev->sas_addr),
+ task->task_status.resp,
+ task->task_status.stat);
sas_free_task(task);
task = NULL;
}
@@ -881,22 +881,20 @@
if (pm8001_dev) {
u32 device_id = pm8001_dev->device_id;
- PM8001_DISC_DBG(pm8001_ha,
- pm8001_printk("found dev[%d:%x] is gone.\n",
- pm8001_dev->device_id, pm8001_dev->dev_type));
- if (pm8001_dev->running_req) {
+ pm8001_dbg(pm8001_ha, DISC, "found dev[%d:%x] is gone.\n",
+ pm8001_dev->device_id, pm8001_dev->dev_type);
+ if (atomic_read(&pm8001_dev->running_req)) {
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
dev, 1, 0);
- while (pm8001_dev->running_req)
+ while (atomic_read(&pm8001_dev->running_req))
msleep(20);
spin_lock_irqsave(&pm8001_ha->lock, flags);
}
PM8001_CHIP_DISP->dereg_dev_req(pm8001_ha, device_id);
pm8001_free_dev(pm8001_dev);
} else {
- PM8001_DISC_DBG(pm8001_ha,
- pm8001_printk("Found dev has gone.\n"));
+ pm8001_dbg(pm8001_ha, DISC, "Found dev has gone.\n");
}
dev->lldd_dev = NULL;
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
@@ -966,7 +964,7 @@
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
spin_lock_irqsave(&task->task_state_lock, flags1);
task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
@@ -993,6 +991,7 @@
/**
* Standard mandates link reset for ATA (type 0) and hard reset for
* SSP (type 1) , only for RECOVERY
+ * @dev: the device structure for the device to reset.
*/
int pm8001_I_T_nexus_reset(struct domain_device *dev)
{
@@ -1015,9 +1014,9 @@
}
rc = sas_phy_reset(phy, 1);
if (rc) {
- PM8001_EH_DBG(pm8001_ha,
- pm8001_printk("phy reset failed for device %x\n"
- "with rc %d\n", pm8001_dev->device_id, rc));
+ pm8001_dbg(pm8001_ha, EH,
+ "phy reset failed for device %x\n"
+ "with rc %d\n", pm8001_dev->device_id, rc);
rc = TMF_RESP_FUNC_FAILED;
goto out;
}
@@ -1025,17 +1024,16 @@
rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
dev, 1, 0);
if (rc) {
- PM8001_EH_DBG(pm8001_ha,
- pm8001_printk("task abort failed %x\n"
- "with rc %d\n", pm8001_dev->device_id, rc));
+ pm8001_dbg(pm8001_ha, EH, "task abort failed %x\n"
+ "with rc %d\n", pm8001_dev->device_id, rc);
rc = TMF_RESP_FUNC_FAILED;
}
} else {
rc = sas_phy_reset(phy, 1);
msleep(2000);
}
- PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n",
- pm8001_dev->device_id, rc));
+ pm8001_dbg(pm8001_ha, EH, " for device[%x]:rc=%d\n",
+ pm8001_dev->device_id, rc);
out:
sas_put_local_phy(phy);
return rc;
@@ -1058,8 +1056,7 @@
pm8001_dev = dev->lldd_dev;
pm8001_ha = pm8001_find_ha_by_dev(dev);
- PM8001_EH_DBG(pm8001_ha,
- pm8001_printk("I_T_Nexus handler invoked !!"));
+ pm8001_dbg(pm8001_ha, EH, "I_T_Nexus handler invoked !!\n");
phy = sas_get_local_phy(dev);
@@ -1098,8 +1095,8 @@
rc = sas_phy_reset(phy, 1);
msleep(2000);
}
- PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n",
- pm8001_dev->device_id, rc));
+ pm8001_dbg(pm8001_ha, EH, " for device[%x]:rc=%d\n",
+ pm8001_dev->device_id, rc);
out:
sas_put_local_phy(phy);
@@ -1128,8 +1125,8 @@
rc = pm8001_issue_ssp_tmf(dev, lun, &tmf_task);
}
/* If failed, fall-through I_T_Nexus reset */
- PM8001_EH_DBG(pm8001_ha, pm8001_printk("for device[%x]:rc=%d\n",
- pm8001_dev->device_id, rc));
+ pm8001_dbg(pm8001_ha, EH, "for device[%x]:rc=%d\n",
+ pm8001_dev->device_id, rc);
return rc;
}
@@ -1137,7 +1134,6 @@
int pm8001_query_task(struct sas_task *task)
{
u32 tag = 0xdeadbeef;
- int i = 0;
struct scsi_lun lun;
struct pm8001_tmf_task tmf_task;
int rc = TMF_RESP_FUNC_FAILED;
@@ -1156,10 +1152,7 @@
rc = TMF_RESP_FUNC_FAILED;
return rc;
}
- PM8001_EH_DBG(pm8001_ha, pm8001_printk("Query:["));
- for (i = 0; i < 16; i++)
- printk(KERN_INFO "%02x ", cmnd->cmnd[i]);
- printk(KERN_INFO "]\n");
+ pm8001_dbg(pm8001_ha, EH, "Query:[%16ph]\n", cmnd->cmnd);
tmf_task.tmf = TMF_QUERY_TASK;
tmf_task.tag_of_task_to_be_managed = tag;
@@ -1167,19 +1160,18 @@
switch (rc) {
/* The task is still in Lun, release it then */
case TMF_RESP_FUNC_SUCC:
- PM8001_EH_DBG(pm8001_ha,
- pm8001_printk("The task is still in Lun\n"));
+ pm8001_dbg(pm8001_ha, EH,
+ "The task is still in Lun\n");
break;
/* The task is not in Lun or failed, reset the phy */
case TMF_RESP_FUNC_FAILED:
case TMF_RESP_FUNC_COMPLETE:
- PM8001_EH_DBG(pm8001_ha,
- pm8001_printk("The task is not in Lun or failed,"
- " reset the phy\n"));
+ pm8001_dbg(pm8001_ha, EH,
+ "The task is not in Lun or failed, reset the phy\n");
break;
}
}
- pm8001_printk(":rc= %d\n", rc);
+ pr_err("pm80xx: rc= %d\n", rc);
return rc;
}
@@ -1261,8 +1253,8 @@
* leaking the task in libsas or losing the race and
* getting a double free.
*/
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("Waiting for local phy ctl\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "Waiting for local phy ctl\n");
ret = wait_for_completion_timeout(&completion,
PM8001_TASK_TIMEOUT * HZ);
if (!ret || !phy->reset_success) {
@@ -1272,8 +1264,8 @@
/* 3. Wait for Port Reset complete or
* Port reset TMO
*/
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("Waiting for Port reset\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "Waiting for Port reset\n");
ret = wait_for_completion_timeout(
&completion_reset,
PM8001_TASK_TIMEOUT * HZ);
@@ -1352,9 +1344,8 @@
struct pm8001_device *pm8001_dev = dev->lldd_dev;
struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev);
- PM8001_EH_DBG(pm8001_ha,
- pm8001_printk("I_T_L_Q clear task set[%x]\n",
- pm8001_dev->device_id));
+ pm8001_dbg(pm8001_ha, EH, "I_T_L_Q clear task set[%x]\n",
+ pm8001_dev->device_id);
tmf_task.tmf = TMF_CLEAR_TASK_SET;
return pm8001_issue_ssp_tmf(dev, lun, &tmf_task);
}
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index ff17c6a..5cd6fe6 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -58,7 +58,7 @@
#include "pm8001_defs.h"
#define DRV_NAME "pm80xx"
-#define DRV_VERSION "0.1.39"
+#define DRV_VERSION "0.1.40"
#define PM8001_FAIL_LOGGING 0x01 /* Error message logging */
#define PM8001_INIT_LOGGING 0x02 /* driver init logging */
#define PM8001_DISC_LOGGING 0x04 /* discovery layer logging */
@@ -66,37 +66,19 @@
#define PM8001_EH_LOGGING 0x10 /* libsas EH function logging*/
#define PM8001_IOCTL_LOGGING 0x20 /* IOCTL message logging */
#define PM8001_MSG_LOGGING 0x40 /* misc message logging */
-#define pm8001_printk(format, arg...) printk(KERN_INFO "pm80xx %s %d:" \
- format, __func__, __LINE__, ## arg)
-#define PM8001_CHECK_LOGGING(HBA, LEVEL, CMD) \
-do { \
- if (unlikely(HBA->logging_level & LEVEL)) \
- do { \
- CMD; \
- } while (0); \
-} while (0);
+#define PM8001_DEV_LOGGING 0x80 /* development message logging */
+#define PM8001_DEVIO_LOGGING 0x100 /* development io message logging */
+#define PM8001_IOERR_LOGGING 0x200 /* development io err message logging */
-#define PM8001_EH_DBG(HBA, CMD) \
- PM8001_CHECK_LOGGING(HBA, PM8001_EH_LOGGING, CMD)
+#define pm8001_printk(fmt, ...) \
+ pr_info("%s:: %s %d:" fmt, \
+ pm8001_ha->name, __func__, __LINE__, ##__VA_ARGS__)
-#define PM8001_INIT_DBG(HBA, CMD) \
- PM8001_CHECK_LOGGING(HBA, PM8001_INIT_LOGGING, CMD)
-
-#define PM8001_DISC_DBG(HBA, CMD) \
- PM8001_CHECK_LOGGING(HBA, PM8001_DISC_LOGGING, CMD)
-
-#define PM8001_IO_DBG(HBA, CMD) \
- PM8001_CHECK_LOGGING(HBA, PM8001_IO_LOGGING, CMD)
-
-#define PM8001_FAIL_DBG(HBA, CMD) \
- PM8001_CHECK_LOGGING(HBA, PM8001_FAIL_LOGGING, CMD)
-
-#define PM8001_IOCTL_DBG(HBA, CMD) \
- PM8001_CHECK_LOGGING(HBA, PM8001_IOCTL_LOGGING, CMD)
-
-#define PM8001_MSG_DBG(HBA, CMD) \
- PM8001_CHECK_LOGGING(HBA, PM8001_MSG_LOGGING, CMD)
-
+#define pm8001_dbg(HBA, level, fmt, ...) \
+do { \
+ if (unlikely((HBA)->logging_level & PM8001_##level##_LOGGING)) \
+ pm8001_printk(fmt, ##__VA_ARGS__); \
+} while (0)
#define PM8001_USE_TASKLET
#define PM8001_USE_MSIX
@@ -126,10 +108,11 @@
u32 signature;
u16 major_function;
u16 minor_function;
- u16 length;
u16 status;
u16 offset;
u16 id;
+ u32 wr_length;
+ u32 rd_length;
u8 *func_specific;
};
@@ -141,6 +124,8 @@
#define MPI_FATAL_EDUMP_TABLE_HANDSHAKE 0x0C /* FDDHSHK */
#define MPI_FATAL_EDUMP_TABLE_STATUS 0x10 /* FDDTSTAT */
#define MPI_FATAL_EDUMP_TABLE_ACCUM_LEN 0x14 /* ACCDDLEN */
+#define MPI_FATAL_EDUMP_TABLE_TOTAL_LEN 0x18 /* TOTALLEN */
+#define MPI_FATAL_EDUMP_TABLE_SIGNATURE 0x1C /* SIGNITURE */
#define MPI_FATAL_EDUMP_HANDSHAKE_RDY 0x1
#define MPI_FATAL_EDUMP_HANDSHAKE_BUSY 0x0
#define MPI_FATAL_EDUMP_TABLE_STAT_RSVD 0x0
@@ -279,7 +264,7 @@
struct completion *dcompletion;
struct completion *setds_completion;
u32 device_id;
- u32 running_req;
+ atomic_t running_req;
};
struct pm8001_prd_imt {
@@ -301,7 +286,7 @@
u32 ccb_tag;
dma_addr_t ccb_dma_handle;
struct pm8001_device *device;
- struct pm8001_prd buf_prd[PM8001_MAX_DMA_SG];
+ struct pm8001_prd *buf_prd;
struct fw_control_ex *fw_control_context;
u8 open_retry;
};
@@ -454,6 +439,7 @@
u32 reserved;
__le32 consumer_index;
u32 producer_idx;
+ spinlock_t iq_lock;
};
struct outbound_queue_table {
u32 element_size_cnt;
@@ -496,6 +482,7 @@
u32 forensic_last_offset;
u32 fatal_forensic_shift_offset;
u32 forensic_fatal_step;
+ u32 forensic_preserved_accumulated_transfer;
u32 evtlog_ib_offset;
u32 evtlog_ob_offset;
void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/
@@ -509,8 +496,8 @@
void __iomem *fatal_tbl_addr; /*MPI IVT Table Addr */
union main_cfg_table main_cfg_tbl;
union general_status_table gs_tbl;
- struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_SPCV_INB_NUM];
- struct outbound_queue_table outbnd_q_tbl[PM8001_MAX_SPCV_OUTB_NUM];
+ struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_INB_NUM];
+ struct outbound_queue_table outbnd_q_tbl[PM8001_MAX_OUTB_NUM];
struct sas_phy_attribute_table phy_attr_table;
/* MPI SAS PHY attributes */
u8 sas_addr[SAS_ADDR_SIZE];
@@ -530,17 +517,28 @@
struct pm8001_ccb_info *ccb_info;
#ifdef PM8001_USE_MSIX
int number_of_intr;/*will be used in remove()*/
+ char intr_drvname[PM8001_MAX_MSIX_VEC]
+ [PM8001_NAME_LENGTH+1+3+1];
#endif
#ifdef PM8001_USE_TASKLET
struct tasklet_struct tasklet[PM8001_MAX_MSIX_VEC];
#endif
u32 logging_level;
+ u32 link_rate;
u32 fw_status;
u32 smp_exp_mode;
bool controller_fatal_error;
const struct firmware *fw_image;
struct isr_param irq_vector[PM8001_MAX_MSIX_VEC];
u32 reset_in_progress;
+ u32 non_fatal_count;
+ u32 non_fatal_read_length;
+ u32 max_q_num;
+ u32 ib_offset;
+ u32 ob_offset;
+ u32 ci_offset;
+ u32 pi_offset;
+ u32 max_memcnt;
};
struct pm8001_work {
@@ -663,7 +661,8 @@
void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha);
int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
struct inbound_queue_table *circularQ,
- u32 opCode, void *payload, u32 responseQueue);
+ u32 opCode, void *payload, size_t nb,
+ u32 responseQueue);
int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ,
u16 messageSize, void **messagePtr);
u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
@@ -723,6 +722,8 @@
int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue);
ssize_t pm80xx_get_fatal_dump(struct device *cdev,
struct device_attribute *attr, char *buf);
+ssize_t pm80xx_get_non_fatal_dump(struct device *cdev,
+ struct device_attribute *attr, char *buf);
ssize_t pm8001_get_gsm_dump(struct device *cdev, u32, char *buf);
/* ctl shared API */
extern struct device_attribute *pm8001_host_attrs[];
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 161bf47..2a3ce46 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -58,15 +58,14 @@
reg_val = pm8001_cr32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER);
} while ((reg_val != shift_value) && time_before(jiffies, start));
if (reg_val != shift_value) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER"
- " = 0x%x\n", reg_val));
+ pm8001_dbg(pm8001_ha, FAIL, "TIMEOUT:MEMBASE_II_SHIFT_REGISTER = 0x%x\n",
+ reg_val);
return -1;
}
return 0;
}
-void pm80xx_pci_mem_copy(struct pm8001_hba_info *pm8001_ha, u32 soffset,
+static void pm80xx_pci_mem_copy(struct pm8001_hba_info *pm8001_ha, u32 soffset,
const void *destination,
u32 dw_count, u32 bus_base_number)
{
@@ -75,7 +74,7 @@
destination1 = (u32 *)destination;
for (index = 0; index < dw_count; index += 4, destination1++) {
- offset = (soffset + index / 4);
+ offset = (soffset + index);
if (offset < (64 * 1024)) {
value = pm8001_cr32(pm8001_ha, bus_base_number, offset);
*destination1 = cpu_to_le32(value);
@@ -92,9 +91,12 @@
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
void __iomem *fatal_table_address = pm8001_ha->fatal_tbl_addr;
u32 accum_len , reg_val, index, *temp;
+ u32 status = 1;
unsigned long start;
u8 *direct_data;
char *fatal_error_data = buf;
+ u32 length_to_read;
+ u32 offset;
pm8001_ha->forensic_info.data_buf.direct_data = buf;
if (pm8001_ha->chip_id == chip_8001) {
@@ -104,16 +106,31 @@
return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
(char *)buf;
}
+ /* initialize variables for very first call from host application */
if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("forensic_info TYPE_NON_FATAL..............\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "forensic_info TYPE_NON_FATAL..............\n");
direct_data = (u8 *)fatal_error_data;
pm8001_ha->forensic_info.data_type = TYPE_NON_FATAL;
pm8001_ha->forensic_info.data_buf.direct_len = SYSFS_OFFSET;
+ pm8001_ha->forensic_info.data_buf.direct_offset = 0;
pm8001_ha->forensic_info.data_buf.read_len = 0;
+ pm8001_ha->forensic_preserved_accumulated_transfer = 0;
+
+ /* Write signature to fatal dump table */
+ pm8001_mw32(fatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_SIGNATURE, 0x1234abcd);
pm8001_ha->forensic_info.data_buf.direct_data = direct_data;
-
+ pm8001_dbg(pm8001_ha, IO, "ossaHwCB: status1 %d\n", status);
+ pm8001_dbg(pm8001_ha, IO, "ossaHwCB: read_len 0x%x\n",
+ pm8001_ha->forensic_info.data_buf.read_len);
+ pm8001_dbg(pm8001_ha, IO, "ossaHwCB: direct_len 0x%x\n",
+ pm8001_ha->forensic_info.data_buf.direct_len);
+ pm8001_dbg(pm8001_ha, IO, "ossaHwCB: direct_offset 0x%x\n",
+ pm8001_ha->forensic_info.data_buf.direct_offset);
+ }
+ if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) {
/* start to get data */
/* Program the MEMBASE II Shifting Register with 0x00.*/
pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
@@ -126,30 +143,61 @@
/* Read until accum_len is retrived */
accum_len = pm8001_mr32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("accum_len 0x%x\n",
- accum_len));
+ /* Determine length of data between previously stored transfer length
+ * and current accumulated transfer length
+ */
+ length_to_read =
+ accum_len - pm8001_ha->forensic_preserved_accumulated_transfer;
+ pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: accum_len 0x%x\n",
+ accum_len);
+ pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: length_to_read 0x%x\n",
+ length_to_read);
+ pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: last_offset 0x%x\n",
+ pm8001_ha->forensic_last_offset);
+ pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: read_len 0x%x\n",
+ pm8001_ha->forensic_info.data_buf.read_len);
+ pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv:: direct_len 0x%x\n",
+ pm8001_ha->forensic_info.data_buf.direct_len);
+ pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv:: direct_offset 0x%x\n",
+ pm8001_ha->forensic_info.data_buf.direct_offset);
+
+ /* If accumulated length failed to read correctly fail the attempt.*/
if (accum_len == 0xFFFFFFFF) {
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("Possible PCI issue 0x%x not expected\n",
- accum_len));
- return -EIO;
+ pm8001_dbg(pm8001_ha, IO,
+ "Possible PCI issue 0x%x not expected\n",
+ accum_len);
+ return status;
}
- if (accum_len == 0 || accum_len >= 0x100000) {
+ /* If accumulated length is zero fail the attempt */
+ if (accum_len == 0) {
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
- "%08x ", 0xFFFFFFFF);
+ "%08x ", 0xFFFFFFFF);
return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
(char *)buf;
}
+ /* Accumulated length is good so start capturing the first data */
temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr;
if (pm8001_ha->forensic_fatal_step == 0) {
moreData:
+ /* If data to read is less than SYSFS_OFFSET then reduce the
+ * length of dataLen
+ */
+ if (pm8001_ha->forensic_last_offset + SYSFS_OFFSET
+ > length_to_read) {
+ pm8001_ha->forensic_info.data_buf.direct_len =
+ length_to_read -
+ pm8001_ha->forensic_last_offset;
+ } else {
+ pm8001_ha->forensic_info.data_buf.direct_len =
+ SYSFS_OFFSET;
+ }
if (pm8001_ha->forensic_info.data_buf.direct_data) {
/* Data is in bar, copy to host memory */
- pm80xx_pci_mem_copy(pm8001_ha, pm8001_ha->fatal_bar_loc,
- pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr,
- pm8001_ha->forensic_info.data_buf.direct_len ,
- 1);
+ pm80xx_pci_mem_copy(pm8001_ha,
+ pm8001_ha->fatal_bar_loc,
+ pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr,
+ pm8001_ha->forensic_info.data_buf.direct_len, 1);
}
pm8001_ha->fatal_bar_loc +=
pm8001_ha->forensic_info.data_buf.direct_len;
@@ -160,21 +208,29 @@
pm8001_ha->forensic_info.data_buf.read_len =
pm8001_ha->forensic_info.data_buf.direct_len;
- if (pm8001_ha->forensic_last_offset >= accum_len) {
+ if (pm8001_ha->forensic_last_offset >= length_to_read) {
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
"%08x ", 3);
- for (index = 0; index < (SYSFS_OFFSET / 4); index++) {
+ for (index = 0; index <
+ (pm8001_ha->forensic_info.data_buf.direct_len
+ / 4); index++) {
pm8001_ha->forensic_info.data_buf.direct_data +=
- sprintf(pm8001_ha->
- forensic_info.data_buf.direct_data,
- "%08x ", *(temp + index));
+ sprintf(
+ pm8001_ha->forensic_info.data_buf.direct_data,
+ "%08x ", *(temp + index));
}
pm8001_ha->fatal_bar_loc = 0;
pm8001_ha->forensic_fatal_step = 1;
pm8001_ha->fatal_forensic_shift_offset = 0;
pm8001_ha->forensic_last_offset = 0;
+ status = 0;
+ offset = (int)
+ ((char *)pm8001_ha->forensic_info.data_buf.direct_data
+ - (char *)buf);
+ pm8001_dbg(pm8001_ha, IO,
+ "get_fatal_spcv:return1 0x%x\n", offset);
return (char *)pm8001_ha->
forensic_info.data_buf.direct_data -
(char *)buf;
@@ -184,12 +240,20 @@
sprintf(pm8001_ha->
forensic_info.data_buf.direct_data,
"%08x ", 2);
- for (index = 0; index < (SYSFS_OFFSET / 4); index++) {
- pm8001_ha->forensic_info.data_buf.direct_data +=
- sprintf(pm8001_ha->
+ for (index = 0; index <
+ (pm8001_ha->forensic_info.data_buf.direct_len
+ / 4); index++) {
+ pm8001_ha->forensic_info.data_buf.direct_data
+ += sprintf(pm8001_ha->
forensic_info.data_buf.direct_data,
"%08x ", *(temp + index));
}
+ status = 0;
+ offset = (int)
+ ((char *)pm8001_ha->forensic_info.data_buf.direct_data
+ - (char *)buf);
+ pm8001_dbg(pm8001_ha, IO,
+ "get_fatal_spcv:return2 0x%x\n", offset);
return (char *)pm8001_ha->
forensic_info.data_buf.direct_data -
(char *)buf;
@@ -199,67 +263,254 @@
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(pm8001_ha->forensic_info.data_buf.direct_data,
"%08x ", 2);
- for (index = 0; index < 256; index++) {
+ for (index = 0; index <
+ (pm8001_ha->forensic_info.data_buf.direct_len
+ / 4) ; index++) {
pm8001_ha->forensic_info.data_buf.direct_data +=
sprintf(pm8001_ha->
- forensic_info.data_buf.direct_data,
- "%08x ", *(temp + index));
+ forensic_info.data_buf.direct_data,
+ "%08x ", *(temp + index));
}
pm8001_ha->fatal_forensic_shift_offset += 0x100;
pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
pm8001_ha->fatal_forensic_shift_offset);
pm8001_ha->fatal_bar_loc = 0;
+ status = 0;
+ offset = (int)
+ ((char *)pm8001_ha->forensic_info.data_buf.direct_data
+ - (char *)buf);
+ pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: return3 0x%x\n",
+ offset);
return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
(char *)buf;
}
if (pm8001_ha->forensic_fatal_step == 1) {
- pm8001_ha->fatal_forensic_shift_offset = 0;
- /* Read 64K of the debug data. */
- pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
- pm8001_ha->fatal_forensic_shift_offset);
- pm8001_mw32(fatal_table_address,
- MPI_FATAL_EDUMP_TABLE_HANDSHAKE,
+ /* store previous accumulated length before triggering next
+ * accumulated length update
+ */
+ pm8001_ha->forensic_preserved_accumulated_transfer =
+ pm8001_mr32(fatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
+
+ /* continue capturing the fatal log until Dump status is 0x3 */
+ if (pm8001_mr32(fatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_STATUS) <
+ MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) {
+
+ /* reset fddstat bit by writing to zero*/
+ pm8001_mw32(fatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_STATUS, 0x0);
+
+ /* set dump control value to '1' so that new data will
+ * be transferred to shared memory
+ */
+ pm8001_mw32(fatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_HANDSHAKE,
MPI_FATAL_EDUMP_HANDSHAKE_RDY);
- /* Poll FDDHSHK until clear */
- start = jiffies + (2 * HZ); /* 2 sec */
+ /*Poll FDDHSHK until clear */
+ start = jiffies + (2 * HZ); /* 2 sec */
- do {
- reg_val = pm8001_mr32(fatal_table_address,
+ do {
+ reg_val = pm8001_mr32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_HANDSHAKE);
- } while ((reg_val) && time_before(jiffies, start));
+ } while ((reg_val) && time_before(jiffies, start));
- if (reg_val != 0) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER"
- " = 0x%x\n", reg_val));
- return -EIO;
- }
+ if (reg_val != 0) {
+ pm8001_dbg(pm8001_ha, FAIL,
+ "TIMEOUT:MPI_FATAL_EDUMP_TABLE_HDSHAKE 0x%x\n",
+ reg_val);
+ /* Fail the dump if a timeout occurs */
+ pm8001_ha->forensic_info.data_buf.direct_data +=
+ sprintf(
+ pm8001_ha->forensic_info.data_buf.direct_data,
+ "%08x ", 0xFFFFFFFF);
+ return((char *)
+ pm8001_ha->forensic_info.data_buf.direct_data
+ - (char *)buf);
+ }
+ /* Poll status register until set to 2 or
+ * 3 for up to 2 seconds
+ */
+ start = jiffies + (2 * HZ); /* 2 sec */
- /* Read the next 64K of the debug data. */
- pm8001_ha->forensic_fatal_step = 0;
- if (pm8001_mr32(fatal_table_address,
- MPI_FATAL_EDUMP_TABLE_STATUS) !=
- MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) {
- pm8001_mw32(fatal_table_address,
- MPI_FATAL_EDUMP_TABLE_HANDSHAKE, 0);
- goto moreData;
- } else {
- pm8001_ha->forensic_info.data_buf.direct_data +=
- sprintf(pm8001_ha->
- forensic_info.data_buf.direct_data,
- "%08x ", 4);
- pm8001_ha->forensic_info.data_buf.read_len = 0xFFFFFFFF;
- pm8001_ha->forensic_info.data_buf.direct_len = 0;
- pm8001_ha->forensic_info.data_buf.direct_offset = 0;
- pm8001_ha->forensic_info.data_buf.read_len = 0;
+ do {
+ reg_val = pm8001_mr32(fatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_STATUS);
+ } while (((reg_val != 2) && (reg_val != 3)) &&
+ time_before(jiffies, start));
+
+ if (reg_val < 2) {
+ pm8001_dbg(pm8001_ha, FAIL,
+ "TIMEOUT:MPI_FATAL_EDUMP_TABLE_STATUS = 0x%x\n",
+ reg_val);
+ /* Fail the dump if a timeout occurs */
+ pm8001_ha->forensic_info.data_buf.direct_data +=
+ sprintf(
+ pm8001_ha->forensic_info.data_buf.direct_data,
+ "%08x ", 0xFFFFFFFF);
+ pm8001_cw32(pm8001_ha, 0,
+ MEMBASE_II_SHIFT_REGISTER,
+ pm8001_ha->fatal_forensic_shift_offset);
+ }
+ /* Read the next block of the debug data.*/
+ length_to_read = pm8001_mr32(fatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_ACCUM_LEN) -
+ pm8001_ha->forensic_preserved_accumulated_transfer;
+ if (length_to_read != 0x0) {
+ pm8001_ha->forensic_fatal_step = 0;
+ goto moreData;
+ } else {
+ pm8001_ha->forensic_info.data_buf.direct_data +=
+ sprintf(
+ pm8001_ha->forensic_info.data_buf.direct_data,
+ "%08x ", 4);
+ pm8001_ha->forensic_info.data_buf.read_len
+ = 0xFFFFFFFF;
+ pm8001_ha->forensic_info.data_buf.direct_len
+ = 0;
+ pm8001_ha->forensic_info.data_buf.direct_offset
+ = 0;
+ pm8001_ha->forensic_info.data_buf.read_len = 0;
+ }
}
}
-
+ offset = (int)((char *)pm8001_ha->forensic_info.data_buf.direct_data
+ - (char *)buf);
+ pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: return4 0x%x\n", offset);
return (char *)pm8001_ha->forensic_info.data_buf.direct_data -
(char *)buf;
}
+/* pm80xx_get_non_fatal_dump - dump the nonfatal data from the dma
+ * location by the firmware.
+ */
+ssize_t pm80xx_get_non_fatal_dump(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+ struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+ void __iomem *nonfatal_table_address = pm8001_ha->fatal_tbl_addr;
+ u32 accum_len = 0;
+ u32 total_len = 0;
+ u32 reg_val = 0;
+ u32 *temp = NULL;
+ u32 index = 0;
+ u32 output_length;
+ unsigned long start = 0;
+ char *buf_copy = buf;
+
+ temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr;
+ if (++pm8001_ha->non_fatal_count == 1) {
+ if (pm8001_ha->chip_id == chip_8001) {
+ snprintf(pm8001_ha->forensic_info.data_buf.direct_data,
+ PAGE_SIZE, "Not supported for SPC controller");
+ return 0;
+ }
+ pm8001_dbg(pm8001_ha, IO, "forensic_info TYPE_NON_FATAL...\n");
+ /*
+ * Step 1: Write the host buffer parameters in the MPI Fatal and
+ * Non-Fatal Error Dump Capture Table.This is the buffer
+ * where debug data will be DMAed to.
+ */
+ pm8001_mw32(nonfatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_LO_OFFSET,
+ pm8001_ha->memoryMap.region[FORENSIC_MEM].phys_addr_lo);
+
+ pm8001_mw32(nonfatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_HI_OFFSET,
+ pm8001_ha->memoryMap.region[FORENSIC_MEM].phys_addr_hi);
+
+ pm8001_mw32(nonfatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_LENGTH, SYSFS_OFFSET);
+
+ /* Optionally, set the DUMPCTRL bit to 1 if the host
+ * keeps sending active I/Os while capturing the non-fatal
+ * debug data. Otherwise, leave this bit set to zero
+ */
+ pm8001_mw32(nonfatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_HANDSHAKE, MPI_FATAL_EDUMP_HANDSHAKE_RDY);
+
+ /*
+ * Step 2: Clear Accumulative Length of Debug Data Transferred
+ * [ACCDDLEN] field in the MPI Fatal and Non-Fatal Error Dump
+ * Capture Table to zero.
+ */
+ pm8001_mw32(nonfatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_ACCUM_LEN, 0);
+
+ /* initiallize previous accumulated length to 0 */
+ pm8001_ha->forensic_preserved_accumulated_transfer = 0;
+ pm8001_ha->non_fatal_read_length = 0;
+ }
+
+ total_len = pm8001_mr32(nonfatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_TOTAL_LEN);
+ /*
+ * Step 3:Clear Fatal/Non-Fatal Debug Data Transfer Status [FDDTSTAT]
+ * field and then request that the SPCv controller transfer the debug
+ * data by setting bit 7 of the Inbound Doorbell Set Register.
+ */
+ pm8001_mw32(nonfatal_table_address, MPI_FATAL_EDUMP_TABLE_STATUS, 0);
+ pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET,
+ SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP);
+
+ /*
+ * Step 4.1: Read back the Inbound Doorbell Set Register (by polling for
+ * 2 seconds) until register bit 7 is cleared.
+ * This step only indicates the request is accepted by the controller.
+ */
+ start = jiffies + (2 * HZ); /* 2 sec */
+ do {
+ reg_val = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET) &
+ SPCv_MSGU_CFG_TABLE_NONFATAL_DUMP;
+ } while ((reg_val != 0) && time_before(jiffies, start));
+
+ /* Step 4.2: To check the completion of the transfer, poll the Fatal/Non
+ * Fatal Debug Data Transfer Status [FDDTSTAT] field for 2 seconds in
+ * the MPI Fatal and Non-Fatal Error Dump Capture Table.
+ */
+ start = jiffies + (2 * HZ); /* 2 sec */
+ do {
+ reg_val = pm8001_mr32(nonfatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_STATUS);
+ } while ((!reg_val) && time_before(jiffies, start));
+
+ if ((reg_val == 0x00) ||
+ (reg_val == MPI_FATAL_EDUMP_TABLE_STAT_DMA_FAILED) ||
+ (reg_val > MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE)) {
+ pm8001_ha->non_fatal_read_length = 0;
+ buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 0xFFFFFFFF);
+ pm8001_ha->non_fatal_count = 0;
+ return (buf_copy - buf);
+ } else if (reg_val ==
+ MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_MORE_DATA) {
+ buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 2);
+ } else if ((reg_val == MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) ||
+ (pm8001_ha->non_fatal_read_length >= total_len)) {
+ pm8001_ha->non_fatal_read_length = 0;
+ buf_copy += snprintf(buf_copy, PAGE_SIZE, "%08x ", 4);
+ pm8001_ha->non_fatal_count = 0;
+ }
+ accum_len = pm8001_mr32(nonfatal_table_address,
+ MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
+ output_length = accum_len -
+ pm8001_ha->forensic_preserved_accumulated_transfer;
+
+ for (index = 0; index < output_length/4; index++)
+ buf_copy += snprintf(buf_copy, PAGE_SIZE,
+ "%08x ", *(temp+index));
+
+ pm8001_ha->non_fatal_read_length += output_length;
+
+ /* store current accumulated length to use in next iteration as
+ * the previous accumulated length
+ */
+ pm8001_ha->forensic_preserved_accumulated_transfer = accum_len;
+ return (buf_copy - buf);
+}
+
/**
* read_main_config_table - read the configure table and save it.
* @pm8001_ha: our hba card information
@@ -317,6 +568,25 @@
pm8001_mr32(address, MAIN_MPI_ILA_RELEASE_TYPE);
pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version =
pm8001_mr32(address, MAIN_MPI_INACTIVE_FW_VERSION);
+
+ pm8001_dbg(pm8001_ha, DEV,
+ "Main cfg table: sign:%x interface rev:%x fw_rev:%x\n",
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.signature,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev);
+
+ pm8001_dbg(pm8001_ha, DEV,
+ "table offset: gst:%x iq:%x oq:%x int vec:%x phy attr:%x\n",
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.gst_offset,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_queue_offset,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.outbound_queue_offset,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.int_vec_table_offset,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset);
+
+ pm8001_dbg(pm8001_ha, DEV,
+ "Main cfg table; ila rev:%x Inactive fw rev:%x\n",
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version,
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version);
}
/**
@@ -438,7 +708,7 @@
{
int i;
void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;
- for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) {
+ for (i = 0; i < PM8001_MAX_INB_NUM; i++) {
u32 offset = i * 0x20;
pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =
get_pci_bar_index(pm8001_mr32(address,
@@ -456,7 +726,7 @@
{
int i;
void __iomem *address = pm8001_ha->outbnd_q_tbl_addr;
- for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
+ for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) {
u32 offset = i * 0x24;
pm8001_ha->outbnd_q_tbl[i].ci_pci_bar =
get_pci_bar_index(pm8001_mr32(address,
@@ -476,6 +746,10 @@
u32 offsetib, offsetob;
void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr;
void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr;
+ u32 ib_offset = pm8001_ha->ib_offset;
+ u32 ob_offset = pm8001_ha->ob_offset;
+ u32 ci_offset = pm8001_ha->ci_offset;
+ u32 pi_offset = pm8001_ha->pi_offset;
pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_event_log_addr =
pm8001_ha->memoryMap.region[AAP1].phys_addr_hi;
@@ -496,23 +770,23 @@
/* Disable end to end CRC checking */
pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump = (0x1 << 16);
- for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) {
+ for (i = 0; i < pm8001_ha->max_q_num; i++) {
pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt =
PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30);
pm8001_ha->inbnd_q_tbl[i].upper_base_addr =
- pm8001_ha->memoryMap.region[IB + i].phys_addr_hi;
+ pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_hi;
pm8001_ha->inbnd_q_tbl[i].lower_base_addr =
- pm8001_ha->memoryMap.region[IB + i].phys_addr_lo;
+ pm8001_ha->memoryMap.region[ib_offset + i].phys_addr_lo;
pm8001_ha->inbnd_q_tbl[i].base_virt =
- (u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr;
+ (u8 *)pm8001_ha->memoryMap.region[ib_offset + i].virt_ptr;
pm8001_ha->inbnd_q_tbl[i].total_length =
- pm8001_ha->memoryMap.region[IB + i].total_len;
+ pm8001_ha->memoryMap.region[ib_offset + i].total_len;
pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr =
- pm8001_ha->memoryMap.region[CI + i].phys_addr_hi;
+ pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_hi;
pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr =
- pm8001_ha->memoryMap.region[CI + i].phys_addr_lo;
+ pm8001_ha->memoryMap.region[ci_offset + i].phys_addr_lo;
pm8001_ha->inbnd_q_tbl[i].ci_virt =
- pm8001_ha->memoryMap.region[CI + i].virt_ptr;
+ pm8001_ha->memoryMap.region[ci_offset + i].virt_ptr;
offsetib = i * 0x20;
pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =
get_pci_bar_index(pm8001_mr32(addressib,
@@ -521,26 +795,31 @@
pm8001_mr32(addressib, (offsetib + 0x18));
pm8001_ha->inbnd_q_tbl[i].producer_idx = 0;
pm8001_ha->inbnd_q_tbl[i].consumer_index = 0;
+
+ pm8001_dbg(pm8001_ha, DEV,
+ "IQ %d pi_bar 0x%x pi_offset 0x%x\n", i,
+ pm8001_ha->inbnd_q_tbl[i].pi_pci_bar,
+ pm8001_ha->inbnd_q_tbl[i].pi_offset);
}
- for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) {
+ for (i = 0; i < pm8001_ha->max_q_num; i++) {
pm8001_ha->outbnd_q_tbl[i].element_size_cnt =
PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30);
pm8001_ha->outbnd_q_tbl[i].upper_base_addr =
- pm8001_ha->memoryMap.region[OB + i].phys_addr_hi;
+ pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_hi;
pm8001_ha->outbnd_q_tbl[i].lower_base_addr =
- pm8001_ha->memoryMap.region[OB + i].phys_addr_lo;
+ pm8001_ha->memoryMap.region[ob_offset + i].phys_addr_lo;
pm8001_ha->outbnd_q_tbl[i].base_virt =
- (u8 *)pm8001_ha->memoryMap.region[OB + i].virt_ptr;
+ (u8 *)pm8001_ha->memoryMap.region[ob_offset + i].virt_ptr;
pm8001_ha->outbnd_q_tbl[i].total_length =
- pm8001_ha->memoryMap.region[OB + i].total_len;
+ pm8001_ha->memoryMap.region[ob_offset + i].total_len;
pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr =
- pm8001_ha->memoryMap.region[PI + i].phys_addr_hi;
+ pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_hi;
pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr =
- pm8001_ha->memoryMap.region[PI + i].phys_addr_lo;
+ pm8001_ha->memoryMap.region[pi_offset + i].phys_addr_lo;
/* interrupt vector based on oq */
pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay = (i << 24);
pm8001_ha->outbnd_q_tbl[i].pi_virt =
- pm8001_ha->memoryMap.region[PI + i].virt_ptr;
+ pm8001_ha->memoryMap.region[pi_offset + i].virt_ptr;
offsetob = i * 0x24;
pm8001_ha->outbnd_q_tbl[i].ci_pci_bar =
get_pci_bar_index(pm8001_mr32(addressob,
@@ -549,6 +828,11 @@
pm8001_mr32(addressob, (offsetob + 0x18));
pm8001_ha->outbnd_q_tbl[i].consumer_idx = 0;
pm8001_ha->outbnd_q_tbl[i].producer_index = 0;
+
+ pm8001_dbg(pm8001_ha, DEV,
+ "OQ %d ci_bar 0x%x ci_offset 0x%x\n", i,
+ pm8001_ha->outbnd_q_tbl[i].ci_pci_bar,
+ pm8001_ha->outbnd_q_tbl[i].ci_offset);
}
}
@@ -579,9 +863,13 @@
pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity);
/* Update Fatal error interrupt vector */
pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt |=
- ((pm8001_ha->number_of_intr - 1) << 8);
+ ((pm8001_ha->max_q_num - 1) << 8);
pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt);
+ pm8001_dbg(pm8001_ha, DEV,
+ "Updated Fatal error interrupt vector 0x%x\n",
+ pm8001_mr32(address, MAIN_FATAL_ERROR_INTERRUPT));
+
pm8001_mw32(address, MAIN_EVENT_CRC_CHECK,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump);
@@ -591,6 +879,9 @@
pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping |= 0x20000000;
pm8001_mw32(address, MAIN_GPIO_LED_FLAGS_OFFSET,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping);
+ pm8001_dbg(pm8001_ha, DEV,
+ "Programming DW 0x21 in main cfg table with 0x%x\n",
+ pm8001_mr32(address, MAIN_GPIO_LED_FLAGS_OFFSET));
pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer);
@@ -613,6 +904,7 @@
/**
* update_inbnd_queue_table - update the inbound queue table to the HBA.
* @pm8001_ha: our hba card information
+ * @number: entry in the queue
*/
static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
int number)
@@ -629,11 +921,27 @@
pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr);
pm8001_mw32(address, offset + IB_CI_BASE_ADDR_LO_OFFSET,
pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr);
+
+ pm8001_dbg(pm8001_ha, DEV,
+ "IQ %d: Element pri size 0x%x\n",
+ number,
+ pm8001_ha->inbnd_q_tbl[number].element_pri_size_cnt);
+
+ pm8001_dbg(pm8001_ha, DEV,
+ "IQ upr base addr 0x%x IQ lwr base addr 0x%x\n",
+ pm8001_ha->inbnd_q_tbl[number].upper_base_addr,
+ pm8001_ha->inbnd_q_tbl[number].lower_base_addr);
+
+ pm8001_dbg(pm8001_ha, DEV,
+ "CI upper base addr 0x%x CI lower base addr 0x%x\n",
+ pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr,
+ pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr);
}
/**
* update_outbnd_queue_table - update the outbound queue table to the HBA.
* @pm8001_ha: our hba card information
+ * @number: entry in the queue
*/
static void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha,
int number)
@@ -652,6 +960,21 @@
pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr);
pm8001_mw32(address, offset + OB_INTERRUPT_COALES_OFFSET,
pm8001_ha->outbnd_q_tbl[number].interrup_vec_cnt_delay);
+
+ pm8001_dbg(pm8001_ha, DEV,
+ "OQ %d: Element pri size 0x%x\n",
+ number,
+ pm8001_ha->outbnd_q_tbl[number].element_size_cnt);
+
+ pm8001_dbg(pm8001_ha, DEV,
+ "OQ upr base addr 0x%x OQ lwr base addr 0x%x\n",
+ pm8001_ha->outbnd_q_tbl[number].upper_base_addr,
+ pm8001_ha->outbnd_q_tbl[number].lower_base_addr);
+
+ pm8001_dbg(pm8001_ha, DEV,
+ "PI upper base addr 0x%x PI lower base addr 0x%x\n",
+ pm8001_ha->outbnd_q_tbl[number].pi_upper_base_addr,
+ pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr);
}
/**
@@ -669,9 +992,9 @@
pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE);
/* wait until Inbound DoorBell Clear Register toggled */
if (IS_SPCV_12G(pm8001_ha->pdev)) {
- max_wait_count = 4 * 1000 * 1000;/* 4 sec */
+ max_wait_count = SPCV_DOORBELL_CLEAR_TIMEOUT;
} else {
- max_wait_count = 2 * 1000 * 1000;/* 2 sec */
+ max_wait_count = SPC_DOORBELL_CLEAR_TIMEOUT;
}
do {
udelay(1);
@@ -679,8 +1002,13 @@
value &= SPCv_MSGU_CFG_TABLE_UPDATE;
} while ((value != 0) && (--max_wait_count));
- if (!max_wait_count)
- return -1;
+ if (!max_wait_count) {
+ /* additional check */
+ pm8001_dbg(pm8001_ha, FAIL,
+ "Inb doorbell clear not toggled[value:%x]\n",
+ value);
+ return -EBUSY;
+ }
/* check the MPI-State for initialization upto 100ms*/
max_wait_count = 100 * 1000;/* 100 msec */
do {
@@ -691,12 +1019,12 @@
} while ((GST_MPI_STATE_INIT !=
(gst_len_mpistate & GST_MPI_STATE_MASK)) && (--max_wait_count));
if (!max_wait_count)
- return -1;
+ return -EBUSY;
/* check MPI Initialization error */
gst_len_mpistate = gst_len_mpistate >> 16;
if (0x0000 != gst_len_mpistate)
- return -1;
+ return -EBUSY;
return 0;
}
@@ -729,9 +1057,9 @@
if (!max_wait_count)
ret = -1;
else {
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" ila ready status in %d millisec\n",
- (max_wait_time - max_wait_count)));
+ pm8001_dbg(pm8001_ha, MSG,
+ " ila ready status in %d millisec\n",
+ (max_wait_time - max_wait_count));
}
/* check RAAE status */
@@ -744,9 +1072,9 @@
if (!max_wait_count)
ret = -1;
else {
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" raae ready status in %d millisec\n",
- (max_wait_time - max_wait_count)));
+ pm8001_dbg(pm8001_ha, MSG,
+ " raae ready status in %d millisec\n",
+ (max_wait_time - max_wait_count));
}
/* check iop0 status */
@@ -759,9 +1087,9 @@
if (!max_wait_count)
ret = -1;
else {
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" iop0 ready status in %d millisec\n",
- (max_wait_time - max_wait_count)));
+ pm8001_dbg(pm8001_ha, MSG,
+ " iop0 ready status in %d millisec\n",
+ (max_wait_time - max_wait_count));
}
/* check iop1 status only for 16 port controllers */
@@ -777,9 +1105,9 @@
if (!max_wait_count)
ret = -1;
else {
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "iop1 ready status in %d millisec\n",
- (max_wait_time - max_wait_count)));
+ pm8001_dbg(pm8001_ha, MSG,
+ "iop1 ready status in %d millisec\n",
+ (max_wait_time - max_wait_count));
}
}
@@ -797,13 +1125,11 @@
value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0);
offset = value & 0x03FFFFFF; /* scratch pad 0 TBL address */
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Scratchpad 0 Offset: 0x%x value 0x%x\n",
- offset, value));
+ pm8001_dbg(pm8001_ha, DEV, "Scratchpad 0 Offset: 0x%x value 0x%x\n",
+ offset, value);
pcilogic = (value & 0xFC000000) >> 26;
pcibar = get_pci_bar_index(pcilogic);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Scratchpad 0 PCI BAR: %d\n", pcibar));
+ pm8001_dbg(pm8001_ha, INIT, "Scratchpad 0 PCI BAR: %d\n", pcibar);
pm8001_ha->main_cfg_tbl_addr = base_addr =
pm8001_ha->io_mem[pcibar].memvirtaddr + offset;
pm8001_ha->general_stat_tbl_addr =
@@ -825,33 +1151,25 @@
base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0xA0) &
0xFFFFFF);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("GST OFFSET 0x%x\n",
- pm8001_cr32(pm8001_ha, pcibar, offset + 0x18)));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("INBND OFFSET 0x%x\n",
- pm8001_cr32(pm8001_ha, pcibar, offset + 0x1C)));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("OBND OFFSET 0x%x\n",
- pm8001_cr32(pm8001_ha, pcibar, offset + 0x20)));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("IVT OFFSET 0x%x\n",
- pm8001_cr32(pm8001_ha, pcibar, offset + 0x8C)));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("PSPA OFFSET 0x%x\n",
- pm8001_cr32(pm8001_ha, pcibar, offset + 0x90)));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("addr - main cfg %p general status %p\n",
- pm8001_ha->main_cfg_tbl_addr,
- pm8001_ha->general_stat_tbl_addr));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("addr - inbnd %p obnd %p\n",
- pm8001_ha->inbnd_q_tbl_addr,
- pm8001_ha->outbnd_q_tbl_addr));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("addr - pspa %p ivt %p\n",
- pm8001_ha->pspa_q_tbl_addr,
- pm8001_ha->ivt_tbl_addr));
+ pm8001_dbg(pm8001_ha, INIT, "GST OFFSET 0x%x\n",
+ pm8001_cr32(pm8001_ha, pcibar, offset + 0x18));
+ pm8001_dbg(pm8001_ha, INIT, "INBND OFFSET 0x%x\n",
+ pm8001_cr32(pm8001_ha, pcibar, offset + 0x1C));
+ pm8001_dbg(pm8001_ha, INIT, "OBND OFFSET 0x%x\n",
+ pm8001_cr32(pm8001_ha, pcibar, offset + 0x20));
+ pm8001_dbg(pm8001_ha, INIT, "IVT OFFSET 0x%x\n",
+ pm8001_cr32(pm8001_ha, pcibar, offset + 0x8C));
+ pm8001_dbg(pm8001_ha, INIT, "PSPA OFFSET 0x%x\n",
+ pm8001_cr32(pm8001_ha, pcibar, offset + 0x90));
+ pm8001_dbg(pm8001_ha, INIT, "addr - main cfg %p general status %p\n",
+ pm8001_ha->main_cfg_tbl_addr,
+ pm8001_ha->general_stat_tbl_addr);
+ pm8001_dbg(pm8001_ha, INIT, "addr - inbnd %p obnd %p\n",
+ pm8001_ha->inbnd_q_tbl_addr,
+ pm8001_ha->outbnd_q_tbl_addr);
+ pm8001_dbg(pm8001_ha, INIT, "addr - pspa %p ivt %p\n",
+ pm8001_ha->pspa_q_tbl_addr,
+ pm8001_ha->ivt_tbl_addr);
}
/**
@@ -885,7 +1203,12 @@
(THERMAL_ENABLE << 8) | page_code;
payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8);
- rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ pm8001_dbg(pm8001_ha, DEV,
+ "Setting up thermal config. cfg_pg 0 0x%x cfg_pg 1 0x%x\n",
+ payload.cfg_pg[0], payload.cfg_pg[1]);
+
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
if (rc)
pm8001_tag_free(pm8001_ha, tag);
return rc;
@@ -937,37 +1260,30 @@
| SAS_COPNRJT_RTRY_THR;
SASConfigPage.MAX_AIP = SAS_MAX_AIP;
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("SASConfigPage.pageCode "
- "0x%08x\n", SASConfigPage.pageCode));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("SASConfigPage.MST_MSI "
- " 0x%08x\n", SASConfigPage.MST_MSI));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("SASConfigPage.STP_SSP_MCT_TMO "
- " 0x%08x\n", SASConfigPage.STP_SSP_MCT_TMO));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("SASConfigPage.STP_FRM_TMO "
- " 0x%08x\n", SASConfigPage.STP_FRM_TMO));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("SASConfigPage.STP_IDLE_TMO "
- " 0x%08x\n", SASConfigPage.STP_IDLE_TMO));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("SASConfigPage.OPNRJT_RTRY_INTVL "
- " 0x%08x\n", SASConfigPage.OPNRJT_RTRY_INTVL));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO "
- " 0x%08x\n", SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR "
- " 0x%08x\n", SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR));
- PM8001_INIT_DBG(pm8001_ha, pm8001_printk("SASConfigPage.MAX_AIP "
- " 0x%08x\n", SASConfigPage.MAX_AIP));
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.pageCode 0x%08x\n",
+ SASConfigPage.pageCode);
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.MST_MSI 0x%08x\n",
+ SASConfigPage.MST_MSI);
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_SSP_MCT_TMO 0x%08x\n",
+ SASConfigPage.STP_SSP_MCT_TMO);
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_FRM_TMO 0x%08x\n",
+ SASConfigPage.STP_FRM_TMO);
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_IDLE_TMO 0x%08x\n",
+ SASConfigPage.STP_IDLE_TMO);
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.OPNRJT_RTRY_INTVL 0x%08x\n",
+ SASConfigPage.OPNRJT_RTRY_INTVL);
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO 0x%08x\n",
+ SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO);
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR 0x%08x\n",
+ SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR);
+ pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.MAX_AIP 0x%08x\n",
+ SASConfigPage.MAX_AIP);
memcpy(&payload.cfg_pg, &SASConfigPage,
sizeof(SASProtocolTimerConfig_t));
- rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
if (rc)
pm8001_tag_free(pm8001_ha, tag);
@@ -1001,18 +1317,18 @@
SCRATCH_PAD3_SMB_ENABLED)
pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;
pm8001_ha->encrypt_info.status = 0;
- PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
- "Encryption: SCRATCH_PAD3_ENC_READY 0x%08X."
- "Cipher mode 0x%x Sec mode 0x%x status 0x%x\n",
- scratch3_value, pm8001_ha->encrypt_info.cipher_mode,
- pm8001_ha->encrypt_info.sec_mode,
- pm8001_ha->encrypt_info.status));
+ pm8001_dbg(pm8001_ha, INIT,
+ "Encryption: SCRATCH_PAD3_ENC_READY 0x%08X.Cipher mode 0x%x Sec mode 0x%x status 0x%x\n",
+ scratch3_value,
+ pm8001_ha->encrypt_info.cipher_mode,
+ pm8001_ha->encrypt_info.sec_mode,
+ pm8001_ha->encrypt_info.status);
ret = 0;
} else if ((scratch3_value & SCRATCH_PAD3_ENC_READY) ==
SCRATCH_PAD3_ENC_DISABLED) {
- PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
- "Encryption: SCRATCH_PAD3_ENC_DISABLED 0x%08X\n",
- scratch3_value));
+ pm8001_dbg(pm8001_ha, INIT,
+ "Encryption: SCRATCH_PAD3_ENC_DISABLED 0x%08X\n",
+ scratch3_value);
pm8001_ha->encrypt_info.status = 0xFFFFFFFF;
pm8001_ha->encrypt_info.cipher_mode = 0;
pm8001_ha->encrypt_info.sec_mode = 0;
@@ -1032,12 +1348,12 @@
if ((scratch3_value & SCRATCH_PAD3_SM_MASK) ==
SCRATCH_PAD3_SMB_ENABLED)
pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;
- PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
- "Encryption: SCRATCH_PAD3_DIS_ERR 0x%08X."
- "Cipher mode 0x%x sec mode 0x%x status 0x%x\n",
- scratch3_value, pm8001_ha->encrypt_info.cipher_mode,
- pm8001_ha->encrypt_info.sec_mode,
- pm8001_ha->encrypt_info.status));
+ pm8001_dbg(pm8001_ha, INIT,
+ "Encryption: SCRATCH_PAD3_DIS_ERR 0x%08X.Cipher mode 0x%x sec mode 0x%x status 0x%x\n",
+ scratch3_value,
+ pm8001_ha->encrypt_info.cipher_mode,
+ pm8001_ha->encrypt_info.sec_mode,
+ pm8001_ha->encrypt_info.status);
} else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) ==
SCRATCH_PAD3_ENC_ENA_ERR) {
@@ -1055,12 +1371,12 @@
SCRATCH_PAD3_SMB_ENABLED)
pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB;
- PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
- "Encryption: SCRATCH_PAD3_ENA_ERR 0x%08X."
- "Cipher mode 0x%x sec mode 0x%x status 0x%x\n",
- scratch3_value, pm8001_ha->encrypt_info.cipher_mode,
- pm8001_ha->encrypt_info.sec_mode,
- pm8001_ha->encrypt_info.status));
+ pm8001_dbg(pm8001_ha, INIT,
+ "Encryption: SCRATCH_PAD3_ENA_ERR 0x%08X.Cipher mode 0x%x sec mode 0x%x status 0x%x\n",
+ scratch3_value,
+ pm8001_ha->encrypt_info.cipher_mode,
+ pm8001_ha->encrypt_info.sec_mode,
+ pm8001_ha->encrypt_info.status);
}
return ret;
}
@@ -1090,7 +1406,12 @@
payload.new_curidx_ksop = ((1 << 24) | (1 << 16) | (1 << 8) |
KEK_MGMT_SUBOP_KEYCARDUPDATE);
- rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ pm8001_dbg(pm8001_ha, DEV,
+ "Saving Encryption info to flash. payload 0x%x\n",
+ payload.new_curidx_ksop);
+
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
if (rc)
pm8001_tag_free(pm8001_ha, tag);
@@ -1108,8 +1429,7 @@
/* check the firmware status */
if (-1 == check_fw_ready(pm8001_ha)) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Firmware is not ready!\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "Firmware is not ready!\n");
return -EBUSY;
}
@@ -1127,15 +1447,13 @@
/* update main config table ,inbound table and outbound table */
update_main_config_table(pm8001_ha);
- for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++)
+ for (i = 0; i < pm8001_ha->max_q_num; i++) {
update_inbnd_queue_table(pm8001_ha, i);
- for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++)
update_outbnd_queue_table(pm8001_ha, i);
-
+ }
/* notify firmware update finished and check initialization status */
if (0 == mpi_init_check(pm8001_ha)) {
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("MPI initialize successful!\n"));
+ pm8001_dbg(pm8001_ha, INIT, "MPI initialize successful!\n");
} else
return -EBUSY;
@@ -1144,16 +1462,13 @@
/* Check for encryption */
if (pm8001_ha->chip->encrypt) {
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Checking for encryption\n"));
+ pm8001_dbg(pm8001_ha, INIT, "Checking for encryption\n");
ret = pm80xx_get_encrypt_info(pm8001_ha);
if (ret == -1) {
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("Encryption error !!\n"));
+ pm8001_dbg(pm8001_ha, INIT, "Encryption error !!\n");
if (pm8001_ha->encrypt_info.status == 0x81) {
- PM8001_INIT_DBG(pm8001_ha, pm8001_printk(
- "Encryption enabled with error."
- "Saving encryption key to flash\n"));
+ pm8001_dbg(pm8001_ha, INIT,
+ "Encryption enabled with error.Saving encryption key to flash\n");
pm80xx_encrypt_update(pm8001_ha);
}
}
@@ -1173,9 +1488,9 @@
/* wait until Inbound DoorBell Clear Register toggled */
if (IS_SPCV_12G(pm8001_ha->pdev)) {
- max_wait_count = 4 * 1000 * 1000;/* 4 sec */
+ max_wait_count = 30 * 1000 * 1000; /* 30 sec */
} else {
- max_wait_count = 2 * 1000 * 1000;/* 2 sec */
+ max_wait_count = 15 * 1000 * 1000; /* 15 sec */
}
do {
udelay(1);
@@ -1184,8 +1499,7 @@
} while ((value != 0) && (--max_wait_count));
if (!max_wait_count) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("TIMEOUT:IBDB value/=%x\n", value));
+ pm8001_dbg(pm8001_ha, FAIL, "TIMEOUT:IBDB value/=%x\n", value);
return -1;
}
@@ -1202,9 +1516,8 @@
break;
} while (--max_wait_count);
if (!max_wait_count) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk(" TIME OUT MPI State = 0x%x\n",
- gst_len_mpistate & GST_MPI_STATE_MASK));
+ pm8001_dbg(pm8001_ha, FAIL, " TIME OUT MPI State = 0x%x\n",
+ gst_len_mpistate & GST_MPI_STATE_MASK);
return -1;
}
@@ -1228,34 +1541,41 @@
if (!pm8001_ha->controller_fatal_error) {
/* Check if MPI is in ready state to reset */
if (mpi_uninit_check(pm8001_ha) != 0) {
- regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
- "MPI state is not ready scratch1 :0x%x\n",
- regval));
- return -1;
+ u32 r0 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0);
+ u32 r1 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+ u32 r2 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2);
+ u32 r3 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3);
+ pm8001_dbg(pm8001_ha, FAIL,
+ "MPI state is not ready scratch: %x:%x:%x:%x\n",
+ r0, r1, r2, r3);
+ /* if things aren't ready but the bootloader is ok then
+ * try the reset anyway.
+ */
+ if (r1 & SCRATCH_PAD1_BOOTSTATE_MASK)
+ return -1;
}
}
/* checked for reset register normal state; 0x0 */
regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("reset register before write : 0x%x\n", regval));
+ pm8001_dbg(pm8001_ha, INIT, "reset register before write : 0x%x\n",
+ regval);
pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, SPCv_NORMAL_RESET_VALUE);
- mdelay(500);
+ msleep(500);
regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("reset register after write 0x%x\n", regval));
+ pm8001_dbg(pm8001_ha, INIT, "reset register after write 0x%x\n",
+ regval);
if ((regval & SPCv_SOFT_RESET_READ_MASK) ==
SPCv_SOFT_RESET_NORMAL_RESET_OCCURED) {
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" soft reset successful [regval: 0x%x]\n",
- regval));
+ pm8001_dbg(pm8001_ha, MSG,
+ " soft reset successful [regval: 0x%x]\n",
+ regval);
} else {
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" soft reset failed [regval: 0x%x]\n",
- regval));
+ pm8001_dbg(pm8001_ha, MSG,
+ " soft reset failed [regval: 0x%x]\n",
+ regval);
/* check bootloader is successfully executed or in HDA mode */
bootloader_state =
@@ -1263,28 +1583,27 @@
SCRATCH_PAD1_BOOTSTATE_MASK;
if (bootloader_state == SCRATCH_PAD1_BOOTSTATE_HDA_SEEPROM) {
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "Bootloader state - HDA mode SEEPROM\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "Bootloader state - HDA mode SEEPROM\n");
} else if (bootloader_state ==
SCRATCH_PAD1_BOOTSTATE_HDA_BOOTSTRAP) {
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "Bootloader state - HDA mode Bootstrap Pin\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "Bootloader state - HDA mode Bootstrap Pin\n");
} else if (bootloader_state ==
SCRATCH_PAD1_BOOTSTATE_HDA_SOFTRESET) {
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "Bootloader state - HDA mode soft reset\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "Bootloader state - HDA mode soft reset\n");
} else if (bootloader_state ==
SCRATCH_PAD1_BOOTSTATE_CRIT_ERROR) {
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "Bootloader state-HDA mode critical error\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "Bootloader state-HDA mode critical error\n");
}
return -EBUSY;
}
/* check the firmware status after reset */
if (-1 == check_fw_ready(pm8001_ha)) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Firmware is not ready!\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "Firmware is not ready!\n");
/* check iButton feature support for motherboard controller */
if (pm8001_ha->pdev->subsystem_vendor !=
PCI_VENDOR_ID_ADAPTEC2 &&
@@ -1296,21 +1615,18 @@
ibutton1 = pm8001_cr32(pm8001_ha, 0,
MSGU_HOST_SCRATCH_PAD_7);
if (!ibutton0 && !ibutton1) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("iButton Feature is"
- " not Available!!!\n"));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "iButton Feature is not Available!!!\n");
return -EBUSY;
}
if (ibutton0 == 0xdeadbeef && ibutton1 == 0xdeadbeef) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("CRC Check for iButton"
- " Feature Failed!!!\n"));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "CRC Check for iButton Feature Failed!!!\n");
return -EBUSY;
}
}
}
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("SPCv soft reset Complete\n"));
+ pm8001_dbg(pm8001_ha, INIT, "SPCv soft reset Complete\n");
return 0;
}
@@ -1318,13 +1634,11 @@
{
u32 i;
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("chip reset start\n"));
+ pm8001_dbg(pm8001_ha, INIT, "chip reset start\n");
/* do SPCv chip reset. */
pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, 0x11);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("SPC soft reset Complete\n"));
+ pm8001_dbg(pm8001_ha, INIT, "SPC soft reset Complete\n");
/* Check this ..whether delay is required or no */
/* delay 10 usec */
@@ -1336,8 +1650,7 @@
mdelay(1);
} while ((--i) != 0);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("chip reset finished\n"));
+ pm8001_dbg(pm8001_ha, INIT, "chip reset finished\n");
}
/**
@@ -1364,6 +1677,7 @@
/**
* pm8001_chip_interrupt_enable - enable PM8001 chip interrupt
* @pm8001_ha: our hba card information
+ * @vec: interrupt number to enable
*/
static void
pm80xx_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec)
@@ -1382,6 +1696,7 @@
/**
* pm8001_chip_interrupt_disable- disable PM8001 chip interrupt
* @pm8001_ha: our hba card information
+ * @vec: interrupt number to disable
*/
static void
pm80xx_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec)
@@ -1411,15 +1726,14 @@
int ret;
if (!pm8001_ha_dev) {
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "dev is null\n");
return;
}
task = sas_alloc_slow_task(GFP_ATOMIC);
if (!task) {
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot "
- "allocate task\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task\n");
return;
}
@@ -1443,7 +1757,9 @@
task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
task_abort.tag = cpu_to_le32(ccb_tag);
- ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort,
+ sizeof(task_abort), 0);
+ pm8001_dbg(pm8001_ha, FAIL, "Executing abort task end\n");
if (ret) {
sas_free_task(task);
pm8001_tag_free(pm8001_ha, ccb_tag);
@@ -1466,8 +1782,7 @@
task = sas_alloc_slow_task(GFP_ATOMIC);
if (!task) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("cannot allocate task !!!\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task !!!\n");
return;
}
task->task_done = pm8001_task_done;
@@ -1475,8 +1790,7 @@
res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
if (res) {
sas_free_task(task);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("cannot allocate tag !!!\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "cannot allocate tag !!!\n");
return;
}
@@ -1487,8 +1801,8 @@
if (!dev) {
sas_free_task(task);
pm8001_tag_free(pm8001_ha, ccb_tag);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Domain device cannot be allocated\n"));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "Domain device cannot be allocated\n");
return;
}
@@ -1519,7 +1833,9 @@
sata_cmd.ncqtag_atap_dir_m_dad |= ((0x1 << 7) | (0x5 << 9));
memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis));
- res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0);
+ res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd,
+ sizeof(sata_cmd), 0);
+ pm8001_dbg(pm8001_ha, FAIL, "Executing read log end\n");
if (res) {
sas_free_task(task);
pm8001_tag_free(pm8001_ha, ccb_tag);
@@ -1565,23 +1881,24 @@
t = ccb->task;
if (status && status != IO_UNDERFLOW)
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("sas IO status 0x%x\n", status));
+ pm8001_dbg(pm8001_ha, FAIL, "sas IO status 0x%x\n", status);
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
ts = &t->task_status;
+
+ pm8001_dbg(pm8001_ha, DEV,
+ "tag::0x%x, status::0x%x task::0x%p\n", tag, status, t);
+
/* Print sas address of IO failed device */
if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) &&
(status != IO_UNDERFLOW))
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SAS Address of IO Failure Drive"
- ":%016llx", SAS_ADDR(t->dev->sas_addr)));
+ pm8001_dbg(pm8001_ha, FAIL, "SAS Address of IO Failure Drive:%016llx\n",
+ SAS_ADDR(t->dev->sas_addr));
switch (status) {
case IO_SUCCESS:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_SUCCESS ,param = 0x%x\n",
- param));
+ pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS ,param = 0x%x\n",
+ param);
if (param == 0) {
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_GOOD;
@@ -1593,73 +1910,83 @@
sas_ssp_task_response(pm8001_ha->dev, t, iu);
}
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_ABORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_ABORTED IOMB Tag\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB Tag\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_ABORTED_TASK;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_UNDERFLOW:
/* SSP Completion with error */
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_UNDERFLOW ,param = 0x%x\n",
- param));
+ pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW ,param = 0x%x\n",
+ param);
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_UNDERRUN;
ts->residual = param;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_NO_DEVICE:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_NO_DEVICE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n");
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_PHY_DOWN;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
/* Force the midlayer to retry */
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_PHY_NOT_READY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_INVALID_SSP_RSP_FRAME:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_INVALID_SSP_RSP_FRAME\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_XFER_ERROR_INVALID_SSP_RSP_FRAME\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_EPROTO;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
@@ -1667,8 +1994,7 @@
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
@@ -1678,67 +2004,78 @@
IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
break;
case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_BAD_DEST;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_NAK_RECEIVED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_NAK_R_ERR;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_DMA:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_DMA\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_DMA\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_OPEN_RETRY_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_OFFSET_MISMATCH:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_PORT_IN_RESET:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_PORT_IN_RESET\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_DS_NON_OPERATIONAL:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_DS_NON_OPERATIONAL\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
if (!t->uldd_task)
@@ -1747,54 +2084,58 @@
IO_DS_NON_OPERATIONAL);
break;
case IO_DS_IN_RECOVERY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_DS_IN_RECOVERY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_TM_TAG_NOT_FOUND:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_TM_TAG_NOT_FOUND\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_TM_TAG_NOT_FOUND\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_SSP_EXT_IU_ZERO_LEN_ERROR:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_SSP_EXT_IU_ZERO_LEN_ERROR\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_SSP_EXT_IU_ZERO_LEN_ERROR\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
default:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("Unknown status 0x%x\n", status));
+ pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status);
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
}
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("scsi_status = 0x%x\n ",
- psspPayload->ssp_resp_iu.status));
+ pm8001_dbg(pm8001_ha, IO, "scsi_status = 0x%x\n ",
+ psspPayload->ssp_resp_iu.status);
spin_lock_irqsave(&t->task_state_lock, flags);
t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
t->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
t->task_state_flags |= SAS_TASK_STATE_DONE;
if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
spin_unlock_irqrestore(&t->task_state_lock, flags);
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
- "task 0x%p done with io_status 0x%x resp 0x%x "
- "stat 0x%x but aborted by upper layer!\n",
- t, status, ts->resp, ts->stat));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
+ t, status, ts->resp, ts->stat);
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
if (t->slow_task)
complete(&t->slow_task->completion);
- pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
} else {
spin_unlock_irqrestore(&t->task_state_lock, flags);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
@@ -1821,52 +2162,47 @@
t = ccb->task;
pm8001_dev = ccb->device;
if (event)
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("sas IO status 0x%x\n", event));
+ pm8001_dbg(pm8001_ha, FAIL, "sas IO status 0x%x\n", event);
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
ts = &t->task_status;
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n",
- port_id, tag, event));
+ pm8001_dbg(pm8001_ha, IOERR, "port_id:0x%x, tag:0x%x, event:0x%x\n",
+ port_id, tag, event);
switch (event) {
case IO_OVERFLOW:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n");)
+ pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
ts->residual = 0;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
pm8001_handle_event(pm8001_ha, t, IO_XFER_ERROR_BREAK);
return;
case IO_XFER_ERROR_PHY_NOT_READY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_EPROTO;
break;
case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
break;
case IO_OPEN_CNX_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
@@ -1877,8 +2213,7 @@
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
@@ -1888,94 +2223,86 @@
IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
break;
case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_BAD_DEST;
break;
case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_CONN_RATE;
break;
case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
break;
case IO_XFER_ERROR_NAK_RECEIVED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_NAK_R_ERR;
break;
case IO_XFER_OPEN_RETRY_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
pm8001_handle_event(pm8001_ha, t, IO_XFER_OPEN_RETRY_TIMEOUT);
return;
case IO_XFER_ERROR_UNEXPECTED_PHASE:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_UNEXPECTED_PHASE\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
break;
case IO_XFER_ERROR_XFER_RDY_OVERRUN:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_XFER_RDY_OVERRUN\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_XFER_RDY_OVERRUN\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
break;
case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
break;
case IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
break;
case IO_XFER_ERROR_OFFSET_MISMATCH:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
break;
case IO_XFER_ERROR_XFER_ZERO_DATA_LEN:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
break;
case IO_XFER_ERROR_INTERNAL_CRC_ERROR:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n"));
+ pm8001_dbg(pm8001_ha, IOERR,
+ "IO_XFR_ERROR_INTERNAL_CRC_ERROR\n");
/* TBC: used default set values */
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
break;
case IO_XFER_CMD_FRAME_ISSUED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_CMD_FRAME_ISSUED\n");
return;
default:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("Unknown status 0x%x\n", event));
+ pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", event);
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
@@ -1987,10 +2314,9 @@
t->task_state_flags |= SAS_TASK_STATE_DONE;
if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
spin_unlock_irqrestore(&t->task_state_lock, flags);
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
- "task 0x%p done with event 0x%x resp 0x%x "
- "stat 0x%x but aborted by upper layer!\n",
- t, event, ts->resp, ts->stat));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "task 0x%p done with event 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
+ t, event, ts->resp, ts->stat);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
} else {
spin_unlock_irqrestore(&t->task_state_lock, flags);
@@ -2025,8 +2351,7 @@
tag = le32_to_cpu(psataPayload->tag);
if (!tag) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("tag null\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "tag null\n");
return;
}
ccb = &pm8001_ha->ccb_info[tag];
@@ -2035,8 +2360,7 @@
t = ccb->task;
pm8001_dev = ccb->device;
} else {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("ccb null\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "ccb null\n");
return;
}
@@ -2044,24 +2368,27 @@
if (t->dev && (t->dev->lldd_dev))
pm8001_dev = t->dev->lldd_dev;
} else {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("task null\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "task null\n");
return;
}
if ((pm8001_dev && !(pm8001_dev->id & NCQ_READ_LOG_FLAG))
&& unlikely(!t || !t->lldd_task || !t->dev)) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("task or dev null\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "task or dev null\n");
return;
}
ts = &t->task_status;
if (!ts) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("ts null\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "ts null\n");
return;
}
+
+ if (unlikely(status))
+ pm8001_dbg(pm8001_ha, IOERR,
+ "status:0x%x, tag:0x%x, task::0x%p\n",
+ status, tag, t);
+
/* Print sas address of IO failed device */
if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) &&
(status != IO_UNDERFLOW)) {
@@ -2092,20 +2419,20 @@
& 0xff000000)) +
pm8001_dev->attached_phy +
0x10);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SAS Address of IO Failure Drive:"
- "%08x%08x", temp_sata_addr_hi,
- temp_sata_addr_low));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "SAS Address of IO Failure Drive:%08x%08x\n",
+ temp_sata_addr_hi,
+ temp_sata_addr_low);
} else {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SAS Address of IO Failure Drive:"
- "%016llx", SAS_ADDR(t->dev->sas_addr)));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "SAS Address of IO Failure Drive:%016llx\n",
+ SAS_ADDR(t->dev->sas_addr));
}
}
switch (status) {
case IO_SUCCESS:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS\n");
if (param == 0) {
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_GOOD;
@@ -2127,94 +2454,100 @@
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_PROTO_RESPONSE;
ts->residual = param;
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("SAS_PROTO_RESPONSE len = %d\n",
- param));
+ pm8001_dbg(pm8001_ha, IO,
+ "SAS_PROTO_RESPONSE len = %d\n",
+ param);
sata_resp = &psataPayload->sata_resp[0];
resp = (struct ata_task_resp *)ts->buf;
if (t->ata_task.dma_xfer == 0 &&
t->data_dir == DMA_FROM_DEVICE) {
len = sizeof(struct pio_setup_fis);
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("PIO read len = %d\n", len));
+ pm8001_dbg(pm8001_ha, IO,
+ "PIO read len = %d\n", len);
} else if (t->ata_task.use_ncq) {
len = sizeof(struct set_dev_bits_fis);
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("FPDMA len = %d\n", len));
+ pm8001_dbg(pm8001_ha, IO, "FPDMA len = %d\n",
+ len);
} else {
len = sizeof(struct dev_to_host_fis);
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("other len = %d\n", len));
+ pm8001_dbg(pm8001_ha, IO, "other len = %d\n",
+ len);
}
if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) {
resp->frame_len = len;
memcpy(&resp->ending_fis[0], sata_resp, len);
ts->buf_valid_size = sizeof(*resp);
} else
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("response to large\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "response too large\n");
}
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_ABORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_ABORTED IOMB Tag\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB Tag\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_ABORTED_TASK;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
/* following cases are to do cases */
case IO_UNDERFLOW:
/* SATA Completion with error */
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_UNDERFLOW param = %d\n", param));
+ pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW param = %d\n", param);
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_UNDERRUN;
ts->residual = param;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_NO_DEVICE:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_NO_DEVICE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n");
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_PHY_DOWN;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_INTERRUPTED;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_PHY_NOT_READY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_EPROTO;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
@@ -2222,8 +2555,7 @@
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
if (!t->uldd_task) {
@@ -2237,8 +2569,8 @@
}
break;
case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_BAD_DEST;
@@ -2253,15 +2585,17 @@
}
break;
case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_CONN_RATE;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
if (!t->uldd_task) {
@@ -2275,57 +2609,65 @@
}
break;
case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_NAK_RECEIVED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_NAK_R_ERR;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_ACK_NAK_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_NAK_R_ERR;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_DMA:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_DMA\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_DMA\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_ABORTED_TASK;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_SATA_LINK_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_SATA_LINK_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_SATA_LINK_TIMEOUT\n");
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_DEV_NO_RESPONSE;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_REJECTED_NCQ_MODE:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_REJECTED_NCQ_MODE\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_UNDERRUN;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_OPEN_RETRY_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_PORT_IN_RESET:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_PORT_IN_RESET\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_DS_NON_OPERATIONAL:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_DS_NON_OPERATIONAL\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
if (!t->uldd_task) {
@@ -2338,14 +2680,14 @@
}
break;
case IO_DS_IN_RECOVERY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_DS_IN_RECOVERY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_DS_IN_ERROR:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_DS_IN_ERROR\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_ERROR\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
if (!t->uldd_task) {
@@ -2358,18 +2700,21 @@
}
break;
case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
default:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("Unknown status 0x%x\n", status));
+ pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status);
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
+ if (pm8001_dev)
+ atomic_dec(&pm8001_dev->running_req);
break;
}
spin_lock_irqsave(&t->task_state_lock, flags);
@@ -2378,13 +2723,12 @@
t->task_state_flags |= SAS_TASK_STATE_DONE;
if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
spin_unlock_irqrestore(&t->task_state_lock, flags);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("task 0x%p done with io_status 0x%x"
- " resp 0x%x stat 0x%x but aborted by upper layer!\n",
- t, status, ts->resp, ts->stat));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
+ t, status, ts->resp, ts->stat);
+ pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
if (t->slow_task)
complete(&t->slow_task->completion);
- pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
} else {
spin_unlock_irqrestore(&t->task_state_lock, flags);
pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
@@ -2412,13 +2756,11 @@
t = ccb->task;
pm8001_dev = ccb->device;
} else {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("No CCB !!!. returning\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "No CCB !!!. returning\n");
return;
}
if (event)
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("SATA EVENT 0x%x\n", event));
+ pm8001_dbg(pm8001_ha, FAIL, "SATA EVENT 0x%x\n", event);
/* Check if this is NCQ error */
if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) {
@@ -2431,54 +2773,49 @@
}
if (unlikely(!t || !t->lldd_task || !t->dev)) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("task or dev null\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "task or dev null\n");
return;
}
ts = &t->task_status;
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n",
- port_id, tag, event));
+ pm8001_dbg(pm8001_ha, IOERR, "port_id:0x%x, tag:0x%x, event:0x%x\n",
+ port_id, tag, event);
switch (event) {
case IO_OVERFLOW:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
ts->residual = 0;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_XFER_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_INTERRUPTED;
break;
case IO_XFER_ERROR_PHY_NOT_READY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_EPROTO;
break;
case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
break;
case IO_OPEN_CNX_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
@@ -2489,8 +2826,8 @@
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_DEV_NO_RESPONSE;
if (!t->uldd_task) {
@@ -2504,107 +2841,96 @@
}
break;
case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_BAD_DEST;
break;
case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_CONN_RATE;
break;
case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
break;
case IO_XFER_ERROR_NAK_RECEIVED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_NAK_R_ERR;
break;
case IO_XFER_ERROR_PEER_ABORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_PEER_ABORTED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PEER_ABORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_NAK_R_ERR;
break;
case IO_XFER_ERROR_REJECTED_NCQ_MODE:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_REJECTED_NCQ_MODE\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_UNDERRUN;
break;
case IO_XFER_OPEN_RETRY_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
case IO_XFER_ERROR_UNEXPECTED_PHASE:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_UNEXPECTED_PHASE\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
case IO_XFER_ERROR_XFER_RDY_OVERRUN:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_XFER_RDY_OVERRUN\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_XFER_RDY_OVERRUN\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
case IO_XFER_ERROR_OFFSET_MISMATCH:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
case IO_XFER_ERROR_XFER_ZERO_DATA_LEN:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
case IO_XFER_CMD_FRAME_ISSUED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_CMD_FRAME_ISSUED\n");
break;
case IO_XFER_PIO_SETUP_ERROR:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_PIO_SETUP_ERROR\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_PIO_SETUP_ERROR\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
case IO_XFER_ERROR_INTERNAL_CRC_ERROR:
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n"));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "IO_XFR_ERROR_INTERNAL_CRC_ERROR\n");
/* TBC: used default set values */
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
case IO_XFER_DMA_ACTIVATE_TIMEOUT:
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("IO_XFR_DMA_ACTIVATE_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "IO_XFR_DMA_ACTIVATE_TIMEOUT\n");
/* TBC: used default set values */
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
break;
default:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("Unknown status 0x%x\n", event));
+ pm8001_dbg(pm8001_ha, IO, "Unknown status 0x%x\n", event);
/* not allowed case. Therefore, return failed status */
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_TO;
@@ -2616,10 +2942,9 @@
t->task_state_flags |= SAS_TASK_STATE_DONE;
if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
spin_unlock_irqrestore(&t->task_state_lock, flags);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("task 0x%p done with io_status 0x%x"
- " resp 0x%x stat 0x%x but aborted by upper layer!\n",
- t, event, ts->resp, ts->stat));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n",
+ t, event, ts->resp, ts->stat);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
} else {
spin_unlock_irqrestore(&t->task_state_lock, flags);
@@ -2652,91 +2977,87 @@
ts = &t->task_status;
pm8001_dev = ccb->device;
if (status)
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("smp IO status 0x%x\n", status));
+ pm8001_dbg(pm8001_ha, FAIL, "smp IO status 0x%x\n", status);
if (unlikely(!t || !t->lldd_task || !t->dev))
return;
+ pm8001_dbg(pm8001_ha, DEV, "tag::0x%x status::0x%x\n", tag, status);
+
switch (status) {
case IO_SUCCESS:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_GOOD;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
if (pm8001_ha->smp_exp_mode == SMP_DIRECT) {
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("DIRECT RESPONSE Length:%d\n",
- param));
+ pm8001_dbg(pm8001_ha, IO,
+ "DIRECT RESPONSE Length:%d\n",
+ param);
pdma_respaddr = (char *)(phys_to_virt(cpu_to_le64
((u64)sg_dma_address
(&t->smp_task.smp_resp))));
for (i = 0; i < param; i++) {
*(pdma_respaddr+i) = psmpPayload->_r_a[i];
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "SMP Byte%d DMA data 0x%x psmp 0x%x\n",
- i, *(pdma_respaddr+i),
- psmpPayload->_r_a[i]));
+ pm8001_dbg(pm8001_ha, IO,
+ "SMP Byte%d DMA data 0x%x psmp 0x%x\n",
+ i, *(pdma_respaddr + i),
+ psmpPayload->_r_a[i]);
}
}
break;
case IO_ABORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_ABORTED IOMB\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_ABORTED_TASK;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_OVERFLOW:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DATA_OVERRUN;
ts->residual = 0;
if (pm8001_dev)
- pm8001_dev->running_req--;
+ atomic_dec(&pm8001_dev->running_req);
break;
case IO_NO_DEVICE:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_PHY_DOWN;
break;
case IO_ERROR_HW_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_ERROR_HW_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_ERROR_HW_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_BUSY;
break;
case IO_XFER_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_BUSY;
break;
case IO_XFER_ERROR_PHY_NOT_READY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAM_STAT_BUSY;
break;
case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
break;
case IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
break;
case IO_OPEN_CNX_ERROR_BREAK:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_CONT0;
@@ -2747,8 +3068,7 @@
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_UNKNOWN;
@@ -2757,75 +3077,68 @@
IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
break;
case IO_OPEN_CNX_ERROR_BAD_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_BAD_DEST;
break;
case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(\
- "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_CONN_RATE;
break;
case IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_WRONG_DEST;
break;
case IO_XFER_ERROR_RX_FRAME:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_ERROR_RX_FRAME\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_RX_FRAME\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
break;
case IO_XFER_OPEN_RETRY_TIMEOUT:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_ERROR_INTERNAL_SMP_RESOURCE:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_ERROR_INTERNAL_SMP_RESOURCE\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_ERROR_INTERNAL_SMP_RESOURCE\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_QUEUE_FULL;
break;
case IO_PORT_IN_RESET:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_PORT_IN_RESET\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_DS_NON_OPERATIONAL:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_DS_NON_OPERATIONAL\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
break;
case IO_DS_IN_RECOVERY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_DS_IN_RECOVERY\n"));
+ pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"));
+ pm8001_dbg(pm8001_ha, IO,
+ "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n");
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_OPEN_REJECT;
ts->open_rej_reason = SAS_OREJ_RSVD_RETRY;
break;
default:
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("Unknown status 0x%x\n", status));
+ pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status);
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_DEV_NO_RESPONSE;
/* not allowed case. Therefore, return failed status */
@@ -2837,10 +3150,9 @@
t->task_state_flags |= SAS_TASK_STATE_DONE;
if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) {
spin_unlock_irqrestore(&t->task_state_lock, flags);
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
- "task 0x%p done with io_status 0x%x resp 0x%x"
- "stat 0x%x but aborted by upper layer!\n",
- t, status, ts->resp, ts->stat));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "task 0x%p done with io_status 0x%x resp 0x%xstat 0x%x but aborted by upper layer!\n",
+ t, status, ts->resp, ts->stat);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
} else {
spin_unlock_irqrestore(&t->task_state_lock, flags);
@@ -2875,7 +3187,8 @@
((phyId & 0xFF) << 24) | (port_id & 0xFF));
payload.param0 = cpu_to_le32(param0);
payload.param1 = cpu_to_le32(param1);
- pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
}
static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
@@ -2929,45 +3242,40 @@
u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);
struct pm8001_port *port = &pm8001_ha->port[port_id];
- struct sas_ha_struct *sas_ha = pm8001_ha->sas;
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
unsigned long flags;
u8 deviceType = pPayload->sas_identify.dev_type;
port->port_state = portstate;
port->wide_port_phymap |= (1U << phy_id);
phy->phy_state = PHY_STATE_LINK_UP_SPCV;
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "portid:%d; phyid:%d; linkrate:%d; "
- "portstate:%x; devicetype:%x\n",
- port_id, phy_id, link_rate, portstate, deviceType));
+ pm8001_dbg(pm8001_ha, MSG,
+ "portid:%d; phyid:%d; linkrate:%d; portstate:%x; devicetype:%x\n",
+ port_id, phy_id, link_rate, portstate, deviceType);
switch (deviceType) {
case SAS_PHY_UNUSED:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("device type no device.\n"));
+ pm8001_dbg(pm8001_ha, MSG, "device type no device.\n");
break;
case SAS_END_DEVICE:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk("end device.\n"));
+ pm8001_dbg(pm8001_ha, MSG, "end device.\n");
pm80xx_chip_phy_ctl_req(pm8001_ha, phy_id,
PHY_NOTIFY_ENABLE_SPINUP);
port->port_attached = 1;
pm8001_get_lrate_mode(phy, link_rate);
break;
case SAS_EDGE_EXPANDER_DEVICE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("expander device.\n"));
+ pm8001_dbg(pm8001_ha, MSG, "expander device.\n");
port->port_attached = 1;
pm8001_get_lrate_mode(phy, link_rate);
break;
case SAS_FANOUT_EXPANDER_DEVICE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("fanout expander device.\n"));
+ pm8001_dbg(pm8001_ha, MSG, "fanout expander device.\n");
port->port_attached = 1;
pm8001_get_lrate_mode(phy, link_rate);
break;
default:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("unknown device type(%x)\n", deviceType));
+ pm8001_dbg(pm8001_ha, DEVIO, "unknown device type(%x)\n",
+ deviceType);
break;
}
phy->phy_type |= PORT_TYPE_SAS;
@@ -2978,7 +3286,7 @@
else if (phy->identify.device_type != SAS_PHY_UNUSED)
phy->identify.target_port_protocols = SAS_PROTOCOL_SMP;
phy->sas_phy.oob_mode = SAS_OOB_MODE;
- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
+ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);
memcpy(phy->frame_rcvd, &pPayload->sas_identify,
sizeof(struct sas_identify_frame)-4);
@@ -2986,7 +3294,7 @@
pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr);
spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags);
if (pm8001_ha->flags == PM8001F_RUN_TIME)
- mdelay(200);/*delay a moment to wait disk to spinup*/
+ mdelay(200); /* delay a moment to wait for disk to spin up */
pm8001_bytes_dmaed(pm8001_ha, phy_id);
}
@@ -3012,12 +3320,11 @@
u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F);
struct pm8001_port *port = &pm8001_ha->port[port_id];
- struct sas_ha_struct *sas_ha = pm8001_ha->sas;
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
unsigned long flags;
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "port id %d, phy id %d link_rate %d portstate 0x%x\n",
- port_id, phy_id, link_rate, portstate));
+ pm8001_dbg(pm8001_ha, DEVIO,
+ "port id %d, phy id %d link_rate %d portstate 0x%x\n",
+ port_id, phy_id, link_rate, portstate);
port->port_state = portstate;
phy->phy_state = PHY_STATE_LINK_UP_SPCV;
@@ -3026,7 +3333,7 @@
phy->phy_type |= PORT_TYPE_SATA;
phy->phy_attached = 1;
phy->sas_phy.oob_mode = SATA_OOB_MODE;
- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
+ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE);
spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags);
memcpy(phy->frame_rcvd, ((u8 *)&pPayload->sata_fis - 4),
sizeof(struct dev_to_host_fis));
@@ -3067,10 +3374,10 @@
case PORT_VALID:
break;
case PORT_INVALID:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" PortInvalid portID %d\n", port_id));
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" Last phy Down and port invalid\n"));
+ pm8001_dbg(pm8001_ha, MSG, " PortInvalid portID %d\n",
+ port_id);
+ pm8001_dbg(pm8001_ha, MSG,
+ " Last phy Down and port invalid\n");
if (port_sata) {
phy->phy_type = 0;
port->port_attached = 0;
@@ -3080,19 +3387,18 @@
sas_phy_disconnected(&phy->sas_phy);
break;
case PORT_IN_RESET:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" Port In Reset portID %d\n", port_id));
+ pm8001_dbg(pm8001_ha, MSG, " Port In Reset portID %d\n",
+ port_id);
break;
case PORT_NOT_ESTABLISHED:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" Phy Down and PORT_NOT_ESTABLISHED\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ " Phy Down and PORT_NOT_ESTABLISHED\n");
port->port_attached = 0;
break;
case PORT_LOSTCOMM:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" Phy Down and PORT_LOSTCOMM\n"));
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" Last phy Down and port invalid\n"));
+ pm8001_dbg(pm8001_ha, MSG, " Phy Down and PORT_LOSTCOMM\n");
+ pm8001_dbg(pm8001_ha, MSG,
+ " Last phy Down and port invalid\n");
if (port_sata) {
port->port_attached = 0;
phy->phy_type = 0;
@@ -3103,17 +3409,14 @@
break;
default:
port->port_attached = 0;
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" Phy Down and(default) = 0x%x\n",
- portstate));
+ pm8001_dbg(pm8001_ha, DEVIO,
+ " Phy Down and(default) = 0x%x\n",
+ portstate);
break;
}
- if (port_sata && (portstate != PORT_IN_RESET)) {
- struct sas_ha_struct *sas_ha = pm8001_ha->sas;
-
- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
- }
+ if (port_sata && (portstate != PORT_IN_RESET))
+ sas_notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL);
}
static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
@@ -3126,14 +3429,16 @@
le32_to_cpu(pPayload->phyid);
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("phy start resp status:0x%x, phyid:0x%x\n",
- status, phy_id));
- if (status == 0) {
+ pm8001_dbg(pm8001_ha, INIT,
+ "phy start resp status:0x%x, phyid:0x%x\n",
+ status, phy_id);
+ if (status == 0)
phy->phy_state = PHY_LINK_DOWN;
- if (pm8001_ha->flags == PM8001F_RUN_TIME &&
- phy->enable_completion != NULL)
- complete(phy->enable_completion);
+
+ if (pm8001_ha->flags == PM8001F_RUN_TIME &&
+ phy->enable_completion != NULL) {
+ complete(phy->enable_completion);
+ phy->enable_completion = NULL;
}
return 0;
@@ -3153,18 +3458,18 @@
u32 rht_lht = le32_to_cpu(pPayload->rht_lht);
if (thermal_event & 0x40) {
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "Thermal Event: Local high temperature violated!\n"));
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "Thermal Event: Measured local high temperature %d\n",
- ((rht_lht & 0xFF00) >> 8)));
+ pm8001_dbg(pm8001_ha, IO,
+ "Thermal Event: Local high temperature violated!\n");
+ pm8001_dbg(pm8001_ha, IO,
+ "Thermal Event: Measured local high temperature %d\n",
+ ((rht_lht & 0xFF00) >> 8));
}
if (thermal_event & 0x10) {
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "Thermal Event: Remote high temperature violated!\n"));
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "Thermal Event: Measured remote high temperature %d\n",
- ((rht_lht & 0xFF000000) >> 24)));
+ pm8001_dbg(pm8001_ha, IO,
+ "Thermal Event: Remote high temperature violated!\n");
+ pm8001_dbg(pm8001_ha, IO,
+ "Thermal Event: Measured remote high temperature %d\n",
+ ((rht_lht & 0xFF000000) >> 24));
}
return 0;
}
@@ -3193,149 +3498,134 @@
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
struct pm8001_port *port = &pm8001_ha->port[port_id];
struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id];
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("portid:%d phyid:%d event:0x%x status:0x%x\n",
- port_id, phy_id, eventType, status));
+ pm8001_dbg(pm8001_ha, DEV,
+ "portid:%d phyid:%d event:0x%x status:0x%x\n",
+ port_id, phy_id, eventType, status);
switch (eventType) {
case HW_EVENT_SAS_PHY_UP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PHY_START_STATUS\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_START_STATUS\n");
hw_event_sas_phy_up(pm8001_ha, piomb);
break;
case HW_EVENT_SATA_PHY_UP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_SATA_PHY_UP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_PHY_UP\n");
hw_event_sata_phy_up(pm8001_ha, piomb);
break;
case HW_EVENT_SATA_SPINUP_HOLD:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD\n"));
- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD);
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_SPINUP_HOLD\n");
+ sas_notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD);
break;
case HW_EVENT_PHY_DOWN:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PHY_DOWN\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_DOWN\n");
hw_event_phy_down(pm8001_ha, piomb);
if (pm8001_ha->reset_in_progress) {
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("Reset in progress\n"));
+ pm8001_dbg(pm8001_ha, MSG, "Reset in progress\n");
return 0;
}
phy->phy_attached = 0;
phy->phy_state = PHY_LINK_DISABLE;
break;
case HW_EVENT_PORT_INVALID:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_INVALID\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_INVALID\n");
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
/* the broadcast change primitive received, tell the LIBSAS this event
to revalidate the sas domain*/
case HW_EVENT_BROADCAST_CHANGE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_BROADCAST_CHANGE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_CHANGE\n");
pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_BROADCAST_CHANGE,
port_id, phy_id, 1, 0);
spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE;
spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
break;
case HW_EVENT_PHY_ERROR:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PHY_ERROR\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_ERROR\n");
sas_phy_disconnected(&phy->sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR);
+ sas_notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR);
break;
case HW_EVENT_BROADCAST_EXP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_BROADCAST_EXP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_EXP\n");
spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP;
spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
break;
case HW_EVENT_LINK_ERR_INVALID_DWORD:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_LINK_ERR_INVALID_DWORD\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "HW_EVENT_LINK_ERR_INVALID_DWORD\n");
pm80xx_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0);
break;
case HW_EVENT_LINK_ERR_DISPARITY_ERROR:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_LINK_ERR_DISPARITY_ERROR\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "HW_EVENT_LINK_ERR_DISPARITY_ERROR\n");
pm80xx_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_DISPARITY_ERROR,
port_id, phy_id, 0, 0);
break;
case HW_EVENT_LINK_ERR_CODE_VIOLATION:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_LINK_ERR_CODE_VIOLATION\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "HW_EVENT_LINK_ERR_CODE_VIOLATION\n");
pm80xx_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_CODE_VIOLATION,
port_id, phy_id, 0, 0);
break;
case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n");
pm80xx_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH,
port_id, phy_id, 0, 0);
break;
case HW_EVENT_MALFUNCTION:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_MALFUNCTION\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_MALFUNCTION\n");
break;
case HW_EVENT_BROADCAST_SES:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_BROADCAST_SES\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_SES\n");
spin_lock_irqsave(&sas_phy->sas_prim_lock, flags);
sas_phy->sas_prim = HW_EVENT_BROADCAST_SES;
spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags);
- sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+ sas_notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
break;
case HW_EVENT_INBOUND_CRC_ERROR:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_INBOUND_CRC_ERROR\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_INBOUND_CRC_ERROR\n");
pm80xx_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_INBOUND_CRC_ERROR,
port_id, phy_id, 0, 0);
break;
case HW_EVENT_HARD_RESET_RECEIVED:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_HARD_RESET_RECEIVED\n"));
- sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET);
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_HARD_RESET_RECEIVED\n");
+ sas_notify_port_event(sas_phy, PORTE_HARD_RESET);
break;
case HW_EVENT_ID_FRAME_TIMEOUT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_ID_FRAME_TIMEOUT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_ID_FRAME_TIMEOUT\n");
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
case HW_EVENT_LINK_ERR_PHY_RESET_FAILED:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n");
pm80xx_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_LINK_ERR_PHY_RESET_FAILED,
port_id, phy_id, 0, 0);
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
break;
case HW_EVENT_PORT_RESET_TIMER_TMO:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RESET_TIMER_TMO\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_TIMER_TMO\n");
pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
port_id, phy_id, 0, 0);
sas_phy_disconnected(sas_phy);
phy->phy_attached = 0;
- sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
+ sas_notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
if (pm8001_ha->phy[phy_id].reset_completion) {
pm8001_ha->phy[phy_id].port_reset_status =
PORT_RESET_TMO;
@@ -3344,28 +3634,26 @@
}
break;
case HW_EVENT_PORT_RECOVERY_TIMER_TMO:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "HW_EVENT_PORT_RECOVERY_TIMER_TMO\n");
pm80xx_hw_event_ack_req(pm8001_ha, 0,
HW_EVENT_PORT_RECOVERY_TIMER_TMO,
port_id, phy_id, 0, 0);
for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
if (port->wide_port_phymap & (1 << i)) {
phy = &pm8001_ha->phy[i];
- sas_ha->notify_phy_event(&phy->sas_phy,
+ sas_notify_phy_event(&phy->sas_phy,
PHYE_LOSS_OF_SIGNAL);
port->wide_port_phymap &= ~(1 << i);
}
}
break;
case HW_EVENT_PORT_RECOVER:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RECOVER\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RECOVER\n");
hw_event_port_recover(pm8001_ha, piomb);
break;
case HW_EVENT_PORT_RESET_COMPLETE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("HW_EVENT_PORT_RESET_COMPLETE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_COMPLETE\n");
if (pm8001_ha->phy[phy_id].reset_completion) {
pm8001_ha->phy[phy_id].port_reset_status =
PORT_RESET_SUCCESS;
@@ -3374,12 +3662,11 @@
}
break;
case EVENT_BROADCAST_ASYNCH_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("EVENT_BROADCAST_ASYNCH_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "EVENT_BROADCAST_ASYNCH_EVENT\n");
break;
default:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("Unknown event type 0x%x\n", eventType));
+ pm8001_dbg(pm8001_ha, DEVIO, "Unknown event type 0x%x\n",
+ eventType);
break;
}
return 0;
@@ -3399,9 +3686,8 @@
u32 phyid =
le32_to_cpu(pPayload->phyid) & 0xFF;
struct pm8001_phy *phy = &pm8001_ha->phy[phyid];
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("phy:0x%x status:0x%x\n",
- phyid, status));
+ pm8001_dbg(pm8001_ha, MSG, "phy:0x%x status:0x%x\n",
+ phyid, status);
if (status == PHY_STOP_SUCCESS ||
status == PHY_STOP_ERR_DEVICE_ATTACHED)
phy->phy_state = PHY_LINK_DISABLE;
@@ -3421,9 +3707,9 @@
u32 status = le32_to_cpu(pPayload->status);
u32 err_qlfr_pgcd = le32_to_cpu(pPayload->err_qlfr_pgcd);
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "SET CONTROLLER RESP: status 0x%x qlfr_pgcd 0x%x\n",
- status, err_qlfr_pgcd));
+ pm8001_dbg(pm8001_ha, MSG,
+ "SET CONTROLLER RESP: status 0x%x qlfr_pgcd 0x%x\n",
+ status, err_qlfr_pgcd);
return 0;
}
@@ -3436,8 +3722,7 @@
static int mpi_get_controller_config_resp(struct pm8001_hba_info *pm8001_ha,
void *piomb)
{
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" pm80xx_addition_functionality\n"));
+ pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");
return 0;
}
@@ -3450,8 +3735,7 @@
static int mpi_get_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
void *piomb)
{
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" pm80xx_addition_functionality\n"));
+ pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");
return 0;
}
@@ -3463,8 +3747,7 @@
*/
static int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
{
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" pm80xx_addition_functionality\n"));
+ pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");
return 0;
}
@@ -3477,28 +3760,31 @@
static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
void *piomb)
{
+ u32 tag;
u8 page_code;
+ int rc = 0;
struct set_phy_profile_resp *pPayload =
(struct set_phy_profile_resp *)(piomb + 4);
u32 ppc_phyid = le32_to_cpu(pPayload->ppc_phyid);
u32 status = le32_to_cpu(pPayload->status);
+ tag = le32_to_cpu(pPayload->tag);
page_code = (u8)((ppc_phyid & 0xFF00) >> 8);
if (status) {
/* status is FAILED */
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("PhyProfile command failed with status "
- "0x%08X \n", status));
- return -1;
+ pm8001_dbg(pm8001_ha, FAIL,
+ "PhyProfile command failed with status 0x%08X\n",
+ status);
+ rc = -1;
} else {
if (page_code != SAS_PHY_ANALOG_SETTINGS_PAGE) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("Invalid page code 0x%X\n",
- page_code));
- return -1;
+ pm8001_dbg(pm8001_ha, FAIL, "Invalid page code 0x%X\n",
+ page_code);
+ rc = -1;
}
}
- return 0;
+ pm8001_tag_free(pm8001_ha, tag);
+ return rc;
}
/**
@@ -3515,9 +3801,9 @@
u32 kidx_new_curr_ksop = le32_to_cpu(pPayload->kidx_new_curr_ksop);
u32 err_qlfr = le32_to_cpu(pPayload->err_qlfr);
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "KEK MGMT RESP. Status 0x%x idx_ksop 0x%x err_qlfr 0x%x\n",
- status, kidx_new_curr_ksop, err_qlfr));
+ pm8001_dbg(pm8001_ha, MSG,
+ "KEK MGMT RESP. Status 0x%x idx_ksop 0x%x err_qlfr 0x%x\n",
+ status, kidx_new_curr_ksop, err_qlfr);
return 0;
}
@@ -3530,8 +3816,7 @@
static int mpi_dek_management_resp(struct pm8001_hba_info *pm8001_ha,
void *piomb)
{
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" pm80xx_addition_functionality\n"));
+ pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");
return 0;
}
@@ -3544,8 +3829,7 @@
static int ssp_coalesced_comp_resp(struct pm8001_hba_info *pm8001_ha,
void *piomb)
{
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk(" pm80xx_addition_functionality\n"));
+ pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n");
return 0;
}
@@ -3562,266 +3846,237 @@
switch (opc) {
case OPC_OUB_ECHO:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk("OPC_OUB_ECHO\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_ECHO\n");
break;
case OPC_OUB_HW_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_HW_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_HW_EVENT\n");
mpi_hw_event(pm8001_ha, piomb);
break;
case OPC_OUB_THERM_HW_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_THERMAL_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_THERMAL_EVENT\n");
mpi_thermal_hw_event(pm8001_ha, piomb);
break;
case OPC_OUB_SSP_COMP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SSP_COMP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_COMP\n");
mpi_ssp_completion(pm8001_ha, piomb);
break;
case OPC_OUB_SMP_COMP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SMP_COMP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SMP_COMP\n");
mpi_smp_completion(pm8001_ha, piomb);
break;
case OPC_OUB_LOCAL_PHY_CNTRL:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_LOCAL_PHY_CNTRL\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_LOCAL_PHY_CNTRL\n");
pm8001_mpi_local_phy_ctl(pm8001_ha, piomb);
break;
case OPC_OUB_DEV_REGIST:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_DEV_REGIST\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEV_REGIST\n");
pm8001_mpi_reg_resp(pm8001_ha, piomb);
break;
case OPC_OUB_DEREG_DEV:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("unregister the device\n"));
+ pm8001_dbg(pm8001_ha, MSG, "unregister the device\n");
pm8001_mpi_dereg_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GET_DEV_HANDLE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GET_DEV_HANDLE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_DEV_HANDLE\n");
break;
case OPC_OUB_SATA_COMP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SATA_COMP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_COMP\n");
mpi_sata_completion(pm8001_ha, piomb);
break;
case OPC_OUB_SATA_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SATA_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_EVENT\n");
mpi_sata_event(pm8001_ha, piomb);
break;
case OPC_OUB_SSP_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SSP_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_EVENT\n");
mpi_ssp_event(pm8001_ha, piomb);
break;
case OPC_OUB_DEV_HANDLE_ARRIV:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_DEV_HANDLE_ARRIV\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEV_HANDLE_ARRIV\n");
/*This is for target*/
break;
case OPC_OUB_SSP_RECV_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SSP_RECV_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_RECV_EVENT\n");
/*This is for target*/
break;
case OPC_OUB_FW_FLASH_UPDATE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_FW_FLASH_UPDATE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_FW_FLASH_UPDATE\n");
pm8001_mpi_fw_flash_update_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GPIO_RESPONSE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GPIO_RESPONSE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GPIO_RESPONSE\n");
break;
case OPC_OUB_GPIO_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GPIO_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GPIO_EVENT\n");
break;
case OPC_OUB_GENERAL_EVENT:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GENERAL_EVENT\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GENERAL_EVENT\n");
pm8001_mpi_general_event(pm8001_ha, piomb);
break;
case OPC_OUB_SSP_ABORT_RSP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SSP_ABORT_RSP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_ABORT_RSP\n");
pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
break;
case OPC_OUB_SATA_ABORT_RSP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SATA_ABORT_RSP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_ABORT_RSP\n");
pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
break;
case OPC_OUB_SAS_DIAG_MODE_START_END:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SAS_DIAG_MODE_START_END\n"));
+ pm8001_dbg(pm8001_ha, MSG,
+ "OPC_OUB_SAS_DIAG_MODE_START_END\n");
break;
case OPC_OUB_SAS_DIAG_EXECUTE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SAS_DIAG_EXECUTE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SAS_DIAG_EXECUTE\n");
break;
case OPC_OUB_GET_TIME_STAMP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GET_TIME_STAMP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_TIME_STAMP\n");
break;
case OPC_OUB_SAS_HW_EVENT_ACK:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SAS_HW_EVENT_ACK\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SAS_HW_EVENT_ACK\n");
break;
case OPC_OUB_PORT_CONTROL:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_PORT_CONTROL\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_PORT_CONTROL\n");
break;
case OPC_OUB_SMP_ABORT_RSP:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SMP_ABORT_RSP\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SMP_ABORT_RSP\n");
pm8001_mpi_task_abort_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GET_NVMD_DATA:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GET_NVMD_DATA\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_NVMD_DATA\n");
pm8001_mpi_get_nvmd_resp(pm8001_ha, piomb);
break;
case OPC_OUB_SET_NVMD_DATA:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SET_NVMD_DATA\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_NVMD_DATA\n");
pm8001_mpi_set_nvmd_resp(pm8001_ha, piomb);
break;
case OPC_OUB_DEVICE_HANDLE_REMOVAL:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_DEVICE_HANDLE_REMOVAL\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEVICE_HANDLE_REMOVAL\n");
break;
case OPC_OUB_SET_DEVICE_STATE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SET_DEVICE_STATE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_DEVICE_STATE\n");
pm8001_mpi_set_dev_state_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GET_DEVICE_STATE:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_GET_DEVICE_STATE\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_DEVICE_STATE\n");
break;
case OPC_OUB_SET_DEV_INFO:
- PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("OPC_OUB_SET_DEV_INFO\n"));
+ pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_DEV_INFO\n");
break;
/* spcv specifc commands */
case OPC_OUB_PHY_START_RESP:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "OPC_OUB_PHY_START_RESP opcode:%x\n", opc));
+ pm8001_dbg(pm8001_ha, MSG,
+ "OPC_OUB_PHY_START_RESP opcode:%x\n", opc);
mpi_phy_start_resp(pm8001_ha, piomb);
break;
case OPC_OUB_PHY_STOP_RESP:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "OPC_OUB_PHY_STOP_RESP opcode:%x\n", opc));
+ pm8001_dbg(pm8001_ha, MSG,
+ "OPC_OUB_PHY_STOP_RESP opcode:%x\n", opc);
mpi_phy_stop_resp(pm8001_ha, piomb);
break;
case OPC_OUB_SET_CONTROLLER_CONFIG:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "OPC_OUB_SET_CONTROLLER_CONFIG opcode:%x\n", opc));
+ pm8001_dbg(pm8001_ha, MSG,
+ "OPC_OUB_SET_CONTROLLER_CONFIG opcode:%x\n", opc);
mpi_set_controller_config_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GET_CONTROLLER_CONFIG:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "OPC_OUB_GET_CONTROLLER_CONFIG opcode:%x\n", opc));
+ pm8001_dbg(pm8001_ha, MSG,
+ "OPC_OUB_GET_CONTROLLER_CONFIG opcode:%x\n", opc);
mpi_get_controller_config_resp(pm8001_ha, piomb);
break;
case OPC_OUB_GET_PHY_PROFILE:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "OPC_OUB_GET_PHY_PROFILE opcode:%x\n", opc));
+ pm8001_dbg(pm8001_ha, MSG,
+ "OPC_OUB_GET_PHY_PROFILE opcode:%x\n", opc);
mpi_get_phy_profile_resp(pm8001_ha, piomb);
break;
case OPC_OUB_FLASH_OP_EXT:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "OPC_OUB_FLASH_OP_EXT opcode:%x\n", opc));
+ pm8001_dbg(pm8001_ha, MSG,
+ "OPC_OUB_FLASH_OP_EXT opcode:%x\n", opc);
mpi_flash_op_ext_resp(pm8001_ha, piomb);
break;
case OPC_OUB_SET_PHY_PROFILE:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "OPC_OUB_SET_PHY_PROFILE opcode:%x\n", opc));
+ pm8001_dbg(pm8001_ha, MSG,
+ "OPC_OUB_SET_PHY_PROFILE opcode:%x\n", opc);
mpi_set_phy_profile_resp(pm8001_ha, piomb);
break;
case OPC_OUB_KEK_MANAGEMENT_RESP:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "OPC_OUB_KEK_MANAGEMENT_RESP opcode:%x\n", opc));
+ pm8001_dbg(pm8001_ha, MSG,
+ "OPC_OUB_KEK_MANAGEMENT_RESP opcode:%x\n", opc);
mpi_kek_management_resp(pm8001_ha, piomb);
break;
case OPC_OUB_DEK_MANAGEMENT_RESP:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "OPC_OUB_DEK_MANAGEMENT_RESP opcode:%x\n", opc));
+ pm8001_dbg(pm8001_ha, MSG,
+ "OPC_OUB_DEK_MANAGEMENT_RESP opcode:%x\n", opc);
mpi_dek_management_resp(pm8001_ha, piomb);
break;
case OPC_OUB_SSP_COALESCED_COMP_RESP:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "OPC_OUB_SSP_COALESCED_COMP_RESP opcode:%x\n", opc));
+ pm8001_dbg(pm8001_ha, MSG,
+ "OPC_OUB_SSP_COALESCED_COMP_RESP opcode:%x\n", opc);
ssp_coalesced_comp_resp(pm8001_ha, piomb);
break;
default:
- PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
- "Unknown outbound Queue IOMB OPC = 0x%x\n", opc));
+ pm8001_dbg(pm8001_ha, DEVIO,
+ "Unknown outbound Queue IOMB OPC = 0x%x\n", opc);
break;
}
}
static void print_scratchpad_registers(struct pm8001_hba_info *pm8001_ha)
{
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("MSGU_SCRATCH_PAD_0: 0x%x\n",
- pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0)));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("MSGU_SCRATCH_PAD_1:0x%x\n",
- pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1)));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("MSGU_SCRATCH_PAD_2: 0x%x\n",
- pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2)));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("MSGU_SCRATCH_PAD_3: 0x%x\n",
- pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3)));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("MSGU_HOST_SCRATCH_PAD_0: 0x%x\n",
- pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_0)));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("MSGU_HOST_SCRATCH_PAD_1: 0x%x\n",
- pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_1)));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("MSGU_HOST_SCRATCH_PAD_2: 0x%x\n",
- pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_2)));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("MSGU_HOST_SCRATCH_PAD_3: 0x%x\n",
- pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_3)));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("MSGU_HOST_SCRATCH_PAD_4: 0x%x\n",
- pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_4)));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("MSGU_HOST_SCRATCH_PAD_5: 0x%x\n",
- pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_5)));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("MSGU_RSVD_SCRATCH_PAD_0: 0x%x\n",
- pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_6)));
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("MSGU_RSVD_SCRATCH_PAD_1: 0x%x\n",
- pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_7)));
+ pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_0: 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0));
+ pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_1:0x%x\n",
+ pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1));
+ pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_2: 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2));
+ pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_3: 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3));
+ pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_0: 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_0));
+ pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_1: 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_1));
+ pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_2: 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_2));
+ pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_3: 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_3));
+ pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_4: 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_4));
+ pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_5: 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_5));
+ pm8001_dbg(pm8001_ha, FAIL, "MSGU_RSVD_SCRATCH_PAD_0: 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_6));
+ pm8001_dbg(pm8001_ha, FAIL, "MSGU_RSVD_SCRATCH_PAD_1: 0x%x\n",
+ pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_7));
}
static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec)
{
struct outbound_queue_table *circularQ;
void *pMsg1 = NULL;
- u8 uninitialized_var(bc);
+ u8 bc;
u32 ret = MPI_IO_STATUS_FAIL;
unsigned long flags;
u32 regval;
- if (vec == (pm8001_ha->number_of_intr - 1)) {
+ /*
+ * Fatal errors are programmed to be signalled in irq vector
+ * pm8001_ha->max_q_num - 1 through pm8001_ha->main_cfg_tbl.pm80xx_tbl.
+ * fatal_err_interrupt
+ */
+ if (vec == (pm8001_ha->max_q_num - 1)) {
+ u32 mipsall_ready;
+
+ if (pm8001_ha->chip_id == chip_8008 ||
+ pm8001_ha->chip_id == chip_8009)
+ mipsall_ready = SCRATCH_PAD_MIPSALL_READY_8PORT;
+ else
+ mipsall_ready = SCRATCH_PAD_MIPSALL_READY_16PORT;
+
regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
- if ((regval & SCRATCH_PAD_MIPSALL_READY) !=
- SCRATCH_PAD_MIPSALL_READY) {
+ if ((regval & mipsall_ready) != mipsall_ready) {
pm8001_ha->controller_fatal_error = true;
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
- "Firmware Fatal error! Regval:0x%x\n", regval));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "Firmware Fatal error! Regval:0x%x\n",
+ regval);
print_scratchpad_registers(pm8001_ha);
return ret;
}
@@ -3927,8 +4182,7 @@
smp_cmd.tag = cpu_to_le32(ccb->ccb_tag);
length = sg_req->length;
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("SMP Frame Length %d\n", sg_req->length));
+ pm8001_dbg(pm8001_ha, IO, "SMP Frame Length %d\n", sg_req->length);
if (!(length - 8))
pm8001_ha->smp_exp_mode = SMP_DIRECT;
else
@@ -3940,8 +4194,7 @@
/* INDIRECT MODE command settings. Use DMA */
if (pm8001_ha->smp_exp_mode == SMP_INDIRECT) {
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("SMP REQUEST INDIRECT MODE\n"));
+ pm8001_dbg(pm8001_ha, IO, "SMP REQUEST INDIRECT MODE\n");
/* for SPCv indirect mode. Place the top 4 bytes of
* SMP Request header here. */
for (i = 0; i < 4; i++)
@@ -3973,28 +4226,27 @@
((u32)sg_dma_len(&task->smp_task.smp_resp)-4);
}
if (pm8001_ha->smp_exp_mode == SMP_DIRECT) {
- PM8001_IO_DBG(pm8001_ha,
- pm8001_printk("SMP REQUEST DIRECT MODE\n"));
+ pm8001_dbg(pm8001_ha, IO, "SMP REQUEST DIRECT MODE\n");
for (i = 0; i < length; i++)
if (i < 16) {
smp_cmd.smp_req16[i] = *(preq_dma_addr+i);
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "Byte[%d]:%x (DMA data:%x)\n",
- i, smp_cmd.smp_req16[i],
- *(preq_dma_addr)));
+ pm8001_dbg(pm8001_ha, IO,
+ "Byte[%d]:%x (DMA data:%x)\n",
+ i, smp_cmd.smp_req16[i],
+ *(preq_dma_addr));
} else {
smp_cmd.smp_req[i] = *(preq_dma_addr+i);
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "Byte[%d]:%x (DMA data:%x)\n",
- i, smp_cmd.smp_req[i],
- *(preq_dma_addr)));
+ pm8001_dbg(pm8001_ha, IO,
+ "Byte[%d]:%x (DMA data:%x)\n",
+ i, smp_cmd.smp_req[i],
+ *(preq_dma_addr));
}
}
build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag,
&smp_cmd, pm8001_ha->smp_exp_mode, length);
- rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
- (u32 *)&smp_cmd, 0);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &smp_cmd,
+ sizeof(smp_cmd), 0);
if (rc)
goto err_out_2;
return 0;
@@ -4058,7 +4310,7 @@
u64 phys_addr, start_addr, end_addr;
u32 end_addr_high, end_addr_low;
struct inbound_queue_table *circularQ;
- u32 q_index;
+ u32 q_index, cpu_id;
u32 opc = OPC_INB_SSPINIIOSTART;
memset(&ssp_cmd, 0, sizeof(ssp_cmd));
memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8);
@@ -4077,15 +4329,16 @@
ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7);
memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cmd->cmnd,
task->ssp_task.cmd->cmd_len);
- q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_INB_NUM;
+ cpu_id = smp_processor_id();
+ q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num);
circularQ = &pm8001_ha->inbnd_q_tbl[q_index];
/* Check if encryption is set */
if (pm8001_ha->chip->encrypt &&
!(pm8001_ha->encrypt_info.status) && check_enc_sas_cmd(task)) {
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "Encryption enabled.Sending Encrypt SAS command 0x%x\n",
- task->ssp_task.cmd->cmnd[0]));
+ pm8001_dbg(pm8001_ha, IO,
+ "Encryption enabled.Sending Encrypt SAS command 0x%x\n",
+ task->ssp_task.cmd->cmnd[0]);
opc = OPC_INB_SSP_INI_DIF_ENC_IO;
/* enable encryption. 0 for SAS 1.1 and SAS 2.0 compatible TLR*/
ssp_cmd.dad_dir_m_tlr = cpu_to_le32
@@ -4095,8 +4348,7 @@
if (task->num_scatter > 1) {
pm8001_chip_make_sg(task->scatter,
ccb->n_elem, ccb->buf_prd);
- phys_addr = ccb->ccb_dma_handle +
- offsetof(struct pm8001_ccb_info, buf_prd[0]);
+ phys_addr = ccb->ccb_dma_handle;
ssp_cmd.enc_addr_low =
cpu_to_le32(lower_32_bits(phys_addr));
ssp_cmd.enc_addr_high =
@@ -4116,18 +4368,13 @@
end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
if (end_addr_high != ssp_cmd.enc_addr_high) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("The sg list address "
- "start_addr=0x%016llx data_len=0x%x "
- "end_addr_high=0x%08x end_addr_low="
- "0x%08x has crossed 4G boundary\n",
- start_addr, ssp_cmd.enc_len,
- end_addr_high, end_addr_low));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",
+ start_addr, ssp_cmd.enc_len,
+ end_addr_high, end_addr_low);
pm8001_chip_make_sg(task->scatter, 1,
ccb->buf_prd);
- phys_addr = ccb->ccb_dma_handle +
- offsetof(struct pm8001_ccb_info,
- buf_prd[0]);
+ phys_addr = ccb->ccb_dma_handle;
ssp_cmd.enc_addr_low =
cpu_to_le32(lower_32_bits(phys_addr));
ssp_cmd.enc_addr_high =
@@ -4148,15 +4395,14 @@
(task->ssp_task.cmd->cmnd[4] << 8) |
(task->ssp_task.cmd->cmnd[5]));
} else {
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "Sending Normal SAS command 0x%x inb q %x\n",
- task->ssp_task.cmd->cmnd[0], q_index));
+ pm8001_dbg(pm8001_ha, IO,
+ "Sending Normal SAS command 0x%x inb q %x\n",
+ task->ssp_task.cmd->cmnd[0], q_index);
/* fill in PRD (scatter/gather) table, if any */
if (task->num_scatter > 1) {
pm8001_chip_make_sg(task->scatter, ccb->n_elem,
ccb->buf_prd);
- phys_addr = ccb->ccb_dma_handle +
- offsetof(struct pm8001_ccb_info, buf_prd[0]);
+ phys_addr = ccb->ccb_dma_handle;
ssp_cmd.addr_low =
cpu_to_le32(lower_32_bits(phys_addr));
ssp_cmd.addr_high =
@@ -4175,18 +4421,13 @@
end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
if (end_addr_high != ssp_cmd.addr_high) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("The sg list address "
- "start_addr=0x%016llx data_len=0x%x "
- "end_addr_high=0x%08x end_addr_low="
- "0x%08x has crossed 4G boundary\n",
- start_addr, ssp_cmd.len,
- end_addr_high, end_addr_low));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",
+ start_addr, ssp_cmd.len,
+ end_addr_high, end_addr_low);
pm8001_chip_make_sg(task->scatter, 1,
ccb->buf_prd);
- phys_addr = ccb->ccb_dma_handle +
- offsetof(struct pm8001_ccb_info,
- buf_prd[0]);
+ phys_addr = ccb->ccb_dma_handle;
ssp_cmd.addr_low =
cpu_to_le32(lower_32_bits(phys_addr));
ssp_cmd.addr_high =
@@ -4200,9 +4441,8 @@
ssp_cmd.esgl = 0;
}
}
- q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM;
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
- &ssp_cmd, q_index);
+ &ssp_cmd, sizeof(ssp_cmd), q_index);
return ret;
}
@@ -4214,7 +4454,7 @@
struct pm8001_device *pm8001_ha_dev = dev->lldd_dev;
u32 tag = ccb->ccb_tag;
int ret;
- u32 q_index;
+ u32 q_index, cpu_id;
struct sata_start_req sata_cmd;
u32 hdr_tag, ncg_tag = 0;
u64 phys_addr, start_addr, end_addr;
@@ -4225,24 +4465,25 @@
unsigned long flags;
u32 opc = OPC_INB_SATA_HOST_OPSTART;
memset(&sata_cmd, 0, sizeof(sata_cmd));
- q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_INB_NUM;
+ cpu_id = smp_processor_id();
+ q_index = (u32) (cpu_id) % (pm8001_ha->max_q_num);
circularQ = &pm8001_ha->inbnd_q_tbl[q_index];
if (task->data_dir == DMA_NONE) {
ATAP = 0x04; /* no data*/
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("no data\n"));
+ pm8001_dbg(pm8001_ha, IO, "no data\n");
} else if (likely(!task->ata_task.device_control_reg_update)) {
if (task->ata_task.dma_xfer) {
ATAP = 0x06; /* DMA */
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("DMA\n"));
+ pm8001_dbg(pm8001_ha, IO, "DMA\n");
} else {
ATAP = 0x05; /* PIO*/
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("PIO\n"));
+ pm8001_dbg(pm8001_ha, IO, "PIO\n");
}
if (task->ata_task.use_ncq &&
dev->sata_dev.class != ATA_DEV_ATAPI) {
ATAP = 0x07; /* FPDMA */
- PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n"));
+ pm8001_dbg(pm8001_ha, IO, "FPDMA\n");
}
}
if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) {
@@ -4262,9 +4503,9 @@
/* Check if encryption is set */
if (pm8001_ha->chip->encrypt &&
!(pm8001_ha->encrypt_info.status) && check_enc_sat_cmd(task)) {
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "Encryption enabled.Sending Encrypt SATA cmd 0x%x\n",
- sata_cmd.sata_fis.command));
+ pm8001_dbg(pm8001_ha, IO,
+ "Encryption enabled.Sending Encrypt SATA cmd 0x%x\n",
+ sata_cmd.sata_fis.command);
opc = OPC_INB_SATA_DIF_ENC_IO;
/* set encryption bit */
@@ -4276,8 +4517,7 @@
if (task->num_scatter > 1) {
pm8001_chip_make_sg(task->scatter,
ccb->n_elem, ccb->buf_prd);
- phys_addr = ccb->ccb_dma_handle +
- offsetof(struct pm8001_ccb_info, buf_prd[0]);
+ phys_addr = ccb->ccb_dma_handle;
sata_cmd.enc_addr_low = lower_32_bits(phys_addr);
sata_cmd.enc_addr_high = upper_32_bits(phys_addr);
sata_cmd.enc_esgl = cpu_to_le32(1 << 31);
@@ -4293,18 +4533,13 @@
end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
if (end_addr_high != sata_cmd.enc_addr_high) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("The sg list address "
- "start_addr=0x%016llx data_len=0x%x "
- "end_addr_high=0x%08x end_addr_low"
- "=0x%08x has crossed 4G boundary\n",
- start_addr, sata_cmd.enc_len,
- end_addr_high, end_addr_low));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",
+ start_addr, sata_cmd.enc_len,
+ end_addr_high, end_addr_low);
pm8001_chip_make_sg(task->scatter, 1,
ccb->buf_prd);
- phys_addr = ccb->ccb_dma_handle +
- offsetof(struct pm8001_ccb_info,
- buf_prd[0]);
+ phys_addr = ccb->ccb_dma_handle;
sata_cmd.enc_addr_low =
lower_32_bits(phys_addr);
sata_cmd.enc_addr_high =
@@ -4330,9 +4565,9 @@
cpu_to_le32((sata_cmd.sata_fis.lbah_exp << 8) |
(sata_cmd.sata_fis.lbam_exp));
} else {
- PM8001_IO_DBG(pm8001_ha, pm8001_printk(
- "Sending Normal SATA command 0x%x inb %x\n",
- sata_cmd.sata_fis.command, q_index));
+ pm8001_dbg(pm8001_ha, IO,
+ "Sending Normal SATA command 0x%x inb %x\n",
+ sata_cmd.sata_fis.command, q_index);
/* dad (bit 0-1) is 0 */
sata_cmd.ncqtag_atap_dir_m_dad =
cpu_to_le32(((ncg_tag & 0xff)<<16) |
@@ -4342,8 +4577,7 @@
if (task->num_scatter > 1) {
pm8001_chip_make_sg(task->scatter,
ccb->n_elem, ccb->buf_prd);
- phys_addr = ccb->ccb_dma_handle +
- offsetof(struct pm8001_ccb_info, buf_prd[0]);
+ phys_addr = ccb->ccb_dma_handle;
sata_cmd.addr_low = lower_32_bits(phys_addr);
sata_cmd.addr_high = upper_32_bits(phys_addr);
sata_cmd.esgl = cpu_to_le32(1 << 31);
@@ -4359,18 +4593,13 @@
end_addr_low = cpu_to_le32(lower_32_bits(end_addr));
end_addr_high = cpu_to_le32(upper_32_bits(end_addr));
if (end_addr_high != sata_cmd.addr_high) {
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("The sg list address "
- "start_addr=0x%016llx data_len=0x%x"
- "end_addr_high=0x%08x end_addr_low="
- "0x%08x has crossed 4G boundary\n",
- start_addr, sata_cmd.len,
- end_addr_high, end_addr_low));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "The sg list address start_addr=0x%016llx data_len=0x%xend_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n",
+ start_addr, sata_cmd.len,
+ end_addr_high, end_addr_low);
pm8001_chip_make_sg(task->scatter, 1,
ccb->buf_prd);
- phys_addr = ccb->ccb_dma_handle +
- offsetof(struct pm8001_ccb_info,
- buf_prd[0]);
+ phys_addr = ccb->ccb_dma_handle;
sata_cmd.addr_low =
lower_32_bits(phys_addr);
sata_cmd.addr_high =
@@ -4426,10 +4655,10 @@
SAS_TASK_STATE_ABORTED))) {
spin_unlock_irqrestore(&task->task_state_lock,
flags);
- PM8001_FAIL_DBG(pm8001_ha,
- pm8001_printk("task 0x%p resp 0x%x "
- " stat 0x%x but aborted by upper layer "
- "\n", task, ts->resp, ts->stat));
+ pm8001_dbg(pm8001_ha, FAIL,
+ "task 0x%p resp 0x%x stat 0x%x but aborted by upper layer\n",
+ task, ts->resp,
+ ts->stat);
pm8001_ccb_task_free(pm8001_ha, task, ccb, tag);
return 0;
} else {
@@ -4437,20 +4666,19 @@
flags);
pm8001_ccb_task_free_done(pm8001_ha, task,
ccb, tag);
+ atomic_dec(&pm8001_ha_dev->running_req);
return 0;
}
}
}
- q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM;
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
- &sata_cmd, q_index);
+ &sata_cmd, sizeof(sata_cmd), q_index);
return ret;
}
/**
* pm80xx_chip_phy_start_req - start phy via PHY_START COMMAND
* @pm8001_ha: our hba card information.
- * @num: the inbound queue number
* @phy_id: the phy id which we wanted to start up.
*/
static int
@@ -4465,25 +4693,10 @@
memset(&payload, 0, sizeof(payload));
payload.tag = cpu_to_le32(tag);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("PHY START REQ for phy_id %d\n", phy_id));
- /*
- ** [0:7] PHY Identifier
- ** [8:11] link rate 1.5G, 3G, 6G
- ** [12:13] link mode 01b SAS mode; 10b SATA mode; 11b Auto mode
- ** [14] 0b disable spin up hold; 1b enable spin up hold
- ** [15] ob no change in current PHY analig setup 1b enable using SPAST
- */
- if (!IS_SPCV_12G(pm8001_ha->pdev))
- payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
- LINKMODE_AUTO | LINKRATE_15 |
- LINKRATE_30 | LINKRATE_60 | phy_id);
- else
- payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
- LINKMODE_AUTO | LINKRATE_15 |
- LINKRATE_30 | LINKRATE_60 | LINKRATE_120 |
- phy_id);
+ pm8001_dbg(pm8001_ha, INIT, "PHY START REQ for phy_id %d\n", phy_id);
+ payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE |
+ LINKMODE_AUTO | pm8001_ha->link_rate | phy_id);
/* SSC Disable and SAS Analog ST configuration */
/**
payload.ase_sh_lm_slr_phyid =
@@ -4496,16 +4709,16 @@
payload.sas_identify.dev_type = SAS_END_DEVICE;
payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
memcpy(payload.sas_identify.sas_addr,
- &pm8001_ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);
+ &pm8001_ha->sas_addr, SAS_ADDR_SIZE);
payload.sas_identify.phy_id = phy_id;
- ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
+ sizeof(payload), 0);
return ret;
}
/**
* pm8001_chip_phy_stop_req - start phy via PHY_STOP COMMAND
* @pm8001_ha: our hba card information.
- * @num: the inbound queue number
* @phy_id: the phy id which we wanted to start up.
*/
static int pm80xx_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
@@ -4520,11 +4733,12 @@
memset(&payload, 0, sizeof(payload));
payload.tag = cpu_to_le32(tag);
payload.phy_id = cpu_to_le32(phy_id);
- ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0);
+ ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload,
+ sizeof(payload), 0);
return ret;
}
-/**
+/*
* see comments on pm8001_mpi_reg_resp.
*/
static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha,
@@ -4586,7 +4800,8 @@
memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
SAS_ADDR_SIZE);
- rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
if (rc)
pm8001_tag_free(pm8001_ha, tag);
@@ -4596,9 +4811,8 @@
/**
* pm80xx_chip_phy_ctl_req - support the local phy operation
* @pm8001_ha: our hba card information.
- * @num: the inbound queue number
- * @phy_id: the phy id which we wanted to operate
- * @phy_op:
+ * @phyId: the phy id which we wanted to operate
+ * @phy_op: phy operation to request
*/
static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
u32 phyId, u32 phy_op)
@@ -4616,7 +4830,8 @@
payload.tag = cpu_to_le32(tag);
payload.phyop_phyid =
cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF));
- return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
}
static u32 pm80xx_chip_is_our_interrupt(struct pm8001_hba_info *pm8001_ha)
@@ -4636,20 +4851,23 @@
/**
* pm8001_chip_isr - PM8001 isr handler.
* @pm8001_ha: our hba card information.
- * @irq: irq number.
- * @stat: stat.
+ * @vec: irq number.
*/
static irqreturn_t
pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)
{
pm80xx_chip_interrupt_disable(pm8001_ha, vec);
+ pm8001_dbg(pm8001_ha, DEVIO,
+ "irq vec %d, ODMR:0x%x\n",
+ vec, pm8001_cr32(pm8001_ha, 0, 0x30));
process_oq(pm8001_ha, vec);
pm80xx_chip_interrupt_enable(pm8001_ha, vec);
return IRQ_HANDLED;
}
-void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
- u32 operation, u32 phyid, u32 length, u32 *buf)
+static void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
+ u32 operation, u32 phyid,
+ u32 length, u32 *buf)
{
u32 tag , i, j = 0;
int rc;
@@ -4660,18 +4878,19 @@
memset(&payload, 0, sizeof(payload));
rc = pm8001_tag_alloc(pm8001_ha, &tag);
if (rc)
- PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Invalid tag\n"));
+ pm8001_dbg(pm8001_ha, FAIL, "Invalid tag\n");
circularQ = &pm8001_ha->inbnd_q_tbl[0];
payload.tag = cpu_to_le32(tag);
payload.ppc_phyid = (((operation & 0xF) << 8) | (phyid & 0xFF));
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk(" phy profile command for phy %x ,length is %d\n",
- payload.ppc_phyid, length));
+ pm8001_dbg(pm8001_ha, INIT,
+ " phy profile command for phy %x ,length is %d\n",
+ payload.ppc_phyid, length);
for (i = length; i < (length + PHY_DWORD_LENGTH - 1); i++) {
payload.reserved[j] = cpu_to_le32(*((u32 *)buf + i));
j++;
}
- rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
if (rc)
pm8001_tag_free(pm8001_ha, tag);
}
@@ -4686,7 +4905,7 @@
SAS_PHY_ANALOG_SETTINGS_PAGE, i, length, (u32 *)buf);
length = length + PHY_DWORD_LENGTH;
}
- PM8001_INIT_DBG(pm8001_ha, pm8001_printk("phy settings completed\n"));
+ pm8001_dbg(pm8001_ha, INIT, "phy settings completed\n");
}
void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha,
@@ -4701,7 +4920,7 @@
rc = pm8001_tag_alloc(pm8001_ha, &tag);
if (rc)
- PM8001_INIT_DBG(pm8001_ha, pm8001_printk("Invalid tag"));
+ pm8001_dbg(pm8001_ha, INIT, "Invalid tag\n");
circularQ = &pm8001_ha->inbnd_q_tbl[0];
opc = OPC_INB_SET_PHY_PROFILE;
@@ -4713,12 +4932,12 @@
for (i = 0; i < length; i++)
payload.reserved[i] = cpu_to_le32(*(buf + i));
- rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
+ rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload,
+ sizeof(payload), 0);
if (rc)
pm8001_tag_free(pm8001_ha, tag);
- PM8001_INIT_DBG(pm8001_ha,
- pm8001_printk("PHY %d settings applied", phy));
+ pm8001_dbg(pm8001_ha, INIT, "PHY %d settings applied\n", phy);
}
const struct pm8001_dispatch pm8001_80xx_dispatch = {
.name = "pmc80xx",
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index dc9ab76..0dfe903 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -220,6 +220,9 @@
#define SAS_DOPNRJT_RTRY_TMO 128
#define SAS_COPNRJT_RTRY_TMO 128
+#define SPCV_DOORBELL_CLEAR_TIMEOUT (30 * 1000 * 1000) /* 30 sec */
+#define SPC_DOORBELL_CLEAR_TIMEOUT (15 * 1000 * 1000) /* 15 sec */
+
/*
Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second.
Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128
@@ -1388,8 +1391,12 @@
#define SCRATCH_PAD_BOOT_LOAD_SUCCESS 0x0
#define SCRATCH_PAD_IOP0_READY 0xC00
#define SCRATCH_PAD_IOP1_READY 0x3000
-#define SCRATCH_PAD_MIPSALL_READY (SCRATCH_PAD_IOP1_READY | \
+#define SCRATCH_PAD_MIPSALL_READY_16PORT (SCRATCH_PAD_IOP1_READY | \
SCRATCH_PAD_IOP0_READY | \
+ SCRATCH_PAD_ILA_READY | \
+ SCRATCH_PAD_RAAE_READY)
+#define SCRATCH_PAD_MIPSALL_READY_8PORT (SCRATCH_PAD_IOP0_READY | \
+ SCRATCH_PAD_ILA_READY | \
SCRATCH_PAD_RAAE_READY)
/* boot loader state */
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index 398d2af..cbe5fab 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -2860,10 +2860,8 @@
{
struct pmcraid_cmd *cancel_cmd;
struct pmcraid_instance *pinstance;
- struct pmcraid_resource_entry *res;
pinstance = (struct pmcraid_instance *)cmd->drv_inst;
- res = cmd->scsi_cmd->device->hostdata;
cancel_cmd = pmcraid_get_free_cmd(pinstance);
@@ -3973,9 +3971,7 @@
.open = pmcraid_chr_open,
.fasync = pmcraid_chr_fasync,
.unlocked_ioctl = pmcraid_chr_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = pmcraid_chr_ioctl,
-#endif
+ .compat_ioctl = compat_ptr_ioctl,
.llseek = noop_llseek,
};
@@ -4654,7 +4650,7 @@
for (i = 0; i < PMCRAID_MAX_CMD; i++) {
pinstance->cmd_list[i]->ioa_cb =
- dma_pool_alloc(
+ dma_pool_zalloc(
pinstance->control_pool,
GFP_KERNEL,
&(pinstance->cmd_list[i]->ioa_cb_bus_addr));
@@ -4663,8 +4659,6 @@
pmcraid_release_control_blocks(pinstance, i);
return -ENOMEM;
}
- memset(pinstance->cmd_list[i]->ioa_cb, 0,
- sizeof(struct pmcraid_control_block));
}
return 0;
}
@@ -4720,7 +4714,6 @@
return -ENOMEM;
}
- memset(pinstance->hrrq_start[i], 0, buffer_size);
pinstance->hrrq_curr[i] = pinstance->hrrq_start[i];
pinstance->hrrq_end[i] =
pinstance->hrrq_start[i] + PMCRAID_MAX_CMD - 1;
diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h
index a4f7eb8..15c9621 100644
--- a/drivers/scsi/pmcraid.h
+++ b/drivers/scsi/pmcraid.h
@@ -623,7 +623,7 @@
u32 hostno;
u32 length;
u8 reserved[8];
- u8 data[0];
+ u8 data[];
};
/* Controller state event message type */
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index a406cc8..aa41f7a 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -717,7 +717,7 @@
}
cmd->SCp.phase++;
}
- /* fall through */
+ fallthrough;
case 2: /* Phase 2 - We are now talking to the scsi bus */
if (!ppa_select(dev, scmd_id(cmd))) {
@@ -725,7 +725,7 @@
return 0;
}
cmd->SCp.phase++;
- /* fall through */
+ fallthrough;
case 3: /* Phase 3 - Ready to accept a command */
w_ctr(ppb, 0x0c);
@@ -735,7 +735,7 @@
if (!ppa_send_command(cmd))
return 0;
cmd->SCp.phase++;
- /* fall through */
+ fallthrough;
case 4: /* Phase 4 - Setup scatter/gather buffers */
if (scsi_bufflen(cmd)) {
@@ -749,7 +749,7 @@
}
cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1;
cmd->SCp.phase++;
- /* fall through */
+ fallthrough;
case 5: /* Phase 5 - Data transfer stage */
w_ctr(ppb, 0x0c);
@@ -762,7 +762,7 @@
if (retv == 0)
return 1;
cmd->SCp.phase++;
- /* fall through */
+ fallthrough;
case 6: /* Phase 6 - Read status/message */
cmd->result = DID_OK << 16;
@@ -779,7 +779,6 @@
(DID_OK << 16) + (h << 8) + (l & STATUS_MASK);
}
return 0; /* Finished */
- break;
default:
printk(KERN_ERR "ppa: Invalid scsi phase\n");
@@ -847,10 +846,8 @@
case 1: /* Have not connected to interface */
dev->cur_cmd = NULL; /* Forget the problem */
return SUCCESS;
- break;
default: /* SCSI command sent, can not abort */
return FAILED;
- break;
}
}
diff --git a/drivers/scsi/qedf/Kconfig b/drivers/scsi/qedf/Kconfig
index 7cd993b..eb81a1b 100644
--- a/drivers/scsi/qedf/Kconfig
+++ b/drivers/scsi/qedf/Kconfig
@@ -7,6 +7,6 @@
depends on LIBFCOE
select QED_LL2
select QED_FCOE
- ---help---
+ help
This driver supports FCoE offload for the QLogic FastLinQ
41000 Series Converged Network Adapters.
diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h
index 0da4e16..0e2cbb1 100644
--- a/drivers/scsi/qedf/qedf.h
+++ b/drivers/scsi/qedf/qedf.h
@@ -388,7 +388,10 @@
#define QEDF_IO_WORK_MIN 64
mempool_t *io_mempool;
struct workqueue_struct *dpc_wq;
+ struct delayed_work recovery_work;
+ struct delayed_work board_disable_work;
struct delayed_work grcdump_work;
+ struct delayed_work stag_work;
u32 slow_sge_ios;
u32 fast_sge_ios;
@@ -404,6 +407,7 @@
u32 flogi_cnt;
u32 flogi_failed;
+ u32 flogi_pending;
/* Used for fc statistics */
struct mutex stats_mutex;
@@ -469,7 +473,7 @@
extern uint qedf_io_tracing;
extern uint qedf_stop_io_on_error;
extern uint qedf_link_down_tmo;
-#define QEDF_RETRY_DELAY_MAX 20 /* 2 seconds */
+#define QEDF_RETRY_DELAY_MAX 600 /* 60 seconds */
extern bool qedf_retry_delay;
extern uint qedf_debug;
@@ -538,9 +542,17 @@
extern void qedf_wq_grcdump(struct work_struct *work);
void qedf_stag_change_work(struct work_struct *work);
void qedf_ctx_soft_reset(struct fc_lport *lport);
+extern void qedf_board_disable_work(struct work_struct *work);
+extern void qedf_schedule_hw_err_handler(void *dev,
+ enum qed_hw_err_type err_type);
#define FCOE_WORD_TO_BYTE 4
#define QEDF_MAX_TASK_NUM 0xFFFF
+#define QL45xxx 0x165C
+#define QL41xxx 0x8080
+#define MAX_CT_PAYLOAD 2048
+#define DISCOVERED_PORTS 4
+#define NUMBER_OF_PORTS 1
struct fip_vlan {
struct ethhdr eth;
diff --git a/drivers/scsi/qedf/qedf_dbg.h b/drivers/scsi/qedf/qedf_dbg.h
index d979f09..2386bfb 100644
--- a/drivers/scsi/qedf/qedf_dbg.h
+++ b/drivers/scsi/qedf/qedf_dbg.h
@@ -42,7 +42,7 @@
#define QEDF_LOG_LPORT 0x4000 /* lport logs */
#define QEDF_LOG_ELS 0x8000 /* ELS logs */
#define QEDF_LOG_NPIV 0x10000 /* NPIV logs */
-#define QEDF_LOG_SESS 0x20000 /* Conection setup, cleanup */
+#define QEDF_LOG_SESS 0x20000 /* Connection setup, cleanup */
#define QEDF_LOG_TID 0x80000 /*
* FW TID context acquire
* free
diff --git a/drivers/scsi/qedf/qedf_debugfs.c b/drivers/scsi/qedf/qedf_debugfs.c
index b88bed9..a3ed681 100644
--- a/drivers/scsi/qedf/qedf_debugfs.c
+++ b/drivers/scsi/qedf/qedf_debugfs.c
@@ -14,10 +14,9 @@
static struct dentry *qedf_dbg_root;
-/**
+/*
* qedf_dbg_host_init - setup the debugfs file for the pf
- * @pf: the pf that is starting up
- **/
+ */
void
qedf_dbg_host_init(struct qedf_dbg_ctx *qedf,
const struct qedf_debugfs_ops *dops,
@@ -42,10 +41,9 @@
}
}
-/**
+/*
* qedf_dbg_host_exit - clear out the pf's debugfs entries
- * @pf: the pf that is stopping
- **/
+ */
void
qedf_dbg_host_exit(struct qedf_dbg_ctx *qedf_dbg)
{
@@ -56,9 +54,9 @@
qedf_dbg->bdf_dentry = NULL;
}
-/**
+/*
* qedf_dbg_init - start up debugfs for the driver
- **/
+ */
void
qedf_dbg_init(char *drv_name)
{
@@ -68,9 +66,9 @@
qedf_dbg_root = debugfs_create_dir(drv_name, NULL);
}
-/**
+/*
* qedf_dbg_exit - clean out the driver's debugfs entries
- **/
+ */
void
qedf_dbg_exit(void)
{
diff --git a/drivers/scsi/qedf/qedf_els.c b/drivers/scsi/qedf/qedf_els.c
index 87e169d..625e58c 100644
--- a/drivers/scsi/qedf/qedf_els.c
+++ b/drivers/scsi/qedf/qedf_els.c
@@ -124,7 +124,7 @@
task = qedf_get_task_mem(&qedf->tasks, xid);
qedf_init_mp_task(els_req, task, sqe);
- /* Put timer on original I/O request */
+ /* Put timer on els request */
if (timer_msec)
qedf_cmd_timer_set(qedf, els_req, timer_msec);
@@ -143,10 +143,33 @@
struct qedf_ioreq *els_req)
{
struct fcoe_cqe_midpath_info *mp_info;
+ struct qedf_rport *fcport;
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS, "Entered with xid = 0x%x"
" cmd_type = %d.\n", els_req->xid, els_req->cmd_type);
+ if ((els_req->event == QEDF_IOREQ_EV_ELS_FLUSH)
+ || (els_req->event == QEDF_IOREQ_EV_CLEANUP_SUCCESS)
+ || (els_req->event == QEDF_IOREQ_EV_CLEANUP_FAILED)) {
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO,
+ "ELS completion xid=0x%x after flush event=0x%x",
+ els_req->xid, els_req->event);
+ return;
+ }
+
+ fcport = els_req->fcport;
+
+ /* When flush is active,
+ * let the cmds be completed from the cleanup context
+ */
+ if (test_bit(QEDF_RPORT_IN_TARGET_RESET, &fcport->flags) ||
+ test_bit(QEDF_RPORT_IN_LUN_RESET, &fcport->flags)) {
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO,
+ "Dropping ELS completion xid=0x%x as fcport is flushing",
+ els_req->xid);
+ return;
+ }
+
clear_bit(QEDF_CMD_OUTSTANDING, &els_req->flags);
/* Kill the ELS timer */
@@ -185,10 +208,6 @@
goto out_free;
}
- if (rrq_req->event != QEDF_IOREQ_EV_ELS_TMO &&
- rrq_req->event != QEDF_IOREQ_EV_ELS_ERR_DETECT)
- cancel_delayed_work_sync(&orig_io_req->timeout_work);
-
refcount = kref_read(&orig_io_req->refcount);
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS, "rrq_compl: orig io = %p,"
" orig xid = 0x%x, rrq_xid = 0x%x, refcount=%d\n",
@@ -388,14 +407,10 @@
mutex_lock(&lport->disc.disc_mutex);
/* Recreate the rport and log back in */
rdata = fc_rport_create(lport, port_id);
- if (rdata) {
- mutex_unlock(&lport->disc.disc_mutex);
+ mutex_unlock(&lport->disc.disc_mutex);
+ if (rdata)
fc_rport_login(rdata);
- fcport->rdata = rdata;
- } else {
- mutex_unlock(&lport->disc.disc_mutex);
- fcport->rdata = NULL;
- }
+ fcport->rdata = rdata;
}
clear_bit(QEDF_RPORT_IN_RESET, &fcport->flags);
}
@@ -887,6 +902,11 @@
opcode = fc_frame_payload_op(fp);
if (opcode == ELS_LS_RJT) {
rjt = fc_frame_payload_get(fp, sizeof(*rjt));
+ if (!rjt) {
+ QEDF_ERR(&qedf->dbg_ctx, "payload get failed");
+ goto out_free_frame;
+ }
+
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS,
"Received LS_RJT for REC: er_reason=0x%x, "
"er_explan=0x%x.\n", rjt->er_reason, rjt->er_explan);
diff --git a/drivers/scsi/qedf/qedf_fip.c b/drivers/scsi/qedf/qedf_fip.c
index bb82f08..ad6a56c 100644
--- a/drivers/scsi/qedf/qedf_fip.c
+++ b/drivers/scsi/qedf/qedf_fip.c
@@ -20,7 +20,7 @@
#define MY_FIP_ALL_FCF_MACS ((__u8[6]) { 1, 0x10, 0x18, 1, 0, 2 })
static u8 my_fcoe_all_fcfs[ETH_ALEN] = MY_FIP_ALL_FCF_MACS;
unsigned long flags = 0;
- int rc = -1;
+ int rc;
skb = dev_alloc_skb(sizeof(struct fip_vlan));
if (!skb) {
diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c
index 4e8a284..472374d 100644
--- a/drivers/scsi/qedf/qedf_io.c
+++ b/drivers/scsi/qedf/qedf_io.c
@@ -22,7 +22,6 @@
container_of(work, struct qedf_ioreq, timeout_work.work);
struct qedf_ctx *qedf;
struct qedf_rport *fcport;
- u8 op = 0;
if (io_req == NULL) {
QEDF_INFO(NULL, QEDF_LOG_IO, "io_req is NULL.\n");
@@ -86,14 +85,13 @@
*/
QEDF_ERR(&(qedf->dbg_ctx), "ELS timeout, xid=0x%x.\n",
io_req->xid);
+ qedf_initiate_cleanup(io_req, true);
io_req->event = QEDF_IOREQ_EV_ELS_TMO;
/* Call callback function to complete command */
if (io_req->cb_func && io_req->cb_arg) {
- op = io_req->cb_arg->op;
io_req->cb_func(io_req->cb_arg);
io_req->cb_arg = NULL;
}
- qedf_initiate_cleanup(io_req, true);
kref_put(&io_req->refcount, qedf_release_cmd);
break;
case QEDF_SEQ_CLEANUP:
@@ -487,7 +485,7 @@
int sg_count = 0;
int bd_count = 0;
u32 sg_len;
- u64 addr, end_addr;
+ u64 addr;
int i = 0;
sg_count = dma_map_sg(&qedf->pdev->dev, scsi_sglist(sc),
@@ -502,10 +500,9 @@
scsi_for_each_sg(sc, sg, sg_count, i) {
sg_len = (u32)sg_dma_len(sg);
addr = (u64)sg_dma_address(sg);
- end_addr = (u64)(addr + sg_len);
/*
- * Intermediate s/g element so check if start and end address
+ * Intermediate s/g element so check if start address
* is page aligned. Only required for writes and only if the
* number of scatter/gather elements is 8 or more.
*/
@@ -860,7 +857,6 @@
struct qedf_ctx *qedf = lport_priv(lport);
struct e4_fcoe_task_context *task_ctx;
u16 xid;
- enum fcoe_task_type req_type = 0;
struct fcoe_wqe *sqe;
u16 sqe_idx;
@@ -873,11 +869,9 @@
io_req->cpu = smp_processor_id();
if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) {
- req_type = FCOE_TASK_TYPE_READ_INITIATOR;
io_req->io_req_flags = QEDF_READ;
qedf->input_requests++;
} else if (sc_cmd->sc_data_direction == DMA_TO_DEVICE) {
- req_type = FCOE_TASK_TYPE_WRITE_INITIATOR;
io_req->io_req_flags = QEDF_WRITE;
qedf->output_requests++;
} else {
@@ -1021,14 +1015,18 @@
atomic_inc(&fcport->ios_to_queue);
if (fcport->retry_delay_timestamp) {
+ /* Take fcport->rport_lock for resetting the delay_timestamp */
+ spin_lock_irqsave(&fcport->rport_lock, flags);
if (time_after(jiffies, fcport->retry_delay_timestamp)) {
fcport->retry_delay_timestamp = 0;
} else {
+ spin_unlock_irqrestore(&fcport->rport_lock, flags);
/* If retry_delay timer is active, flow off the ML */
rc = SCSI_MLQUEUE_TARGET_BUSY;
atomic_dec(&fcport->ios_to_queue);
goto exit_qcmd;
}
+ spin_unlock_irqrestore(&fcport->rport_lock, flags);
}
io_req = qedf_alloc_cmd(fcport, QEDF_SCSI_CMD);
@@ -1126,14 +1124,14 @@
void qedf_scsi_completion(struct qedf_ctx *qedf, struct fcoe_cqe *cqe,
struct qedf_ioreq *io_req)
{
- u16 xid;
- struct e4_fcoe_task_context *task_ctx;
struct scsi_cmnd *sc_cmd;
struct fcoe_cqe_rsp_info *fcp_rsp;
struct qedf_rport *fcport;
int refcount;
u16 scope, qualifier = 0;
u8 fw_residual_flag = 0;
+ unsigned long flags = 0;
+ u16 chk_scope = 0;
if (!io_req)
return;
@@ -1149,8 +1147,6 @@
return;
}
- xid = io_req->xid;
- task_ctx = qedf_get_task_mem(&qedf->tasks, xid);
sc_cmd = io_req->sc_cmd;
fcp_rsp = &cqe->cqe_info.rsp_info;
@@ -1267,16 +1263,8 @@
/* Lower 14 bits */
qualifier = fcp_rsp->retry_delay_timer & 0x3FFF;
- if (qedf_retry_delay &&
- scope > 0 && qualifier > 0 &&
- qualifier <= 0x3FEF) {
- /* Check we don't go over the max */
- if (qualifier > QEDF_RETRY_DELAY_MAX)
- qualifier =
- QEDF_RETRY_DELAY_MAX;
- fcport->retry_delay_timestamp =
- jiffies + (qualifier * HZ / 10);
- }
+ if (qedf_retry_delay)
+ chk_scope = 1;
/* Record stats */
if (io_req->cdb_status ==
SAM_STAT_TASK_SET_FULL)
@@ -1287,6 +1275,36 @@
}
if (io_req->fcp_resid)
scsi_set_resid(sc_cmd, io_req->fcp_resid);
+
+ if (chk_scope == 1) {
+ if ((scope == 1 || scope == 2) &&
+ (qualifier > 0 && qualifier <= 0x3FEF)) {
+ /* Check we don't go over the max */
+ if (qualifier > QEDF_RETRY_DELAY_MAX) {
+ qualifier = QEDF_RETRY_DELAY_MAX;
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO,
+ "qualifier = %d\n",
+ (fcp_rsp->retry_delay_timer &
+ 0x3FFF));
+ }
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO,
+ "Scope = %d and qualifier = %d",
+ scope, qualifier);
+ /* Take fcport->rport_lock to
+ * update the retry_delay_timestamp
+ */
+ spin_lock_irqsave(&fcport->rport_lock, flags);
+ fcport->retry_delay_timestamp =
+ jiffies + (qualifier * HZ / 10);
+ spin_unlock_irqrestore(&fcport->rport_lock,
+ flags);
+
+ } else {
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO,
+ "combination of scope = %d and qualifier = %d is not handled in qedf.\n",
+ scope, qualifier);
+ }
+ }
break;
default:
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_IO, "fcp_status=%d.\n",
@@ -1314,7 +1332,6 @@
void qedf_scsi_done(struct qedf_ctx *qedf, struct qedf_ioreq *io_req,
int result)
{
- u16 xid;
struct scsi_cmnd *sc_cmd;
int refcount;
@@ -1336,7 +1353,6 @@
*/
clear_bit(QEDF_CMD_OUTSTANDING, &io_req->flags);
- xid = io_req->xid;
sc_cmd = io_req->sc_cmd;
if (!sc_cmd) {
@@ -1566,6 +1582,8 @@
*/
els_req->event = QEDF_IOREQ_EV_ELS_FLUSH;
+ clear_bit(QEDF_CMD_OUTSTANDING, &els_req->flags);
+
/* Cancel the timer */
cancel_delayed_work_sync(&els_req->timeout_work);
@@ -1708,8 +1726,10 @@
io_req, io_req->xid);
continue;
}
+ qedf_initiate_cleanup(io_req, false);
flush_cnt++;
qedf_flush_els_req(qedf, io_req);
+
/*
* Release the kref and go back to the top of the
* loop.
@@ -1855,7 +1875,6 @@
struct fc_rport_priv *rdata;
struct qedf_ctx *qedf;
u16 xid;
- u32 r_a_tov = 0;
int rc = 0;
unsigned long flags;
struct fcoe_wqe *sqe;
@@ -1878,7 +1897,6 @@
goto out;
}
- r_a_tov = rdata->r_a_tov;
lport = qedf->lport;
if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
@@ -1956,14 +1974,12 @@
struct qedf_ioreq *io_req)
{
uint32_t r_ctl;
- uint16_t xid;
int rc;
struct qedf_rport *fcport = io_req->fcport;
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_SCSI_TM, "Entered with xid = "
"0x%x cmd_type = %d\n", io_req->xid, io_req->cmd_type);
- xid = io_req->xid;
r_ctl = cqe->cqe_info.abts_info.r_ctl;
/* This was added at a point when we were scheduling abts_compl &
@@ -2151,8 +2167,6 @@
{
struct qedf_rport *fcport;
struct qedf_ctx *qedf;
- uint16_t xid;
- struct e4_fcoe_task_context *task;
int tmo = 0;
int rc = SUCCESS;
unsigned long flags;
@@ -2169,7 +2183,6 @@
/* Sanity check qedf_rport before dereferencing any pointers */
if (!test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags)) {
QEDF_ERR(NULL, "tgt not offloaded\n");
- rc = 1;
return SUCCESS;
}
@@ -2179,6 +2192,10 @@
return SUCCESS;
}
+ if (io_req->cmd_type == QEDF_ELS) {
+ goto process_els;
+ }
+
if (!test_bit(QEDF_CMD_OUTSTANDING, &io_req->flags) ||
test_and_set_bit(QEDF_CMD_IN_CLEANUP, &io_req->flags)) {
QEDF_ERR(&(qedf->dbg_ctx), "io_req xid=0x%x already in "
@@ -2188,6 +2205,7 @@
}
set_bit(QEDF_CMD_IN_CLEANUP, &io_req->flags);
+process_els:
/* Ensure room on SQ */
if (!atomic_read(&fcport->free_sqes)) {
QEDF_ERR(&(qedf->dbg_ctx), "No SQ entries available\n");
@@ -2212,12 +2230,9 @@
refcount, fcport, fcport->rdata->ids.port_id);
/* Cleanup cmds re-use the same TID as the original I/O */
- xid = io_req->xid;
io_req->cmd_type = QEDF_CLEANUP;
io_req->return_scsi_cmd_on_abts = return_scsi_cmd_on_abts;
- task = qedf_get_task_mem(&qedf->tasks, xid);
-
init_completion(&io_req->cleanup_done);
spin_lock_irqsave(&fcport->rport_lock, flags);
@@ -2253,6 +2268,7 @@
io_req->tm_flags == FCP_TMF_TGT_RESET) {
clear_bit(QEDF_CMD_OUTSTANDING, &io_req->flags);
io_req->sc_cmd = NULL;
+ kref_put(&io_req->refcount, qedf_release_cmd);
complete(&io_req->tm_done);
}
@@ -2523,7 +2539,6 @@
struct fcoe_cqe *cqe)
{
unsigned long flags;
- uint16_t tmp;
uint16_t pktlen = cqe->cqe_info.unsolic_info.pkt_len;
u32 payload_len, crc;
struct fc_frame_header *fh;
@@ -2621,9 +2636,9 @@
qedf->bdq_prod_idx = 0;
writew(qedf->bdq_prod_idx, qedf->bdq_primary_prod);
- tmp = readw(qedf->bdq_primary_prod);
+ readw(qedf->bdq_primary_prod);
writew(qedf->bdq_prod_idx, qedf->bdq_secondary_prod);
- tmp = readw(qedf->bdq_secondary_prod);
+ readw(qedf->bdq_secondary_prod);
spin_unlock_irqrestore(&qedf->hba_lock, flags);
}
diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index c95e04c..e64457f 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -13,6 +13,7 @@
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/kthread.h>
+#include <linux/phylink.h>
#include <scsi/libfc.h>
#include <scsi/scsi_host.h>
#include <scsi/fc_frame.h>
@@ -28,6 +29,8 @@
static int qedf_probe(struct pci_dev *pdev, const struct pci_device_id *id);
static void qedf_remove(struct pci_dev *pdev);
static void qedf_shutdown(struct pci_dev *pdev);
+static void qedf_schedule_recovery_handler(void *dev);
+static void qedf_recovery_handler(struct work_struct *work);
/*
* Driver module parameters.
@@ -38,7 +41,7 @@
"remote ports (default 60)");
uint qedf_debug = QEDF_LOG_INFO;
-module_param_named(debug, qedf_debug, uint, S_IRUGO);
+module_param_named(debug, qedf_debug, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(debug, " Debug mask. Pass '1' to enable default debugging"
" mask");
@@ -102,6 +105,12 @@
MODULE_PARM_DESC(dp_level, " printk verbosity control passed to qed module "
"during probe (0-3: 0 more verbose).");
+static bool qedf_enable_recovery = true;
+module_param_named(enable_recovery, qedf_enable_recovery,
+ bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(enable_recovery, "Enable/disable recovery on driver/firmware "
+ "interface level errors 0 = Disabled, 1 = Enabled (Default: 1).");
+
struct workqueue_struct *qedf_io_wq;
static struct fcoe_percpu_s qedf_global;
@@ -282,6 +291,7 @@
else if (fc_frame_payload_op(fp) == ELS_LS_ACC) {
/* Set the source MAC we will use for FCoE traffic */
qedf_set_data_src_addr(qedf, fp);
+ qedf->flogi_pending = 0;
}
/* Complete flogi_compl so we can proceed to sending ADISCs */
@@ -307,6 +317,11 @@
*/
if (resp == fc_lport_flogi_resp) {
qedf->flogi_cnt++;
+ if (qedf->flogi_pending >= QEDF_FLOGI_RETRY_CNT) {
+ schedule_delayed_work(&qedf->stag_work, 2);
+ return NULL;
+ }
+ qedf->flogi_pending++;
return fc_elsct_send(lport, did, fp, op, qedf_flogi_resp,
arg, timeout);
}
@@ -432,6 +447,7 @@
static void qedf_update_link_speed(struct qedf_ctx *qedf,
struct qed_link_output *link)
{
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(sup_caps);
struct fc_lport *lport = qedf->lport;
lport->link_speed = FC_PORTSPEED_UNKNOWN;
@@ -466,41 +482,89 @@
* Set supported link speed by querying the supported
* capabilities of the link.
*/
- if ((link->supported_caps & QED_LM_10000baseT_Full_BIT) ||
- (link->supported_caps & QED_LM_10000baseKX4_Full_BIT) ||
- (link->supported_caps & QED_LM_10000baseR_FEC_BIT) ||
- (link->supported_caps & QED_LM_10000baseCR_Full_BIT) ||
- (link->supported_caps & QED_LM_10000baseSR_Full_BIT) ||
- (link->supported_caps & QED_LM_10000baseLR_Full_BIT) ||
- (link->supported_caps & QED_LM_10000baseLRM_Full_BIT) ||
- (link->supported_caps & QED_LM_10000baseKR_Full_BIT)) {
+
+ phylink_zero(sup_caps);
+ phylink_set(sup_caps, 10000baseT_Full);
+ phylink_set(sup_caps, 10000baseKX4_Full);
+ phylink_set(sup_caps, 10000baseR_FEC);
+ phylink_set(sup_caps, 10000baseCR_Full);
+ phylink_set(sup_caps, 10000baseSR_Full);
+ phylink_set(sup_caps, 10000baseLR_Full);
+ phylink_set(sup_caps, 10000baseLRM_Full);
+ phylink_set(sup_caps, 10000baseKR_Full);
+
+ if (linkmode_intersects(link->supported_caps, sup_caps))
lport->link_supported_speeds |= FC_PORTSPEED_10GBIT;
- }
- if ((link->supported_caps & QED_LM_25000baseKR_Full_BIT) ||
- (link->supported_caps & QED_LM_25000baseCR_Full_BIT) ||
- (link->supported_caps & QED_LM_25000baseSR_Full_BIT)) {
+
+ phylink_zero(sup_caps);
+ phylink_set(sup_caps, 25000baseKR_Full);
+ phylink_set(sup_caps, 25000baseCR_Full);
+ phylink_set(sup_caps, 25000baseSR_Full);
+
+ if (linkmode_intersects(link->supported_caps, sup_caps))
lport->link_supported_speeds |= FC_PORTSPEED_25GBIT;
- }
- if ((link->supported_caps & QED_LM_40000baseLR4_Full_BIT) ||
- (link->supported_caps & QED_LM_40000baseKR4_Full_BIT) ||
- (link->supported_caps & QED_LM_40000baseCR4_Full_BIT) ||
- (link->supported_caps & QED_LM_40000baseSR4_Full_BIT)) {
+
+ phylink_zero(sup_caps);
+ phylink_set(sup_caps, 40000baseLR4_Full);
+ phylink_set(sup_caps, 40000baseKR4_Full);
+ phylink_set(sup_caps, 40000baseCR4_Full);
+ phylink_set(sup_caps, 40000baseSR4_Full);
+
+ if (linkmode_intersects(link->supported_caps, sup_caps))
lport->link_supported_speeds |= FC_PORTSPEED_40GBIT;
- }
- if ((link->supported_caps & QED_LM_50000baseKR2_Full_BIT) ||
- (link->supported_caps & QED_LM_50000baseCR2_Full_BIT) ||
- (link->supported_caps & QED_LM_50000baseSR2_Full_BIT)) {
+
+ phylink_zero(sup_caps);
+ phylink_set(sup_caps, 50000baseKR2_Full);
+ phylink_set(sup_caps, 50000baseCR2_Full);
+ phylink_set(sup_caps, 50000baseSR2_Full);
+
+ if (linkmode_intersects(link->supported_caps, sup_caps))
lport->link_supported_speeds |= FC_PORTSPEED_50GBIT;
- }
- if ((link->supported_caps & QED_LM_100000baseKR4_Full_BIT) ||
- (link->supported_caps & QED_LM_100000baseSR4_Full_BIT) ||
- (link->supported_caps & QED_LM_100000baseCR4_Full_BIT) ||
- (link->supported_caps & QED_LM_100000baseLR4_ER4_Full_BIT)) {
+
+ phylink_zero(sup_caps);
+ phylink_set(sup_caps, 100000baseKR4_Full);
+ phylink_set(sup_caps, 100000baseSR4_Full);
+ phylink_set(sup_caps, 100000baseCR4_Full);
+ phylink_set(sup_caps, 100000baseLR4_ER4_Full);
+
+ if (linkmode_intersects(link->supported_caps, sup_caps))
lport->link_supported_speeds |= FC_PORTSPEED_100GBIT;
- }
- if (link->supported_caps & QED_LM_20000baseKR2_Full_BIT)
+
+ phylink_zero(sup_caps);
+ phylink_set(sup_caps, 20000baseKR2_Full);
+
+ if (linkmode_intersects(link->supported_caps, sup_caps))
lport->link_supported_speeds |= FC_PORTSPEED_20GBIT;
- fc_host_supported_speeds(lport->host) = lport->link_supported_speeds;
+
+ if (lport->host && lport->host->shost_data)
+ fc_host_supported_speeds(lport->host) =
+ lport->link_supported_speeds;
+}
+
+static void qedf_bw_update(void *dev)
+{
+ struct qedf_ctx *qedf = (struct qedf_ctx *)dev;
+ struct qed_link_output link;
+
+ /* Get the latest status of the link */
+ qed_ops->common->get_link(qedf->cdev, &link);
+
+ if (test_bit(QEDF_UNLOADING, &qedf->flags)) {
+ QEDF_ERR(&qedf->dbg_ctx,
+ "Ignore link update, driver getting unload.\n");
+ return;
+ }
+
+ if (link.link_up) {
+ if (atomic_read(&qedf->link_state) == QEDF_LINK_UP)
+ qedf_update_link_speed(qedf, &link);
+ else
+ QEDF_ERR(&qedf->dbg_ctx,
+ "Ignore bw update, link is down.\n");
+
+ } else {
+ QEDF_ERR(&qedf->dbg_ctx, "link_up is not set.\n");
+ }
}
static void qedf_link_update(void *dev, struct qed_link_output *link)
@@ -629,9 +693,12 @@
static struct qed_fcoe_cb_ops qedf_cb_ops = {
{
.link_update = qedf_link_update,
+ .bw_update = qedf_bw_update,
+ .schedule_recovery_handler = qedf_schedule_recovery_handler,
.dcbx_aen = qedf_dcbx_handler,
.get_generic_tlv_data = qedf_get_generic_tlv_data,
.get_protocol_tlv_data = qedf_get_protocol_tlv_data,
+ .schedule_hw_err_handler = qedf_schedule_hw_err_handler,
}
};
@@ -850,6 +917,7 @@
qedf = lport_priv(lport);
+ qedf->flogi_pending = 0;
/* For host reset, essentially do a soft link up/down */
atomic_set(&qedf->link_state, QEDF_LINK_DOWN);
QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
@@ -982,9 +1050,8 @@
return rc;
}
-/**
+/*
* qedf_xmit - qedf FCoE frame transmit function
- *
*/
static int qedf_xmit(struct fc_lport *lport, struct fc_frame *fp)
{
@@ -1275,7 +1342,7 @@
ether_addr_copy(conn_info.dst_mac, qedf->ctlr.dest_addr);
conn_info.tx_max_fc_pay_len = fcport->rdata->maxframe_size;
- conn_info.e_d_tov_timer_val = qedf->lport->e_d_tov / 20;
+ conn_info.e_d_tov_timer_val = qedf->lport->e_d_tov;
conn_info.rec_tov_timer_val = 3; /* I think this is what E3 was */
conn_info.rx_max_fc_pay_len = fcport->rdata->maxframe_size;
@@ -1378,7 +1445,7 @@
kref_put(&rdata->kref, fc_rport_destroy);
}
-/**
+/*
* This event_callback is called after successful completion of libfc
* initiated target login. qedf can proceed with initiating the session
* establishment.
@@ -1500,6 +1567,17 @@
if (port_id == FC_FID_DIR_SERV)
break;
+ if (rdata->spp_type != FC_TYPE_FCP) {
+ QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
+ "No action since spp type isn't FCP\n");
+ break;
+ }
+ if (!(rdata->ids.roles & FC_RPORT_ROLE_FCP_TARGET)) {
+ QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
+ "Not FCP target so no action\n");
+ break;
+ }
+
if (!rport) {
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
"port_id=%x - rport notcreated Yet!!\n", port_id);
@@ -1576,12 +1654,13 @@
static void qedf_setup_fdmi(struct qedf_ctx *qedf)
{
struct fc_lport *lport = qedf->lport;
- struct fc_host_attrs *fc_host = shost_to_fc_host(lport->host);
u8 buf[8];
- int i, pos;
+ int pos;
+ uint32_t i;
/*
- * fdmi_enabled needs to be set for libfc to execute FDMI registration.
+ * fdmi_enabled needs to be set for libfc
+ * to execute FDMI registration
*/
lport->fdmi_enabled = 1;
@@ -1597,33 +1676,47 @@
for (i = 0; i < 8; i++)
pci_read_config_byte(qedf->pdev, pos + i, &buf[i]);
- snprintf(fc_host->serial_number,
- sizeof(fc_host->serial_number),
+ snprintf(fc_host_serial_number(lport->host),
+ FC_SERIAL_NUMBER_SIZE,
"%02X%02X%02X%02X%02X%02X%02X%02X",
buf[7], buf[6], buf[5], buf[4],
buf[3], buf[2], buf[1], buf[0]);
} else
- snprintf(fc_host->serial_number,
- sizeof(fc_host->serial_number), "Unknown");
+ snprintf(fc_host_serial_number(lport->host),
+ FC_SERIAL_NUMBER_SIZE, "Unknown");
- snprintf(fc_host->manufacturer,
- sizeof(fc_host->manufacturer), "%s", "Cavium Inc.");
+ snprintf(fc_host_manufacturer(lport->host),
+ FC_SERIAL_NUMBER_SIZE, "%s", "Marvell Semiconductor Inc.");
- snprintf(fc_host->model, sizeof(fc_host->model), "%s", "QL41000");
+ if (qedf->pdev->device == QL45xxx) {
+ snprintf(fc_host_model(lport->host),
+ FC_SYMBOLIC_NAME_SIZE, "%s", "QL45xxx");
- snprintf(fc_host->model_description, sizeof(fc_host->model_description),
- "%s", "QLogic FastLinQ QL41000 Series 10/25/40/50GGbE Controller"
- "(FCoE)");
+ snprintf(fc_host_model_description(lport->host),
+ FC_SYMBOLIC_NAME_SIZE, "%s",
+ "Marvell FastLinQ QL45xxx FCoE Adapter");
+ }
- snprintf(fc_host->hardware_version, sizeof(fc_host->hardware_version),
- "Rev %d", qedf->pdev->revision);
+ if (qedf->pdev->device == QL41xxx) {
+ snprintf(fc_host_model(lport->host),
+ FC_SYMBOLIC_NAME_SIZE, "%s", "QL41xxx");
- snprintf(fc_host->driver_version, sizeof(fc_host->driver_version),
- "%s", QEDF_VERSION);
+ snprintf(fc_host_model_description(lport->host),
+ FC_SYMBOLIC_NAME_SIZE, "%s",
+ "Marvell FastLinQ QL41xxx FCoE Adapter");
+ }
- snprintf(fc_host->firmware_version, sizeof(fc_host->firmware_version),
- "%d.%d.%d.%d", FW_MAJOR_VERSION, FW_MINOR_VERSION,
- FW_REVISION_VERSION, FW_ENGINEERING_VERSION);
+ snprintf(fc_host_hardware_version(lport->host),
+ FC_VERSION_STRING_SIZE, "Rev %d", qedf->pdev->revision);
+
+ snprintf(fc_host_driver_version(lport->host),
+ FC_VERSION_STRING_SIZE, "%s", QEDF_VERSION);
+
+ snprintf(fc_host_firmware_version(lport->host),
+ FC_VERSION_STRING_SIZE, "%d.%d.%d.%d",
+ FW_MAJOR_VERSION, FW_MINOR_VERSION, FW_REVISION_VERSION,
+ FW_ENGINEERING_VERSION);
+
}
static int qedf_lport_setup(struct qedf_ctx *qedf)
@@ -1670,8 +1763,13 @@
fc_host_dev_loss_tmo(lport->host) = qedf_dev_loss_tmo;
/* Set symbolic node name */
- snprintf(fc_host_symbolic_name(lport->host), 256,
- "QLogic %s v%s", QEDF_MODULE_NAME, QEDF_VERSION);
+ if (qedf->pdev->device == QL45xxx)
+ snprintf(fc_host_symbolic_name(lport->host), 256,
+ "Marvell FastLinQ 45xxx FCoE v%s", QEDF_VERSION);
+
+ if (qedf->pdev->device == QL41xxx)
+ snprintf(fc_host_symbolic_name(lport->host), 256,
+ "Marvell FastLinQ 41xxx FCoE v%s", QEDF_VERSION);
qedf_setup_fdmi(qedf);
@@ -1761,6 +1859,7 @@
vport_qedf->cmd_mgr = base_qedf->cmd_mgr;
init_completion(&vport_qedf->flogi_compl);
INIT_LIST_HEAD(&vport_qedf->fcports);
+ INIT_DELAYED_WORK(&vport_qedf->stag_work, qedf_stag_change_work);
rc = qedf_vport_libfc_config(vport, vn_port);
if (rc) {
@@ -1924,6 +2023,13 @@
return 0;
}
+static void qedf_get_host_port_id(struct Scsi_Host *shost)
+{
+ struct fc_lport *lport = shost_priv(shost);
+
+ fc_host_port_id(shost) = lport->port_id;
+}
+
static struct fc_host_statistics *qedf_fc_get_host_stats(struct Scsi_Host
*shost)
{
@@ -1994,6 +2100,7 @@
.show_host_active_fc4s = 1,
.show_host_maxframe_size = 1,
+ .get_host_port_id = qedf_get_host_port_id,
.show_host_port_id = 1,
.show_host_supported_speeds = 1,
.get_host_speed = fc_get_host_speed,
@@ -3161,12 +3268,16 @@
void *task_start, *task_end;
struct qed_slowpath_params slowpath_params;
struct qed_probe_params qed_params;
- u16 tmp;
+ u16 retry_cnt = 10;
/*
* When doing error recovery we didn't reap the lport so don't try
* to reallocate it.
*/
+retry_probe:
+ if (mode == QEDF_MODE_RECOVERY)
+ msleep(2000);
+
if (mode != QEDF_MODE_RECOVERY) {
lport = libfc_host_alloc(&qedf_host_template,
sizeof(struct qedf_ctx));
@@ -3196,6 +3307,7 @@
init_completion(&qedf->fipvlan_compl);
mutex_init(&qedf->stats_mutex);
mutex_init(&qedf->flush_mutex);
+ qedf->flogi_pending = 0;
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_INFO,
"QLogic FastLinQ FCoE Module qedf %s, "
@@ -3229,6 +3341,7 @@
INIT_DELAYED_WORK(&qedf->link_update, qedf_handle_link_update);
INIT_DELAYED_WORK(&qedf->link_recovery, qedf_link_recovery);
INIT_DELAYED_WORK(&qedf->grcdump_work, qedf_wq_grcdump);
+ INIT_DELAYED_WORK(&qedf->stag_work, qedf_stag_change_work);
qedf->fipvlan_retries = qedf_fipvlan_retries;
/* Set a default prio in case DCBX doesn't converge */
if (qedf_default_prio > -1) {
@@ -3251,6 +3364,12 @@
qed_params.is_vf = is_vf;
qedf->cdev = qed_ops->common->probe(pdev, &qed_params);
if (!qedf->cdev) {
+ if ((mode == QEDF_MODE_RECOVERY) && retry_cnt) {
+ QEDF_ERR(&qedf->dbg_ctx,
+ "Retry %d initialize hardware\n", retry_cnt);
+ retry_cnt--;
+ goto retry_probe;
+ }
QEDF_ERR(&qedf->dbg_ctx, "common probe failed.\n");
rc = -ENODEV;
goto err1;
@@ -3283,6 +3402,13 @@
}
qed_ops->common->update_pf_params(qedf->cdev, &qedf->pf_params);
+ /* Learn information crucial for qedf to progress */
+ rc = qed_ops->fill_dev_info(qedf->cdev, &qedf->dev_info);
+ if (rc) {
+ QEDF_ERR(&qedf->dbg_ctx, "Failed to fill dev info.\n");
+ goto err2;
+ }
+
/* Record BDQ producer doorbell addresses */
qedf->bdq_primary_prod = qedf->dev_info.primary_dbq_rq_addr;
qedf->bdq_secondary_prod = qedf->dev_info.secondary_bdq_rq_addr;
@@ -3346,9 +3472,9 @@
"Writing %d to primary and secondary BDQ doorbell registers.\n",
qedf->bdq_prod_idx);
writew(qedf->bdq_prod_idx, qedf->bdq_primary_prod);
- tmp = readw(qedf->bdq_primary_prod);
+ readw(qedf->bdq_primary_prod);
writew(qedf->bdq_prod_idx, qedf->bdq_secondary_prod);
- tmp = readw(qedf->bdq_secondary_prod);
+ readw(qedf->bdq_secondary_prod);
qed_ops->common->set_power_state(qedf->cdev, PCI_D0);
@@ -3468,6 +3594,7 @@
qedf->lport->host->host_no);
qedf->dpc_wq = create_workqueue(host_buf);
}
+ INIT_DELAYED_WORK(&qedf->recovery_work, qedf_recovery_handler);
/*
* GRC dump and sysfs parameters are not reaped during the recovery
@@ -3691,6 +3818,44 @@
qedf_capture_grc_dump(qedf);
}
+void qedf_schedule_hw_err_handler(void *dev, enum qed_hw_err_type err_type)
+{
+ struct qedf_ctx *qedf = dev;
+
+ QEDF_ERR(&(qedf->dbg_ctx),
+ "Hardware error handler scheduled, event=%d.\n",
+ err_type);
+
+ if (test_bit(QEDF_IN_RECOVERY, &qedf->flags)) {
+ QEDF_ERR(&(qedf->dbg_ctx),
+ "Already in recovery, not scheduling board disable work.\n");
+ return;
+ }
+
+ switch (err_type) {
+ case QED_HW_ERR_FAN_FAIL:
+ schedule_delayed_work(&qedf->board_disable_work, 0);
+ break;
+ case QED_HW_ERR_MFW_RESP_FAIL:
+ case QED_HW_ERR_HW_ATTN:
+ case QED_HW_ERR_DMAE_FAIL:
+ case QED_HW_ERR_FW_ASSERT:
+ /* Prevent HW attentions from being reasserted */
+ qed_ops->common->attn_clr_enable(qedf->cdev, true);
+ break;
+ case QED_HW_ERR_RAMROD_FAIL:
+ /* Prevent HW attentions from being reasserted */
+ qed_ops->common->attn_clr_enable(qedf->cdev, true);
+
+ if (qedf_enable_recovery)
+ qed_ops->common->recovery_process(qedf->cdev);
+
+ break;
+ default:
+ break;
+ }
+}
+
/*
* Protocol TLV handler
*/
@@ -3787,11 +3952,64 @@
fcoe->scsi_tsk_full = qedf->task_set_fulls;
}
+/* Deferred work function to perform soft context reset on STAG change */
+void qedf_stag_change_work(struct work_struct *work)
+{
+ struct qedf_ctx *qedf =
+ container_of(work, struct qedf_ctx, stag_work.work);
+
+ if (!qedf) {
+ QEDF_ERR(NULL, "qedf is NULL");
+ return;
+ }
+ QEDF_ERR(&qedf->dbg_ctx, "Performing software context reset.\n");
+ qedf_ctx_soft_reset(qedf->lport);
+}
+
static void qedf_shutdown(struct pci_dev *pdev)
{
__qedf_remove(pdev, QEDF_MODE_NORMAL);
}
+/*
+ * Recovery handler code
+ */
+static void qedf_schedule_recovery_handler(void *dev)
+{
+ struct qedf_ctx *qedf = dev;
+
+ QEDF_ERR(&qedf->dbg_ctx, "Recovery handler scheduled.\n");
+ schedule_delayed_work(&qedf->recovery_work, 0);
+}
+
+static void qedf_recovery_handler(struct work_struct *work)
+{
+ struct qedf_ctx *qedf =
+ container_of(work, struct qedf_ctx, recovery_work.work);
+
+ if (test_and_set_bit(QEDF_IN_RECOVERY, &qedf->flags))
+ return;
+
+ /*
+ * Call common_ops->recovery_prolog to allow the MFW to quiesce
+ * any PCI transactions.
+ */
+ qed_ops->common->recovery_prolog(qedf->cdev);
+
+ QEDF_ERR(&qedf->dbg_ctx, "Recovery work start.\n");
+ __qedf_remove(qedf->pdev, QEDF_MODE_RECOVERY);
+ /*
+ * Reset link and dcbx to down state since we will not get a link down
+ * event from the MFW but calling __qedf_remove will essentially be a
+ * link down event.
+ */
+ atomic_set(&qedf->link_state, QEDF_LINK_DOWN);
+ atomic_set(&qedf->dcbx, QEDF_DCBX_PENDING);
+ __qedf_probe(qedf->pdev, QEDF_MODE_RECOVERY);
+ clear_bit(QEDF_IN_RECOVERY, &qedf->flags);
+ QEDF_ERR(&qedf->dbg_ctx, "Recovery work complete.\n");
+}
+
/* Generic TLV data callback */
void qedf_get_generic_tlv_data(void *dev, struct qed_generic_tlvs *data)
{
diff --git a/drivers/scsi/qedi/Kconfig b/drivers/scsi/qedi/Kconfig
index 7ab07f3..2091d88 100644
--- a/drivers/scsi/qedi/Kconfig
+++ b/drivers/scsi/qedi/Kconfig
@@ -8,6 +8,6 @@
select QED_OOO
select QED_ISCSI
select ISCSI_BOOT_SYSFS
- ---help---
+ help
This driver supports iSCSI offload for the QLogic FastLinQ
41000 Series Converged Network Adapters.
diff --git a/drivers/scsi/qedi/qedi.h b/drivers/scsi/qedi/qedi.h
index 9513fd3..ce199a7 100644
--- a/drivers/scsi/qedi/qedi.h
+++ b/drivers/scsi/qedi/qedi.h
@@ -36,6 +36,7 @@
*/
#define QEDI_MODE_NORMAL 0
#define QEDI_MODE_RECOVERY 1
+#define QEDI_MODE_SHUTDOWN 2
#define ISCSI_WQE_SET_PTU_INVALIDATE 1
#define QEDI_MAX_ISCSI_TASK 4096
@@ -273,11 +274,17 @@
spinlock_t ll2_lock; /* Light L2 lock */
spinlock_t hba_lock; /* per port lock */
struct task_struct *ll2_recv_thread;
+ unsigned long qedi_err_flags;
+#define QEDI_ERR_ATTN_CLR_EN 0
+#define QEDI_ERR_IS_RECOVERABLE 2
+#define QEDI_ERR_OVERRIDE_EN 31
unsigned long flags;
#define UIO_DEV_OPENED 1
#define QEDI_IOTHREAD_WAKE 2
#define QEDI_IN_RECOVERY 5
#define QEDI_IN_OFFLINE 6
+#define QEDI_IN_SHUTDOWN 7
+#define QEDI_BLOCK_IO 8
u8 mac[ETH_ALEN];
u32 src_ip[4];
@@ -303,6 +310,7 @@
u32 max_sqes;
u8 num_queues;
u32 max_active_conns;
+ s32 msix_count;
struct iscsi_cid_queue cid_que;
struct qedi_endpoint **ep_tbl;
@@ -331,6 +339,8 @@
u16 ll2_mtu;
struct workqueue_struct *dpc_wq;
+ struct delayed_work recovery_work;
+ struct delayed_work board_disable_work;
spinlock_t task_idx_lock; /* To protect gbl context */
s32 last_tidx_alloc;
diff --git a/drivers/scsi/qedi/qedi_dbg.h b/drivers/scsi/qedi/qedi_dbg.h
index 243acc8..37d0840 100644
--- a/drivers/scsi/qedi/qedi_dbg.h
+++ b/drivers/scsi/qedi/qedi_dbg.h
@@ -44,7 +44,7 @@
#define QEDI_LOG_LPORT 0x4000 /* lport logs */
#define QEDI_LOG_ELS 0x8000 /* ELS logs */
#define QEDI_LOG_NPIV 0x10000 /* NPIV logs */
-#define QEDI_LOG_SESS 0x20000 /* Conection setup, cleanup */
+#define QEDI_LOG_SESS 0x20000 /* Connection setup, cleanup */
#define QEDI_LOG_UIO 0x40000 /* iSCSI UIO logs */
#define QEDI_LOG_TID 0x80000 /* FW TID context acquire,
* free
diff --git a/drivers/scsi/qedi/qedi_fw.c b/drivers/scsi/qedi/qedi_fw.c
index 37b8f08..4c87640 100644
--- a/drivers/scsi/qedi/qedi_fw.c
+++ b/drivers/scsi/qedi/qedi_fw.c
@@ -73,7 +73,6 @@
spin_unlock(&qedi_conn->list_lock);
cmd->state = RESPONSE_RECEIVED;
- qedi_clear_task_idx(qedi, cmd->task_id);
__iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr, NULL, 0);
spin_unlock(&session->back_lock);
@@ -138,7 +137,6 @@
spin_unlock(&qedi_conn->list_lock);
cmd->state = RESPONSE_RECEIVED;
- qedi_clear_task_idx(qedi, cmd->task_id);
__iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr_ptr,
qedi_conn->gen_pdu.resp_buf,
@@ -161,16 +159,9 @@
set_bit(QEDI_CONN_FW_CLEANUP, &qedi_conn->flags);
resp_hdr_ptr = (struct iscsi_tm_rsp *)qedi_cmd->tmf_resp_buf;
- iscsi_block_session(session->cls_session);
rval = qedi_cleanup_all_io(qedi, qedi_conn, qedi_cmd->task, true);
- if (rval) {
- qedi_clear_task_idx(qedi, qedi_cmd->task_id);
- iscsi_unblock_session(session->cls_session);
+ if (rval)
goto exit_tmf_resp;
- }
-
- iscsi_unblock_session(session->cls_session);
- qedi_clear_task_idx(qedi, qedi_cmd->task_id);
spin_lock(&session->back_lock);
__iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr_ptr, NULL, 0);
@@ -245,8 +236,6 @@
goto unblock_sess;
}
- qedi_clear_task_idx(qedi, qedi_cmd->task_id);
-
__iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr_ptr, NULL, 0);
kfree(resp_hdr_ptr);
@@ -314,7 +303,6 @@
"Freeing tid=0x%x for cid=0x%x\n",
cmd->task_id, qedi_conn->iscsi_conn_id);
cmd->state = RESPONSE_RECEIVED;
- qedi_clear_task_idx(qedi, cmd->task_id);
}
static void qedi_get_rq_bdq_buf(struct qedi_ctx *qedi,
@@ -360,7 +348,6 @@
struct iscsi_cqe_unsolicited *cqe,
int count)
{
- u16 tmp;
u16 idx = 0;
struct scsi_bd *pbl;
@@ -389,10 +376,10 @@
qedi->bdq_prod_idx += count;
writew(qedi->bdq_prod_idx, qedi->bdq_primary_prod);
- tmp = readw(qedi->bdq_primary_prod);
+ readw(qedi->bdq_primary_prod);
writew(qedi->bdq_prod_idx, qedi->bdq_secondary_prod);
- tmp = readw(qedi->bdq_secondary_prod);
+ readw(qedi->bdq_secondary_prod);
}
static void qedi_unsol_pdu_adjust_bdq(struct qedi_ctx *qedi,
@@ -469,7 +456,6 @@
}
spin_unlock(&qedi_conn->list_lock);
- qedi_clear_task_idx(qedi, cmd->task_id);
}
done:
@@ -674,7 +660,6 @@
if (qedi_io_tracing)
qedi_trace_io(qedi, task, cmd->task_id, QEDI_IO_TRACE_RSP);
- qedi_clear_task_idx(qedi, cmd->task_id);
__iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr,
conn->data, datalen);
error:
@@ -731,7 +716,6 @@
cqe->itid, cmd->task_id);
cmd->state = RESPONSE_RECEIVED;
- qedi_clear_task_idx(qedi, cmd->task_id);
spin_lock_bh(&session->back_lock);
__iscsi_put_task(task);
@@ -749,7 +733,6 @@
itt_t protoitt = 0;
int found = 0;
struct qedi_cmd *qedi_cmd = NULL;
- u32 rtid = 0;
u32 iscsi_cid;
struct qedi_conn *qedi_conn;
struct qedi_cmd *dbg_cmd;
@@ -780,7 +763,6 @@
found = 1;
mtask = qedi_cmd->task;
tmf_hdr = (struct iscsi_tm *)mtask->hdr;
- rtid = work->rtid;
list_del_init(&work->list);
kfree(work);
@@ -822,8 +804,6 @@
if (qedi_cmd->state == CLEANUP_WAIT_FAILED)
qedi_cmd->state = CLEANUP_RECV;
- qedi_clear_task_idx(qedi_conn->qedi, rtid);
-
spin_lock(&qedi_conn->list_lock);
if (likely(dbg_cmd->io_cmd_in_list)) {
dbg_cmd->io_cmd_in_list = false;
@@ -857,7 +837,6 @@
QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_TID,
"Freeing tid=0x%x for cid=0x%x\n",
cqe->itid, qedi_conn->iscsi_conn_id);
- qedi_clear_task_idx(qedi_conn->qedi, cqe->itid);
} else {
qedi_get_proto_itt(qedi, cqe->itid, &ptmp_itt);
@@ -1268,7 +1247,8 @@
rval = wait_event_interruptible_timeout(qedi_conn->wait_queue,
((qedi_conn->cmd_cleanup_req ==
qedi_conn->cmd_cleanup_cmpl) ||
- qedi_conn->ep),
+ test_bit(QEDI_IN_RECOVERY,
+ &qedi->flags)),
5 * HZ);
if (rval) {
QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_SCSI_TM,
@@ -1293,7 +1273,9 @@
/* Enable IOs for all other sessions except current.*/
if (!wait_event_interruptible_timeout(qedi_conn->wait_queue,
(qedi_conn->cmd_cleanup_req ==
- qedi_conn->cmd_cleanup_cmpl),
+ qedi_conn->cmd_cleanup_cmpl) ||
+ test_bit(QEDI_IN_RECOVERY,
+ &qedi->flags),
5 * HZ)) {
iscsi_host_for_each_session(qedi->shost,
qedi_mark_device_available);
diff --git a/drivers/scsi/qedi/qedi_gbl.h b/drivers/scsi/qedi/qedi_gbl.h
index 8ba7c77..116645c 100644
--- a/drivers/scsi/qedi/qedi_gbl.h
+++ b/drivers/scsi/qedi/qedi_gbl.h
@@ -73,5 +73,6 @@
void qedi_clearsq(struct qedi_ctx *qedi,
struct qedi_conn *qedi_conn,
struct iscsi_task *task);
+void qedi_clear_session_ctx(struct iscsi_cls_session *cls_sess);
#endif
diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c
index 755f66b..f51723e 100644
--- a/drivers/scsi/qedi/qedi_iscsi.c
+++ b/drivers/scsi/qedi/qedi_iscsi.c
@@ -330,12 +330,22 @@
void qedi_mark_device_missing(struct iscsi_cls_session *cls_session)
{
- iscsi_block_session(cls_session);
+ struct iscsi_session *session = cls_session->dd_data;
+ struct qedi_conn *qedi_conn = session->leadconn->dd_data;
+
+ spin_lock_bh(&session->frwd_lock);
+ set_bit(QEDI_BLOCK_IO, &qedi_conn->qedi->flags);
+ spin_unlock_bh(&session->frwd_lock);
}
void qedi_mark_device_available(struct iscsi_cls_session *cls_session)
{
- iscsi_unblock_session(cls_session);
+ struct iscsi_session *session = cls_session->dd_data;
+ struct qedi_conn *qedi_conn = session->leadconn->dd_data;
+
+ spin_lock_bh(&session->frwd_lock);
+ clear_bit(QEDI_BLOCK_IO, &qedi_conn->qedi->flags);
+ spin_unlock_bh(&session->frwd_lock);
}
static int qedi_bind_conn_to_iscsi_cid(struct qedi_ctx *qedi,
@@ -392,6 +402,7 @@
qedi_ep->conn = qedi_conn;
qedi_conn->ep = qedi_ep;
+ qedi_conn->iscsi_ep = ep;
qedi_conn->iscsi_conn_id = qedi_ep->iscsi_cid;
qedi_conn->fw_cid = qedi_ep->fw_cid;
qedi_conn->cmd_cleanup_req = 0;
@@ -771,7 +782,6 @@
}
cmd->conn = conn->dd_data;
- cmd->scsi_cmd = NULL;
return qedi_iscsi_send_generic_request(task);
}
@@ -782,6 +792,16 @@
struct qedi_cmd *cmd = task->dd_data;
struct scsi_cmnd *sc = task->sc;
+ /* Clear now so in cleanup_task we know it didn't make it */
+ cmd->scsi_cmd = NULL;
+ cmd->task_id = U16_MAX;
+
+ if (test_bit(QEDI_IN_SHUTDOWN, &qedi_conn->qedi->flags))
+ return -ENODEV;
+
+ if (test_bit(QEDI_BLOCK_IO, &qedi_conn->qedi->flags))
+ return -EACCES;
+
cmd->state = 0;
cmd->task = NULL;
cmd->use_slowpath = false;
@@ -832,6 +852,11 @@
return ERR_PTR(ret);
}
+ if (atomic_read(&qedi->link_state) != QEDI_LINK_UP) {
+ QEDI_WARN(&qedi->dbg_ctx, "qedi link down\n");
+ return ERR_PTR(-ENXIO);
+ }
+
ep = iscsi_create_endpoint(sizeof(struct qedi_endpoint));
if (!ep) {
QEDI_ERR(&qedi->dbg_ctx, "endpoint create fail\n");
@@ -866,12 +891,6 @@
QEDI_ERR(&qedi->dbg_ctx, "Invalid endpoint\n");
}
- if (atomic_read(&qedi->link_state) != QEDI_LINK_UP) {
- QEDI_WARN(&qedi->dbg_ctx, "qedi link down\n");
- ret = -ENXIO;
- goto ep_conn_exit;
- }
-
ret = qedi_alloc_sq(qedi, qedi_ep);
if (ret)
goto ep_conn_exit;
@@ -1068,6 +1087,11 @@
wait_delay += qedi->pf_params.iscsi_pf_params.two_msl_timer;
qedi_ep->state = EP_STATE_DISCONN_START;
+
+ if (test_bit(QEDI_IN_SHUTDOWN, &qedi->flags) ||
+ test_bit(QEDI_IN_RECOVERY, &qedi->flags))
+ goto ep_release_conn;
+
ret = qedi_ops->destroy_conn(qedi->cdev, qedi_ep->handle, abrt_conn);
if (ret) {
QEDI_WARN(&qedi->dbg_ctx,
@@ -1375,13 +1399,24 @@
static void qedi_cleanup_task(struct iscsi_task *task)
{
- if (!task->sc || task->state == ISCSI_TASK_PENDING) {
+ struct qedi_cmd *cmd;
+
+ if (task->state == ISCSI_TASK_PENDING) {
QEDI_INFO(NULL, QEDI_LOG_IO, "Returning ref_cnt=%d\n",
refcount_read(&task->refcount));
return;
}
- qedi_iscsi_unmap_sg_list(task->dd_data);
+ if (task->sc)
+ qedi_iscsi_unmap_sg_list(task->dd_data);
+
+ cmd = task->dd_data;
+ if (cmd->task_id != U16_MAX)
+ qedi_clear_task_idx(iscsi_host_priv(task->conn->session->host),
+ cmd->task_id);
+
+ cmd->task_id = U16_MAX;
+ cmd->scsi_cmd = NULL;
}
struct iscsi_transport qedi_iscsi_transport = {
@@ -1545,7 +1580,7 @@
},
};
-char *qedi_get_iscsi_error(enum iscsi_error_types err_code)
+static char *qedi_get_iscsi_error(enum iscsi_error_types err_code)
{
int i;
char *msg = NULL;
@@ -1606,6 +1641,20 @@
qedi_start_conn_recovery(qedi_conn->qedi, qedi_conn);
}
+void qedi_clear_session_ctx(struct iscsi_cls_session *cls_sess)
+{
+ struct iscsi_session *session = cls_sess->dd_data;
+ struct iscsi_conn *conn = session->leadconn;
+ struct qedi_conn *qedi_conn = conn->dd_data;
+
+ if (iscsi_is_session_online(cls_sess))
+ qedi_ep_disconnect(qedi_conn->iscsi_ep);
+
+ qedi_conn_destroy(qedi_conn->cls_conn);
+
+ qedi_session_destroy(cls_sess);
+}
+
void qedi_process_tcp_error(struct qedi_endpoint *ep,
struct iscsi_eqe_data *data)
{
diff --git a/drivers/scsi/qedi/qedi_iscsi.h b/drivers/scsi/qedi/qedi_iscsi.h
index 67c3b73..39dc27c 100644
--- a/drivers/scsi/qedi/qedi_iscsi.h
+++ b/drivers/scsi/qedi/qedi_iscsi.h
@@ -149,6 +149,7 @@
struct iscsi_cls_conn *cls_conn;
struct qedi_ctx *qedi;
struct qedi_endpoint *ep;
+ struct iscsi_endpoint *iscsi_ep;
struct list_head active_cmd_list;
spinlock_t list_lock; /* internal conn lock */
u32 active_cmd_count;
diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c
index 92c4a36..299d036 100644
--- a/drivers/scsi/qedi/qedi_main.c
+++ b/drivers/scsi/qedi/qedi_main.c
@@ -28,6 +28,10 @@
#include "qedi_gbl.h"
#include "qedi_iscsi.h"
+static uint qedi_qed_debug;
+module_param(qedi_qed_debug, uint, 0644);
+MODULE_PARM_DESC(qedi_qed_debug, " QED debug level 0 (default)");
+
static uint qedi_fw_debug;
module_param(qedi_fw_debug, uint, 0644);
MODULE_PARM_DESC(qedi_fw_debug, " Firmware debug level 0(default) to 3");
@@ -41,11 +45,15 @@
MODULE_PARM_DESC(qedi_io_tracing,
" Enable logging of SCSI requests/completions into trace buffer. (default off).");
-uint qedi_ll2_buf_size = 0x400;
+static uint qedi_ll2_buf_size = 0x400;
module_param(qedi_ll2_buf_size, uint, 0644);
MODULE_PARM_DESC(qedi_ll2_buf_size,
"parameter to set ping packet size, default - 0x400, Jumbo packets - 0x2400.");
+static uint qedi_flags_override;
+module_param(qedi_flags_override, uint, 0644);
+MODULE_PARM_DESC(qedi_flags_override, "Disable/Enable MFW error flags bits action.");
+
const struct qed_iscsi_ops *qedi_ops;
static struct scsi_transport_template *qedi_scsi_transport;
static struct pci_driver qedi_pci_driver;
@@ -58,6 +66,9 @@
static void qedi_reset_uio_rings(struct qedi_uio_dev *udev);
static void qedi_ll2_free_skbs(struct qedi_ctx *qedi);
static struct nvm_iscsi_block *qedi_get_nvram_block(struct qedi_ctx *qedi);
+static void qedi_recovery_handler(struct work_struct *work);
+static void qedi_schedule_hw_err_handler(void *dev,
+ enum qed_hw_err_type err_type);
static int qedi_iscsi_event_cb(void *context, u8 fw_event_code, void *fw_handle)
{
@@ -657,8 +668,6 @@
static int qedi_ll2_rx(void *cookie, struct sk_buff *skb, u32 arg1, u32 arg2)
{
struct qedi_ctx *qedi = (struct qedi_ctx *)cookie;
- struct qedi_uio_dev *udev;
- struct qedi_uio_ctrl *uctrl;
struct skb_work_list *work;
struct ethhdr *eh;
@@ -697,9 +706,6 @@
"Allowed frame ethertype [0x%x] len [0x%x].\n",
eh->h_proto, skb->len);
- udev = qedi->udev;
- uctrl = udev->uctrl;
-
work = kzalloc(sizeof(*work), GFP_ATOMIC);
if (!work) {
QEDI_WARN(&qedi->dbg_ctx,
@@ -789,8 +795,7 @@
spin_lock_bh(&qedi->ll2_lock);
list_for_each_entry_safe(work, work_tmp, &qedi->ll2_skb_list, list) {
list_del(&work->list);
- if (work->skb)
- kfree_skb(work->skb);
+ kfree_skb(work->skb);
kfree(work);
}
spin_unlock_bh(&qedi->ll2_lock);
@@ -920,7 +925,7 @@
ipv6_en = !!(block->generic.ctrl_flags &
NVM_ISCSI_CFG_GEN_IPV6_ENABLED);
- snprintf(tgt->iscsi_name, sizeof(tgt->iscsi_name), "%s\n",
+ snprintf(tgt->iscsi_name, sizeof(tgt->iscsi_name), "%s",
block->target[index].target_name.byte);
tgt->ipv6_en = ipv6_en;
@@ -1113,6 +1118,65 @@
return;
}
+void qedi_schedule_hw_err_handler(void *dev,
+ enum qed_hw_err_type err_type)
+{
+ struct qedi_ctx *qedi = (struct qedi_ctx *)dev;
+ unsigned long override_flags = qedi_flags_override;
+
+ if (override_flags && test_bit(QEDI_ERR_OVERRIDE_EN, &override_flags))
+ qedi->qedi_err_flags = qedi_flags_override;
+
+ QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
+ "HW error handler scheduled, err=%d err_flags=0x%x\n",
+ err_type, qedi->qedi_err_flags);
+
+ switch (err_type) {
+ case QED_HW_ERR_FAN_FAIL:
+ schedule_delayed_work(&qedi->board_disable_work, 0);
+ break;
+ case QED_HW_ERR_MFW_RESP_FAIL:
+ case QED_HW_ERR_HW_ATTN:
+ case QED_HW_ERR_DMAE_FAIL:
+ case QED_HW_ERR_RAMROD_FAIL:
+ case QED_HW_ERR_FW_ASSERT:
+ /* Prevent HW attentions from being reasserted */
+ if (test_bit(QEDI_ERR_ATTN_CLR_EN, &qedi->qedi_err_flags))
+ qedi_ops->common->attn_clr_enable(qedi->cdev, true);
+
+ if (err_type == QED_HW_ERR_RAMROD_FAIL &&
+ test_bit(QEDI_ERR_IS_RECOVERABLE, &qedi->qedi_err_flags))
+ qedi_ops->common->recovery_process(qedi->cdev);
+
+ break;
+ default:
+ break;
+ }
+}
+
+static void qedi_schedule_recovery_handler(void *dev)
+{
+ struct qedi_ctx *qedi = dev;
+
+ QEDI_ERR(&qedi->dbg_ctx, "Recovery handler scheduled.\n");
+
+ if (test_and_set_bit(QEDI_IN_RECOVERY, &qedi->flags))
+ return;
+
+ atomic_set(&qedi->link_state, QEDI_LINK_DOWN);
+
+ schedule_delayed_work(&qedi->recovery_work, 0);
+}
+
+static void qedi_set_conn_recovery(struct iscsi_cls_session *cls_session)
+{
+ struct iscsi_session *session = cls_session->dd_data;
+ struct iscsi_conn *conn = session->leadconn;
+ struct qedi_conn *qedi_conn = conn->dd_data;
+
+ qedi_start_conn_recovery(qedi_conn->qedi, qedi_conn);
+}
+
static void qedi_link_update(void *dev, struct qed_link_output *link)
{
struct qedi_ctx *qedi = (struct qedi_ctx *)dev;
@@ -1124,12 +1188,15 @@
QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
"Link Down event.\n");
atomic_set(&qedi->link_state, QEDI_LINK_DOWN);
+ iscsi_host_for_each_session(qedi->shost, qedi_set_conn_recovery);
}
}
static struct qed_iscsi_cb_ops qedi_cb_ops = {
{
.link_update = qedi_link_update,
+ .schedule_recovery_handler = qedi_schedule_recovery_handler,
+ .schedule_hw_err_handler = qedi_schedule_hw_err_handler,
.get_protocol_tlv_data = qedi_get_protocol_tlv_data,
.get_generic_tlv_data = qedi_get_generic_tlv_data,
}
@@ -1140,7 +1207,6 @@
{
struct qedi_work *qedi_work;
struct qedi_conn *q_conn;
- struct iscsi_conn *conn;
struct qedi_cmd *qedi_cmd;
u32 iscsi_cid;
int rc = 0;
@@ -1153,7 +1219,6 @@
iscsi_cid);
return -1;
}
- conn = q_conn->cls_conn->dd_data;
switch (cqe->cqe_common.cqe_type) {
case ISCSI_CQE_TYPE_SOLICITED:
@@ -1286,13 +1351,13 @@
"process already running\n");
}
- if (qedi_fp_has_work(fp) == 0)
+ if (!qedi_fp_has_work(fp))
qed_sb_update_sb_idx(fp->sb_info);
/* Check for more work */
rmb();
- if (qedi_fp_has_work(fp) == 0)
+ if (!qedi_fp_has_work(fp))
qed_sb_ack(fp->sb_info, IGU_INT_ENABLE, 1);
else
goto process_again;
@@ -1344,7 +1409,7 @@
u16 idx;
cpu = cpumask_first(cpu_online_mask);
- for (i = 0; i < MIN_NUM_CPUS_MSIX(qedi); i++) {
+ for (i = 0; i < qedi->msix_count; i++) {
idx = i * qedi->dev_info.common.num_hwfns +
qedi_ops->common->get_affin_hwfn_idx(qedi->cdev);
@@ -1374,7 +1439,12 @@
{
int rc = 0;
- rc = qedi_ops->common->set_fp_int(qedi->cdev, num_online_cpus());
+ rc = qedi_ops->common->set_fp_int(qedi->cdev, qedi->num_queues);
+ if (rc < 0)
+ goto exit_setup_int;
+
+ qedi->msix_count = rc;
+
rc = qedi_ops->common->get_fp_int(qedi->cdev, &qedi->int_info);
if (rc)
goto exit_setup_int;
@@ -1948,7 +2018,7 @@
qedi_ops->ll2->start(qedi->cdev, ¶ms);
}
-/**
+/*
* qedi_get_nvram_block: - Scan through the iSCSI NVRAM block (while accounting
* for gaps) for the matching absolute-pf-id of the QEDI device.
*/
@@ -2324,21 +2394,47 @@
return -ENOMEM;
}
+static pci_ers_result_t qedi_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct qedi_ctx *qedi = pci_get_drvdata(pdev);
+
+ QEDI_ERR(&qedi->dbg_ctx, "%s: PCI error detected [%d]\n",
+ __func__, state);
+
+ if (test_and_set_bit(QEDI_IN_RECOVERY, &qedi->flags)) {
+ QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
+ "Recovery already in progress.\n");
+ return PCI_ERS_RESULT_NONE;
+ }
+
+ qedi_ops->common->recovery_process(qedi->cdev);
+
+ return PCI_ERS_RESULT_CAN_RECOVER;
+}
+
static void __qedi_remove(struct pci_dev *pdev, int mode)
{
struct qedi_ctx *qedi = pci_get_drvdata(pdev);
int rval;
+ u16 retry = 10;
- if (qedi->tmf_thread) {
- flush_workqueue(qedi->tmf_thread);
- destroy_workqueue(qedi->tmf_thread);
- qedi->tmf_thread = NULL;
- }
+ if (mode == QEDI_MODE_SHUTDOWN)
+ iscsi_host_for_each_session(qedi->shost,
+ qedi_clear_session_ctx);
- if (qedi->offload_thread) {
- flush_workqueue(qedi->offload_thread);
- destroy_workqueue(qedi->offload_thread);
- qedi->offload_thread = NULL;
+ if (mode == QEDI_MODE_NORMAL || mode == QEDI_MODE_SHUTDOWN) {
+ if (qedi->tmf_thread) {
+ flush_workqueue(qedi->tmf_thread);
+ destroy_workqueue(qedi->tmf_thread);
+ qedi->tmf_thread = NULL;
+ }
+
+ if (qedi->offload_thread) {
+ flush_workqueue(qedi->offload_thread);
+ destroy_workqueue(qedi->offload_thread);
+ qedi->offload_thread = NULL;
+ }
}
#ifdef CONFIG_DEBUG_FS
@@ -2350,12 +2446,17 @@
qedi_sync_free_irqs(qedi);
if (!test_bit(QEDI_IN_OFFLINE, &qedi->flags)) {
- qedi_ops->stop(qedi->cdev);
+ while (retry--) {
+ rval = qedi_ops->stop(qedi->cdev);
+ if (rval < 0)
+ msleep(1000);
+ else
+ break;
+ }
qedi_ops->ll2->stop(qedi->cdev);
}
- if (mode == QEDI_MODE_NORMAL)
- qedi_free_iscsi_pf_param(qedi);
+ qedi_free_iscsi_pf_param(qedi);
rval = qedi_ops->common->update_drv_state(qedi->cdev, false);
if (rval)
@@ -2368,15 +2469,12 @@
qedi_destroy_fp(qedi);
- if (mode == QEDI_MODE_NORMAL) {
+ if (mode == QEDI_MODE_NORMAL || mode == QEDI_MODE_SHUTDOWN) {
qedi_release_cid_que(qedi);
qedi_cm_free_mem(qedi);
qedi_free_uio(qedi->udev);
qedi_free_itt(qedi);
- iscsi_host_remove(qedi->shost);
- iscsi_host_free(qedi->shost);
-
if (qedi->ll2_recv_thread) {
kthread_stop(qedi->ll2_recv_thread);
qedi->ll2_recv_thread = NULL;
@@ -2385,14 +2483,41 @@
if (qedi->boot_kset)
iscsi_boot_destroy_kset(qedi->boot_kset);
+
+ iscsi_host_remove(qedi->shost);
+ iscsi_host_free(qedi->shost);
}
}
+static void qedi_board_disable_work(struct work_struct *work)
+{
+ struct qedi_ctx *qedi =
+ container_of(work, struct qedi_ctx,
+ board_disable_work.work);
+
+ QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
+ "Fan failure, Unloading firmware context.\n");
+
+ if (test_and_set_bit(QEDI_IN_SHUTDOWN, &qedi->flags))
+ return;
+
+ __qedi_remove(qedi->pdev, QEDI_MODE_SHUTDOWN);
+}
+
+static void qedi_shutdown(struct pci_dev *pdev)
+{
+ struct qedi_ctx *qedi = pci_get_drvdata(pdev);
+
+ QEDI_ERR(&qedi->dbg_ctx, "%s: Shutdown qedi\n", __func__);
+ if (test_and_set_bit(QEDI_IN_SHUTDOWN, &qedi->flags))
+ return;
+ __qedi_remove(pdev, QEDI_MODE_SHUTDOWN);
+}
+
static int __qedi_probe(struct pci_dev *pdev, int mode)
{
struct qedi_ctx *qedi;
struct qed_ll2_params params;
- u32 dp_module = 0;
u8 dp_level = 0;
bool is_vf = false;
char host_buf[16];
@@ -2401,7 +2526,7 @@
struct qed_probe_params qed_params;
void *task_start, *task_end;
int rc;
- u16 tmp;
+ u16 retry = 10;
if (mode != QEDI_MODE_RECOVERY) {
qedi = qedi_host_alloc(pdev);
@@ -2413,18 +2538,31 @@
qedi = pci_get_drvdata(pdev);
}
+retry_probe:
+ if (mode == QEDI_MODE_RECOVERY)
+ msleep(2000);
+
memset(&qed_params, 0, sizeof(qed_params));
qed_params.protocol = QED_PROTOCOL_ISCSI;
- qed_params.dp_module = dp_module;
+ qed_params.dp_module = qedi_qed_debug;
qed_params.dp_level = dp_level;
qed_params.is_vf = is_vf;
qedi->cdev = qedi_ops->common->probe(pdev, &qed_params);
if (!qedi->cdev) {
+ if (mode == QEDI_MODE_RECOVERY && retry) {
+ QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
+ "Retry %d initialize hardware\n", retry);
+ retry--;
+ goto retry_probe;
+ }
+
rc = -ENODEV;
QEDI_ERR(&qedi->dbg_ctx, "Cannot initialize hardware\n");
goto free_host;
}
+ set_bit(QEDI_ERR_ATTN_CLR_EN, &qedi->qedi_err_flags);
+ set_bit(QEDI_ERR_IS_RECOVERABLE, &qedi->qedi_err_flags);
atomic_set(&qedi->link_state, QEDI_LINK_DOWN);
rc = qedi_ops->fill_dev_info(qedi->cdev, &qedi->dev_info);
@@ -2436,14 +2574,12 @@
qedi->dev_info.common.num_hwfns,
qedi_ops->common->get_affin_hwfn_idx(qedi->cdev));
- if (mode != QEDI_MODE_RECOVERY) {
- rc = qedi_set_iscsi_pf_param(qedi);
- if (rc) {
- rc = -ENOMEM;
- QEDI_ERR(&qedi->dbg_ctx,
- "Set iSCSI pf param fail\n");
- goto free_host;
- }
+ rc = qedi_set_iscsi_pf_param(qedi);
+ if (rc) {
+ rc = -ENOMEM;
+ QEDI_ERR(&qedi->dbg_ctx,
+ "Set iSCSI pf param fail\n");
+ goto free_host;
}
qedi_ops->common->update_pf_params(qedi->cdev, &qedi->pf_params);
@@ -2502,15 +2638,15 @@
"Writing %d to primary and secondary BDQ doorbell registers.\n",
qedi->bdq_prod_idx);
writew(qedi->bdq_prod_idx, qedi->bdq_primary_prod);
- tmp = readw(qedi->bdq_primary_prod);
+ readw(qedi->bdq_primary_prod);
writew(qedi->bdq_prod_idx, qedi->bdq_secondary_prod);
- tmp = readw(qedi->bdq_secondary_prod);
+ readw(qedi->bdq_secondary_prod);
ether_addr_copy(qedi->mac, qedi->dev_info.common.hw_mac);
QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_DISC, "MAC address is %pM.\n",
qedi->mac);
- sprintf(host_buf, "host_%d", qedi->shost->host_no);
+ snprintf(host_buf, sizeof(host_buf), "host_%d", qedi->shost->host_no);
qedi_ops->common->set_name(qedi->cdev, host_buf);
qedi_ops->register_ops(qedi->cdev, &qedi_cb_ops, qedi);
@@ -2634,6 +2770,10 @@
goto free_tmf_thread;
}
+ INIT_DELAYED_WORK(&qedi->recovery_work, qedi_recovery_handler);
+ INIT_DELAYED_WORK(&qedi->board_disable_work,
+ qedi_board_disable_work);
+
/* F/w needs 1st task context memory entry for performance */
set_bit(QEDI_RESERVE_TASK_ID, qedi->task_idx_map);
atomic_set(&qedi->num_offloads, 0);
@@ -2676,6 +2816,32 @@
return rc;
}
+static void qedi_mark_conn_recovery(struct iscsi_cls_session *cls_session)
+{
+ struct iscsi_session *session = cls_session->dd_data;
+ struct iscsi_conn *conn = session->leadconn;
+ struct qedi_conn *qedi_conn = conn->dd_data;
+
+ iscsi_conn_failure(qedi_conn->cls_conn->dd_data, ISCSI_ERR_CONN_FAILED);
+}
+
+static void qedi_recovery_handler(struct work_struct *work)
+{
+ struct qedi_ctx *qedi =
+ container_of(work, struct qedi_ctx, recovery_work.work);
+
+ iscsi_host_for_each_session(qedi->shost, qedi_mark_conn_recovery);
+
+ /* Call common_ops->recovery_prolog to allow the MFW to quiesce
+ * any PCI transactions.
+ */
+ qedi_ops->common->recovery_prolog(qedi->cdev);
+
+ __qedi_remove(qedi->pdev, QEDI_MODE_RECOVERY);
+ __qedi_probe(qedi->pdev, QEDI_MODE_RECOVERY);
+ clear_bit(QEDI_IN_RECOVERY, &qedi->flags);
+}
+
static int qedi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
return __qedi_probe(pdev, QEDI_MODE_NORMAL);
@@ -2695,11 +2861,17 @@
static enum cpuhp_state qedi_cpuhp_state;
+static struct pci_error_handlers qedi_err_handler = {
+ .error_detected = qedi_io_error_detected,
+};
+
static struct pci_driver qedi_pci_driver = {
.name = QEDI_MODULE_NAME,
.id_table = qedi_pci_tbl,
.probe = qedi_probe,
.remove = qedi_remove,
+ .shutdown = qedi_shutdown,
+ .err_handler = &qedi_err_handler,
};
static int __init qedi_init(void)
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 832af42..545936c 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -526,7 +526,7 @@
};
MODULE_DEVICE_TABLE(pci, qla1280_pci_tbl);
-DEFINE_MUTEX(qla1280_firmware_mutex);
+static DEFINE_MUTEX(qla1280_firmware_mutex);
struct qla_fw {
char *fwname;
@@ -535,7 +535,7 @@
#define QL_NUM_FW_IMAGES 3
-struct qla_fw qla1280_fw_tbl[QL_NUM_FW_IMAGES] = {
+static struct qla_fw qla1280_fw_tbl[QL_NUM_FW_IMAGES] = {
{"qlogic/1040.bin", NULL}, /* image 0 */
{"qlogic/1280.bin", NULL}, /* image 1 */
{"qlogic/12160.bin", NULL}, /* image 2 */
@@ -1241,7 +1241,7 @@
{
struct srb *sp;
struct list_head *done_q;
- int bus, target, lun;
+ int bus, target;
struct scsi_cmnd *cmd;
ENTER("qla1280_done");
@@ -1256,7 +1256,6 @@
cmd = sp->cmd;
bus = SCSI_BUS_32(cmd);
target = SCSI_TCN_32(cmd);
- lun = SCSI_LUN_32(cmd);
switch ((CMD_RESULT(cmd) >> 16)) {
case DID_RESET:
@@ -1699,6 +1698,16 @@
return err;
}
+#ifdef QLA_64BIT_PTR
+#define LOAD_CMD MBC_LOAD_RAM_A64_ROM
+#define DUMP_CMD MBC_DUMP_RAM_A64_ROM
+#define CMD_ARGS (BIT_7 | BIT_6 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0)
+#else
+#define LOAD_CMD MBC_LOAD_RAM
+#define DUMP_CMD MBC_DUMP_RAM
+#define CMD_ARGS (BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0)
+#endif
+
#define DUMP_IT_BACK 0 /* for debug of RISC loading */
static int
qla1280_load_firmware_dma(struct scsi_qla_host *ha)
@@ -1748,7 +1757,7 @@
for(i = 0; i < cnt; i++)
((__le16 *)ha->request_ring)[i] = fw_data[i];
- mb[0] = MBC_LOAD_RAM;
+ mb[0] = LOAD_CMD;
mb[1] = risc_address;
mb[4] = cnt;
mb[3] = ha->request_dma & 0xffff;
@@ -1759,8 +1768,7 @@
__func__, mb[0],
(void *)(long)ha->request_dma,
mb[6], mb[7], mb[2], mb[3]);
- err = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | BIT_2 |
- BIT_1 | BIT_0, mb);
+ err = qla1280_mailbox_command(ha, CMD_ARGS, mb);
if (err) {
printk(KERN_ERR "scsi(%li): Failed to load partial "
"segment of f\n", ha->host_no);
@@ -1768,7 +1776,7 @@
}
#if DUMP_IT_BACK
- mb[0] = MBC_DUMP_RAM;
+ mb[0] = DUMP_CMD;
mb[1] = risc_address;
mb[4] = cnt;
mb[3] = p_tbuf & 0xffff;
@@ -1776,8 +1784,7 @@
mb[7] = upper_32_bits(p_tbuf) & 0xffff;
mb[6] = upper_32_bits(p_tbuf) >> 16;
- err = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | BIT_2 |
- BIT_1 | BIT_0, mb);
+ err = qla1280_mailbox_command(ha, CMD_ARGS, mb);
if (err) {
printk(KERN_ERR
"Failed to dump partial segment of f/w\n");
@@ -2177,13 +2184,12 @@
nv->cntr_flags_1.disable_loading_risc_code;
if (IS_ISP1040(ha)) {
- uint16_t hwrev, cfg1, cdma_conf, ddma_conf;
+ uint16_t hwrev, cfg1, cdma_conf;
hwrev = RD_REG_WORD(®->cfg_0) & ISP_CFG0_HWMSK;
cfg1 = RD_REG_WORD(®->cfg_1) & ~(BIT_4 | BIT_5 | BIT_6);
cdma_conf = RD_REG_WORD(®->cdma_cfg);
- ddma_conf = RD_REG_WORD(®->ddma_cfg);
/* Busted fifo, says mjacob. */
if (hwrev != ISP_CFG0_1040A)
@@ -2419,7 +2425,6 @@
int cnt;
uint16_t *optr, *iptr;
uint16_t __iomem *mptr;
- uint16_t data;
DECLARE_COMPLETION_ONSTACK(wait);
ENTER("qla1280_mailbox_command");
@@ -2454,7 +2459,7 @@
spin_unlock_irq(ha->host->host_lock);
WRT_REG_WORD(®->host_cmd, HC_SET_HOST_INT);
- data = qla1280_debounce_register(®->istatus);
+ qla1280_debounce_register(®->istatus);
wait_for_completion(&wait);
del_timer_sync(&ha->mailbox_timer);
@@ -3596,7 +3601,6 @@
qla1280_status_entry(struct scsi_qla_host *ha, struct response *pkt,
struct list_head *done_q)
{
- unsigned int bus, target, lun;
int sense_sz;
struct srb *sp;
struct scsi_cmnd *cmd;
@@ -3622,11 +3626,6 @@
cmd = sp->cmd;
- /* Generate LU queue on cntrl, target, LUN */
- bus = SCSI_BUS_32(cmd);
- target = SCSI_TCN_32(cmd);
- lun = SCSI_LUN_32(cmd);
-
if (comp_status || scsi_status) {
dprintk(3, "scsi: comp_status = 0x%x, scsi_status = "
"0x%x, handle = 0x%x\n", comp_status,
@@ -3665,7 +3664,8 @@
dprintk(2, "qla1280_status_entry: Check "
"condition Sense data, b %i, t %i, "
- "l %i\n", bus, target, lun);
+ "l %i\n", SCSI_BUS_32(cmd), SCSI_TCN_32(cmd),
+ SCSI_LUN_32(cmd));
if (sense_sz)
qla1280_dump_buffer(2,
(char *)cmd->sense_buffer,
diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
index a1a8aef..e7820b5 100644
--- a/drivers/scsi/qla1280.h
+++ b/drivers/scsi/qla1280.h
@@ -277,6 +277,8 @@
#define MBC_MAILBOX_REGISTER_TEST 6 /* Wrap incoming mailboxes */
#define MBC_VERIFY_CHECKSUM 7 /* Verify checksum */
#define MBC_ABOUT_FIRMWARE 8 /* Get firmware revision */
+#define MBC_LOAD_RAM_A64_ROM 9 /* Load RAM 64bit ROM version */
+#define MBC_DUMP_RAM_A64_ROM 0x0a /* Dump RAM 64bit ROM version */
#define MBC_INIT_REQUEST_QUEUE 0x10 /* Initialize request queue */
#define MBC_INIT_RESPONSE_QUEUE 0x11 /* Initialize response queue */
#define MBC_EXECUTE_IOCB 0x12 /* Execute IOCB command */
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
index 7645018..802c373 100644
--- a/drivers/scsi/qla2xxx/Kconfig
+++ b/drivers/scsi/qla2xxx/Kconfig
@@ -6,7 +6,7 @@
depends on NVME_FC || !NVME_FC
select FW_LOADER
select BTREE
- ---help---
+ help
This qla2xxx driver supports all QLogic Fibre Channel
PCI and PCIe host adapters.
@@ -37,14 +37,14 @@
depends on LIBFC
select BTREE
default n
- ---help---
+ help
Say Y here to enable the TCM_QLA2XXX fabric module for QLogic 24xx+ series target mode HBAs
if TCM_QLA2XXX
config TCM_QLA2XXX_DEBUG
bool "TCM_QLA2XXX fabric module DEBUG mode for QLogic 24xx+ series target mode HBAs"
default n
- ---help---
+ help
Say Y here to enable the TCM_QLA2XXX fabric module DEBUG for QLogic 24xx+ series target mode HBAs
This will include code to enable the SCSI command jammer
endif
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 580d30c..e40a372 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
#include "qla_target.h"
@@ -26,7 +25,8 @@
struct qla_hw_data *ha = vha->hw;
int rval = 0;
- if (!(ha->fw_dump_reading || ha->mctp_dump_reading))
+ if (!(ha->fw_dump_reading || ha->mctp_dump_reading ||
+ ha->mpi_fw_dump_reading))
return 0;
mutex_lock(&ha->optrom_mutex);
@@ -42,6 +42,10 @@
} else if (ha->mctp_dumped && ha->mctp_dump_reading) {
rval = memory_read_from_buffer(buf, count, &off, ha->mctp_dump,
MCTP_DUMP_SIZE);
+ } else if (ha->mpi_fw_dumped && ha->mpi_fw_dump_reading) {
+ rval = memory_read_from_buffer(buf, count, &off,
+ ha->mpi_fw_dump,
+ ha->mpi_fw_dump_len);
} else if (ha->fw_dump_reading) {
rval = memory_read_from_buffer(buf, count, &off, ha->fw_dump,
ha->fw_dump_len);
@@ -79,7 +83,7 @@
qla82xx_md_prep(vha);
}
ha->fw_dump_reading = 0;
- ha->fw_dumped = 0;
+ ha->fw_dumped = false;
break;
case 1:
if (ha->fw_dumped && !ha->fw_dump_reading) {
@@ -102,8 +106,9 @@
qla8044_idc_lock(ha);
qla82xx_set_reset_owner(vha);
qla8044_idc_unlock(ha);
- } else
+ } else {
qla2x00_system_error(vha);
+ }
break;
case 4:
if (IS_P3P_TYPE(ha)) {
@@ -135,6 +140,30 @@
vha->host_no);
}
break;
+ case 8:
+ if (!ha->mpi_fw_dump_reading)
+ break;
+ ql_log(ql_log_info, vha, 0x70e7,
+ "MPI firmware dump cleared on (%ld).\n", vha->host_no);
+ ha->mpi_fw_dump_reading = 0;
+ ha->mpi_fw_dumped = 0;
+ break;
+ case 9:
+ if (ha->mpi_fw_dumped && !ha->mpi_fw_dump_reading) {
+ ha->mpi_fw_dump_reading = 1;
+ ql_log(ql_log_info, vha, 0x70e8,
+ "Raw MPI firmware dump ready for read on (%ld).\n",
+ vha->host_no);
+ }
+ break;
+ case 10:
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ ql_log(ql_log_info, vha, 0x70e9,
+ "Issuing MPI firmware dump on host#%ld.\n",
+ vha->host_no);
+ ha->isp_ops->mpi_fw_dump(vha, 0);
+ }
+ break;
}
return count;
}
@@ -205,10 +234,9 @@
/* Checksum NVRAM. */
if (IS_FWI2_CAPABLE(ha)) {
- uint32_t *iter;
+ __le32 *iter = (__force __le32 *)buf;
uint32_t chksum;
- iter = (uint32_t *)buf;
chksum = 0;
for (cnt = 0; cnt < ((count >> 2) - 1); cnt++, iter++)
chksum += le32_to_cpu(*iter);
@@ -704,7 +732,8 @@
scsi_unblock_requests(vha->host);
break;
case 0x2025d:
- if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha))
+ if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
+ !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return -EPERM;
ql_log(ql_log_info, vha, 0x706f,
@@ -735,6 +764,7 @@
scsi_unblock_requests(vha->host);
break;
}
+ break;
case 0x2025e:
if (!IS_P3P_TYPE(ha) || vha != base_vha) {
ql_log(ql_log_info, vha, 0x7071,
@@ -1322,6 +1352,79 @@
}
static ssize_t
+qla2x00_beacon_config_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ struct qla_hw_data *ha = vha->hw;
+ uint16_t led[3] = { 0 };
+
+ if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+ return -EPERM;
+
+ if (ql26xx_led_config(vha, 0, led))
+ return scnprintf(buf, PAGE_SIZE, "\n");
+
+ return scnprintf(buf, PAGE_SIZE, "%#04hx %#04hx %#04hx\n",
+ led[0], led[1], led[2]);
+}
+
+static ssize_t
+qla2x00_beacon_config_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ struct qla_hw_data *ha = vha->hw;
+ uint16_t options = BIT_0;
+ uint16_t led[3] = { 0 };
+ uint16_t word[4];
+ int n;
+
+ if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+ return -EPERM;
+
+ n = sscanf(buf, "%hx %hx %hx %hx", word+0, word+1, word+2, word+3);
+ if (n == 4) {
+ if (word[0] == 3) {
+ options |= BIT_3|BIT_2|BIT_1;
+ led[0] = word[1];
+ led[1] = word[2];
+ led[2] = word[3];
+ goto write;
+ }
+ return -EINVAL;
+ }
+
+ if (n == 2) {
+ /* check led index */
+ if (word[0] == 0) {
+ options |= BIT_2;
+ led[0] = word[1];
+ goto write;
+ }
+ if (word[0] == 1) {
+ options |= BIT_3;
+ led[1] = word[1];
+ goto write;
+ }
+ if (word[0] == 2) {
+ options |= BIT_1;
+ led[2] = word[1];
+ goto write;
+ }
+ return -EINVAL;
+ }
+
+ return -EINVAL;
+
+write:
+ if (ql26xx_led_config(vha, options, led))
+ return -EFAULT;
+
+ return count;
+}
+
+static ssize_t
qla2x00_optrom_bios_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1759,6 +1862,18 @@
return strlen(buf);
}
+static const struct {
+ u16 rate;
+ char *str;
+} port_speed_str[] = {
+ { PORT_SPEED_4GB, "4" },
+ { PORT_SPEED_8GB, "8" },
+ { PORT_SPEED_16GB, "16" },
+ { PORT_SPEED_32GB, "32" },
+ { PORT_SPEED_64GB, "64" },
+ { PORT_SPEED_10GB, "10" },
+};
+
static ssize_t
qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -1766,7 +1881,8 @@
struct scsi_qla_host *vha = shost_priv(dev_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
ssize_t rval;
- char *spd[7] = {"0", "0", "0", "4", "8", "16", "32"};
+ u16 i;
+ char *speed = "Unknown";
rval = qla2x00_get_data_rate(vha);
if (rval != QLA_SUCCESS) {
@@ -1775,7 +1891,14 @@
return -EINVAL;
}
- return scnprintf(buf, PAGE_SIZE, "%s\n", spd[ha->link_data_rate]);
+ for (i = 0; i < ARRAY_SIZE(port_speed_str); i++) {
+ if (port_speed_str[i].rate != ha->link_data_rate)
+ continue;
+ speed = port_speed_str[i].str;
+ break;
+ }
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n", speed);
}
/* ----- */
@@ -1823,9 +1946,8 @@
};
#define NEED_EXCH_OFFLOAD(_exchg) ((_exchg) > FW_DEF_EXCHANGES_CNT)
-static int qla_set_ini_mode(scsi_qla_host_t *vha, int op)
+static void qla_set_ini_mode(scsi_qla_host_t *vha, int op)
{
- int rc = 0;
enum {
NO_ACTION,
MODE_CHANGE_ACCEPT,
@@ -2098,8 +2220,6 @@
vha->ql2xexchoffld, vha->u_ql2xexchoffld);
break;
}
-
- return rc;
}
static ssize_t
@@ -2245,6 +2365,26 @@
return scnprintf(buf, PAGE_SIZE, "%u\n", vha->hw->port_no);
}
+static ssize_t
+qla2x00_dport_diagnostics_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+
+ if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) &&
+ !IS_QLA28XX(vha->hw))
+ return scnprintf(buf, PAGE_SIZE, "\n");
+
+ if (!*vha->dport_data)
+ return scnprintf(buf, PAGE_SIZE, "\n");
+
+ return scnprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n",
+ vha->dport_data[0], vha->dport_data[1],
+ vha->dport_data[2], vha->dport_data[3]);
+}
+static DEVICE_ATTR(dport_diagnostics, 0444,
+ qla2x00_dport_diagnostics_show, NULL);
+
static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_driver_version_show, NULL);
static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
@@ -2259,6 +2399,8 @@
qla2x00_zio_timer_store);
static DEVICE_ATTR(beacon, S_IRUGO | S_IWUSR, qla2x00_beacon_show,
qla2x00_beacon_store);
+static DEVICE_ATTR(beacon_config, 0644, qla2x00_beacon_config_show,
+ qla2x00_beacon_config_store);
static DEVICE_ATTR(optrom_bios_version, S_IRUGO,
qla2x00_optrom_bios_version_show, NULL);
static DEVICE_ATTR(optrom_efi_version, S_IRUGO,
@@ -2322,6 +2464,7 @@
&dev_attr_zio,
&dev_attr_zio_timer,
&dev_attr_beacon,
+ &dev_attr_beacon_config,
&dev_attr_optrom_bios_version,
&dev_attr_optrom_efi_version,
&dev_attr_optrom_fcode_version,
@@ -2350,6 +2493,7 @@
&dev_attr_port_speed,
&dev_attr_port_no,
&dev_attr_fw_attr,
+ &dev_attr_dport_diagnostics,
NULL, /* reserve for qlini_mode */
NULL, /* reserve for ql2xiniexchg */
NULL, /* reserve for ql2xexchoffld */
@@ -2607,6 +2751,9 @@
struct link_statistics *stats;
dma_addr_t stats_dma;
struct fc_host_statistics *p = &vha->fc_host_stat;
+ struct qla_qpair *qpair;
+ int i;
+ u64 ib = 0, ob = 0, ir = 0, or = 0;
memset(p, -1, sizeof(*p));
@@ -2643,30 +2790,58 @@
if (rval != QLA_SUCCESS)
goto done_free;
- p->link_failure_count = stats->link_fail_cnt;
- p->loss_of_sync_count = stats->loss_sync_cnt;
- p->loss_of_signal_count = stats->loss_sig_cnt;
- p->prim_seq_protocol_err_count = stats->prim_seq_err_cnt;
- p->invalid_tx_word_count = stats->inval_xmit_word_cnt;
- p->invalid_crc_count = stats->inval_crc_cnt;
- if (IS_FWI2_CAPABLE(ha)) {
- p->lip_count = stats->lip_cnt;
- p->tx_frames = stats->tx_frames;
- p->rx_frames = stats->rx_frames;
- p->dumped_frames = stats->discarded_frames;
- p->nos_count = stats->nos_rcvd;
- p->error_frames =
- stats->dropped_frames + stats->discarded_frames;
- p->rx_words = vha->qla_stats.input_bytes;
- p->tx_words = vha->qla_stats.output_bytes;
+ /* --- */
+ for (i = 0; i < vha->hw->max_qpairs; i++) {
+ qpair = vha->hw->queue_pair_map[i];
+ if (!qpair)
+ continue;
+ ir += qpair->counters.input_requests;
+ or += qpair->counters.output_requests;
+ ib += qpair->counters.input_bytes;
+ ob += qpair->counters.output_bytes;
}
+ ir += ha->base_qpair->counters.input_requests;
+ or += ha->base_qpair->counters.output_requests;
+ ib += ha->base_qpair->counters.input_bytes;
+ ob += ha->base_qpair->counters.output_bytes;
+
+ ir += vha->qla_stats.input_requests;
+ or += vha->qla_stats.output_requests;
+ ib += vha->qla_stats.input_bytes;
+ ob += vha->qla_stats.output_bytes;
+ /* --- */
+
+ p->link_failure_count = le32_to_cpu(stats->link_fail_cnt);
+ p->loss_of_sync_count = le32_to_cpu(stats->loss_sync_cnt);
+ p->loss_of_signal_count = le32_to_cpu(stats->loss_sig_cnt);
+ p->prim_seq_protocol_err_count = le32_to_cpu(stats->prim_seq_err_cnt);
+ p->invalid_tx_word_count = le32_to_cpu(stats->inval_xmit_word_cnt);
+ p->invalid_crc_count = le32_to_cpu(stats->inval_crc_cnt);
+ if (IS_FWI2_CAPABLE(ha)) {
+ p->lip_count = le32_to_cpu(stats->lip_cnt);
+ p->tx_frames = le32_to_cpu(stats->tx_frames);
+ p->rx_frames = le32_to_cpu(stats->rx_frames);
+ p->dumped_frames = le32_to_cpu(stats->discarded_frames);
+ p->nos_count = le32_to_cpu(stats->nos_rcvd);
+ p->error_frames =
+ le32_to_cpu(stats->dropped_frames) +
+ le32_to_cpu(stats->discarded_frames);
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ p->rx_words = le64_to_cpu(stats->fpm_recv_word_cnt);
+ p->tx_words = le64_to_cpu(stats->fpm_xmit_word_cnt);
+ } else {
+ p->rx_words = ib >> 2;
+ p->tx_words = ob >> 2;
+ }
+ }
+
p->fcp_control_requests = vha->qla_stats.control_requests;
- p->fcp_input_requests = vha->qla_stats.input_requests;
- p->fcp_output_requests = vha->qla_stats.output_requests;
- p->fcp_input_megabytes = vha->qla_stats.input_bytes >> 20;
- p->fcp_output_megabytes = vha->qla_stats.output_bytes >> 20;
+ p->fcp_input_requests = ir;
+ p->fcp_output_requests = or;
+ p->fcp_input_megabytes = ib >> 20;
+ p->fcp_output_megabytes = ob >> 20;
p->seconds_since_last_reset =
- get_jiffies_64() - vha->qla_stats.jiffies_at_last_reset;
+ get_jiffies_64() - vha->qla_stats.jiffies_at_last_reset;
do_div(p->seconds_since_last_reset, HZ);
done_free:
@@ -2684,9 +2859,18 @@
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
struct link_statistics *stats;
dma_addr_t stats_dma;
+ int i;
+ struct qla_qpair *qpair;
memset(&vha->qla_stats, 0, sizeof(vha->qla_stats));
memset(&vha->fc_host_stat, 0, sizeof(vha->fc_host_stat));
+ for (i = 0; i < vha->hw->max_qpairs; i++) {
+ qpair = vha->hw->queue_pair_map[i];
+ if (!qpair)
+ continue;
+ memset(&qpair->counters, 0, sizeof(qpair->counters));
+ }
+ memset(&ha->base_qpair->counters, 0, sizeof(qpair->counters));
vha->qla_stats.jiffies_at_last_reset = get_jiffies_64();
@@ -3095,46 +3279,7 @@
fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports;
fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count;
- if (IS_CNA_CAPABLE(ha))
- speeds = FC_PORTSPEED_10GBIT;
- else if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) {
- if (ha->max_supported_speed == 2) {
- if (ha->min_supported_speed <= 6)
- speeds |= FC_PORTSPEED_64GBIT;
- }
- if (ha->max_supported_speed == 2 ||
- ha->max_supported_speed == 1) {
- if (ha->min_supported_speed <= 5)
- speeds |= FC_PORTSPEED_32GBIT;
- }
- if (ha->max_supported_speed == 2 ||
- ha->max_supported_speed == 1 ||
- ha->max_supported_speed == 0) {
- if (ha->min_supported_speed <= 4)
- speeds |= FC_PORTSPEED_16GBIT;
- }
- if (ha->max_supported_speed == 1 ||
- ha->max_supported_speed == 0) {
- if (ha->min_supported_speed <= 3)
- speeds |= FC_PORTSPEED_8GBIT;
- }
- if (ha->max_supported_speed == 0) {
- if (ha->min_supported_speed <= 2)
- speeds |= FC_PORTSPEED_4GBIT;
- }
- } else if (IS_QLA2031(ha))
- speeds = FC_PORTSPEED_16GBIT|FC_PORTSPEED_8GBIT|
- FC_PORTSPEED_4GBIT;
- else if (IS_QLA25XX(ha) || IS_QLAFX00(ha))
- speeds = FC_PORTSPEED_8GBIT|FC_PORTSPEED_4GBIT|
- FC_PORTSPEED_2GBIT|FC_PORTSPEED_1GBIT;
- else if (IS_QLA24XX_TYPE(ha))
- speeds = FC_PORTSPEED_4GBIT|FC_PORTSPEED_2GBIT|
- FC_PORTSPEED_1GBIT;
- else if (IS_QLA23XX(ha))
- speeds = FC_PORTSPEED_2GBIT|FC_PORTSPEED_1GBIT;
- else
- speeds = FC_PORTSPEED_1GBIT;
+ speeds = qla25xx_fdmi_port_speed_capability(ha);
fc_host_supported_speeds(vha->host) = speeds;
}
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index ce55121..1fd292a 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
@@ -11,6 +10,14 @@
#include <linux/delay.h>
#include <linux/bsg-lib.h>
+static void qla2xxx_free_fcport_work(struct work_struct *work)
+{
+ struct fc_port *fcport = container_of(work, typeof(*fcport),
+ free_work);
+
+ qla2x00_free_fcport(fcport);
+}
+
/* BSG support for ELS/CT pass through */
void qla2x00_bsg_job_done(srb_t *sp, int res)
{
@@ -54,8 +61,11 @@
if (sp->type == SRB_CT_CMD ||
sp->type == SRB_FXIOCB_BCMD ||
- sp->type == SRB_ELS_CMD_HST)
- kfree(sp->fcport);
+ sp->type == SRB_ELS_CMD_HST) {
+ INIT_WORK(&sp->fcport->free_work, qla2xxx_free_fcport_work);
+ queue_work(ha->wq, &sp->fcport->free_work);
+ }
+
qla2x00_rel_sp(sp);
}
@@ -213,8 +223,7 @@
/* validate fcp priority data */
- if (!qla24xx_fcp_prio_cfg_valid(vha,
- (struct qla_fcp_prio_cfg *) ha->fcp_prio_cfg, 1)) {
+ if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 1)) {
bsg_reply->result = (DID_ERROR << 16);
ret = -EINVAL;
/* If buffer was invalidatic int
@@ -405,8 +414,8 @@
goto done_free_fcport;
done_free_fcport:
- if (bsg_request->msgcode == FC_BSG_RPT_ELS)
- kfree(fcport);
+ if (bsg_request->msgcode != FC_BSG_RPT_ELS)
+ qla2x00_free_fcport(fcport);
done:
return rval;
}
@@ -480,7 +489,7 @@
>> 24;
switch (loop_id) {
case 0xFC:
- loop_id = cpu_to_le16(NPH_SNS);
+ loop_id = NPH_SNS;
break;
case 0xFA:
loop_id = vha->mgmt_svr_loop_id;
@@ -546,7 +555,7 @@
return rval;
done_free_fcport:
- kfree(fcport);
+ qla2x00_free_fcport(fcport);
done_unmap_sg:
dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
@@ -681,7 +690,7 @@
* dump and reset the chip.
*/
if (ret) {
- ha->isp_ops->fw_dump(vha, 0);
+ qla2xxx_dump_fw(vha);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
}
rval = -EINVAL;
@@ -718,7 +727,7 @@
uint16_t response[MAILBOX_REGISTER_COUNT];
uint16_t config[4], new_config[4];
uint8_t *fw_sts_ptr;
- uint8_t *req_data = NULL;
+ void *req_data = NULL;
dma_addr_t req_data_dma;
uint32_t req_data_len;
uint8_t *rsp_data = NULL;
@@ -796,10 +805,11 @@
bsg_request->rqst_data.h_vendor.vendor_cmd[2];
if (atomic_read(&vha->loop_state) == LOOP_READY &&
- (ha->current_topology == ISP_CFG_F ||
- (le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE &&
- req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
- elreq.options == EXTERNAL_LOOPBACK) {
+ ((ha->current_topology == ISP_CFG_F && (elreq.options & 7) >= 2) ||
+ ((IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) &&
+ get_unaligned_le32(req_data) == ELS_OPCODE_BYTE &&
+ req_data_len == MAX_ELS_FRAME_PAYLOAD &&
+ elreq.options == EXTERNAL_LOOPBACK))) {
type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
ql_dbg(ql_dbg_user, vha, 0x701e,
"BSG request type: %s.\n", type);
@@ -885,7 +895,7 @@
* doesn't work take FCoE dump and then
* reset the chip.
*/
- ha->isp_ops->fw_dump(vha, 0);
+ qla2xxx_dump_fw(vha);
set_bit(ISP_ABORT_NEEDED,
&vha->dpc_flags);
}
@@ -1506,10 +1516,15 @@
bsg_job->request_payload.sg_cnt, ha->optrom_buffer,
ha->optrom_region_size);
- ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
+ rval = ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
ha->optrom_region_start, ha->optrom_region_size);
- bsg_reply->result = DID_OK;
+ if (rval) {
+ bsg_reply->result = -EINVAL;
+ rval = -EINVAL;
+ } else {
+ bsg_reply->result = DID_OK;
+ }
vfree(ha->optrom_buffer);
ha->optrom_buffer = NULL;
ha->optrom_state = QLA_SWAITING;
@@ -2026,7 +2041,7 @@
/* Initialize all required fields of fcport */
fcport->vha = vha;
- fcport->loop_id = piocb_rqst->dataword;
+ fcport->loop_id = le32_to_cpu(piocb_rqst->dataword);
sp->type = SRB_FXIOCB_BCMD;
sp->name = "bsg_fx_mgmt";
@@ -2050,7 +2065,7 @@
return rval;
done_free_fcport:
- kfree(fcport);
+ qla2x00_free_fcport(fcport);
done_unmap_rsp_sg:
if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID)
@@ -2404,7 +2419,7 @@
regions.global_image = active_regions.global;
if (IS_QLA28XX(ha)) {
- qla27xx_get_active_image(vha, &active_regions);
+ qla28xx_get_aux_images(vha, &active_regions);
regions.board_config = active_regions.aux.board_config;
regions.vpd_nvram = active_regions.aux.vpd_nvram;
regions.npiv_config_0_1 = active_regions.aux.npiv_config_0_1;
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index 7594fad..1a09b55 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#ifndef __QLA_BSG_H
#define __QLA_BSG_H
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 88a56e8..00b4d03 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
/*
@@ -11,14 +10,11 @@
* ----------------------------------------------------------------------
* | Level | Last Value Used | Holes |
* ----------------------------------------------------------------------
- * | Module Init and Probe | 0x0193 | 0x0146 |
- * | | | 0x015b-0x0160 |
- * | | | 0x016e |
- * | Mailbox commands | 0x1206 | 0x11a2-0x11ff |
- * | Device Discovery | 0x2134 | 0x210e-0x2116 |
- * | | | 0x211a |
+ * | Module Init and Probe | 0x0199 | |
+ * | Mailbox commands | 0x1206 | 0x11a5-0x11ff |
+ * | Device Discovery | 0x2134 | 0x210e-0x2115 |
* | | | 0x211c-0x2128 |
- * | | | 0x212a-0x2134 |
+ * | | | 0x212c-0x2134 |
* | Queue Command and IO tracing | 0x3074 | 0x300b |
* | | | 0x3027-0x3028 |
* | | | 0x303d-0x3041 |
@@ -26,11 +22,7 @@
* | | | 0x3036,0x3038 |
* | | | 0x303a |
* | DPC Thread | 0x4023 | 0x4002,0x4013 |
- * | Async Events | 0x5090 | 0x502b-0x502f |
- * | | | 0x5047 |
- * | | | 0x5084,0x5075 |
- * | | | 0x503d,0x5044 |
- * | | | 0x505f |
+ * | Async Events | 0x509c | |
* | Timer Routines | 0x6012 | |
* | User Space Interactions | 0x70e3 | 0x7018,0x702e |
* | | | 0x7020,0x7024 |
@@ -73,6 +65,8 @@
#include "qla_def.h"
#include <linux/delay.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/qla.h>
static uint32_t ql_dbg_offset = 0x800;
@@ -113,7 +107,7 @@
{
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
dma_addr_t dump_dma = ha->gid_list_dma;
- uint32_t *chunk = (void *)ha->gid_list;
+ uint32_t *chunk = (uint32_t *)ha->gid_list;
uint32_t dwords = qla2x00_gid_list_size(ha) / 4;
uint32_t stat;
ulong i, j, timer = 6000000;
@@ -124,26 +118,26 @@
if (i + dwords > ram_dwords)
dwords = ram_dwords - i;
- WRT_REG_WORD(®->mailbox0, MBC_LOAD_DUMP_MPI_RAM);
- WRT_REG_WORD(®->mailbox1, LSW(addr));
- WRT_REG_WORD(®->mailbox8, MSW(addr));
+ wrt_reg_word(®->mailbox0, MBC_LOAD_DUMP_MPI_RAM);
+ wrt_reg_word(®->mailbox1, LSW(addr));
+ wrt_reg_word(®->mailbox8, MSW(addr));
- WRT_REG_WORD(®->mailbox2, MSW(LSD(dump_dma)));
- WRT_REG_WORD(®->mailbox3, LSW(LSD(dump_dma)));
- WRT_REG_WORD(®->mailbox6, MSW(MSD(dump_dma)));
- WRT_REG_WORD(®->mailbox7, LSW(MSD(dump_dma)));
+ wrt_reg_word(®->mailbox2, MSW(LSD(dump_dma)));
+ wrt_reg_word(®->mailbox3, LSW(LSD(dump_dma)));
+ wrt_reg_word(®->mailbox6, MSW(MSD(dump_dma)));
+ wrt_reg_word(®->mailbox7, LSW(MSD(dump_dma)));
- WRT_REG_WORD(®->mailbox4, MSW(dwords));
- WRT_REG_WORD(®->mailbox5, LSW(dwords));
+ wrt_reg_word(®->mailbox4, MSW(dwords));
+ wrt_reg_word(®->mailbox5, LSW(dwords));
- WRT_REG_WORD(®->mailbox9, 0);
- WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT);
+ wrt_reg_word(®->mailbox9, 0);
+ wrt_reg_dword(®->hccr, HCCRX_SET_HOST_INT);
ha->flags.mbox_int = 0;
while (timer--) {
udelay(5);
- stat = RD_REG_DWORD(®->host_status);
+ stat = rd_reg_dword(®->host_status);
/* Check for pending interrupts. */
if (!(stat & HSRX_RISC_INT))
continue;
@@ -153,15 +147,15 @@
stat != 0x10 && stat != 0x11) {
/* Clear this intr; it wasn't a mailbox intr */
- WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT);
- RD_REG_DWORD(®->hccr);
+ wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT);
+ rd_reg_dword(®->hccr);
continue;
}
set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
- rval = RD_REG_WORD(®->mailbox0) & MBS_MASK;
- WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT);
- RD_REG_DWORD(®->hccr);
+ rval = rd_reg_word(®->mailbox0) & MBS_MASK;
+ wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT);
+ rd_reg_dword(®->hccr);
break;
}
ha->flags.mbox_int = 1;
@@ -187,13 +181,13 @@
}
int
-qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram,
- uint32_t ram_dwords, void **nxt)
+qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, __be32 *ram,
+ uint32_t ram_dwords, void **nxt)
{
int rval = QLA_FUNCTION_FAILED;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
dma_addr_t dump_dma = ha->gid_list_dma;
- uint32_t *chunk = (void *)ha->gid_list;
+ uint32_t *chunk = (uint32_t *)ha->gid_list;
uint32_t dwords = qla2x00_gid_list_size(ha) / 4;
uint32_t stat;
ulong i, j, timer = 6000000;
@@ -204,23 +198,24 @@
if (i + dwords > ram_dwords)
dwords = ram_dwords - i;
- WRT_REG_WORD(®->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED);
- WRT_REG_WORD(®->mailbox1, LSW(addr));
- WRT_REG_WORD(®->mailbox8, MSW(addr));
+ wrt_reg_word(®->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED);
+ wrt_reg_word(®->mailbox1, LSW(addr));
+ wrt_reg_word(®->mailbox8, MSW(addr));
+ wrt_reg_word(®->mailbox10, 0);
- WRT_REG_WORD(®->mailbox2, MSW(LSD(dump_dma)));
- WRT_REG_WORD(®->mailbox3, LSW(LSD(dump_dma)));
- WRT_REG_WORD(®->mailbox6, MSW(MSD(dump_dma)));
- WRT_REG_WORD(®->mailbox7, LSW(MSD(dump_dma)));
+ wrt_reg_word(®->mailbox2, MSW(LSD(dump_dma)));
+ wrt_reg_word(®->mailbox3, LSW(LSD(dump_dma)));
+ wrt_reg_word(®->mailbox6, MSW(MSD(dump_dma)));
+ wrt_reg_word(®->mailbox7, LSW(MSD(dump_dma)));
- WRT_REG_WORD(®->mailbox4, MSW(dwords));
- WRT_REG_WORD(®->mailbox5, LSW(dwords));
- WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT);
+ wrt_reg_word(®->mailbox4, MSW(dwords));
+ wrt_reg_word(®->mailbox5, LSW(dwords));
+ wrt_reg_dword(®->hccr, HCCRX_SET_HOST_INT);
ha->flags.mbox_int = 0;
while (timer--) {
udelay(5);
- stat = RD_REG_DWORD(®->host_status);
+ stat = rd_reg_dword(®->host_status);
/* Check for pending interrupts. */
if (!(stat & HSRX_RISC_INT))
@@ -229,15 +224,15 @@
stat &= 0xff;
if (stat != 0x1 && stat != 0x2 &&
stat != 0x10 && stat != 0x11) {
- WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT);
- RD_REG_DWORD(®->hccr);
+ wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT);
+ rd_reg_dword(®->hccr);
continue;
}
set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
- rval = RD_REG_WORD(®->mailbox0) & MBS_MASK;
- WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT);
- RD_REG_DWORD(®->hccr);
+ rval = rd_reg_word(®->mailbox0) & MBS_MASK;
+ wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT);
+ rd_reg_dword(®->hccr);
break;
}
ha->flags.mbox_int = 1;
@@ -252,9 +247,9 @@
return rval;
}
for (j = 0; j < dwords; j++) {
- ram[i + j] =
- (IS_QLA27XX(ha) || IS_QLA28XX(ha)) ?
- chunk[j] : swab32(chunk[j]);
+ ram[i + j] = (__force __be32)
+ ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) ?
+ chunk[j] : swab32(chunk[j]));
}
}
@@ -263,8 +258,8 @@
}
static int
-qla24xx_dump_memory(struct qla_hw_data *ha, uint32_t *code_ram,
- uint32_t cram_size, void **nxt)
+qla24xx_dump_memory(struct qla_hw_data *ha, __be32 *code_ram,
+ uint32_t cram_size, void **nxt)
{
int rval;
@@ -284,16 +279,16 @@
return rval;
}
-static uint32_t *
+static __be32 *
qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase,
- uint32_t count, uint32_t *buf)
+ uint32_t count, __be32 *buf)
{
- uint32_t __iomem *dmp_reg;
+ __le32 __iomem *dmp_reg;
- WRT_REG_DWORD(®->iobase_addr, iobase);
+ wrt_reg_dword(®->iobase_addr, iobase);
dmp_reg = ®->iobase_window;
for ( ; count--; dmp_reg++)
- *buf++ = htonl(RD_REG_DWORD(dmp_reg));
+ *buf++ = htonl(rd_reg_dword(dmp_reg));
return buf;
}
@@ -301,11 +296,11 @@
void
qla24xx_pause_risc(struct device_reg_24xx __iomem *reg, struct qla_hw_data *ha)
{
- WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE);
+ wrt_reg_dword(®->hccr, HCCRX_SET_RISC_PAUSE);
/* 100 usec delay is sufficient enough for hardware to pause RISC */
udelay(100);
- if (RD_REG_DWORD(®->host_status) & HSRX_RISC_PAUSED)
+ if (rd_reg_dword(®->host_status) & HSRX_RISC_PAUSED)
set_bit(RISC_PAUSE_CMPL, &ha->fw_dump_cap_flags);
}
@@ -322,17 +317,17 @@
* Driver can proceed with the reset sequence after waiting
* for a timeout period.
*/
- WRT_REG_DWORD(®->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
+ wrt_reg_dword(®->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
for (cnt = 0; cnt < 30000; cnt++) {
- if ((RD_REG_DWORD(®->ctrl_status) & CSRX_DMA_ACTIVE) == 0)
+ if ((rd_reg_dword(®->ctrl_status) & CSRX_DMA_ACTIVE) == 0)
break;
udelay(10);
}
- if (!(RD_REG_DWORD(®->ctrl_status) & CSRX_DMA_ACTIVE))
+ if (!(rd_reg_dword(®->ctrl_status) & CSRX_DMA_ACTIVE))
set_bit(DMA_SHUTDOWN_CMPL, &ha->fw_dump_cap_flags);
- WRT_REG_DWORD(®->ctrl_status,
+ wrt_reg_dword(®->ctrl_status,
CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
@@ -340,19 +335,19 @@
/* Wait for soft-reset to complete. */
for (cnt = 0; cnt < 30000; cnt++) {
- if ((RD_REG_DWORD(®->ctrl_status) &
+ if ((rd_reg_dword(®->ctrl_status) &
CSRX_ISP_SOFT_RESET) == 0)
break;
udelay(10);
}
- if (!(RD_REG_DWORD(®->ctrl_status) & CSRX_ISP_SOFT_RESET))
+ if (!(rd_reg_dword(®->ctrl_status) & CSRX_ISP_SOFT_RESET))
set_bit(ISP_RESET_CMPL, &ha->fw_dump_cap_flags);
- WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_RESET);
- RD_REG_DWORD(®->hccr); /* PCI Posting. */
+ wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_RESET);
+ rd_reg_dword(®->hccr); /* PCI Posting. */
- for (cnt = 10000; RD_REG_WORD(®->mailbox0) != 0 &&
+ for (cnt = 10000; rd_reg_word(®->mailbox0) != 0 &&
rval == QLA_SUCCESS; cnt--) {
if (cnt)
udelay(10);
@@ -366,7 +361,7 @@
}
static int
-qla2xxx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint16_t *ram,
+qla2xxx_dump_ram(struct qla_hw_data *ha, uint32_t addr, __be16 *ram,
uint32_t ram_words, void **nxt)
{
int rval;
@@ -374,7 +369,7 @@
uint16_t mb0;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
dma_addr_t dump_dma = ha->gid_list_dma;
- uint16_t *dump = (uint16_t *)ha->gid_list;
+ __le16 *dump = (__force __le16 *)ha->gid_list;
rval = QLA_SUCCESS;
mb0 = 0;
@@ -397,11 +392,11 @@
WRT_MAILBOX_REG(ha, reg, 7, LSW(MSD(dump_dma)));
WRT_MAILBOX_REG(ha, reg, 4, words);
- WRT_REG_WORD(®->hccr, HCCR_SET_HOST_INT);
+ wrt_reg_word(®->hccr, HCCR_SET_HOST_INT);
for (timer = 6000000; timer; timer--) {
/* Check for pending interrupts. */
- stat = RD_REG_DWORD(®->u.isp2300.host_status);
+ stat = rd_reg_dword(®->u.isp2300.host_status);
if (stat & HSR_RISC_INT) {
stat &= 0xff;
@@ -412,10 +407,10 @@
mb0 = RD_MAILBOX_REG(ha, reg, 0);
/* Release mailbox registers. */
- WRT_REG_WORD(®->semaphore, 0);
- WRT_REG_WORD(®->hccr,
+ wrt_reg_word(®->semaphore, 0);
+ wrt_reg_word(®->hccr,
HCCR_CLR_RISC_INT);
- RD_REG_WORD(®->hccr);
+ rd_reg_word(®->hccr);
break;
} else if (stat == 0x10 || stat == 0x11) {
set_bit(MBX_INTERRUPT,
@@ -423,15 +418,15 @@
mb0 = RD_MAILBOX_REG(ha, reg, 0);
- WRT_REG_WORD(®->hccr,
+ wrt_reg_word(®->hccr,
HCCR_CLR_RISC_INT);
- RD_REG_WORD(®->hccr);
+ rd_reg_word(®->hccr);
break;
}
/* clear this intr; it wasn't a mailbox intr */
- WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT);
- RD_REG_WORD(®->hccr);
+ wrt_reg_word(®->hccr, HCCR_CLR_RISC_INT);
+ rd_reg_word(®->hccr);
}
udelay(5);
}
@@ -439,7 +434,8 @@
if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
rval = mb0 & MBS_MASK;
for (idx = 0; idx < words; idx++)
- ram[cnt + idx] = swab16(dump[idx]);
+ ram[cnt + idx] =
+ cpu_to_be16(le16_to_cpu(dump[idx]));
} else {
rval = QLA_FUNCTION_FAILED;
}
@@ -451,12 +447,12 @@
static inline void
qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count,
- uint16_t *buf)
+ __be16 *buf)
{
- uint16_t __iomem *dmp_reg = ®->u.isp2300.fb_cmd;
+ __le16 __iomem *dmp_reg = ®->u.isp2300.fb_cmd;
for ( ; count--; dmp_reg++)
- *buf++ = htons(RD_REG_WORD(dmp_reg));
+ *buf++ = htons(rd_reg_word(dmp_reg));
}
static inline void *
@@ -470,10 +466,10 @@
}
static inline void *
-qla25xx_copy_fce(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
+qla25xx_copy_fce(struct qla_hw_data *ha, void *ptr, __be32 **last_chain)
{
uint32_t cnt;
- uint32_t *iter_reg;
+ __be32 *iter_reg;
struct qla2xxx_fce_chain *fcec = ptr;
if (!ha->fce)
@@ -497,7 +493,7 @@
}
static inline void *
-qla25xx_copy_exlogin(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
+qla25xx_copy_exlogin(struct qla_hw_data *ha, void *ptr, __be32 **last_chain)
{
struct qla2xxx_offld_chain *c = ptr;
@@ -515,11 +511,11 @@
ptr += sizeof(struct qla2xxx_offld_chain);
memcpy(ptr, ha->exlogin_buf, ha->exlogin_size);
- return (char *)ptr + cpu_to_be32(c->size);
+ return (char *)ptr + be32_to_cpu(c->size);
}
static inline void *
-qla81xx_copy_exchoffld(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
+qla81xx_copy_exchoffld(struct qla_hw_data *ha, void *ptr, __be32 **last_chain)
{
struct qla2xxx_offld_chain *c = ptr;
@@ -537,12 +533,12 @@
ptr += sizeof(struct qla2xxx_offld_chain);
memcpy(ptr, ha->exchoffld_buf, ha->exchoffld_size);
- return (char *)ptr + cpu_to_be32(c->size);
+ return (char *)ptr + be32_to_cpu(c->size);
}
static inline void *
qla2xxx_copy_atioqueues(struct qla_hw_data *ha, void *ptr,
- uint32_t **last_chain)
+ __be32 **last_chain)
{
struct qla2xxx_mqueue_chain *q;
struct qla2xxx_mqueue_header *qh;
@@ -589,7 +585,7 @@
}
static inline void *
-qla25xx_copy_mqueues(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
+qla25xx_copy_mqueues(struct qla_hw_data *ha, void *ptr, __be32 **last_chain)
{
struct qla2xxx_mqueue_chain *q;
struct qla2xxx_mqueue_header *qh;
@@ -660,7 +656,7 @@
}
static inline void *
-qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
+qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, __be32 **last_chain)
{
uint32_t cnt, que_idx;
uint8_t que_cnt;
@@ -683,13 +679,13 @@
reg = ISP_QUE_REG(ha, cnt);
que_idx = cnt * 4;
mq->qregs[que_idx] =
- htonl(RD_REG_DWORD(®->isp25mq.req_q_in));
+ htonl(rd_reg_dword(®->isp25mq.req_q_in));
mq->qregs[que_idx+1] =
- htonl(RD_REG_DWORD(®->isp25mq.req_q_out));
+ htonl(rd_reg_dword(®->isp25mq.req_q_out));
mq->qregs[que_idx+2] =
- htonl(RD_REG_DWORD(®->isp25mq.rsp_q_in));
+ htonl(rd_reg_dword(®->isp25mq.rsp_q_in));
mq->qregs[que_idx+3] =
- htonl(RD_REG_DWORD(®->isp25mq.rsp_q_out));
+ htonl(rd_reg_dword(®->isp25mq.rsp_q_out));
}
return ptr + sizeof(struct qla2xxx_mq_chain);
@@ -704,45 +700,47 @@
ql_log(ql_log_warn, vha, 0xd000,
"Failed to dump firmware (%x), dump status flags (0x%lx).\n",
rval, ha->fw_dump_cap_flags);
- ha->fw_dumped = 0;
+ ha->fw_dumped = false;
} else {
ql_log(ql_log_info, vha, 0xd001,
"Firmware dump saved to temp buffer (%ld/%p), dump status flags (0x%lx).\n",
vha->host_no, ha->fw_dump, ha->fw_dump_cap_flags);
- ha->fw_dumped = 1;
+ ha->fw_dumped = true;
qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP);
}
}
+void qla2xxx_dump_fw(scsi_qla_host_t *vha)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&vha->hw->hardware_lock, flags);
+ vha->hw->isp_ops->fw_dump(vha);
+ spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
+}
+
/**
* qla2300_fw_dump() - Dumps binary data from the 2300 firmware.
* @vha: HA context
- * @hardware_locked: Called with the hardware_lock
*/
void
-qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
+qla2300_fw_dump(scsi_qla_host_t *vha)
{
int rval;
uint32_t cnt;
struct qla_hw_data *ha = vha->hw;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
- uint16_t __iomem *dmp_reg;
- unsigned long flags;
+ __le16 __iomem *dmp_reg;
struct qla2300_fw_dump *fw;
void *nxt;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
- flags = 0;
-
-#ifndef __CHECKER__
- if (!hardware_locked)
- spin_lock_irqsave(&ha->hardware_lock, flags);
-#endif
+ lockdep_assert_held(&ha->hardware_lock);
if (!ha->fw_dump) {
ql_log(ql_log_warn, vha, 0xd002,
"No buffer available for dump.\n");
- goto qla2300_fw_dump_failed;
+ return;
}
if (ha->fw_dumped) {
@@ -750,19 +748,19 @@
"Firmware has been previously dumped (%p) "
"-- ignoring request.\n",
ha->fw_dump);
- goto qla2300_fw_dump_failed;
+ return;
}
fw = &ha->fw_dump->isp.isp23;
qla2xxx_prep_dump(ha, ha->fw_dump);
rval = QLA_SUCCESS;
- fw->hccr = htons(RD_REG_WORD(®->hccr));
+ fw->hccr = htons(rd_reg_word(®->hccr));
/* Pause RISC. */
- WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC);
+ wrt_reg_word(®->hccr, HCCR_PAUSE_RISC);
if (IS_QLA2300(ha)) {
for (cnt = 30000;
- (RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) == 0 &&
+ (rd_reg_word(®->hccr) & HCCR_RISC_PAUSE) == 0 &&
rval == QLA_SUCCESS; cnt--) {
if (cnt)
udelay(100);
@@ -770,74 +768,74 @@
rval = QLA_FUNCTION_TIMEOUT;
}
} else {
- RD_REG_WORD(®->hccr); /* PCI Posting. */
+ rd_reg_word(®->hccr); /* PCI Posting. */
udelay(10);
}
if (rval == QLA_SUCCESS) {
dmp_reg = ®->flash_address;
- for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++, dmp_reg++)
- fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->pbiu_reg); cnt++, dmp_reg++)
+ fw->pbiu_reg[cnt] = htons(rd_reg_word(dmp_reg));
dmp_reg = ®->u.isp2300.req_q_in;
- for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2;
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->risc_host_reg);
cnt++, dmp_reg++)
- fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
+ fw->risc_host_reg[cnt] = htons(rd_reg_word(dmp_reg));
dmp_reg = ®->u.isp2300.mailbox0;
- for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2;
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->mailbox_reg);
cnt++, dmp_reg++)
- fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
+ fw->mailbox_reg[cnt] = htons(rd_reg_word(dmp_reg));
- WRT_REG_WORD(®->ctrl_status, 0x40);
+ wrt_reg_word(®->ctrl_status, 0x40);
qla2xxx_read_window(reg, 32, fw->resp_dma_reg);
- WRT_REG_WORD(®->ctrl_status, 0x50);
+ wrt_reg_word(®->ctrl_status, 0x50);
qla2xxx_read_window(reg, 48, fw->dma_reg);
- WRT_REG_WORD(®->ctrl_status, 0x00);
+ wrt_reg_word(®->ctrl_status, 0x00);
dmp_reg = ®->risc_hw;
- for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2;
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->risc_hdw_reg);
cnt++, dmp_reg++)
- fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
+ fw->risc_hdw_reg[cnt] = htons(rd_reg_word(dmp_reg));
- WRT_REG_WORD(®->pcr, 0x2000);
+ wrt_reg_word(®->pcr, 0x2000);
qla2xxx_read_window(reg, 16, fw->risc_gp0_reg);
- WRT_REG_WORD(®->pcr, 0x2200);
+ wrt_reg_word(®->pcr, 0x2200);
qla2xxx_read_window(reg, 16, fw->risc_gp1_reg);
- WRT_REG_WORD(®->pcr, 0x2400);
+ wrt_reg_word(®->pcr, 0x2400);
qla2xxx_read_window(reg, 16, fw->risc_gp2_reg);
- WRT_REG_WORD(®->pcr, 0x2600);
+ wrt_reg_word(®->pcr, 0x2600);
qla2xxx_read_window(reg, 16, fw->risc_gp3_reg);
- WRT_REG_WORD(®->pcr, 0x2800);
+ wrt_reg_word(®->pcr, 0x2800);
qla2xxx_read_window(reg, 16, fw->risc_gp4_reg);
- WRT_REG_WORD(®->pcr, 0x2A00);
+ wrt_reg_word(®->pcr, 0x2A00);
qla2xxx_read_window(reg, 16, fw->risc_gp5_reg);
- WRT_REG_WORD(®->pcr, 0x2C00);
+ wrt_reg_word(®->pcr, 0x2C00);
qla2xxx_read_window(reg, 16, fw->risc_gp6_reg);
- WRT_REG_WORD(®->pcr, 0x2E00);
+ wrt_reg_word(®->pcr, 0x2E00);
qla2xxx_read_window(reg, 16, fw->risc_gp7_reg);
- WRT_REG_WORD(®->ctrl_status, 0x10);
+ wrt_reg_word(®->ctrl_status, 0x10);
qla2xxx_read_window(reg, 64, fw->frame_buf_hdw_reg);
- WRT_REG_WORD(®->ctrl_status, 0x20);
+ wrt_reg_word(®->ctrl_status, 0x20);
qla2xxx_read_window(reg, 64, fw->fpm_b0_reg);
- WRT_REG_WORD(®->ctrl_status, 0x30);
+ wrt_reg_word(®->ctrl_status, 0x30);
qla2xxx_read_window(reg, 64, fw->fpm_b1_reg);
/* Reset RISC. */
- WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET);
+ wrt_reg_word(®->ctrl_status, CSR_ISP_SOFT_RESET);
for (cnt = 0; cnt < 30000; cnt++) {
- if ((RD_REG_WORD(®->ctrl_status) &
+ if ((rd_reg_word(®->ctrl_status) &
CSR_ISP_SOFT_RESET) == 0)
break;
@@ -858,12 +856,12 @@
/* Get RISC SRAM. */
if (rval == QLA_SUCCESS)
rval = qla2xxx_dump_ram(ha, 0x800, fw->risc_ram,
- sizeof(fw->risc_ram) / 2, &nxt);
+ ARRAY_SIZE(fw->risc_ram), &nxt);
/* Get stack SRAM. */
if (rval == QLA_SUCCESS)
rval = qla2xxx_dump_ram(ha, 0x10000, fw->stack_ram,
- sizeof(fw->stack_ram) / 2, &nxt);
+ ARRAY_SIZE(fw->stack_ram), &nxt);
/* Get data SRAM. */
if (rval == QLA_SUCCESS)
@@ -874,48 +872,31 @@
qla2xxx_copy_queues(ha, nxt);
qla2xxx_dump_post_process(base_vha, rval);
-
-qla2300_fw_dump_failed:
-#ifndef __CHECKER__
- if (!hardware_locked)
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-#else
- ;
-#endif
}
/**
* qla2100_fw_dump() - Dumps binary data from the 2100/2200 firmware.
* @vha: HA context
- * @hardware_locked: Called with the hardware_lock
*/
void
-qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
+qla2100_fw_dump(scsi_qla_host_t *vha)
{
int rval;
uint32_t cnt, timer;
- uint16_t risc_address;
- uint16_t mb0, mb2;
+ uint16_t risc_address = 0;
+ uint16_t mb0 = 0, mb2 = 0;
struct qla_hw_data *ha = vha->hw;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
- uint16_t __iomem *dmp_reg;
- unsigned long flags;
+ __le16 __iomem *dmp_reg;
struct qla2100_fw_dump *fw;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
- risc_address = 0;
- mb0 = mb2 = 0;
- flags = 0;
-
-#ifndef __CHECKER__
- if (!hardware_locked)
- spin_lock_irqsave(&ha->hardware_lock, flags);
-#endif
+ lockdep_assert_held(&ha->hardware_lock);
if (!ha->fw_dump) {
ql_log(ql_log_warn, vha, 0xd004,
"No buffer available for dump.\n");
- goto qla2100_fw_dump_failed;
+ return;
}
if (ha->fw_dumped) {
@@ -923,17 +904,17 @@
"Firmware has been previously dumped (%p) "
"-- ignoring request.\n",
ha->fw_dump);
- goto qla2100_fw_dump_failed;
+ return;
}
fw = &ha->fw_dump->isp.isp21;
qla2xxx_prep_dump(ha, ha->fw_dump);
rval = QLA_SUCCESS;
- fw->hccr = htons(RD_REG_WORD(®->hccr));
+ fw->hccr = htons(rd_reg_word(®->hccr));
/* Pause RISC. */
- WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC);
- for (cnt = 30000; (RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) == 0 &&
+ wrt_reg_word(®->hccr, HCCR_PAUSE_RISC);
+ for (cnt = 30000; (rd_reg_word(®->hccr) & HCCR_RISC_PAUSE) == 0 &&
rval == QLA_SUCCESS; cnt--) {
if (cnt)
udelay(100);
@@ -942,61 +923,61 @@
}
if (rval == QLA_SUCCESS) {
dmp_reg = ®->flash_address;
- for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++, dmp_reg++)
- fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->pbiu_reg); cnt++, dmp_reg++)
+ fw->pbiu_reg[cnt] = htons(rd_reg_word(dmp_reg));
dmp_reg = ®->u.isp2100.mailbox0;
for (cnt = 0; cnt < ha->mbx_count; cnt++, dmp_reg++) {
if (cnt == 8)
dmp_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 = ®->u.isp2100.unused_2[0];
- for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++, dmp_reg++)
- fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->dma_reg); cnt++, dmp_reg++)
+ fw->dma_reg[cnt] = htons(rd_reg_word(dmp_reg));
- WRT_REG_WORD(®->ctrl_status, 0x00);
+ wrt_reg_word(®->ctrl_status, 0x00);
dmp_reg = ®->risc_hw;
- for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++, dmp_reg++)
- fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg));
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->risc_hdw_reg); cnt++, dmp_reg++)
+ fw->risc_hdw_reg[cnt] = htons(rd_reg_word(dmp_reg));
- WRT_REG_WORD(®->pcr, 0x2000);
+ wrt_reg_word(®->pcr, 0x2000);
qla2xxx_read_window(reg, 16, fw->risc_gp0_reg);
- WRT_REG_WORD(®->pcr, 0x2100);
+ wrt_reg_word(®->pcr, 0x2100);
qla2xxx_read_window(reg, 16, fw->risc_gp1_reg);
- WRT_REG_WORD(®->pcr, 0x2200);
+ wrt_reg_word(®->pcr, 0x2200);
qla2xxx_read_window(reg, 16, fw->risc_gp2_reg);
- WRT_REG_WORD(®->pcr, 0x2300);
+ wrt_reg_word(®->pcr, 0x2300);
qla2xxx_read_window(reg, 16, fw->risc_gp3_reg);
- WRT_REG_WORD(®->pcr, 0x2400);
+ wrt_reg_word(®->pcr, 0x2400);
qla2xxx_read_window(reg, 16, fw->risc_gp4_reg);
- WRT_REG_WORD(®->pcr, 0x2500);
+ wrt_reg_word(®->pcr, 0x2500);
qla2xxx_read_window(reg, 16, fw->risc_gp5_reg);
- WRT_REG_WORD(®->pcr, 0x2600);
+ wrt_reg_word(®->pcr, 0x2600);
qla2xxx_read_window(reg, 16, fw->risc_gp6_reg);
- WRT_REG_WORD(®->pcr, 0x2700);
+ wrt_reg_word(®->pcr, 0x2700);
qla2xxx_read_window(reg, 16, fw->risc_gp7_reg);
- WRT_REG_WORD(®->ctrl_status, 0x10);
+ wrt_reg_word(®->ctrl_status, 0x10);
qla2xxx_read_window(reg, 16, fw->frame_buf_hdw_reg);
- WRT_REG_WORD(®->ctrl_status, 0x20);
+ wrt_reg_word(®->ctrl_status, 0x20);
qla2xxx_read_window(reg, 64, fw->fpm_b0_reg);
- WRT_REG_WORD(®->ctrl_status, 0x30);
+ wrt_reg_word(®->ctrl_status, 0x30);
qla2xxx_read_window(reg, 64, fw->fpm_b1_reg);
/* Reset the ISP. */
- WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET);
+ wrt_reg_word(®->ctrl_status, CSR_ISP_SOFT_RESET);
}
for (cnt = 30000; RD_MAILBOX_REG(ha, reg, 0) != 0 &&
@@ -1009,11 +990,11 @@
/* Pause RISC. */
if (rval == QLA_SUCCESS && (IS_QLA2200(ha) || (IS_QLA2100(ha) &&
- (RD_REG_WORD(®->mctr) & (BIT_1 | BIT_0)) != 0))) {
+ (rd_reg_word(®->mctr) & (BIT_1 | BIT_0)) != 0))) {
- WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC);
+ wrt_reg_word(®->hccr, HCCR_PAUSE_RISC);
for (cnt = 30000;
- (RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) == 0 &&
+ (rd_reg_word(®->hccr) & HCCR_RISC_PAUSE) == 0 &&
rval == QLA_SUCCESS; cnt--) {
if (cnt)
udelay(100);
@@ -1023,13 +1004,13 @@
if (rval == QLA_SUCCESS) {
/* Set memory configuration and timing. */
if (IS_QLA2100(ha))
- WRT_REG_WORD(®->mctr, 0xf1);
+ wrt_reg_word(®->mctr, 0xf1);
else
- WRT_REG_WORD(®->mctr, 0xf2);
- RD_REG_WORD(®->mctr); /* PCI Posting. */
+ wrt_reg_word(®->mctr, 0xf2);
+ rd_reg_word(®->mctr); /* PCI Posting. */
/* Release RISC. */
- WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC);
+ wrt_reg_word(®->hccr, HCCR_RELEASE_RISC);
}
}
@@ -1039,29 +1020,29 @@
WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_WORD);
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
}
- for (cnt = 0; cnt < sizeof(fw->risc_ram) / 2 && rval == QLA_SUCCESS;
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->risc_ram) && rval == QLA_SUCCESS;
cnt++, risc_address++) {
WRT_MAILBOX_REG(ha, reg, 1, risc_address);
- WRT_REG_WORD(®->hccr, HCCR_SET_HOST_INT);
+ wrt_reg_word(®->hccr, HCCR_SET_HOST_INT);
for (timer = 6000000; timer != 0; timer--) {
/* Check for pending interrupts. */
- if (RD_REG_WORD(®->istatus) & ISR_RISC_INT) {
- if (RD_REG_WORD(®->semaphore) & BIT_0) {
+ if (rd_reg_word(®->istatus) & ISR_RISC_INT) {
+ if (rd_reg_word(®->semaphore) & BIT_0) {
set_bit(MBX_INTERRUPT,
&ha->mbx_cmd_flags);
mb0 = RD_MAILBOX_REG(ha, reg, 0);
mb2 = RD_MAILBOX_REG(ha, reg, 2);
- WRT_REG_WORD(®->semaphore, 0);
- WRT_REG_WORD(®->hccr,
+ wrt_reg_word(®->semaphore, 0);
+ wrt_reg_word(®->hccr,
HCCR_CLR_RISC_INT);
- RD_REG_WORD(®->hccr);
+ rd_reg_word(®->hccr);
break;
}
- WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT);
- RD_REG_WORD(®->hccr);
+ wrt_reg_word(®->hccr, HCCR_CLR_RISC_INT);
+ rd_reg_word(®->hccr);
}
udelay(5);
}
@@ -1075,51 +1056,38 @@
}
if (rval == QLA_SUCCESS)
- qla2xxx_copy_queues(ha, &fw->risc_ram[cnt]);
+ qla2xxx_copy_queues(ha, &fw->queue_dump[0]);
qla2xxx_dump_post_process(base_vha, rval);
-
-qla2100_fw_dump_failed:
-#ifndef __CHECKER__
- if (!hardware_locked)
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-#else
- ;
-#endif
}
void
-qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
+qla24xx_fw_dump(scsi_qla_host_t *vha)
{
int rval;
uint32_t cnt;
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
- uint32_t __iomem *dmp_reg;
- uint32_t *iter_reg;
- uint16_t __iomem *mbx_reg;
- unsigned long flags;
+ __le32 __iomem *dmp_reg;
+ __be32 *iter_reg;
+ __le16 __iomem *mbx_reg;
struct qla24xx_fw_dump *fw;
void *nxt;
void *nxt_chain;
- uint32_t *last_chain = NULL;
+ __be32 *last_chain = NULL;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
+ lockdep_assert_held(&ha->hardware_lock);
+
if (IS_P3P_TYPE(ha))
return;
- flags = 0;
ha->fw_dump_cap_flags = 0;
-#ifndef __CHECKER__
- if (!hardware_locked)
- spin_lock_irqsave(&ha->hardware_lock, flags);
-#endif
-
if (!ha->fw_dump) {
ql_log(ql_log_warn, vha, 0xd006,
"No buffer available for dump.\n");
- goto qla24xx_fw_dump_failed;
+ return;
}
if (ha->fw_dumped) {
@@ -1127,13 +1095,13 @@
"Firmware has been previously dumped (%p) "
"-- ignoring request.\n",
ha->fw_dump);
- goto qla24xx_fw_dump_failed;
+ return;
}
QLA_FW_STOPPED(ha);
fw = &ha->fw_dump->isp.isp24;
qla2xxx_prep_dump(ha, ha->fw_dump);
- fw->host_status = htonl(RD_REG_DWORD(®->host_status));
+ fw->host_status = htonl(rd_reg_dword(®->host_status));
/*
* Pause RISC. No need to track timeout, as resetting the chip
@@ -1143,41 +1111,41 @@
/* Host interface registers. */
dmp_reg = ®->flash_addr;
- for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++)
- fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg));
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->host_reg); cnt++, dmp_reg++)
+ fw->host_reg[cnt] = htonl(rd_reg_dword(dmp_reg));
/* Disable interrupts. */
- WRT_REG_DWORD(®->ictrl, 0);
- RD_REG_DWORD(®->ictrl);
+ wrt_reg_dword(®->ictrl, 0);
+ rd_reg_dword(®->ictrl);
/* Shadow registers. */
- WRT_REG_DWORD(®->iobase_addr, 0x0F70);
- RD_REG_DWORD(®->iobase_addr);
- WRT_REG_DWORD(®->iobase_select, 0xB0000000);
- fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_addr, 0x0F70);
+ rd_reg_dword(®->iobase_addr);
+ wrt_reg_dword(®->iobase_select, 0xB0000000);
+ fw->shadow_reg[0] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0100000);
- fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0100000);
+ fw->shadow_reg[1] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0200000);
- fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0200000);
+ fw->shadow_reg[2] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0300000);
- fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0300000);
+ fw->shadow_reg[3] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0400000);
- fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0400000);
+ fw->shadow_reg[4] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0500000);
- fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0500000);
+ fw->shadow_reg[5] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0600000);
- fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0600000);
+ fw->shadow_reg[6] = htonl(rd_reg_dword(®->iobase_sdata));
/* Mailbox registers. */
mbx_reg = ®->mailbox0;
- for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++)
- fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg));
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->mailbox_reg); cnt++, mbx_reg++)
+ fw->mailbox_reg[cnt] = htons(rd_reg_word(mbx_reg));
/* Transfer sequence registers. */
iter_reg = fw->xseq_gp_reg;
@@ -1216,19 +1184,19 @@
iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
dmp_reg = ®->iobase_q;
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
- *iter_reg++ = htonl(RD_REG_DWORD(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 = ®->iobase_q;
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
- *iter_reg++ = htonl(RD_REG_DWORD(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 = ®->iobase_q;
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
- *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
+ *iter_reg++ = htonl(rd_reg_dword(dmp_reg));
/* Transmit DMA registers. */
iter_reg = fw->xmt0_dma_reg;
@@ -1337,44 +1305,31 @@
qla24xx_fw_dump_failed_0:
qla2xxx_dump_post_process(base_vha, rval);
-
-qla24xx_fw_dump_failed:
-#ifndef __CHECKER__
- if (!hardware_locked)
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-#else
- ;
-#endif
}
void
-qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
+qla25xx_fw_dump(scsi_qla_host_t *vha)
{
int rval;
uint32_t cnt;
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
- uint32_t __iomem *dmp_reg;
- uint32_t *iter_reg;
- uint16_t __iomem *mbx_reg;
- unsigned long flags;
+ __le32 __iomem *dmp_reg;
+ __be32 *iter_reg;
+ __le16 __iomem *mbx_reg;
struct qla25xx_fw_dump *fw;
void *nxt, *nxt_chain;
- uint32_t *last_chain = NULL;
+ __be32 *last_chain = NULL;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
- flags = 0;
- ha->fw_dump_cap_flags = 0;
+ lockdep_assert_held(&ha->hardware_lock);
-#ifndef __CHECKER__
- if (!hardware_locked)
- spin_lock_irqsave(&ha->hardware_lock, flags);
-#endif
+ ha->fw_dump_cap_flags = 0;
if (!ha->fw_dump) {
ql_log(ql_log_warn, vha, 0xd008,
"No buffer available for dump.\n");
- goto qla25xx_fw_dump_failed;
+ return;
}
if (ha->fw_dumped) {
@@ -1382,14 +1337,14 @@
"Firmware has been previously dumped (%p) "
"-- ignoring request.\n",
ha->fw_dump);
- goto qla25xx_fw_dump_failed;
+ return;
}
QLA_FW_STOPPED(ha);
fw = &ha->fw_dump->isp.isp25;
qla2xxx_prep_dump(ha, ha->fw_dump);
ha->fw_dump->version = htonl(2);
- fw->host_status = htonl(RD_REG_DWORD(®->host_status));
+ fw->host_status = htonl(rd_reg_dword(®->host_status));
/*
* Pause RISC. No need to track timeout, as resetting the chip
@@ -1403,73 +1358,73 @@
qla24xx_read_window(reg, 0x7010, 16, iter_reg);
/* PCIe registers. */
- WRT_REG_DWORD(®->iobase_addr, 0x7C00);
- RD_REG_DWORD(®->iobase_addr);
- WRT_REG_DWORD(®->iobase_window, 0x01);
+ wrt_reg_dword(®->iobase_addr, 0x7C00);
+ rd_reg_dword(®->iobase_addr);
+ wrt_reg_dword(®->iobase_window, 0x01);
dmp_reg = ®->iobase_c4;
- fw->pcie_regs[0] = 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));
+ 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(®->iobase_window));
+ fw->pcie_regs[2] = htonl(rd_reg_dword(dmp_reg));
+ fw->pcie_regs[3] = htonl(rd_reg_dword(®->iobase_window));
- WRT_REG_DWORD(®->iobase_window, 0x00);
- RD_REG_DWORD(®->iobase_window);
+ wrt_reg_dword(®->iobase_window, 0x00);
+ rd_reg_dword(®->iobase_window);
/* Host interface registers. */
dmp_reg = ®->flash_addr;
- for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++)
- fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg));
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->host_reg); cnt++, dmp_reg++)
+ fw->host_reg[cnt] = htonl(rd_reg_dword(dmp_reg));
/* Disable interrupts. */
- WRT_REG_DWORD(®->ictrl, 0);
- RD_REG_DWORD(®->ictrl);
+ wrt_reg_dword(®->ictrl, 0);
+ rd_reg_dword(®->ictrl);
/* Shadow registers. */
- WRT_REG_DWORD(®->iobase_addr, 0x0F70);
- RD_REG_DWORD(®->iobase_addr);
- WRT_REG_DWORD(®->iobase_select, 0xB0000000);
- fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_addr, 0x0F70);
+ rd_reg_dword(®->iobase_addr);
+ wrt_reg_dword(®->iobase_select, 0xB0000000);
+ fw->shadow_reg[0] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0100000);
- fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0100000);
+ fw->shadow_reg[1] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0200000);
- fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0200000);
+ fw->shadow_reg[2] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0300000);
- fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0300000);
+ fw->shadow_reg[3] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0400000);
- fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0400000);
+ fw->shadow_reg[4] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0500000);
- fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0500000);
+ fw->shadow_reg[5] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0600000);
- fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0600000);
+ fw->shadow_reg[6] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0700000);
- fw->shadow_reg[7] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0700000);
+ fw->shadow_reg[7] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0800000);
- fw->shadow_reg[8] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0800000);
+ fw->shadow_reg[8] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0900000);
- fw->shadow_reg[9] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0900000);
+ fw->shadow_reg[9] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0A00000);
- fw->shadow_reg[10] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0A00000);
+ fw->shadow_reg[10] = htonl(rd_reg_dword(®->iobase_sdata));
/* RISC I/O register. */
- WRT_REG_DWORD(®->iobase_addr, 0x0010);
- fw->risc_io_reg = htonl(RD_REG_DWORD(®->iobase_window));
+ wrt_reg_dword(®->iobase_addr, 0x0010);
+ fw->risc_io_reg = htonl(rd_reg_dword(®->iobase_window));
/* Mailbox registers. */
mbx_reg = ®->mailbox0;
- for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++)
- fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg));
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->mailbox_reg); cnt++, mbx_reg++)
+ fw->mailbox_reg[cnt] = htons(rd_reg_word(mbx_reg));
/* Transfer sequence registers. */
iter_reg = fw->xseq_gp_reg;
@@ -1533,19 +1488,19 @@
iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
dmp_reg = ®->iobase_q;
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
- *iter_reg++ = htonl(RD_REG_DWORD(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 = ®->iobase_q;
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
- *iter_reg++ = htonl(RD_REG_DWORD(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 = ®->iobase_q;
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
- *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
+ *iter_reg++ = htonl(rd_reg_dword(dmp_reg));
/* Transmit DMA registers. */
iter_reg = fw->xmt0_dma_reg;
@@ -1663,44 +1618,31 @@
qla25xx_fw_dump_failed_0:
qla2xxx_dump_post_process(base_vha, rval);
-
-qla25xx_fw_dump_failed:
-#ifndef __CHECKER__
- if (!hardware_locked)
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-#else
- ;
-#endif
}
void
-qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
+qla81xx_fw_dump(scsi_qla_host_t *vha)
{
int rval;
uint32_t cnt;
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
- uint32_t __iomem *dmp_reg;
- uint32_t *iter_reg;
- uint16_t __iomem *mbx_reg;
- unsigned long flags;
+ __le32 __iomem *dmp_reg;
+ __be32 *iter_reg;
+ __le16 __iomem *mbx_reg;
struct qla81xx_fw_dump *fw;
void *nxt, *nxt_chain;
- uint32_t *last_chain = NULL;
+ __be32 *last_chain = NULL;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
- flags = 0;
- ha->fw_dump_cap_flags = 0;
+ lockdep_assert_held(&ha->hardware_lock);
-#ifndef __CHECKER__
- if (!hardware_locked)
- spin_lock_irqsave(&ha->hardware_lock, flags);
-#endif
+ ha->fw_dump_cap_flags = 0;
if (!ha->fw_dump) {
ql_log(ql_log_warn, vha, 0xd00a,
"No buffer available for dump.\n");
- goto qla81xx_fw_dump_failed;
+ return;
}
if (ha->fw_dumped) {
@@ -1708,12 +1650,12 @@
"Firmware has been previously dumped (%p) "
"-- ignoring request.\n",
ha->fw_dump);
- goto qla81xx_fw_dump_failed;
+ return;
}
fw = &ha->fw_dump->isp.isp81;
qla2xxx_prep_dump(ha, ha->fw_dump);
- fw->host_status = htonl(RD_REG_DWORD(®->host_status));
+ fw->host_status = htonl(rd_reg_dword(®->host_status));
/*
* Pause RISC. No need to track timeout, as resetting the chip
@@ -1727,73 +1669,73 @@
qla24xx_read_window(reg, 0x7010, 16, iter_reg);
/* PCIe registers. */
- WRT_REG_DWORD(®->iobase_addr, 0x7C00);
- RD_REG_DWORD(®->iobase_addr);
- WRT_REG_DWORD(®->iobase_window, 0x01);
+ wrt_reg_dword(®->iobase_addr, 0x7C00);
+ rd_reg_dword(®->iobase_addr);
+ wrt_reg_dword(®->iobase_window, 0x01);
dmp_reg = ®->iobase_c4;
- fw->pcie_regs[0] = 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));
+ 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(®->iobase_window));
+ fw->pcie_regs[2] = htonl(rd_reg_dword(dmp_reg));
+ fw->pcie_regs[3] = htonl(rd_reg_dword(®->iobase_window));
- WRT_REG_DWORD(®->iobase_window, 0x00);
- RD_REG_DWORD(®->iobase_window);
+ wrt_reg_dword(®->iobase_window, 0x00);
+ rd_reg_dword(®->iobase_window);
/* Host interface registers. */
dmp_reg = ®->flash_addr;
- for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++)
- fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg));
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->host_reg); cnt++, dmp_reg++)
+ fw->host_reg[cnt] = htonl(rd_reg_dword(dmp_reg));
/* Disable interrupts. */
- WRT_REG_DWORD(®->ictrl, 0);
- RD_REG_DWORD(®->ictrl);
+ wrt_reg_dword(®->ictrl, 0);
+ rd_reg_dword(®->ictrl);
/* Shadow registers. */
- WRT_REG_DWORD(®->iobase_addr, 0x0F70);
- RD_REG_DWORD(®->iobase_addr);
- WRT_REG_DWORD(®->iobase_select, 0xB0000000);
- fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_addr, 0x0F70);
+ rd_reg_dword(®->iobase_addr);
+ wrt_reg_dword(®->iobase_select, 0xB0000000);
+ fw->shadow_reg[0] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0100000);
- fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0100000);
+ fw->shadow_reg[1] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0200000);
- fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0200000);
+ fw->shadow_reg[2] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0300000);
- fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0300000);
+ fw->shadow_reg[3] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0400000);
- fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0400000);
+ fw->shadow_reg[4] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0500000);
- fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0500000);
+ fw->shadow_reg[5] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0600000);
- fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0600000);
+ fw->shadow_reg[6] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0700000);
- fw->shadow_reg[7] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0700000);
+ fw->shadow_reg[7] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0800000);
- fw->shadow_reg[8] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0800000);
+ fw->shadow_reg[8] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0900000);
- fw->shadow_reg[9] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0900000);
+ fw->shadow_reg[9] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0A00000);
- fw->shadow_reg[10] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0A00000);
+ fw->shadow_reg[10] = htonl(rd_reg_dword(®->iobase_sdata));
/* RISC I/O register. */
- WRT_REG_DWORD(®->iobase_addr, 0x0010);
- fw->risc_io_reg = htonl(RD_REG_DWORD(®->iobase_window));
+ wrt_reg_dword(®->iobase_addr, 0x0010);
+ fw->risc_io_reg = htonl(rd_reg_dword(®->iobase_window));
/* Mailbox registers. */
mbx_reg = ®->mailbox0;
- for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++)
- fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg));
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->mailbox_reg); cnt++, mbx_reg++)
+ fw->mailbox_reg[cnt] = htons(rd_reg_word(mbx_reg));
/* Transfer sequence registers. */
iter_reg = fw->xseq_gp_reg;
@@ -1857,19 +1799,19 @@
iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
dmp_reg = ®->iobase_q;
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
- *iter_reg++ = htonl(RD_REG_DWORD(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 = ®->iobase_q;
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
- *iter_reg++ = htonl(RD_REG_DWORD(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 = ®->iobase_q;
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
- *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
+ *iter_reg++ = htonl(rd_reg_dword(dmp_reg));
/* Transmit DMA registers. */
iter_reg = fw->xmt0_dma_reg;
@@ -1991,57 +1933,44 @@
qla81xx_fw_dump_failed_0:
qla2xxx_dump_post_process(base_vha, rval);
-
-qla81xx_fw_dump_failed:
-#ifndef __CHECKER__
- if (!hardware_locked)
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-#else
- ;
-#endif
}
void
-qla83xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
+qla83xx_fw_dump(scsi_qla_host_t *vha)
{
int rval;
uint32_t cnt;
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
- uint32_t __iomem *dmp_reg;
- uint32_t *iter_reg;
- uint16_t __iomem *mbx_reg;
- unsigned long flags;
+ __le32 __iomem *dmp_reg;
+ __be32 *iter_reg;
+ __le16 __iomem *mbx_reg;
struct qla83xx_fw_dump *fw;
void *nxt, *nxt_chain;
- uint32_t *last_chain = NULL;
+ __be32 *last_chain = NULL;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
- flags = 0;
- ha->fw_dump_cap_flags = 0;
+ lockdep_assert_held(&ha->hardware_lock);
-#ifndef __CHECKER__
- if (!hardware_locked)
- spin_lock_irqsave(&ha->hardware_lock, flags);
-#endif
+ ha->fw_dump_cap_flags = 0;
if (!ha->fw_dump) {
ql_log(ql_log_warn, vha, 0xd00c,
"No buffer available for dump!!!\n");
- goto qla83xx_fw_dump_failed;
+ return;
}
if (ha->fw_dumped) {
ql_log(ql_log_warn, vha, 0xd00d,
"Firmware has been previously dumped (%p) -- ignoring "
"request...\n", ha->fw_dump);
- goto qla83xx_fw_dump_failed;
+ return;
}
QLA_FW_STOPPED(ha);
fw = &ha->fw_dump->isp.isp83;
qla2xxx_prep_dump(ha, ha->fw_dump);
- fw->host_status = htonl(RD_REG_DWORD(®->host_status));
+ fw->host_status = htonl(rd_reg_dword(®->host_status));
/*
* Pause RISC. No need to track timeout, as resetting the chip
@@ -2049,24 +1978,24 @@
*/
qla24xx_pause_risc(reg, ha);
- WRT_REG_DWORD(®->iobase_addr, 0x6000);
+ wrt_reg_dword(®->iobase_addr, 0x6000);
dmp_reg = ®->iobase_window;
- RD_REG_DWORD(dmp_reg);
- WRT_REG_DWORD(dmp_reg, 0);
+ rd_reg_dword(dmp_reg);
+ wrt_reg_dword(dmp_reg, 0);
dmp_reg = ®->unused_4_1[0];
- RD_REG_DWORD(dmp_reg);
- WRT_REG_DWORD(dmp_reg, 0);
+ rd_reg_dword(dmp_reg);
+ wrt_reg_dword(dmp_reg, 0);
- WRT_REG_DWORD(®->iobase_addr, 0x6010);
+ wrt_reg_dword(®->iobase_addr, 0x6010);
dmp_reg = ®->unused_4_1[2];
- RD_REG_DWORD(dmp_reg);
- WRT_REG_DWORD(dmp_reg, 0);
+ rd_reg_dword(dmp_reg);
+ wrt_reg_dword(dmp_reg, 0);
/* select PCR and disable ecc checking and correction */
- WRT_REG_DWORD(®->iobase_addr, 0x0F70);
- RD_REG_DWORD(®->iobase_addr);
- WRT_REG_DWORD(®->iobase_select, 0x60000000); /* write to F0h = PCR */
+ wrt_reg_dword(®->iobase_addr, 0x0F70);
+ rd_reg_dword(®->iobase_addr);
+ wrt_reg_dword(®->iobase_select, 0x60000000); /* write to F0h = PCR */
/* Host/Risc registers. */
iter_reg = fw->host_risc_reg;
@@ -2075,73 +2004,73 @@
qla24xx_read_window(reg, 0x7040, 16, iter_reg);
/* PCIe registers. */
- WRT_REG_DWORD(®->iobase_addr, 0x7C00);
- RD_REG_DWORD(®->iobase_addr);
- WRT_REG_DWORD(®->iobase_window, 0x01);
+ wrt_reg_dword(®->iobase_addr, 0x7C00);
+ rd_reg_dword(®->iobase_addr);
+ wrt_reg_dword(®->iobase_window, 0x01);
dmp_reg = ®->iobase_c4;
- fw->pcie_regs[0] = 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));
+ 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(®->iobase_window));
+ fw->pcie_regs[2] = htonl(rd_reg_dword(dmp_reg));
+ fw->pcie_regs[3] = htonl(rd_reg_dword(®->iobase_window));
- WRT_REG_DWORD(®->iobase_window, 0x00);
- RD_REG_DWORD(®->iobase_window);
+ wrt_reg_dword(®->iobase_window, 0x00);
+ rd_reg_dword(®->iobase_window);
/* Host interface registers. */
dmp_reg = ®->flash_addr;
- for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++, dmp_reg++)
- fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg));
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->host_reg); cnt++, dmp_reg++)
+ fw->host_reg[cnt] = htonl(rd_reg_dword(dmp_reg));
/* Disable interrupts. */
- WRT_REG_DWORD(®->ictrl, 0);
- RD_REG_DWORD(®->ictrl);
+ wrt_reg_dword(®->ictrl, 0);
+ rd_reg_dword(®->ictrl);
/* Shadow registers. */
- WRT_REG_DWORD(®->iobase_addr, 0x0F70);
- RD_REG_DWORD(®->iobase_addr);
- WRT_REG_DWORD(®->iobase_select, 0xB0000000);
- fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_addr, 0x0F70);
+ rd_reg_dword(®->iobase_addr);
+ wrt_reg_dword(®->iobase_select, 0xB0000000);
+ fw->shadow_reg[0] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0100000);
- fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0100000);
+ fw->shadow_reg[1] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0200000);
- fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0200000);
+ fw->shadow_reg[2] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0300000);
- fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0300000);
+ fw->shadow_reg[3] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0400000);
- fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0400000);
+ fw->shadow_reg[4] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0500000);
- fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0500000);
+ fw->shadow_reg[5] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0600000);
- fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0600000);
+ fw->shadow_reg[6] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0700000);
- fw->shadow_reg[7] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0700000);
+ fw->shadow_reg[7] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0800000);
- fw->shadow_reg[8] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0800000);
+ fw->shadow_reg[8] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0900000);
- fw->shadow_reg[9] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0900000);
+ fw->shadow_reg[9] = htonl(rd_reg_dword(®->iobase_sdata));
- WRT_REG_DWORD(®->iobase_select, 0xB0A00000);
- fw->shadow_reg[10] = htonl(RD_REG_DWORD(®->iobase_sdata));
+ wrt_reg_dword(®->iobase_select, 0xB0A00000);
+ fw->shadow_reg[10] = htonl(rd_reg_dword(®->iobase_sdata));
/* RISC I/O register. */
- WRT_REG_DWORD(®->iobase_addr, 0x0010);
- fw->risc_io_reg = htonl(RD_REG_DWORD(®->iobase_window));
+ wrt_reg_dword(®->iobase_addr, 0x0010);
+ fw->risc_io_reg = htonl(rd_reg_dword(®->iobase_window));
/* Mailbox registers. */
mbx_reg = ®->mailbox0;
- for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++, mbx_reg++)
- fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg));
+ for (cnt = 0; cnt < ARRAY_SIZE(fw->mailbox_reg); cnt++, mbx_reg++)
+ fw->mailbox_reg[cnt] = htons(rd_reg_word(mbx_reg));
/* Transfer sequence registers. */
iter_reg = fw->xseq_gp_reg;
@@ -2237,19 +2166,19 @@
iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
dmp_reg = ®->iobase_q;
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
- *iter_reg++ = htonl(RD_REG_DWORD(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 = ®->iobase_q;
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
- *iter_reg++ = htonl(RD_REG_DWORD(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 = ®->iobase_q;
for (cnt = 0; cnt < 7; cnt++, dmp_reg++)
- *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg));
+ *iter_reg++ = htonl(rd_reg_dword(dmp_reg));
/* Transmit DMA registers. */
iter_reg = fw->xmt0_dma_reg;
@@ -2455,16 +2384,16 @@
ql_log(ql_log_warn, vha, 0xd00f, "try a bigger hammer!!!\n");
- WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET);
- RD_REG_DWORD(®->hccr);
+ wrt_reg_dword(®->hccr, HCCRX_SET_RISC_RESET);
+ rd_reg_dword(®->hccr);
- WRT_REG_DWORD(®->hccr, HCCRX_REL_RISC_PAUSE);
- RD_REG_DWORD(®->hccr);
+ wrt_reg_dword(®->hccr, HCCRX_REL_RISC_PAUSE);
+ rd_reg_dword(®->hccr);
- WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_RESET);
- RD_REG_DWORD(®->hccr);
+ wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_RESET);
+ rd_reg_dword(®->hccr);
- for (cnt = 30000; cnt && (RD_REG_WORD(®->mailbox0)); cnt--)
+ for (cnt = 30000; cnt && (rd_reg_word(®->mailbox0)); cnt--)
udelay(5);
if (!cnt) {
@@ -2505,20 +2434,29 @@
qla83xx_fw_dump_failed_0:
qla2xxx_dump_post_process(base_vha, rval);
-
-qla83xx_fw_dump_failed:
-#ifndef __CHECKER__
- if (!hardware_locked)
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-#else
- ;
-#endif
}
/****************************************************************************/
/* Driver Debug Functions. */
/****************************************************************************/
+/* Write the debug message prefix into @pbuf. */
+static void ql_dbg_prefix(char *pbuf, int pbuf_size,
+ const scsi_qla_host_t *vha, uint msg_id)
+{
+ if (vha) {
+ const struct pci_dev *pdev = vha->hw->pdev;
+
+ /* <module-name> [<dev-name>]-<msg-id>:<host>: */
+ snprintf(pbuf, pbuf_size, "%s [%s]-%04x:%lu: ", QL_MSGHDR,
+ dev_name(&(pdev->dev)), msg_id, vha->host_no);
+ } else {
+ /* <module-name> [<dev-name>]-<msg-id>: : */
+ snprintf(pbuf, pbuf_size, "%s [%s]-%04x: : ", QL_MSGHDR,
+ "0000:00:00.0", msg_id);
+ }
+}
+
/*
* This function is for formatting and logging debug information.
* It is to be used when vha is available. It formats the message
@@ -2537,8 +2475,9 @@
{
va_list va;
struct va_format vaf;
+ char pbuf[64];
- if (!ql_mask_match(level))
+ if (!ql_mask_match(level) && !trace_ql_dbg_log_enabled())
return;
va_start(va, fmt);
@@ -2546,16 +2485,12 @@
vaf.fmt = fmt;
vaf.va = &va;
- if (vha != NULL) {
- const struct pci_dev *pdev = vha->hw->pdev;
- /* <module-name> <pci-name> <msg-id>:<host> Message */
- pr_warn("%s [%s]-%04x:%ld: %pV",
- QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset,
- vha->host_no, &vaf);
- } else {
- pr_warn("%s [%s]-%04x: : %pV",
- QL_MSGHDR, "0000:00:00.0", id + ql_dbg_offset, &vaf);
- }
+ ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), vha, id);
+
+ if (!ql_mask_match(level))
+ trace_ql_dbg_log(pbuf, &vaf);
+ else
+ pr_warn("%s%pV", pbuf, &vaf);
va_end(va);
@@ -2580,6 +2515,7 @@
{
va_list va;
struct va_format vaf;
+ char pbuf[128];
if (pdev == NULL)
return;
@@ -2591,9 +2527,8 @@
vaf.fmt = fmt;
vaf.va = &va;
- /* <module-name> <dev-name>:<msg-id> Message */
- pr_warn("%s [%s]-%04x: : %pV",
- QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset, &vaf);
+ ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL, id + ql_dbg_offset);
+ pr_warn("%s%pV", pbuf, &vaf);
va_end(va);
}
@@ -2621,16 +2556,7 @@
if (level > ql_errlev)
return;
- if (vha != NULL) {
- const struct pci_dev *pdev = vha->hw->pdev;
- /* <module-name> <msg-id>:<host> Message */
- snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x:%ld: ",
- QL_MSGHDR, dev_name(&(pdev->dev)), id, vha->host_no);
- } else {
- snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ",
- QL_MSGHDR, "0000:00:00.0", id);
- }
- pbuf[sizeof(pbuf) - 1] = 0;
+ ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), vha, id);
va_start(va, fmt);
@@ -2681,10 +2607,7 @@
if (level > ql_errlev)
return;
- /* <module-name> <dev-name>:<msg-id> Message */
- snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ",
- QL_MSGHDR, dev_name(&(pdev->dev)), id);
- pbuf[sizeof(pbuf) - 1] = 0;
+ ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), NULL, id);
va_start(va, fmt);
@@ -2717,7 +2640,7 @@
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
- uint16_t __iomem *mbx_reg;
+ __le16 __iomem *mbx_reg;
if (!ql_mask_match(level))
return;
@@ -2732,10 +2655,9 @@
ql_dbg(level, vha, id, "Mailbox registers:\n");
for (i = 0; i < 6; i++, mbx_reg++)
ql_dbg(level, vha, id,
- "mbox[%d] %#04x\n", i, RD_REG_WORD(mbx_reg));
+ "mbox[%d] %#04x\n", i, rd_reg_word(mbx_reg));
}
-
void
ql_dump_buffer(uint level, scsi_qla_host_t *vha, uint id, const void *buf,
uint size)
@@ -2780,16 +2702,7 @@
if (level > ql_errlev)
return;
- if (qpair != NULL) {
- const struct pci_dev *pdev = qpair->pdev;
- /* <module-name> <msg-id>:<host> Message */
- snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: ",
- QL_MSGHDR, dev_name(&(pdev->dev)), id);
- } else {
- snprintf(pbuf, sizeof(pbuf), "%s [%s]-%04x: : ",
- QL_MSGHDR, "0000:00:00.0", id);
- }
- pbuf[sizeof(pbuf) - 1] = 0;
+ ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), qpair ? qpair->vha : NULL, id);
va_start(va, fmt);
@@ -2833,6 +2746,7 @@
{
va_list va;
struct va_format vaf;
+ char pbuf[128];
if (!ql_mask_match(level))
return;
@@ -2842,16 +2756,9 @@
vaf.fmt = fmt;
vaf.va = &va;
- if (qpair != NULL) {
- const struct pci_dev *pdev = qpair->pdev;
- /* <module-name> <pci-name> <msg-id>:<host> Message */
- pr_warn("%s [%s]-%04x: %pV",
- QL_MSGHDR, dev_name(&(pdev->dev)), id + ql_dbg_offset,
- &vaf);
- } else {
- pr_warn("%s [%s]-%04x: : %pV",
- QL_MSGHDR, "0000:00:00.0", id + ql_dbg_offset, &vaf);
- }
+ ql_dbg_prefix(pbuf, ARRAY_SIZE(pbuf), qpair ? qpair->vha : NULL,
+ id + ql_dbg_offset);
+ pr_warn("%s%pV", pbuf, &vaf);
va_end(va);
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index 433e955..2e59e75 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
@@ -12,205 +11,206 @@
*/
struct qla2300_fw_dump {
- uint16_t hccr;
- uint16_t pbiu_reg[8];
- uint16_t risc_host_reg[8];
- uint16_t mailbox_reg[32];
- uint16_t resp_dma_reg[32];
- uint16_t dma_reg[48];
- uint16_t risc_hdw_reg[16];
- uint16_t risc_gp0_reg[16];
- uint16_t risc_gp1_reg[16];
- uint16_t risc_gp2_reg[16];
- uint16_t risc_gp3_reg[16];
- uint16_t risc_gp4_reg[16];
- uint16_t risc_gp5_reg[16];
- uint16_t risc_gp6_reg[16];
- uint16_t risc_gp7_reg[16];
- uint16_t frame_buf_hdw_reg[64];
- uint16_t fpm_b0_reg[64];
- uint16_t fpm_b1_reg[64];
- uint16_t risc_ram[0xf800];
- uint16_t stack_ram[0x1000];
- uint16_t data_ram[1];
+ __be16 hccr;
+ __be16 pbiu_reg[8];
+ __be16 risc_host_reg[8];
+ __be16 mailbox_reg[32];
+ __be16 resp_dma_reg[32];
+ __be16 dma_reg[48];
+ __be16 risc_hdw_reg[16];
+ __be16 risc_gp0_reg[16];
+ __be16 risc_gp1_reg[16];
+ __be16 risc_gp2_reg[16];
+ __be16 risc_gp3_reg[16];
+ __be16 risc_gp4_reg[16];
+ __be16 risc_gp5_reg[16];
+ __be16 risc_gp6_reg[16];
+ __be16 risc_gp7_reg[16];
+ __be16 frame_buf_hdw_reg[64];
+ __be16 fpm_b0_reg[64];
+ __be16 fpm_b1_reg[64];
+ __be16 risc_ram[0xf800];
+ __be16 stack_ram[0x1000];
+ __be16 data_ram[1];
};
struct qla2100_fw_dump {
- uint16_t hccr;
- uint16_t pbiu_reg[8];
- uint16_t mailbox_reg[32];
- uint16_t dma_reg[48];
- uint16_t risc_hdw_reg[16];
- uint16_t risc_gp0_reg[16];
- uint16_t risc_gp1_reg[16];
- uint16_t risc_gp2_reg[16];
- uint16_t risc_gp3_reg[16];
- uint16_t risc_gp4_reg[16];
- uint16_t risc_gp5_reg[16];
- uint16_t risc_gp6_reg[16];
- uint16_t risc_gp7_reg[16];
- uint16_t frame_buf_hdw_reg[16];
- uint16_t fpm_b0_reg[64];
- uint16_t fpm_b1_reg[64];
- uint16_t risc_ram[0xf000];
+ __be16 hccr;
+ __be16 pbiu_reg[8];
+ __be16 mailbox_reg[32];
+ __be16 dma_reg[48];
+ __be16 risc_hdw_reg[16];
+ __be16 risc_gp0_reg[16];
+ __be16 risc_gp1_reg[16];
+ __be16 risc_gp2_reg[16];
+ __be16 risc_gp3_reg[16];
+ __be16 risc_gp4_reg[16];
+ __be16 risc_gp5_reg[16];
+ __be16 risc_gp6_reg[16];
+ __be16 risc_gp7_reg[16];
+ __be16 frame_buf_hdw_reg[16];
+ __be16 fpm_b0_reg[64];
+ __be16 fpm_b1_reg[64];
+ __be16 risc_ram[0xf000];
+ u8 queue_dump[];
};
struct qla24xx_fw_dump {
- uint32_t host_status;
- uint32_t host_reg[32];
- uint32_t shadow_reg[7];
- uint16_t mailbox_reg[32];
- uint32_t xseq_gp_reg[128];
- uint32_t xseq_0_reg[16];
- uint32_t xseq_1_reg[16];
- uint32_t rseq_gp_reg[128];
- uint32_t rseq_0_reg[16];
- uint32_t rseq_1_reg[16];
- uint32_t rseq_2_reg[16];
- uint32_t cmd_dma_reg[16];
- uint32_t req0_dma_reg[15];
- uint32_t resp0_dma_reg[15];
- uint32_t req1_dma_reg[15];
- uint32_t xmt0_dma_reg[32];
- uint32_t xmt1_dma_reg[32];
- uint32_t xmt2_dma_reg[32];
- uint32_t xmt3_dma_reg[32];
- uint32_t xmt4_dma_reg[32];
- uint32_t xmt_data_dma_reg[16];
- uint32_t rcvt0_data_dma_reg[32];
- uint32_t rcvt1_data_dma_reg[32];
- uint32_t risc_gp_reg[128];
- uint32_t lmc_reg[112];
- uint32_t fpm_hdw_reg[192];
- uint32_t fb_hdw_reg[176];
- uint32_t code_ram[0x2000];
- uint32_t ext_mem[1];
+ __be32 host_status;
+ __be32 host_reg[32];
+ __be32 shadow_reg[7];
+ __be16 mailbox_reg[32];
+ __be32 xseq_gp_reg[128];
+ __be32 xseq_0_reg[16];
+ __be32 xseq_1_reg[16];
+ __be32 rseq_gp_reg[128];
+ __be32 rseq_0_reg[16];
+ __be32 rseq_1_reg[16];
+ __be32 rseq_2_reg[16];
+ __be32 cmd_dma_reg[16];
+ __be32 req0_dma_reg[15];
+ __be32 resp0_dma_reg[15];
+ __be32 req1_dma_reg[15];
+ __be32 xmt0_dma_reg[32];
+ __be32 xmt1_dma_reg[32];
+ __be32 xmt2_dma_reg[32];
+ __be32 xmt3_dma_reg[32];
+ __be32 xmt4_dma_reg[32];
+ __be32 xmt_data_dma_reg[16];
+ __be32 rcvt0_data_dma_reg[32];
+ __be32 rcvt1_data_dma_reg[32];
+ __be32 risc_gp_reg[128];
+ __be32 lmc_reg[112];
+ __be32 fpm_hdw_reg[192];
+ __be32 fb_hdw_reg[176];
+ __be32 code_ram[0x2000];
+ __be32 ext_mem[1];
};
struct qla25xx_fw_dump {
- uint32_t host_status;
- uint32_t host_risc_reg[32];
- uint32_t pcie_regs[4];
- uint32_t host_reg[32];
- uint32_t shadow_reg[11];
- uint32_t risc_io_reg;
- uint16_t mailbox_reg[32];
- uint32_t xseq_gp_reg[128];
- uint32_t xseq_0_reg[48];
- uint32_t xseq_1_reg[16];
- uint32_t rseq_gp_reg[128];
- uint32_t rseq_0_reg[32];
- uint32_t rseq_1_reg[16];
- uint32_t rseq_2_reg[16];
- uint32_t aseq_gp_reg[128];
- uint32_t aseq_0_reg[32];
- uint32_t aseq_1_reg[16];
- uint32_t aseq_2_reg[16];
- uint32_t cmd_dma_reg[16];
- uint32_t req0_dma_reg[15];
- uint32_t resp0_dma_reg[15];
- uint32_t req1_dma_reg[15];
- uint32_t xmt0_dma_reg[32];
- uint32_t xmt1_dma_reg[32];
- uint32_t xmt2_dma_reg[32];
- uint32_t xmt3_dma_reg[32];
- uint32_t xmt4_dma_reg[32];
- uint32_t xmt_data_dma_reg[16];
- uint32_t rcvt0_data_dma_reg[32];
- uint32_t rcvt1_data_dma_reg[32];
- uint32_t risc_gp_reg[128];
- uint32_t lmc_reg[128];
- uint32_t fpm_hdw_reg[192];
- uint32_t fb_hdw_reg[192];
- uint32_t code_ram[0x2000];
- uint32_t ext_mem[1];
+ __be32 host_status;
+ __be32 host_risc_reg[32];
+ __be32 pcie_regs[4];
+ __be32 host_reg[32];
+ __be32 shadow_reg[11];
+ __be32 risc_io_reg;
+ __be16 mailbox_reg[32];
+ __be32 xseq_gp_reg[128];
+ __be32 xseq_0_reg[48];
+ __be32 xseq_1_reg[16];
+ __be32 rseq_gp_reg[128];
+ __be32 rseq_0_reg[32];
+ __be32 rseq_1_reg[16];
+ __be32 rseq_2_reg[16];
+ __be32 aseq_gp_reg[128];
+ __be32 aseq_0_reg[32];
+ __be32 aseq_1_reg[16];
+ __be32 aseq_2_reg[16];
+ __be32 cmd_dma_reg[16];
+ __be32 req0_dma_reg[15];
+ __be32 resp0_dma_reg[15];
+ __be32 req1_dma_reg[15];
+ __be32 xmt0_dma_reg[32];
+ __be32 xmt1_dma_reg[32];
+ __be32 xmt2_dma_reg[32];
+ __be32 xmt3_dma_reg[32];
+ __be32 xmt4_dma_reg[32];
+ __be32 xmt_data_dma_reg[16];
+ __be32 rcvt0_data_dma_reg[32];
+ __be32 rcvt1_data_dma_reg[32];
+ __be32 risc_gp_reg[128];
+ __be32 lmc_reg[128];
+ __be32 fpm_hdw_reg[192];
+ __be32 fb_hdw_reg[192];
+ __be32 code_ram[0x2000];
+ __be32 ext_mem[1];
};
struct qla81xx_fw_dump {
- uint32_t host_status;
- uint32_t host_risc_reg[32];
- uint32_t pcie_regs[4];
- uint32_t host_reg[32];
- uint32_t shadow_reg[11];
- uint32_t risc_io_reg;
- uint16_t mailbox_reg[32];
- uint32_t xseq_gp_reg[128];
- uint32_t xseq_0_reg[48];
- uint32_t xseq_1_reg[16];
- uint32_t rseq_gp_reg[128];
- uint32_t rseq_0_reg[32];
- uint32_t rseq_1_reg[16];
- uint32_t rseq_2_reg[16];
- uint32_t aseq_gp_reg[128];
- uint32_t aseq_0_reg[32];
- uint32_t aseq_1_reg[16];
- uint32_t aseq_2_reg[16];
- uint32_t cmd_dma_reg[16];
- uint32_t req0_dma_reg[15];
- uint32_t resp0_dma_reg[15];
- uint32_t req1_dma_reg[15];
- uint32_t xmt0_dma_reg[32];
- uint32_t xmt1_dma_reg[32];
- uint32_t xmt2_dma_reg[32];
- uint32_t xmt3_dma_reg[32];
- uint32_t xmt4_dma_reg[32];
- uint32_t xmt_data_dma_reg[16];
- uint32_t rcvt0_data_dma_reg[32];
- uint32_t rcvt1_data_dma_reg[32];
- uint32_t risc_gp_reg[128];
- uint32_t lmc_reg[128];
- uint32_t fpm_hdw_reg[224];
- uint32_t fb_hdw_reg[208];
- uint32_t code_ram[0x2000];
- uint32_t ext_mem[1];
+ __be32 host_status;
+ __be32 host_risc_reg[32];
+ __be32 pcie_regs[4];
+ __be32 host_reg[32];
+ __be32 shadow_reg[11];
+ __be32 risc_io_reg;
+ __be16 mailbox_reg[32];
+ __be32 xseq_gp_reg[128];
+ __be32 xseq_0_reg[48];
+ __be32 xseq_1_reg[16];
+ __be32 rseq_gp_reg[128];
+ __be32 rseq_0_reg[32];
+ __be32 rseq_1_reg[16];
+ __be32 rseq_2_reg[16];
+ __be32 aseq_gp_reg[128];
+ __be32 aseq_0_reg[32];
+ __be32 aseq_1_reg[16];
+ __be32 aseq_2_reg[16];
+ __be32 cmd_dma_reg[16];
+ __be32 req0_dma_reg[15];
+ __be32 resp0_dma_reg[15];
+ __be32 req1_dma_reg[15];
+ __be32 xmt0_dma_reg[32];
+ __be32 xmt1_dma_reg[32];
+ __be32 xmt2_dma_reg[32];
+ __be32 xmt3_dma_reg[32];
+ __be32 xmt4_dma_reg[32];
+ __be32 xmt_data_dma_reg[16];
+ __be32 rcvt0_data_dma_reg[32];
+ __be32 rcvt1_data_dma_reg[32];
+ __be32 risc_gp_reg[128];
+ __be32 lmc_reg[128];
+ __be32 fpm_hdw_reg[224];
+ __be32 fb_hdw_reg[208];
+ __be32 code_ram[0x2000];
+ __be32 ext_mem[1];
};
struct qla83xx_fw_dump {
- uint32_t host_status;
- uint32_t host_risc_reg[48];
- uint32_t pcie_regs[4];
- uint32_t host_reg[32];
- uint32_t shadow_reg[11];
- uint32_t risc_io_reg;
- uint16_t mailbox_reg[32];
- uint32_t xseq_gp_reg[256];
- uint32_t xseq_0_reg[48];
- uint32_t xseq_1_reg[16];
- uint32_t xseq_2_reg[16];
- uint32_t rseq_gp_reg[256];
- uint32_t rseq_0_reg[32];
- uint32_t rseq_1_reg[16];
- uint32_t rseq_2_reg[16];
- uint32_t rseq_3_reg[16];
- uint32_t aseq_gp_reg[256];
- uint32_t aseq_0_reg[32];
- uint32_t aseq_1_reg[16];
- uint32_t aseq_2_reg[16];
- uint32_t aseq_3_reg[16];
- uint32_t cmd_dma_reg[64];
- uint32_t req0_dma_reg[15];
- uint32_t resp0_dma_reg[15];
- uint32_t req1_dma_reg[15];
- uint32_t xmt0_dma_reg[32];
- uint32_t xmt1_dma_reg[32];
- uint32_t xmt2_dma_reg[32];
- uint32_t xmt3_dma_reg[32];
- uint32_t xmt4_dma_reg[32];
- uint32_t xmt_data_dma_reg[16];
- uint32_t rcvt0_data_dma_reg[32];
- uint32_t rcvt1_data_dma_reg[32];
- uint32_t risc_gp_reg[128];
- uint32_t lmc_reg[128];
- uint32_t fpm_hdw_reg[256];
- uint32_t rq0_array_reg[256];
- uint32_t rq1_array_reg[256];
- uint32_t rp0_array_reg[256];
- uint32_t rp1_array_reg[256];
- uint32_t queue_control_reg[16];
- uint32_t fb_hdw_reg[432];
- uint32_t at0_array_reg[128];
- uint32_t code_ram[0x2400];
- uint32_t ext_mem[1];
+ __be32 host_status;
+ __be32 host_risc_reg[48];
+ __be32 pcie_regs[4];
+ __be32 host_reg[32];
+ __be32 shadow_reg[11];
+ __be32 risc_io_reg;
+ __be16 mailbox_reg[32];
+ __be32 xseq_gp_reg[256];
+ __be32 xseq_0_reg[48];
+ __be32 xseq_1_reg[16];
+ __be32 xseq_2_reg[16];
+ __be32 rseq_gp_reg[256];
+ __be32 rseq_0_reg[32];
+ __be32 rseq_1_reg[16];
+ __be32 rseq_2_reg[16];
+ __be32 rseq_3_reg[16];
+ __be32 aseq_gp_reg[256];
+ __be32 aseq_0_reg[32];
+ __be32 aseq_1_reg[16];
+ __be32 aseq_2_reg[16];
+ __be32 aseq_3_reg[16];
+ __be32 cmd_dma_reg[64];
+ __be32 req0_dma_reg[15];
+ __be32 resp0_dma_reg[15];
+ __be32 req1_dma_reg[15];
+ __be32 xmt0_dma_reg[32];
+ __be32 xmt1_dma_reg[32];
+ __be32 xmt2_dma_reg[32];
+ __be32 xmt3_dma_reg[32];
+ __be32 xmt4_dma_reg[32];
+ __be32 xmt_data_dma_reg[16];
+ __be32 rcvt0_data_dma_reg[32];
+ __be32 rcvt1_data_dma_reg[32];
+ __be32 risc_gp_reg[128];
+ __be32 lmc_reg[128];
+ __be32 fpm_hdw_reg[256];
+ __be32 rq0_array_reg[256];
+ __be32 rq1_array_reg[256];
+ __be32 rp0_array_reg[256];
+ __be32 rp1_array_reg[256];
+ __be32 queue_control_reg[16];
+ __be32 fb_hdw_reg[432];
+ __be32 at0_array_reg[128];
+ __be32 code_ram[0x2400];
+ __be32 ext_mem[1];
};
#define EFT_NUM_BUFFERS 4
@@ -223,44 +223,45 @@
#define fce_calc_size(b) ((FCE_BYTES_PER_BUFFER) * (b))
struct qla2xxx_fce_chain {
- uint32_t type;
- uint32_t chain_size;
+ __be32 type;
+ __be32 chain_size;
- uint32_t size;
- uint32_t addr_l;
- uint32_t addr_h;
- uint32_t eregs[8];
+ __be32 size;
+ __be32 addr_l;
+ __be32 addr_h;
+ __be32 eregs[8];
};
/* used by exchange off load and extended login offload */
struct qla2xxx_offld_chain {
- uint32_t type;
- uint32_t chain_size;
+ __be32 type;
+ __be32 chain_size;
- uint32_t size;
- u64 addr;
+ __be32 size;
+ __be32 reserved;
+ __be64 addr;
};
struct qla2xxx_mq_chain {
- uint32_t type;
- uint32_t chain_size;
+ __be32 type;
+ __be32 chain_size;
- uint32_t count;
- uint32_t qregs[4 * QLA_MQ_SIZE];
+ __be32 count;
+ __be32 qregs[4 * QLA_MQ_SIZE];
};
struct qla2xxx_mqueue_header {
- uint32_t queue;
+ __be32 queue;
#define TYPE_REQUEST_QUEUE 0x1
#define TYPE_RESPONSE_QUEUE 0x2
#define TYPE_ATIO_QUEUE 0x3
- uint32_t number;
- uint32_t size;
+ __be32 number;
+ __be32 size;
};
struct qla2xxx_mqueue_chain {
- uint32_t type;
- uint32_t chain_size;
+ __be32 type;
+ __be32 chain_size;
};
#define DUMP_CHAIN_VARIANT 0x80000000
@@ -273,28 +274,28 @@
struct qla2xxx_fw_dump {
uint8_t signature[4];
- uint32_t version;
+ __be32 version;
- uint32_t fw_major_version;
- uint32_t fw_minor_version;
- uint32_t fw_subminor_version;
- uint32_t fw_attributes;
+ __be32 fw_major_version;
+ __be32 fw_minor_version;
+ __be32 fw_subminor_version;
+ __be32 fw_attributes;
- uint32_t vendor;
- uint32_t device;
- uint32_t subsystem_vendor;
- uint32_t subsystem_device;
+ __be32 vendor;
+ __be32 device;
+ __be32 subsystem_vendor;
+ __be32 subsystem_device;
- uint32_t fixed_size;
- uint32_t mem_size;
- uint32_t req_q_size;
- uint32_t rsp_q_size;
+ __be32 fixed_size;
+ __be32 mem_size;
+ __be32 req_q_size;
+ __be32 rsp_q_size;
- uint32_t eft_size;
- uint32_t eft_addr_l;
- uint32_t eft_addr_h;
+ __be32 eft_size;
+ __be32 eft_addr_l;
+ __be32 eft_addr_h;
- uint32_t header_size;
+ __be32 header_size;
union {
struct qla2100_fw_dump isp21;
@@ -369,7 +370,7 @@
extern int qla27xx_dump_mpi_ram(struct qla_hw_data *, uint32_t, uint32_t *,
uint32_t, void **);
-extern int qla24xx_dump_ram(struct qla_hw_data *, uint32_t, uint32_t *,
+extern int qla24xx_dump_ram(struct qla_hw_data *, uint32_t, __be32 *,
uint32_t, void **);
extern void qla24xx_pause_risc(struct device_reg_24xx __iomem *,
struct qla_hw_data *);
@@ -378,5 +379,8 @@
static inline int
ql_mask_match(uint level)
{
+ if (ql2xextended_error_logging == 1)
+ ql2xextended_error_logging = QL_DBG_DEFAULT1_MASK;
+
return (level & ql2xextended_error_logging) == level;
}
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 7c22f8e..e1fd91a 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#ifndef __QLA_DEF_H
#define __QLA_DEF_H
@@ -34,6 +33,8 @@
#include <scsi/scsi_transport_fc.h>
#include <scsi/scsi_bsg_fc.h>
+#include <uapi/scsi/fc/fc_els.h>
+
/* Big endian Fibre Channel S_ID (source ID) or D_ID (destination ID). */
typedef struct {
uint8_t domain;
@@ -119,21 +120,59 @@
#define LSD(x) ((uint32_t)((uint64_t)(x)))
#define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16))
-#define MAKE_HANDLE(x, y) ((uint32_t)((((uint32_t)(x)) << 16) | (uint32_t)(y)))
+static inline uint32_t make_handle(uint16_t x, uint16_t y)
+{
+ return ((uint32_t)x << 16) | y;
+}
/*
* I/O register
*/
-#define RD_REG_BYTE(addr) readb(addr)
-#define RD_REG_WORD(addr) readw(addr)
-#define RD_REG_DWORD(addr) readl(addr)
-#define RD_REG_BYTE_RELAXED(addr) readb_relaxed(addr)
-#define RD_REG_WORD_RELAXED(addr) readw_relaxed(addr)
-#define RD_REG_DWORD_RELAXED(addr) readl_relaxed(addr)
-#define WRT_REG_BYTE(addr, data) writeb(data, addr)
-#define WRT_REG_WORD(addr, data) writew(data, addr)
-#define WRT_REG_DWORD(addr, data) writel(data, addr)
+static inline u8 rd_reg_byte(const volatile u8 __iomem *addr)
+{
+ return readb(addr);
+}
+
+static inline u16 rd_reg_word(const volatile __le16 __iomem *addr)
+{
+ return readw(addr);
+}
+
+static inline u32 rd_reg_dword(const volatile __le32 __iomem *addr)
+{
+ return readl(addr);
+}
+
+static inline u8 rd_reg_byte_relaxed(const volatile u8 __iomem *addr)
+{
+ return readb_relaxed(addr);
+}
+
+static inline u16 rd_reg_word_relaxed(const volatile __le16 __iomem *addr)
+{
+ return readw_relaxed(addr);
+}
+
+static inline u32 rd_reg_dword_relaxed(const volatile __le32 __iomem *addr)
+{
+ return readl_relaxed(addr);
+}
+
+static inline void wrt_reg_byte(volatile u8 __iomem *addr, u8 data)
+{
+ return writeb(data, addr);
+}
+
+static inline void wrt_reg_word(volatile __le16 __iomem *addr, u16 data)
+{
+ return writew(data, addr);
+}
+
+static inline void wrt_reg_dword(volatile __le32 __iomem *addr, u32 data)
+{
+ return writel(data, addr);
+}
/*
* ISP83XX specific remote register addresses
@@ -414,7 +453,7 @@
struct els_plogi_payload {
uint8_t opcode;
uint8_t rsvd[3];
- uint8_t data[112];
+ __be32 data[112 / 4];
};
struct ct_arg {
@@ -466,7 +505,7 @@
u32 rx_size;
dma_addr_t els_plogi_pyld_dma;
dma_addr_t els_resp_pyld_dma;
- uint32_t fw_status[3];
+ __le32 fw_status[3];
__le16 comp_status;
__le16 len;
} els_plogi;
@@ -517,8 +556,8 @@
#define MAX_IOCB_MB_REG 28
#define SIZEOF_IOCB_MB_REG (MAX_IOCB_MB_REG * sizeof(uint16_t))
struct {
- __le16 in_mb[MAX_IOCB_MB_REG]; /* from FW */
- __le16 out_mb[MAX_IOCB_MB_REG]; /* to FW */
+ u16 in_mb[MAX_IOCB_MB_REG]; /* from FW */
+ u16 out_mb[MAX_IOCB_MB_REG]; /* to FW */
void *out, *in;
dma_addr_t out_dma, in_dma;
struct completion comp;
@@ -529,7 +568,7 @@
} nack;
struct {
__le16 comp_status;
- uint16_t rsp_pyld_len;
+ __le16 rsp_pyld_len;
uint8_t aen_op;
void *desc;
@@ -584,6 +623,12 @@
TYPE_TGT_TMCMD, /* task management */
};
+struct iocb_resource {
+ u8 res_type;
+ u8 pad;
+ u16 iocb_cnt;
+};
+
typedef struct srb {
/*
* Do not move cmd_type field, it needs to
@@ -591,15 +636,13 @@
*/
uint8_t cmd_type;
uint8_t pad[3];
+ struct iocb_resource iores;
struct kref cmd_kref; /* need to migrate ref_count over to this */
void *priv;
wait_queue_head_t nvme_ls_waitq;
struct fc_port *fcport;
struct scsi_qla_host *vha;
unsigned int start_timer:1;
- unsigned int abort:1;
- unsigned int aborted:1;
- unsigned int completed:1;
uint32_t handle;
uint16_t flags;
@@ -663,23 +706,23 @@
* ISP I/O Register Set structure definitions.
*/
struct device_reg_2xxx {
- uint16_t flash_address; /* Flash BIOS address */
- uint16_t flash_data; /* Flash BIOS data */
- uint16_t unused_1[1]; /* Gap */
- uint16_t ctrl_status; /* Control/Status */
+ __le16 flash_address; /* Flash BIOS address */
+ __le16 flash_data; /* Flash BIOS data */
+ __le16 unused_1[1]; /* Gap */
+ __le16 ctrl_status; /* Control/Status */
#define CSR_FLASH_64K_BANK BIT_3 /* Flash upper 64K bank select */
#define CSR_FLASH_ENABLE BIT_1 /* Flash BIOS Read/Write enable */
#define CSR_ISP_SOFT_RESET BIT_0 /* ISP soft reset */
- uint16_t ictrl; /* Interrupt control */
+ __le16 ictrl; /* Interrupt control */
#define ICR_EN_INT BIT_15 /* ISP enable interrupts. */
#define ICR_EN_RISC BIT_3 /* ISP enable RISC interrupts. */
- uint16_t istatus; /* Interrupt status */
+ __le16 istatus; /* Interrupt status */
#define ISR_RISC_INT BIT_3 /* RISC interrupt */
- uint16_t semaphore; /* Semaphore */
- uint16_t nvram; /* NVRAM register. */
+ __le16 semaphore; /* Semaphore */
+ __le16 nvram; /* NVRAM register. */
#define NVR_DESELECT 0
#define NVR_BUSY BIT_15
#define NVR_WRT_ENABLE BIT_14 /* Write enable */
@@ -693,80 +736,80 @@
union {
struct {
- uint16_t mailbox0;
- uint16_t mailbox1;
- uint16_t mailbox2;
- uint16_t mailbox3;
- uint16_t mailbox4;
- uint16_t mailbox5;
- uint16_t mailbox6;
- uint16_t mailbox7;
- uint16_t unused_2[59]; /* Gap */
+ __le16 mailbox0;
+ __le16 mailbox1;
+ __le16 mailbox2;
+ __le16 mailbox3;
+ __le16 mailbox4;
+ __le16 mailbox5;
+ __le16 mailbox6;
+ __le16 mailbox7;
+ __le16 unused_2[59]; /* Gap */
} __attribute__((packed)) isp2100;
struct {
/* Request Queue */
- uint16_t req_q_in; /* In-Pointer */
- uint16_t req_q_out; /* Out-Pointer */
+ __le16 req_q_in; /* In-Pointer */
+ __le16 req_q_out; /* Out-Pointer */
/* Response Queue */
- uint16_t rsp_q_in; /* In-Pointer */
- uint16_t rsp_q_out; /* Out-Pointer */
+ __le16 rsp_q_in; /* In-Pointer */
+ __le16 rsp_q_out; /* Out-Pointer */
/* RISC to Host Status */
- uint32_t host_status;
+ __le32 host_status;
#define HSR_RISC_INT BIT_15 /* RISC interrupt */
#define HSR_RISC_PAUSED BIT_8 /* RISC Paused */
/* Host to Host Semaphore */
- uint16_t host_semaphore;
- uint16_t unused_3[17]; /* Gap */
- uint16_t mailbox0;
- uint16_t mailbox1;
- uint16_t mailbox2;
- uint16_t mailbox3;
- uint16_t mailbox4;
- uint16_t mailbox5;
- uint16_t mailbox6;
- uint16_t mailbox7;
- uint16_t mailbox8;
- uint16_t mailbox9;
- uint16_t mailbox10;
- uint16_t mailbox11;
- uint16_t mailbox12;
- uint16_t mailbox13;
- uint16_t mailbox14;
- uint16_t mailbox15;
- uint16_t mailbox16;
- uint16_t mailbox17;
- uint16_t mailbox18;
- uint16_t mailbox19;
- uint16_t mailbox20;
- uint16_t mailbox21;
- uint16_t mailbox22;
- uint16_t mailbox23;
- uint16_t mailbox24;
- uint16_t mailbox25;
- uint16_t mailbox26;
- uint16_t mailbox27;
- uint16_t mailbox28;
- uint16_t mailbox29;
- uint16_t mailbox30;
- uint16_t mailbox31;
- uint16_t fb_cmd;
- uint16_t unused_4[10]; /* Gap */
+ __le16 host_semaphore;
+ __le16 unused_3[17]; /* Gap */
+ __le16 mailbox0;
+ __le16 mailbox1;
+ __le16 mailbox2;
+ __le16 mailbox3;
+ __le16 mailbox4;
+ __le16 mailbox5;
+ __le16 mailbox6;
+ __le16 mailbox7;
+ __le16 mailbox8;
+ __le16 mailbox9;
+ __le16 mailbox10;
+ __le16 mailbox11;
+ __le16 mailbox12;
+ __le16 mailbox13;
+ __le16 mailbox14;
+ __le16 mailbox15;
+ __le16 mailbox16;
+ __le16 mailbox17;
+ __le16 mailbox18;
+ __le16 mailbox19;
+ __le16 mailbox20;
+ __le16 mailbox21;
+ __le16 mailbox22;
+ __le16 mailbox23;
+ __le16 mailbox24;
+ __le16 mailbox25;
+ __le16 mailbox26;
+ __le16 mailbox27;
+ __le16 mailbox28;
+ __le16 mailbox29;
+ __le16 mailbox30;
+ __le16 mailbox31;
+ __le16 fb_cmd;
+ __le16 unused_4[10]; /* Gap */
} __attribute__((packed)) isp2300;
} u;
- uint16_t fpm_diag_config;
- uint16_t unused_5[0x4]; /* Gap */
- uint16_t risc_hw;
- uint16_t unused_5_1; /* Gap */
- uint16_t pcr; /* Processor Control Register. */
- uint16_t unused_6[0x5]; /* Gap */
- uint16_t mctr; /* Memory Configuration and Timing. */
- uint16_t unused_7[0x3]; /* Gap */
- uint16_t fb_cmd_2100; /* Unused on 23XX */
- uint16_t unused_8[0x3]; /* Gap */
- uint16_t hccr; /* Host command & control register. */
+ __le16 fpm_diag_config;
+ __le16 unused_5[0x4]; /* Gap */
+ __le16 risc_hw;
+ __le16 unused_5_1; /* Gap */
+ __le16 pcr; /* Processor Control Register. */
+ __le16 unused_6[0x5]; /* Gap */
+ __le16 mctr; /* Memory Configuration and Timing. */
+ __le16 unused_7[0x3]; /* Gap */
+ __le16 fb_cmd_2100; /* Unused on 23XX */
+ __le16 unused_8[0x3]; /* Gap */
+ __le16 hccr; /* Host command & control register. */
#define HCCR_HOST_INT BIT_7 /* Host interrupt bit */
#define HCCR_RISC_PAUSE BIT_5 /* Pause mode bit */
/* HCCR commands */
@@ -779,9 +822,9 @@
#define HCCR_DISABLE_PARITY_PAUSE 0x4001 /* Disable parity error RISC pause. */
#define HCCR_ENABLE_PARITY 0xA000 /* Enable PARITY interrupt */
- uint16_t unused_9[5]; /* Gap */
- uint16_t gpiod; /* GPIO Data register. */
- uint16_t gpioe; /* GPIO Enable register. */
+ __le16 unused_9[5]; /* Gap */
+ __le16 gpiod; /* GPIO Data register. */
+ __le16 gpioe; /* GPIO Enable register. */
#define GPIO_LED_MASK 0x00C0
#define GPIO_LED_GREEN_OFF_AMBER_OFF 0x0000
#define GPIO_LED_GREEN_ON_AMBER_OFF 0x0040
@@ -793,95 +836,95 @@
union {
struct {
- uint16_t unused_10[8]; /* Gap */
- uint16_t mailbox8;
- uint16_t mailbox9;
- uint16_t mailbox10;
- uint16_t mailbox11;
- uint16_t mailbox12;
- uint16_t mailbox13;
- uint16_t mailbox14;
- uint16_t mailbox15;
- uint16_t mailbox16;
- uint16_t mailbox17;
- uint16_t mailbox18;
- uint16_t mailbox19;
- uint16_t mailbox20;
- uint16_t mailbox21;
- uint16_t mailbox22;
- uint16_t mailbox23; /* Also probe reg. */
+ __le16 unused_10[8]; /* Gap */
+ __le16 mailbox8;
+ __le16 mailbox9;
+ __le16 mailbox10;
+ __le16 mailbox11;
+ __le16 mailbox12;
+ __le16 mailbox13;
+ __le16 mailbox14;
+ __le16 mailbox15;
+ __le16 mailbox16;
+ __le16 mailbox17;
+ __le16 mailbox18;
+ __le16 mailbox19;
+ __le16 mailbox20;
+ __le16 mailbox21;
+ __le16 mailbox22;
+ __le16 mailbox23; /* Also probe reg. */
} __attribute__((packed)) isp2200;
} u_end;
};
struct device_reg_25xxmq {
- uint32_t req_q_in;
- uint32_t req_q_out;
- uint32_t rsp_q_in;
- uint32_t rsp_q_out;
- uint32_t atio_q_in;
- uint32_t atio_q_out;
+ __le32 req_q_in;
+ __le32 req_q_out;
+ __le32 rsp_q_in;
+ __le32 rsp_q_out;
+ __le32 atio_q_in;
+ __le32 atio_q_out;
};
struct device_reg_fx00 {
- uint32_t mailbox0; /* 00 */
- uint32_t mailbox1; /* 04 */
- uint32_t mailbox2; /* 08 */
- uint32_t mailbox3; /* 0C */
- uint32_t mailbox4; /* 10 */
- uint32_t mailbox5; /* 14 */
- uint32_t mailbox6; /* 18 */
- uint32_t mailbox7; /* 1C */
- uint32_t mailbox8; /* 20 */
- uint32_t mailbox9; /* 24 */
- uint32_t mailbox10; /* 28 */
- uint32_t mailbox11;
- uint32_t mailbox12;
- uint32_t mailbox13;
- uint32_t mailbox14;
- uint32_t mailbox15;
- uint32_t mailbox16;
- uint32_t mailbox17;
- uint32_t mailbox18;
- uint32_t mailbox19;
- uint32_t mailbox20;
- uint32_t mailbox21;
- uint32_t mailbox22;
- uint32_t mailbox23;
- uint32_t mailbox24;
- uint32_t mailbox25;
- uint32_t mailbox26;
- uint32_t mailbox27;
- uint32_t mailbox28;
- uint32_t mailbox29;
- uint32_t mailbox30;
- uint32_t mailbox31;
- uint32_t aenmailbox0;
- uint32_t aenmailbox1;
- uint32_t aenmailbox2;
- uint32_t aenmailbox3;
- uint32_t aenmailbox4;
- uint32_t aenmailbox5;
- uint32_t aenmailbox6;
- uint32_t aenmailbox7;
+ __le32 mailbox0; /* 00 */
+ __le32 mailbox1; /* 04 */
+ __le32 mailbox2; /* 08 */
+ __le32 mailbox3; /* 0C */
+ __le32 mailbox4; /* 10 */
+ __le32 mailbox5; /* 14 */
+ __le32 mailbox6; /* 18 */
+ __le32 mailbox7; /* 1C */
+ __le32 mailbox8; /* 20 */
+ __le32 mailbox9; /* 24 */
+ __le32 mailbox10; /* 28 */
+ __le32 mailbox11;
+ __le32 mailbox12;
+ __le32 mailbox13;
+ __le32 mailbox14;
+ __le32 mailbox15;
+ __le32 mailbox16;
+ __le32 mailbox17;
+ __le32 mailbox18;
+ __le32 mailbox19;
+ __le32 mailbox20;
+ __le32 mailbox21;
+ __le32 mailbox22;
+ __le32 mailbox23;
+ __le32 mailbox24;
+ __le32 mailbox25;
+ __le32 mailbox26;
+ __le32 mailbox27;
+ __le32 mailbox28;
+ __le32 mailbox29;
+ __le32 mailbox30;
+ __le32 mailbox31;
+ __le32 aenmailbox0;
+ __le32 aenmailbox1;
+ __le32 aenmailbox2;
+ __le32 aenmailbox3;
+ __le32 aenmailbox4;
+ __le32 aenmailbox5;
+ __le32 aenmailbox6;
+ __le32 aenmailbox7;
/* Request Queue. */
- uint32_t req_q_in; /* A0 - Request Queue In-Pointer */
- uint32_t req_q_out; /* A4 - Request Queue Out-Pointer */
+ __le32 req_q_in; /* A0 - Request Queue In-Pointer */
+ __le32 req_q_out; /* A4 - Request Queue Out-Pointer */
/* Response Queue. */
- uint32_t rsp_q_in; /* A8 - Response Queue In-Pointer */
- uint32_t rsp_q_out; /* AC - Response Queue Out-Pointer */
+ __le32 rsp_q_in; /* A8 - Response Queue In-Pointer */
+ __le32 rsp_q_out; /* AC - Response Queue Out-Pointer */
/* Init values shadowed on FW Up Event */
- uint32_t initval0; /* B0 */
- uint32_t initval1; /* B4 */
- uint32_t initval2; /* B8 */
- uint32_t initval3; /* BC */
- uint32_t initval4; /* C0 */
- uint32_t initval5; /* C4 */
- uint32_t initval6; /* C8 */
- uint32_t initval7; /* CC */
- uint32_t fwheartbeat; /* D0 */
- uint32_t pseudoaen; /* D4 */
+ __le32 initval0; /* B0 */
+ __le32 initval1; /* B4 */
+ __le32 initval2; /* B8 */
+ __le32 initval3; /* BC */
+ __le32 initval4; /* C0 */
+ __le32 initval5; /* C4 */
+ __le32 initval6; /* C8 */
+ __le32 initval7; /* CC */
+ __le32 fwheartbeat; /* D0 */
+ __le32 pseudoaen; /* D4 */
};
@@ -921,18 +964,18 @@
&(reg)->u_end.isp2200.mailbox8 + (num) - 8) : \
&(reg)->u.isp2300.mailbox0 + (num))
#define RD_MAILBOX_REG(ha, reg, num) \
- RD_REG_WORD(MAILBOX_REG(ha, reg, num))
+ rd_reg_word(MAILBOX_REG(ha, reg, num))
#define WRT_MAILBOX_REG(ha, reg, num, data) \
- WRT_REG_WORD(MAILBOX_REG(ha, reg, num), data)
+ wrt_reg_word(MAILBOX_REG(ha, reg, num), data)
#define FB_CMD_REG(ha, reg) \
(IS_QLA2100(ha) || IS_QLA2200(ha) ? \
&(reg)->fb_cmd_2100 : \
&(reg)->u.isp2300.fb_cmd)
#define RD_FB_CMD_REG(ha, reg) \
- RD_REG_WORD(FB_CMD_REG(ha, reg))
+ rd_reg_word(FB_CMD_REG(ha, reg))
#define WRT_FB_CMD_REG(ha, reg, data) \
- WRT_REG_WORD(FB_CMD_REG(ha, reg), data)
+ wrt_reg_word(FB_CMD_REG(ha, reg), data)
typedef struct {
uint32_t out_mb; /* outbound from driver */
@@ -1018,6 +1061,7 @@
#define MBA_LIP_F8 0x8016 /* Received a LIP F8. */
#define MBA_LOOP_INIT_ERR 0x8017 /* Loop Initialization Error. */
#define MBA_FABRIC_AUTH_REQ 0x801b /* Fabric Authentication Required. */
+#define MBA_CONGN_NOTI_RECV 0x801e /* Congestion Notification Received */
#define MBA_SCSI_COMPLETION 0x8020 /* SCSI Command Complete. */
#define MBA_CTIO_COMPLETION 0x8021 /* CTIO Complete. */
#define MBA_IP_COMPLETION 0x8022 /* IP Transmit Command Complete. */
@@ -1049,6 +1093,7 @@
#define MBA_TEMPERATURE_ALERT 0x8070 /* Temperature Alert */
#define MBA_DPORT_DIAGNOSTICS 0x8080 /* D-port Diagnostics */
#define MBA_TRANS_INSERT 0x8130 /* Transceiver Insertion */
+#define MBA_TRANS_REMOVE 0x8131 /* Transceiver Removal */
#define MBA_FW_INIT_FAILURE 0x8401 /* Firmware initialization failure */
#define MBA_MIRROR_LUN_CHANGE 0x8402 /* Mirror LUN State Change
Notification */
@@ -1134,6 +1179,7 @@
#define MBC_GET_FIRMWARE_OPTION 0x28 /* Get Firmware Options. */
#define MBC_GET_MEM_OFFLOAD_CNTRL_STAT 0x34 /* Memory Offload ctrl/Stat*/
#define MBC_SET_FIRMWARE_OPTION 0x38 /* Set Firmware Options. */
+#define MBC_SET_GET_FC_LED_CONFIG 0x3b /* Set/Get FC LED config */
#define MBC_LOOP_PORT_BYPASS 0x40 /* Loop Port Bypass. */
#define MBC_LOOP_PORT_ENABLE 0x41 /* Loop Port Enable. */
#define MBC_GET_RESOURCE_COUNTS 0x42 /* Get Resource Counts. */
@@ -1260,10 +1306,14 @@
#define MBX_1 BIT_1
#define MBX_0 BIT_0
+#define RNID_TYPE_ELS_CMD 0x5
#define RNID_TYPE_PORT_LOGIN 0x7
+#define RNID_BUFFER_CREDITS 0x8
#define RNID_TYPE_SET_VERSION 0x9
#define RNID_TYPE_ASIC_TEMP 0xC
+#define ELS_CMD_MAP_SIZE 32
+
/*
* Firmware state codes from get firmware state mailbox command
*/
@@ -1309,7 +1359,7 @@
uint8_t port_id[4];
uint8_t node_name[WWN_SIZE];
uint8_t port_name[WWN_SIZE];
- uint16_t execution_throttle;
+ __le16 execution_throttle;
uint16_t execution_count;
uint8_t reset_count;
uint8_t reserved_2;
@@ -1395,9 +1445,9 @@
*/
uint8_t firmware_options[2];
- uint16_t frame_payload_size;
- uint16_t max_iocb_allocation;
- uint16_t execution_throttle;
+ __le16 frame_payload_size;
+ __le16 max_iocb_allocation;
+ __le16 execution_throttle;
uint8_t retry_count;
uint8_t retry_delay; /* unused */
uint8_t port_name[WWN_SIZE]; /* Big endian. */
@@ -1406,17 +1456,17 @@
uint8_t login_timeout;
uint8_t node_name[WWN_SIZE]; /* Big endian. */
- uint16_t request_q_outpointer;
- uint16_t response_q_inpointer;
- uint16_t request_q_length;
- uint16_t response_q_length;
- __le64 request_q_address __packed;
- __le64 response_q_address __packed;
+ __le16 request_q_outpointer;
+ __le16 response_q_inpointer;
+ __le16 request_q_length;
+ __le16 response_q_length;
+ __le64 request_q_address __packed;
+ __le64 response_q_address __packed;
- uint16_t lun_enables;
+ __le16 lun_enables;
uint8_t command_resource_count;
uint8_t immediate_notify_resource_count;
- uint16_t timeout;
+ __le16 timeout;
uint8_t reserved_2[2];
/*
@@ -1467,6 +1517,25 @@
uint8_t reserved_3[26];
} init_cb_t;
+/* Special Features Control Block */
+struct init_sf_cb {
+ uint8_t format;
+ uint8_t reserved0;
+ /*
+ * BIT 15-14 = Reserved
+ * BIT_13 = SAN Congestion Management (1 - Enabled, 0 - Disabled)
+ * BIT_12 = Remote Write Optimization (1 - Enabled, 0 - Disabled)
+ * BIT 11-0 = Reserved
+ */
+ uint16_t flags;
+ uint8_t reserved1[32];
+ uint16_t discard_OHRB_timeout_value;
+ uint16_t remote_write_opt_queue_num;
+ uint8_t reserved2[40];
+ uint8_t scm_related_parameter[16];
+ uint8_t reserved3[32];
+};
+
/*
* Get Link Status mailbox command return buffer.
*/
@@ -1474,47 +1543,44 @@
#define GLSO_USE_DID BIT_3
struct link_statistics {
- uint32_t link_fail_cnt;
- uint32_t loss_sync_cnt;
- uint32_t loss_sig_cnt;
- uint32_t prim_seq_err_cnt;
- uint32_t inval_xmit_word_cnt;
- uint32_t inval_crc_cnt;
- uint32_t lip_cnt;
- uint32_t link_up_cnt;
- uint32_t link_down_loop_init_tmo;
- uint32_t link_down_los;
- uint32_t link_down_loss_rcv_clk;
+ __le32 link_fail_cnt;
+ __le32 loss_sync_cnt;
+ __le32 loss_sig_cnt;
+ __le32 prim_seq_err_cnt;
+ __le32 inval_xmit_word_cnt;
+ __le32 inval_crc_cnt;
+ __le32 lip_cnt;
+ __le32 link_up_cnt;
+ __le32 link_down_loop_init_tmo;
+ __le32 link_down_los;
+ __le32 link_down_loss_rcv_clk;
uint32_t reserved0[5];
- uint32_t port_cfg_chg;
+ __le32 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;
+ __le32 rsp_q_full;
+ __le32 atio_q_full;
+ __le32 drop_ae;
+ __le32 els_proto_err;
+ __le32 reserved2;
+ __le32 tx_frames;
+ __le32 rx_frames;
+ __le32 discarded_frames;
+ __le32 dropped_frames;
uint32_t reserved3;
- uint32_t nos_rcvd;
+ __le32 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;
+ __le32 tx_prjt;
+ __le32 rcv_exfail;
+ __le32 rcv_abts;
+ __le32 seq_frm_miss;
+ __le32 corr_err;
+ __le32 mb_rqst;
+ __le32 nport_full;
+ __le32 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;
+ __le64 fpm_recv_word_cnt;
+ __le64 fpm_disc_word_cnt;
+ __le64 fpm_xmit_word_cnt;
uint32_t reserved6[70];
};
@@ -1566,9 +1632,9 @@
*/
uint8_t firmware_options[2];
- uint16_t frame_payload_size;
- uint16_t max_iocb_allocation;
- uint16_t execution_throttle;
+ __le16 frame_payload_size;
+ __le16 max_iocb_allocation;
+ __le16 execution_throttle;
uint8_t retry_count;
uint8_t retry_delay; /* unused */
uint8_t port_name[WWN_SIZE]; /* Big endian. */
@@ -1692,7 +1758,7 @@
uint8_t reset_delay;
uint8_t port_down_retry_count;
uint8_t boot_id_number;
- uint16_t max_luns_per_target;
+ __le16 max_luns_per_target;
uint8_t fcode_boot_port_name[WWN_SIZE];
uint8_t alternate_port_name[WWN_SIZE];
uint8_t alternate_node_name[WWN_SIZE];
@@ -1798,7 +1864,7 @@
};
typedef union {
- uint16_t extended;
+ __le16 extended;
struct {
uint8_t reserved;
uint8_t standard;
@@ -1824,18 +1890,18 @@
uint8_t entry_status; /* Entry Status. */
uint32_t handle; /* System handle. */
target_id_t target; /* SCSI ID */
- uint16_t lun; /* SCSI LUN */
- uint16_t control_flags; /* Control flags. */
+ __le16 lun; /* SCSI LUN */
+ __le16 control_flags; /* Control flags. */
#define CF_WRITE BIT_6
#define CF_READ BIT_5
#define CF_SIMPLE_TAG BIT_3
#define CF_ORDERED_TAG BIT_2
#define CF_HEAD_TAG BIT_1
uint16_t reserved_1;
- uint16_t timeout; /* Command timeout. */
- uint16_t dseg_count; /* Data segment count. */
+ __le16 timeout; /* Command timeout. */
+ __le16 dseg_count; /* Data segment count. */
uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */
- uint32_t byte_count; /* Total byte count. */
+ __le32 byte_count; /* Total byte count. */
union {
struct dsd32 dsd32[3];
struct dsd64 dsd64[2];
@@ -1853,11 +1919,11 @@
uint8_t entry_status; /* Entry Status. */
uint32_t handle; /* System handle. */
target_id_t target; /* SCSI ID */
- uint16_t lun; /* SCSI LUN */
- uint16_t control_flags; /* Control flags. */
+ __le16 lun; /* SCSI LUN */
+ __le16 control_flags; /* Control flags. */
uint16_t reserved_1;
- uint16_t timeout; /* Command timeout. */
- uint16_t dseg_count; /* Data segment count. */
+ __le16 timeout; /* Command timeout. */
+ __le16 dseg_count; /* Data segment count. */
uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */
uint32_t byte_count; /* Total byte count. */
struct dsd64 dsd[2];
@@ -1919,7 +1985,7 @@
__le16 guard_seed; /* Initial Guard Seed */
__le16 prot_opts; /* Requested Data Protection Mode */
__le16 blk_size; /* Data size in bytes */
- uint16_t runt_blk_guard; /* Guard value for runt block (tape
+ __le16 runt_blk_guard; /* Guard value for runt block (tape
* only) */
__le32 byte_count; /* Total byte count/ total data
* transfer count */
@@ -1972,13 +2038,13 @@
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
uint32_t handle; /* System handle. */
- uint16_t scsi_status; /* SCSI status. */
- uint16_t comp_status; /* Completion status. */
- uint16_t state_flags; /* State flags. */
- uint16_t status_flags; /* Status flags. */
- uint16_t rsp_info_len; /* Response Info Length. */
- uint16_t req_sense_length; /* Request sense data length. */
- uint32_t residual_length; /* Residual transfer length. */
+ __le16 scsi_status; /* SCSI status. */
+ __le16 comp_status; /* Completion status. */
+ __le16 state_flags; /* State flags. */
+ __le16 status_flags; /* Status flags. */
+ __le16 rsp_info_len; /* Response Info Length. */
+ __le16 req_sense_length; /* Request sense data length. */
+ __le32 residual_length; /* Residual transfer length. */
uint8_t rsp_info[8]; /* FCP response information. */
uint8_t req_sense_data[32]; /* Request sense data. */
} sts_entry_t;
@@ -2110,8 +2176,8 @@
/* clear port changed, */
/* use sequence number. */
uint8_t reserved_1;
- uint16_t sequence_number; /* Sequence number of event */
- uint16_t lun; /* SCSI LUN */
+ __le16 sequence_number; /* Sequence number of event */
+ __le16 lun; /* SCSI LUN */
uint8_t reserved_2[48];
} mrk_entry_t;
@@ -2126,23 +2192,25 @@
uint8_t entry_status; /* Entry Status. */
uint32_t handle1; /* System handle. */
target_id_t loop_id;
- uint16_t status;
- uint16_t control_flags; /* Control flags. */
+ __le16 status;
+ __le16 control_flags; /* Control flags. */
uint16_t reserved2;
- uint16_t timeout;
- uint16_t cmd_dsd_count;
- uint16_t total_dsd_count;
+ __le16 timeout;
+ __le16 cmd_dsd_count;
+ __le16 total_dsd_count;
uint8_t type;
uint8_t r_ctl;
- uint16_t rx_id;
+ __le16 rx_id;
uint16_t reserved3;
uint32_t handle2;
- uint32_t rsp_bytecount;
- uint32_t req_bytecount;
+ __le32 rsp_bytecount;
+ __le32 req_bytecount;
struct dsd64 req_dsd;
struct dsd64 rsp_dsd;
} ms_iocb_entry_t;
+#define SCM_EDC_ACC_RECEIVED BIT_6
+#define SCM_RDF_ACC_RECEIVED BIT_7
/*
* ISP queue - Mailbox Command entry structure definition.
@@ -2166,20 +2234,20 @@
uint32_t handle;
target_id_t loop_id;
- uint16_t status;
- uint16_t state_flags;
- uint16_t status_flags;
+ __le16 status;
+ __le16 state_flags;
+ __le16 status_flags;
uint32_t sys_define2[2];
- uint16_t mb0;
- uint16_t mb1;
- uint16_t mb2;
- uint16_t mb3;
- uint16_t mb6;
- uint16_t mb7;
- uint16_t mb9;
- uint16_t mb10;
+ __le16 mb0;
+ __le16 mb1;
+ __le16 mb2;
+ __le16 mb3;
+ __le16 mb6;
+ __le16 mb7;
+ __le16 mb9;
+ __le16 mb10;
uint32_t reserved_2[2];
uint8_t node_name[WWN_SIZE];
uint8_t port_name[WWN_SIZE];
@@ -2201,52 +2269,52 @@
uint8_t entry_status; /* Entry Status. */
union {
struct {
- uint32_t sys_define_2; /* System defined. */
+ __le32 sys_define_2; /* System defined. */
target_id_t target;
- uint16_t lun;
+ __le16 lun;
uint8_t target_id;
uint8_t reserved_1;
- uint16_t status_modifier;
- uint16_t status;
- uint16_t task_flags;
- uint16_t seq_id;
- uint16_t srr_rx_id;
- uint32_t srr_rel_offs;
- uint16_t srr_ui;
+ __le16 status_modifier;
+ __le16 status;
+ __le16 task_flags;
+ __le16 seq_id;
+ __le16 srr_rx_id;
+ __le32 srr_rel_offs;
+ __le16 srr_ui;
#define SRR_IU_DATA_IN 0x1
#define SRR_IU_DATA_OUT 0x5
#define SRR_IU_STATUS 0x7
- uint16_t srr_ox_id;
+ __le16 srr_ox_id;
uint8_t reserved_2[28];
} isp2x;
struct {
uint32_t reserved;
- uint16_t nport_handle;
+ __le16 nport_handle;
uint16_t reserved_2;
- uint16_t flags;
+ __le16 flags;
#define NOTIFY24XX_FLAGS_GLOBAL_TPRLO BIT_1
#define NOTIFY24XX_FLAGS_PUREX_IOCB BIT_0
- uint16_t srr_rx_id;
- uint16_t status;
+ __le16 srr_rx_id;
+ __le16 status;
uint8_t status_subcode;
uint8_t fw_handle;
- uint32_t exchange_address;
- uint32_t srr_rel_offs;
- uint16_t srr_ui;
- uint16_t srr_ox_id;
+ __le32 exchange_address;
+ __le32 srr_rel_offs;
+ __le16 srr_ui;
+ __le16 srr_ox_id;
union {
struct {
uint8_t node_name[8];
} plogi; /* PLOGI/ADISC/PDISC */
struct {
/* PRLI word 3 bit 0-15 */
- uint16_t wd3_lo;
+ __le16 wd3_lo;
uint8_t resv0[6];
} prli;
struct {
uint8_t port_id[3];
uint8_t resv1;
- uint16_t nport_handle;
+ __le16 nport_handle;
uint16_t resv2;
} req_els;
} u;
@@ -2259,7 +2327,7 @@
} isp24;
} u;
uint16_t reserved_7;
- uint16_t ox_id;
+ __le16 ox_id;
} __packed;
#endif
@@ -2381,12 +2449,6 @@
struct list_head list;
struct scsi_qla_host *vha;
- uint8_t node_name[WWN_SIZE];
- uint8_t port_name[WWN_SIZE];
- port_id_t d_id;
- uint16_t loop_id;
- uint16_t old_loop_id;
-
unsigned int conf_compl_supported:1;
unsigned int deleted:2;
unsigned int free_pending:1;
@@ -2403,15 +2465,24 @@
unsigned int n2n_flag:1;
unsigned int explicit_logout:1;
unsigned int prli_pend_timer:1;
+ uint8_t nvme_flag;
+
+ uint8_t node_name[WWN_SIZE];
+ uint8_t port_name[WWN_SIZE];
+ port_id_t d_id;
+ uint16_t loop_id;
+ uint16_t old_loop_id;
struct completion nvme_del_done;
uint32_t nvme_prli_service_param;
+#define NVME_PRLI_SP_PI_CTRL BIT_9
+#define NVME_PRLI_SP_SLER BIT_8
#define NVME_PRLI_SP_CONF BIT_7
#define NVME_PRLI_SP_INITIATOR BIT_5
#define NVME_PRLI_SP_TARGET BIT_4
#define NVME_PRLI_SP_DISCOVERY BIT_3
#define NVME_PRLI_SP_FIRST_BURST BIT_0
- uint8_t nvme_flag;
+
uint32_t nvme_first_burst_size;
#define NVME_FLAG_REGISTERED 4
#define NVME_FLAG_DELETING 2
@@ -2482,10 +2553,14 @@
u8 last_login_state;
u16 n2n_link_reset_cnt;
u16 n2n_chip_reset;
+
+ struct dentry *dfs_rport_dir;
} fc_port_t;
-#define FC4_PRIORITY_NVME 0
-#define FC4_PRIORITY_FCP 1
+enum {
+ FC4_PRIORITY_NVME = 1,
+ FC4_PRIORITY_FCP = 2,
+};
#define QLA_FCPORT_SCAN 1
#define QLA_FCPORT_FOUND 2
@@ -2622,10 +2697,11 @@
#define GFF_ID_RSP_SIZE (16 + 128)
/*
- * HBA attribute types.
+ * FDMI HBA attribute types.
*/
-#define FDMI_HBA_ATTR_COUNT 9
-#define FDMIV2_HBA_ATTR_COUNT 17
+#define FDMI1_HBA_ATTR_COUNT 9
+#define FDMI2_HBA_ATTR_COUNT 17
+
#define FDMI_HBA_NODE_NAME 0x1
#define FDMI_HBA_MANUFACTURER 0x2
#define FDMI_HBA_SERIAL_NUMBER 0x3
@@ -2637,16 +2713,17 @@
#define FDMI_HBA_FIRMWARE_VERSION 0x9
#define FDMI_HBA_OS_NAME_AND_VERSION 0xa
#define FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH 0xb
+
#define FDMI_HBA_NODE_SYMBOLIC_NAME 0xc
-#define FDMI_HBA_VENDOR_ID 0xd
+#define FDMI_HBA_VENDOR_SPECIFIC_INFO 0xd
#define FDMI_HBA_NUM_PORTS 0xe
#define FDMI_HBA_FABRIC_NAME 0xf
#define FDMI_HBA_BOOT_BIOS_NAME 0x10
-#define FDMI_HBA_TYPE_VENDOR_IDENTIFIER 0xe0
+#define FDMI_HBA_VENDOR_IDENTIFIER 0xe0
struct ct_fdmi_hba_attr {
- uint16_t type;
- uint16_t len;
+ __be16 type;
+ __be16 len;
union {
uint8_t node_name[WWN_SIZE];
uint8_t manufacturer[64];
@@ -2658,55 +2735,41 @@
uint8_t orom_version[16];
uint8_t fw_version[32];
uint8_t os_version[128];
- uint32_t max_ct_len;
- } a;
-};
+ __be32 max_ct_len;
-struct ct_fdmi_hba_attributes {
- uint32_t count;
- struct ct_fdmi_hba_attr entry[FDMI_HBA_ATTR_COUNT];
-};
-
-struct ct_fdmiv2_hba_attr {
- uint16_t type;
- uint16_t len;
- union {
- uint8_t node_name[WWN_SIZE];
- uint8_t manufacturer[64];
- uint8_t serial_num[32];
- uint8_t model[16+1];
- uint8_t model_desc[80];
- uint8_t hw_version[16];
- uint8_t driver_version[32];
- uint8_t orom_version[16];
- uint8_t fw_version[32];
- uint8_t os_version[128];
- uint32_t max_ct_len;
uint8_t sym_name[256];
- uint32_t vendor_id;
- uint32_t num_ports;
+ __be32 vendor_specific_info;
+ __be32 num_ports;
uint8_t fabric_name[WWN_SIZE];
uint8_t bios_name[32];
uint8_t vendor_identifier[8];
} a;
};
-struct ct_fdmiv2_hba_attributes {
- uint32_t count;
- struct ct_fdmiv2_hba_attr entry[FDMIV2_HBA_ATTR_COUNT];
+struct ct_fdmi1_hba_attributes {
+ __be32 count;
+ struct ct_fdmi_hba_attr entry[FDMI1_HBA_ATTR_COUNT];
+};
+
+struct ct_fdmi2_hba_attributes {
+ __be32 count;
+ struct ct_fdmi_hba_attr entry[FDMI2_HBA_ATTR_COUNT];
};
/*
- * Port attribute types.
+ * FDMI Port attribute types.
*/
-#define FDMI_PORT_ATTR_COUNT 6
-#define FDMIV2_PORT_ATTR_COUNT 16
+#define FDMI1_PORT_ATTR_COUNT 6
+#define FDMI2_PORT_ATTR_COUNT 16
+#define FDMI2_SMARTSAN_PORT_ATTR_COUNT 23
+
#define FDMI_PORT_FC4_TYPES 0x1
#define FDMI_PORT_SUPPORT_SPEED 0x2
#define FDMI_PORT_CURRENT_SPEED 0x3
#define FDMI_PORT_MAX_FRAME_SIZE 0x4
#define FDMI_PORT_OS_DEVICE_NAME 0x5
#define FDMI_PORT_HOST_NAME 0x6
+
#define FDMI_PORT_NODE_NAME 0x7
#define FDMI_PORT_NAME 0x8
#define FDMI_PORT_SYM_NAME 0x9
@@ -2716,7 +2779,15 @@
#define FDMI_PORT_FC4_TYPE 0xd
#define FDMI_PORT_STATE 0x101
#define FDMI_PORT_COUNT 0x102
-#define FDMI_PORT_ID 0x103
+#define FDMI_PORT_IDENTIFIER 0x103
+
+#define FDMI_SMARTSAN_SERVICE 0xF100
+#define FDMI_SMARTSAN_GUID 0xF101
+#define FDMI_SMARTSAN_VERSION 0xF102
+#define FDMI_SMARTSAN_PROD_NAME 0xF103
+#define FDMI_SMARTSAN_PORT_INFO 0xF104
+#define FDMI_SMARTSAN_QOS_SUPPORT 0xF105
+#define FDMI_SMARTSAN_SECURITY_SUPPORT 0xF106
#define FDMI_PORT_SPEED_1GB 0x1
#define FDMI_PORT_SPEED_2GB 0x2
@@ -2732,54 +2803,58 @@
#define FC_CLASS_3 0x08
#define FC_CLASS_2_3 0x0C
-struct ct_fdmiv2_port_attr {
- uint16_t type;
- uint16_t len;
+struct ct_fdmi_port_attr {
+ __be16 type;
+ __be16 len;
union {
uint8_t fc4_types[32];
- uint32_t sup_speed;
- uint32_t cur_speed;
- uint32_t max_frame_size;
+ __be32 sup_speed;
+ __be32 cur_speed;
+ __be32 max_frame_size;
uint8_t os_dev_name[32];
uint8_t host_name[256];
+
uint8_t node_name[WWN_SIZE];
uint8_t port_name[WWN_SIZE];
uint8_t port_sym_name[128];
- uint32_t port_type;
- uint32_t port_supported_cos;
+ __be32 port_type;
+ __be32 port_supported_cos;
uint8_t fabric_name[WWN_SIZE];
uint8_t port_fc4_type[32];
- uint32_t port_state;
- uint32_t num_ports;
- uint32_t port_id;
+ __be32 port_state;
+ __be32 num_ports;
+ __be32 port_id;
+
+ uint8_t smartsan_service[24];
+ uint8_t smartsan_guid[16];
+ uint8_t smartsan_version[24];
+ uint8_t smartsan_prod_name[16];
+ __be32 smartsan_port_info;
+ __be32 smartsan_qos_support;
+ __be32 smartsan_security_support;
} a;
};
-/*
- * Port Attribute Block.
- */
-struct ct_fdmiv2_port_attributes {
- uint32_t count;
- struct ct_fdmiv2_port_attr entry[FDMIV2_PORT_ATTR_COUNT];
+struct ct_fdmi1_port_attributes {
+ __be32 count;
+ struct ct_fdmi_port_attr entry[FDMI1_PORT_ATTR_COUNT];
};
-struct ct_fdmi_port_attr {
- uint16_t type;
- uint16_t len;
- union {
- uint8_t fc4_types[32];
- uint32_t sup_speed;
- uint32_t cur_speed;
- uint32_t max_frame_size;
- uint8_t os_dev_name[32];
- uint8_t host_name[256];
- } a;
+struct ct_fdmi2_port_attributes {
+ __be32 count;
+ struct ct_fdmi_port_attr entry[FDMI2_PORT_ATTR_COUNT];
};
-struct ct_fdmi_port_attributes {
- uint32_t count;
- struct ct_fdmi_port_attr entry[FDMI_PORT_ATTR_COUNT];
-};
+#define FDMI_ATTR_TYPELEN(obj) \
+ (sizeof((obj)->type) + sizeof((obj)->len))
+
+#define FDMI_ATTR_ALIGNMENT(len) \
+ (4 - ((len) & 3))
+
+/* FDMI register call options */
+#define CALLOPT_FDMI1 0
+#define CALLOPT_FDMI2 1
+#define CALLOPT_FDMI2_SMARTSAN 2
/* FDMI definitions. */
#define GRHL_CMD 0x100
@@ -2791,10 +2866,13 @@
#define RHBA_RSP_SIZE 16
#define RHAT_CMD 0x201
+
#define RPRT_CMD 0x210
+#define RPRT_RSP_SIZE 24
#define RPA_CMD 0x211
#define RPA_RSP_SIZE 16
+#define SMARTSAN_RPA_RSP_SIZE 24
#define DHBA_CMD 0x300
#define DHBA_REQ_SIZE (16 + 8)
@@ -2817,8 +2895,8 @@
/* CT command request */
struct ct_sns_req {
struct ct_cmd_hdr header;
- uint16_t command;
- uint16_t max_rsp_size;
+ __be16 command;
+ __be16 max_rsp_size;
uint8_t fragment_id;
uint8_t reserved[3];
@@ -2875,32 +2953,26 @@
struct {
uint8_t hba_identifier[8];
- uint32_t entry_count;
+ __be32 entry_count;
uint8_t port_name[8];
- struct ct_fdmi_hba_attributes attrs;
+ struct ct_fdmi2_hba_attributes attrs;
} rhba;
struct {
uint8_t hba_identifier[8];
- uint32_t entry_count;
- uint8_t port_name[8];
- struct ct_fdmiv2_hba_attributes attrs;
- } rhba2;
-
- struct {
- uint8_t hba_identifier[8];
- struct ct_fdmi_hba_attributes attrs;
+ struct ct_fdmi1_hba_attributes attrs;
} rhat;
struct {
uint8_t port_name[8];
- struct ct_fdmi_port_attributes attrs;
+ struct ct_fdmi2_port_attributes attrs;
} rpa;
struct {
+ uint8_t hba_identifier[8];
uint8_t port_name[8];
- struct ct_fdmiv2_port_attributes attrs;
- } rpa2;
+ struct ct_fdmi2_port_attributes attrs;
+ } rprt;
struct {
uint8_t port_name[8];
@@ -2936,7 +3008,7 @@
/* CT command response header */
struct ct_rsp_hdr {
struct ct_cmd_hdr header;
- uint16_t response;
+ __be16 response;
uint16_t residual;
uint8_t fragment_id;
uint8_t reason_code;
@@ -3014,7 +3086,7 @@
struct {
uint32_t entry_count;
uint8_t port_name[8];
- struct ct_fdmi_hba_attributes attrs;
+ struct ct_fdmi1_hba_attributes attrs;
} ghat;
struct {
@@ -3022,8 +3094,8 @@
} gfpn_id;
struct {
- uint16_t speeds;
- uint16_t speed;
+ __be16 speeds;
+ __be16 speed;
} gpsc;
#define GFF_FCP_SCSI_OFFSET 7
@@ -3113,13 +3185,13 @@
struct sns_cmd_pkt {
union {
struct {
- uint16_t buffer_length;
- uint16_t reserved_1;
- __le64 buffer_address __packed;
- uint16_t subcommand_length;
- uint16_t reserved_2;
- uint16_t subcommand;
- uint16_t size;
+ __le16 buffer_length;
+ __le16 reserved_1;
+ __le64 buffer_address __packed;
+ __le16 subcommand_length;
+ __le16 reserved_2;
+ __le16 subcommand;
+ __le16 size;
uint32_t reserved_3;
uint8_t param[36];
} cmd;
@@ -3145,7 +3217,7 @@
uint8_t area;
uint8_t domain;
uint8_t loop_id_2100; /* ISP2100/ISP2200 -- 4 bytes. */
- uint16_t loop_id; /* ISP23XX -- 6 bytes. */
+ __le16 loop_id; /* ISP23XX -- 6 bytes. */
uint16_t reserved_1; /* ISP24XX -- 8 bytes. */
};
@@ -3219,7 +3291,8 @@
int (*write_nvram)(struct scsi_qla_host *, void *, uint32_t,
uint32_t);
- void (*fw_dump) (struct scsi_qla_host *, int);
+ void (*fw_dump)(struct scsi_qla_host *vha);
+ void (*mpi_fw_dump)(struct scsi_qla_host *, int);
int (*beacon_on) (struct scsi_qla_host *);
int (*beacon_off) (struct scsi_qla_host *);
@@ -3248,6 +3321,7 @@
#define QLA_MSIX_RSP_Q 0x01
#define QLA_ATIO_VECTOR 0x02
#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q 0x03
+#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS 0x04
#define QLA_MIDX_DEFAULT 0
#define QLA_MIDX_RSP_Q 1
@@ -3277,7 +3351,6 @@
QLA_EVT_IDC_ACK,
QLA_EVT_ASYNC_LOGIN,
QLA_EVT_ASYNC_LOGOUT,
- QLA_EVT_ASYNC_LOGOUT_DONE,
QLA_EVT_ASYNC_ADISC,
QLA_EVT_UEVENT,
QLA_EVT_AENFX,
@@ -3446,6 +3519,14 @@
uint64_t num_term_xchg_sent;
};
+struct qla_counters {
+ uint64_t input_bytes;
+ uint64_t input_requests;
+ uint64_t output_bytes;
+ uint64_t output_requests;
+
+};
+
struct qla_qpair;
/* Response queue data structure */
@@ -3453,8 +3534,8 @@
dma_addr_t dma;
response_t *ring;
response_t *ring_ptr;
- uint32_t __iomem *rsp_q_in; /* FWI2-capable only. */
- uint32_t __iomem *rsp_q_out;
+ __le32 __iomem *rsp_q_in; /* FWI2-capable only. */
+ __le32 __iomem *rsp_q_out;
uint16_t ring_index;
uint16_t out_ptr;
uint16_t *in_ptr; /* queue shadow in index */
@@ -3480,8 +3561,8 @@
dma_addr_t dma;
request_t *ring;
request_t *ring_ptr;
- uint32_t __iomem *req_q_in; /* FWI2-capable only. */
- uint32_t __iomem *req_q_out;
+ __le32 __iomem *req_q_in; /* FWI2-capable only. */
+ __le32 __iomem *req_q_out;
uint16_t ring_index;
uint16_t in_ptr;
uint16_t *out_ptr; /* queue shadow out index */
@@ -3504,6 +3585,15 @@
uint8_t req_pkt[REQUEST_ENTRY_SIZE];
};
+struct qla_fw_resources {
+ u16 iocbs_total;
+ u16 iocbs_limit;
+ u16 iocbs_qp_limit;
+ u16 iocbs_used;
+};
+
+#define QLA_IOCB_PCT_LIMIT 95
+
/*Queue pair data structure */
struct qla_qpair {
spinlock_t qp_lock;
@@ -3530,6 +3620,7 @@
uint32_t enable_class_2:1;
uint32_t enable_explicit_conf:1;
uint32_t use_shadow_reg:1;
+ uint32_t rcv_intr:1;
uint16_t id; /* qp number used with FW */
uint16_t vp_idx; /* vport ID */
@@ -3545,13 +3636,17 @@
struct qla_msix_entry *msix; /* point to &ha->msix_entries[x] */
struct qla_hw_data *hw;
struct work_struct q_work;
+ struct qla_counters counters;
+
struct list_head qp_list_elem; /* vha->qp_list */
struct list_head hints_list;
- uint16_t cpuid;
+
uint16_t retry_term_cnt;
- uint32_t retry_term_exchg_addr;
+ __le32 retry_term_exchg_addr;
uint64_t retry_term_jiff;
struct qla_tgt_counters tgt_counters;
+ uint16_t cpuid;
+ struct qla_fw_resources fwres ____cacheline_aligned;
};
/* Place holder for FW buffer parameters */
@@ -3561,6 +3656,134 @@
uint32_t len;
};
+struct rdp_req_payload {
+ uint32_t els_request;
+ uint32_t desc_list_len;
+
+ /* NPIV descriptor */
+ struct {
+ uint32_t desc_tag;
+ uint32_t desc_len;
+ uint8_t reserved;
+ uint8_t nport_id[3];
+ } npiv_desc;
+};
+
+struct rdp_rsp_payload {
+ struct {
+ __be32 cmd;
+ __be32 len;
+ } hdr;
+
+ /* LS Request Info descriptor */
+ struct {
+ __be32 desc_tag;
+ __be32 desc_len;
+ __be32 req_payload_word_0;
+ } ls_req_info_desc;
+
+ /* LS Request Info descriptor */
+ struct {
+ __be32 desc_tag;
+ __be32 desc_len;
+ __be32 req_payload_word_0;
+ } ls_req_info_desc2;
+
+ /* SFP diagnostic param descriptor */
+ struct {
+ __be32 desc_tag;
+ __be32 desc_len;
+ __be16 temperature;
+ __be16 vcc;
+ __be16 tx_bias;
+ __be16 tx_power;
+ __be16 rx_power;
+ __be16 sfp_flags;
+ } sfp_diag_desc;
+
+ /* Port Speed Descriptor */
+ struct {
+ __be32 desc_tag;
+ __be32 desc_len;
+ __be16 speed_capab;
+ __be16 operating_speed;
+ } port_speed_desc;
+
+ /* Link Error Status Descriptor */
+ struct {
+ __be32 desc_tag;
+ __be32 desc_len;
+ __be32 link_fail_cnt;
+ __be32 loss_sync_cnt;
+ __be32 loss_sig_cnt;
+ __be32 prim_seq_err_cnt;
+ __be32 inval_xmit_word_cnt;
+ __be32 inval_crc_cnt;
+ uint8_t pn_port_phy_type;
+ uint8_t reserved[3];
+ } ls_err_desc;
+
+ /* Port name description with diag param */
+ struct {
+ __be32 desc_tag;
+ __be32 desc_len;
+ uint8_t WWNN[WWN_SIZE];
+ uint8_t WWPN[WWN_SIZE];
+ } port_name_diag_desc;
+
+ /* Port Name desc for Direct attached Fx_Port or Nx_Port */
+ struct {
+ __be32 desc_tag;
+ __be32 desc_len;
+ uint8_t WWNN[WWN_SIZE];
+ uint8_t WWPN[WWN_SIZE];
+ } port_name_direct_desc;
+
+ /* Buffer Credit descriptor */
+ struct {
+ __be32 desc_tag;
+ __be32 desc_len;
+ __be32 fcport_b2b;
+ __be32 attached_fcport_b2b;
+ __be32 fcport_rtt;
+ } buffer_credit_desc;
+
+ /* Optical Element Data Descriptor */
+ struct {
+ __be32 desc_tag;
+ __be32 desc_len;
+ __be16 high_alarm;
+ __be16 low_alarm;
+ __be16 high_warn;
+ __be16 low_warn;
+ __be32 element_flags;
+ } optical_elmt_desc[5];
+
+ /* Optical Product Data Descriptor */
+ struct {
+ __be32 desc_tag;
+ __be32 desc_len;
+ uint8_t vendor_name[16];
+ uint8_t part_number[16];
+ uint8_t serial_number[16];
+ uint8_t revision[4];
+ uint8_t date[8];
+ } optical_prod_desc;
+};
+
+#define RDP_DESC_LEN(obj) \
+ (sizeof(obj) - sizeof((obj).desc_tag) - sizeof((obj).desc_len))
+
+#define RDP_PORT_SPEED_1GB BIT_15
+#define RDP_PORT_SPEED_2GB BIT_14
+#define RDP_PORT_SPEED_4GB BIT_13
+#define RDP_PORT_SPEED_10GB BIT_12
+#define RDP_PORT_SPEED_8GB BIT_11
+#define RDP_PORT_SPEED_16GB BIT_10
+#define RDP_PORT_SPEED_32GB BIT_9
+#define RDP_PORT_SPEED_64GB BIT_8
+#define RDP_PORT_SPEED_UNKNOWN BIT_0
+
struct scsi_qlt_host {
void *target_lport_ptr;
struct mutex tgt_mutex;
@@ -3577,17 +3800,17 @@
struct atio *atio_ring_ptr; /* Current address. */
uint16_t atio_ring_index; /* Current index. */
uint16_t atio_q_length;
- uint32_t __iomem *atio_q_in;
- uint32_t __iomem *atio_q_out;
+ __le32 __iomem *atio_q_in;
+ __le32 __iomem *atio_q_out;
struct qla_tgt_func_tmpl *tgt_ops;
struct qla_tgt_vp_map *tgt_vp_map;
int saved_set;
- uint16_t saved_exchange_count;
- uint32_t saved_firmware_options_1;
- uint32_t saved_firmware_options_2;
- uint32_t saved_firmware_options_3;
+ __le16 saved_exchange_count;
+ __le32 saved_firmware_options_1;
+ __le32 saved_firmware_options_2;
+ __le32 saved_firmware_options_3;
uint8_t saved_firmware_options[2];
uint8_t saved_add_firmware_options[2];
@@ -3617,6 +3840,11 @@
#define LEAK_EXCHG_THRESH_HOLD_PERCENT 75 /* 75 percent */
+struct qla_hw_data_stat {
+ u32 num_fw_dump;
+ u32 num_mpi_reset;
+};
+
/*
* Qlogic host adapter specific data structure.
*/
@@ -3672,17 +3900,24 @@
uint32_t fw_started:1;
uint32_t fw_init_done:1;
- uint32_t detected_lr_sfp:1;
- uint32_t using_lr_setting:1;
+ uint32_t lr_detected:1;
+
uint32_t rida_fmt2:1;
uint32_t purge_mbox:1;
uint32_t n2n_bigger:1;
uint32_t secure_adapter:1;
uint32_t secure_fw:1;
+ /* Supported by Adapter */
+ uint32_t scm_supported_a:1;
+ /* Supported by Firmware */
+ uint32_t scm_supported_f:1;
+ /* Enabled in Driver */
+ uint32_t scm_enabled:1;
+ uint32_t plogi_template_valid:1;
} flags;
uint16_t max_exchg;
- uint16_t long_range_distance; /* 32G & above */
+ uint16_t lr_distance; /* 32G & above */
#define LR_DISTANCE_5K 1
#define LR_DISTANCE_10K 0
@@ -3925,6 +4160,10 @@
#define USE_ASYNC_SCAN(ha) (IS_QLA25XX(ha) || IS_QLA81XX(ha) ||\
IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
+#define IS_ZIO_THRESHOLD_CAPABLE(ha) \
+ ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&\
+ (ha->zio_mode == QLA_ZIO_MODE_6))
+
/* HBA serial number */
uint8_t serial0;
uint8_t serial1;
@@ -3964,10 +4203,12 @@
#define SFP_DEV_SIZE 512
#define SFP_BLOCK_SIZE 64
+#define SFP_RTDI_LEN SFP_BLOCK_SIZE
+
void *sfp_data;
dma_addr_t sfp_data_dma;
- void *flt;
+ struct qla_flt_header *flt;
dma_addr_t flt_dma;
#define XGMAC_DATA_SIZE 4096
@@ -3994,6 +4235,13 @@
int init_cb_size;
dma_addr_t ex_init_cb_dma;
struct ex_init_cb_81xx *ex_init_cb;
+ dma_addr_t sf_init_cb_dma;
+ struct init_sf_cb *sf_init_cb;
+
+ void *scm_fpin_els_buff;
+ uint64_t scm_fpin_els_buff_size;
+ bool scm_fpin_valid;
+ bool scm_fpin_payload_size;
void *async_pd;
dma_addr_t async_pd_dma;
@@ -4003,7 +4251,7 @@
/* Extended Logins */
void *exlogin_buf;
dma_addr_t exlogin_buf_dma;
- int exlogin_size;
+ uint32_t exlogin_size;
#define ENABLE_EXCHANGE_OFFLD BIT_2
@@ -4014,7 +4262,8 @@
int exchoffld_count;
/* n2n */
- struct els_plogi_payload plogi_els_payld;
+ struct fc_els_flogi plogi_els_payld;
+#define LOGIN_TEMPLATE_SIZE (sizeof(struct fc_els_flogi) - 4)
void *swl;
@@ -4056,6 +4305,13 @@
#define FW_ATTR_H_NVME BIT_10
#define FW_ATTR_H_NVME_UPDATED BIT_14
+ /* About firmware SCM support */
+#define FW_ATTR_EXT0_SCM_SUPPORTED BIT_12
+ /* Brocade fabric attached */
+#define FW_ATTR_EXT0_SCM_BROCADE 0x00001000
+ /* Cisco fabric attached */
+#define FW_ATTR_EXT0_SCM_CISCO 0x00002000
+#define FW_ATTR_EXT0_NVME2 BIT_13
uint16_t fw_attributes_ext[2];
uint32_t fw_memory_size;
uint32_t fw_transfer_size;
@@ -4079,7 +4335,7 @@
uint16_t fw_options[16]; /* slots: 1,2,3,10,11 */
uint8_t fw_seriallink_options[4];
- uint16_t fw_seriallink_options24[4];
+ __le16 fw_seriallink_options24[4];
uint8_t serdes_version[3];
uint8_t mpi_version[3];
@@ -4097,7 +4353,6 @@
uint32_t fw_dump_len;
u32 fw_dump_alloc_len;
bool fw_dumped;
- bool fw_dump_mpi;
unsigned long fw_dump_cap_flags;
#define RISC_PAUSE_CMPL 0
#define DMA_SHUTDOWN_CMPL 1
@@ -4108,6 +4363,10 @@
#define ISP_MBX_RDY 6
#define ISP_SOFT_RESET_CMPL 7
int fw_dump_reading;
+ void *mpi_fw_dump;
+ u32 mpi_fw_dump_len;
+ unsigned int mpi_fw_dump_reading:1;
+ unsigned int mpi_fw_dumped:1;
int prev_minidump_failed;
dma_addr_t eft_dma;
void *eft;
@@ -4259,7 +4518,7 @@
#define NUM_DSD_CHAIN 4096
uint8_t fw_type;
- __le32 file_prd_off; /* File firmware product offset */
+ uint32_t file_prd_off; /* File firmware product offset */
uint32_t md_template_size;
void *md_tmplt_hdr;
@@ -4321,6 +4580,8 @@
uint16_t last_zio_threshold;
#define DEFAULT_ZIO_THRESHOLD 5
+
+ struct qla_hw_data_stat stat;
};
struct active_regions {
@@ -4343,6 +4604,31 @@
#define QLA_SET_DATA_RATE_NOLR 1
#define QLA_SET_DATA_RATE_LR 2 /* Set speed and initiate LR */
+#define QLA_DEFAULT_PAYLOAD_SIZE 64
+/*
+ * This item might be allocated with a size > sizeof(struct purex_item).
+ * The "size" variable gives the size of the payload (which
+ * is variable) starting at "iocb".
+ */
+struct purex_item {
+ struct list_head list;
+ struct scsi_qla_host *vha;
+ void (*process_item)(struct scsi_qla_host *vha,
+ struct purex_item *pkt);
+ atomic_t in_use;
+ uint16_t size;
+ struct {
+ uint8_t iocb[64];
+ } iocb;
+};
+
+#define SCM_FLAG_RDF_REJECT 0x00
+#define SCM_FLAG_RDF_COMPLETED 0x01
+
+#define QLA_CON_PRIMITIVE_RECEIVED 0x1
+#define QLA_CONGESTION_ARB_WARNING 0x1
+#define QLA_CONGESTION_ARB_ALARM 0X2
+
/*
* Qlogic scsi host structure
*/
@@ -4375,6 +4661,7 @@
uint32_t qpairs_rsp_created:1;
uint32_t nvme_enabled:1;
uint32_t nvme_first_burst:1;
+ uint32_t nvme2_enabled:1;
} flags;
atomic_t loop_state;
@@ -4423,6 +4710,8 @@
#define ISP_ABORT_TO_ROM 33
#define VPORT_DELETE 34
+#define PROCESS_PUREX_IOCB 63
+
unsigned long pci_flags;
#define PFLG_DISCONNECTED 0 /* PCI device removed */
#define PFLG_DRIVER_REMOVING 1 /* PCI driver .remove */
@@ -4460,6 +4749,7 @@
uint8_t node_name[WWN_SIZE];
uint8_t port_name[WWN_SIZE];
uint8_t fabric_node_name[WWN_SIZE];
+ uint8_t fabric_port_name[WWN_SIZE];
struct nvme_fc_local_port *nvme_local_port;
struct completion nvme_del_done;
@@ -4530,6 +4820,14 @@
uint16_t ql2xexchoffld;
uint16_t ql2xiniexchg;
+ struct dentry *dfs_rport_root;
+
+ struct purex_list {
+ struct list_head head;
+ spinlock_t lock;
+ } purex_list;
+ struct purex_item default_item;
+
struct name_list_extended gnl;
/* Count of active session/fcport */
int fcport_count;
@@ -4539,21 +4837,23 @@
uint8_t n2n_node_name[WWN_SIZE];
uint8_t n2n_port_name[WWN_SIZE];
uint16_t n2n_id;
+ __le16 dport_data[4];
struct list_head gpnid_list;
struct fab_scan scan;
+ uint8_t scm_fabric_connection_flags;
unsigned int irq_offset;
} scsi_qla_host_t;
struct qla27xx_image_status {
uint8_t image_status_mask;
- uint16_t generation;
+ __le16 generation;
uint8_t ver_major;
uint8_t ver_minor;
uint8_t bitmap; /* 28xx only */
uint8_t reserved[2];
- uint32_t checksum;
- uint32_t signature;
+ __le32 checksum;
+ __le32 signature;
} __packed;
/* 28xx aux image status bimap values */
@@ -4821,11 +5121,14 @@
u8 resv2[128];
};
-#define AUTO_DETECT_SFP_SUPPORT(_vha)\
- (ql2xautodetectsfp && !_vha->vp_idx && \
- (IS_QLA25XX(_vha->hw) || IS_QLA81XX(_vha->hw) ||\
- IS_QLA83XX(_vha->hw) || IS_QLA27XX(_vha->hw) || \
- IS_QLA28XX(_vha->hw)))
+/* BPM -- Buffer Plus Management support. */
+#define IS_BPM_CAPABLE(ha) \
+ (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || \
+ IS_QLA27XX(ha) || IS_QLA28XX(ha))
+#define IS_BPM_RANGE_CAPABLE(ha) \
+ (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
+#define IS_BPM_ENABLED(vha) \
+ (ql2xautodetectsfp && !vha->vp_idx && IS_BPM_CAPABLE(vha->hw))
#define FLASH_SEMAPHORE_REGISTER_ADDR 0x00101016
@@ -4842,6 +5145,8 @@
ha->current_topology == ISP_CFG_N || \
!ha->current_topology)
+#define QLA_N2N_WAIT_TIME 5 /* 2 * ra_tov(n2n) + 1 */
+
#define NVME_TYPE(fcport) \
(fcport->fc4_type & FS_FC4TYPE_NVME) \
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index 0a6fb35..d5ebcf7 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
@@ -12,6 +11,140 @@
static struct dentry *qla2x00_dfs_root;
static atomic_t qla2x00_dfs_root_count;
+#define QLA_DFS_RPORT_DEVLOSS_TMO 1
+
+static int
+qla_dfs_rport_get(struct fc_port *fp, int attr_id, u64 *val)
+{
+ switch (attr_id) {
+ case QLA_DFS_RPORT_DEVLOSS_TMO:
+ /* Only supported for FC-NVMe devices that are registered. */
+ if (!(fp->nvme_flag & NVME_FLAG_REGISTERED))
+ return -EIO;
+ *val = fp->nvme_remote_port->dev_loss_tmo;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int
+qla_dfs_rport_set(struct fc_port *fp, int attr_id, u64 val)
+{
+ switch (attr_id) {
+ case QLA_DFS_RPORT_DEVLOSS_TMO:
+ /* Only supported for FC-NVMe devices that are registered. */
+ if (!(fp->nvme_flag & NVME_FLAG_REGISTERED))
+ return -EIO;
+#if (IS_ENABLED(CONFIG_NVME_FC))
+ return nvme_fc_set_remoteport_devloss(fp->nvme_remote_port,
+ val);
+#else /* CONFIG_NVME_FC */
+ return -EINVAL;
+#endif /* CONFIG_NVME_FC */
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+#define DEFINE_QLA_DFS_RPORT_RW_ATTR(_attr_id, _attr) \
+static int qla_dfs_rport_##_attr##_get(void *data, u64 *val) \
+{ \
+ struct fc_port *fp = data; \
+ return qla_dfs_rport_get(fp, _attr_id, val); \
+} \
+static int qla_dfs_rport_##_attr##_set(void *data, u64 val) \
+{ \
+ struct fc_port *fp = data; \
+ return qla_dfs_rport_set(fp, _attr_id, val); \
+} \
+DEFINE_DEBUGFS_ATTRIBUTE(qla_dfs_rport_##_attr##_fops, \
+ qla_dfs_rport_##_attr##_get, \
+ qla_dfs_rport_##_attr##_set, "%llu\n")
+
+/*
+ * Wrapper for getting fc_port fields.
+ *
+ * _attr : Attribute name.
+ * _get_val : Accessor macro to retrieve the value.
+ */
+#define DEFINE_QLA_DFS_RPORT_FIELD_GET(_attr, _get_val) \
+static int qla_dfs_rport_field_##_attr##_get(void *data, u64 *val) \
+{ \
+ struct fc_port *fp = data; \
+ *val = _get_val; \
+ return 0; \
+} \
+DEFINE_DEBUGFS_ATTRIBUTE(qla_dfs_rport_field_##_attr##_fops, \
+ qla_dfs_rport_field_##_attr##_get, \
+ NULL, "%llu\n")
+
+#define DEFINE_QLA_DFS_RPORT_ACCESS(_attr, _get_val) \
+ DEFINE_QLA_DFS_RPORT_FIELD_GET(_attr, _get_val)
+
+#define DEFINE_QLA_DFS_RPORT_FIELD(_attr) \
+ DEFINE_QLA_DFS_RPORT_FIELD_GET(_attr, fp->_attr)
+
+DEFINE_QLA_DFS_RPORT_RW_ATTR(QLA_DFS_RPORT_DEVLOSS_TMO, dev_loss_tmo);
+
+DEFINE_QLA_DFS_RPORT_FIELD(disc_state);
+DEFINE_QLA_DFS_RPORT_FIELD(scan_state);
+DEFINE_QLA_DFS_RPORT_FIELD(fw_login_state);
+DEFINE_QLA_DFS_RPORT_FIELD(login_pause);
+DEFINE_QLA_DFS_RPORT_FIELD(flags);
+DEFINE_QLA_DFS_RPORT_FIELD(nvme_flag);
+DEFINE_QLA_DFS_RPORT_FIELD(last_rscn_gen);
+DEFINE_QLA_DFS_RPORT_FIELD(rscn_gen);
+DEFINE_QLA_DFS_RPORT_FIELD(login_gen);
+DEFINE_QLA_DFS_RPORT_FIELD(loop_id);
+DEFINE_QLA_DFS_RPORT_FIELD_GET(port_id, fp->d_id.b24);
+DEFINE_QLA_DFS_RPORT_FIELD_GET(sess_kref, kref_read(&fp->sess_kref));
+
+void
+qla2x00_dfs_create_rport(scsi_qla_host_t *vha, struct fc_port *fp)
+{
+ char wwn[32];
+
+#define QLA_CREATE_RPORT_FIELD_ATTR(_attr) \
+ debugfs_create_file(#_attr, 0400, fp->dfs_rport_dir, \
+ fp, &qla_dfs_rport_field_##_attr##_fops)
+
+ if (!vha->dfs_rport_root || fp->dfs_rport_dir)
+ return;
+
+ sprintf(wwn, "pn-%016llx", wwn_to_u64(fp->port_name));
+ fp->dfs_rport_dir = debugfs_create_dir(wwn, vha->dfs_rport_root);
+ if (!fp->dfs_rport_dir)
+ return;
+ if (NVME_TARGET(vha->hw, fp))
+ debugfs_create_file("dev_loss_tmo", 0600, fp->dfs_rport_dir,
+ fp, &qla_dfs_rport_dev_loss_tmo_fops);
+
+ QLA_CREATE_RPORT_FIELD_ATTR(disc_state);
+ QLA_CREATE_RPORT_FIELD_ATTR(scan_state);
+ QLA_CREATE_RPORT_FIELD_ATTR(fw_login_state);
+ QLA_CREATE_RPORT_FIELD_ATTR(login_pause);
+ QLA_CREATE_RPORT_FIELD_ATTR(flags);
+ QLA_CREATE_RPORT_FIELD_ATTR(nvme_flag);
+ QLA_CREATE_RPORT_FIELD_ATTR(last_rscn_gen);
+ QLA_CREATE_RPORT_FIELD_ATTR(rscn_gen);
+ QLA_CREATE_RPORT_FIELD_ATTR(login_gen);
+ QLA_CREATE_RPORT_FIELD_ATTR(loop_id);
+ QLA_CREATE_RPORT_FIELD_ATTR(port_id);
+ QLA_CREATE_RPORT_FIELD_ATTR(sess_kref);
+}
+
+void
+qla2x00_dfs_remove_rport(scsi_qla_host_t *vha, struct fc_port *fp)
+{
+ if (!vha->dfs_rport_root || !fp->dfs_rport_dir)
+ return;
+ debugfs_remove_recursive(fp->dfs_rport_dir);
+ fp->dfs_rport_dir = NULL;
+}
+
static int
qla2x00_dfs_tgt_sess_show(struct seq_file *s, void *unused)
{
@@ -37,89 +170,63 @@
return 0;
}
-static int
-qla2x00_dfs_tgt_sess_open(struct inode *inode, struct file *file)
-{
- scsi_qla_host_t *vha = inode->i_private;
-
- return single_open(file, qla2x00_dfs_tgt_sess_show, vha);
-}
-
-static const struct file_operations dfs_tgt_sess_ops = {
- .open = qla2x00_dfs_tgt_sess_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(qla2x00_dfs_tgt_sess);
static int
qla2x00_dfs_tgt_port_database_show(struct seq_file *s, void *unused)
{
scsi_qla_host_t *vha = s->private;
struct qla_hw_data *ha = vha->hw;
- struct gid_list_info *gid_list, *gid;
+ struct gid_list_info *gid_list;
dma_addr_t gid_list_dma;
fc_port_t fc_port;
+ char *id_iter;
int rc, i;
uint16_t entries, loop_id;
- struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
seq_printf(s, "%s\n", vha->host_str);
- if (tgt) {
- gid_list = dma_alloc_coherent(&ha->pdev->dev,
- qla2x00_gid_list_size(ha),
- &gid_list_dma, GFP_KERNEL);
- if (!gid_list) {
- ql_dbg(ql_dbg_user, vha, 0x7018,
- "DMA allocation failed for %u\n",
- qla2x00_gid_list_size(ha));
- return 0;
- }
-
- rc = qla24xx_gidlist_wait(vha, gid_list, gid_list_dma,
- &entries);
- if (rc != QLA_SUCCESS)
- goto out_free_id_list;
-
- gid = gid_list;
-
- seq_puts(s, "Port Name Port ID Loop ID\n");
-
- for (i = 0; i < entries; i++) {
- loop_id = le16_to_cpu(gid->loop_id);
- memset(&fc_port, 0, sizeof(fc_port_t));
-
- fc_port.loop_id = loop_id;
-
- rc = qla24xx_gpdb_wait(vha, &fc_port, 0);
- seq_printf(s, "%8phC %02x%02x%02x %d\n",
- fc_port.port_name, fc_port.d_id.b.domain,
- fc_port.d_id.b.area, fc_port.d_id.b.al_pa,
- fc_port.loop_id);
- gid = (void *)gid + ha->gid_list_info_size;
- }
-out_free_id_list:
- dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha),
- gid_list, gid_list_dma);
+ gid_list = dma_alloc_coherent(&ha->pdev->dev,
+ qla2x00_gid_list_size(ha),
+ &gid_list_dma, GFP_KERNEL);
+ if (!gid_list) {
+ ql_dbg(ql_dbg_user, vha, 0x7018,
+ "DMA allocation failed for %u\n",
+ qla2x00_gid_list_size(ha));
+ return 0;
}
+ rc = qla24xx_gidlist_wait(vha, gid_list, gid_list_dma,
+ &entries);
+ if (rc != QLA_SUCCESS)
+ goto out_free_id_list;
+
+ id_iter = (char *)gid_list;
+
+ seq_puts(s, "Port Name Port ID Loop ID\n");
+
+ for (i = 0; i < entries; i++) {
+ struct gid_list_info *gid =
+ (struct gid_list_info *)id_iter;
+ loop_id = le16_to_cpu(gid->loop_id);
+ memset(&fc_port, 0, sizeof(fc_port_t));
+
+ fc_port.loop_id = loop_id;
+
+ rc = qla24xx_gpdb_wait(vha, &fc_port, 0);
+ seq_printf(s, "%8phC %02x%02x%02x %d\n",
+ fc_port.port_name, fc_port.d_id.b.domain,
+ fc_port.d_id.b.area, fc_port.d_id.b.al_pa,
+ fc_port.loop_id);
+ id_iter += ha->gid_list_info_size;
+ }
+out_free_id_list:
+ dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha),
+ gid_list, gid_list_dma);
+
return 0;
}
-static int
-qla2x00_dfs_tgt_port_database_open(struct inode *inode, struct file *file)
-{
- scsi_qla_host_t *vha = inode->i_private;
-
- return single_open(file, qla2x00_dfs_tgt_port_database_show, vha);
-}
-
-static const struct file_operations dfs_tgt_port_database_ops = {
- .open = qla2x00_dfs_tgt_port_database_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(qla2x00_dfs_tgt_port_database);
static int
qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused)
@@ -127,6 +234,8 @@
struct scsi_qla_host *vha = s->private;
uint16_t mb[MAX_IOCB_MB_REG];
int rc;
+ struct qla_hw_data *ha = vha->hw;
+ u16 iocbs_used, i;
rc = qla24xx_res_count_wait(vha, mb, SIZEOF_IOCB_MB_REG);
if (rc != QLA_SUCCESS) {
@@ -134,11 +243,11 @@
} else {
seq_puts(s, "FW Resource count\n\n");
seq_printf(s, "Original TGT exchg count[%d]\n", mb[1]);
- seq_printf(s, "current TGT exchg count[%d]\n", mb[2]);
- seq_printf(s, "original Initiator Exchange count[%d]\n", mb[3]);
- seq_printf(s, "Current Initiator Exchange count[%d]\n", mb[6]);
- seq_printf(s, "Original IOCB count[%d]\n", mb[7]);
- seq_printf(s, "Current IOCB count[%d]\n", mb[10]);
+ seq_printf(s, "Current TGT exchg count[%d]\n", mb[2]);
+ seq_printf(s, "Current Initiator Exchange count[%d]\n", mb[3]);
+ seq_printf(s, "Original Initiator Exchange count[%d]\n", mb[6]);
+ seq_printf(s, "Current IOCB count[%d]\n", mb[7]);
+ seq_printf(s, "Original IOCB count[%d]\n", mb[10]);
seq_printf(s, "MAX VP count[%d]\n", mb[11]);
seq_printf(s, "MAX FCF count[%d]\n", mb[12]);
seq_printf(s, "Current free pageable XCB buffer cnt[%d]\n",
@@ -149,26 +258,24 @@
mb[22]);
seq_printf(s, "Original Target fast XCB buffer cnt[%d]\n",
mb[23]);
+ }
+ if (ql2xenforce_iocb_limit) {
+ /* lock is not require. It's an estimate. */
+ iocbs_used = ha->base_qpair->fwres.iocbs_used;
+ for (i = 0; i < ha->max_qpairs; i++) {
+ if (ha->queue_pair_map[i])
+ iocbs_used += ha->queue_pair_map[i]->fwres.iocbs_used;
+ }
+
+ seq_printf(s, "Driver: estimate iocb used [%d] high water limit [%d]\n",
+ iocbs_used, ha->base_qpair->fwres.iocbs_limit);
}
return 0;
}
-static int
-qla_dfs_fw_resource_cnt_open(struct inode *inode, struct file *file)
-{
- struct scsi_qla_host *vha = inode->i_private;
-
- return single_open(file, qla_dfs_fw_resource_cnt_show, vha);
-}
-
-static const struct file_operations dfs_fw_resource_cnt_ops = {
- .open = qla_dfs_fw_resource_cnt_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(qla_dfs_fw_resource_cnt);
static int
qla_dfs_tgt_counters_show(struct seq_file *s, void *unused)
@@ -245,20 +352,7 @@
return 0;
}
-static int
-qla_dfs_tgt_counters_open(struct inode *inode, struct file *file)
-{
- struct scsi_qla_host *vha = inode->i_private;
-
- return single_open(file, qla_dfs_tgt_counters_show, vha);
-}
-
-static const struct file_operations dfs_tgt_counters_ops = {
- .open = qla_dfs_tgt_counters_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(qla_dfs_tgt_counters);
static int
qla2x00_dfs_fce_show(struct seq_file *s, void *unused)
@@ -460,23 +554,35 @@
create_nodes:
ha->dfs_fw_resource_cnt = debugfs_create_file("fw_resource_count",
- S_IRUSR, ha->dfs_dir, vha, &dfs_fw_resource_cnt_ops);
+ S_IRUSR, ha->dfs_dir, vha, &qla_dfs_fw_resource_cnt_fops);
ha->dfs_tgt_counters = debugfs_create_file("tgt_counters", S_IRUSR,
- ha->dfs_dir, vha, &dfs_tgt_counters_ops);
+ ha->dfs_dir, vha, &qla_dfs_tgt_counters_fops);
ha->tgt.dfs_tgt_port_database = debugfs_create_file("tgt_port_database",
- S_IRUSR, ha->dfs_dir, vha, &dfs_tgt_port_database_ops);
+ S_IRUSR, ha->dfs_dir, vha, &qla2x00_dfs_tgt_port_database_fops);
ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, vha,
&dfs_fce_ops);
ha->tgt.dfs_tgt_sess = debugfs_create_file("tgt_sess",
- S_IRUSR, ha->dfs_dir, vha, &dfs_tgt_sess_ops);
+ S_IRUSR, ha->dfs_dir, vha, &qla2x00_dfs_tgt_sess_fops);
- if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha))
+ if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) {
ha->tgt.dfs_naqp = debugfs_create_file("naqp",
0400, ha->dfs_dir, vha, &dfs_naqp_ops);
+ if (!ha->tgt.dfs_naqp) {
+ ql_log(ql_log_warn, vha, 0xd011,
+ "Unable to create debugFS naqp node.\n");
+ goto out;
+ }
+ }
+ vha->dfs_rport_root = debugfs_create_dir("rports", ha->dfs_dir);
+ if (!vha->dfs_rport_root) {
+ ql_log(ql_log_warn, vha, 0xd012,
+ "Unable to create debugFS rports node.\n");
+ goto out;
+ }
out:
return 0;
}
@@ -516,6 +622,11 @@
ha->dfs_fce = NULL;
}
+ if (vha->dfs_rport_root) {
+ debugfs_remove_recursive(vha->dfs_rport_root);
+ vha->dfs_rport_root = NULL;
+ }
+
if (ha->dfs_dir) {
debugfs_remove(ha->dfs_dir);
ha->dfs_dir = NULL;
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 9dc09c1..12b689e 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#ifndef __QLA_FW_H
#define __QLA_FW_H
@@ -31,6 +30,9 @@
#define PDO_FORCE_ADISC BIT_1
#define PDO_FORCE_PLOGI BIT_0
+struct buffer_credit_24xx {
+ u32 parameter[28];
+};
#define PORT_DATABASE_24XX_SIZE 64
struct port_database_24xx {
@@ -131,28 +133,28 @@
struct nvram_24xx {
/* NVRAM header. */
uint8_t id[4];
- uint16_t nvram_version;
+ __le16 nvram_version;
uint16_t reserved_0;
/* Firmware Initialization Control Block. */
- uint16_t version;
+ __le16 version;
uint16_t reserved_1;
- __le16 frame_payload_size;
- uint16_t execution_throttle;
- uint16_t exchange_count;
- uint16_t hard_address;
+ __le16 frame_payload_size;
+ __le16 execution_throttle;
+ __le16 exchange_count;
+ __le16 hard_address;
uint8_t port_name[WWN_SIZE];
uint8_t node_name[WWN_SIZE];
- uint16_t login_retry_count;
- uint16_t link_down_on_nos;
- uint16_t interrupt_delay_timer;
- uint16_t login_timeout;
+ __le16 login_retry_count;
+ __le16 link_down_on_nos;
+ __le16 interrupt_delay_timer;
+ __le16 login_timeout;
- uint32_t firmware_options_1;
- uint32_t firmware_options_2;
- uint32_t firmware_options_3;
+ __le32 firmware_options_1;
+ __le32 firmware_options_2;
+ __le32 firmware_options_3;
/* Offset 56. */
@@ -175,7 +177,7 @@
* BIT 11-13 = Output Emphasis 4G
* BIT 14-15 = Reserved
*/
- uint16_t seriallink_options[4];
+ __le16 seriallink_options[4];
uint16_t reserved_2[16];
@@ -215,25 +217,25 @@
*
* BIT 16-31 =
*/
- uint32_t host_p;
+ __le32 host_p;
uint8_t alternate_port_name[WWN_SIZE];
uint8_t alternate_node_name[WWN_SIZE];
uint8_t boot_port_name[WWN_SIZE];
- uint16_t boot_lun_number;
+ __le16 boot_lun_number;
uint16_t reserved_8;
uint8_t alt1_boot_port_name[WWN_SIZE];
- uint16_t alt1_boot_lun_number;
+ __le16 alt1_boot_lun_number;
uint16_t reserved_9;
uint8_t alt2_boot_port_name[WWN_SIZE];
- uint16_t alt2_boot_lun_number;
+ __le16 alt2_boot_lun_number;
uint16_t reserved_10;
uint8_t alt3_boot_port_name[WWN_SIZE];
- uint16_t alt3_boot_lun_number;
+ __le16 alt3_boot_lun_number;
uint16_t reserved_11;
/*
@@ -246,23 +248,23 @@
* BIT 6 = Reserved
* BIT 7-31 =
*/
- uint32_t efi_parameters;
+ __le32 efi_parameters;
uint8_t reset_delay;
uint8_t reserved_12;
uint16_t reserved_13;
- uint16_t boot_id_number;
+ __le16 boot_id_number;
uint16_t reserved_14;
- uint16_t max_luns_per_target;
+ __le16 max_luns_per_target;
uint16_t reserved_15;
- uint16_t port_down_retry_count;
- uint16_t link_down_timeout;
+ __le16 port_down_retry_count;
+ __le16 link_down_timeout;
/* FCode parameters. */
- uint16_t fcode_parameter;
+ __le16 fcode_parameter;
uint16_t reserved_16[3];
@@ -272,13 +274,13 @@
uint8_t prev_drv_ver_minor;
uint8_t prev_drv_ver_subminor;
- uint16_t prev_bios_ver_major;
- uint16_t prev_bios_ver_minor;
+ __le16 prev_bios_ver_major;
+ __le16 prev_bios_ver_minor;
- uint16_t prev_efi_ver_major;
- uint16_t prev_efi_ver_minor;
+ __le16 prev_efi_ver_major;
+ __le16 prev_efi_ver_minor;
- uint16_t prev_fw_ver_major;
+ __le16 prev_fw_ver_major;
uint8_t prev_fw_ver_minor;
uint8_t prev_fw_ver_subminor;
@@ -306,7 +308,7 @@
uint16_t subsystem_vendor_id;
uint16_t subsystem_device_id;
- uint32_t checksum;
+ __le32 checksum;
};
/*
@@ -315,46 +317,46 @@
*/
#define ICB_VERSION 1
struct init_cb_24xx {
- uint16_t version;
+ __le16 version;
uint16_t reserved_1;
- uint16_t frame_payload_size;
- uint16_t execution_throttle;
- uint16_t exchange_count;
+ __le16 frame_payload_size;
+ __le16 execution_throttle;
+ __le16 exchange_count;
- uint16_t hard_address;
+ __le16 hard_address;
uint8_t port_name[WWN_SIZE]; /* Big endian. */
uint8_t node_name[WWN_SIZE]; /* Big endian. */
- uint16_t response_q_inpointer;
- uint16_t request_q_outpointer;
+ __le16 response_q_inpointer;
+ __le16 request_q_outpointer;
- uint16_t login_retry_count;
+ __le16 login_retry_count;
- uint16_t prio_request_q_outpointer;
+ __le16 prio_request_q_outpointer;
- uint16_t response_q_length;
- uint16_t request_q_length;
+ __le16 response_q_length;
+ __le16 request_q_length;
- uint16_t link_down_on_nos; /* Milliseconds. */
+ __le16 link_down_on_nos; /* Milliseconds. */
- uint16_t prio_request_q_length;
+ __le16 prio_request_q_length;
__le64 request_q_address __packed;
__le64 response_q_address __packed;
__le64 prio_request_q_address __packed;
- uint16_t msix;
- uint16_t msix_atio;
+ __le16 msix;
+ __le16 msix_atio;
uint8_t reserved_2[4];
- uint16_t atio_q_inpointer;
- uint16_t atio_q_length;
- __le64 atio_q_address __packed;
+ __le16 atio_q_inpointer;
+ __le16 atio_q_length;
+ __le64 atio_q_address __packed;
- uint16_t interrupt_delay_timer; /* 100us increments. */
- uint16_t login_timeout;
+ __le16 interrupt_delay_timer; /* 100us increments. */
+ __le16 login_timeout;
/*
* BIT 0 = Enable Hard Loop Id
@@ -375,7 +377,7 @@
* BIT 14 = Node Name Option
* BIT 15-31 = Reserved
*/
- uint32_t firmware_options_1;
+ __le32 firmware_options_1;
/*
* BIT 0 = Operation Mode bit 0
@@ -396,7 +398,7 @@
* BIT 14 = Enable Target PRLI Control
* BIT 15-31 = Reserved
*/
- uint32_t firmware_options_2;
+ __le32 firmware_options_2;
/*
* BIT 0 = Reserved
@@ -422,9 +424,9 @@
* BIT 30 = Enable request queue 0 out index shadowing
* BIT 31 = Reserved
*/
- uint32_t firmware_options_3;
- uint16_t qos;
- uint16_t rid;
+ __le32 firmware_options_3;
+ __le16 qos;
+ __le16 rid;
uint8_t reserved_3[20];
};
@@ -440,27 +442,27 @@
uint32_t handle; /* System handle. */
- uint16_t nport_handle; /* N_PORT hanlde. */
+ __le16 nport_handle; /* N_PORT handle. */
- uint16_t timeout; /* Commnad timeout. */
+ __le16 timeout; /* Command timeout. */
- uint16_t wr_dseg_count; /* Write Data segment count. */
- uint16_t rd_dseg_count; /* Read Data segment count. */
+ __le16 wr_dseg_count; /* Write Data segment count. */
+ __le16 rd_dseg_count; /* Read Data segment count. */
struct scsi_lun lun; /* FCP LUN (BE). */
- uint16_t control_flags; /* Control flags. */
+ __le16 control_flags; /* Control flags. */
#define BD_WRAP_BACK BIT_3
#define BD_READ_DATA BIT_1
#define BD_WRITE_DATA BIT_0
- uint16_t fcp_cmnd_dseg_len; /* Data segment length. */
+ __le16 fcp_cmnd_dseg_len; /* Data segment length. */
__le64 fcp_cmnd_dseg_address __packed;/* Data segment address. */
uint16_t reserved[2]; /* Reserved */
- uint32_t rd_byte_count; /* Total Byte count Read. */
- uint32_t wr_byte_count; /* Total Byte count write. */
+ __le32 rd_byte_count; /* Total Byte count Read. */
+ __le32 wr_byte_count; /* Total Byte count write. */
uint8_t port_id[3]; /* PortID of destination port.*/
uint8_t vp_index;
@@ -477,28 +479,28 @@
uint32_t handle; /* System handle. */
- uint16_t nport_handle; /* N_PORT handle. */
- uint16_t timeout; /* Command timeout. */
+ __le16 nport_handle; /* N_PORT handle. */
+ __le16 timeout; /* Command timeout. */
- uint16_t dseg_count; /* Data segment count. */
+ __le16 dseg_count; /* Data segment count. */
- uint16_t fcp_rsp_dsd_len; /* FCP_RSP DSD length. */
+ __le16 fcp_rsp_dsd_len; /* FCP_RSP DSD length. */
struct scsi_lun lun; /* FCP LUN (BE). */
- uint16_t control_flags; /* Control flags. */
+ __le16 control_flags; /* Control flags. */
#define CF_DIF_SEG_DESCR_ENABLE BIT_3
#define CF_DATA_SEG_DESCR_ENABLE BIT_2
#define CF_READ_DATA BIT_1
#define CF_WRITE_DATA BIT_0
- uint16_t fcp_cmnd_dseg_len; /* Data segment length. */
+ __le16 fcp_cmnd_dseg_len; /* Data segment length. */
/* Data segment address. */
__le64 fcp_cmnd_dseg_address __packed;
/* Data segment address. */
__le64 fcp_rsp_dseg_address __packed;
- uint32_t byte_count; /* Total byte count. */
+ __le32 byte_count; /* Total byte count. */
uint8_t port_id[3]; /* PortID of destination port. */
uint8_t vp_index;
@@ -515,16 +517,16 @@
uint32_t handle; /* System handle. */
- uint16_t nport_handle; /* N_PORT handle. */
- uint16_t timeout; /* Command timeout. */
+ __le16 nport_handle; /* N_PORT handle. */
+ __le16 timeout; /* Command timeout. */
#define FW_MAX_TIMEOUT 0x1999
- uint16_t dseg_count; /* Data segment count. */
+ __le16 dseg_count; /* Data segment count. */
uint16_t reserved_1;
struct scsi_lun lun; /* FCP LUN (BE). */
- uint16_t task_mgmt_flags; /* Task management flags. */
+ __le16 task_mgmt_flags; /* Task management flags. */
#define TMF_CLEAR_ACA BIT_14
#define TMF_TARGET_RESET BIT_13
#define TMF_LUN_RESET BIT_12
@@ -544,7 +546,7 @@
uint8_t crn;
uint8_t fcp_cdb[MAX_CMDSZ]; /* SCSI command words. */
- uint32_t byte_count; /* Total byte count. */
+ __le32 byte_count; /* Total byte count. */
uint8_t port_id[3]; /* PortID of destination port. */
uint8_t vp_index;
@@ -562,29 +564,29 @@
uint32_t handle; /* System handle. */
- uint16_t nport_handle; /* N_PORT handle. */
- uint16_t timeout; /* Command timeout. */
+ __le16 nport_handle; /* N_PORT handle. */
+ __le16 timeout; /* Command timeout. */
- uint16_t dseg_count; /* Data segment count. */
+ __le16 dseg_count; /* Data segment count. */
- uint16_t fcp_rsp_dseg_len; /* FCP_RSP DSD length. */
+ __le16 fcp_rsp_dseg_len; /* FCP_RSP DSD length. */
struct scsi_lun lun; /* FCP LUN (BE). */
- uint16_t control_flags; /* Control flags. */
+ __le16 control_flags; /* Control flags. */
- uint16_t fcp_cmnd_dseg_len; /* Data segment length. */
+ __le16 fcp_cmnd_dseg_len; /* Data segment length. */
__le64 fcp_cmnd_dseg_address __packed;
/* Data segment address. */
__le64 fcp_rsp_dseg_address __packed;
- uint32_t byte_count; /* Total byte count. */
+ __le32 byte_count; /* Total byte count. */
uint8_t port_id[3]; /* PortID of destination port. */
uint8_t vp_index;
__le64 crc_context_address __packed; /* Data segment address. */
- uint16_t crc_context_len; /* Data segment length. */
+ __le16 crc_context_len; /* Data segment length. */
uint16_t reserved_1; /* MUST be set to 0. */
};
@@ -601,32 +603,32 @@
uint32_t handle; /* System handle. */
- uint16_t comp_status; /* Completion status. */
- uint16_t ox_id; /* OX_ID used by the firmware. */
+ __le16 comp_status; /* Completion status. */
+ __le16 ox_id; /* OX_ID used by the firmware. */
- uint32_t residual_len; /* FW calc residual transfer length. */
+ __le32 residual_len; /* FW calc residual transfer length. */
union {
- uint16_t reserved_1;
- uint16_t nvme_rsp_pyld_len;
+ __le16 reserved_1;
+ __le16 nvme_rsp_pyld_len;
};
- uint16_t state_flags; /* State flags. */
+ __le16 state_flags; /* State flags. */
#define SF_TRANSFERRED_DATA BIT_11
#define SF_NVME_ERSP BIT_6
#define SF_FCP_RSP_DMA BIT_0
- uint16_t retry_delay;
- uint16_t scsi_status; /* SCSI status. */
+ __le16 status_qualifier;
+ __le16 scsi_status; /* SCSI status. */
#define SS_CONFIRMATION_REQ BIT_12
- uint32_t rsp_residual_count; /* FCP RSP residual count. */
+ __le32 rsp_residual_count; /* FCP RSP residual count. */
- uint32_t sense_len; /* FCP SENSE length. */
+ __le32 sense_len; /* FCP SENSE length. */
union {
struct {
- uint32_t rsp_data_len; /* FCP response data length */
+ __le32 rsp_data_len; /* FCP response data length */
uint8_t data[28]; /* FCP rsp/sense information */
};
struct nvme_fc_ersp_iu nvme_ersp;
@@ -669,7 +671,7 @@
uint32_t handle; /* System handle. */
- uint16_t nport_handle; /* N_PORT handle. */
+ __le16 nport_handle; /* N_PORT handle. */
uint8_t modifier; /* Modifier (7-0). */
#define MK_SYNC_ID_LUN 0 /* Synchronize ID/LUN */
@@ -698,28 +700,72 @@
uint32_t handle; /* System handle. */
- uint16_t comp_status; /* Completion status. */
+ __le16 comp_status; /* Completion status. */
- uint16_t nport_handle; /* N_PORT handle. */
+ __le16 nport_handle; /* N_PORT handle. */
- uint16_t cmd_dsd_count;
+ __le16 cmd_dsd_count;
uint8_t vp_index;
uint8_t reserved_1;
- uint16_t timeout; /* Command timeout. */
+ __le16 timeout; /* Command timeout. */
uint16_t reserved_2;
- uint16_t rsp_dsd_count;
+ __le16 rsp_dsd_count;
uint8_t reserved_3[10];
- uint32_t rsp_byte_count;
- uint32_t cmd_byte_count;
+ __le32 rsp_byte_count;
+ __le32 cmd_byte_count;
struct dsd64 dsd[2];
};
+#define PURX_ELS_HEADER_SIZE 0x18
+
+/*
+ * ISP queue - PUREX IOCB entry structure definition
+ */
+#define PUREX_IOCB_TYPE 0x51 /* CT Pass Through IOCB entry */
+struct purex_entry_24xx {
+ uint8_t entry_type; /* Entry type. */
+ uint8_t entry_count; /* Entry count. */
+ uint8_t sys_define; /* System defined. */
+ uint8_t entry_status; /* Entry Status. */
+
+ __le16 reserved1;
+ uint8_t vp_idx;
+ uint8_t reserved2;
+
+ __le16 status_flags;
+ __le16 nport_handle;
+
+ __le16 frame_size;
+ __le16 trunc_frame_size;
+
+ __le32 rx_xchg_addr;
+
+ uint8_t d_id[3];
+ uint8_t r_ctl;
+
+ uint8_t s_id[3];
+ uint8_t cs_ctl;
+
+ uint8_t f_ctl[3];
+ uint8_t type;
+
+ __le16 seq_cnt;
+ uint8_t df_ctl;
+ uint8_t seq_id;
+
+ __le16 rx_id;
+ __le16 ox_id;
+ __le32 param;
+
+ uint8_t els_frame_payload[20];
+};
+
/*
* ISP queue - ELS Pass-Through entry structure definition.
*/
@@ -732,27 +778,26 @@
uint32_t handle; /* System handle. */
- uint16_t reserved_1;
+ __le16 comp_status; /* response only */
+ __le16 nport_handle;
- uint16_t nport_handle; /* N_PORT handle. */
-
- uint16_t tx_dsd_count;
+ __le16 tx_dsd_count;
uint8_t vp_index;
uint8_t sof_type;
#define EST_SOFI3 (1 << 4)
#define EST_SOFI2 (3 << 4)
- uint32_t rx_xchg_address; /* Receive exchange address. */
- uint16_t rx_dsd_count;
+ __le32 rx_xchg_address; /* Receive exchange address. */
+ __le16 rx_dsd_count;
uint8_t opcode;
uint8_t reserved_2;
- uint8_t port_id[3];
+ uint8_t d_id[3];
uint8_t s_id[3];
- uint16_t control_flags; /* Control flags. */
+ __le16 control_flags; /* Control flags. */
#define ECF_PAYLOAD_DESCR_MASK (BIT_15|BIT_14|BIT_13)
#define EPD_ELS_COMMAND (0 << 13)
#define EPD_ELS_ACC (1 << 13)
@@ -761,13 +806,24 @@
#define ECF_CLR_PASSTHRU_PEND BIT_12
#define ECF_INCL_FRAME_HDR BIT_11
- __le32 rx_byte_count;
- __le32 tx_byte_count;
+ union {
+ struct {
+ __le32 rx_byte_count;
+ __le32 tx_byte_count;
- __le64 tx_address __packed; /* Data segment 0 address. */
- __le32 tx_len; /* Data segment 0 length. */
- __le64 rx_address __packed; /* Data segment 1 address. */
- __le32 rx_len; /* Data segment 1 length. */
+ __le64 tx_address __packed; /* DSD 0 address. */
+ __le32 tx_len; /* DSD 0 length. */
+
+ __le64 rx_address __packed; /* DSD 1 address. */
+ __le32 rx_len; /* DSD 1 length. */
+ };
+ struct {
+ __le32 total_byte_count;
+ __le32 error_subcode_1;
+ __le32 error_subcode_2;
+ __le32 error_subcode_3;
+ };
+ };
};
struct els_sts_entry_24xx {
@@ -776,32 +832,33 @@
uint8_t sys_define; /* System Defined. */
uint8_t entry_status; /* Entry Status. */
- uint32_t handle; /* System handle. */
+ __le32 handle; /* System handle. */
- uint16_t comp_status;
+ __le16 comp_status;
- uint16_t nport_handle; /* N_PORT handle. */
+ __le16 nport_handle; /* N_PORT handle. */
- uint16_t reserved_1;
+ __le16 reserved_1;
uint8_t vp_index;
uint8_t sof_type;
- uint32_t rx_xchg_address; /* Receive exchange address. */
- uint16_t reserved_2;
+ __le32 rx_xchg_address; /* Receive exchange address. */
+ __le16 reserved_2;
uint8_t opcode;
uint8_t reserved_3;
- uint8_t port_id[3];
- uint8_t reserved_4;
+ uint8_t d_id[3];
+ uint8_t s_id[3];
- uint16_t reserved_5;
+ __le16 control_flags; /* Control flags. */
+ __le32 total_byte_count;
+ __le32 error_subcode_1;
+ __le32 error_subcode_2;
+ __le32 error_subcode_3;
- uint16_t control_flags; /* Control flags. */
- uint32_t total_byte_count;
- uint32_t error_subcode_1;
- uint32_t error_subcode_2;
+ __le32 reserved_4[4];
};
/*
* ISP queue - Mailbox Command entry structure definition.
@@ -828,12 +885,12 @@
uint32_t handle; /* System handle. */
- uint16_t comp_status; /* Completion status. */
+ __le16 comp_status; /* Completion status. */
#define CS_LOGIO_ERROR 0x31 /* Login/Logout IOCB error. */
- uint16_t nport_handle; /* N_PORT handle. */
+ __le16 nport_handle; /* N_PORT handle. */
- uint16_t control_flags; /* Control flags. */
+ __le16 control_flags; /* Control flags. */
/* Modifiers. */
#define LCF_INCLUDE_SNS BIT_10 /* Include SNS (FFFFFC) during LOGO. */
#define LCF_FCP2_OVERRIDE BIT_9 /* Set/Reset word 3 of PRLI. */
@@ -862,7 +919,7 @@
uint8_t rsp_size; /* Response size in 32bit words. */
- uint32_t io_parameter[11]; /* General I/O parameters. */
+ __le32 io_parameter[11]; /* General I/O parameters. */
#define LSC_SCODE_NOLINK 0x01
#define LSC_SCODE_NOIOCB 0x02
#define LSC_SCODE_NOXCB 0x03
@@ -890,17 +947,17 @@
uint32_t handle; /* System handle. */
- uint16_t nport_handle; /* N_PORT handle. */
+ __le16 nport_handle; /* N_PORT handle. */
uint16_t reserved_1;
- uint16_t delay; /* Activity delay in seconds. */
+ __le16 delay; /* Activity delay in seconds. */
- uint16_t timeout; /* Command timeout. */
+ __le16 timeout; /* Command timeout. */
struct scsi_lun lun; /* FCP LUN (BE). */
- uint32_t control_flags; /* Control Flags. */
+ __le32 control_flags; /* Control Flags. */
#define TCF_NOTMCMD_TO_TARGET BIT_31
#define TCF_LUN_RESET BIT_4
#define TCF_ABORT_TASK_SET BIT_3
@@ -925,15 +982,15 @@
uint32_t handle; /* System handle. */
- uint16_t nport_handle; /* N_PORT handle. */
+ __le16 nport_handle; /* N_PORT handle. */
/* or Completion status. */
- uint16_t options; /* Options. */
+ __le16 options; /* Options. */
#define AOF_NO_ABTS BIT_0 /* Do not send any ABTS. */
uint32_t handle_to_abort; /* System handle to abort. */
- uint16_t req_que_no;
+ __le16 req_que_no;
uint8_t reserved_1[30];
uint8_t port_id[3]; /* PortID of destination port. */
@@ -942,11 +999,96 @@
uint8_t reserved_2[12];
};
+#define ABTS_RCV_TYPE 0x54
+#define ABTS_RSP_TYPE 0x55
+struct abts_entry_24xx {
+ uint8_t entry_type;
+ uint8_t entry_count;
+ uint8_t handle_count;
+ uint8_t entry_status;
+
+ __le32 handle; /* type 0x55 only */
+
+ __le16 comp_status; /* type 0x55 only */
+ __le16 nport_handle; /* type 0x54 only */
+
+ __le16 control_flags; /* type 0x55 only */
+ uint8_t vp_idx;
+ uint8_t sof_type; /* sof_type is upper nibble */
+
+ __le32 rx_xch_addr;
+
+ uint8_t d_id[3];
+ uint8_t r_ctl;
+
+ uint8_t s_id[3];
+ uint8_t cs_ctl;
+
+ uint8_t f_ctl[3];
+ uint8_t type;
+
+ __le16 seq_cnt;
+ uint8_t df_ctl;
+ uint8_t seq_id;
+
+ __le16 rx_id;
+ __le16 ox_id;
+
+ __le32 param;
+
+ union {
+ struct {
+ __le32 subcode3;
+ __le32 rsvd;
+ __le32 subcode1;
+ __le32 subcode2;
+ } error;
+ struct {
+ __le16 rsrvd1;
+ uint8_t last_seq_id;
+ uint8_t seq_id_valid;
+ __le16 aborted_rx_id;
+ __le16 aborted_ox_id;
+ __le16 high_seq_cnt;
+ __le16 low_seq_cnt;
+ } ba_acc;
+ struct {
+ uint8_t vendor_unique;
+ uint8_t explanation;
+ uint8_t reason;
+ } ba_rjt;
+ } payload;
+
+ __le32 rx_xch_addr_to_abort;
+} __packed;
+
+/* ABTS payload explanation values */
+#define BA_RJT_EXP_NO_ADDITIONAL 0
+#define BA_RJT_EXP_INV_OX_RX_ID 3
+#define BA_RJT_EXP_SEQ_ABORTED 5
+
+/* ABTS payload reason values */
+#define BA_RJT_RSN_INV_CMD_CODE 1
+#define BA_RJT_RSN_LOGICAL_ERROR 3
+#define BA_RJT_RSN_LOGICAL_BUSY 5
+#define BA_RJT_RSN_PROTOCOL_ERROR 7
+#define BA_RJT_RSN_UNABLE_TO_PERFORM 9
+#define BA_RJT_RSN_VENDOR_SPECIFIC 0xff
+
+/* FC_F values */
+#define FC_TYPE_BLD 0x000 /* Basic link data */
+#define FC_F_CTL_RSP_CNTXT 0x800000 /* Responder of exchange */
+#define FC_F_CTL_LAST_SEQ 0x100000 /* Last sequence */
+#define FC_F_CTL_END_SEQ 0x80000 /* Last sequence */
+#define FC_F_CTL_SEQ_INIT 0x010000 /* Sequence initiative */
+#define FC_ROUTING_BLD 0x80 /* Basic link data frame */
+#define FC_R_CTL_BLD_BA_ACC 0x04 /* BA_ACC (basic accept) */
+
/*
* ISP I/O Register Set structure definitions.
*/
struct device_reg_24xx {
- uint32_t flash_addr; /* Flash/NVRAM BIOS address. */
+ __le32 flash_addr; /* Flash/NVRAM BIOS address. */
#define FARX_DATA_FLAG BIT_31
#define FARX_ACCESS_FLASH_CONF 0x7FFD0000
#define FARX_ACCESS_FLASH_DATA 0x7FF00000
@@ -997,9 +1139,9 @@
#define HW_EVENT_NVRAM_CHKSUM_ERR 0xF023
#define HW_EVENT_FLASH_FW_ERR 0xF024
- uint32_t flash_data; /* Flash/NVRAM BIOS data. */
+ __le32 flash_data; /* Flash/NVRAM BIOS data. */
- uint32_t ctrl_status; /* Control/Status. */
+ __le32 ctrl_status; /* Control/Status. */
#define CSRX_FLASH_ACCESS_ERROR BIT_18 /* Flash/NVRAM Access Error. */
#define CSRX_DMA_ACTIVE BIT_17 /* DMA Active status. */
#define CSRX_DMA_SHUTDOWN BIT_16 /* DMA Shutdown control status. */
@@ -1025,35 +1167,35 @@
#define CSRX_FLASH_ENABLE BIT_1 /* Flash BIOS Read/Write enable. */
#define CSRX_ISP_SOFT_RESET BIT_0 /* ISP soft reset. */
- uint32_t ictrl; /* Interrupt control. */
+ __le32 ictrl; /* Interrupt control. */
#define ICRX_EN_RISC_INT BIT_3 /* Enable RISC interrupts on PCI. */
- uint32_t istatus; /* Interrupt status. */
+ __le32 istatus; /* Interrupt status. */
#define ISRX_RISC_INT BIT_3 /* RISC interrupt. */
- uint32_t unused_1[2]; /* Gap. */
+ __le32 unused_1[2]; /* Gap. */
/* Request Queue. */
- uint32_t req_q_in; /* In-Pointer. */
- uint32_t req_q_out; /* Out-Pointer. */
+ __le32 req_q_in; /* In-Pointer. */
+ __le32 req_q_out; /* Out-Pointer. */
/* Response Queue. */
- uint32_t rsp_q_in; /* In-Pointer. */
- uint32_t rsp_q_out; /* Out-Pointer. */
+ __le32 rsp_q_in; /* In-Pointer. */
+ __le32 rsp_q_out; /* Out-Pointer. */
/* Priority Request Queue. */
- uint32_t preq_q_in; /* In-Pointer. */
- uint32_t preq_q_out; /* Out-Pointer. */
+ __le32 preq_q_in; /* In-Pointer. */
+ __le32 preq_q_out; /* Out-Pointer. */
- uint32_t unused_2[2]; /* Gap. */
+ __le32 unused_2[2]; /* Gap. */
/* ATIO Queue. */
- uint32_t atio_q_in; /* In-Pointer. */
- uint32_t atio_q_out; /* Out-Pointer. */
+ __le32 atio_q_in; /* In-Pointer. */
+ __le32 atio_q_out; /* Out-Pointer. */
- uint32_t host_status;
+ __le32 host_status;
#define HSRX_RISC_INT BIT_15 /* RISC to Host interrupt. */
#define HSRX_RISC_PAUSED BIT_8 /* RISC Paused. */
- uint32_t hccr; /* Host command & control register. */
+ __le32 hccr; /* Host command & control register. */
/* HCCR statuses. */
#define HCCRX_HOST_INT BIT_6 /* Host to RISC interrupt bit. */
#define HCCRX_RISC_RESET BIT_5 /* RISC Reset mode bit. */
@@ -1075,7 +1217,7 @@
/* Clear RISC to PCI interrupt. */
#define HCCRX_CLR_RISC_INT 0xA0000000
- uint32_t gpiod; /* GPIO Data register. */
+ __le32 gpiod; /* GPIO Data register. */
/* LED update mask. */
#define GPDX_LED_UPDATE_MASK (BIT_20|BIT_19|BIT_18)
@@ -1094,7 +1236,7 @@
/* Data in/out. */
#define GPDX_DATA_INOUT (BIT_1|BIT_0)
- uint32_t gpioe; /* GPIO Enable register. */
+ __le32 gpioe; /* GPIO Enable register. */
/* Enable update mask. */
#define GPEX_ENABLE_UPDATE_MASK (BIT_17|BIT_16)
/* Enable update mask. */
@@ -1102,56 +1244,56 @@
/* Enable. */
#define GPEX_ENABLE (BIT_1|BIT_0)
- uint32_t iobase_addr; /* I/O Bus Base Address register. */
+ __le32 iobase_addr; /* I/O Bus Base Address register. */
- uint32_t unused_3[10]; /* Gap. */
+ __le32 unused_3[10]; /* Gap. */
- uint16_t mailbox0;
- uint16_t mailbox1;
- uint16_t mailbox2;
- uint16_t mailbox3;
- uint16_t mailbox4;
- uint16_t mailbox5;
- uint16_t mailbox6;
- uint16_t mailbox7;
- uint16_t mailbox8;
- uint16_t mailbox9;
- uint16_t mailbox10;
- uint16_t mailbox11;
- uint16_t mailbox12;
- uint16_t mailbox13;
- uint16_t mailbox14;
- uint16_t mailbox15;
- uint16_t mailbox16;
- uint16_t mailbox17;
- uint16_t mailbox18;
- uint16_t mailbox19;
- uint16_t mailbox20;
- uint16_t mailbox21;
- uint16_t mailbox22;
- uint16_t mailbox23;
- uint16_t mailbox24;
- uint16_t mailbox25;
- uint16_t mailbox26;
- uint16_t mailbox27;
- uint16_t mailbox28;
- uint16_t mailbox29;
- uint16_t mailbox30;
- uint16_t mailbox31;
+ __le16 mailbox0;
+ __le16 mailbox1;
+ __le16 mailbox2;
+ __le16 mailbox3;
+ __le16 mailbox4;
+ __le16 mailbox5;
+ __le16 mailbox6;
+ __le16 mailbox7;
+ __le16 mailbox8;
+ __le16 mailbox9;
+ __le16 mailbox10;
+ __le16 mailbox11;
+ __le16 mailbox12;
+ __le16 mailbox13;
+ __le16 mailbox14;
+ __le16 mailbox15;
+ __le16 mailbox16;
+ __le16 mailbox17;
+ __le16 mailbox18;
+ __le16 mailbox19;
+ __le16 mailbox20;
+ __le16 mailbox21;
+ __le16 mailbox22;
+ __le16 mailbox23;
+ __le16 mailbox24;
+ __le16 mailbox25;
+ __le16 mailbox26;
+ __le16 mailbox27;
+ __le16 mailbox28;
+ __le16 mailbox29;
+ __le16 mailbox30;
+ __le16 mailbox31;
- uint32_t iobase_window;
- uint32_t iobase_c4;
- uint32_t iobase_c8;
- uint32_t unused_4_1[6]; /* Gap. */
- uint32_t iobase_q;
- uint32_t unused_5[2]; /* Gap. */
- uint32_t iobase_select;
- uint32_t unused_6[2]; /* Gap. */
- uint32_t iobase_sdata;
+ __le32 iobase_window;
+ __le32 iobase_c4;
+ __le32 iobase_c8;
+ __le32 unused_4_1[6]; /* Gap. */
+ __le32 iobase_q;
+ __le32 unused_5[2]; /* Gap. */
+ __le32 iobase_select;
+ __le32 unused_6[2]; /* Gap. */
+ __le32 iobase_sdata;
};
/* RISC-RISC semaphore register PCI offet */
#define RISC_REGISTER_BASE_OFFSET 0x7010
-#define RISC_REGISTER_WINDOW_OFFET 0x6
+#define RISC_REGISTER_WINDOW_OFFSET 0x6
/* RISC-RISC semaphore/flag register (risc address 0x7016) */
@@ -1213,8 +1355,8 @@
struct mid_init_cb_24xx {
struct init_cb_24xx init_cb;
- uint16_t count;
- uint16_t options;
+ __le16 count;
+ __le16 options;
struct mid_conf_entry_24xx entries[MAX_MULTI_ID_FABRIC];
};
@@ -1248,27 +1390,27 @@
uint32_t handle; /* System handle. */
- uint16_t vp_idx_failed;
+ __le16 vp_idx_failed;
- uint16_t comp_status; /* Completion status. */
+ __le16 comp_status; /* Completion status. */
#define CS_VCE_IOCB_ERROR 0x01 /* Error processing IOCB */
#define CS_VCE_ACQ_ID_ERROR 0x02 /* Error while acquireing ID. */
#define CS_VCE_BUSY 0x05 /* Firmware not ready to accept cmd. */
- uint16_t command;
+ __le16 command;
#define VCE_COMMAND_ENABLE_VPS 0x00 /* Enable VPs. */
#define VCE_COMMAND_DISABLE_VPS 0x08 /* Disable VPs. */
#define VCE_COMMAND_DISABLE_VPS_REINIT 0x09 /* Disable VPs and reinit link. */
#define VCE_COMMAND_DISABLE_VPS_LOGO 0x0a /* Disable VPs and LOGO ports. */
#define VCE_COMMAND_DISABLE_VPS_LOGO_ALL 0x0b /* Disable VPs and LOGO ports. */
- uint16_t vp_count;
+ __le16 vp_count;
uint8_t vp_idx_map[16];
- uint16_t flags;
- uint16_t id;
+ __le16 flags;
+ __le16 id;
uint16_t reserved_4;
- uint16_t hopct;
+ __le16 hopct;
uint8_t reserved_5[24];
};
@@ -1284,12 +1426,12 @@
uint32_t handle; /* System handle. */
- uint16_t flags;
+ __le16 flags;
#define CS_VF_BIND_VPORTS_TO_VF BIT_0
#define CS_VF_SET_QOS_OF_VPORTS BIT_1
#define CS_VF_SET_HOPS_OF_VPORTS BIT_2
- uint16_t comp_status; /* Completion status. */
+ __le16 comp_status; /* Completion status. */
#define CS_VCT_STS_ERROR 0x01 /* Specified VPs were not disabled. */
#define CS_VCT_CNT_ERROR 0x02 /* Invalid VP count. */
#define CS_VCT_ERROR 0x03 /* Unknown error. */
@@ -1316,9 +1458,9 @@
uint16_t reserved_vp2;
uint8_t port_name_idx2[WWN_SIZE];
uint8_t node_name_idx2[WWN_SIZE];
- uint16_t id;
+ __le16 id;
uint16_t reserved_4;
- uint16_t hopct;
+ __le16 hopct;
uint8_t reserved_5[2];
};
@@ -1345,7 +1487,7 @@
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
- uint32_t resv1;
+ __le32 resv1;
uint8_t vp_acquired;
uint8_t vp_setup;
uint8_t vp_idx; /* Format 0=reserved */
@@ -1354,12 +1496,12 @@
uint8_t port_id[3];
uint8_t format;
union {
- struct {
+ struct _f0 {
/* format 0 loop */
uint8_t vp_idx_map[16];
uint8_t reserved_4[32];
} f0;
- struct {
+ struct _f1 {
/* format 1 fabric */
uint8_t vpstat1_subcode; /* vp_status=1 subcode */
uint8_t flags;
@@ -1381,21 +1523,22 @@
uint16_t bbcr;
uint8_t reserved_5[6];
} f1;
- struct { /* format 2: N2N direct connect */
- uint8_t vpstat1_subcode;
- uint8_t flags;
- uint16_t rsv6;
- uint8_t rsv2[12];
+ struct _f2 { /* format 2: N2N direct connect */
+ uint8_t vpstat1_subcode;
+ uint8_t flags;
+ uint16_t fip_flags;
+ uint8_t rsv2[12];
- uint8_t ls_rjt_vendor;
- uint8_t ls_rjt_explanation;
- uint8_t ls_rjt_reason;
- uint8_t rsv3[5];
+ uint8_t ls_rjt_vendor;
+ uint8_t ls_rjt_explanation;
+ uint8_t ls_rjt_reason;
+ uint8_t rsv3[5];
- uint8_t port_name[8];
- uint8_t node_name[8];
- uint8_t remote_nport_id[4];
- uint32_t reserved_5;
+ uint8_t port_name[8];
+ uint8_t node_name[8];
+ uint16_t bbcr;
+ uint8_t reserved_5[2];
+ uint8_t remote_nport_id[4];
} f2;
} u;
};
@@ -1408,15 +1551,15 @@
uint8_t entry_status; /* Entry Status. */
uint32_t handle; /* System handle. */
- uint16_t comp_status; /* Completion status. */
- uint16_t timeout; /* timeout */
- uint16_t adim_tagging_mode;
+ __le16 comp_status; /* Completion status. */
+ __le16 timeout; /* timeout */
+ __le16 adim_tagging_mode;
- uint16_t vfport_id;
+ __le16 vfport_id;
uint32_t exch_addr;
- uint16_t nport_handle; /* N_PORT handle. */
- uint16_t control_flags;
+ __le16 nport_handle; /* N_PORT handle. */
+ __le16 control_flags;
uint32_t io_parameter_0;
uint32_t io_parameter_1;
__le64 tx_address __packed; /* Data segment 0 address. */
@@ -1431,13 +1574,13 @@
struct qla_fdt_layout {
uint8_t sig[4];
- uint16_t version;
- uint16_t len;
- uint16_t checksum;
+ __le16 version;
+ __le16 len;
+ __le16 checksum;
uint8_t unused1[2];
uint8_t model[16];
- uint16_t man_id;
- uint16_t id;
+ __le16 man_id;
+ __le16 id;
uint8_t flags;
uint8_t erase_cmd;
uint8_t alt_erase_cmd;
@@ -1446,15 +1589,15 @@
uint8_t wrt_sts_reg_cmd;
uint8_t unprotect_sec_cmd;
uint8_t read_man_id_cmd;
- uint32_t block_size;
- uint32_t alt_block_size;
- uint32_t flash_size;
- uint32_t wrt_enable_data;
+ __le32 block_size;
+ __le32 alt_block_size;
+ __le32 flash_size;
+ __le32 wrt_enable_data;
uint8_t read_id_addr_len;
uint8_t wrt_disable_bits;
uint8_t read_dev_id_len;
uint8_t chip_erase_cmd;
- uint16_t read_timeout;
+ __le16 read_timeout;
uint8_t protect_sec_cmd;
uint8_t unused2[65];
};
@@ -1463,18 +1606,11 @@
struct qla_flt_location {
uint8_t sig[4];
- uint16_t start_lo;
- uint16_t start_hi;
+ __le16 start_lo;
+ __le16 start_hi;
uint8_t version;
uint8_t unused[5];
- uint16_t checksum;
-};
-
-struct qla_flt_header {
- uint16_t version;
- uint16_t length;
- uint16_t checksum;
- uint16_t unused;
+ __le16 checksum;
};
#define FLT_REG_FW 0x01
@@ -1529,12 +1665,20 @@
#define FLT_REG_PEP_SEC_28XX 0xF1
struct qla_flt_region {
- uint16_t code;
+ __le16 code;
uint8_t attribute;
uint8_t reserved;
- uint32_t size;
- uint32_t start;
- uint32_t end;
+ __le32 size;
+ __le32 start;
+ __le32 end;
+};
+
+struct qla_flt_header {
+ __le16 version;
+ __le16 length;
+ __le16 checksum;
+ __le16 unused;
+ struct qla_flt_region region[0];
};
#define FLT_REGION_SIZE 16
@@ -1545,18 +1689,18 @@
struct qla_npiv_header {
uint8_t sig[2];
- uint16_t version;
- uint16_t entries;
- uint16_t unused[4];
- uint16_t checksum;
+ __le16 version;
+ __le16 entries;
+ __le16 unused[4];
+ __le16 checksum;
};
struct qla_npiv_entry {
- uint16_t flags;
- uint16_t vf_id;
+ __le16 flags;
+ __le16 vf_id;
uint8_t q_qos;
uint8_t f_qos;
- uint16_t unused1;
+ __le16 unused1;
uint8_t port_name[WWN_SIZE];
uint8_t node_name[WWN_SIZE];
};
@@ -1586,7 +1730,7 @@
uint32_t handle;
- uint16_t options;
+ __le16 options;
#define VCO_DONT_UPDATE_FW BIT_0
#define VCO_FORCE_UPDATE BIT_1
#define VCO_DONT_RESET_UPDATE BIT_2
@@ -1594,18 +1738,18 @@
#define VCO_END_OF_DATA BIT_14
#define VCO_ENABLE_DSD BIT_15
- uint16_t reserved_1;
+ __le16 reserved_1;
- uint16_t data_seg_cnt;
- uint16_t reserved_2[3];
+ __le16 data_seg_cnt;
+ __le16 reserved_2[3];
- uint32_t fw_ver;
- uint32_t exchange_address;
+ __le32 fw_ver;
+ __le32 exchange_address;
- uint32_t reserved_3[3];
- uint32_t fw_size;
- uint32_t fw_seq_size;
- uint32_t relative_offset;
+ __le32 reserved_3[3];
+ __le32 fw_size;
+ __le32 fw_seq_size;
+ __le32 relative_offset;
struct dsd64 dsd;
};
@@ -1618,22 +1762,22 @@
uint32_t handle;
- uint16_t comp_status;
+ __le16 comp_status;
#define CS_VCS_CHIP_FAILURE 0x3
#define CS_VCS_BAD_EXCHANGE 0x8
#define CS_VCS_SEQ_COMPLETEi 0x40
- uint16_t failure_code;
+ __le16 failure_code;
#define VFC_CHECKSUM_ERROR 0x1
#define VFC_INVALID_LEN 0x2
#define VFC_ALREADY_IN_PROGRESS 0x8
- uint16_t reserved_1[4];
+ __le16 reserved_1[4];
- uint32_t fw_ver;
- uint32_t exchange_address;
+ __le32 fw_ver;
+ __le32 exchange_address;
- uint32_t reserved_2[6];
+ __le32 reserved_2[6];
};
#define ACCESS_CHIP_IOCB_TYPE 0x2B
@@ -1645,24 +1789,24 @@
uint32_t handle;
- uint16_t options;
+ __le16 options;
#define ACO_DUMP_MEMORY 0x0
#define ACO_LOAD_MEMORY 0x1
#define ACO_CHANGE_CONFIG_PARAM 0x2
#define ACO_REQUEST_INFO 0x3
- uint16_t reserved1;
+ __le16 reserved1;
- uint16_t dseg_count;
- uint16_t reserved2[3];
+ __le16 dseg_count;
+ __le16 reserved2[3];
- uint32_t parameter1;
- uint32_t parameter2;
- uint32_t parameter3;
+ __le32 parameter1;
+ __le32 parameter2;
+ __le32 parameter3;
- uint32_t reserved3[3];
- uint32_t total_byte_cnt;
- uint32_t reserved4;
+ __le32 reserved3[3];
+ __le32 total_byte_cnt;
+ __le32 reserved4;
struct dsd64 dsd;
};
@@ -1675,11 +1819,11 @@
uint32_t handle;
- uint16_t comp_status;
- uint16_t failure_code;
- uint32_t residual_count;
+ __le16 comp_status;
+ __le16 failure_code;
+ __le32 residual_count;
- uint32_t reserved[12];
+ __le32 reserved[12];
};
/* 81XX Support **************************************************************/
@@ -1724,9 +1868,8 @@
/* LR Distance bit positions */
#define LR_DIST_NV_POS 2
+#define LR_DIST_NV_MASK 0xf
#define LR_DIST_FW_POS 12
-#define LR_DIST_FW_SHIFT (LR_DIST_FW_POS - LR_DIST_NV_POS)
-#define LR_DIST_FW_FIELD(x) ((x) << LR_DIST_FW_SHIFT & 0xf000)
/* FAC semaphore defines */
#define FAC_SEMAPHORE_UNLOCK 0
@@ -1735,52 +1878,52 @@
struct nvram_81xx {
/* NVRAM header. */
uint8_t id[4];
- uint16_t nvram_version;
- uint16_t reserved_0;
+ __le16 nvram_version;
+ __le16 reserved_0;
/* Firmware Initialization Control Block. */
- uint16_t version;
- uint16_t reserved_1;
- uint16_t frame_payload_size;
- uint16_t execution_throttle;
- uint16_t exchange_count;
- uint16_t reserved_2;
+ __le16 version;
+ __le16 reserved_1;
+ __le16 frame_payload_size;
+ __le16 execution_throttle;
+ __le16 exchange_count;
+ __le16 reserved_2;
uint8_t port_name[WWN_SIZE];
uint8_t node_name[WWN_SIZE];
- uint16_t login_retry_count;
- uint16_t reserved_3;
- uint16_t interrupt_delay_timer;
- uint16_t login_timeout;
+ __le16 login_retry_count;
+ __le16 reserved_3;
+ __le16 interrupt_delay_timer;
+ __le16 login_timeout;
- uint32_t firmware_options_1;
- uint32_t firmware_options_2;
- uint32_t firmware_options_3;
+ __le32 firmware_options_1;
+ __le32 firmware_options_2;
+ __le32 firmware_options_3;
- uint16_t reserved_4[4];
+ __le16 reserved_4[4];
/* Offset 64. */
uint8_t enode_mac[6];
- uint16_t reserved_5[5];
+ __le16 reserved_5[5];
/* Offset 80. */
- uint16_t reserved_6[24];
+ __le16 reserved_6[24];
/* Offset 128. */
- uint16_t ex_version;
+ __le16 ex_version;
uint8_t prio_fcf_matching_flags;
uint8_t reserved_6_1[3];
- uint16_t pri_fcf_vlan_id;
+ __le16 pri_fcf_vlan_id;
uint8_t pri_fcf_fabric_name[8];
- uint16_t reserved_6_2[7];
+ __le16 reserved_6_2[7];
uint8_t spma_mac_addr[6];
- uint16_t reserved_6_3[14];
+ __le16 reserved_6_3[14];
/* Offset 192. */
uint8_t min_supported_speed;
uint8_t reserved_7_0;
- uint16_t reserved_7[31];
+ __le16 reserved_7[31];
/*
* BIT 0 = Enable spinup delay
@@ -1813,26 +1956,26 @@
* BIT 25 = Temp WWPN
* BIT 26-31 =
*/
- uint32_t host_p;
+ __le32 host_p;
uint8_t alternate_port_name[WWN_SIZE];
uint8_t alternate_node_name[WWN_SIZE];
uint8_t boot_port_name[WWN_SIZE];
- uint16_t boot_lun_number;
- uint16_t reserved_8;
+ __le16 boot_lun_number;
+ __le16 reserved_8;
uint8_t alt1_boot_port_name[WWN_SIZE];
- uint16_t alt1_boot_lun_number;
- uint16_t reserved_9;
+ __le16 alt1_boot_lun_number;
+ __le16 reserved_9;
uint8_t alt2_boot_port_name[WWN_SIZE];
- uint16_t alt2_boot_lun_number;
- uint16_t reserved_10;
+ __le16 alt2_boot_lun_number;
+ __le16 reserved_10;
uint8_t alt3_boot_port_name[WWN_SIZE];
- uint16_t alt3_boot_lun_number;
- uint16_t reserved_11;
+ __le16 alt3_boot_lun_number;
+ __le16 reserved_11;
/*
* BIT 0 = Selective Login
@@ -1844,60 +1987,63 @@
* BIT 6 = Reserved
* BIT 7-31 =
*/
- uint32_t efi_parameters;
+ __le32 efi_parameters;
uint8_t reset_delay;
uint8_t reserved_12;
- uint16_t reserved_13;
+ __le16 reserved_13;
- uint16_t boot_id_number;
- uint16_t reserved_14;
+ __le16 boot_id_number;
+ __le16 reserved_14;
- uint16_t max_luns_per_target;
- uint16_t reserved_15;
+ __le16 max_luns_per_target;
+ __le16 reserved_15;
- uint16_t port_down_retry_count;
- uint16_t link_down_timeout;
+ __le16 port_down_retry_count;
+ __le16 link_down_timeout;
/* FCode parameters. */
- uint16_t fcode_parameter;
+ __le16 fcode_parameter;
- uint16_t reserved_16[3];
+ __le16 reserved_16[3];
/* Offset 352. */
uint8_t reserved_17[4];
- uint16_t reserved_18[5];
+ __le16 reserved_18[5];
uint8_t reserved_19[2];
- uint16_t reserved_20[8];
+ __le16 reserved_20[8];
/* Offset 384. */
uint8_t reserved_21[16];
- uint16_t reserved_22[3];
+ __le16 reserved_22[3];
/* Offset 406 (0x196) Enhanced Features
* BIT 0 = Extended BB credits for LR
* BIT 1 = Virtual Fabric Enable
* BIT 2-5 = Distance Support if BIT 0 is on
- * BIT 6-15 = Unused
+ * BIT 6 = Prefer FCP
+ * BIT 7 = SCM Disabled if BIT is set (1)
+ * BIT 8-15 = Unused
*/
uint16_t enhanced_features;
+
uint16_t reserved_24[4];
/* Offset 416. */
- uint16_t reserved_25[32];
+ __le16 reserved_25[32];
/* Offset 480. */
uint8_t model_name[16];
/* Offset 496. */
- uint16_t feature_mask_l;
- uint16_t feature_mask_h;
- uint16_t reserved_26[2];
+ __le16 feature_mask_l;
+ __le16 feature_mask_h;
+ __le16 reserved_26[2];
- uint16_t subsystem_vendor_id;
- uint16_t subsystem_device_id;
+ __le16 subsystem_vendor_id;
+ __le16 subsystem_device_id;
- uint32_t checksum;
+ __le32 checksum;
};
/*
@@ -1906,31 +2052,31 @@
*/
#define ICB_VERSION 1
struct init_cb_81xx {
- uint16_t version;
- uint16_t reserved_1;
+ __le16 version;
+ __le16 reserved_1;
- uint16_t frame_payload_size;
- uint16_t execution_throttle;
- uint16_t exchange_count;
+ __le16 frame_payload_size;
+ __le16 execution_throttle;
+ __le16 exchange_count;
- uint16_t reserved_2;
+ __le16 reserved_2;
uint8_t port_name[WWN_SIZE]; /* Big endian. */
uint8_t node_name[WWN_SIZE]; /* Big endian. */
- uint16_t response_q_inpointer;
- uint16_t request_q_outpointer;
+ __le16 response_q_inpointer;
+ __le16 request_q_outpointer;
- uint16_t login_retry_count;
+ __le16 login_retry_count;
- uint16_t prio_request_q_outpointer;
+ __le16 prio_request_q_outpointer;
- uint16_t response_q_length;
- uint16_t request_q_length;
+ __le16 response_q_length;
+ __le16 request_q_length;
- uint16_t reserved_3;
+ __le16 reserved_3;
- uint16_t prio_request_q_length;
+ __le16 prio_request_q_length;
__le64 request_q_address __packed;
__le64 response_q_address __packed;
@@ -1938,12 +2084,12 @@
uint8_t reserved_4[8];
- uint16_t atio_q_inpointer;
- uint16_t atio_q_length;
+ __le16 atio_q_inpointer;
+ __le16 atio_q_length;
__le64 atio_q_address __packed;
- uint16_t interrupt_delay_timer; /* 100us increments. */
- uint16_t login_timeout;
+ __le16 interrupt_delay_timer; /* 100us increments. */
+ __le16 login_timeout;
/*
* BIT 0-3 = Reserved
@@ -1956,7 +2102,7 @@
* BIT 14 = Node Name Option
* BIT 15-31 = Reserved
*/
- uint32_t firmware_options_1;
+ __le32 firmware_options_1;
/*
* BIT 0 = Operation Mode bit 0
@@ -1974,7 +2120,7 @@
* BIT 14 = Enable Target PRLI Control
* BIT 15-31 = Reserved
*/
- uint32_t firmware_options_2;
+ __le32 firmware_options_2;
/*
* BIT 0-3 = Reserved
@@ -1995,7 +2141,7 @@
* BIT 28 = SPMA selection bit 1
* BIT 30-31 = Reserved
*/
- uint32_t firmware_options_3;
+ __le32 firmware_options_3;
uint8_t reserved_5[8];
@@ -2073,9 +2219,9 @@
#define FCP_PRIO_ATTR_ENABLE 0x1
#define FCP_PRIO_ATTR_PERSIST 0x2
uint8_t reserved; /* Reserved for future use */
-#define FCP_PRIO_CFG_HDR_SIZE 0x10
- struct qla_fcp_prio_entry entry[1]; /* fcp priority entries */
-#define FCP_PRIO_CFG_ENTRY_SIZE 0x20
+#define FCP_PRIO_CFG_HDR_SIZE offsetof(struct qla_fcp_prio_cfg, entry)
+ struct qla_fcp_prio_entry entry[1023]; /* fcp priority entries */
+ uint8_t reserved2[16];
};
#define FCP_PRIO_CFG_SIZE (32*1024) /* fcp prio data per port*/
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 7aa2337..3bc1850 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#ifndef __QLA_GBL_H
#define __QLA_GBL_H
@@ -31,7 +30,7 @@
extern int qla81xx_nvram_config(struct scsi_qla_host *);
extern void qla2x00_update_fw_options(struct scsi_qla_host *);
extern void qla24xx_update_fw_options(scsi_qla_host_t *);
-extern void qla81xx_update_fw_options(scsi_qla_host_t *);
+
extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *);
extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *);
extern int qla81xx_load_risc(scsi_qla_host_t *, uint32_t *);
@@ -72,8 +71,6 @@
extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t);
extern void qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
-extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
- uint16_t *);
struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *,
enum qla_work_type);
extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *);
@@ -111,7 +108,7 @@
int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *, u8*,
void *, u8);
int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
-int qla24xx_detect_sfp(scsi_qla_host_t *vha);
+int qla24xx_detect_sfp(scsi_qla_host_t *);
int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
extern void qla28xx_get_aux_images(struct scsi_qla_host *,
@@ -129,7 +126,10 @@
void qla_do_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport);
int qla2x00_reserve_mgmt_server_loop_id(scsi_qla_host_t *);
void qla_rscn_replay(fc_port_t *fcport);
+void qla24xx_free_purex_item(struct purex_item *item);
extern bool qla24xx_risc_firmware_invalid(uint32_t *);
+void qla_init_iocb_limit(scsi_qla_host_t *);
+
/*
* Global Data in qla_os.c source file.
@@ -144,6 +144,8 @@
extern int ql2xplogiabsentdevice;
extern int ql2xloginretrycount;
extern int ql2xfdmienable;
+extern int ql2xrdpenable;
+extern int ql2xsmartsan;
extern int ql2xallocfwdump;
extern int ql2xextended_error_logging;
extern int ql2xiidmaenable;
@@ -156,7 +158,6 @@
extern int ql2xgffidenable;
extern int ql2xenabledif;
extern int ql2xenablehba_err_chk;
-extern int ql2xtargetreset;
extern int ql2xdontresethba;
extern uint64_t ql2xmaxlun;
extern int ql2xmdcapmask;
@@ -173,6 +174,8 @@
extern int qla2xuseresexchforels;
extern int ql2xexlogins;
extern int ql2xdifbundlinginternalbuffers;
+extern int ql2xfulldump_on_mpifail;
+extern int ql2xenforce_iocb_limit;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -183,8 +186,6 @@
uint16_t *);
extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
-extern int qla2x00_post_async_logout_done_work(struct scsi_qla_host *,
- fc_port_t *, uint16_t *);
extern int qla2x00_post_async_adisc_work(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
extern int qla2x00_post_async_adisc_done_work(struct scsi_qla_host *,
@@ -202,6 +203,7 @@
extern void qla2x00_relogin(struct scsi_qla_host *);
extern void qla2x00_do_work(struct scsi_qla_host *);
extern void qla2x00_free_fcports(struct scsi_qla_host *);
+extern void qla2x00_free_fcport(fc_port_t *);
extern void qla83xx_schedule_work(scsi_qla_host_t *, int);
extern void qla83xx_service_idc_aen(struct work_struct *);
@@ -229,6 +231,8 @@
int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *);
int qla24xx_post_relogin_work(struct scsi_qla_host *vha);
void qla2x00_wait_for_sess_deletion(scsi_qla_host_t *);
+void qla24xx_process_purex_rdp(struct scsi_qla_host *vha,
+ struct purex_item *pkt);
/*
* Global Functions in qla_mid.c source file.
@@ -254,8 +258,8 @@
extern void qla2x00_sp_free_dma(srb_t *sp);
extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *);
-extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int);
-extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int);
+extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int);
+extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *);
extern int qla24xx_async_abort_cmd(srb_t *, bool);
extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *);
@@ -357,6 +361,9 @@
qla2x00_get_port_database(scsi_qla_host_t *, fc_port_t *, uint8_t);
extern int
+qla24xx_get_port_database(scsi_qla_host_t *, u16, struct port_database_24xx *);
+
+extern int
qla2x00_get_firmware_state(scsi_qla_host_t *, uint16_t *);
extern int
@@ -455,6 +462,13 @@
qla25xx_set_driver_version(scsi_qla_host_t *, char *);
extern int
+qla25xx_set_els_cmds_supported(scsi_qla_host_t *);
+
+extern int
+qla24xx_get_buffer_credits(scsi_qla_host_t *, struct buffer_credit_24xx *,
+ dma_addr_t);
+
+extern int
qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint8_t *,
uint16_t, uint16_t, uint16_t, uint16_t);
@@ -555,6 +569,8 @@
uint32_t);
extern irqreturn_t
qla2xxx_msix_rsp_q(int irq, void *dev_id);
+extern irqreturn_t
+qla2xxx_msix_rsp_q_hs(int irq, void *dev_id);
fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t);
fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8);
fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8);
@@ -624,15 +640,17 @@
/*
* Global Function Prototypes in qla_dbg.c source file.
*/
-extern void qla2100_fw_dump(scsi_qla_host_t *, int);
-extern void qla2300_fw_dump(scsi_qla_host_t *, int);
-extern void qla24xx_fw_dump(scsi_qla_host_t *, int);
-extern void qla25xx_fw_dump(scsi_qla_host_t *, int);
-extern void qla81xx_fw_dump(scsi_qla_host_t *, int);
-extern void qla82xx_fw_dump(scsi_qla_host_t *, int);
-extern void qla8044_fw_dump(scsi_qla_host_t *, int);
+void qla2xxx_dump_fw(scsi_qla_host_t *vha);
+void qla2100_fw_dump(scsi_qla_host_t *vha);
+void qla2300_fw_dump(scsi_qla_host_t *vha);
+void qla24xx_fw_dump(scsi_qla_host_t *vha);
+void qla25xx_fw_dump(scsi_qla_host_t *vha);
+void qla81xx_fw_dump(scsi_qla_host_t *vha);
+void qla82xx_fw_dump(scsi_qla_host_t *vha);
+void qla8044_fw_dump(scsi_qla_host_t *vha);
-extern void qla27xx_fwdump(scsi_qla_host_t *, int);
+void qla27xx_fwdump(scsi_qla_host_t *vha);
+extern void qla27xx_mpi_fwdump(scsi_qla_host_t *, int);
extern ulong qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *, void *);
extern int qla27xx_fwdt_template_valid(void *);
extern ulong qla27xx_fwdt_template_size(void *);
@@ -659,7 +677,7 @@
extern int qla2x00_fdmi_register(scsi_qla_host_t *);
extern int qla2x00_gfpn_id(scsi_qla_host_t *, sw_info_t *);
extern int qla2x00_gpsc(scsi_qla_host_t *, sw_info_t *);
-extern void qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t);
+extern size_t qla2x00_get_sym_node_name(scsi_qla_host_t *, uint8_t *, size_t);
extern int qla2x00_chk_ms_status(scsi_qla_host_t *, ms_iocb_entry_t *,
struct ct_sns_rsp *, const char *);
extern void qla2x00_async_iocb_timeout(void *data);
@@ -687,6 +705,8 @@
void qla24xx_handle_gfpnid_event(scsi_qla_host_t *, struct event_arg *);
void qla24xx_sp_unmap(scsi_qla_host_t *, srb_t *);
void qla_scan_work_fn(struct work_struct *);
+uint qla25xx_fdmi_port_speed_capability(struct qla_hw_data *);
+uint qla25xx_fdmi_port_speed_currently(struct qla_hw_data *);
/*
* Global Function Prototypes in qla_attr.c source file.
@@ -757,7 +777,7 @@
extern int qlafx00_configure_devices(scsi_qla_host_t *);
extern int qlafx00_reset_initialize(scsi_qla_host_t *);
extern int qlafx00_fx_disc(scsi_qla_host_t *, fc_port_t *, uint16_t);
-extern int qlafx00_process_aen(struct scsi_qla_host *, struct qla_work_evt *);
+extern void qlafx00_process_aen(struct scsi_qla_host *, struct qla_work_evt *);
extern int qlafx00_post_aenfx_work(struct scsi_qla_host *, uint32_t,
uint32_t *, int);
extern uint32_t qlafx00_fw_state_show(struct device *,
@@ -770,7 +790,6 @@
extern void qlafx00_fxdisc_iocb(srb_t *, struct fxdisc_entry_fx00 *);
extern void qlafx00_timer_routine(scsi_qla_host_t *);
extern int qlafx00_rescan_isp(scsi_qla_host_t *);
-extern int qlafx00_loop_reset(scsi_qla_host_t *vha);
/* qla82xx related functions */
@@ -847,6 +866,7 @@
extern int qla82xx_read_temperature(scsi_qla_host_t *);
extern int qla8044_read_temperature(scsi_qla_host_t *);
extern int qla2x00_read_sfp_dev(struct scsi_qla_host *, char *, int);
+extern int ql26xx_led_config(scsi_qla_host_t *, uint16_t, uint16_t *);
/* BSG related functions */
extern int qla24xx_bsg_request(struct bsg_job *);
@@ -858,7 +878,7 @@
uint16_t *, uint16_t *);
/* 83xx related functions */
-extern void qla83xx_fw_dump(scsi_qla_host_t *, int);
+void qla83xx_fw_dump(scsi_qla_host_t *vha);
/* Minidump related functions */
extern int qla82xx_md_get_template_size(scsi_qla_host_t *);
@@ -916,6 +936,9 @@
void qlt_clr_qp_table(struct scsi_qla_host *vha);
void qlt_set_mode(struct scsi_qla_host *);
int qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode);
+extern void qla24xx_process_purex_list(struct purex_list *);
+extern void qla2x00_dfs_create_rport(scsi_qla_host_t *vha, struct fc_port *fp);
+extern void qla2x00_dfs_remove_rport(scsi_qla_host_t *vha, struct fc_port *fp);
/* nvme.c */
void qla_nvme_unregister_remote_port(struct fc_port *fcport);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index d9b5ea7..e28c4b7 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
#include "qla_target.h"
@@ -19,6 +18,8 @@
static int qla_async_rnnid(scsi_qla_host_t *, port_id_t *, u8*);
static int qla_async_rsnn_nn(scsi_qla_host_t *);
+
+
/**
* qla2x00_prep_ms_iocb() - Prepare common MS/CT IOCB fields for SNS CT query.
* @vha: HA context
@@ -175,7 +176,7 @@
break;
case CS_TIMEOUT:
rval = QLA_FUNCTION_TIMEOUT;
- /* fall through */
+ fallthrough;
default:
ql_dbg(ql_dbg_disc, vha, 0x2033,
"%s failed, completion status (%x) on port_id: "
@@ -844,19 +845,18 @@
return rval;
}
-void
+size_t
qla2x00_get_sym_node_name(scsi_qla_host_t *vha, uint8_t *snn, size_t size)
{
struct qla_hw_data *ha = vha->hw;
if (IS_QLAFX00(ha))
- snprintf(snn, size, "%s FW:v%s DVR:v%s", ha->model_number,
- ha->mr.fw_version, qla2x00_version_str);
- else
- snprintf(snn, size,
- "%s FW:v%d.%02d.%02d DVR:v%s", ha->model_number,
- ha->fw_major_version, ha->fw_minor_version,
- ha->fw_subminor_version, qla2x00_version_str);
+ return scnprintf(snn, size, "%s FW:v%s DVR:v%s",
+ ha->model_number, ha->mr.fw_version, qla2x00_version_str);
+
+ return scnprintf(snn, size, "%s FW:v%d.%02d.%02d DVR:v%s",
+ ha->model_number, ha->fw_major_version, ha->fw_minor_version,
+ ha->fw_subminor_version, qla2x00_version_str);
}
/**
@@ -1501,747 +1501,740 @@
return &p->p.req;
}
-/**
- * qla2x00_fdmi_rhba() - perform RHBA FDMI registration
- * @vha: HA context
- *
- * Returns 0 on success.
- */
-static int
-qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
+uint
+qla25xx_fdmi_port_speed_capability(struct qla_hw_data *ha)
{
- int rval, alen;
- uint32_t size, sn;
+ uint speeds = 0;
- ms_iocb_entry_t *ms_pkt;
- struct ct_sns_req *ct_req;
- struct ct_sns_rsp *ct_rsp;
- void *entries;
- struct ct_fdmi_hba_attr *eiter;
- struct qla_hw_data *ha = vha->hw;
-
- /* Issue RHBA */
- /* Prepare common MS IOCB */
- /* Request size adjusted after CT preparation */
- ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
-
- /* Prepare CT request */
- ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, RHBA_RSP_SIZE);
- ct_rsp = &ha->ct_sns->p.rsp;
-
- /* Prepare FDMI command arguments -- attribute block, attributes. */
- memcpy(ct_req->req.rhba.hba_identifier, vha->port_name, WWN_SIZE);
- ct_req->req.rhba.entry_count = cpu_to_be32(1);
- memcpy(ct_req->req.rhba.port_name, vha->port_name, WWN_SIZE);
- size = 2 * WWN_SIZE + 4 + 4;
-
- /* Attributes */
- ct_req->req.rhba.attrs.count =
- cpu_to_be32(FDMI_HBA_ATTR_COUNT);
- entries = &ct_req->req;
-
- /* Nodename. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME);
- eiter->len = cpu_to_be16(4 + WWN_SIZE);
- memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
- size += 4 + WWN_SIZE;
-
- ql_dbg(ql_dbg_disc, vha, 0x2025,
- "NodeName = %8phN.\n", eiter->a.node_name);
-
- /* Manufacturer. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER);
- alen = strlen(QLA2XXX_MANUFACTURER);
- snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
- "%s", "QLogic Corporation");
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x2026,
- "Manufacturer = %s.\n", eiter->a.manufacturer);
-
- /* Serial number. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
- if (IS_FWI2_CAPABLE(ha))
- qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num,
- sizeof(eiter->a.serial_num));
- else {
- sn = ((ha->serial0 & 0x1f) << 16) |
- (ha->serial2 << 8) | ha->serial1;
- snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num),
- "%c%05d", 'A' + sn / 100000, sn % 100000);
- }
- alen = strlen(eiter->a.serial_num);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x2027,
- "Serial no. = %s.\n", eiter->a.serial_num);
-
- /* Model name. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_HBA_MODEL);
- snprintf(eiter->a.model, sizeof(eiter->a.model),
- "%s", ha->model_number);
- alen = strlen(eiter->a.model);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x2028,
- "Model Name = %s.\n", eiter->a.model);
-
- /* Model description. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
- snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc),
- "%s", ha->model_desc);
- alen = strlen(eiter->a.model_desc);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x2029,
- "Model Desc = %s.\n", eiter->a.model_desc);
-
- /* Hardware version. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
- if (!IS_FWI2_CAPABLE(ha)) {
- snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
- "HW:%s", ha->adapter_id);
- } else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version,
- sizeof(eiter->a.hw_version))) {
- ;
- } else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version,
- sizeof(eiter->a.hw_version))) {
- ;
- } else {
- snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
- "HW:%s", ha->adapter_id);
- }
- alen = strlen(eiter->a.hw_version);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x202a,
- "Hardware ver = %s.\n", eiter->a.hw_version);
-
- /* Driver version. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
- snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version),
- "%s", qla2x00_version_str);
- alen = strlen(eiter->a.driver_version);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x202b,
- "Driver ver = %s.\n", eiter->a.driver_version);
-
- /* Option ROM version. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
- snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version),
- "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
- alen = strlen(eiter->a.orom_version);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha , 0x202c,
- "Optrom vers = %s.\n", eiter->a.orom_version);
-
- /* Firmware version */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
- ha->isp_ops->fw_version_str(vha, eiter->a.fw_version,
- sizeof(eiter->a.fw_version));
- alen = strlen(eiter->a.fw_version);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x202d,
- "Firmware vers = %s.\n", eiter->a.fw_version);
-
- /* Update MS request size. */
- qla2x00_update_ms_fdmi_iocb(vha, size + 16);
-
- ql_dbg(ql_dbg_disc, vha, 0x202e,
- "RHBA identifier = %8phN size=%d.\n",
- ct_req->req.rhba.hba_identifier, size);
- ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2076,
- entries, size);
-
- /* Execute MS IOCB */
- rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
- sizeof(ms_iocb_entry_t));
- if (rval != QLA_SUCCESS) {
- /*EMPTY*/
- ql_dbg(ql_dbg_disc, vha, 0x2030,
- "RHBA issue IOCB failed (%d).\n", rval);
- } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
- QLA_SUCCESS) {
- rval = QLA_FUNCTION_FAILED;
- if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
- ct_rsp->header.explanation_code ==
- CT_EXPL_ALREADY_REGISTERED) {
- ql_dbg(ql_dbg_disc, vha, 0x2034,
- "HBA already registered.\n");
- rval = QLA_ALREADY_REGISTERED;
- } else {
- ql_dbg(ql_dbg_disc, vha, 0x20ad,
- "RHBA FDMI registration failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
- ct_rsp->header.reason_code,
- ct_rsp->header.explanation_code);
+ if (IS_CNA_CAPABLE(ha))
+ return FDMI_PORT_SPEED_10GB;
+ if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) {
+ if (ha->max_supported_speed == 2) {
+ if (ha->min_supported_speed <= 6)
+ speeds |= FDMI_PORT_SPEED_64GB;
}
- } else {
- ql_dbg(ql_dbg_disc, vha, 0x2035,
- "RHBA exiting normally.\n");
+ if (ha->max_supported_speed == 2 ||
+ ha->max_supported_speed == 1) {
+ if (ha->min_supported_speed <= 5)
+ speeds |= FDMI_PORT_SPEED_32GB;
+ }
+ if (ha->max_supported_speed == 2 ||
+ ha->max_supported_speed == 1 ||
+ ha->max_supported_speed == 0) {
+ if (ha->min_supported_speed <= 4)
+ speeds |= FDMI_PORT_SPEED_16GB;
+ }
+ if (ha->max_supported_speed == 1 ||
+ ha->max_supported_speed == 0) {
+ if (ha->min_supported_speed <= 3)
+ speeds |= FDMI_PORT_SPEED_8GB;
+ }
+ if (ha->max_supported_speed == 0) {
+ if (ha->min_supported_speed <= 2)
+ speeds |= FDMI_PORT_SPEED_4GB;
+ }
+ return speeds;
}
-
- return rval;
+ if (IS_QLA2031(ha)) {
+ if ((ha->pdev->subsystem_vendor == 0x103C) &&
+ (ha->pdev->subsystem_device == 0x8002)) {
+ speeds = FDMI_PORT_SPEED_16GB;
+ } else {
+ speeds = FDMI_PORT_SPEED_16GB|FDMI_PORT_SPEED_8GB|
+ FDMI_PORT_SPEED_4GB;
+ }
+ return speeds;
+ }
+ if (IS_QLA25XX(ha) || IS_QLAFX00(ha))
+ return FDMI_PORT_SPEED_8GB|FDMI_PORT_SPEED_4GB|
+ FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB;
+ if (IS_QLA24XX_TYPE(ha))
+ return FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_2GB|
+ FDMI_PORT_SPEED_1GB;
+ if (IS_QLA23XX(ha))
+ return FDMI_PORT_SPEED_2GB|FDMI_PORT_SPEED_1GB;
+ return FDMI_PORT_SPEED_1GB;
}
-/**
- * qla2x00_fdmi_rpa() - perform RPA registration
- * @vha: HA context
- *
- * Returns 0 on success.
- */
-static int
-qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
+uint
+qla25xx_fdmi_port_speed_currently(struct qla_hw_data *ha)
{
- int rval, alen;
- uint32_t size;
- struct qla_hw_data *ha = vha->hw;
- ms_iocb_entry_t *ms_pkt;
- struct ct_sns_req *ct_req;
- struct ct_sns_rsp *ct_rsp;
- void *entries;
- struct ct_fdmi_port_attr *eiter;
- struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
- struct new_utsname *p_sysid = NULL;
-
- /* Issue RPA */
- /* Prepare common MS IOCB */
- /* Request size adjusted after CT preparation */
- ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE);
-
- /* Prepare CT request */
- ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD,
- RPA_RSP_SIZE);
- ct_rsp = &ha->ct_sns->p.rsp;
-
- /* Prepare FDMI command arguments -- attribute block, attributes. */
- memcpy(ct_req->req.rpa.port_name, vha->port_name, WWN_SIZE);
- size = WWN_SIZE + 4;
-
- /* Attributes */
- ct_req->req.rpa.attrs.count = cpu_to_be32(FDMI_PORT_ATTR_COUNT);
- entries = &ct_req->req;
-
- /* FC4 types. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES);
- eiter->len = cpu_to_be16(4 + 32);
- eiter->a.fc4_types[2] = 0x01;
- size += 4 + 32;
-
- ql_dbg(ql_dbg_disc, vha, 0x2039,
- "FC4_TYPES=%02x %02x.\n",
- eiter->a.fc4_types[2],
- eiter->a.fc4_types[1]);
-
- /* Supported speed. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
- eiter->len = cpu_to_be16(4 + 4);
- if (IS_CNA_CAPABLE(ha))
- eiter->a.sup_speed = cpu_to_be32(
- FDMI_PORT_SPEED_10GB);
- else if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
- eiter->a.sup_speed = cpu_to_be32(
- FDMI_PORT_SPEED_32GB|
- FDMI_PORT_SPEED_16GB|
- FDMI_PORT_SPEED_8GB);
- else if (IS_QLA2031(ha))
- eiter->a.sup_speed = cpu_to_be32(
- FDMI_PORT_SPEED_16GB|
- FDMI_PORT_SPEED_8GB|
- FDMI_PORT_SPEED_4GB);
- else if (IS_QLA25XX(ha))
- eiter->a.sup_speed = cpu_to_be32(
- FDMI_PORT_SPEED_8GB|
- FDMI_PORT_SPEED_4GB|
- FDMI_PORT_SPEED_2GB|
- FDMI_PORT_SPEED_1GB);
- else if (IS_QLA24XX_TYPE(ha))
- eiter->a.sup_speed = cpu_to_be32(
- FDMI_PORT_SPEED_4GB|
- FDMI_PORT_SPEED_2GB|
- FDMI_PORT_SPEED_1GB);
- else if (IS_QLA23XX(ha))
- eiter->a.sup_speed = cpu_to_be32(
- FDMI_PORT_SPEED_2GB|
- FDMI_PORT_SPEED_1GB);
- else
- eiter->a.sup_speed = cpu_to_be32(
- FDMI_PORT_SPEED_1GB);
- size += 4 + 4;
-
- ql_dbg(ql_dbg_disc, vha, 0x203a,
- "Supported_Speed=%x.\n", eiter->a.sup_speed);
-
- /* Current speed. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
- eiter->len = cpu_to_be16(4 + 4);
switch (ha->link_data_rate) {
case PORT_SPEED_1GB:
- eiter->a.cur_speed =
- cpu_to_be32(FDMI_PORT_SPEED_1GB);
- break;
+ return FDMI_PORT_SPEED_1GB;
case PORT_SPEED_2GB:
- eiter->a.cur_speed =
- cpu_to_be32(FDMI_PORT_SPEED_2GB);
- break;
+ return FDMI_PORT_SPEED_2GB;
case PORT_SPEED_4GB:
- eiter->a.cur_speed =
- cpu_to_be32(FDMI_PORT_SPEED_4GB);
- break;
+ return FDMI_PORT_SPEED_4GB;
case PORT_SPEED_8GB:
- eiter->a.cur_speed =
- cpu_to_be32(FDMI_PORT_SPEED_8GB);
- break;
+ return FDMI_PORT_SPEED_8GB;
case PORT_SPEED_10GB:
- eiter->a.cur_speed =
- cpu_to_be32(FDMI_PORT_SPEED_10GB);
- break;
+ return FDMI_PORT_SPEED_10GB;
case PORT_SPEED_16GB:
- eiter->a.cur_speed =
- cpu_to_be32(FDMI_PORT_SPEED_16GB);
- break;
+ return FDMI_PORT_SPEED_16GB;
case PORT_SPEED_32GB:
- eiter->a.cur_speed =
- cpu_to_be32(FDMI_PORT_SPEED_32GB);
- break;
+ return FDMI_PORT_SPEED_32GB;
+ case PORT_SPEED_64GB:
+ return FDMI_PORT_SPEED_64GB;
default:
- eiter->a.cur_speed =
- cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
- break;
+ return FDMI_PORT_SPEED_UNKNOWN;
}
- size += 4 + 4;
-
- ql_dbg(ql_dbg_disc, vha, 0x203b,
- "Current_Speed=%x.\n", eiter->a.cur_speed);
-
- /* Max frame size. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
- eiter->len = cpu_to_be16(4 + 4);
- eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ?
- le16_to_cpu(icb24->frame_payload_size) :
- le16_to_cpu(ha->init_cb->frame_payload_size);
- eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size);
- size += 4 + 4;
-
- ql_dbg(ql_dbg_disc, vha, 0x203c,
- "Max_Frame_Size=%x.\n", eiter->a.max_frame_size);
-
- /* OS device name. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
- snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name),
- "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no);
- alen = strlen(eiter->a.os_dev_name);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x204b,
- "OS_Device_Name=%s.\n", eiter->a.os_dev_name);
-
- /* Hostname. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME);
- p_sysid = utsname();
- if (p_sysid) {
- snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
- "%s", p_sysid->nodename);
- } else {
- snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
- "%s", fc_host_system_hostname(vha->host));
- }
- alen = strlen(eiter->a.host_name);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x203d, "HostName=%s.\n", eiter->a.host_name);
-
- /* Update MS request size. */
- qla2x00_update_ms_fdmi_iocb(vha, size + 16);
-
- ql_dbg(ql_dbg_disc, vha, 0x203e,
- "RPA portname %016llx, size = %d.\n",
- wwn_to_u64(ct_req->req.rpa.port_name), size);
- ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2079,
- entries, size);
-
- /* Execute MS IOCB */
- rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
- sizeof(ms_iocb_entry_t));
- if (rval != QLA_SUCCESS) {
- /*EMPTY*/
- ql_dbg(ql_dbg_disc, vha, 0x2040,
- "RPA issue IOCB failed (%d).\n", rval);
- } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
- QLA_SUCCESS) {
- rval = QLA_FUNCTION_FAILED;
- if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
- ct_rsp->header.explanation_code ==
- CT_EXPL_ALREADY_REGISTERED) {
- ql_dbg(ql_dbg_disc, vha, 0x20cd,
- "RPA already registered.\n");
- rval = QLA_ALREADY_REGISTERED;
- }
-
- } else {
- ql_dbg(ql_dbg_disc, vha, 0x2041,
- "RPA exiting normally.\n");
- }
-
- return rval;
}
/**
- * qla2x00_fdmiv2_rhba() - perform RHBA FDMI v2 registration
+ * qla2x00_hba_attributes() perform HBA attributes registration
* @vha: HA context
+ * @entries: number of entries to use
+ * @callopt: Option to issue extended or standard FDMI
+ * command parameter
*
* Returns 0 on success.
*/
-static int
-qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha)
+static unsigned long
+qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries,
+ unsigned int callopt)
{
- int rval, alen;
- uint32_t size, sn;
- ms_iocb_entry_t *ms_pkt;
- struct ct_sns_req *ct_req;
- struct ct_sns_rsp *ct_rsp;
- void *entries;
- struct ct_fdmiv2_hba_attr *eiter;
struct qla_hw_data *ha = vha->hw;
- struct new_utsname *p_sysid = NULL;
-
- /* Issue RHBA */
- /* Prepare common MS IOCB */
- /* Request size adjusted after CT preparation */
- ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RHBA_RSP_SIZE);
-
- /* Prepare CT request */
- ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD,
- RHBA_RSP_SIZE);
- ct_rsp = &ha->ct_sns->p.rsp;
-
- /* Prepare FDMI command arguments -- attribute block, attributes. */
- memcpy(ct_req->req.rhba2.hba_identifier, vha->port_name, WWN_SIZE);
- ct_req->req.rhba2.entry_count = cpu_to_be32(1);
- memcpy(ct_req->req.rhba2.port_name, vha->port_name, WWN_SIZE);
- size = 2 * WWN_SIZE + 4 + 4;
-
- /* Attributes */
- ct_req->req.rhba2.attrs.count = cpu_to_be32(FDMIV2_HBA_ATTR_COUNT);
- entries = &ct_req->req;
+ struct init_cb_24xx *icb24 = (void *)ha->init_cb;
+ struct new_utsname *p_sysid = utsname();
+ struct ct_fdmi_hba_attr *eiter;
+ uint16_t alen;
+ unsigned long size = 0;
/* Nodename. */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_NODE_NAME);
- eiter->len = cpu_to_be16(4 + WWN_SIZE);
- memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
- size += 4 + WWN_SIZE;
-
- ql_dbg(ql_dbg_disc, vha, 0x207d,
- "NodeName = %016llx.\n", wwn_to_u64(eiter->a.node_name));
-
+ memcpy(eiter->a.node_name, vha->node_name, sizeof(eiter->a.node_name));
+ alen = sizeof(eiter->a.node_name);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20a0,
+ "NODENAME = %016llx.\n", wwn_to_u64(eiter->a.node_name));
/* Manufacturer. */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER);
- snprintf(eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
- "%s", "QLogic Corporation");
- eiter->a.manufacturer[strlen("QLogic Corporation")] = '\0';
- alen = strlen(eiter->a.manufacturer);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x20a5,
- "Manufacturer = %s.\n", eiter->a.manufacturer);
-
+ alen = scnprintf(
+ eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
+ "%s", "QLogic Corporation");
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20a1,
+ "MANUFACTURER = %s.\n", eiter->a.manufacturer);
/* Serial number. */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_SERIAL_NUMBER);
- if (IS_FWI2_CAPABLE(ha))
- qla2xxx_get_vpd_field(vha, "SN", eiter->a.serial_num,
- sizeof(eiter->a.serial_num));
- else {
- sn = ((ha->serial0 & 0x1f) << 16) |
- (ha->serial2 << 8) | ha->serial1;
- snprintf(eiter->a.serial_num, sizeof(eiter->a.serial_num),
- "%c%05d", 'A' + sn / 100000, sn % 100000);
+ alen = 0;
+ if (IS_FWI2_CAPABLE(ha)) {
+ alen = qla2xxx_get_vpd_field(vha, "SN",
+ eiter->a.serial_num, sizeof(eiter->a.serial_num));
}
- alen = strlen(eiter->a.serial_num);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x20a6,
- "Serial no. = %s.\n", eiter->a.serial_num);
-
+ if (!alen) {
+ uint32_t sn = ((ha->serial0 & 0x1f) << 16) |
+ (ha->serial2 << 8) | ha->serial1;
+ alen = scnprintf(
+ eiter->a.serial_num, sizeof(eiter->a.serial_num),
+ "%c%05d", 'A' + sn / 100000, sn % 100000);
+ }
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20a2,
+ "SERIAL NUMBER = %s.\n", eiter->a.serial_num);
/* Model name. */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_MODEL);
- snprintf(eiter->a.model, sizeof(eiter->a.model),
- "%s", ha->model_number);
- alen = strlen(eiter->a.model);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x20a7,
- "Model Name = %s.\n", eiter->a.model);
-
+ alen = scnprintf(
+ eiter->a.model, sizeof(eiter->a.model),
+ "%s", ha->model_number);
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20a3,
+ "MODEL NAME = %s.\n", eiter->a.model);
/* Model description. */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION);
- snprintf(eiter->a.model_desc, sizeof(eiter->a.model_desc),
- "%s", ha->model_desc);
- alen = strlen(eiter->a.model_desc);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x20a8,
- "Model Desc = %s.\n", eiter->a.model_desc);
-
+ alen = scnprintf(
+ eiter->a.model_desc, sizeof(eiter->a.model_desc),
+ "%s", ha->model_desc);
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20a4,
+ "MODEL DESCRIPTION = %s.\n", eiter->a.model_desc);
/* Hardware version. */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION);
- if (!IS_FWI2_CAPABLE(ha)) {
- snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
- "HW:%s", ha->adapter_id);
- } else if (qla2xxx_get_vpd_field(vha, "MN", eiter->a.hw_version,
- sizeof(eiter->a.hw_version))) {
- ;
- } else if (qla2xxx_get_vpd_field(vha, "EC", eiter->a.hw_version,
- sizeof(eiter->a.hw_version))) {
- ;
- } else {
- snprintf(eiter->a.hw_version, sizeof(eiter->a.hw_version),
- "HW:%s", ha->adapter_id);
+ alen = 0;
+ if (IS_FWI2_CAPABLE(ha)) {
+ if (!alen) {
+ alen = qla2xxx_get_vpd_field(vha, "MN",
+ eiter->a.hw_version, sizeof(eiter->a.hw_version));
+ }
+ if (!alen) {
+ alen = qla2xxx_get_vpd_field(vha, "EC",
+ eiter->a.hw_version, sizeof(eiter->a.hw_version));
+ }
}
- alen = strlen(eiter->a.hw_version);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x20a9,
- "Hardware ver = %s.\n", eiter->a.hw_version);
-
+ if (!alen) {
+ alen = scnprintf(
+ eiter->a.hw_version, sizeof(eiter->a.hw_version),
+ "HW:%s", ha->adapter_id);
+ }
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20a5,
+ "HARDWARE VERSION = %s.\n", eiter->a.hw_version);
/* Driver version. */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_DRIVER_VERSION);
- snprintf(eiter->a.driver_version, sizeof(eiter->a.driver_version),
- "%s", qla2x00_version_str);
- alen = strlen(eiter->a.driver_version);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x20aa,
- "Driver ver = %s.\n", eiter->a.driver_version);
-
+ alen = scnprintf(
+ eiter->a.driver_version, sizeof(eiter->a.driver_version),
+ "%s", qla2x00_version_str);
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20a6,
+ "DRIVER VERSION = %s.\n", eiter->a.driver_version);
/* Option ROM version. */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_OPTION_ROM_VERSION);
- snprintf(eiter->a.orom_version, sizeof(eiter->a.orom_version),
- "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
- alen = strlen(eiter->a.orom_version);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
+ alen = scnprintf(
+ eiter->a.orom_version, sizeof(eiter->a.orom_version),
+ "%d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
- ql_dbg(ql_dbg_disc, vha , 0x20ab,
- "Optrom version = %d.%02d.\n", eiter->a.orom_version[1],
- eiter->a.orom_version[0]);
-
+ ql_dbg(ql_dbg_disc, vha, 0x20a7,
+ "OPTROM VERSION = %d.%02d.\n",
+ eiter->a.orom_version[1], eiter->a.orom_version[0]);
/* Firmware version */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_FIRMWARE_VERSION);
ha->isp_ops->fw_version_str(vha, eiter->a.fw_version,
sizeof(eiter->a.fw_version));
- alen = strlen(eiter->a.fw_version);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x20ac,
- "Firmware vers = %s.\n", eiter->a.fw_version);
-
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20a8,
+ "FIRMWARE VERSION = %s.\n", eiter->a.fw_version);
+ if (callopt == CALLOPT_FDMI1)
+ goto done;
/* OS Name and Version */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_OS_NAME_AND_VERSION);
- p_sysid = utsname();
+ alen = 0;
if (p_sysid) {
- snprintf(eiter->a.os_version, sizeof(eiter->a.os_version),
- "%s %s %s",
- p_sysid->sysname, p_sysid->release, p_sysid->version);
- } else {
- snprintf(eiter->a.os_version, sizeof(eiter->a.os_version),
- "%s %s", "Linux", fc_host_system_hostname(vha->host));
+ alen = scnprintf(
+ eiter->a.os_version, sizeof(eiter->a.os_version),
+ "%s %s %s",
+ p_sysid->sysname, p_sysid->release, p_sysid->machine);
}
- alen = strlen(eiter->a.os_version);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x20ae,
- "OS Name and Version = %s.\n", eiter->a.os_version);
-
+ if (!alen) {
+ alen = scnprintf(
+ eiter->a.os_version, sizeof(eiter->a.os_version),
+ "%s %s",
+ "Linux", fc_host_system_hostname(vha->host));
+ }
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20a9,
+ "OS VERSION = %s.\n", eiter->a.os_version);
/* MAX CT Payload Length */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_MAXIMUM_CT_PAYLOAD_LENGTH);
- eiter->a.max_ct_len = cpu_to_be32(ha->frame_payload_size);
- eiter->a.max_ct_len = cpu_to_be32(eiter->a.max_ct_len);
- eiter->len = cpu_to_be16(4 + 4);
- size += 4 + 4;
-
- ql_dbg(ql_dbg_disc, vha, 0x20af,
- "CT Payload Length = 0x%x.\n", eiter->a.max_ct_len);
-
+ eiter->a.max_ct_len = cpu_to_be32(le16_to_cpu(IS_FWI2_CAPABLE(ha) ?
+ icb24->frame_payload_size : ha->init_cb->frame_payload_size));
+ alen = sizeof(eiter->a.max_ct_len);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20aa,
+ "CT PAYLOAD LENGTH = 0x%x.\n", be32_to_cpu(eiter->a.max_ct_len));
/* Node Sybolic Name */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_NODE_SYMBOLIC_NAME);
- qla2x00_get_sym_node_name(vha, eiter->a.sym_name,
+ alen = qla2x00_get_sym_node_name(vha, eiter->a.sym_name,
sizeof(eiter->a.sym_name));
- alen = strlen(eiter->a.sym_name);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x20b0,
- "Symbolic Name = %s.\n", eiter->a.sym_name);
-
- /* Vendor Id */
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20ab,
+ "SYMBOLIC NAME = %s.\n", eiter->a.sym_name);
+ /* Vendor Specific information */
eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_ID);
- eiter->a.vendor_id = cpu_to_be32(0x1077);
- eiter->len = cpu_to_be16(4 + 4);
- size += 4 + 4;
-
- ql_dbg(ql_dbg_disc, vha, 0x20b1,
- "Vendor Id = %x.\n", eiter->a.vendor_id);
-
+ eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_SPECIFIC_INFO);
+ eiter->a.vendor_specific_info = cpu_to_be32(PCI_VENDOR_ID_QLOGIC);
+ alen = sizeof(eiter->a.vendor_specific_info);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20ac,
+ "VENDOR SPECIFIC INFO = 0x%x.\n",
+ be32_to_cpu(eiter->a.vendor_specific_info));
/* Num Ports */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_NUM_PORTS);
eiter->a.num_ports = cpu_to_be32(1);
- eiter->len = cpu_to_be16(4 + 4);
- size += 4 + 4;
-
- ql_dbg(ql_dbg_disc, vha, 0x20b2,
- "Port Num = %x.\n", eiter->a.num_ports);
-
+ alen = sizeof(eiter->a.num_ports);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20ad,
+ "PORT COUNT = %x.\n", be32_to_cpu(eiter->a.num_ports));
/* Fabric Name */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_FABRIC_NAME);
- memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE);
- eiter->len = cpu_to_be16(4 + WWN_SIZE);
- size += 4 + WWN_SIZE;
-
- ql_dbg(ql_dbg_disc, vha, 0x20b3,
- "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
-
+ memcpy(eiter->a.fabric_name, vha->fabric_node_name,
+ sizeof(eiter->a.fabric_name));
+ alen = sizeof(eiter->a.fabric_name);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20ae,
+ "FABRIC NAME = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
/* BIOS Version */
eiter = entries + size;
eiter->type = cpu_to_be16(FDMI_HBA_BOOT_BIOS_NAME);
- snprintf(eiter->a.bios_name, sizeof(eiter->a.bios_name),
- "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
- alen = strlen(eiter->a.bios_name);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x20b4,
- "BIOS Name = %s\n", eiter->a.bios_name);
-
+ alen = scnprintf(
+ eiter->a.bios_name, sizeof(eiter->a.bios_name),
+ "BIOS %d.%02d", ha->bios_revision[1], ha->bios_revision[0]);
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20af,
+ "BIOS NAME = %s\n", eiter->a.bios_name);
/* Vendor Identifier */
eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_HBA_TYPE_VENDOR_IDENTIFIER);
- snprintf(eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier),
- "%s", "QLGC");
- alen = strlen(eiter->a.vendor_identifier);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
+ eiter->type = cpu_to_be16(FDMI_HBA_VENDOR_IDENTIFIER);
+ alen = scnprintf(
+ eiter->a.vendor_identifier, sizeof(eiter->a.vendor_identifier),
+ "%s", "QLGC");
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20b0,
+ "VENDOR IDENTIFIER = %s.\n", eiter->a.vendor_identifier);
+done:
+ return size;
+}
- ql_dbg(ql_dbg_disc, vha, 0x201b,
- "Vendor Identifier = %s.\n", eiter->a.vendor_identifier);
+/**
+ * qla2x00_port_attributes() perform Port attributes registration
+ * @vha: HA context
+ * @entries: number of entries to use
+ * @callopt: Option to issue extended or standard FDMI
+ * command parameter
+ *
+ * Returns 0 on success.
+ */
+static unsigned long
+qla2x00_port_attributes(scsi_qla_host_t *vha, void *entries,
+ unsigned int callopt)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct init_cb_24xx *icb24 = (void *)ha->init_cb;
+ struct new_utsname *p_sysid = utsname();
+ char *hostname = p_sysid ?
+ p_sysid->nodename : fc_host_system_hostname(vha->host);
+ struct ct_fdmi_port_attr *eiter;
+ uint16_t alen;
+ unsigned long size = 0;
+
+ /* FC4 types. */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES);
+ eiter->a.fc4_types[0] = 0x00;
+ eiter->a.fc4_types[1] = 0x00;
+ eiter->a.fc4_types[2] = 0x01;
+ eiter->a.fc4_types[3] = 0x00;
+ alen = sizeof(eiter->a.fc4_types);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20c0,
+ "FC4 TYPES = %016llx.\n", *(uint64_t *)eiter->a.fc4_types);
+ if (vha->flags.nvme_enabled) {
+ eiter->a.fc4_types[6] = 1; /* NVMe type 28h */
+ ql_dbg(ql_dbg_disc, vha, 0x211f,
+ "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n",
+ eiter->a.fc4_types[6]);
+ }
+ /* Supported speed. */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
+ eiter->a.sup_speed = cpu_to_be32(
+ qla25xx_fdmi_port_speed_capability(ha));
+ alen = sizeof(eiter->a.sup_speed);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20c1,
+ "SUPPORTED SPEED = %x.\n", be32_to_cpu(eiter->a.sup_speed));
+ /* Current speed. */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
+ eiter->a.cur_speed = cpu_to_be32(
+ qla25xx_fdmi_port_speed_currently(ha));
+ alen = sizeof(eiter->a.cur_speed);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20c2,
+ "CURRENT SPEED = %x.\n", be32_to_cpu(eiter->a.cur_speed));
+ /* Max frame size. */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
+ eiter->a.max_frame_size = cpu_to_be32(le16_to_cpu(IS_FWI2_CAPABLE(ha) ?
+ icb24->frame_payload_size : ha->init_cb->frame_payload_size));
+ alen = sizeof(eiter->a.max_frame_size);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20c3,
+ "MAX FRAME SIZE = %x.\n", be32_to_cpu(eiter->a.max_frame_size));
+ /* OS device name. */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
+ alen = scnprintf(
+ eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name),
+ "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no);
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20c4,
+ "OS DEVICE NAME = %s.\n", eiter->a.os_dev_name);
+ /* Hostname. */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME);
+ if (!*hostname || !strncmp(hostname, "(none)", 6))
+ hostname = "Linux-default";
+ alen = scnprintf(
+ eiter->a.host_name, sizeof(eiter->a.host_name),
+ "%s", hostname);
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20c5,
+ "HOSTNAME = %s.\n", eiter->a.host_name);
+
+ if (callopt == CALLOPT_FDMI1)
+ goto done;
+
+ /* Node Name */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME);
+ memcpy(eiter->a.node_name, vha->node_name, sizeof(eiter->a.node_name));
+ alen = sizeof(eiter->a.node_name);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20c6,
+ "NODENAME = %016llx.\n", wwn_to_u64(eiter->a.node_name));
+
+ /* Port Name */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_NAME);
+ memcpy(eiter->a.port_name, vha->port_name, sizeof(eiter->a.port_name));
+ alen = sizeof(eiter->a.port_name);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20c7,
+ "PORTNAME = %016llx.\n", wwn_to_u64(eiter->a.port_name));
+
+ /* Port Symbolic Name */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME);
+ alen = qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name,
+ sizeof(eiter->a.port_sym_name));
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20c8,
+ "PORT SYMBOLIC NAME = %s\n", eiter->a.port_sym_name);
+
+ /* Port Type */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_TYPE);
+ eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE);
+ alen = sizeof(eiter->a.port_type);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20c9,
+ "PORT TYPE = %x.\n", be32_to_cpu(eiter->a.port_type));
+
+ /* Supported Class of Service */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS);
+ eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3);
+ alen = sizeof(eiter->a.port_supported_cos);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20ca,
+ "SUPPORTED COS = %08x\n", be32_to_cpu(eiter->a.port_supported_cos));
+
+ /* Port Fabric Name */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME);
+ memcpy(eiter->a.fabric_name, vha->fabric_node_name,
+ sizeof(eiter->a.fabric_name));
+ alen = sizeof(eiter->a.fabric_name);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20cb,
+ "FABRIC NAME = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
+
+ /* FC4_type */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE);
+ eiter->a.port_fc4_type[0] = 0x00;
+ eiter->a.port_fc4_type[1] = 0x00;
+ eiter->a.port_fc4_type[2] = 0x01;
+ eiter->a.port_fc4_type[3] = 0x00;
+ alen = sizeof(eiter->a.port_fc4_type);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20cc,
+ "PORT ACTIVE FC4 TYPE = %016llx.\n",
+ *(uint64_t *)eiter->a.port_fc4_type);
+
+ /* Port State */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_STATE);
+ eiter->a.port_state = cpu_to_be32(2);
+ alen = sizeof(eiter->a.port_state);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20cd,
+ "PORT_STATE = %x.\n", be32_to_cpu(eiter->a.port_state));
+
+ /* Number of Ports */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_COUNT);
+ eiter->a.num_ports = cpu_to_be32(1);
+ alen = sizeof(eiter->a.num_ports);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20ce,
+ "PORT COUNT = %x.\n", be32_to_cpu(eiter->a.num_ports));
+
+ /* Port Identifier */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_PORT_IDENTIFIER);
+ eiter->a.port_id = cpu_to_be32(vha->d_id.b24);
+ alen = sizeof(eiter->a.port_id);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20cf,
+ "PORT ID = %x.\n", be32_to_cpu(eiter->a.port_id));
+
+ if (callopt == CALLOPT_FDMI2 || !ql2xsmartsan)
+ goto done;
+
+ /* Smart SAN Service Category (Populate Smart SAN Initiator)*/
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_SMARTSAN_SERVICE);
+ alen = scnprintf(
+ eiter->a.smartsan_service, sizeof(eiter->a.smartsan_service),
+ "%s", "Smart SAN Initiator");
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20d0,
+ "SMARTSAN SERVICE CATEGORY = %s.\n", eiter->a.smartsan_service);
+
+ /* Smart SAN GUID (NWWN+PWWN) */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_SMARTSAN_GUID);
+ memcpy(eiter->a.smartsan_guid, vha->node_name, WWN_SIZE);
+ memcpy(eiter->a.smartsan_guid + WWN_SIZE, vha->port_name, WWN_SIZE);
+ alen = sizeof(eiter->a.smartsan_guid);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20d1,
+ "Smart SAN GUID = %016llx-%016llx\n",
+ wwn_to_u64(eiter->a.smartsan_guid),
+ wwn_to_u64(eiter->a.smartsan_guid + WWN_SIZE));
+
+ /* Smart SAN Version (populate "Smart SAN Version 1.0") */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_SMARTSAN_VERSION);
+ alen = scnprintf(
+ eiter->a.smartsan_version, sizeof(eiter->a.smartsan_version),
+ "%s", "Smart SAN Version 2.0");
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20d2,
+ "SMARTSAN VERSION = %s\n", eiter->a.smartsan_version);
+
+ /* Smart SAN Product Name (Specify Adapter Model No) */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_SMARTSAN_PROD_NAME);
+ alen = scnprintf(eiter->a.smartsan_prod_name,
+ sizeof(eiter->a.smartsan_prod_name),
+ "ISP%04x", ha->pdev->device);
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20d3,
+ "SMARTSAN PRODUCT NAME = %s\n", eiter->a.smartsan_prod_name);
+
+ /* Smart SAN Port Info (specify: 1=Physical, 2=NPIV, 3=SRIOV) */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_SMARTSAN_PORT_INFO);
+ eiter->a.smartsan_port_info = cpu_to_be32(vha->vp_idx ? 2 : 1);
+ alen = sizeof(eiter->a.smartsan_port_info);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20d4,
+ "SMARTSAN PORT INFO = %x\n", eiter->a.smartsan_port_info);
+
+ /* Smart SAN Security Support */
+ eiter = entries + size;
+ eiter->type = cpu_to_be16(FDMI_SMARTSAN_SECURITY_SUPPORT);
+ eiter->a.smartsan_security_support = cpu_to_be32(1);
+ alen = sizeof(eiter->a.smartsan_security_support);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+ size += alen;
+ ql_dbg(ql_dbg_disc, vha, 0x20d6,
+ "SMARTSAN SECURITY SUPPORT = %d\n",
+ be32_to_cpu(eiter->a.smartsan_security_support));
+
+done:
+ return size;
+}
+
+/**
+ * qla2x00_fdmi_rhba() - perform RHBA FDMI registration
+ * @vha: HA context
+ * @callopt: Option to issue FDMI registration
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_fdmi_rhba(scsi_qla_host_t *vha, unsigned int callopt)
+{
+ struct qla_hw_data *ha = vha->hw;
+ unsigned long size = 0;
+ unsigned int rval, count;
+ ms_iocb_entry_t *ms_pkt;
+ struct ct_sns_req *ct_req;
+ struct ct_sns_rsp *ct_rsp;
+ void *entries;
+
+ count = callopt != CALLOPT_FDMI1 ?
+ FDMI2_HBA_ATTR_COUNT : FDMI1_HBA_ATTR_COUNT;
+
+ size = RHBA_RSP_SIZE;
+
+ ql_dbg(ql_dbg_disc, vha, 0x20e0,
+ "RHBA (callopt=%x count=%u size=%lu).\n", callopt, count, size);
+
+ /* Request size adjusted after CT preparation */
+ ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size);
+
+ /* Prepare CT request */
+ ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RHBA_CMD, size);
+ ct_rsp = &ha->ct_sns->p.rsp;
+
+ /* Prepare FDMI command entries */
+ memcpy(ct_req->req.rhba.hba_identifier, vha->port_name,
+ sizeof(ct_req->req.rhba.hba_identifier));
+ size += sizeof(ct_req->req.rhba.hba_identifier);
+
+ ct_req->req.rhba.entry_count = cpu_to_be32(1);
+ size += sizeof(ct_req->req.rhba.entry_count);
+
+ memcpy(ct_req->req.rhba.port_name, vha->port_name,
+ sizeof(ct_req->req.rhba.port_name));
+ size += sizeof(ct_req->req.rhba.port_name);
+
+ /* Attribute count */
+ ct_req->req.rhba.attrs.count = cpu_to_be32(count);
+ size += sizeof(ct_req->req.rhba.attrs.count);
+
+ /* Attribute block */
+ entries = &ct_req->req.rhba.attrs.entry;
+
+ size += qla2x00_hba_attributes(vha, entries, callopt);
/* Update MS request size. */
qla2x00_update_ms_fdmi_iocb(vha, size + 16);
- ql_dbg(ql_dbg_disc, vha, 0x20b5,
- "RHBA identifier = %016llx.\n",
- wwn_to_u64(ct_req->req.rhba2.hba_identifier));
- ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20b6,
+ ql_dbg(ql_dbg_disc, vha, 0x20e1,
+ "RHBA %016llx %016llx.\n",
+ wwn_to_u64(ct_req->req.rhba.hba_identifier),
+ wwn_to_u64(ct_req->req.rhba.port_name));
+
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20e2,
entries, size);
/* Execute MS IOCB */
rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
- sizeof(ms_iocb_entry_t));
- if (rval != QLA_SUCCESS) {
- /*EMPTY*/
- ql_dbg(ql_dbg_disc, vha, 0x20b7,
- "RHBA issue IOCB failed (%d).\n", rval);
- } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA") !=
- QLA_SUCCESS) {
- rval = QLA_FUNCTION_FAILED;
+ sizeof(*ha->ms_iocb));
+ if (rval) {
+ ql_dbg(ql_dbg_disc, vha, 0x20e3,
+ "RHBA iocb failed (%d).\n", rval);
+ return rval;
+ }
+ rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RHBA");
+ if (rval) {
if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
ct_rsp->header.explanation_code ==
CT_EXPL_ALREADY_REGISTERED) {
- ql_dbg(ql_dbg_disc, vha, 0x20b8,
- "HBA already registered.\n");
- rval = QLA_ALREADY_REGISTERED;
- } else {
- ql_dbg(ql_dbg_disc, vha, 0x2016,
- "RHBA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
- ct_rsp->header.reason_code,
- ct_rsp->header.explanation_code);
+ ql_dbg(ql_dbg_disc, vha, 0x20e4,
+ "RHBA already registered.\n");
+ return QLA_ALREADY_REGISTERED;
}
- } else {
- ql_dbg(ql_dbg_disc, vha, 0x20b9,
- "RHBA FDMI V2 exiting normally.\n");
+
+ ql_dbg(ql_dbg_disc, vha, 0x20e5,
+ "RHBA failed, CT Reason %#x, CT Explanation %#x\n",
+ ct_rsp->header.reason_code,
+ ct_rsp->header.explanation_code);
+ return rval;
}
+ ql_dbg(ql_dbg_disc, vha, 0x20e6, "RHBA exiting normally.\n");
return rval;
}
-/**
- * qla2x00_fdmi_dhba() -
- * @vha: HA context
- *
- * Returns 0 on success.
- */
+
static int
qla2x00_fdmi_dhba(scsi_qla_host_t *vha)
{
@@ -2250,22 +2243,17 @@
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
-
/* Issue RPA */
/* Prepare common MS IOCB */
ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, DHBA_REQ_SIZE,
DHBA_RSP_SIZE);
-
/* Prepare CT request */
ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, DHBA_CMD, DHBA_RSP_SIZE);
ct_rsp = &ha->ct_sns->p.rsp;
-
/* Prepare FDMI command arguments -- portname. */
memcpy(ct_req->req.dhba.port_name, vha->port_name, WWN_SIZE);
-
ql_dbg(ql_dbg_disc, vha, 0x2036,
"DHBA portname = %8phN.\n", ct_req->req.dhba.port_name);
-
/* Execute MS IOCB */
rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
sizeof(ms_iocb_entry_t));
@@ -2280,337 +2268,178 @@
ql_dbg(ql_dbg_disc, vha, 0x2038,
"DHBA exiting normally.\n");
}
-
return rval;
}
/**
- * qla2x00_fdmiv2_rpa() -
+ * qla2x00_fdmi_rprt() perform RPRT registration
* @vha: HA context
+ * @callopt: Option to issue extended or standard FDMI
+ * command parameter
*
* Returns 0 on success.
*/
static int
-qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha)
+qla2x00_fdmi_rprt(scsi_qla_host_t *vha, int callopt)
{
- int rval, alen;
- uint32_t size;
+ struct scsi_qla_host *base_vha = pci_get_drvdata(vha->hw->pdev);
struct qla_hw_data *ha = vha->hw;
+ ulong size = 0;
+ uint rval, count;
ms_iocb_entry_t *ms_pkt;
struct ct_sns_req *ct_req;
struct ct_sns_rsp *ct_rsp;
void *entries;
- struct ct_fdmiv2_port_attr *eiter;
- struct init_cb_24xx *icb24 = (struct init_cb_24xx *)ha->init_cb;
- struct new_utsname *p_sysid = NULL;
+ count = callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ?
+ FDMI2_SMARTSAN_PORT_ATTR_COUNT :
+ callopt != CALLOPT_FDMI1 ?
+ FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT;
- /* Issue RPA */
- /* Prepare common MS IOCB */
- /* Request size adjusted after CT preparation */
- ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, RPA_RSP_SIZE);
+ size = RPRT_RSP_SIZE;
+ ql_dbg(ql_dbg_disc, vha, 0x20e8,
+ "RPRT (callopt=%x count=%u size=%lu).\n", callopt, count, size);
+ /* Request size adjusted after CT preparation */
+ ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size);
+ /* Prepare CT request */
+ ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPRT_CMD, size);
+ ct_rsp = &ha->ct_sns->p.rsp;
+ /* Prepare FDMI command entries */
+ memcpy(ct_req->req.rprt.hba_identifier, base_vha->port_name,
+ sizeof(ct_req->req.rprt.hba_identifier));
+ size += sizeof(ct_req->req.rprt.hba_identifier);
+ memcpy(ct_req->req.rprt.port_name, vha->port_name,
+ sizeof(ct_req->req.rprt.port_name));
+ size += sizeof(ct_req->req.rprt.port_name);
+ /* Attribute count */
+ ct_req->req.rprt.attrs.count = cpu_to_be32(count);
+ size += sizeof(ct_req->req.rprt.attrs.count);
+ /* Attribute block */
+ entries = ct_req->req.rprt.attrs.entry;
+ size += qla2x00_port_attributes(vha, entries, callopt);
+ /* Update MS request size. */
+ qla2x00_update_ms_fdmi_iocb(vha, size + 16);
+ ql_dbg(ql_dbg_disc, vha, 0x20e9,
+ "RPRT %016llx %016llx.\n",
+ wwn_to_u64(ct_req->req.rprt.port_name),
+ wwn_to_u64(ct_req->req.rprt.port_name));
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ea,
+ entries, size);
+ /* Execute MS IOCB */
+ rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
+ sizeof(*ha->ms_iocb));
+ if (rval) {
+ ql_dbg(ql_dbg_disc, vha, 0x20eb,
+ "RPRT iocb failed (%d).\n", rval);
+ return rval;
+ }
+ rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPRT");
+ if (rval) {
+ if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
+ ct_rsp->header.explanation_code ==
+ CT_EXPL_ALREADY_REGISTERED) {
+ ql_dbg(ql_dbg_disc, vha, 0x20ec,
+ "RPRT already registered.\n");
+ return QLA_ALREADY_REGISTERED;
+ }
+
+ ql_dbg(ql_dbg_disc, vha, 0x20ed,
+ "RPRT failed, CT Reason code: %#x, CT Explanation %#x\n",
+ ct_rsp->header.reason_code,
+ ct_rsp->header.explanation_code);
+ return rval;
+ }
+ ql_dbg(ql_dbg_disc, vha, 0x20ee, "RPRT exiting normally.\n");
+ return rval;
+}
+
+/**
+ * qla2x00_fdmi_rpa() - perform RPA registration
+ * @vha: HA context
+ * @callopt: Option to issue FDMI registration
+ *
+ * Returns 0 on success.
+ */
+static int
+qla2x00_fdmi_rpa(scsi_qla_host_t *vha, uint callopt)
+{
+ struct qla_hw_data *ha = vha->hw;
+ ulong size = 0;
+ uint rval, count;
+ ms_iocb_entry_t *ms_pkt;
+ struct ct_sns_req *ct_req;
+ struct ct_sns_rsp *ct_rsp;
+ void *entries;
+
+ count =
+ callopt == CALLOPT_FDMI2_SMARTSAN && ql2xsmartsan ?
+ FDMI2_SMARTSAN_PORT_ATTR_COUNT :
+ callopt != CALLOPT_FDMI1 ?
+ FDMI2_PORT_ATTR_COUNT : FDMI1_PORT_ATTR_COUNT;
+
+ size =
+ callopt != CALLOPT_FDMI1 ?
+ SMARTSAN_RPA_RSP_SIZE : RPA_RSP_SIZE;
+
+ ql_dbg(ql_dbg_disc, vha, 0x20f0,
+ "RPA (callopt=%x count=%u size=%lu).\n", callopt, count, size);
+
+ /* Request size adjusted after CT preparation */
+ ms_pkt = ha->isp_ops->prep_ms_fdmi_iocb(vha, 0, size);
/* Prepare CT request */
- ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, RPA_RSP_SIZE);
+ ct_req = qla2x00_prep_ct_fdmi_req(ha->ct_sns, RPA_CMD, size);
ct_rsp = &ha->ct_sns->p.rsp;
- /* Prepare FDMI command arguments -- attribute block, attributes. */
- memcpy(ct_req->req.rpa2.port_name, vha->port_name, WWN_SIZE);
- size = WWN_SIZE + 4;
+ /* Prepare FDMI command entries. */
+ memcpy(ct_req->req.rpa.port_name, vha->port_name,
+ sizeof(ct_req->req.rpa.port_name));
+ size += sizeof(ct_req->req.rpa.port_name);
- /* Attributes */
- ct_req->req.rpa2.attrs.count = cpu_to_be32(FDMIV2_PORT_ATTR_COUNT);
- entries = &ct_req->req;
+ /* Attribute count */
+ ct_req->req.rpa.attrs.count = cpu_to_be32(count);
+ size += sizeof(ct_req->req.rpa.attrs.count);
- /* FC4 types. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPES);
- eiter->len = cpu_to_be16(4 + 32);
- eiter->a.fc4_types[2] = 0x01;
- size += 4 + 32;
+ /* Attribute block */
+ entries = ct_req->req.rpa.attrs.entry;
- ql_dbg(ql_dbg_disc, vha, 0x20ba,
- "FC4_TYPES=%02x %02x.\n",
- eiter->a.fc4_types[2],
- eiter->a.fc4_types[1]);
-
- if (vha->flags.nvme_enabled) {
- eiter->a.fc4_types[6] = 1; /* NVMe type 28h */
- ql_dbg(ql_dbg_disc, vha, 0x211f,
- "NVME FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n",
- eiter->a.fc4_types[6]);
- }
-
- /* Supported speed. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
- eiter->len = cpu_to_be16(4 + 4);
- if (IS_CNA_CAPABLE(ha))
- eiter->a.sup_speed = cpu_to_be32(
- FDMI_PORT_SPEED_10GB);
- else if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
- eiter->a.sup_speed = cpu_to_be32(
- FDMI_PORT_SPEED_32GB|
- FDMI_PORT_SPEED_16GB|
- FDMI_PORT_SPEED_8GB);
- else if (IS_QLA2031(ha))
- eiter->a.sup_speed = cpu_to_be32(
- FDMI_PORT_SPEED_16GB|
- FDMI_PORT_SPEED_8GB|
- FDMI_PORT_SPEED_4GB);
- else if (IS_QLA25XX(ha))
- eiter->a.sup_speed = cpu_to_be32(
- FDMI_PORT_SPEED_8GB|
- FDMI_PORT_SPEED_4GB|
- FDMI_PORT_SPEED_2GB|
- FDMI_PORT_SPEED_1GB);
- else if (IS_QLA24XX_TYPE(ha))
- eiter->a.sup_speed = cpu_to_be32(
- FDMI_PORT_SPEED_4GB|
- FDMI_PORT_SPEED_2GB|
- FDMI_PORT_SPEED_1GB);
- else if (IS_QLA23XX(ha))
- eiter->a.sup_speed = cpu_to_be32(
- FDMI_PORT_SPEED_2GB|
- FDMI_PORT_SPEED_1GB);
- else
- eiter->a.sup_speed = cpu_to_be32(
- FDMI_PORT_SPEED_1GB);
- size += 4 + 4;
-
- ql_dbg(ql_dbg_disc, vha, 0x20bb,
- "Supported Port Speed = %x.\n", eiter->a.sup_speed);
-
- /* Current speed. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_CURRENT_SPEED);
- eiter->len = cpu_to_be16(4 + 4);
- switch (ha->link_data_rate) {
- case PORT_SPEED_1GB:
- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_1GB);
- break;
- case PORT_SPEED_2GB:
- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_2GB);
- break;
- case PORT_SPEED_4GB:
- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_4GB);
- break;
- case PORT_SPEED_8GB:
- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_8GB);
- break;
- case PORT_SPEED_10GB:
- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_10GB);
- break;
- case PORT_SPEED_16GB:
- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_16GB);
- break;
- case PORT_SPEED_32GB:
- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_32GB);
- break;
- default:
- eiter->a.cur_speed = cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
- break;
- }
- size += 4 + 4;
-
- ql_dbg(ql_dbg_disc, vha, 0x2017,
- "Current_Speed = %x.\n", eiter->a.cur_speed);
-
- /* Max frame size. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
- eiter->len = cpu_to_be16(4 + 4);
- eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ?
- le16_to_cpu(icb24->frame_payload_size) :
- le16_to_cpu(ha->init_cb->frame_payload_size);
- eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size);
- size += 4 + 4;
-
- ql_dbg(ql_dbg_disc, vha, 0x20bc,
- "Max_Frame_Size = %x.\n", eiter->a.max_frame_size);
-
- /* OS device name. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME);
- alen = strlen(QLA2XXX_DRIVER_NAME);
- snprintf(eiter->a.os_dev_name, sizeof(eiter->a.os_dev_name),
- "%s:host%lu", QLA2XXX_DRIVER_NAME, vha->host_no);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x20be,
- "OS_Device_Name = %s.\n", eiter->a.os_dev_name);
-
- /* Hostname. */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME);
- p_sysid = utsname();
- if (p_sysid) {
- snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
- "%s", p_sysid->nodename);
- } else {
- snprintf(eiter->a.host_name, sizeof(eiter->a.host_name),
- "%s", fc_host_system_hostname(vha->host));
- }
- alen = strlen(eiter->a.host_name);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x201a,
- "HostName=%s.\n", eiter->a.host_name);
-
- /* Node Name */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_NODE_NAME);
- memcpy(eiter->a.node_name, vha->node_name, WWN_SIZE);
- eiter->len = cpu_to_be16(4 + WWN_SIZE);
- size += 4 + WWN_SIZE;
-
- ql_dbg(ql_dbg_disc, vha, 0x20c0,
- "Node Name = %016llx.\n", wwn_to_u64(eiter->a.node_name));
-
- /* Port Name */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_NAME);
- memcpy(eiter->a.port_name, vha->port_name, WWN_SIZE);
- eiter->len = cpu_to_be16(4 + WWN_SIZE);
- size += 4 + WWN_SIZE;
-
- ql_dbg(ql_dbg_disc, vha, 0x20c1,
- "Port Name = %016llx.\n", wwn_to_u64(eiter->a.port_name));
-
- /* Port Symbolic Name */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_SYM_NAME);
- qla2x00_get_sym_node_name(vha, eiter->a.port_sym_name,
- sizeof(eiter->a.port_sym_name));
- alen = strlen(eiter->a.port_sym_name);
- alen += 4 - (alen & 3);
- eiter->len = cpu_to_be16(4 + alen);
- size += 4 + alen;
-
- ql_dbg(ql_dbg_disc, vha, 0x20c2,
- "port symbolic name = %s\n", eiter->a.port_sym_name);
-
- /* Port Type */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_TYPE);
- eiter->a.port_type = cpu_to_be32(NS_NX_PORT_TYPE);
- eiter->len = cpu_to_be16(4 + 4);
- size += 4 + 4;
-
- ql_dbg(ql_dbg_disc, vha, 0x20c3,
- "Port Type = %x.\n", eiter->a.port_type);
-
- /* Class of Service */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_SUPP_COS);
- eiter->a.port_supported_cos = cpu_to_be32(FC_CLASS_3);
- eiter->len = cpu_to_be16(4 + 4);
- size += 4 + 4;
-
- ql_dbg(ql_dbg_disc, vha, 0x20c4,
- "Supported COS = %08x\n", eiter->a.port_supported_cos);
-
- /* Port Fabric Name */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_FABRIC_NAME);
- memcpy(eiter->a.fabric_name, vha->fabric_node_name, WWN_SIZE);
- eiter->len = cpu_to_be16(4 + WWN_SIZE);
- size += 4 + WWN_SIZE;
-
- ql_dbg(ql_dbg_disc, vha, 0x20c5,
- "Fabric Name = %016llx.\n", wwn_to_u64(eiter->a.fabric_name));
-
- /* FC4_type */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_FC4_TYPE);
- eiter->a.port_fc4_type[0] = 0;
- eiter->a.port_fc4_type[1] = 0;
- eiter->a.port_fc4_type[2] = 1;
- eiter->a.port_fc4_type[3] = 0;
- eiter->len = cpu_to_be16(4 + 32);
- size += 4 + 32;
-
- ql_dbg(ql_dbg_disc, vha, 0x20c6,
- "Port Active FC4 Type = %02x %02x.\n",
- eiter->a.port_fc4_type[2], eiter->a.port_fc4_type[1]);
-
- if (vha->flags.nvme_enabled) {
- eiter->a.port_fc4_type[4] = 0;
- eiter->a.port_fc4_type[5] = 0;
- eiter->a.port_fc4_type[6] = 1; /* NVMe type 28h */
- ql_dbg(ql_dbg_disc, vha, 0x2120,
- "NVME Port Active FC4 Type = %02x 0x0 0x0 0x0 0x0 0x0.\n",
- eiter->a.port_fc4_type[6]);
- }
-
- /* Port State */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_STATE);
- eiter->a.port_state = cpu_to_be32(1);
- eiter->len = cpu_to_be16(4 + 4);
- size += 4 + 4;
-
- ql_dbg(ql_dbg_disc, vha, 0x20c7,
- "Port State = %x.\n", eiter->a.port_state);
-
- /* Number of Ports */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_COUNT);
- eiter->a.num_ports = cpu_to_be32(1);
- eiter->len = cpu_to_be16(4 + 4);
- size += 4 + 4;
-
- ql_dbg(ql_dbg_disc, vha, 0x20c8,
- "Number of ports = %x.\n", eiter->a.num_ports);
-
- /* Port Id */
- eiter = entries + size;
- eiter->type = cpu_to_be16(FDMI_PORT_ID);
- eiter->a.port_id = cpu_to_be32(vha->d_id.b24);
- eiter->len = cpu_to_be16(4 + 4);
- size += 4 + 4;
-
- ql_dbg(ql_dbg_disc, vha, 0x201c,
- "Port Id = %x.\n", eiter->a.port_id);
+ size += qla2x00_port_attributes(vha, entries, callopt);
/* Update MS request size. */
qla2x00_update_ms_fdmi_iocb(vha, size + 16);
- ql_dbg(ql_dbg_disc, vha, 0x2018,
- "RPA portname= %8phN size=%d.\n", ct_req->req.rpa.port_name, size);
- ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20ca,
+ ql_dbg(ql_dbg_disc, vha, 0x20f1,
+ "RPA %016llx.\n", wwn_to_u64(ct_req->req.rpa.port_name));
+
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x20f2,
entries, size);
/* Execute MS IOCB */
rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
- sizeof(ms_iocb_entry_t));
- if (rval != QLA_SUCCESS) {
- /*EMPTY*/
- ql_dbg(ql_dbg_disc, vha, 0x20cb,
- "RPA FDMI v2 issue IOCB failed (%d).\n", rval);
- } else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA") !=
- QLA_SUCCESS) {
- rval = QLA_FUNCTION_FAILED;
+ sizeof(*ha->ms_iocb));
+ if (rval) {
+ ql_dbg(ql_dbg_disc, vha, 0x20f3,
+ "RPA iocb failed (%d).\n", rval);
+ return rval;
+ }
+
+ rval = qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp, "RPA");
+ if (rval) {
if (ct_rsp->header.reason_code == CT_REASON_CANNOT_PERFORM &&
ct_rsp->header.explanation_code ==
CT_EXPL_ALREADY_REGISTERED) {
- ql_dbg(ql_dbg_disc, vha, 0x20ce,
- "RPA FDMI v2 already registered\n");
- rval = QLA_ALREADY_REGISTERED;
- } else {
- ql_dbg(ql_dbg_disc, vha, 0x2020,
- "RPA FDMI v2 failed, CT Reason code: 0x%x, CT Explanation 0x%x\n",
- ct_rsp->header.reason_code,
- ct_rsp->header.explanation_code);
+ ql_dbg(ql_dbg_disc, vha, 0x20f4,
+ "RPA already registered.\n");
+ return QLA_ALREADY_REGISTERED;
}
- } else {
- ql_dbg(ql_dbg_disc, vha, 0x20cc,
- "RPA FDMI V2 exiting normally.\n");
+
+ ql_dbg(ql_dbg_disc, vha, 0x20f5,
+ "RPA failed, CT Reason code: %#x, CT Explanation %#x\n",
+ ct_rsp->header.reason_code,
+ ct_rsp->header.explanation_code);
+ return rval;
}
+ ql_dbg(ql_dbg_disc, vha, 0x20f6, "RPA exiting normally.\n");
return rval;
}
@@ -2623,18 +2452,31 @@
int
qla2x00_fdmi_register(scsi_qla_host_t *vha)
{
- int rval = QLA_FUNCTION_FAILED;
+ int rval = QLA_SUCCESS;
struct qla_hw_data *ha = vha->hw;
if (IS_QLA2100(ha) || IS_QLA2200(ha) ||
IS_QLAFX00(ha))
- return QLA_FUNCTION_FAILED;
+ return rval;
rval = qla2x00_mgmt_svr_login(vha);
if (rval)
return rval;
- rval = qla2x00_fdmiv2_rhba(vha);
+ /* For npiv/vport send rprt only */
+ if (vha->vp_idx) {
+ if (ql2xsmartsan)
+ rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI2_SMARTSAN);
+ if (rval || !ql2xsmartsan)
+ rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI2);
+ if (rval)
+ rval = qla2x00_fdmi_rprt(vha, CALLOPT_FDMI1);
+
+ return rval;
+ }
+
+ /* Try fdmi2 first, if fails then try fdmi1 */
+ rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI2);
if (rval) {
if (rval != QLA_ALREADY_REGISTERED)
goto try_fdmi;
@@ -2643,18 +2485,22 @@
if (rval)
goto try_fdmi;
- rval = qla2x00_fdmiv2_rhba(vha);
+ rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI2);
if (rval)
goto try_fdmi;
}
- rval = qla2x00_fdmiv2_rpa(vha);
+
+ if (ql2xsmartsan)
+ rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI2_SMARTSAN);
+ if (rval || !ql2xsmartsan)
+ rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI2);
if (rval)
goto try_fdmi;
- goto out;
+ return rval;
try_fdmi:
- rval = qla2x00_fdmi_rhba(vha);
+ rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI1);
if (rval) {
if (rval != QLA_ALREADY_REGISTERED)
return rval;
@@ -2663,12 +2509,13 @@
if (rval)
return rval;
- rval = qla2x00_fdmi_rhba(vha);
+ rval = qla2x00_fdmi_rhba(vha, CALLOPT_FDMI1);
if (rval)
return rval;
}
- rval = qla2x00_fdmi_rpa(vha);
-out:
+
+ rval = qla2x00_fdmi_rpa(vha, CALLOPT_FDMI1);
+
return rval;
}
@@ -2893,7 +2740,7 @@
for (i = 0; i < ha->max_fibre_devices; i++) {
/* Set default FC4 Type as UNKNOWN so the default is to
* Process this port */
- list[i].fc4_type = FC4_TYPE_UNKNOWN;
+ list[i].fc4_type = 0;
/* Do not attempt GFF_ID if we are not FWI_2 capable */
if (!IS_FWI2_CAPABLE(ha))
@@ -2963,7 +2810,6 @@
return QLA_FUNCTION_FAILED;
e->u.fcport.fcport = fcport;
- fcport->flags |= FCF_ASYNC_ACTIVE;
return qla2x00_post_work(vha, e);
}
@@ -3097,9 +2943,7 @@
done_free_sp:
sp->free(sp);
- fcport->flags &= ~FCF_ASYNC_SENT;
done:
- fcport->flags &= ~FCF_ASYNC_ACTIVE;
return rval;
}
@@ -3246,7 +3090,7 @@
"%s %d %8phC post new sess\n",
__func__, __LINE__, ea->port_name);
qla24xx_post_newsess_work(vha, &ea->id,
- ea->port_name, NULL, NULL, FC4_TYPE_UNKNOWN);
+ ea->port_name, NULL, NULL, 0);
}
}
}
@@ -3571,7 +3415,7 @@
u8 recheck = 0;
u16 dup = 0, dup_cnt = 0;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
"%s enter\n", __func__);
if (sp->gen1 != vha->hw->base_qpair->chip_reset) {
@@ -3587,11 +3431,22 @@
if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ goto out;
} else {
ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Fabric scan failed on all retries.\n");
+ "%s: Fabric scan failed for %d retries.\n",
+ __func__, vha->scan.scan_retry);
+ /*
+ * Unable to scan any rports. logout loop below
+ * will unregister all sessions.
+ */
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if ((fcport->flags & FCF_FABRIC_DEVICE) != 0) {
+ fcport->scan_state = QLA_FCPORT_SCAN;
+ }
+ }
+ goto login_logout;
}
- goto out;
}
vha->scan.scan_retry = 0;
@@ -3638,6 +3493,7 @@
if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE))
continue;
fcport->scan_state = QLA_FCPORT_FOUND;
+ fcport->last_rscn_gen = fcport->rscn_gen;
found = true;
/*
* If device was not a fabric device before.
@@ -3671,6 +3527,7 @@
dup_cnt);
}
+login_logout:
/*
* Logout all previous fabric dev marked lost, except FCP2 devices.
*/
@@ -3897,6 +3754,18 @@
unsigned long flags;
const char *name = sp->name;
+ if (res == QLA_OS_TIMER_EXPIRED) {
+ /* switch is ignoring all commands.
+ * This might be a zone disable behavior.
+ * This means we hit 64s timeout.
+ * 22s GPNFT + 44s Abort = 64s
+ */
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s: Switch Zone check please .\n",
+ name);
+ qla2x00_mark_all_devices_lost(vha);
+ }
+
/*
* We are in an Interrupt context, queue up this
* sp for GNNFT_DONE work. This will allow all
@@ -4069,7 +3938,7 @@
void qla24xx_async_gpnft_done(scsi_qla_host_t *vha, srb_t *sp)
{
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
"%s enter\n", __func__);
qla24xx_async_gnnft(vha, sp, sp->gen2);
}
@@ -4083,7 +3952,7 @@
u32 rspsz;
unsigned long flags;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
"%s enter\n", __func__);
if (!vha->flags.online)
@@ -4092,14 +3961,15 @@
spin_lock_irqsave(&vha->work_lock, flags);
if (vha->scan.scan_flags & SF_SCANNING) {
spin_unlock_irqrestore(&vha->work_lock, flags);
- ql_dbg(ql_dbg_disc, vha, 0xffff, "scan active\n");
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
+ "%s: scan active\n", __func__);
return rval;
}
vha->scan.scan_flags |= SF_SCANNING;
spin_unlock_irqrestore(&vha->work_lock, flags);
if (fc4_type == FC4_TYPE_FCP_SCSI) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
"%s: Performing FCP Scan\n", __func__);
if (sp)
@@ -4154,7 +4024,7 @@
}
sp->u.iocb_cmd.u.ctarg.rsp_size = rspsz;
- ql_dbg(ql_dbg_disc, vha, 0xffff,
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
"%s scan list size %d\n", __func__, vha->scan.size);
memset(vha->scan.l, 0, vha->scan.size);
@@ -4219,8 +4089,8 @@
spin_lock_irqsave(&vha->work_lock, flags);
vha->scan.scan_flags &= ~SF_SCANNING;
if (vha->scan.scan_flags == 0) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s: schedule\n", __func__);
+ ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0xffff,
+ "%s: Scan scheduled.\n", __func__);
vha->scan.scan_flags |= SF_QUEUED;
schedule_delayed_work(&vha->scan.scan_work, 5);
}
@@ -4464,7 +4334,6 @@
done_free_sp:
sp->free(sp);
- fcport->flags &= ~FCF_ASYNC_SENT;
done:
return rval;
}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 643b8ae..fdae25e 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
#include "qla_gbl.h"
@@ -17,7 +16,6 @@
#include <asm/prom.h>
#endif
-#include <target/target_core_base.h>
#include "qla_target.h"
/*
@@ -131,7 +129,7 @@
if (sp->cmd_sp)
sp->cmd_sp->done(sp->cmd_sp, QLA_OS_TIMER_EXPIRED);
- abt->u.abt.comp_status = CS_TIMEOUT;
+ abt->u.abt.comp_status = cpu_to_le16(CS_TIMEOUT);
sp->done(sp, QLA_OS_TIMER_EXPIRED);
}
@@ -426,7 +424,7 @@
fcport->flags &= ~FCF_ASYNC_ACTIVE;
/* Don't re-login in target mode */
if (!fcport->tgt_session)
- qla2x00_mark_device_lost(vha, fcport, 1, 0);
+ qla2x00_mark_device_lost(vha, fcport, 1);
qlt_logo_completion_handler(fcport, data[0]);
}
@@ -868,7 +866,7 @@
fcport);
break;
}
- /* fall through */
+ fallthrough;
default:
if (fcport_is_smaller(fcport)) {
/* local adapter is bigger */
@@ -978,8 +976,6 @@
sp->name, res, sp->u.iocb_cmd.u.mbx.in_mb[1],
sp->u.iocb_cmd.u.mbx.in_mb[2]);
- if (res == QLA_FUNCTION_TIMEOUT)
- return;
sp->fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE);
memset(&ea, 0, sizeof(ea));
@@ -1003,7 +999,7 @@
ql_dbg(ql_dbg_disc, vha, 0x20e8,
"%s %8phC %02x:%02x:%02x CLS %x/%x lid %x \n",
- __func__, (void *)&wwn, e->port_id[2], e->port_id[1],
+ __func__, &wwn, e->port_id[2], e->port_id[1],
e->port_id[0], e->current_login_state, e->last_login_state,
(loop_id & 0x7fff));
}
@@ -1017,8 +1013,8 @@
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
list_for_each_entry_safe(fcport, tf, &h, gnl_entry) {
- list_del_init(&fcport->gnl_entry);
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+ list_del_init(&fcport->gnl_entry);
fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
ea.fcport = fcport;
@@ -1054,7 +1050,7 @@
__func__, __LINE__, (u8 *)&wwn, id.b24);
wwnn = wwn_to_u64(e->node_name);
qla24xx_post_newsess_work(vha, &id, (u8 *)&wwn,
- (u8 *)&wwnn, NULL, FC4_TYPE_UNKNOWN);
+ (u8 *)&wwnn, NULL, 0);
}
}
@@ -1140,8 +1136,8 @@
done_free_sp:
sp->free(sp);
- fcport->flags &= ~FCF_ASYNC_SENT;
done:
+ fcport->flags &= ~(FCF_ASYNC_ACTIVE | FCF_ASYNC_SENT);
return rval;
}
@@ -1192,6 +1188,9 @@
{
struct qla_work_evt *e;
+ if (vha->host->active_mode == MODE_TARGET)
+ return QLA_FUNCTION_FAILED;
+
e = qla2x00_alloc_work(vha, QLA_EVT_PRLI);
if (!e)
return QLA_FUNCTION_FAILED;
@@ -1270,9 +1269,10 @@
lio->u.logio.flags |= SRB_LOGIN_NVME_PRLI;
ql_dbg(ql_dbg_disc, vha, 0x211b,
- "Async-prli - %8phC hdl=%x, loopid=%x portid=%06x retries=%d %s.\n",
+ "Async-prli - %8phC hdl=%x, loopid=%x portid=%06x retries=%d fc4type %x priority %x %s.\n",
fcport->port_name, sp->handle, fcport->loop_id, fcport->d_id.b24,
- fcport->login_retry, NVME_TARGET(vha->hw, fcport) ? "nvme" : "fc");
+ fcport->login_retry, fcport->fc4_type, vha->hw->fc4_type_priority,
+ NVME_TARGET(vha->hw, fcport) ? "nvme" : "fcp");
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
@@ -1354,7 +1354,7 @@
mb[9] = vha->vp_idx;
mb[10] = opt;
- mbx->u.mbx.in = (void *)pd;
+ mbx->u.mbx.in = pd;
mbx->u.mbx.in_dma = pd_dma;
sp->done = qla24xx_async_gpdb_sp_done;
@@ -1375,6 +1375,7 @@
sp->free(sp);
fcport->flags &= ~FCF_ASYNC_SENT;
done:
+ fcport->flags &= ~FCF_ASYNC_ACTIVE;
qla24xx_post_gpdb_work(vha, fcport, opt);
return rval;
}
@@ -1553,8 +1554,8 @@
}
}
- /* for pure Target Mode. Login will not be initiated */
- if (vha->host->active_mode == MODE_TARGET)
+ /* Target won't initiate port login if fabric is present */
+ if (vha->host->active_mode == MODE_TARGET && !N2N_TOPO(vha->hw))
return 0;
if (fcport->flags & FCF_ASYNC_SENT) {
@@ -1705,10 +1706,52 @@
fc_port_t *fcport;
unsigned long flags;
- fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
- if (fcport) {
- fcport->scan_needed = 1;
- fcport->rscn_gen++;
+ switch (ea->id.b.rsvd_1) {
+ case RSCN_PORT_ADDR:
+ fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
+ if (fcport) {
+ if (fcport->flags & FCF_FCP2_DEVICE) {
+ ql_dbg(ql_dbg_disc, vha, 0x2115,
+ "Delaying session delete for FCP2 portid=%06x %8phC ",
+ fcport->d_id.b24, fcport->port_name);
+ return;
+ }
+ fcport->scan_needed = 1;
+ fcport->rscn_gen++;
+ }
+ break;
+ case RSCN_AREA_ADDR:
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if (fcport->flags & FCF_FCP2_DEVICE)
+ continue;
+
+ if ((ea->id.b24 & 0xffff00) == (fcport->d_id.b24 & 0xffff00)) {
+ fcport->scan_needed = 1;
+ fcport->rscn_gen++;
+ }
+ }
+ break;
+ case RSCN_DOM_ADDR:
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if (fcport->flags & FCF_FCP2_DEVICE)
+ continue;
+
+ if ((ea->id.b24 & 0xff0000) == (fcport->d_id.b24 & 0xff0000)) {
+ fcport->scan_needed = 1;
+ fcport->rscn_gen++;
+ }
+ }
+ break;
+ case RSCN_FAB_ADDR:
+ default:
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if (fcport->flags & FCF_FCP2_DEVICE)
+ continue;
+
+ fcport->scan_needed = 1;
+ fcport->rscn_gen++;
+ }
+ break;
}
spin_lock_irqsave(&vha->work_lock, flags);
@@ -1750,6 +1793,10 @@
void qla_handle_els_plogi_done(scsi_qla_host_t *vha,
struct event_arg *ea)
{
+ /* for pure Target Mode, PRLI will not be initiated */
+ if (vha->host->active_mode == MODE_TARGET)
+ return;
+
ql_dbg(ql_dbg_disc, vha, 0x2118,
"%s %d %8phC post PRLI\n",
__func__, __LINE__, ea->fcport->port_name);
@@ -1797,7 +1844,7 @@
}
}
spin_unlock_irqrestore(sp->qpair->qp_lock_ptr, flags);
- tmf->u.tmf.comp_status = CS_TIMEOUT;
+ tmf->u.tmf.comp_status = cpu_to_le16(CS_TIMEOUT);
tmf->u.tmf.data = QLA_FUNCTION_FAILED;
complete(&tmf->u.tmf.comp);
}
@@ -1929,26 +1976,58 @@
break;
}
- /*
- * Retry PRLI with other FC-4 type if failure occurred on dual
- * FCP/NVMe port
- */
- if (NVME_FCP_TARGET(ea->fcport)) {
- ql_dbg(ql_dbg_disc, vha, 0x2118,
- "%s %d %8phC post %s prli\n",
- __func__, __LINE__, ea->fcport->port_name,
- (ea->fcport->fc4_type & FS_FC4TYPE_NVME) ?
- "NVMe" : "FCP");
- if (vha->hw->fc4_type_priority == FC4_PRIORITY_NVME)
- ea->fcport->fc4_type &= ~FS_FC4TYPE_NVME;
- else
- ea->fcport->fc4_type &= ~FS_FC4TYPE_FCP;
- }
+ ql_dbg(ql_dbg_disc, vha, 0x2118,
+ "%s %d %8phC priority %s, fc4type %x\n",
+ __func__, __LINE__, ea->fcport->port_name,
+ vha->hw->fc4_type_priority == FC4_PRIORITY_FCP ?
+ "FCP" : "NVMe", ea->fcport->fc4_type);
- ea->fcport->flags &= ~FCF_ASYNC_SENT;
- ea->fcport->keep_nport_handle = 0;
- ea->fcport->logout_on_delete = 1;
- qlt_schedule_sess_for_deletion(ea->fcport);
+ if (N2N_TOPO(vha->hw)) {
+ if (vha->hw->fc4_type_priority == FC4_PRIORITY_NVME) {
+ ea->fcport->fc4_type &= ~FS_FC4TYPE_NVME;
+ ea->fcport->fc4_type |= FS_FC4TYPE_FCP;
+ } else {
+ ea->fcport->fc4_type &= ~FS_FC4TYPE_FCP;
+ ea->fcport->fc4_type |= FS_FC4TYPE_NVME;
+ }
+
+ if (ea->fcport->n2n_link_reset_cnt < 3) {
+ ea->fcport->n2n_link_reset_cnt++;
+ vha->relogin_jif = jiffies + 2 * HZ;
+ /*
+ * PRLI failed. Reset link to kick start
+ * state machine
+ */
+ set_bit(N2N_LINK_RESET, &vha->dpc_flags);
+ } else {
+ ql_log(ql_log_warn, vha, 0x2119,
+ "%s %d %8phC Unable to reconnect\n",
+ __func__, __LINE__,
+ ea->fcport->port_name);
+ }
+ } else {
+ /*
+ * switch connect. login failed. Take connection down
+ * and allow relogin to retrigger
+ */
+ if (NVME_FCP_TARGET(ea->fcport)) {
+ ql_dbg(ql_dbg_disc, vha, 0x2118,
+ "%s %d %8phC post %s prli\n",
+ __func__, __LINE__,
+ ea->fcport->port_name,
+ (ea->fcport->fc4_type & FS_FC4TYPE_NVME)
+ ? "NVMe" : "FCP");
+ if (vha->hw->fc4_type_priority == FC4_PRIORITY_NVME)
+ ea->fcport->fc4_type &= ~FS_FC4TYPE_NVME;
+ else
+ ea->fcport->fc4_type &= ~FS_FC4TYPE_FCP;
+ }
+
+ ea->fcport->flags &= ~FCF_ASYNC_SENT;
+ ea->fcport->keep_nport_handle = 0;
+ ea->fcport->logout_on_delete = 1;
+ qlt_schedule_sess_for_deletion(ea->fcport);
+ }
break;
}
}
@@ -2040,7 +2119,7 @@
if (ea->data[1] & QLA_LOGIO_LOGIN_RETRIED)
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
else
- qla2x00_mark_device_lost(vha, ea->fcport, 1, 0);
+ qla2x00_mark_device_lost(vha, ea->fcport, 1);
break;
case MBS_LOOP_ID_USED:
/* data[1] = IO PARAM 1 = nport ID */
@@ -2095,16 +2174,6 @@
return;
}
-void
-qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
- uint16_t *data)
-{
- qlt_logo_completion_handler(fcport, data[0]);
- fcport->login_gen++;
- fcport->flags &= ~FCF_ASYNC_ACTIVE;
- return;
-}
-
/****************************************************************************/
/* QLogic ISP2x00 Hardware Support Functions. */
/****************************************************************************/
@@ -2235,10 +2304,10 @@
/* Check for secure flash support */
if (IS_QLA28XX(ha)) {
- if (RD_REG_DWORD(®->mailbox12) & BIT_0) {
- ql_log(ql_log_info, vha, 0xffff, "Adapter is Secure\n");
+ if (rd_reg_word(®->mailbox12) & BIT_0)
ha->flags.secure_adapter = 1;
- }
+ ql_log(ql_log_info, vha, 0xffff, "Secure Adapter: %s\n",
+ (ha->flags.secure_adapter) ? "Yes" : "No");
}
@@ -2264,8 +2333,18 @@
ql_dbg(ql_dbg_init, vha, 0x0061,
"Configure NVRAM parameters...\n");
+ /* Let priority default to FCP, can be overridden by nvram_config */
+ ha->fc4_type_priority = FC4_PRIORITY_FCP;
+
ha->isp_ops->nvram_config(vha);
+ if (ha->fc4_type_priority != FC4_PRIORITY_FCP &&
+ ha->fc4_type_priority != FC4_PRIORITY_NVME)
+ ha->fc4_type_priority = FC4_PRIORITY_FCP;
+
+ ql_log(ql_log_info, vha, 0xffff, "FC4 priority set to %s\n",
+ ha->fc4_type_priority == FC4_PRIORITY_FCP ? "FCP" : "NVMe");
+
if (ha->flags.disable_serdes) {
/* Mask HBA via NVRAM settings? */
ql_log(ql_log_info, vha, 0x0077,
@@ -2276,6 +2355,12 @@
ql_dbg(ql_dbg_init, vha, 0x0078,
"Verifying loaded RISC code...\n");
+ /* If smartsan enabled then require fdmi and rdp enabled */
+ if (ql2xsmartsan) {
+ ql2xfdmienable = 1;
+ ql2xrdpenable = 1;
+ }
+
if (qla2x00_isp_firmware(vha) != QLA_SUCCESS) {
rval = ha->isp_ops->chip_diag(vha);
if (rval)
@@ -2357,7 +2442,7 @@
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
- ha->pci_attr = RD_REG_WORD(®->ctrl_status);
+ ha->pci_attr = rd_reg_word(®->ctrl_status);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_SUCCESS;
@@ -2399,17 +2484,17 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
/* Pause RISC. */
- WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC);
+ wrt_reg_word(®->hccr, HCCR_PAUSE_RISC);
for (cnt = 0; cnt < 30000; cnt++) {
- if ((RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) != 0)
+ if ((rd_reg_word(®->hccr) & HCCR_RISC_PAUSE) != 0)
break;
udelay(10);
}
/* Select FPM registers. */
- WRT_REG_WORD(®->ctrl_status, 0x20);
- RD_REG_WORD(®->ctrl_status);
+ wrt_reg_word(®->ctrl_status, 0x20);
+ rd_reg_word(®->ctrl_status);
/* Get the fb rev level */
ha->fb_rev = RD_FB_CMD_REG(ha, reg);
@@ -2418,13 +2503,13 @@
pci_clear_mwi(ha->pdev);
/* Deselect FPM registers. */
- WRT_REG_WORD(®->ctrl_status, 0x0);
- RD_REG_WORD(®->ctrl_status);
+ wrt_reg_word(®->ctrl_status, 0x0);
+ rd_reg_word(®->ctrl_status);
/* Release RISC module. */
- WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC);
+ wrt_reg_word(®->hccr, HCCR_RELEASE_RISC);
for (cnt = 0; cnt < 30000; cnt++) {
- if ((RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) == 0)
+ if ((rd_reg_word(®->hccr) & HCCR_RISC_PAUSE) == 0)
break;
udelay(10);
@@ -2439,7 +2524,7 @@
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
- ha->pci_attr = RD_REG_WORD(®->ctrl_status);
+ ha->pci_attr = rd_reg_word(®->ctrl_status);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_SUCCESS;
@@ -2483,7 +2568,7 @@
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
- ha->pci_attr = RD_REG_DWORD(®->ctrl_status);
+ ha->pci_attr = rd_reg_dword(®->ctrl_status);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_SUCCESS;
@@ -2587,36 +2672,36 @@
if (!IS_QLA2100(ha)) {
/* Pause RISC. */
- WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC);
+ wrt_reg_word(®->hccr, HCCR_PAUSE_RISC);
if (IS_QLA2200(ha) || IS_QLA2300(ha)) {
for (cnt = 0; cnt < 30000; cnt++) {
- if ((RD_REG_WORD(®->hccr) &
+ if ((rd_reg_word(®->hccr) &
HCCR_RISC_PAUSE) != 0)
break;
udelay(100);
}
} else {
- RD_REG_WORD(®->hccr); /* PCI Posting. */
+ rd_reg_word(®->hccr); /* PCI Posting. */
udelay(10);
}
/* Select FPM registers. */
- WRT_REG_WORD(®->ctrl_status, 0x20);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->ctrl_status, 0x20);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
/* FPM Soft Reset. */
- WRT_REG_WORD(®->fpm_diag_config, 0x100);
- RD_REG_WORD(®->fpm_diag_config); /* PCI Posting. */
+ wrt_reg_word(®->fpm_diag_config, 0x100);
+ rd_reg_word(®->fpm_diag_config); /* PCI Posting. */
/* Toggle Fpm Reset. */
if (!IS_QLA2200(ha)) {
- WRT_REG_WORD(®->fpm_diag_config, 0x0);
- RD_REG_WORD(®->fpm_diag_config); /* PCI Posting. */
+ wrt_reg_word(®->fpm_diag_config, 0x0);
+ rd_reg_word(®->fpm_diag_config); /* PCI Posting. */
}
/* Select frame buffer registers. */
- WRT_REG_WORD(®->ctrl_status, 0x10);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->ctrl_status, 0x10);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
/* Reset frame buffer FIFOs. */
if (IS_QLA2200(ha)) {
@@ -2634,23 +2719,23 @@
}
/* Select RISC module registers. */
- WRT_REG_WORD(®->ctrl_status, 0);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->ctrl_status, 0);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
/* Reset RISC processor. */
- WRT_REG_WORD(®->hccr, HCCR_RESET_RISC);
- RD_REG_WORD(®->hccr); /* PCI Posting. */
+ wrt_reg_word(®->hccr, HCCR_RESET_RISC);
+ rd_reg_word(®->hccr); /* PCI Posting. */
/* Release RISC processor. */
- WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC);
- RD_REG_WORD(®->hccr); /* PCI Posting. */
+ wrt_reg_word(®->hccr, HCCR_RELEASE_RISC);
+ rd_reg_word(®->hccr); /* PCI Posting. */
}
- WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT);
- WRT_REG_WORD(®->hccr, HCCR_CLR_HOST_INT);
+ wrt_reg_word(®->hccr, HCCR_CLR_RISC_INT);
+ wrt_reg_word(®->hccr, HCCR_CLR_HOST_INT);
/* Reset ISP chip. */
- WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET);
+ wrt_reg_word(®->ctrl_status, CSR_ISP_SOFT_RESET);
/* Wait for RISC to recover from reset. */
if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
@@ -2661,7 +2746,7 @@
*/
udelay(20);
for (cnt = 30000; cnt; cnt--) {
- if ((RD_REG_WORD(®->ctrl_status) &
+ if ((rd_reg_word(®->ctrl_status) &
CSR_ISP_SOFT_RESET) == 0)
break;
udelay(100);
@@ -2670,13 +2755,13 @@
udelay(10);
/* Reset RISC processor. */
- WRT_REG_WORD(®->hccr, HCCR_RESET_RISC);
+ wrt_reg_word(®->hccr, HCCR_RESET_RISC);
- WRT_REG_WORD(®->semaphore, 0);
+ wrt_reg_word(®->semaphore, 0);
/* Release RISC processor. */
- WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC);
- RD_REG_WORD(®->hccr); /* PCI Posting. */
+ wrt_reg_word(®->hccr, HCCR_RELEASE_RISC);
+ rd_reg_word(®->hccr); /* PCI Posting. */
if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
for (cnt = 0; cnt < 30000; cnt++) {
@@ -2694,8 +2779,8 @@
/* Disable RISC pause on FPM parity error. */
if (!IS_QLA2100(ha)) {
- WRT_REG_WORD(®->hccr, HCCR_DISABLE_PARITY_PAUSE);
- RD_REG_WORD(®->hccr); /* PCI Posting. */
+ wrt_reg_word(®->hccr, HCCR_DISABLE_PARITY_PAUSE);
+ rd_reg_word(®->hccr); /* PCI Posting. */
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -2740,32 +2825,32 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
/* Reset RISC. */
- WRT_REG_DWORD(®->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
+ wrt_reg_dword(®->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
for (cnt = 0; cnt < 30000; cnt++) {
- if ((RD_REG_DWORD(®->ctrl_status) & CSRX_DMA_ACTIVE) == 0)
+ if ((rd_reg_dword(®->ctrl_status) & CSRX_DMA_ACTIVE) == 0)
break;
udelay(10);
}
- if (!(RD_REG_DWORD(®->ctrl_status) & CSRX_DMA_ACTIVE))
+ if (!(rd_reg_dword(®->ctrl_status) & CSRX_DMA_ACTIVE))
set_bit(DMA_SHUTDOWN_CMPL, &ha->fw_dump_cap_flags);
ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x017e,
"HCCR: 0x%x, Control Status %x, DMA active status:0x%x\n",
- RD_REG_DWORD(®->hccr),
- RD_REG_DWORD(®->ctrl_status),
- (RD_REG_DWORD(®->ctrl_status) & CSRX_DMA_ACTIVE));
+ rd_reg_dword(®->hccr),
+ rd_reg_dword(®->ctrl_status),
+ (rd_reg_dword(®->ctrl_status) & CSRX_DMA_ACTIVE));
- WRT_REG_DWORD(®->ctrl_status,
+ wrt_reg_dword(®->ctrl_status,
CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
udelay(100);
/* Wait for firmware to complete NVRAM accesses. */
- RD_REG_WORD(®->mailbox0);
- for (cnt = 10000; RD_REG_WORD(®->mailbox0) != 0 &&
+ rd_reg_word(®->mailbox0);
+ for (cnt = 10000; rd_reg_word(®->mailbox0) != 0 &&
rval == QLA_SUCCESS; cnt--) {
barrier();
if (cnt)
@@ -2779,26 +2864,26 @@
ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x017f,
"HCCR: 0x%x, MailBox0 Status 0x%x\n",
- RD_REG_DWORD(®->hccr),
- RD_REG_DWORD(®->mailbox0));
+ rd_reg_dword(®->hccr),
+ rd_reg_word(®->mailbox0));
/* Wait for soft-reset to complete. */
- RD_REG_DWORD(®->ctrl_status);
+ rd_reg_dword(®->ctrl_status);
for (cnt = 0; cnt < 60; cnt++) {
barrier();
- if ((RD_REG_DWORD(®->ctrl_status) &
+ if ((rd_reg_dword(®->ctrl_status) &
CSRX_ISP_SOFT_RESET) == 0)
break;
udelay(5);
}
- if (!(RD_REG_DWORD(®->ctrl_status) & CSRX_ISP_SOFT_RESET))
+ if (!(rd_reg_dword(®->ctrl_status) & CSRX_ISP_SOFT_RESET))
set_bit(ISP_SOFT_RESET_CMPL, &ha->fw_dump_cap_flags);
ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x015d,
"HCCR: 0x%x, Soft Reset status: 0x%x\n",
- RD_REG_DWORD(®->hccr),
- RD_REG_DWORD(®->ctrl_status));
+ rd_reg_dword(®->hccr),
+ rd_reg_dword(®->ctrl_status));
/* If required, do an MPI FW reset now */
if (test_and_clear_bit(MPI_RESET_NEEDED, &vha->dpc_flags)) {
@@ -2817,17 +2902,17 @@
}
}
- WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET);
- RD_REG_DWORD(®->hccr);
+ wrt_reg_dword(®->hccr, HCCRX_SET_RISC_RESET);
+ rd_reg_dword(®->hccr);
- WRT_REG_DWORD(®->hccr, HCCRX_REL_RISC_PAUSE);
- RD_REG_DWORD(®->hccr);
+ wrt_reg_dword(®->hccr, HCCRX_REL_RISC_PAUSE);
+ rd_reg_dword(®->hccr);
- WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_RESET);
- RD_REG_DWORD(®->hccr);
+ wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_RESET);
+ rd_reg_dword(®->hccr);
- RD_REG_WORD(®->mailbox0);
- for (cnt = 60; RD_REG_WORD(®->mailbox0) != 0 &&
+ rd_reg_word(®->mailbox0);
+ for (cnt = 60; rd_reg_word(®->mailbox0) != 0 &&
rval == QLA_SUCCESS; cnt--) {
barrier();
if (cnt)
@@ -2840,8 +2925,8 @@
ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x015e,
"Host Risc 0x%x, mailbox0 0x%x\n",
- RD_REG_DWORD(®->hccr),
- RD_REG_WORD(®->mailbox0));
+ rd_reg_dword(®->hccr),
+ rd_reg_word(®->mailbox0));
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -2860,9 +2945,8 @@
{
struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;
- WRT_REG_DWORD(®->iobase_addr, RISC_REGISTER_BASE_OFFSET);
- *data = RD_REG_DWORD(®->iobase_window + RISC_REGISTER_WINDOW_OFFET);
-
+ wrt_reg_dword(®->iobase_addr, RISC_REGISTER_BASE_OFFSET);
+ *data = rd_reg_dword(®->iobase_window + RISC_REGISTER_WINDOW_OFFSET);
}
static void
@@ -2870,8 +2954,8 @@
{
struct device_reg_24xx __iomem *reg = &vha->hw->iobase->isp24;
- WRT_REG_DWORD(®->iobase_addr, RISC_REGISTER_BASE_OFFSET);
- WRT_REG_DWORD(®->iobase_window + RISC_REGISTER_WINDOW_OFFET, data);
+ wrt_reg_dword(®->iobase_addr, RISC_REGISTER_BASE_OFFSET);
+ wrt_reg_dword(®->iobase_window + RISC_REGISTER_WINDOW_OFFSET, data);
}
static void
@@ -2887,7 +2971,7 @@
vha->hw->pdev->subsystem_device != 0x0240)
return;
- WRT_REG_DWORD(&vha->hw->iobase->isp24.hccr, HCCRX_SET_RISC_PAUSE);
+ wrt_reg_dword(&vha->hw->iobase->isp24.hccr, HCCRX_SET_RISC_PAUSE);
udelay(100);
attempt:
@@ -2989,7 +3073,7 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
/* Reset ISP chip. */
- WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET);
+ wrt_reg_word(®->ctrl_status, CSR_ISP_SOFT_RESET);
/*
* We need to have a delay here since the card will not respond while
@@ -2999,7 +3083,7 @@
data = qla2x00_debounce_register(®->ctrl_status);
for (cnt = 6000000 ; cnt && (data & CSR_ISP_SOFT_RESET); cnt--) {
udelay(5);
- data = RD_REG_WORD(®->ctrl_status);
+ data = rd_reg_word(®->ctrl_status);
barrier();
}
@@ -3010,8 +3094,8 @@
"Reset register cleared by chip reset.\n");
/* Reset RISC processor. */
- WRT_REG_WORD(®->hccr, HCCR_RESET_RISC);
- WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC);
+ wrt_reg_word(®->hccr, HCCR_RESET_RISC);
+ wrt_reg_word(®->hccr, HCCR_RELEASE_RISC);
/* Workaround for QLA2312 PCI parity error */
if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
@@ -3289,6 +3373,8 @@
j, fwdt->dump_size);
dump_size += fwdt->dump_size;
}
+ /* Add space for spare MPI fw dump. */
+ dump_size += ha->fwdt[1].dump_size;
} else {
req_q_size = req->length * sizeof(request_t);
rsp_q_size = rsp->length * sizeof(response_t);
@@ -3339,6 +3425,8 @@
dump_size / 1024);
if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ ha->mpi_fw_dump = (char *)fw_dump +
+ ha->fwdt[1].dump_size;
mutex_unlock(&ha->optrom_mutex);
return;
}
@@ -3550,53 +3638,100 @@
}
-/*
- * Return Code:
- * QLA_SUCCESS: no action
- * QLA_INTERFACE_ERROR: SFP is not there.
- * QLA_FUNCTION_FAILED: detected New SFP
+/**
+ * qla24xx_detect_sfp()
+ *
+ * @vha: adapter state pointer.
+ *
+ * @return
+ * 0 -- Configure firmware to use short-range settings -- normal
+ * buffer-to-buffer credits.
+ *
+ * 1 -- Configure firmware to use long-range settings -- extra
+ * buffer-to-buffer credits should be allocated with
+ * ha->lr_distance containing distance settings from NVRAM or SFP
+ * (if supported).
*/
int
qla24xx_detect_sfp(scsi_qla_host_t *vha)
{
- int rc = QLA_SUCCESS;
+ int rc, used_nvram;
struct sff_8247_a0 *a;
struct qla_hw_data *ha = vha->hw;
+ struct nvram_81xx *nv = ha->nvram;
+#define LR_DISTANCE_UNKNOWN 2
+ static const char * const types[] = { "Short", "Long" };
+ static const char * const lengths[] = { "(10km)", "(5km)", "" };
+ u8 ll = 0;
- if (!AUTO_DETECT_SFP_SUPPORT(vha))
+ /* Seed with NVRAM settings. */
+ used_nvram = 0;
+ ha->flags.lr_detected = 0;
+ if (IS_BPM_RANGE_CAPABLE(ha) &&
+ (nv->enhanced_features & NEF_LR_DIST_ENABLE)) {
+ used_nvram = 1;
+ ha->flags.lr_detected = 1;
+ ha->lr_distance =
+ (nv->enhanced_features >> LR_DIST_NV_POS)
+ & LR_DIST_NV_MASK;
+ }
+
+ if (!IS_BPM_ENABLED(vha))
goto out;
-
+ /* Determine SR/LR capabilities of SFP/Transceiver. */
rc = qla2x00_read_sfp_dev(vha, NULL, 0);
if (rc)
goto out;
+ used_nvram = 0;
a = (struct sff_8247_a0 *)vha->hw->sfp_data;
qla2xxx_print_sfp_info(vha);
- if (a->fc_ll_cc7 & FC_LL_VL || a->fc_ll_cc7 & FC_LL_L) {
- /* long range */
- ha->flags.detected_lr_sfp = 1;
+ ha->flags.lr_detected = 0;
+ ll = a->fc_ll_cc7;
+ if (ll & FC_LL_VL || ll & FC_LL_L) {
+ /* Long range, track length. */
+ ha->flags.lr_detected = 1;
if (a->length_km > 5 || a->length_100m > 50)
- ha->long_range_distance = LR_DISTANCE_10K;
+ ha->lr_distance = LR_DISTANCE_10K;
else
- ha->long_range_distance = LR_DISTANCE_5K;
-
- if (ha->flags.detected_lr_sfp != ha->flags.using_lr_setting)
- ql_dbg(ql_dbg_async, vha, 0x507b,
- "Detected Long Range SFP.\n");
- } else {
- /* short range */
- ha->flags.detected_lr_sfp = 0;
- if (ha->flags.using_lr_setting)
- ql_dbg(ql_dbg_async, vha, 0x5084,
- "Detected Short Range SFP.\n");
+ ha->lr_distance = LR_DISTANCE_5K;
}
- if (!vha->flags.init_done)
- rc = QLA_SUCCESS;
out:
- return rc;
+ ql_dbg(ql_dbg_async, vha, 0x507b,
+ "SFP detect: %s-Range SFP %s (nvr=%x ll=%x lr=%x lrd=%x).\n",
+ types[ha->flags.lr_detected],
+ ha->flags.lr_detected ? lengths[ha->lr_distance] :
+ lengths[LR_DISTANCE_UNKNOWN],
+ used_nvram, ll, ha->flags.lr_detected, ha->lr_distance);
+ return ha->flags.lr_detected;
+}
+
+void qla_init_iocb_limit(scsi_qla_host_t *vha)
+{
+ u16 i, num_qps;
+ u32 limit;
+ struct qla_hw_data *ha = vha->hw;
+
+ num_qps = ha->num_qpairs + 1;
+ limit = (ha->orig_fw_iocb_count * QLA_IOCB_PCT_LIMIT) / 100;
+
+ ha->base_qpair->fwres.iocbs_total = ha->orig_fw_iocb_count;
+ ha->base_qpair->fwres.iocbs_limit = limit;
+ ha->base_qpair->fwres.iocbs_qp_limit = limit / num_qps;
+ ha->base_qpair->fwres.iocbs_used = 0;
+ for (i = 0; i < ha->max_qpairs; i++) {
+ if (ha->queue_pair_map[i]) {
+ ha->queue_pair_map[i]->fwres.iocbs_total =
+ ha->orig_fw_iocb_count;
+ ha->queue_pair_map[i]->fwres.iocbs_limit = limit;
+ ha->queue_pair_map[i]->fwres.iocbs_qp_limit =
+ limit / num_qps;
+ ha->queue_pair_map[i]->fwres.iocbs_used = 0;
+ }
+ }
}
/**
@@ -3614,6 +3749,7 @@
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
unsigned long flags;
uint16_t fw_major_version;
+ int done_once = 0;
if (IS_P3P_TYPE(ha)) {
rval = ha->isp_ops->load_risc(vha, &srisc_address);
@@ -3627,13 +3763,14 @@
if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) {
/* Disable SRAM, Instruction RAM and GP RAM parity. */
spin_lock_irqsave(&ha->hardware_lock, flags);
- WRT_REG_WORD(®->hccr, (HCCR_ENABLE_PARITY + 0x0));
- RD_REG_WORD(®->hccr);
+ wrt_reg_word(®->hccr, (HCCR_ENABLE_PARITY + 0x0));
+ rd_reg_word(®->hccr);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
qla81xx_mpi_sync(vha);
+execute_fw_with_lr:
/* Load firmware sequences */
rval = ha->isp_ops->load_risc(vha, &srisc_address);
if (rval == QLA_SUCCESS) {
@@ -3655,11 +3792,17 @@
rval = qla2x00_execute_fw(vha, srisc_address);
/* Retrieve firmware information. */
if (rval == QLA_SUCCESS) {
- qla24xx_detect_sfp(vha);
+ /* Enable BPM support? */
+ if (!done_once++ && qla24xx_detect_sfp(vha)) {
+ ql_dbg(ql_dbg_init, vha, 0x00ca,
+ "Re-starting firmware -- BPM.\n");
+ /* Best-effort - re-init. */
+ ha->isp_ops->reset_chip(vha);
+ ha->isp_ops->chip_diag(vha);
+ goto execute_fw_with_lr;
+ }
- if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
- IS_QLA28XX(ha)) &&
- (ha->zio_mode == QLA_ZIO_MODE_6))
+ if (IS_ZIO_THRESHOLD_CAPABLE(ha))
qla27xx_set_zio_threshold(vha,
ha->last_zio_threshold);
@@ -3690,6 +3833,7 @@
MIN_MULTI_ID_FABRIC - 1;
}
qla2x00_get_resource_cnts(vha);
+ qla_init_iocb_limit(vha);
/*
* Allocate the array of outstanding commands
@@ -3714,6 +3858,10 @@
"ISP Firmware failed checksum.\n");
goto failed;
}
+
+ /* Enable PUREX PASSTHRU */
+ if (ql2xrdpenable || ha->flags.scm_supported_f)
+ qla25xx_set_els_cmds_supported(vha);
} else
goto failed;
@@ -3722,11 +3870,11 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
if (IS_QLA2300(ha))
/* SRAM parity */
- WRT_REG_WORD(®->hccr, HCCR_ENABLE_PARITY + 0x1);
+ wrt_reg_word(®->hccr, HCCR_ENABLE_PARITY + 0x1);
else
/* SRAM, Instruction RAM and GP RAM parity */
- WRT_REG_WORD(®->hccr, HCCR_ENABLE_PARITY + 0x7);
- RD_REG_WORD(®->hccr);
+ wrt_reg_word(®->hccr, HCCR_ENABLE_PARITY + 0x7);
+ rd_reg_word(®->hccr);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
@@ -3925,6 +4073,13 @@
ha->fw_options[2] &= ~BIT_8;
}
+ if (ql2xrdpenable || ha->flags.scm_supported_f)
+ ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB;
+
+ /* Enable Async 8130/8131 events -- transceiver insertion/removal */
+ if (IS_BPM_RANGE_CAPABLE(ha))
+ ha->fw_options[3] |= BIT_10;
+
ql_dbg(ql_dbg_init, vha, 0x00e8,
"%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n",
__func__, ha->fw_options[1], ha->fw_options[2],
@@ -3963,11 +4118,11 @@
put_unaligned_le64(req->dma, &ha->init_cb->request_q_address);
put_unaligned_le64(rsp->dma, &ha->init_cb->response_q_address);
- WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), 0);
- WRT_REG_WORD(ISP_REQ_Q_OUT(ha, reg), 0);
- WRT_REG_WORD(ISP_RSP_Q_IN(ha, reg), 0);
- WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), 0);
- RD_REG_WORD(ISP_RSP_Q_OUT(ha, reg)); /* PCI Posting. */
+ wrt_reg_word(ISP_REQ_Q_IN(ha, reg), 0);
+ wrt_reg_word(ISP_REQ_Q_OUT(ha, reg), 0);
+ wrt_reg_word(ISP_RSP_Q_IN(ha, reg), 0);
+ wrt_reg_word(ISP_RSP_Q_OUT(ha, reg), 0);
+ rd_reg_word(ISP_RSP_Q_OUT(ha, reg)); /* PCI Posting. */
}
void
@@ -4029,15 +4184,15 @@
}
icb->firmware_options_2 |= cpu_to_le32(BIT_23);
- WRT_REG_DWORD(®->isp25mq.req_q_in, 0);
- WRT_REG_DWORD(®->isp25mq.req_q_out, 0);
- WRT_REG_DWORD(®->isp25mq.rsp_q_in, 0);
- WRT_REG_DWORD(®->isp25mq.rsp_q_out, 0);
+ wrt_reg_dword(®->isp25mq.req_q_in, 0);
+ wrt_reg_dword(®->isp25mq.req_q_out, 0);
+ wrt_reg_dword(®->isp25mq.rsp_q_in, 0);
+ wrt_reg_dword(®->isp25mq.rsp_q_out, 0);
} else {
- WRT_REG_DWORD(®->isp24.req_q_in, 0);
- WRT_REG_DWORD(®->isp24.req_q_out, 0);
- WRT_REG_DWORD(®->isp24.rsp_q_in, 0);
- WRT_REG_DWORD(®->isp24.rsp_q_out, 0);
+ wrt_reg_dword(®->isp24.req_q_in, 0);
+ wrt_reg_dword(®->isp24.req_q_out, 0);
+ wrt_reg_dword(®->isp24.rsp_q_in, 0);
+ wrt_reg_dword(®->isp24.rsp_q_out, 0);
}
qlt_24xx_config_rings(vha);
@@ -4047,11 +4202,11 @@
ql_dbg(ql_dbg_init, vha, 0x00fd,
"Speed set by user : %s Gbps \n",
qla2x00_get_link_speed_str(ha, ha->set_data_rate));
- icb->firmware_options_3 = (ha->set_data_rate << 13);
+ icb->firmware_options_3 = cpu_to_le32(ha->set_data_rate << 13);
}
/* PCI posting */
- RD_REG_DWORD(&ioreg->hccr);
+ rd_reg_word(&ioreg->hccr);
}
/**
@@ -4082,7 +4237,7 @@
req = ha->req_q_map[que];
if (!req || !test_bit(que, ha->req_qid_map))
continue;
- req->out_ptr = (void *)(req->ring + req->length);
+ req->out_ptr = (uint16_t *)(req->ring + req->length);
*req->out_ptr = 0;
for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++)
req->outstanding_cmds[cnt] = NULL;
@@ -4099,7 +4254,7 @@
rsp = ha->rsp_q_map[que];
if (!rsp || !test_bit(que, ha->rsp_qid_map))
continue;
- rsp->in_ptr = (void *)(rsp->ring + rsp->length);
+ rsp->in_ptr = (uint16_t *)(rsp->ring + rsp->length);
*rsp->in_ptr = 0;
/* Initialize response queue entries */
if (IS_QLAFX00(ha))
@@ -4138,12 +4293,14 @@
mid_init_cb->init_cb.execution_throttle =
cpu_to_le16(ha->cur_fw_xcb_count);
ha->flags.dport_enabled =
- (mid_init_cb->init_cb.firmware_options_1 & BIT_7) != 0;
+ (le32_to_cpu(mid_init_cb->init_cb.firmware_options_1) &
+ BIT_7) != 0;
ql_dbg(ql_dbg_init, vha, 0x0191, "DPORT Support: %s.\n",
(ha->flags.dport_enabled) ? "enabled" : "disabled");
/* FA-WWPN Status */
ha->flags.fawwpn_enabled =
- (mid_init_cb->init_cb.firmware_options_1 & BIT_6) != 0;
+ (le32_to_cpu(mid_init_cb->init_cb.firmware_options_1) &
+ BIT_6) != 0;
ql_dbg(ql_dbg_init, vha, 0x00bc, "FA-WWPN Support: %s.\n",
(ha->flags.fawwpn_enabled) ? "enabled" : "disabled");
}
@@ -4522,7 +4679,7 @@
ha->nvram_size = sizeof(*nv);
ha->nvram_base = 0;
if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha))
- if ((RD_REG_WORD(®->ctrl_status) >> 14) == 1)
+ if ((rd_reg_word(®->ctrl_status) >> 14) == 1)
ha->nvram_base = 0x80;
/* Get NVRAM data and calculate checksum. */
@@ -4557,18 +4714,18 @@
nv->firmware_options[1] = BIT_7 | BIT_5;
nv->add_firmware_options[0] = BIT_5;
nv->add_firmware_options[1] = BIT_5 | BIT_4;
- nv->frame_payload_size = 2048;
+ nv->frame_payload_size = cpu_to_le16(2048);
nv->special_options[1] = BIT_7;
} else if (IS_QLA2200(ha)) {
nv->firmware_options[0] = BIT_2 | BIT_1;
nv->firmware_options[1] = BIT_7 | BIT_5;
nv->add_firmware_options[0] = BIT_5;
nv->add_firmware_options[1] = BIT_5 | BIT_4;
- nv->frame_payload_size = 1024;
+ nv->frame_payload_size = cpu_to_le16(1024);
} else if (IS_QLA2100(ha)) {
nv->firmware_options[0] = BIT_3 | BIT_1;
nv->firmware_options[1] = BIT_5;
- nv->frame_payload_size = 1024;
+ nv->frame_payload_size = cpu_to_le16(1024);
}
nv->max_iocb_allocation = cpu_to_le16(256);
@@ -4911,6 +5068,29 @@
kfree(fcport);
}
+static void qla_get_login_template(scsi_qla_host_t *vha)
+{
+ struct qla_hw_data *ha = vha->hw;
+ int rval;
+ u32 *bp, sz;
+ __be32 *q;
+
+ memset(ha->init_cb, 0, ha->init_cb_size);
+ sz = min_t(int, sizeof(struct fc_els_flogi), ha->init_cb_size);
+ rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma,
+ ha->init_cb, sz);
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_init, vha, 0x00d1,
+ "PLOGI ELS param read fail.\n");
+ return;
+ }
+ q = (__be32 *)&ha->plogi_els_payld.fl_csp;
+
+ bp = (uint32_t *)ha->init_cb;
+ cpu_to_be32_array(q, bp, sz / 4);
+ ha->flags.plogi_template_valid = 1;
+}
+
/*
* qla2x00_configure_loop
* Updates Fibre Channel Device Database with what is actually on loop.
@@ -4954,14 +5134,11 @@
clear_bit(RSCN_UPDATE, &vha->dpc_flags);
qla2x00_get_data_rate(vha);
+ qla_get_login_template(vha);
/* Determine what we need to do */
- if (ha->current_topology == ISP_CFG_FL &&
- (test_bit(LOCAL_LOOP_UPDATE, &flags))) {
-
- set_bit(RSCN_UPDATE, &flags);
-
- } else if (ha->current_topology == ISP_CFG_F &&
+ if ((ha->current_topology == ISP_CFG_FL ||
+ ha->current_topology == ISP_CFG_F) &&
(test_bit(LOCAL_LOOP_UPDATE, &flags))) {
set_bit(RSCN_UPDATE, &flags);
@@ -5040,6 +5217,32 @@
return (rval);
}
+static int qla2x00_configure_n2n_loop(scsi_qla_host_t *vha)
+{
+ unsigned long flags;
+ fc_port_t *fcport;
+
+ if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags))
+ set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if (fcport->n2n_flag) {
+ qla24xx_fcport_handle_login(vha, fcport);
+ return QLA_SUCCESS;
+ }
+ }
+
+ spin_lock_irqsave(&vha->work_lock, flags);
+ vha->scan.scan_retry++;
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+
+ if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
+ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ }
+ return QLA_FUNCTION_FAILED;
+}
+
/*
* qla2x00_configure_local_loop
* Updates Fibre Channel Device Database with local loop devices.
@@ -5057,7 +5260,6 @@
int found_devs;
int found;
fc_port_t *fcport, *new_fcport;
-
uint16_t index;
uint16_t entries;
struct gid_list_info *gid;
@@ -5067,47 +5269,8 @@
unsigned long flags;
/* Inititae N2N login. */
- if (N2N_TOPO(ha)) {
- if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) {
- /* borrowing */
- u32 *bp, i, sz;
-
- memset(ha->init_cb, 0, ha->init_cb_size);
- sz = min_t(int, sizeof(struct els_plogi_payload),
- ha->init_cb_size);
- rval = qla24xx_get_port_login_templ(vha,
- ha->init_cb_dma, (void *)ha->init_cb, sz);
- if (rval == QLA_SUCCESS) {
- bp = (uint32_t *)ha->init_cb;
- for (i = 0; i < sz/4 ; i++, bp++)
- *bp = cpu_to_be32(*bp);
-
- memcpy(&ha->plogi_els_payld.data,
- (void *)ha->init_cb,
- sizeof(ha->plogi_els_payld.data));
- } else {
- ql_dbg(ql_dbg_init, vha, 0x00d1,
- "PLOGI ELS param read fail.\n");
- goto skip_login;
- }
- }
-
- list_for_each_entry(fcport, &vha->vp_fcports, list) {
- if (fcport->n2n_flag) {
- qla24xx_fcport_handle_login(vha, fcport);
- return QLA_SUCCESS;
- }
- }
-skip_login:
- spin_lock_irqsave(&vha->work_lock, flags);
- vha->scan.scan_retry++;
- spin_unlock_irqrestore(&vha->work_lock, flags);
-
- if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
- set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
- set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
- }
- }
+ if (N2N_TOPO(ha))
+ return qla2x00_configure_n2n_loop(vha);
found_devs = 0;
new_fcport = NULL;
@@ -5118,7 +5281,7 @@
rval = qla2x00_get_id_list(vha, ha->gid_list, ha->gid_list_dma,
&entries);
if (rval != QLA_SUCCESS)
- goto cleanup_allocation;
+ goto err;
ql_dbg(ql_dbg_disc, vha, 0x2011,
"Entries in ID list (%d).\n", entries);
@@ -5148,7 +5311,7 @@
ql_log(ql_log_warn, vha, 0x2012,
"Memory allocation failed for fcport.\n");
rval = QLA_MEMORY_ALLOC_FAILED;
- goto cleanup_allocation;
+ goto err;
}
new_fcport->flags &= ~FCF_FABRIC_DEVICE;
@@ -5238,7 +5401,7 @@
ql_log(ql_log_warn, vha, 0xd031,
"Failed to allocate memory for fcport.\n");
rval = QLA_MEMORY_ALLOC_FAILED;
- goto cleanup_allocation;
+ goto err;
}
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
new_fcport->flags &= ~FCF_FABRIC_DEVICE;
@@ -5261,7 +5424,7 @@
qla_ini_mode_enabled(vha)) &&
atomic_read(&fcport->state) == FCS_ONLINE) {
qla2x00_mark_device_lost(vha, fcport,
- ql2xplogiabsentdevice, 0);
+ ql2xplogiabsentdevice);
if (fcport->loop_id != FC_NO_LOOP_ID &&
(fcport->flags & FCF_FCP2_DEVICE) == 0 &&
fcport->port_type != FCT_INITIATOR &&
@@ -5281,15 +5444,14 @@
qla24xx_fcport_handle_login(vha, fcport);
}
-cleanup_allocation:
- kfree(new_fcport);
+ qla2x00_free_fcport(new_fcport);
- if (rval != QLA_SUCCESS) {
- ql_dbg(ql_dbg_disc, vha, 0x2098,
- "Configure local loop error exit: rval=%x.\n", rval);
- }
+ return rval;
- return (rval);
+err:
+ ql_dbg(ql_dbg_disc, vha, 0x2098,
+ "Configure local loop error exit: rval=%x.\n", rval);
+ return rval;
}
static void
@@ -5420,7 +5582,10 @@
fcport->login_retry = vha->hw->login_retry_count;
fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
fcport->deleted = 0;
- fcport->logout_on_delete = 1;
+ if (vha->hw->current_topology == ISP_CFG_NL)
+ fcport->logout_on_delete = 0;
+ else
+ fcport->logout_on_delete = 1;
fcport->n2n_chip_reset = fcport->n2n_link_reset_cnt = 0;
switch (vha->hw->current_topology) {
@@ -5434,6 +5599,8 @@
qla2x00_iidma_fcport(vha, fcport);
+ qla2x00_dfs_create_rport(vha, fcport);
+
if (NVME_TARGET(vha->hw, fcport)) {
qla_nvme_register_remote(vha, fcport);
qla2x00_set_fcport_disc_state(fcport, DSC_LOGIN_COMPLETE);
@@ -5549,24 +5716,22 @@
}
vha->device_flags |= SWITCH_FOUND;
+ rval = qla2x00_get_port_name(vha, loop_id, vha->fabric_port_name, 0);
+ if (rval != QLA_SUCCESS)
+ ql_dbg(ql_dbg_disc, vha, 0x20ff,
+ "Failed to get Fabric Port Name\n");
if (qla_tgt_mode_enabled(vha) || qla_dual_mode_enabled(vha)) {
rval = qla2x00_send_change_request(vha, 0x3, 0);
if (rval != QLA_SUCCESS)
ql_log(ql_log_warn, vha, 0x121,
- "Failed to enable receiving of RSCN requests: 0x%x.\n",
- rval);
+ "Failed to enable receiving of RSCN requests: 0x%x.\n",
+ rval);
}
-
do {
qla2x00_mgmt_svr_login(vha);
- /* FDMI support. */
- if (ql2xfdmienable &&
- test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags))
- qla2x00_fdmi_register(vha);
-
/* Ensure we are logged into the SNS. */
loop_id = NPH_SNS_LID(ha);
rval = ha->isp_ops->fabric_login(vha, loop_id, 0xff, 0xff,
@@ -5578,6 +5743,12 @@
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
return rval;
}
+
+ /* FDMI support. */
+ if (ql2xfdmienable &&
+ test_and_clear_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags))
+ qla2x00_fdmi_register(vha);
+
if (test_and_clear_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags)) {
if (qla2x00_rft_id(vha)) {
/* EMPTY */
@@ -5820,7 +5991,7 @@
/* Bypass ports whose FCP-4 type is not FCP_SCSI */
if (ql2xgffidenable &&
(!(new_fcport->fc4_type & FS_FC4TYPE_FCP) &&
- new_fcport->fc4_type != FC4_TYPE_UNKNOWN))
+ new_fcport->fc4_type != 0))
continue;
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
@@ -5888,7 +6059,7 @@
break;
}
- if (NVME_TARGET(vha->hw, fcport)) {
+ if (found && NVME_TARGET(vha->hw, fcport)) {
if (fcport->disc_state == DSC_DELETE_PEND) {
qla2x00_set_fcport_disc_state(fcport, DSC_GNL);
vha->fcport_count--;
@@ -5936,7 +6107,7 @@
qla_ini_mode_enabled(vha)) &&
atomic_read(&fcport->state) == FCS_ONLINE) {
qla2x00_mark_device_lost(vha, fcport,
- ql2xplogiabsentdevice, 0);
+ ql2xplogiabsentdevice);
if (fcport->loop_id != FC_NO_LOOP_ID &&
(fcport->flags & FCF_FCP2_DEVICE) == 0 &&
fcport->port_type != FCT_INITIATOR &&
@@ -6102,7 +6273,7 @@
ha->isp_ops->fabric_logout(vha, fcport->loop_id,
fcport->d_id.b.domain, fcport->d_id.b.area,
fcport->d_id.b.al_pa);
- qla2x00_mark_device_lost(vha, fcport, 1, 0);
+ qla2x00_mark_device_lost(vha, fcport, 1);
rval = 1;
break;
@@ -6616,9 +6787,9 @@
atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
atomic_set(&vha->loop_state, LOOP_DOWN);
- qla2x00_mark_all_devices_lost(vha, 0);
+ qla2x00_mark_all_devices_lost(vha);
list_for_each_entry(vp, &ha->vp_list, list)
- qla2x00_mark_all_devices_lost(vp, 0);
+ qla2x00_mark_all_devices_lost(vp);
} else {
if (!atomic_read(&vha->loop_down_timer))
atomic_set(&vha->loop_down_timer,
@@ -6664,7 +6835,7 @@
ha->flags.n2n_ae = 0;
ha->flags.lip_ae = 0;
ha->current_topology = 0;
- ha->flags.fw_started = 0;
+ QLA_FW_STOPPED(ha);
ha->flags.fw_init_done = 0;
ha->chip_reset++;
ha->base_qpair->chip_reset = ha->chip_reset;
@@ -6694,14 +6865,14 @@
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
atomic_set(&vha->loop_state, LOOP_DOWN);
- qla2x00_mark_all_devices_lost(vha, 0);
+ qla2x00_mark_all_devices_lost(vha);
spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry(vp, &ha->vp_list, list) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);
- qla2x00_mark_all_devices_lost(vp, 0);
+ qla2x00_mark_all_devices_lost(vp);
spin_lock_irqsave(&ha->vport_slock, flags);
atomic_dec(&vp->vref_count);
@@ -6803,7 +6974,8 @@
return 0;
break;
case QLA2XXX_INI_MODE_DUAL:
- if (!qla_dual_mode_enabled(vha))
+ if (!qla_dual_mode_enabled(vha) &&
+ !qla_ini_mode_enabled(vha))
return 0;
break;
case QLA2XXX_INI_MODE_ENABLED:
@@ -6940,36 +7112,41 @@
static int
qla2x00_restart_isp(scsi_qla_host_t *vha)
{
- int status = 0;
+ int status;
struct qla_hw_data *ha = vha->hw;
/* If firmware needs to be loaded */
if (qla2x00_isp_firmware(vha)) {
vha->flags.online = 0;
status = ha->isp_ops->chip_diag(vha);
- if (!status)
- status = qla2x00_setup_chip(vha);
+ if (status)
+ return status;
+ status = qla2x00_setup_chip(vha);
+ if (status)
+ return status;
}
- if (!status && !(status = qla2x00_init_rings(vha))) {
- clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
- ha->flags.chip_reset_done = 1;
+ status = qla2x00_init_rings(vha);
+ if (status)
+ return status;
- /* Initialize the queues in use */
- qla25xx_init_queues(ha);
+ clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
+ ha->flags.chip_reset_done = 1;
- status = qla2x00_fw_ready(vha);
- if (!status) {
- /* Issue a marker after FW becomes ready. */
- qla2x00_marker(vha, ha->base_qpair, 0, 0, MK_SYNC_ALL);
- set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
- }
+ /* Initialize the queues in use */
+ qla25xx_init_queues(ha);
+ status = qla2x00_fw_ready(vha);
+ if (status) {
/* if no cable then assume it's good */
- if ((vha->device_flags & DFLG_NO_CABLE))
- status = 0;
+ return vha->device_flags & DFLG_NO_CABLE ? 0 : status;
}
- return (status);
+
+ /* Issue a marker after FW becomes ready. */
+ qla2x00_marker(vha, ha->base_qpair, 0, 0, MK_SYNC_ALL);
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+
+ return 0;
}
static int
@@ -7033,10 +7210,10 @@
ha->isp_ops->disable_intrs(ha);
spin_lock_irqsave(&ha->hardware_lock, flags);
- WRT_REG_WORD(®->hccr, HCCR_RESET_RISC);
- RD_REG_WORD(®->hccr); /* PCI Posting. */
- WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC);
- RD_REG_WORD(®->hccr); /* PCI Posting. */
+ wrt_reg_word(®->hccr, HCCR_RESET_RISC);
+ rd_reg_word(®->hccr); /* PCI Posting. */
+ wrt_reg_word(®->hccr, HCCR_RELEASE_RISC);
+ rd_reg_word(®->hccr); /* PCI Posting. */
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_SUCCESS;
@@ -7048,25 +7225,24 @@
unsigned long flags = 0;
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
- int rval = QLA_SUCCESS;
if (IS_P3P_TYPE(ha))
- return rval;
+ return QLA_SUCCESS;
vha->flags.online = 0;
ha->isp_ops->disable_intrs(ha);
spin_lock_irqsave(&ha->hardware_lock, flags);
- WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET);
- RD_REG_DWORD(®->hccr);
- WRT_REG_DWORD(®->hccr, HCCRX_REL_RISC_PAUSE);
- RD_REG_DWORD(®->hccr);
+ wrt_reg_dword(®->hccr, HCCRX_SET_RISC_RESET);
+ rd_reg_dword(®->hccr);
+ wrt_reg_dword(®->hccr, HCCRX_REL_RISC_PAUSE);
+ rd_reg_dword(®->hccr);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (IS_NOPOLLING_TYPE(ha))
ha->isp_ops->enable_intrs(ha);
- return rval;
+ return QLA_SUCCESS;
}
/* On sparc systems, obtain port and node WWN from firmware
@@ -7098,7 +7274,7 @@
int rval;
struct init_cb_24xx *icb;
struct nvram_24xx *nv;
- uint32_t *dptr;
+ __le32 *dptr;
uint8_t *dptr1, *dptr2;
uint32_t chksum;
uint16_t cnt;
@@ -7126,7 +7302,7 @@
ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4);
/* Get NVRAM data into cache and calculate checksum. */
- dptr = (uint32_t *)nv;
+ dptr = (__force __le32 *)nv;
ha->isp_ops->read_nvram(vha, dptr, ha->nvram_base, ha->nvram_size);
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++)
chksum += le32_to_cpu(*dptr);
@@ -7154,7 +7330,7 @@
memset(nv, 0, ha->nvram_size);
nv->nvram_version = cpu_to_le16(ICB_VERSION);
nv->version = cpu_to_le16(ICB_VERSION);
- nv->frame_payload_size = 2048;
+ nv->frame_payload_size = cpu_to_le16(2048);
nv->execution_throttle = cpu_to_le16(0xFFFF);
nv->exchange_count = cpu_to_le16(0);
nv->hard_address = cpu_to_le16(124);
@@ -7322,7 +7498,7 @@
ha->login_retry_count = ql2xloginretrycount;
/* N2N: driver will initiate Login instead of FW */
- icb->firmware_options_3 |= BIT_8;
+ icb->firmware_options_3 |= cpu_to_le32(BIT_8);
/* Enable ZIO. */
if (!vha->flags.init_done) {
@@ -7390,7 +7566,7 @@
static ulong
qla27xx_image_status_checksum(struct qla27xx_image_status *image_status)
{
- uint32_t *p = (void *)image_status;
+ __le32 *p = (__force __le32 *)image_status;
uint n = sizeof(*image_status) / sizeof(*p);
uint32_t sum = 0;
@@ -7453,7 +7629,7 @@
goto check_sec_image;
}
- qla24xx_read_flash_data(vha, (void *)&pri_aux_image_status,
+ qla24xx_read_flash_data(vha, (uint32_t *)&pri_aux_image_status,
ha->flt_region_aux_img_status_pri,
sizeof(pri_aux_image_status) >> 2);
qla27xx_print_image(vha, "Primary aux image", &pri_aux_image_status);
@@ -7486,7 +7662,7 @@
goto check_valid_image;
}
- qla24xx_read_flash_data(vha, (void *)&sec_aux_image_status,
+ qla24xx_read_flash_data(vha, (uint32_t *)&sec_aux_image_status,
ha->flt_region_aux_img_status_sec,
sizeof(sec_aux_image_status) >> 2);
qla27xx_print_image(vha, "Secondary aux image", &sec_aux_image_status);
@@ -7551,7 +7727,7 @@
goto check_sec_image;
}
- if (qla24xx_read_flash_data(vha, (void *)(&pri_image_status),
+ if (qla24xx_read_flash_data(vha, (uint32_t *)&pri_image_status,
ha->flt_region_img_status_pri, sizeof(pri_image_status) >> 2) !=
QLA_SUCCESS) {
WARN_ON_ONCE(true);
@@ -7658,7 +7834,7 @@
ql_dbg(ql_dbg_init, vha, 0x008b,
"FW: Loading firmware from flash (%x).\n", faddr);
- dcode = (void *)req->ring;
+ dcode = (uint32_t *)req->ring;
qla24xx_read_flash_data(vha, dcode, faddr, 8);
if (qla24xx_risc_firmware_invalid(dcode)) {
ql_log(ql_log_fatal, vha, 0x008c,
@@ -7671,18 +7847,18 @@
return QLA_FUNCTION_FAILED;
}
- dcode = (void *)req->ring;
+ dcode = (uint32_t *)req->ring;
*srisc_addr = 0;
segments = FA_RISC_CODE_SEGMENTS;
for (j = 0; j < segments; j++) {
ql_dbg(ql_dbg_init, vha, 0x008d,
"-> Loading segment %u...\n", j);
qla24xx_read_flash_data(vha, dcode, faddr, 10);
- risc_addr = be32_to_cpu(dcode[2]);
- risc_size = be32_to_cpu(dcode[3]);
+ risc_addr = be32_to_cpu((__force __be32)dcode[2]);
+ risc_size = be32_to_cpu((__force __be32)dcode[3]);
if (!*srisc_addr) {
*srisc_addr = risc_addr;
- risc_attr = be32_to_cpu(dcode[9]);
+ risc_attr = be32_to_cpu((__force __be32)dcode[9]);
}
dlen = ha->fw_transfer_size >> 2;
@@ -7722,9 +7898,9 @@
fwdt->template = NULL;
fwdt->length = 0;
- dcode = (void *)req->ring;
+ dcode = (uint32_t *)req->ring;
qla24xx_read_flash_data(vha, dcode, faddr, 7);
- risc_size = be32_to_cpu(dcode[2]);
+ risc_size = be32_to_cpu((__force __be32)dcode[2]);
ql_dbg(ql_dbg_init, vha, 0x0161,
"-> fwdt%u template array at %#x (%#x dwords)\n",
j, faddr, risc_size);
@@ -7793,7 +7969,8 @@
{
int rval;
int i, fragment;
- uint16_t *wcode, *fwcode;
+ uint16_t *wcode;
+ __be16 *fwcode;
uint32_t risc_addr, risc_size, fwclen, wlen, *seg;
struct fw_blob *blob;
struct qla_hw_data *ha = vha->hw;
@@ -7813,7 +7990,7 @@
wcode = (uint16_t *)req->ring;
*srisc_addr = 0;
- fwcode = (uint16_t *)blob->fw->data;
+ fwcode = (__force __be16 *)blob->fw->data;
fwclen = 0;
/* Validate firmware image by checking version. */
@@ -7861,7 +8038,7 @@
"words 0x%x.\n", risc_addr, wlen);
for (i = 0; i < wlen; i++)
- wcode[i] = swab16(fwcode[i]);
+ wcode[i] = swab16((__force u32)fwcode[i]);
rval = qla2x00_load_ram(vha, req->dma, risc_addr,
wlen);
@@ -7898,7 +8075,7 @@
ulong i;
uint j;
struct fw_blob *blob;
- uint32_t *fwcode;
+ __be32 *fwcode;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
struct fwdt *fwdt = ha->fwdt;
@@ -7914,8 +8091,8 @@
return QLA_FUNCTION_FAILED;
}
- fwcode = (void *)blob->fw->data;
- dcode = fwcode;
+ fwcode = (__force __be32 *)blob->fw->data;
+ dcode = (__force uint32_t *)fwcode;
if (qla24xx_risc_firmware_invalid(dcode)) {
ql_log(ql_log_fatal, vha, 0x0093,
"Unable to verify integrity of firmware image (%zd).\n",
@@ -7926,7 +8103,7 @@
return QLA_FUNCTION_FAILED;
}
- dcode = (void *)req->ring;
+ dcode = (uint32_t *)req->ring;
*srisc_addr = 0;
segments = FA_RISC_CODE_SEGMENTS;
for (j = 0; j < segments; j++) {
@@ -7952,7 +8129,7 @@
dlen);
for (i = 0; i < dlen; i++)
- dcode[i] = swab32(fwcode[i]);
+ dcode[i] = swab32((__force u32)fwcode[i]);
rval = qla2x00_load_ram(vha, req->dma, risc_addr, dlen);
if (rval) {
@@ -8006,7 +8183,7 @@
dcode = fwdt->template;
for (i = 0; i < risc_size; i++)
- dcode[i] = fwcode[i];
+ dcode[i] = (__force u32)fwcode[i];
if (!qla27xx_fwdt_template_valid(dcode)) {
ql_log(ql_log_warn, vha, 0x0175,
@@ -8277,7 +8454,7 @@
int rval;
struct init_cb_81xx *icb;
struct nvram_81xx *nv;
- uint32_t *dptr;
+ __le32 *dptr;
uint8_t *dptr1, *dptr2;
uint32_t chksum;
uint16_t cnt;
@@ -8324,7 +8501,7 @@
"primary" : "secondary");
ha->isp_ops->read_optrom(vha, ha->nvram, faddr << 2, ha->nvram_size);
- dptr = (uint32_t *)nv;
+ dptr = (__force __le32 *)nv;
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++)
chksum += le32_to_cpu(*dptr);
@@ -8351,7 +8528,7 @@
memset(nv, 0, ha->nvram_size);
nv->nvram_version = cpu_to_le16(ICB_VERSION);
nv->version = cpu_to_le16(ICB_VERSION);
- nv->frame_payload_size = 2048;
+ nv->frame_payload_size = cpu_to_le16(2048);
nv->execution_throttle = cpu_to_le16(0xFFFF);
nv->exchange_count = cpu_to_le16(0);
nv->port_name[0] = 0x21;
@@ -8395,7 +8572,7 @@
}
if (IS_T10_PI_CAPABLE(ha))
- nv->frame_payload_size &= ~7;
+ nv->frame_payload_size &= cpu_to_le16(~7);
qlt_81xx_config_nvram_stage1(vha, nv);
@@ -8457,6 +8634,11 @@
icb->node_name[0] &= 0xF0;
}
+ if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) {
+ if ((nv->enhanced_features & BIT_7) == 0)
+ ha->flags.scm_supported_a = 1;
+ }
+
/* Set host adapter parameters. */
ha->flags.disable_risc_code_load = 0;
ha->flags.enable_lip_reset = 0;
@@ -8558,15 +8740,13 @@
}
/* enable RIDA Format2 */
- icb->firmware_options_3 |= BIT_0;
+ icb->firmware_options_3 |= cpu_to_le32(BIT_0);
/* N2N: driver will initiate Login instead of FW */
- icb->firmware_options_3 |= BIT_8;
+ icb->firmware_options_3 |= cpu_to_le32(BIT_8);
/* Determine NVMe/FCP priority for target ports */
ha->fc4_type_priority = qla2xxx_get_fc4_priority(vha);
- ql_log(ql_log_info, vha, 0xffff, "FC4 priority set to %s\n",
- ha->fc4_type_priority & BIT_0 ? "FCP" : "NVMe");
if (rval) {
ql_log(ql_log_warn, vha, 0x0076,
@@ -8673,61 +8853,6 @@
return status;
}
-void
-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;
-
- /* Set Retry FLOGI in case of P2P connection */
- if (ha->operating_mode == P2P) {
- ha->fw_options[2] |= BIT_3;
- ql_dbg(ql_dbg_disc, vha, 0x2103,
- "(%s): Setting FLOGI retry BIT in fw_options[2]: 0x%x\n",
- __func__, ha->fw_options[2]);
- }
-
- /* Move PUREX, ABTS RX & RIDA to ATIOQ */
- if (ql2xmvasynctoatio) {
- if (qla_tgt_mode_enabled(vha) ||
- qla_dual_mode_enabled(vha))
- ha->fw_options[2] |= BIT_11;
- else
- ha->fw_options[2] &= ~BIT_11;
- }
-
- if (qla_tgt_mode_enabled(vha) ||
- qla_dual_mode_enabled(vha)) {
- /* FW auto send SCSI status during */
- ha->fw_options[1] |= BIT_8;
- ha->fw_options[10] |= (u16)SAM_STAT_BUSY << 8;
-
- /* FW perform Exchange validation */
- ha->fw_options[2] |= BIT_4;
- } else {
- ha->fw_options[1] &= ~BIT_8;
- ha->fw_options[10] &= 0x00ff;
-
- ha->fw_options[2] &= ~BIT_4;
- }
-
- if (ql2xetsenable) {
- /* Enable ETS Burst. */
- memset(ha->fw_options, 0, sizeof(ha->fw_options));
- ha->fw_options[2] |= BIT_9;
- }
-
- ql_dbg(ql_dbg_init, vha, 0x00e9,
- "%s, add FW options 1-3 = 0x%04x 0x%04x 0x%04x mode %x\n",
- __func__, ha->fw_options[1], ha->fw_options[2],
- ha->fw_options[3], vha->host->active_mode);
-
- qla2x00_set_fw_options(vha, ha->fw_options);
-}
-
/*
* qla24xx_get_fcp_prio
* Gets the fcp cmd priority value for the logged in port.
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 477b0b8..e80e41b 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_target.h"
@@ -11,7 +10,7 @@
* Continuation Type 1 IOCBs to allocate.
*
* @vha: HA context
- * @dsds: number of data segment decriptors needed
+ * @dsds: number of data segment descriptors needed
*
* Returns the number of IOCB entries needed to store @dsds.
*/
@@ -40,16 +39,16 @@
* register value.
*/
static __inline__ uint16_t
-qla2x00_debounce_register(volatile uint16_t __iomem *addr)
+qla2x00_debounce_register(volatile __le16 __iomem *addr)
{
volatile uint16_t first;
volatile uint16_t second;
do {
- first = RD_REG_WORD(addr);
+ first = rd_reg_word(addr);
barrier();
cpu_relax();
- second = RD_REG_WORD(addr);
+ second = rd_reg_word(addr);
} while (first != second);
return (first);
@@ -271,11 +270,41 @@
}
static inline void
-qla2x00_set_retry_delay_timestamp(fc_port_t *fcport, uint16_t retry_delay)
+qla2x00_set_retry_delay_timestamp(fc_port_t *fcport, uint16_t sts_qual)
{
- if (retry_delay)
- fcport->retry_delay_timestamp = jiffies +
- (retry_delay * HZ / 10);
+ u8 scope;
+ u16 qual;
+#define SQ_SCOPE_MASK 0xc000 /* SAM-6 rev5 5.3.2 */
+#define SQ_SCOPE_SHIFT 14
+#define SQ_QUAL_MASK 0x3fff
+
+#define SQ_MAX_WAIT_SEC 60 /* Max I/O hold off time in seconds. */
+#define SQ_MAX_WAIT_TIME (SQ_MAX_WAIT_SEC * 10) /* in 100ms. */
+
+ if (!sts_qual) /* Common case. */
+ return;
+
+ scope = (sts_qual & SQ_SCOPE_MASK) >> SQ_SCOPE_SHIFT;
+ /* Handle only scope 1 or 2, which is for I-T nexus. */
+ if (scope != 1 && scope != 2)
+ return;
+
+ /* Skip processing, if retry delay timer is already in effect. */
+ if (fcport->retry_delay_timestamp &&
+ time_before(jiffies, fcport->retry_delay_timestamp))
+ return;
+
+ qual = sts_qual & SQ_QUAL_MASK;
+ if (qual < 1 || qual > 0x3fef)
+ return;
+ qual = min(qual, (u16)SQ_MAX_WAIT_TIME);
+
+ /* qual is expressed in 100ms increments. */
+ fcport->retry_delay_timestamp = jiffies + (qual * HZ / 10);
+
+ ql_log(ql_log_warn, fcport->vha, 0x5101,
+ "%8phC: I/O throttling requested (status qualifier = %04xh), holding off I/Os for %ums.\n",
+ fcport->port_name, sts_qual, qual * 100);
}
static inline bool
@@ -334,7 +363,7 @@
} else
req->ring_ptr++;
- WRT_REG_DWORD(req->req_q_in, req->ring_index);
+ wrt_reg_dword(req->req_q_in, req->ring_index);
}
static inline int
@@ -346,5 +375,60 @@
((uint8_t *)vha->hw->nvram)[NVRAM_DUAL_FCP_NVME_FLAG_OFFSET];
- return ((data >> 6) & BIT_0);
+ return (data >> 6) & BIT_0 ? FC4_PRIORITY_FCP : FC4_PRIORITY_NVME;
+}
+
+enum {
+ RESOURCE_NONE,
+ RESOURCE_INI,
+};
+
+static inline int
+qla_get_iocbs(struct qla_qpair *qp, struct iocb_resource *iores)
+{
+ u16 iocbs_used, i;
+ struct qla_hw_data *ha = qp->vha->hw;
+
+ if (!ql2xenforce_iocb_limit) {
+ iores->res_type = RESOURCE_NONE;
+ return 0;
+ }
+
+ if ((iores->iocb_cnt + qp->fwres.iocbs_used) < qp->fwres.iocbs_qp_limit) {
+ qp->fwres.iocbs_used += iores->iocb_cnt;
+ return 0;
+ } else {
+ /* no need to acquire qpair lock. It's just rough calculation */
+ iocbs_used = ha->base_qpair->fwres.iocbs_used;
+ for (i = 0; i < ha->max_qpairs; i++) {
+ if (ha->queue_pair_map[i])
+ iocbs_used += ha->queue_pair_map[i]->fwres.iocbs_used;
+ }
+
+ if ((iores->iocb_cnt + iocbs_used) < qp->fwres.iocbs_limit) {
+ qp->fwres.iocbs_used += iores->iocb_cnt;
+ return 0;
+ } else {
+ iores->res_type = RESOURCE_NONE;
+ return -ENOSPC;
+ }
+ }
+}
+
+static inline void
+qla_put_iocbs(struct qla_qpair *qp, struct iocb_resource *iores)
+{
+ switch (iores->res_type) {
+ case RESOURCE_NONE:
+ break;
+ default:
+ if (qp->fwres.iocbs_used >= iores->iocb_cnt) {
+ qp->fwres.iocbs_used -= iores->iocb_cnt;
+ } else {
+ // should not happen
+ qp->fwres.iocbs_used = 0;
+ }
+ break;
+ }
+ iores->res_type = RESOURCE_NONE;
}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 9361036..c532c74 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
#include "qla_target.h"
@@ -44,7 +43,7 @@
* qla2x00_calc_iocbs_32() - Determine number of Command Type 2 and
* Continuation Type 0 IOCBs to allocate.
*
- * @dsds: number of data segment decriptors needed
+ * @dsds: number of data segment descriptors needed
*
* Returns the number of IOCB entries needed to store @dsds.
*/
@@ -66,7 +65,7 @@
* qla2x00_calc_iocbs_64() - Determine number of Command Type 3 and
* Continuation Type 1 IOCBs to allocate.
*
- * @dsds: number of data segment decriptors needed
+ * @dsds: number of data segment descriptors needed
*
* Returns the number of IOCB entries needed to store @dsds.
*/
@@ -376,7 +375,7 @@
/* Calculate the number of request entries needed. */
req_cnt = ha->isp_ops->calc_req_entries(tot_dsds);
if (req->cnt < (req_cnt + 2)) {
- cnt = RD_REG_WORD_RELAXED(ISP_REQ_Q_OUT(ha, reg));
+ cnt = rd_reg_word_relaxed(ISP_REQ_Q_OUT(ha, reg));
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
else
@@ -428,8 +427,8 @@
sp->flags |= SRB_DMA_VALID;
/* Set chip new ring index. */
- WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), req->ring_index);
- RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, reg)); /* PCI Posting. */
+ wrt_reg_word(ISP_REQ_Q_IN(ha, reg), req->ring_index);
+ rd_reg_word_relaxed(ISP_REQ_Q_IN(ha, reg)); /* PCI Posting. */
/* Manage unprocessed RIO/ZIO commands in response queue. */
if (vha->flags.process_response_queue &&
@@ -472,21 +471,21 @@
/* Set chip new ring index. */
if (ha->mqenable || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
- WRT_REG_DWORD(req->req_q_in, req->ring_index);
+ wrt_reg_dword(req->req_q_in, req->ring_index);
} else if (IS_QLA83XX(ha)) {
- WRT_REG_DWORD(req->req_q_in, req->ring_index);
- RD_REG_DWORD_RELAXED(&ha->iobase->isp24.hccr);
+ wrt_reg_dword(req->req_q_in, req->ring_index);
+ rd_reg_dword_relaxed(&ha->iobase->isp24.hccr);
} else if (IS_QLAFX00(ha)) {
- WRT_REG_DWORD(®->ispfx00.req_q_in, req->ring_index);
- RD_REG_DWORD_RELAXED(®->ispfx00.req_q_in);
+ wrt_reg_dword(®->ispfx00.req_q_in, req->ring_index);
+ rd_reg_dword_relaxed(®->ispfx00.req_q_in);
QLAFX00_SET_HST_INTR(ha, ha->rqstq_intr_code);
} else if (IS_FWI2_CAPABLE(ha)) {
- WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index);
- RD_REG_DWORD_RELAXED(®->isp24.req_q_in);
+ wrt_reg_dword(®->isp24.req_q_in, req->ring_index);
+ rd_reg_dword_relaxed(®->isp24.req_q_in);
} else {
- WRT_REG_WORD(ISP_REQ_Q_IN(ha, ®->isp),
+ wrt_reg_word(ISP_REQ_Q_IN(ha, ®->isp),
req->ring_index);
- RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, ®->isp));
+ rd_reg_word_relaxed(ISP_REQ_Q_IN(ha, ®->isp));
}
}
}
@@ -530,7 +529,7 @@
int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun);
host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun));
mrk24->vp_index = vha->vp_idx;
- mrk24->handle = MAKE_HANDLE(req->id, mrk24->handle);
+ mrk24->handle = make_handle(req->id, mrk24->handle);
} else {
SET_TARGET_ID(ha, mrk->target, loop_id);
mrk->lun = cpu_to_le16((uint16_t)lun);
@@ -594,6 +593,7 @@
uint32_t dsd_list_len;
struct dsd_dma *dsd_ptr;
struct ct6_dsd *ctx;
+ struct qla_qpair *qpair = sp->qpair;
cmd = GET_CMD_SP(sp);
@@ -612,12 +612,12 @@
/* Set transfer direction */
if (cmd->sc_data_direction == DMA_TO_DEVICE) {
cmd_pkt->control_flags = cpu_to_le16(CF_WRITE_DATA);
- vha->qla_stats.output_bytes += scsi_bufflen(cmd);
- vha->qla_stats.output_requests++;
+ qpair->counters.output_bytes += scsi_bufflen(cmd);
+ qpair->counters.output_requests++;
} else if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
cmd_pkt->control_flags = cpu_to_le16(CF_READ_DATA);
- vha->qla_stats.input_bytes += scsi_bufflen(cmd);
- vha->qla_stats.input_requests++;
+ qpair->counters.input_bytes += scsi_bufflen(cmd);
+ qpair->counters.input_requests++;
}
cur_seg = scsi_sglist(cmd);
@@ -661,7 +661,7 @@
cur_dsd->address = 0;
cur_dsd->length = 0;
cur_dsd++;
- cmd_pkt->control_flags |= CF_DATA_SEG_DESCR_ENABLE;
+ cmd_pkt->control_flags |= cpu_to_le16(CF_DATA_SEG_DESCR_ENABLE);
return 0;
}
@@ -669,7 +669,7 @@
* qla24xx_calc_dsd_lists() - Determine number of DSD list required
* for Command Type 6.
*
- * @dsds: number of data segment decriptors needed
+ * @dsds: number of data segment descriptors needed
*
* Returns the number of dsd list needed to store @dsds.
*/
@@ -704,6 +704,7 @@
struct scsi_cmnd *cmd;
struct scatterlist *sg;
int i;
+ struct qla_qpair *qpair = sp->qpair;
cmd = GET_CMD_SP(sp);
@@ -721,12 +722,12 @@
/* Set transfer direction */
if (cmd->sc_data_direction == DMA_TO_DEVICE) {
cmd_pkt->task_mgmt_flags = cpu_to_le16(TMF_WRITE_DATA);
- vha->qla_stats.output_bytes += scsi_bufflen(cmd);
- vha->qla_stats.output_requests++;
+ qpair->counters.output_bytes += scsi_bufflen(cmd);
+ qpair->counters.output_requests++;
} else if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
cmd_pkt->task_mgmt_flags = cpu_to_le16(TMF_READ_DATA);
- vha->qla_stats.input_bytes += scsi_bufflen(cmd);
- vha->qla_stats.input_requests++;
+ qpair->counters.input_bytes += scsi_bufflen(cmd);
+ qpair->counters.input_requests++;
}
/* One DSD is available in the Command Type 3 IOCB */
@@ -755,8 +756,8 @@
}
struct fw_dif_context {
- uint32_t ref_tag;
- uint16_t app_tag;
+ __le32 ref_tag;
+ __le16 app_tag;
uint8_t ref_tag_mask[4]; /* Validation/Replacement Mask*/
uint8_t app_tag_mask[2]; /* Validation/Replacement Mask*/
};
@@ -1389,7 +1390,7 @@
uint16_t tot_dsds, uint16_t tot_prot_dsds, uint16_t fw_prot_opts)
{
struct dsd64 *cur_dsd;
- uint32_t *fcp_dl;
+ __be32 *fcp_dl;
scsi_qla_host_t *vha;
struct scsi_cmnd *cmd;
uint32_t total_bytes = 0;
@@ -1456,7 +1457,7 @@
&crc_ctx_pkt->ref_tag, tot_prot_dsds);
put_unaligned_le64(crc_ctx_dma, &cmd_pkt->crc_context_address);
- cmd_pkt->crc_context_len = CRC_CONTEXT_LEN_FW;
+ cmd_pkt->crc_context_len = cpu_to_le16(CRC_CONTEXT_LEN_FW);
/* Determine SCSI command length -- align to 4 byte boundary */
if (cmd->cmd_len > 16) {
@@ -1545,7 +1546,7 @@
crc_ctx_pkt->guard_seed = cpu_to_le16(0);
/* Fibre channel byte count */
cmd_pkt->byte_count = cpu_to_le32(total_bytes);
- fcp_dl = (uint32_t *)(crc_ctx_pkt->fcp_cmnd.cdb + 16 +
+ fcp_dl = (__be32 *)(crc_ctx_pkt->fcp_cmnd.cdb + 16 +
additional_fcpcdb_len);
*fcp_dl = htonl(total_bytes);
@@ -1635,9 +1636,15 @@
tot_dsds = nseg;
req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
+
+ sp->iores.res_type = RESOURCE_INI;
+ sp->iores.iocb_cnt = req_cnt;
+ if (qla_get_iocbs(sp->qpair, &sp->iores))
+ goto queuing_error;
+
if (req->cnt < (req_cnt + 2)) {
cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
- RD_REG_DWORD_RELAXED(req->req_q_out);
+ rd_reg_dword_relaxed(req->req_q_out);
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
else
@@ -1655,7 +1662,7 @@
req->cnt -= req_cnt;
cmd_pkt = (struct cmd_type_7 *)req->ring_ptr;
- cmd_pkt->handle = MAKE_HANDLE(req->id, handle);
+ cmd_pkt->handle = make_handle(req->id, handle);
/* Zero out remaining portion of packet. */
/* tagged queuing modifier -- default is TSK_SIMPLE (0). */
@@ -1698,7 +1705,7 @@
sp->flags |= SRB_DMA_VALID;
/* Set chip new ring index. */
- WRT_REG_DWORD(req->req_q_in, req->ring_index);
+ wrt_reg_dword(req->req_q_in, req->ring_index);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_SUCCESS;
@@ -1707,6 +1714,7 @@
if (tot_dsds)
scsi_dma_unmap(cmd);
+ qla_put_iocbs(sp->qpair, &sp->iores);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_FUNCTION_FAILED;
@@ -1820,9 +1828,15 @@
/* Total Data and protection sg segment(s) */
tot_prot_dsds = nseg;
tot_dsds += nseg;
+
+ sp->iores.res_type = RESOURCE_INI;
+ sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
+ if (qla_get_iocbs(sp->qpair, &sp->iores))
+ goto queuing_error;
+
if (req->cnt < (req_cnt + 2)) {
cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
- RD_REG_DWORD_RELAXED(req->req_q_out);
+ rd_reg_dword_relaxed(req->req_q_out);
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
else
@@ -1843,7 +1857,7 @@
/* Fill-in common area */
cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr;
- cmd_pkt->handle = MAKE_HANDLE(req->id, handle);
+ cmd_pkt->handle = make_handle(req->id, handle);
clr_ptr = (uint32_t *)cmd_pkt + 2;
memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8);
@@ -1881,7 +1895,7 @@
req->ring_ptr++;
/* Set chip new ring index. */
- WRT_REG_DWORD(req->req_q_in, req->ring_index);
+ wrt_reg_dword(req->req_q_in, req->ring_index);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -1894,6 +1908,7 @@
}
/* Cleanup will be performed by the caller (queuecommand) */
+ qla_put_iocbs(sp->qpair, &sp->iores);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return QLA_FUNCTION_FAILED;
}
@@ -1955,9 +1970,15 @@
tot_dsds = nseg;
req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
+
+ sp->iores.res_type = RESOURCE_INI;
+ sp->iores.iocb_cnt = req_cnt;
+ if (qla_get_iocbs(sp->qpair, &sp->iores))
+ goto queuing_error;
+
if (req->cnt < (req_cnt + 2)) {
cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
- RD_REG_DWORD_RELAXED(req->req_q_out);
+ rd_reg_dword_relaxed(req->req_q_out);
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
else
@@ -1975,7 +1996,7 @@
req->cnt -= req_cnt;
cmd_pkt = (struct cmd_type_7 *)req->ring_ptr;
- cmd_pkt->handle = MAKE_HANDLE(req->id, handle);
+ cmd_pkt->handle = make_handle(req->id, handle);
/* Zero out remaining portion of packet. */
/* tagged queuing modifier -- default is TSK_SIMPLE (0). */
@@ -2018,7 +2039,7 @@
sp->flags |= SRB_DMA_VALID;
/* Set chip new ring index. */
- WRT_REG_DWORD(req->req_q_in, req->ring_index);
+ wrt_reg_dword(req->req_q_in, req->ring_index);
spin_unlock_irqrestore(&qpair->qp_lock, flags);
return QLA_SUCCESS;
@@ -2027,6 +2048,7 @@
if (tot_dsds)
scsi_dma_unmap(cmd);
+ qla_put_iocbs(sp->qpair, &sp->iores);
spin_unlock_irqrestore(&qpair->qp_lock, flags);
return QLA_FUNCTION_FAILED;
@@ -2155,9 +2177,15 @@
/* Total Data and protection sg segment(s) */
tot_prot_dsds = nseg;
tot_dsds += nseg;
+
+ sp->iores.res_type = RESOURCE_INI;
+ sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
+ if (qla_get_iocbs(sp->qpair, &sp->iores))
+ goto queuing_error;
+
if (req->cnt < (req_cnt + 2)) {
cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
- RD_REG_DWORD_RELAXED(req->req_q_out);
+ rd_reg_dword_relaxed(req->req_q_out);
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
else
@@ -2178,7 +2206,7 @@
/* Fill-in common area */
cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr;
- cmd_pkt->handle = MAKE_HANDLE(req->id, handle);
+ cmd_pkt->handle = make_handle(req->id, handle);
clr_ptr = (uint32_t *)cmd_pkt + 2;
memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8);
@@ -2214,7 +2242,7 @@
req->ring_ptr++;
/* Set chip new ring index. */
- WRT_REG_DWORD(req->req_q_in, req->ring_index);
+ wrt_reg_dword(req->req_q_in, req->ring_index);
/* Manage unprocessed RIO/ZIO commands in response queue. */
if (vha->flags.process_response_queue &&
@@ -2232,6 +2260,7 @@
}
/* Cleanup will be performed by the caller (queuecommand) */
+ qla_put_iocbs(sp->qpair, &sp->iores);
spin_unlock_irqrestore(&qpair->qp_lock, flags);
return QLA_FUNCTION_FAILED;
}
@@ -2266,13 +2295,13 @@
cnt = *req->out_ptr;
else if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
IS_QLA28XX(ha))
- cnt = RD_REG_DWORD(®->isp25mq.req_q_out);
+ cnt = rd_reg_dword(®->isp25mq.req_q_out);
else if (IS_P3P_TYPE(ha))
- cnt = RD_REG_DWORD(®->isp82.req_q_out);
+ cnt = rd_reg_dword(reg->isp82.req_q_out);
else if (IS_FWI2_CAPABLE(ha))
- cnt = RD_REG_DWORD(®->isp24.req_q_out);
+ cnt = rd_reg_dword(®->isp24.req_q_out);
else if (IS_QLAFX00(ha))
- cnt = RD_REG_DWORD(®->ispfx00.req_q_out);
+ cnt = rd_reg_dword(®->ispfx00.req_q_out);
else
cnt = qla2x00_debounce_register(
ISP_REQ_Q_OUT(ha, ®->isp));
@@ -2305,8 +2334,8 @@
pkt = req->ring_ptr;
memset(pkt, 0, REQUEST_ENTRY_SIZE);
if (IS_QLAFX00(ha)) {
- WRT_REG_BYTE((void __iomem *)&pkt->entry_count, req_cnt);
- WRT_REG_WORD((void __iomem *)&pkt->handle, handle);
+ wrt_reg_byte((u8 __force __iomem *)&pkt->entry_count, req_cnt);
+ wrt_reg_dword((__le32 __force __iomem *)&pkt->handle, handle);
} else {
pkt->entry_count = req_cnt;
pkt->handle = handle;
@@ -2344,9 +2373,18 @@
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
logio->control_flags = cpu_to_le16(LCF_COMMAND_PRLI);
if (lio->u.logio.flags & SRB_LOGIN_NVME_PRLI) {
- logio->control_flags |= LCF_NVME_PRLI;
+ logio->control_flags |= cpu_to_le16(LCF_NVME_PRLI);
if (sp->vha->flags.nvme_first_burst)
- logio->io_parameter[0] = NVME_PRLI_SP_FIRST_BURST;
+ logio->io_parameter[0] =
+ cpu_to_le32(NVME_PRLI_SP_FIRST_BURST);
+ if (sp->vha->flags.nvme2_enabled) {
+ /* Set service parameter BIT_8 for SLER support */
+ logio->io_parameter[0] |=
+ cpu_to_le32(NVME_PRLI_SP_SLER);
+ /* Set service parameter BIT_9 for PI control support */
+ logio->io_parameter[0] |=
+ cpu_to_le32(NVME_PRLI_SP_PI_CTRL);
+ }
}
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
@@ -2362,6 +2400,8 @@
struct srb_iocb *lio = &sp->u.iocb_cmd;
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
+ logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI);
+
if (lio->u.logio.flags & SRB_LOGIN_PRLI_ONLY) {
logio->control_flags = cpu_to_le16(LCF_COMMAND_PRLI);
} else {
@@ -2489,7 +2529,7 @@
tsk->entry_type = TSK_MGMT_IOCB_TYPE;
tsk->entry_count = 1;
- tsk->handle = MAKE_HANDLE(req->id, tsk->handle);
+ tsk->handle = make_handle(req->id, tsk->handle);
tsk->nport_handle = cpu_to_le16(fcport->loop_id);
tsk->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
tsk->control_flags = cpu_to_le32(flags);
@@ -2644,6 +2684,10 @@
memcpy(elsio->u.els_logo.els_logo_pyld, &logo_pyld,
sizeof(struct els_logo_payload));
+ ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x3075, "LOGO buffer:");
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x010a,
+ elsio->u.els_logo.els_logo_pyld,
+ sizeof(*elsio->u.els_logo.els_logo_pyld));
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
@@ -2674,15 +2718,15 @@
els_iocb->entry_status = 0;
els_iocb->handle = sp->handle;
els_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id);
- els_iocb->tx_dsd_count = 1;
+ els_iocb->tx_dsd_count = cpu_to_le16(1);
els_iocb->vp_index = vha->vp_idx;
els_iocb->sof_type = EST_SOFI3;
els_iocb->rx_dsd_count = 0;
els_iocb->opcode = elsio->u.els_logo.els_cmd;
- els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa;
- els_iocb->port_id[1] = sp->fcport->d_id.b.area;
- els_iocb->port_id[2] = sp->fcport->d_id.b.domain;
+ els_iocb->d_id[0] = sp->fcport->d_id.b.al_pa;
+ els_iocb->d_id[1] = sp->fcport->d_id.b.area;
+ els_iocb->d_id[2] = sp->fcport->d_id.b.domain;
/* For SID the byte order is different than DID */
els_iocb->s_id[1] = vha->d_id.b.al_pa;
els_iocb->s_id[2] = vha->d_id.b.area;
@@ -2694,7 +2738,7 @@
cpu_to_le32(sizeof(struct els_plogi_payload));
put_unaligned_le64(elsio->u.els_plogi.els_plogi_pyld_dma,
&els_iocb->tx_address);
- els_iocb->rx_dsd_count = 1;
+ els_iocb->rx_dsd_count = cpu_to_le16(1);
els_iocb->rx_byte_count = els_iocb->rx_len =
cpu_to_le32(sizeof(struct els_plogi_payload));
put_unaligned_le64(elsio->u.els_plogi.els_resp_pyld_dma,
@@ -2706,7 +2750,7 @@
(uint8_t *)els_iocb,
sizeof(*els_iocb));
} else {
- els_iocb->control_flags = 1 << 13;
+ els_iocb->control_flags = cpu_to_le16(1 << 13);
els_iocb->tx_byte_count =
cpu_to_le32(sizeof(struct els_logo_payload));
put_unaligned_le64(elsio->u.els_logo.els_logo_pyld_dma,
@@ -2716,6 +2760,11 @@
els_iocb->rx_byte_count = 0;
els_iocb->rx_address = 0;
els_iocb->rx_len = 0;
+ ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3076,
+ "LOGO ELS IOCB:");
+ ql_dump_buffer(ql_log_info, vha, 0x010b,
+ els_iocb,
+ sizeof(*els_iocb));
}
sp->vha->qla_stats.control_requests++;
@@ -2776,7 +2825,7 @@
struct qla_work_evt *e;
struct fc_port *conflict_fcport;
port_id_t cid; /* conflict Nport id */
- u32 *fw_status = sp->u.iocb_cmd.u.els_plogi.fw_status;
+ const __le32 *fw_status = sp->u.iocb_cmd.u.els_plogi.fw_status;
u16 lid;
ql_dbg(ql_dbg_disc, vha, 0x3072,
@@ -2789,7 +2838,7 @@
if (sp->flags & SRB_WAKEUP_ON_COMP)
complete(&lio->u.els_plogi.comp);
else {
- switch (fw_status[0]) {
+ switch (le32_to_cpu(fw_status[0])) {
case CS_DATA_UNDERRUN:
case CS_COMPLETE:
memset(&ea, 0, sizeof(ea));
@@ -2799,9 +2848,9 @@
break;
case CS_IOCB_ERROR:
- switch (fw_status[1]) {
+ switch (le32_to_cpu(fw_status[1])) {
case LSC_SCODE_PORTID_USED:
- lid = fw_status[2] & 0xffff;
+ lid = le32_to_cpu(fw_status[2]) & 0xffff;
qlt_find_sess_invalidate_other(vha,
wwn_to_u64(fcport->port_name),
fcport->d_id, lid, &conflict_fcport);
@@ -2835,9 +2884,11 @@
break;
case LSC_SCODE_NPORT_USED:
- cid.b.domain = (fw_status[2] >> 16) & 0xff;
- cid.b.area = (fw_status[2] >> 8) & 0xff;
- cid.b.al_pa = fw_status[2] & 0xff;
+ cid.b.domain = (le32_to_cpu(fw_status[2]) >> 16)
+ & 0xff;
+ cid.b.area = (le32_to_cpu(fw_status[2]) >> 8)
+ & 0xff;
+ cid.b.al_pa = le32_to_cpu(fw_status[2]) & 0xff;
cid.b.rsvd_1 = 0;
ql_dbg(ql_dbg_disc, vha, 0x20ec,
@@ -2860,7 +2911,7 @@
&vha->dpc_flags);
qla2xxx_wake_dpc(vha);
}
- /* fall through */
+ fallthrough;
default:
ql_dbg(ql_dbg_disc, vha, 0x20eb,
"%s %8phC cmd error fw_status 0x%x 0x%x 0x%x\n",
@@ -2915,6 +2966,7 @@
if (!sp) {
ql_log(ql_log_info, vha, 0x70e6,
"SRB allocation failed\n");
+ fcport->flags &= ~FCF_ASYNC_ACTIVE;
return -ENOMEM;
}
@@ -2929,7 +2981,6 @@
sp->fcport = fcport;
elsio->timeout = qla2x00_els_dcmd2_iocb_timeout;
- init_completion(&elsio->u.els_plogi.comp);
if (wait)
sp->flags = SRB_WAKEUP_ON_COMP;
@@ -2939,7 +2990,7 @@
elsio->u.els_plogi.tx_size = elsio->u.els_plogi.rx_size = DMA_POOL_SIZE;
ptr = elsio->u.els_plogi.els_plogi_pyld =
- dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
+ dma_alloc_coherent(&ha->pdev->dev, elsio->u.els_plogi.tx_size,
&elsio->u.els_plogi.els_plogi_pyld_dma, GFP_KERNEL);
if (!elsio->u.els_plogi.els_plogi_pyld) {
@@ -2948,7 +2999,7 @@
}
resp_ptr = elsio->u.els_plogi.els_resp_pyld =
- dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
+ dma_alloc_coherent(&ha->pdev->dev, elsio->u.els_plogi.rx_size,
&elsio->u.els_plogi.els_resp_pyld_dma, GFP_KERNEL);
if (!elsio->u.els_plogi.els_resp_pyld) {
@@ -2961,8 +3012,7 @@
memset(ptr, 0, sizeof(struct els_plogi_payload));
memset(resp_ptr, 0, sizeof(struct els_plogi_payload));
memcpy(elsio->u.els_plogi.els_plogi_pyld->data,
- &ha->plogi_els_payld.data,
- sizeof(elsio->u.els_plogi.els_plogi_pyld->data));
+ &ha->plogi_els_payld.fl_csp, LOGIN_TEMPLATE_SIZE);
elsio->u.els_plogi.els_cmd = els_opcode;
elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode;
@@ -2972,6 +3022,7 @@
(uint8_t *)elsio->u.els_plogi.els_plogi_pyld,
sizeof(*elsio->u.els_plogi.els_plogi_pyld));
+ init_completion(&elsio->u.els_plogi.comp);
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
rval = QLA_FUNCTION_FAILED;
@@ -2992,7 +3043,7 @@
}
out:
- fcport->flags &= ~(FCF_ASYNC_SENT);
+ fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
sp->free(sp);
done:
@@ -3010,7 +3061,7 @@
els_iocb->sys_define = 0;
els_iocb->entry_status = 0;
els_iocb->handle = sp->handle;
- els_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id);
+ els_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id);
els_iocb->tx_dsd_count = cpu_to_le16(bsg_job->request_payload.sg_cnt);
els_iocb->vp_index = sp->vha->vp_idx;
els_iocb->sof_type = EST_SOFI3;
@@ -3020,9 +3071,9 @@
sp->type == SRB_ELS_CMD_RPT ?
bsg_request->rqst_data.r_els.els_code :
bsg_request->rqst_data.h_els.command_code;
- els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa;
- els_iocb->port_id[1] = sp->fcport->d_id.b.area;
- els_iocb->port_id[2] = sp->fcport->d_id.b.domain;
+ els_iocb->d_id[0] = sp->fcport->d_id.b.al_pa;
+ els_iocb->d_id[1] = sp->fcport->d_id.b.area;
+ els_iocb->d_id[2] = sp->fcport->d_id.b.domain;
els_iocb->control_flags = 0;
els_iocb->rx_byte_count =
cpu_to_le32(bsg_job->reply_payload.payload_len);
@@ -3204,7 +3255,7 @@
uint16_t tot_dsds;
struct device_reg_82xx __iomem *reg;
uint32_t dbval;
- uint32_t *fcp_dl;
+ __be32 *fcp_dl;
uint8_t additional_cdb_len;
struct ct6_dsd *ctx;
struct scsi_qla_host *vha = sp->vha;
@@ -3298,7 +3349,7 @@
req_cnt = 1;
if (req->cnt < (req_cnt + 2)) {
- cnt = (uint16_t)RD_REG_DWORD_RELAXED(
+ cnt = (uint16_t)rd_reg_dword_relaxed(
®->req_q_out[0]);
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
@@ -3348,7 +3399,7 @@
}
cmd_pkt = (struct cmd_type_6 *)req->ring_ptr;
- cmd_pkt->handle = MAKE_HANDLE(req->id, handle);
+ cmd_pkt->handle = make_handle(req->id, handle);
/* Zero out remaining portion of packet. */
/* tagged queuing modifier -- default is TSK_SIMPLE (0). */
@@ -3386,7 +3437,7 @@
memcpy(ctx->fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len);
- fcp_dl = (uint32_t *)(ctx->fcp_cmnd->cdb + 16 +
+ fcp_dl = (__be32 *)(ctx->fcp_cmnd->cdb + 16 +
additional_cdb_len);
*fcp_dl = htonl((uint32_t)scsi_bufflen(cmd));
@@ -3407,7 +3458,7 @@
req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
if (req->cnt < (req_cnt + 2)) {
- cnt = (uint16_t)RD_REG_DWORD_RELAXED(
+ cnt = (uint16_t)rd_reg_dword_relaxed(
®->req_q_out[0]);
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
@@ -3419,7 +3470,7 @@
goto queuing_error;
cmd_pkt = (struct cmd_type_7 *)req->ring_ptr;
- cmd_pkt->handle = MAKE_HANDLE(req->id, handle);
+ cmd_pkt->handle = make_handle(req->id, handle);
/* Zero out remaining portion of packet. */
/* tagged queuing modifier -- default is TSK_SIMPLE (0).*/
@@ -3483,10 +3534,10 @@
if (ql2xdbwr)
qla82xx_wr_32(ha, (uintptr_t __force)ha->nxdb_wr_ptr, dbval);
else {
- WRT_REG_DWORD(ha->nxdb_wr_ptr, dbval);
+ wrt_reg_dword(ha->nxdb_wr_ptr, dbval);
wmb();
- while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) {
- WRT_REG_DWORD(ha->nxdb_wr_ptr, dbval);
+ while (rd_reg_dword(ha->nxdb_rd_ptr) != dbval) {
+ wrt_reg_dword(ha->nxdb_wr_ptr, dbval);
wmb();
}
}
@@ -3524,7 +3575,7 @@
memset(abt_iocb, 0, sizeof(struct abort_entry_24xx));
abt_iocb->entry_type = ABORT_IOCB_TYPE;
abt_iocb->entry_count = 1;
- abt_iocb->handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle));
+ abt_iocb->handle = make_handle(req->id, sp->handle);
if (sp->fcport) {
abt_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id);
abt_iocb->port_id[0] = sp->fcport->d_id.b.al_pa;
@@ -3532,10 +3583,10 @@
abt_iocb->port_id[2] = sp->fcport->d_id.b.domain;
}
abt_iocb->handle_to_abort =
- cpu_to_le32(MAKE_HANDLE(aio->u.abt.req_que_no,
- aio->u.abt.cmd_hndl));
+ make_handle(le16_to_cpu(aio->u.abt.req_que_no),
+ aio->u.abt.cmd_hndl);
abt_iocb->vp_index = vha->vp_idx;
- abt_iocb->req_que_no = cpu_to_le16(aio->u.abt.req_que_no);
+ abt_iocb->req_que_no = aio->u.abt.req_que_no;
/* Send the command to the firmware */
wmb();
}
@@ -3550,7 +3601,7 @@
sz = min(ARRAY_SIZE(mbx->mb), ARRAY_SIZE(sp->u.iocb_cmd.u.mbx.out_mb));
for (i = 0; i < sz; i++)
- mbx->mb[i] = cpu_to_le16(sp->u.iocb_cmd.u.mbx.out_mb[i]);
+ mbx->mb[i] = sp->u.iocb_cmd.u.mbx.out_mb[i];
}
static void
@@ -3574,7 +3625,7 @@
nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle;
if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) {
nack->u.isp24.flags = ntfy->u.isp24.flags &
- cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB);
+ cpu_to_le16(NOTIFY24XX_FLAGS_PUREX_IOCB);
}
nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id;
nack->u.isp24.status = ntfy->u.isp24.status;
@@ -3592,32 +3643,29 @@
/*
* Build NVME LS request
*/
-static int
+static void
qla_nvme_ls(srb_t *sp, struct pt_ls4_request *cmd_pkt)
{
struct srb_iocb *nvme;
- int rval = QLA_SUCCESS;
nvme = &sp->u.iocb_cmd;
cmd_pkt->entry_type = PT_LS4_REQUEST;
cmd_pkt->entry_count = 1;
- cmd_pkt->control_flags = CF_LS4_ORIGINATOR << CF_LS4_SHIFT;
+ cmd_pkt->control_flags = cpu_to_le16(CF_LS4_ORIGINATOR << CF_LS4_SHIFT);
cmd_pkt->timeout = cpu_to_le16(nvme->u.nvme.timeout_sec);
cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id);
cmd_pkt->vp_index = sp->fcport->vha->vp_idx;
- cmd_pkt->tx_dseg_count = 1;
- cmd_pkt->tx_byte_count = nvme->u.nvme.cmd_len;
- cmd_pkt->dsd[0].length = nvme->u.nvme.cmd_len;
+ cmd_pkt->tx_dseg_count = cpu_to_le16(1);
+ cmd_pkt->tx_byte_count = cpu_to_le32(nvme->u.nvme.cmd_len);
+ cmd_pkt->dsd[0].length = cpu_to_le32(nvme->u.nvme.cmd_len);
put_unaligned_le64(nvme->u.nvme.cmd_dma, &cmd_pkt->dsd[0].address);
- cmd_pkt->rx_dseg_count = 1;
- cmd_pkt->rx_byte_count = nvme->u.nvme.rsp_len;
- cmd_pkt->dsd[1].length = nvme->u.nvme.rsp_len;
+ cmd_pkt->rx_dseg_count = cpu_to_le16(1);
+ cmd_pkt->rx_byte_count = cpu_to_le32(nvme->u.nvme.rsp_len);
+ cmd_pkt->dsd[1].length = cpu_to_le32(nvme->u.nvme.rsp_len);
put_unaligned_le64(nvme->u.nvme.rsp_dma, &cmd_pkt->dsd[1].address);
-
- return rval;
}
static void
@@ -3882,7 +3930,7 @@
/* Check for room on request queue. */
if (req->cnt < req_cnt + 2) {
cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
- RD_REG_DWORD_RELAXED(req->req_q_out);
+ rd_reg_dword_relaxed(req->req_q_out);
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
else
@@ -3895,7 +3943,7 @@
}
cmd_pkt = (struct cmd_bidir *)req->ring_ptr;
- cmd_pkt->handle = MAKE_HANDLE(req->id, handle);
+ cmd_pkt->handle = make_handle(req->id, handle);
/* Zero out remaining portion of packet. */
/* tagged queuing modifier -- default is TSK_SIMPLE (0).*/
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 3e9c576..5e040b6 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
#include "qla_target.h"
@@ -22,6 +21,31 @@
static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *);
static int qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *,
sts_entry_t *);
+static void qla27xx_process_purex_fpin(struct scsi_qla_host *vha,
+ struct purex_item *item);
+static struct purex_item *qla24xx_alloc_purex_item(scsi_qla_host_t *vha,
+ uint16_t size);
+static struct purex_item *qla24xx_copy_std_pkt(struct scsi_qla_host *vha,
+ void *pkt);
+static struct purex_item *qla27xx_copy_fpin_pkt(struct scsi_qla_host *vha,
+ void **pkt, struct rsp_que **rsp);
+
+static void
+qla27xx_process_purex_fpin(struct scsi_qla_host *vha, struct purex_item *item)
+{
+ void *pkt = &item->iocb;
+ uint16_t pkt_size = item->size;
+
+ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x508d,
+ "%s: Enter\n", __func__);
+
+ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x508e,
+ "-------- ELS REQ -------\n");
+ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x508f,
+ pkt, pkt_size);
+
+ fc_host_fpin_rcv(vha->host, pkt_size, (char *)pkt);
+}
const char *const port_state_str[] = {
"Unknown",
@@ -31,6 +55,119 @@
"ONLINE"
};
+static void
+qla24xx_process_abts(struct scsi_qla_host *vha, struct purex_item *pkt)
+{
+ struct abts_entry_24xx *abts =
+ (struct abts_entry_24xx *)&pkt->iocb;
+ struct qla_hw_data *ha = vha->hw;
+ struct els_entry_24xx *rsp_els;
+ struct abts_entry_24xx *abts_rsp;
+ dma_addr_t dma;
+ uint32_t fctl;
+ int rval;
+
+ ql_dbg(ql_dbg_init, vha, 0x0286, "%s: entered.\n", __func__);
+
+ ql_log(ql_log_warn, vha, 0x0287,
+ "Processing ABTS xchg=%#x oxid=%#x rxid=%#x seqid=%#x seqcnt=%#x\n",
+ abts->rx_xch_addr_to_abort, abts->ox_id, abts->rx_id,
+ abts->seq_id, abts->seq_cnt);
+ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0287,
+ "-------- ABTS RCV -------\n");
+ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0287,
+ (uint8_t *)abts, sizeof(*abts));
+
+ rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), &dma,
+ GFP_KERNEL);
+ if (!rsp_els) {
+ ql_log(ql_log_warn, vha, 0x0287,
+ "Failed allocate dma buffer ABTS/ELS RSP.\n");
+ return;
+ }
+
+ /* terminate exchange */
+ rsp_els->entry_type = ELS_IOCB_TYPE;
+ rsp_els->entry_count = 1;
+ rsp_els->nport_handle = cpu_to_le16(~0);
+ rsp_els->rx_xchg_address = abts->rx_xch_addr_to_abort;
+ rsp_els->control_flags = cpu_to_le16(EPD_RX_XCHG);
+ ql_dbg(ql_dbg_init, vha, 0x0283,
+ "Sending ELS Response to terminate exchange %#x...\n",
+ abts->rx_xch_addr_to_abort);
+ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0283,
+ "-------- ELS RSP -------\n");
+ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0283,
+ (uint8_t *)rsp_els, sizeof(*rsp_els));
+ rval = qla2x00_issue_iocb(vha, rsp_els, dma, 0);
+ if (rval) {
+ ql_log(ql_log_warn, vha, 0x0288,
+ "%s: iocb failed to execute -> %x\n", __func__, rval);
+ } else if (rsp_els->comp_status) {
+ ql_log(ql_log_warn, vha, 0x0289,
+ "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n",
+ __func__, rsp_els->comp_status,
+ rsp_els->error_subcode_1, rsp_els->error_subcode_2);
+ } else {
+ ql_dbg(ql_dbg_init, vha, 0x028a,
+ "%s: abort exchange done.\n", __func__);
+ }
+
+ /* send ABTS response */
+ abts_rsp = (void *)rsp_els;
+ memset(abts_rsp, 0, sizeof(*abts_rsp));
+ abts_rsp->entry_type = ABTS_RSP_TYPE;
+ abts_rsp->entry_count = 1;
+ abts_rsp->nport_handle = abts->nport_handle;
+ abts_rsp->vp_idx = abts->vp_idx;
+ abts_rsp->sof_type = abts->sof_type & 0xf0;
+ abts_rsp->rx_xch_addr = abts->rx_xch_addr;
+ abts_rsp->d_id[0] = abts->s_id[0];
+ abts_rsp->d_id[1] = abts->s_id[1];
+ abts_rsp->d_id[2] = abts->s_id[2];
+ abts_rsp->r_ctl = FC_ROUTING_BLD | FC_R_CTL_BLD_BA_ACC;
+ abts_rsp->s_id[0] = abts->d_id[0];
+ abts_rsp->s_id[1] = abts->d_id[1];
+ abts_rsp->s_id[2] = abts->d_id[2];
+ abts_rsp->cs_ctl = abts->cs_ctl;
+ /* include flipping bit23 in fctl */
+ fctl = ~(abts->f_ctl[2] | 0x7F) << 16 |
+ FC_F_CTL_LAST_SEQ | FC_F_CTL_END_SEQ | FC_F_CTL_SEQ_INIT;
+ abts_rsp->f_ctl[0] = fctl >> 0 & 0xff;
+ abts_rsp->f_ctl[1] = fctl >> 8 & 0xff;
+ abts_rsp->f_ctl[2] = fctl >> 16 & 0xff;
+ abts_rsp->type = FC_TYPE_BLD;
+ abts_rsp->rx_id = abts->rx_id;
+ abts_rsp->ox_id = abts->ox_id;
+ abts_rsp->payload.ba_acc.aborted_rx_id = abts->rx_id;
+ abts_rsp->payload.ba_acc.aborted_ox_id = abts->ox_id;
+ abts_rsp->payload.ba_acc.high_seq_cnt = cpu_to_le16(~0);
+ abts_rsp->rx_xch_addr_to_abort = abts->rx_xch_addr_to_abort;
+ ql_dbg(ql_dbg_init, vha, 0x028b,
+ "Sending BA ACC response to ABTS %#x...\n",
+ abts->rx_xch_addr_to_abort);
+ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x028b,
+ "-------- ELS RSP -------\n");
+ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x028b,
+ (uint8_t *)abts_rsp, sizeof(*abts_rsp));
+ rval = qla2x00_issue_iocb(vha, abts_rsp, dma, 0);
+ if (rval) {
+ ql_log(ql_log_warn, vha, 0x028c,
+ "%s: iocb failed to execute -> %x\n", __func__, rval);
+ } else if (abts_rsp->comp_status) {
+ ql_log(ql_log_warn, vha, 0x028d,
+ "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n",
+ __func__, abts_rsp->comp_status,
+ abts_rsp->payload.error.subcode1,
+ abts_rsp->payload.error.subcode2);
+ } else {
+ ql_dbg(ql_dbg_init, vha, 0x028ea,
+ "%s: done.\n", __func__);
+ }
+
+ dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), rsp_els, dma);
+}
+
/**
* qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
* @irq: interrupt number
@@ -67,7 +204,7 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
vha = pci_get_drvdata(ha->pdev);
for (iter = 50; iter--; ) {
- hccr = RD_REG_WORD(®->hccr);
+ hccr = rd_reg_word(®->hccr);
if (qla2x00_check_reg16_for_disconnect(vha, hccr))
break;
if (hccr & HCCR_RISC_PAUSE) {
@@ -79,18 +216,18 @@
* bit to be cleared. Schedule a big hammer to get
* out of the RISC PAUSED state.
*/
- WRT_REG_WORD(®->hccr, HCCR_RESET_RISC);
- RD_REG_WORD(®->hccr);
+ wrt_reg_word(®->hccr, HCCR_RESET_RISC);
+ rd_reg_word(®->hccr);
- ha->isp_ops->fw_dump(vha, 1);
+ ha->isp_ops->fw_dump(vha);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
break;
- } else if ((RD_REG_WORD(®->istatus) & ISR_RISC_INT) == 0)
+ } else if ((rd_reg_word(®->istatus) & ISR_RISC_INT) == 0)
break;
- if (RD_REG_WORD(®->semaphore) & BIT_0) {
- WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT);
- RD_REG_WORD(®->hccr);
+ if (rd_reg_word(®->semaphore) & BIT_0) {
+ wrt_reg_word(®->hccr, HCCR_CLR_RISC_INT);
+ rd_reg_word(®->hccr);
/* Get mailbox data. */
mb[0] = RD_MAILBOX_REG(ha, reg, 0);
@@ -109,13 +246,13 @@
mb[0]);
}
/* Release mailbox registers. */
- WRT_REG_WORD(®->semaphore, 0);
- RD_REG_WORD(®->semaphore);
+ wrt_reg_word(®->semaphore, 0);
+ rd_reg_word(®->semaphore);
} else {
qla2x00_process_response_queue(rsp);
- WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT);
- RD_REG_WORD(®->hccr);
+ wrt_reg_word(®->hccr, HCCR_CLR_RISC_INT);
+ rd_reg_word(®->hccr);
}
}
qla2x00_handle_mbx_completion(ha, status);
@@ -187,14 +324,14 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
vha = pci_get_drvdata(ha->pdev);
for (iter = 50; iter--; ) {
- stat = RD_REG_DWORD(®->u.isp2300.host_status);
+ stat = rd_reg_dword(®->u.isp2300.host_status);
if (qla2x00_check_reg32_for_disconnect(vha, stat))
break;
if (stat & HSR_RISC_PAUSED) {
if (unlikely(pci_channel_offline(ha->pdev)))
break;
- hccr = RD_REG_WORD(®->hccr);
+ hccr = rd_reg_word(®->hccr);
if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8))
ql_log(ql_log_warn, vha, 0x5026,
@@ -210,10 +347,10 @@
* interrupt bit to be cleared. Schedule a big
* hammer to get out of the RISC PAUSED state.
*/
- WRT_REG_WORD(®->hccr, HCCR_RESET_RISC);
- RD_REG_WORD(®->hccr);
+ wrt_reg_word(®->hccr, HCCR_RESET_RISC);
+ rd_reg_word(®->hccr);
- ha->isp_ops->fw_dump(vha, 1);
+ ha->isp_ops->fw_dump(vha);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
break;
} else if ((stat & HSR_RISC_INT) == 0)
@@ -228,7 +365,7 @@
status |= MBX_INTERRUPT;
/* Release mailbox registers. */
- WRT_REG_WORD(®->semaphore, 0);
+ wrt_reg_word(®->semaphore, 0);
break;
case 0x12:
mb[0] = MSW(stat);
@@ -256,8 +393,8 @@
"Unrecognized interrupt type (%d).\n", stat & 0xff);
break;
}
- WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT);
- RD_REG_WORD_RELAXED(®->hccr);
+ wrt_reg_word(®->hccr, HCCR_CLR_RISC_INT);
+ rd_reg_word_relaxed(®->hccr);
}
qla2x00_handle_mbx_completion(ha, status);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -275,7 +412,7 @@
{
uint16_t cnt;
uint32_t mboxes;
- uint16_t __iomem *wptr;
+ __le16 __iomem *wptr;
struct qla_hw_data *ha = vha->hw;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
@@ -291,15 +428,15 @@
ha->flags.mbox_int = 1;
ha->mailbox_out[0] = mb0;
mboxes >>= 1;
- wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 1);
+ wptr = MAILBOX_REG(ha, reg, 1);
for (cnt = 1; cnt < ha->mbx_count; cnt++) {
if (IS_QLA2200(ha) && cnt == 8)
- wptr = (uint16_t __iomem *)MAILBOX_REG(ha, reg, 8);
+ wptr = MAILBOX_REG(ha, reg, 8);
if ((cnt == 4 || cnt == 5) && (mboxes & BIT_0))
ha->mailbox_out[cnt] = qla2x00_debounce_register(wptr);
else if (mboxes & BIT_0)
- ha->mailbox_out[cnt] = RD_REG_WORD(wptr);
+ ha->mailbox_out[cnt] = rd_reg_word(wptr);
wptr++;
mboxes >>= 1;
@@ -314,19 +451,19 @@
int rval;
struct device_reg_24xx __iomem *reg24 = &vha->hw->iobase->isp24;
struct device_reg_82xx __iomem *reg82 = &vha->hw->iobase->isp82;
- uint16_t __iomem *wptr;
+ __le16 __iomem *wptr;
uint16_t cnt, timeout, mb[QLA_IDC_ACK_REGS];
/* Seed data -- mailbox1 -> mailbox7. */
if (IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw))
- wptr = (uint16_t __iomem *)®24->mailbox1;
+ wptr = ®24->mailbox1;
else if (IS_QLA8044(vha->hw))
- wptr = (uint16_t __iomem *)®82->mailbox_out[1];
+ wptr = ®82->mailbox_out[1];
else
return;
for (cnt = 0; cnt < QLA_IDC_ACK_REGS; cnt++, wptr++)
- mb[cnt] = RD_REG_WORD(wptr);
+ mb[cnt] = rd_reg_word(wptr);
ql_dbg(ql_dbg_async, vha, 0x5021,
"Inter-Driver Communication %s -- "
@@ -619,6 +756,212 @@
return NULL;
}
+/* Shall be called only on supported adapters. */
+static void
+qla27xx_handle_8200_aen(scsi_qla_host_t *vha, uint16_t *mb)
+{
+ struct qla_hw_data *ha = vha->hw;
+ bool reset_isp_needed = 0;
+
+ ql_log(ql_log_warn, vha, 0x02f0,
+ "MPI Heartbeat stop. MPI reset is%s needed. "
+ "MB0[%xh] MB1[%xh] MB2[%xh] MB3[%xh]\n",
+ mb[1] & BIT_8 ? "" : " not",
+ mb[0], mb[1], mb[2], mb[3]);
+
+ if ((mb[1] & BIT_8) == 0)
+ return;
+
+ ql_log(ql_log_warn, vha, 0x02f1,
+ "MPI Heartbeat stop. FW dump needed\n");
+
+ if (ql2xfulldump_on_mpifail) {
+ ha->isp_ops->fw_dump(vha);
+ reset_isp_needed = 1;
+ }
+
+ ha->isp_ops->mpi_fw_dump(vha, 1);
+
+ if (reset_isp_needed) {
+ vha->hw->flags.fw_init_done = 0;
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ }
+}
+
+static struct purex_item *
+qla24xx_alloc_purex_item(scsi_qla_host_t *vha, uint16_t size)
+{
+ struct purex_item *item = NULL;
+ uint8_t item_hdr_size = sizeof(*item);
+
+ if (size > QLA_DEFAULT_PAYLOAD_SIZE) {
+ item = kzalloc(item_hdr_size +
+ (size - QLA_DEFAULT_PAYLOAD_SIZE), GFP_ATOMIC);
+ } else {
+ if (atomic_inc_return(&vha->default_item.in_use) == 1) {
+ item = &vha->default_item;
+ goto initialize_purex_header;
+ } else {
+ item = kzalloc(item_hdr_size, GFP_ATOMIC);
+ }
+ }
+ if (!item) {
+ ql_log(ql_log_warn, vha, 0x5092,
+ ">> Failed allocate purex list item.\n");
+
+ return NULL;
+ }
+
+initialize_purex_header:
+ item->vha = vha;
+ item->size = size;
+ return item;
+}
+
+static void
+qla24xx_queue_purex_item(scsi_qla_host_t *vha, struct purex_item *pkt,
+ void (*process_item)(struct scsi_qla_host *vha,
+ struct purex_item *pkt))
+{
+ struct purex_list *list = &vha->purex_list;
+ ulong flags;
+
+ pkt->process_item = process_item;
+
+ spin_lock_irqsave(&list->lock, flags);
+ list_add_tail(&pkt->list, &list->head);
+ spin_unlock_irqrestore(&list->lock, flags);
+
+ set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags);
+}
+
+/**
+ * qla24xx_copy_std_pkt() - Copy over purex ELS which is
+ * contained in a single IOCB.
+ * purex packet.
+ * @vha: SCSI driver HA context
+ * @pkt: ELS packet
+ */
+static struct purex_item
+*qla24xx_copy_std_pkt(struct scsi_qla_host *vha, void *pkt)
+{
+ struct purex_item *item;
+
+ item = qla24xx_alloc_purex_item(vha,
+ QLA_DEFAULT_PAYLOAD_SIZE);
+ if (!item)
+ return item;
+
+ memcpy(&item->iocb, pkt, sizeof(item->iocb));
+ return item;
+}
+
+/**
+ * qla27xx_copy_fpin_pkt() - Copy over fpin packets that can
+ * span over multiple IOCBs.
+ * @vha: SCSI driver HA context
+ * @pkt: ELS packet
+ * @rsp: Response queue
+ */
+static struct purex_item *
+qla27xx_copy_fpin_pkt(struct scsi_qla_host *vha, void **pkt,
+ struct rsp_que **rsp)
+{
+ struct purex_entry_24xx *purex = *pkt;
+ struct rsp_que *rsp_q = *rsp;
+ sts_cont_entry_t *new_pkt;
+ uint16_t no_bytes = 0, total_bytes = 0, pending_bytes = 0;
+ uint16_t buffer_copy_offset = 0;
+ uint16_t entry_count, entry_count_remaining;
+ struct purex_item *item;
+ void *fpin_pkt = NULL;
+
+ total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF)
+ - PURX_ELS_HEADER_SIZE;
+ pending_bytes = total_bytes;
+ entry_count = entry_count_remaining = purex->entry_count;
+ no_bytes = (pending_bytes > sizeof(purex->els_frame_payload)) ?
+ sizeof(purex->els_frame_payload) : pending_bytes;
+ ql_log(ql_log_info, vha, 0x509a,
+ "FPIN ELS, frame_size 0x%x, entry count %d\n",
+ total_bytes, entry_count);
+
+ item = qla24xx_alloc_purex_item(vha, total_bytes);
+ if (!item)
+ return item;
+
+ fpin_pkt = &item->iocb;
+
+ memcpy(fpin_pkt, &purex->els_frame_payload[0], no_bytes);
+ buffer_copy_offset += no_bytes;
+ pending_bytes -= no_bytes;
+ --entry_count_remaining;
+
+ ((response_t *)purex)->signature = RESPONSE_PROCESSED;
+ wmb();
+
+ do {
+ while ((total_bytes > 0) && (entry_count_remaining > 0)) {
+ if (rsp_q->ring_ptr->signature == RESPONSE_PROCESSED) {
+ ql_dbg(ql_dbg_async, vha, 0x5084,
+ "Ran out of IOCBs, partial data 0x%x\n",
+ buffer_copy_offset);
+ cpu_relax();
+ continue;
+ }
+
+ new_pkt = (sts_cont_entry_t *)rsp_q->ring_ptr;
+ *pkt = new_pkt;
+
+ if (new_pkt->entry_type != STATUS_CONT_TYPE) {
+ ql_log(ql_log_warn, vha, 0x507a,
+ "Unexpected IOCB type, partial data 0x%x\n",
+ buffer_copy_offset);
+ break;
+ }
+
+ rsp_q->ring_index++;
+ if (rsp_q->ring_index == rsp_q->length) {
+ rsp_q->ring_index = 0;
+ rsp_q->ring_ptr = rsp_q->ring;
+ } else {
+ rsp_q->ring_ptr++;
+ }
+ no_bytes = (pending_bytes > sizeof(new_pkt->data)) ?
+ sizeof(new_pkt->data) : pending_bytes;
+ if ((buffer_copy_offset + no_bytes) <= total_bytes) {
+ memcpy(((uint8_t *)fpin_pkt +
+ buffer_copy_offset), new_pkt->data,
+ no_bytes);
+ buffer_copy_offset += no_bytes;
+ pending_bytes -= no_bytes;
+ --entry_count_remaining;
+ } else {
+ ql_log(ql_log_warn, vha, 0x5044,
+ "Attempt to copy more that we got, optimizing..%x\n",
+ buffer_copy_offset);
+ memcpy(((uint8_t *)fpin_pkt +
+ buffer_copy_offset), new_pkt->data,
+ total_bytes - buffer_copy_offset);
+ }
+
+ ((response_t *)new_pkt)->signature = RESPONSE_PROCESSED;
+ wmb();
+ }
+
+ if (pending_bytes != 0 || entry_count_remaining != 0) {
+ ql_log(ql_log_fatal, vha, 0x508b,
+ "Dropping partial FPIN, underrun bytes = 0x%x, entry cnts 0x%x\n",
+ total_bytes, entry_count_remaining);
+ qla24xx_free_purex_item(item);
+ return NULL;
+ }
+ } while (entry_count_remaining > 0);
+ host_to_fcp_swap((uint8_t *)&item->iocb, total_bytes);
+ return item;
+}
+
/**
* qla2x00_async_event() - Process aynchronous events.
* @vha: SCSI driver HA context
@@ -648,7 +991,7 @@
goto skip_rio;
switch (mb[0]) {
case MBA_SCSI_COMPLETION:
- handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1]));
+ handles[0] = make_handle(mb[2], mb[1]);
handle_cnt = 1;
break;
case MBA_CMPLT_1_16BIT:
@@ -687,10 +1030,9 @@
mb[0] = MBA_SCSI_COMPLETION;
break;
case MBA_CMPLT_2_32BIT:
- handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1]));
- handles[1] = le32_to_cpu(
- ((uint32_t)(RD_MAILBOX_REG(ha, reg, 7) << 16)) |
- RD_MAILBOX_REG(ha, reg, 6));
+ handles[0] = make_handle(mb[2], mb[1]);
+ handles[1] = make_handle(RD_MAILBOX_REG(ha, reg, 7),
+ RD_MAILBOX_REG(ha, reg, 6));
handle_cnt = 2;
mb[0] = MBA_SCSI_COMPLETION;
break;
@@ -716,16 +1058,28 @@
break;
case MBA_SYSTEM_ERR: /* System Error */
- mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
- IS_QLA28XX(ha)) ?
- RD_REG_WORD(®24->mailbox7) : 0;
- ql_log(ql_log_warn, vha, 0x5003,
- "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh "
- "mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx);
- ha->fw_dump_mpi =
- (IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
- RD_REG_WORD(®24->mailbox7) & BIT_8;
- ha->isp_ops->fw_dump(vha, 1);
+ mbx = 0;
+ if (IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
+ IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ u16 m[4];
+
+ m[0] = rd_reg_word(®24->mailbox4);
+ m[1] = rd_reg_word(®24->mailbox5);
+ m[2] = rd_reg_word(®24->mailbox6);
+ mbx = m[3] = rd_reg_word(®24->mailbox7);
+
+ ql_log(ql_log_warn, vha, 0x5003,
+ "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh mbx4=%xh mbx5=%xh mbx6=%xh mbx7=%xh.\n",
+ mb[1], mb[2], mb[3], m[0], m[1], m[2], m[3]);
+ } else
+ ql_log(ql_log_warn, vha, 0x5003,
+ "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n ",
+ mb[1], mb[2], mb[3]);
+
+ if ((IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
+ rd_reg_word(®24->mailbox7) & BIT_8)
+ ha->isp_ops->mpi_fw_dump(vha, 1);
+ ha->isp_ops->fw_dump(vha);
ha->flags.fw_init_done = 0;
QLA_FW_STOPPED(ha);
@@ -788,7 +1142,7 @@
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
atomic_set(&vha->loop_state, LOOP_DOWN);
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
- qla2x00_mark_all_devices_lost(vha, 1);
+ qla2x00_mark_all_devices_lost(vha);
}
if (vha->vp_idx) {
@@ -813,13 +1167,15 @@
"LOOP UP detected (%s Gbps).\n",
qla2x00_get_link_speed_str(ha, ha->link_data_rate));
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ if (mb[2] & BIT_0)
+ ql_log(ql_log_info, vha, 0x11a0,
+ "FEC=enabled (link up).\n");
+ }
+
vha->flags.management_server_logged_in = 0;
qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate);
- if (AUTO_DETECT_SFP_SUPPORT(vha)) {
- set_bit(DETECT_SFP_CHANGE, &vha->dpc_flags);
- qla2xxx_wake_dpc(vha);
- }
break;
case MBA_LOOP_DOWN: /* Loop Down Event */
@@ -828,8 +1184,8 @@
ha->current_topology = 0;
mbx = (IS_QLA81XX(ha) || IS_QLA8031(ha))
- ? RD_REG_WORD(®24->mailbox4) : 0;
- mbx = (IS_P3P_TYPE(ha)) ? RD_REG_WORD(®82->mailbox_out[4])
+ ? rd_reg_word(®24->mailbox4) : 0;
+ mbx = (IS_P3P_TYPE(ha)) ? rd_reg_word(®82->mailbox_out[4])
: mbx;
ql_log(ql_log_info, vha, 0x500b,
"LOOP DOWN detected (%x %x %x %x).\n",
@@ -861,7 +1217,7 @@
}
vha->device_flags |= DFLG_NO_CABLE;
- qla2x00_mark_all_devices_lost(vha, 1);
+ qla2x00_mark_all_devices_lost(vha);
}
if (vha->vp_idx) {
@@ -881,7 +1237,7 @@
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
atomic_set(&vha->loop_state, LOOP_DOWN);
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
- qla2x00_mark_all_devices_lost(vha, 1);
+ qla2x00_mark_all_devices_lost(vha);
}
if (vha->vp_idx) {
@@ -924,7 +1280,7 @@
atomic_set(&vha->loop_down_timer,
LOOP_DOWN_TIME);
if (!N2N_TOPO(ha))
- qla2x00_mark_all_devices_lost(vha, 1);
+ qla2x00_mark_all_devices_lost(vha);
}
if (vha->vp_idx) {
@@ -953,7 +1309,7 @@
if (!atomic_read(&vha->loop_down_timer))
atomic_set(&vha->loop_down_timer,
LOOP_DOWN_TIME);
- qla2x00_mark_all_devices_lost(vha, 1);
+ qla2x00_mark_all_devices_lost(vha);
}
if (vha->vp_idx) {
@@ -1022,7 +1378,6 @@
"Marking port lost loopid=%04x portid=%06x.\n",
fcport->loop_id, fcport->d_id.b24);
if (qla_ini_mode_enabled(vha)) {
- qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
fcport->logout_on_delete = 0;
qlt_schedule_sess_for_deletion(fcport);
}
@@ -1034,14 +1389,14 @@
atomic_set(&vha->loop_down_timer,
LOOP_DOWN_TIME);
vha->device_flags |= DFLG_NO_CABLE;
- qla2x00_mark_all_devices_lost(vha, 1);
+ qla2x00_mark_all_devices_lost(vha);
}
if (vha->vp_idx) {
atomic_set(&vha->vp_state, VP_FAILED);
fc_vport_set_state(vha->fc_vport,
FC_VPORT_FAILED);
- qla2x00_mark_all_devices_lost(vha, 1);
+ qla2x00_mark_all_devices_lost(vha);
}
vha->flags.management_server_logged_in = 0;
@@ -1120,6 +1475,19 @@
qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry);
}
break;
+ case MBA_CONGN_NOTI_RECV:
+ if (!ha->flags.scm_enabled ||
+ mb[1] != QLA_CON_PRIMITIVE_RECEIVED)
+ break;
+
+ if (mb[2] == QLA_CONGESTION_ARB_WARNING) {
+ ql_dbg(ql_dbg_async, vha, 0x509b,
+ "Congestion Warning %04x %04x.\n", mb[1], mb[2]);
+ } else if (mb[2] == QLA_CONGESTION_ARB_ALARM) {
+ ql_log(ql_log_warn, vha, 0x509b,
+ "Congestion Alarm %04x %04x.\n", mb[1], mb[2]);
+ }
+ break;
/* case MBA_RIO_RESPONSE: */
case MBA_ZIO_RESPONSE:
ql_dbg(ql_dbg_async, vha, 0x5015,
@@ -1197,7 +1565,7 @@
break;
case MBA_IDC_NOTIFY:
if (IS_QLA8031(vha->hw) || IS_QLA8044(ha)) {
- mb[4] = RD_REG_WORD(®24->mailbox4);
+ mb[4] = rd_reg_word(®24->mailbox4);
if (((mb[2] & 0x7fff) == MBC_PORT_RESET ||
(mb[2] & 0x7fff) == MBC_SET_PORT_CONFIG) &&
(mb[4] & INTERNAL_LOOPBACK_MASK) != 0) {
@@ -1211,11 +1579,11 @@
qla2xxx_wake_dpc(vha);
}
}
- /* fall through */
+ fallthrough;
case MBA_IDC_COMPLETE:
if (ha->notify_lb_portup_comp && !vha->vp_idx)
complete(&ha->lb_portup_comp);
- /* Fallthru */
+ fallthrough;
case MBA_IDC_TIME_EXT:
if (IS_QLA81XX(vha->hw) || IS_QLA8031(vha->hw) ||
IS_QLA8044(ha))
@@ -1223,20 +1591,51 @@
break;
case MBA_IDC_AEN:
- mb[4] = RD_REG_WORD(®24->mailbox4);
- mb[5] = RD_REG_WORD(®24->mailbox5);
- mb[6] = RD_REG_WORD(®24->mailbox6);
- mb[7] = RD_REG_WORD(®24->mailbox7);
- qla83xx_handle_8200_aen(vha, mb);
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ qla27xx_handle_8200_aen(vha, mb);
+ } else if (IS_QLA83XX(ha)) {
+ mb[4] = rd_reg_word(®24->mailbox4);
+ mb[5] = rd_reg_word(®24->mailbox5);
+ mb[6] = rd_reg_word(®24->mailbox6);
+ mb[7] = rd_reg_word(®24->mailbox7);
+ qla83xx_handle_8200_aen(vha, mb);
+ } else {
+ ql_dbg(ql_dbg_async, vha, 0x5052,
+ "skip Heartbeat processing mb0-3=[0x%04x] [0x%04x] [0x%04x] [0x%04x]\n",
+ mb[0], mb[1], mb[2], mb[3]);
+ }
break;
case MBA_DPORT_DIAGNOSTICS:
ql_dbg(ql_dbg_async, vha, 0x5052,
- "D-Port Diagnostics: %04x result=%s\n",
- mb[0],
- mb[1] == 0 ? "start" :
- mb[1] == 1 ? "done (pass)" :
- mb[1] == 2 ? "done (error)" : "other");
+ "D-Port Diagnostics: %04x %04x %04x %04x\n",
+ mb[0], mb[1], mb[2], mb[3]);
+ memcpy(vha->dport_data, mb, sizeof(vha->dport_data));
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ static char *results[] = {
+ "start", "done(pass)", "done(error)", "undefined" };
+ static char *types[] = {
+ "none", "dynamic", "static", "other" };
+ uint result = mb[1] >> 0 & 0x3;
+ uint type = mb[1] >> 6 & 0x3;
+ uint sw = mb[1] >> 15 & 0x1;
+ ql_dbg(ql_dbg_async, vha, 0x5052,
+ "D-Port Diagnostics: result=%s type=%s [sw=%u]\n",
+ results[result], types[type], sw);
+ if (result == 2) {
+ static char *reasons[] = {
+ "reserved", "unexpected reject",
+ "unexpected phase", "retry exceeded",
+ "timed out", "not supported",
+ "user stopped" };
+ uint reason = mb[2] >> 0 & 0xf;
+ uint phase = mb[2] >> 12 & 0xf;
+ ql_dbg(ql_dbg_async, vha, 0x5052,
+ "D-Port Diagnostics: reason=%s phase=%u \n",
+ reason < 7 ? reasons[reason] : "other",
+ phase >> 1);
+ }
+ }
break;
case MBA_TEMPERATURE_ALERT:
@@ -1249,6 +1648,11 @@
case MBA_TRANS_INSERT:
ql_dbg(ql_dbg_async, vha, 0x5091,
"Transceiver Insertion: %04x\n", mb[1]);
+ set_bit(DETECT_SFP_CHANGE, &vha->dpc_flags);
+ break;
+
+ case MBA_TRANS_REMOVE:
+ ql_dbg(ql_dbg_async, vha, 0x5091, "Transceiver Removal\n");
break;
default:
@@ -1311,35 +1715,35 @@
{
struct qla_hw_data *ha = vha->hw;
sts_entry_t *pkt = iocb;
- srb_t *sp = NULL;
+ srb_t *sp;
uint16_t index;
index = LSW(pkt->handle);
if (index >= req->num_outstanding_cmds) {
ql_log(ql_log_warn, vha, 0x5031,
- "Invalid command index (%x) type %8ph.\n",
- index, iocb);
+ "%s: Invalid command index (%x) type %8ph.\n",
+ func, index, iocb);
if (IS_P3P_TYPE(ha))
set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
else
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
- goto done;
+ return NULL;
}
sp = req->outstanding_cmds[index];
if (!sp) {
ql_log(ql_log_warn, vha, 0x5032,
- "Invalid completion handle (%x) -- timed-out.\n", index);
- return sp;
+ "%s: Invalid completion handle (%x) -- timed-out.\n",
+ func, index);
+ return NULL;
}
if (sp->handle != index) {
ql_log(ql_log_warn, vha, 0x5033,
- "SRB handle (%x) mismatch %x.\n", sp->handle, index);
+ "%s: SRB handle (%x) mismatch %x.\n", func,
+ sp->handle, index);
return NULL;
}
req->outstanding_cmds[index] = NULL;
-
-done:
return sp;
}
@@ -1434,6 +1838,7 @@
struct mbx_24xx_entry *pkt)
{
const char func[] = "MBX-IOCB2";
+ struct qla_hw_data *ha = vha->hw;
srb_t *sp;
struct srb_iocb *si;
u16 sz, i;
@@ -1443,11 +1848,23 @@
if (!sp)
return;
+ if (sp->type == SRB_SCSI_CMD ||
+ sp->type == SRB_NVME_CMD ||
+ sp->type == SRB_TM_CMD) {
+ ql_log(ql_log_warn, vha, 0x509d,
+ "Inconsistent event entry type %d\n", sp->type);
+ if (IS_P3P_TYPE(ha))
+ set_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags);
+ else
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ return;
+ }
+
si = &sp->u.iocb_cmd;
sz = min(ARRAY_SIZE(pkt->mb), ARRAY_SIZE(sp->u.iocb_cmd.u.mbx.in_mb));
for (i = 0; i < sz; i++)
- si->u.mbx.in_mb[i] = le16_to_cpu(pkt->mb[i]);
+ si->u.mbx.in_mb[i] = pkt->mb[i];
res = (si->u.mbx.in_mb[0] & MBS_MASK);
@@ -1548,6 +1965,7 @@
qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
struct sts_entry_24xx *pkt, int iocb_type)
{
+ struct els_sts_entry_24xx *ese = (struct els_sts_entry_24xx *)pkt;
const char func[] = "ELS_CT_IOCB";
const char *type;
srb_t *sp;
@@ -1597,33 +2015,31 @@
}
comp_status = fw_status[0] = le16_to_cpu(pkt->comp_status);
- fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx *)pkt)->error_subcode_1);
- fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx *)pkt)->error_subcode_2);
+ fw_status[1] = le32_to_cpu(ese->error_subcode_1);
+ fw_status[2] = le32_to_cpu(ese->error_subcode_2);
if (iocb_type == ELS_IOCB_TYPE) {
els = &sp->u.iocb_cmd;
- els->u.els_plogi.fw_status[0] = fw_status[0];
- els->u.els_plogi.fw_status[1] = fw_status[1];
- els->u.els_plogi.fw_status[2] = fw_status[2];
- els->u.els_plogi.comp_status = fw_status[0];
+ els->u.els_plogi.fw_status[0] = cpu_to_le32(fw_status[0]);
+ els->u.els_plogi.fw_status[1] = cpu_to_le32(fw_status[1]);
+ els->u.els_plogi.fw_status[2] = cpu_to_le32(fw_status[2]);
+ els->u.els_plogi.comp_status = cpu_to_le16(fw_status[0]);
if (comp_status == CS_COMPLETE) {
res = DID_OK << 16;
} else {
if (comp_status == CS_DATA_UNDERRUN) {
res = DID_OK << 16;
- els->u.els_plogi.len =
- le16_to_cpu(((struct els_sts_entry_24xx *)
- pkt)->total_byte_count);
+ els->u.els_plogi.len = cpu_to_le16(le32_to_cpu(
+ ese->total_byte_count));
} else {
els->u.els_plogi.len = 0;
res = DID_ERROR << 16;
}
}
- ql_dbg(ql_dbg_user, vha, 0x503f,
- "ELS IOCB Done -%s error hdl=%x comp_status=0x%x error subcode 1=0x%x error subcode 2=0x%x total_byte=0x%x\n",
+ ql_dbg(ql_dbg_disc, vha, 0x503f,
+ "ELS IOCB Done -%s hdl=%x comp_status=0x%x error subcode 1=0x%x error subcode 2=0x%x total_byte=0x%x\n",
type, sp->handle, comp_status, fw_status[1], fw_status[2],
- le16_to_cpu(((struct els_sts_entry_24xx *)
- pkt)->total_byte_count));
+ le32_to_cpu(ese->total_byte_count));
goto els_ct_done;
}
@@ -1639,23 +2055,20 @@
if (comp_status == CS_DATA_UNDERRUN) {
res = DID_OK << 16;
bsg_reply->reply_payload_rcv_len =
- le16_to_cpu(((struct els_sts_entry_24xx *)pkt)->total_byte_count);
+ le32_to_cpu(ese->total_byte_count);
ql_dbg(ql_dbg_user, vha, 0x503f,
"ELS-CT pass-through-%s error hdl=%x comp_status-status=0x%x "
"error subcode 1=0x%x error subcode 2=0x%x total_byte = 0x%x.\n",
type, sp->handle, comp_status, fw_status[1], fw_status[2],
- le16_to_cpu(((struct els_sts_entry_24xx *)
- pkt)->total_byte_count));
+ le32_to_cpu(ese->total_byte_count));
} else {
ql_dbg(ql_dbg_user, vha, 0x5040,
"ELS-CT pass-through-%s error hdl=%x comp_status-status=0x%x "
"error subcode 1=0x%x error subcode 2=0x%x.\n",
type, sp->handle, comp_status,
- le16_to_cpu(((struct els_sts_entry_24xx *)
- pkt)->error_subcode_1),
- le16_to_cpu(((struct els_sts_entry_24xx *)
- pkt)->error_subcode_2));
+ le32_to_cpu(ese->error_subcode_1),
+ le32_to_cpu(ese->error_subcode_2));
res = DID_ERROR << 16;
bsg_reply->reply_payload_rcv_len = 0;
}
@@ -1712,11 +2125,9 @@
}
if (le16_to_cpu(logio->comp_status) == CS_COMPLETE) {
- ql_dbg(ql_dbg_async, fcport->vha, 0x5036,
- "Async-%s complete - %8phC hdl=%x portid=%02x%02x%02x "
- "iop0=%x.\n", type, fcport->port_name, sp->handle,
- fcport->d_id.b.domain,
- fcport->d_id.b.area, fcport->d_id.b.al_pa,
+ ql_dbg(ql_dbg_async, sp->vha, 0x5036,
+ "Async-%s complete: handle=%x pid=%06x wwpn=%8phC iop0=%x\n",
+ type, sp->handle, fcport->d_id.b24, fcport->port_name,
le32_to_cpu(logio->io_parameter[0]));
vha->hw->exch_starvation = 0;
@@ -1789,17 +2200,15 @@
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
}
- /* fall through */
+ fallthrough;
default:
data[0] = MBS_COMMAND_ERROR;
break;
}
- ql_dbg(ql_dbg_async, fcport->vha, 0x5037,
- "Async-%s failed - %8phC hdl=%x portid=%02x%02x%02x comp=%x "
- "iop0=%x iop1=%x.\n", type, fcport->port_name,
- sp->handle, fcport->d_id.b.domain,
- fcport->d_id.b.area, fcport->d_id.b.al_pa,
+ ql_dbg(ql_dbg_async, sp->vha, 0x5037,
+ "Async-%s failed: handle=%x pid=%06x wwpn=%8phC comp_status=%x iop0=%x iop1=%x\n",
+ type, sp->handle, fcport->d_id.b24, fcport->port_name,
le16_to_cpu(logio->comp_status),
le32_to_cpu(logio->io_parameter[0]),
le32_to_cpu(logio->io_parameter[1]));
@@ -1867,7 +2276,8 @@
uint16_t state_flags;
struct nvmefc_fcp_req *fd;
uint16_t ret = QLA_SUCCESS;
- uint16_t comp_status = le16_to_cpu(sts->comp_status);
+ __le16 comp_status = sts->comp_status;
+ int logit = 0;
iocb = &sp->u.iocb_cmd;
fcport = sp->fcport;
@@ -1878,6 +2288,12 @@
if (unlikely(iocb->u.nvme.aen_op))
atomic_dec(&sp->vha->hw->nvme_active_aen_cnt);
+ if (unlikely(comp_status != CS_COMPLETE))
+ logit = 1;
+
+ fd->transferred_length = fd->payload_length -
+ le32_to_cpu(sts->residual_len);
+
/*
* State flags: Bit 6 and 0.
* If 0 is set, we don't care about 6.
@@ -1888,16 +2304,28 @@
*/
if (!(state_flags & (SF_FCP_RSP_DMA | SF_NVME_ERSP))) {
iocb->u.nvme.rsp_pyld_len = 0;
+ } else if ((state_flags & (SF_FCP_RSP_DMA | SF_NVME_ERSP)) ==
+ (SF_FCP_RSP_DMA | SF_NVME_ERSP)) {
+ /* Response already DMA'd to fd->rspaddr. */
+ iocb->u.nvme.rsp_pyld_len = sts->nvme_rsp_pyld_len;
} else if ((state_flags & SF_FCP_RSP_DMA)) {
- iocb->u.nvme.rsp_pyld_len = le16_to_cpu(sts->nvme_rsp_pyld_len);
+ /*
+ * Non-zero value in first 12 bytes of NVMe_RSP IU, treat this
+ * as an error.
+ */
+ iocb->u.nvme.rsp_pyld_len = 0;
+ fd->transferred_length = 0;
+ ql_dbg(ql_dbg_io, fcport->vha, 0x307a,
+ "Unexpected values in NVMe_RSP IU.\n");
+ logit = 1;
} else if (state_flags & SF_NVME_ERSP) {
uint32_t *inbuf, *outbuf;
uint16_t iter;
inbuf = (uint32_t *)&sts->nvme_ersp_data;
outbuf = (uint32_t *)fd->rspaddr;
- iocb->u.nvme.rsp_pyld_len = le16_to_cpu(sts->nvme_rsp_pyld_len);
- if (unlikely(iocb->u.nvme.rsp_pyld_len >
+ iocb->u.nvme.rsp_pyld_len = sts->nvme_rsp_pyld_len;
+ if (unlikely(le16_to_cpu(iocb->u.nvme.rsp_pyld_len) >
sizeof(struct nvme_fc_ersp_iu))) {
if (ql_mask_match(ql_dbg_io)) {
WARN_ONCE(1, "Unexpected response payload length %u.\n",
@@ -1907,21 +2335,33 @@
iocb->u.nvme.rsp_pyld_len);
}
iocb->u.nvme.rsp_pyld_len =
- sizeof(struct nvme_fc_ersp_iu);
+ cpu_to_le16(sizeof(struct nvme_fc_ersp_iu));
}
- iter = iocb->u.nvme.rsp_pyld_len >> 2;
+ iter = le16_to_cpu(iocb->u.nvme.rsp_pyld_len) >> 2;
for (; iter; iter--)
*outbuf++ = swab32(*inbuf++);
- } else { /* unhandled case */
- ql_log(ql_log_warn, fcport->vha, 0x503a,
- "NVME-%s error. Unhandled state_flags of %x\n",
- sp->name, state_flags);
}
- fd->transferred_length = fd->payload_length -
- le32_to_cpu(sts->residual_len);
+ if (state_flags & SF_NVME_ERSP) {
+ struct nvme_fc_ersp_iu *rsp_iu = fd->rspaddr;
+ u32 tgt_xfer_len;
- if (unlikely(comp_status != CS_COMPLETE))
+ tgt_xfer_len = be32_to_cpu(rsp_iu->xfrd_len);
+ if (fd->transferred_length != tgt_xfer_len) {
+ ql_dbg(ql_dbg_io, fcport->vha, 0x3079,
+ "Dropped frame(s) detected (sent/rcvd=%u/%u).\n",
+ tgt_xfer_len, fd->transferred_length);
+ logit = 1;
+ } else if (le16_to_cpu(comp_status) == CS_DATA_UNDERRUN) {
+ /*
+ * Do not log if this is just an underflow and there
+ * is no data loss.
+ */
+ logit = 0;
+ }
+ }
+
+ if (unlikely(logit))
ql_log(ql_log_warn, fcport->vha, 0x5060,
"NVME-%s ERR Handling - hdl=%x status(%x) tr_len:%x resid=%x ox_id=%x\n",
sp->name, sp->handle, comp_status,
@@ -1932,7 +2372,7 @@
* If transport error then Failure (HBA rejects request)
* otherwise transport will handle.
*/
- switch (comp_status) {
+ switch (le16_to_cpu(comp_status)) {
case CS_COMPLETE:
break;
@@ -1940,7 +2380,7 @@
case CS_PORT_UNAVAILABLE:
case CS_PORT_LOGGED_OUT:
fcport->nvme_flag |= NVME_FLAG_RESETTING;
- /* fall through */
+ fallthrough;
case CS_ABORTED:
case CS_PORT_BUSY:
fd->transferred_length = 0;
@@ -2074,7 +2514,7 @@
}
/* Adjust ring index */
- WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), rsp->ring_index);
+ wrt_reg_word(ISP_RSP_Q_OUT(ha, reg), rsp->ring_index);
}
static inline void
@@ -2143,12 +2583,12 @@
* swab32 of the "data" field in the beginning of qla2x00_status_entry()
* would make guard field appear at offset 2
*/
- a_guard = le16_to_cpu(*(uint16_t *)(ap + 2));
- a_app_tag = le16_to_cpu(*(uint16_t *)(ap + 0));
- a_ref_tag = le32_to_cpu(*(uint32_t *)(ap + 4));
- e_guard = le16_to_cpu(*(uint16_t *)(ep + 2));
- e_app_tag = le16_to_cpu(*(uint16_t *)(ep + 0));
- e_ref_tag = le32_to_cpu(*(uint32_t *)(ep + 4));
+ a_guard = get_unaligned_le16(ap + 2);
+ a_app_tag = get_unaligned_le16(ap + 0);
+ a_ref_tag = get_unaligned_le32(ap + 4);
+ e_guard = get_unaligned_le16(ep + 2);
+ e_app_tag = get_unaligned_le16(ep + 0);
+ e_ref_tag = get_unaligned_le32(ep + 4);
ql_dbg(ql_dbg_io, vha, 0x3023,
"iocb(s) %p Returned STATUS.\n", sts24);
@@ -2165,9 +2605,9 @@
* For type 3: ref & app tag is all 'f's
* For type 0,1,2: app tag is all 'f's
*/
- if ((a_app_tag == T10_PI_APP_ESCAPE) &&
- ((scsi_get_prot_type(cmd) != SCSI_PROT_DIF_TYPE3) ||
- (a_ref_tag == T10_PI_REF_ESCAPE))) {
+ if (a_app_tag == be16_to_cpu(T10_PI_APP_ESCAPE) &&
+ (scsi_get_prot_type(cmd) != SCSI_PROT_DIF_TYPE3 ||
+ a_ref_tag == be32_to_cpu(T10_PI_REF_ESCAPE))) {
uint32_t blocks_done, resid;
sector_t lba_s = scsi_get_lba(cmd);
@@ -2427,7 +2867,7 @@
int logit = 1;
int res = 0;
uint16_t state_flags = 0;
- uint16_t retry_delay = 0;
+ uint16_t sts_qual = 0;
if (IS_FWI2_CAPABLE(ha)) {
comp_status = le16_to_cpu(sts24->comp_status);
@@ -2473,11 +2913,7 @@
}
return;
}
-
- if (sp->abort)
- sp->aborted = 1;
- else
- sp->completed = 1;
+ qla_put_iocbs(sp->qpair, &sp->iores);
if (sp->cmd_type != TYPE_SRB) {
req->outstanding_cmds[handle] = NULL;
@@ -2543,13 +2979,7 @@
host_to_fcp_swap(sts24->data, sizeof(sts24->data));
ox_id = le16_to_cpu(sts24->ox_id);
par_sense_len = sizeof(sts24->data);
- /* Valid values of the retry delay timer are 0x1-0xffef */
- if (sts24->retry_delay > 0 && sts24->retry_delay < 0xfff1) {
- retry_delay = sts24->retry_delay & 0x3fff;
- ql_dbg(ql_dbg_io, sp->vha, 0x3033,
- "%s: scope=%#x retry_delay=%#x\n", __func__,
- sts24->retry_delay >> 14, retry_delay);
- }
+ sts_qual = le16_to_cpu(sts24->status_qualifier);
} else {
if (scsi_status & SS_SENSE_LEN_VALID)
sense_len = le16_to_cpu(sts->req_sense_length);
@@ -2587,9 +3017,9 @@
* Check retry_delay_timer value if we receive a busy or
* queue full.
*/
- if (lscsi_status == SAM_STAT_TASK_SET_FULL ||
- lscsi_status == SAM_STAT_BUSY)
- qla2x00_set_retry_delay_timestamp(fcport, retry_delay);
+ if (unlikely(lscsi_status == SAM_STAT_TASK_SET_FULL ||
+ lscsi_status == SAM_STAT_BUSY))
+ qla2x00_set_retry_delay_timestamp(fcport, sts_qual);
/*
* Based on Host and scsi status generate status code for Linux
@@ -2736,7 +3166,6 @@
port_state_str[FCS_ONLINE],
comp_status);
- qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
qlt_schedule_sess_for_deletion(fcport);
}
@@ -2897,6 +3326,7 @@
default:
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (sp) {
+ qla_put_iocbs(sp->qpair, &sp->iores);
sp->done(sp, res);
return 0;
}
@@ -2923,7 +3353,7 @@
{
uint16_t cnt;
uint32_t mboxes;
- uint16_t __iomem *wptr;
+ __le16 __iomem *wptr;
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
@@ -2939,11 +3369,11 @@
ha->flags.mbox_int = 1;
ha->mailbox_out[0] = mb0;
mboxes >>= 1;
- wptr = (uint16_t __iomem *)®->mailbox1;
+ wptr = ®->mailbox1;
for (cnt = 1; cnt < ha->mbx_count; cnt++) {
if (mboxes & BIT_0)
- ha->mailbox_out[cnt] = RD_REG_WORD(wptr);
+ ha->mailbox_out[cnt] = rd_reg_word(wptr);
mboxes >>= 1;
wptr++;
@@ -2963,7 +3393,7 @@
return;
abt = &sp->u.iocb_cmd;
- abt->u.abt.comp_status = le16_to_cpu(pkt->nport_handle);
+ abt->u.abt.comp_status = pkt->nport_handle;
sp->done(sp, 0);
}
@@ -2992,12 +3422,16 @@
{
struct sts_entry_24xx *pkt;
struct qla_hw_data *ha = vha->hw;
+ struct purex_entry_24xx *purex_entry;
+ struct purex_item *pure_item;
if (!ha->flags.fw_started)
return;
- if (rsp->qpair->cpuid != smp_processor_id())
+ if (rsp->qpair->cpuid != smp_processor_id() || !rsp->qpair->rcv_intr) {
+ rsp->qpair->rcv_intr = 1;
qla_cpu_update(rsp->qpair, smp_processor_id());
+ }
while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
pkt = (struct sts_entry_24xx *)rsp->ring_ptr;
@@ -3042,6 +3476,14 @@
qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE);
break;
case ABTS_RECV_24XX:
+ if (qla_ini_mode_enabled(vha)) {
+ pure_item = qla24xx_copy_std_pkt(vha, pkt);
+ if (!pure_item)
+ break;
+ qla24xx_queue_purex_item(vha, pure_item,
+ qla24xx_process_abts);
+ break;
+ }
if (IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
IS_QLA28XX(ha)) {
/* ensure that the ATIO queue is empty */
@@ -3051,7 +3493,7 @@
} else {
qlt_24xx_process_atio_queue(vha, 1);
}
- /* fall through */
+ fallthrough;
case ABTS_RESP_24XX:
case CTIO_TYPE7:
case CTIO_CRC2:
@@ -3086,12 +3528,41 @@
qla_ctrlvp_completed(vha, rsp->req,
(struct vp_ctrl_entry_24xx *)pkt);
break;
+ case PUREX_IOCB_TYPE:
+ purex_entry = (void *)pkt;
+ switch (purex_entry->els_frame_payload[3]) {
+ case ELS_RDP:
+ pure_item = qla24xx_copy_std_pkt(vha, pkt);
+ if (!pure_item)
+ break;
+ qla24xx_queue_purex_item(vha, pure_item,
+ qla24xx_process_purex_rdp);
+ break;
+ case ELS_FPIN:
+ if (!vha->hw->flags.scm_enabled) {
+ ql_log(ql_log_warn, vha, 0x5094,
+ "SCM not active for this port\n");
+ break;
+ }
+ pure_item = qla27xx_copy_fpin_pkt(vha,
+ (void **)&pkt, &rsp);
+ if (!pure_item)
+ break;
+ qla24xx_queue_purex_item(vha, pure_item,
+ qla27xx_process_purex_fpin);
+ break;
+
+ default:
+ ql_log(ql_log_warn, vha, 0x509c,
+ "Discarding ELS Request opcode 0x%x\n",
+ purex_entry->els_frame_payload[3]);
+ }
+ break;
default:
/* Type Not Supported. */
ql_dbg(ql_dbg_async, vha, 0x5042,
- "Received unknown response pkt type %x "
- "entry status=%x.\n",
- pkt->entry_type, pkt->entry_status);
+ "Received unknown response pkt type 0x%x entry status=%x.\n",
+ pkt->entry_type, pkt->entry_status);
break;
}
((response_t *)pkt)->signature = RESPONSE_PROCESSED;
@@ -3102,9 +3573,9 @@
if (IS_P3P_TYPE(ha)) {
struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
- WRT_REG_DWORD(®->rsp_q_out[0], rsp->ring_index);
+ wrt_reg_dword(®->rsp_q_out[0], rsp->ring_index);
} else {
- WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index);
+ wrt_reg_dword(rsp->rsp_q_out, rsp->ring_index);
}
}
@@ -3121,13 +3592,13 @@
return;
rval = QLA_SUCCESS;
- WRT_REG_DWORD(®->iobase_addr, 0x7C00);
- RD_REG_DWORD(®->iobase_addr);
- WRT_REG_DWORD(®->iobase_window, 0x0001);
- for (cnt = 10000; (RD_REG_DWORD(®->iobase_window) & BIT_0) == 0 &&
+ wrt_reg_dword(®->iobase_addr, 0x7C00);
+ rd_reg_dword(®->iobase_addr);
+ wrt_reg_dword(®->iobase_window, 0x0001);
+ for (cnt = 10000; (rd_reg_dword(®->iobase_window) & BIT_0) == 0 &&
rval == QLA_SUCCESS; cnt--) {
if (cnt) {
- WRT_REG_DWORD(®->iobase_window, 0x0001);
+ wrt_reg_dword(®->iobase_window, 0x0001);
udelay(10);
} else
rval = QLA_FUNCTION_TIMEOUT;
@@ -3136,11 +3607,11 @@
goto next_test;
rval = QLA_SUCCESS;
- WRT_REG_DWORD(®->iobase_window, 0x0003);
- for (cnt = 100; (RD_REG_DWORD(®->iobase_window) & BIT_0) == 0 &&
+ wrt_reg_dword(®->iobase_window, 0x0003);
+ for (cnt = 100; (rd_reg_dword(®->iobase_window) & BIT_0) == 0 &&
rval == QLA_SUCCESS; cnt--) {
if (cnt) {
- WRT_REG_DWORD(®->iobase_window, 0x0003);
+ wrt_reg_dword(®->iobase_window, 0x0003);
udelay(10);
} else
rval = QLA_FUNCTION_TIMEOUT;
@@ -3149,13 +3620,13 @@
goto done;
next_test:
- if (RD_REG_DWORD(®->iobase_c8) & BIT_3)
+ if (rd_reg_dword(®->iobase_c8) & BIT_3)
ql_log(ql_log_info, vha, 0x504c,
"Additional code -- 0x55AA.\n");
done:
- WRT_REG_DWORD(®->iobase_window, 0x0000);
- RD_REG_DWORD(®->iobase_window);
+ wrt_reg_dword(®->iobase_window, 0x0000);
+ rd_reg_dword(®->iobase_window);
}
/**
@@ -3199,14 +3670,14 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
vha = pci_get_drvdata(ha->pdev);
for (iter = 50; iter--; ) {
- stat = RD_REG_DWORD(®->host_status);
+ stat = rd_reg_dword(®->host_status);
if (qla2x00_check_reg32_for_disconnect(vha, stat))
break;
if (stat & HSRX_RISC_PAUSED) {
if (unlikely(pci_channel_offline(ha->pdev)))
break;
- hccr = RD_REG_DWORD(®->hccr);
+ hccr = rd_reg_dword(®->hccr);
ql_log(ql_log_warn, vha, 0x504b,
"RISC paused -- HCCR=%x, Dumping firmware.\n",
@@ -3214,7 +3685,7 @@
qla2xxx_check_risc_status(vha);
- ha->isp_ops->fw_dump(vha, 1);
+ ha->isp_ops->fw_dump(vha);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
break;
} else if ((stat & HSRX_RISC_INT) == 0)
@@ -3231,9 +3702,9 @@
break;
case INTR_ASYNC_EVENT:
mb[0] = MSW(stat);
- mb[1] = RD_REG_WORD(®->mailbox1);
- mb[2] = RD_REG_WORD(®->mailbox2);
- mb[3] = RD_REG_WORD(®->mailbox3);
+ mb[1] = rd_reg_word(®->mailbox1);
+ mb[2] = rd_reg_word(®->mailbox2);
+ mb[3] = rd_reg_word(®->mailbox3);
qla2x00_async_event(vha, rsp, mb);
break;
case INTR_RSP_QUE_UPDATE:
@@ -3253,8 +3724,8 @@
"Unrecognized interrupt type (%d).\n", stat * 0xff);
break;
}
- WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT);
- RD_REG_DWORD_RELAXED(®->hccr);
+ wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT);
+ rd_reg_dword_relaxed(®->hccr);
if (unlikely(IS_QLA83XX(ha) && (ha->pdev->revision == 1)))
ndelay(3500);
}
@@ -3293,8 +3764,8 @@
vha = pci_get_drvdata(ha->pdev);
qla24xx_process_response_queue(vha, rsp);
if (!ha->flags.disable_msix_handshake) {
- WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT);
- RD_REG_DWORD_RELAXED(®->hccr);
+ wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT);
+ rd_reg_dword_relaxed(®->hccr);
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -3328,14 +3799,14 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
vha = pci_get_drvdata(ha->pdev);
do {
- stat = RD_REG_DWORD(®->host_status);
+ stat = rd_reg_dword(®->host_status);
if (qla2x00_check_reg32_for_disconnect(vha, stat))
break;
if (stat & HSRX_RISC_PAUSED) {
if (unlikely(pci_channel_offline(ha->pdev)))
break;
- hccr = RD_REG_DWORD(®->hccr);
+ hccr = rd_reg_dword(®->hccr);
ql_log(ql_log_info, vha, 0x5050,
"RISC paused -- HCCR=%x, Dumping firmware.\n",
@@ -3343,7 +3814,7 @@
qla2xxx_check_risc_status(vha);
- ha->isp_ops->fw_dump(vha, 1);
+ ha->isp_ops->fw_dump(vha);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
break;
} else if ((stat & HSRX_RISC_INT) == 0)
@@ -3360,9 +3831,9 @@
break;
case INTR_ASYNC_EVENT:
mb[0] = MSW(stat);
- mb[1] = RD_REG_WORD(®->mailbox1);
- mb[2] = RD_REG_WORD(®->mailbox2);
- mb[3] = RD_REG_WORD(®->mailbox3);
+ mb[1] = rd_reg_word(®->mailbox1);
+ mb[2] = rd_reg_word(®->mailbox2);
+ mb[3] = rd_reg_word(®->mailbox3);
qla2x00_async_event(vha, rsp, mb);
break;
case INTR_RSP_QUE_UPDATE:
@@ -3382,7 +3853,7 @@
"Unrecognized interrupt type (%d).\n", stat & 0xff);
break;
}
- WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT);
+ wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT);
} while (0);
qla2x00_handle_mbx_completion(ha, status);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -3401,6 +3872,25 @@
{
struct qla_hw_data *ha;
struct qla_qpair *qpair;
+
+ qpair = dev_id;
+ if (!qpair) {
+ ql_log(ql_log_info, NULL, 0x505b,
+ "%s: NULL response queue pointer.\n", __func__);
+ return IRQ_NONE;
+ }
+ ha = qpair->hw;
+
+ queue_work_on(smp_processor_id(), ha->wq, &qpair->q_work);
+
+ return IRQ_HANDLED;
+}
+
+irqreturn_t
+qla2xxx_msix_rsp_q_hs(int irq, void *dev_id)
+{
+ struct qla_hw_data *ha;
+ struct qla_qpair *qpair;
struct device_reg_24xx __iomem *reg;
unsigned long flags;
@@ -3412,15 +3902,12 @@
}
ha = qpair->hw;
- /* Clear the interrupt, if enabled, for this response queue */
- if (unlikely(!ha->flags.disable_msix_handshake)) {
- reg = &ha->iobase->isp24;
- spin_lock_irqsave(&ha->hardware_lock, flags);
- WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
- }
+ reg = &ha->iobase->isp24;
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
- queue_work(ha->wq, &qpair->q_work);
+ queue_work_on(smp_processor_id(), ha->wq, &qpair->q_work);
return IRQ_HANDLED;
}
@@ -3437,6 +3924,7 @@
{ "rsp_q", qla24xx_msix_rsp_q },
{ "atio_q", qla83xx_msix_atio_q },
{ "qpair_multiq", qla2xxx_msix_rsp_q },
+ { "qpair_multiq_hs", qla2xxx_msix_rsp_q_hs },
};
static const struct qla_init_msix_entry qla82xx_msix_entries[] = {
@@ -3670,6 +4158,8 @@
ql_dbg(ql_dbg_init, vha, 0x0125,
"INTa mode: Enabled.\n");
ha->flags.mr_intr_valid = 1;
+ /* Set max_qpair to 0, as MSI-X and MSI in not enabled */
+ ha->max_qpairs = 0;
}
clear_risc_ints:
@@ -3677,7 +4167,7 @@
goto fail;
spin_lock_irq(&ha->hardware_lock);
- WRT_REG_WORD(®->isp.semaphore, 0);
+ wrt_reg_word(®->isp.semaphore, 0);
spin_unlock_irq(&ha->hardware_lock);
fail:
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 098388a..734745f 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
#include "qla_target.h"
@@ -59,6 +58,7 @@
{ MBC_IOCB_COMMAND_A64 },
{ MBC_GET_ADAPTER_LOOP_ID },
{ MBC_READ_SFP },
+ { MBC_SET_RNID_PARAMS },
{ MBC_GET_RNID_PARAMS },
{ MBC_GET_SET_ZIO_THRESHOLD },
};
@@ -106,7 +106,7 @@
uint8_t io_lock_on;
uint16_t command = 0;
uint16_t *iptr;
- uint16_t __iomem *optr;
+ __le16 __iomem *optr;
uint32_t cnt;
uint32_t mboxes;
unsigned long wait_time;
@@ -117,10 +117,9 @@
ql_dbg(ql_dbg_mbx, vha, 0x1000, "Entered %s.\n", __func__);
- if (ha->pdev->error_state > pci_channel_io_frozen) {
+ if (ha->pdev->error_state == pci_channel_io_perm_failure) {
ql_log(ql_log_warn, vha, 0x1001,
- "error_state is greater than pci_channel_io_frozen, "
- "exiting.\n");
+ "PCI channel failed permanently, exiting.\n");
return QLA_FUNCTION_TIMEOUT;
}
@@ -209,11 +208,11 @@
/* Load mailbox registers. */
if (IS_P3P_TYPE(ha))
- optr = (uint16_t __iomem *)®->isp82.mailbox_in[0];
+ optr = ®->isp82.mailbox_in[0];
else if (IS_FWI2_CAPABLE(ha) && !(IS_P3P_TYPE(ha)))
- optr = (uint16_t __iomem *)®->isp24.mailbox0;
+ optr = ®->isp24.mailbox0;
else
- optr = (uint16_t __iomem *)MAILBOX_REG(ha, ®->isp, 0);
+ optr = MAILBOX_REG(ha, ®->isp, 0);
iptr = mcp->mb;
command = mcp->mb[0];
@@ -223,12 +222,11 @@
"Mailbox registers (OUT):\n");
for (cnt = 0; cnt < ha->mbx_count; cnt++) {
if (IS_QLA2200(ha) && cnt == 8)
- optr =
- (uint16_t __iomem *)MAILBOX_REG(ha, ®->isp, 8);
+ optr = MAILBOX_REG(ha, ®->isp, 8);
if (mboxes & BIT_0) {
ql_dbg(ql_dbg_mbx, vha, 0x1112,
"mbox[%d]<-0x%04x\n", cnt, *iptr);
- WRT_REG_WORD(optr, *iptr);
+ wrt_reg_word(optr, *iptr);
}
mboxes >>= 1;
@@ -254,11 +252,11 @@
set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
if (IS_P3P_TYPE(ha))
- WRT_REG_DWORD(®->isp82.hint, HINT_MBX_INT_PENDING);
+ wrt_reg_dword(®->isp82.hint, HINT_MBX_INT_PENDING);
else if (IS_FWI2_CAPABLE(ha))
- WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT);
+ wrt_reg_dword(®->isp24.hccr, HCCRX_SET_HOST_INT);
else
- WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT);
+ wrt_reg_word(®->isp.hccr, HCCR_SET_HOST_INT);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
wait_time = jiffies;
@@ -301,7 +299,7 @@
"Cmd=%x Polling Mode.\n", command);
if (IS_P3P_TYPE(ha)) {
- if (RD_REG_DWORD(®->isp82.hint) &
+ if (rd_reg_dword(®->isp82.hint) &
HINT_MBX_INT_PENDING) {
ha->flags.mbox_busy = 0;
spin_unlock_irqrestore(&ha->hardware_lock,
@@ -312,11 +310,11 @@
rval = QLA_FUNCTION_TIMEOUT;
goto premature_exit;
}
- WRT_REG_DWORD(®->isp82.hint, HINT_MBX_INT_PENDING);
+ wrt_reg_dword(®->isp82.hint, HINT_MBX_INT_PENDING);
} else if (IS_FWI2_CAPABLE(ha))
- WRT_REG_DWORD(®->isp24.hccr, HCCRX_SET_HOST_INT);
+ wrt_reg_dword(®->isp24.hccr, HCCRX_SET_HOST_INT);
else
- WRT_REG_WORD(®->isp.hccr, HCCR_SET_HOST_INT);
+ wrt_reg_word(®->isp.hccr, HCCR_SET_HOST_INT);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
wait_time = jiffies + mcp->tov * HZ; /* wait at most tov secs */
@@ -406,14 +404,14 @@
uint16_t w;
if (IS_FWI2_CAPABLE(ha)) {
- mb[0] = RD_REG_WORD(®->isp24.mailbox0);
- mb[1] = RD_REG_WORD(®->isp24.mailbox1);
- mb[2] = RD_REG_WORD(®->isp24.mailbox2);
- mb[3] = RD_REG_WORD(®->isp24.mailbox3);
- mb[7] = RD_REG_WORD(®->isp24.mailbox7);
- ictrl = RD_REG_DWORD(®->isp24.ictrl);
- host_status = RD_REG_DWORD(®->isp24.host_status);
- hccr = RD_REG_DWORD(®->isp24.hccr);
+ mb[0] = rd_reg_word(®->isp24.mailbox0);
+ mb[1] = rd_reg_word(®->isp24.mailbox1);
+ mb[2] = rd_reg_word(®->isp24.mailbox2);
+ mb[3] = rd_reg_word(®->isp24.mailbox3);
+ mb[7] = rd_reg_word(®->isp24.mailbox7);
+ ictrl = rd_reg_dword(®->isp24.ictrl);
+ host_status = rd_reg_dword(®->isp24.host_status);
+ hccr = rd_reg_dword(®->isp24.hccr);
ql_log(ql_log_warn, vha, 0xd04c,
"MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx "
@@ -423,7 +421,7 @@
} else {
mb[0] = RD_MAILBOX_REG(ha, ®->isp, 0);
- ictrl = RD_REG_WORD(®->isp.ictrl);
+ ictrl = rd_reg_word(®->isp.ictrl);
ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119,
"MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx "
"mb[0]=0x%x\n", command, ictrl, jiffies, mb[0]);
@@ -455,7 +453,7 @@
* a dump
*/
if (mcp->mb[0] != MBC_GEN_SYSTEM_ERROR)
- ha->isp_ops->fw_dump(vha, 0);
+ qla2xxx_dump_fw(vha);
rval = QLA_FUNCTION_TIMEOUT;
}
}
@@ -566,15 +564,15 @@
if (IS_FWI2_CAPABLE(ha) && !(IS_P3P_TYPE(ha))) {
ql_dbg(ql_dbg_mbx, vha, 0x1198,
"host_status=%#x intr_ctrl=%#x intr_status=%#x\n",
- RD_REG_DWORD(®->isp24.host_status),
- RD_REG_DWORD(®->isp24.ictrl),
- RD_REG_DWORD(®->isp24.istatus));
+ rd_reg_dword(®->isp24.host_status),
+ rd_reg_dword(®->isp24.ictrl),
+ rd_reg_dword(®->isp24.istatus));
} else {
ql_dbg(ql_dbg_mbx, vha, 0x1206,
"ctrl_status=%#x ictrl=%#x istatus=%#x\n",
- RD_REG_WORD(®->isp.ctrl_status),
- RD_REG_WORD(®->isp.ictrl),
- RD_REG_WORD(®->isp.istatus));
+ rd_reg_word(®->isp.ctrl_status),
+ rd_reg_word(®->isp.ictrl),
+ rd_reg_word(®->isp.istatus));
}
} else {
ql_dbg(ql_dbg_mbx, base_vha, 0x1021, "Done %s.\n", __func__);
@@ -635,30 +633,7 @@
return rval;
}
-#define EXTENDED_BB_CREDITS BIT_0
#define NVME_ENABLE_FLAG BIT_3
-static inline uint16_t qla25xx_set_sfp_lr_dist(struct qla_hw_data *ha)
-{
- uint16_t mb4 = BIT_0;
-
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
- mb4 |= ha->long_range_distance << LR_DIST_FW_POS;
-
- return mb4;
-}
-
-static inline uint16_t qla25xx_set_nvr_lr_dist(struct qla_hw_data *ha)
-{
- uint16_t mb4 = BIT_0;
-
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
- struct nvram_81xx *nv = ha->nvram;
-
- mb4 |= LR_DIST_FW_FIELD(nv->enhanced_features);
- }
-
- return mb4;
-}
/*
* qla2x00_execute_fw
@@ -682,10 +657,14 @@
struct qla_hw_data *ha = vha->hw;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ u8 semaphore = 0;
+#define EXE_FW_FORCE_SEMAPHORE BIT_7
+ u8 retry = 3;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1025,
"Entered %s.\n", __func__);
+again:
mcp->mb[0] = MBC_EXECUTE_FIRMWARE;
mcp->out_mb = MBX_0;
mcp->in_mb = MBX_0;
@@ -695,25 +674,13 @@
mcp->mb[3] = 0;
mcp->mb[4] = 0;
mcp->mb[11] = 0;
- ha->flags.using_lr_setting = 0;
- if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
- IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
- if (ql2xautodetectsfp) {
- if (ha->flags.detected_lr_sfp) {
- mcp->mb[4] |=
- qla25xx_set_sfp_lr_dist(ha);
- ha->flags.using_lr_setting = 1;
- }
- } else {
- struct nvram_81xx *nv = ha->nvram;
- /* set LR distance if specified in nvram */
- if (nv->enhanced_features &
- NEF_LR_DIST_ENABLE) {
- mcp->mb[4] |=
- qla25xx_set_nvr_lr_dist(ha);
- ha->flags.using_lr_setting = 1;
- }
- }
+
+ /* Enable BPM? */
+ if (ha->flags.lr_detected) {
+ mcp->mb[4] = BIT_0;
+ if (IS_BPM_RANGE_CAPABLE(ha))
+ mcp->mb[4] |=
+ ha->lr_distance << LR_DIST_FW_POS;
}
if (ql2xnvmeenable && (IS_QLA27XX(ha) || IS_QLA28XX(ha)))
@@ -739,6 +706,9 @@
if (ha->flags.exchoffld_enabled)
mcp->mb[4] |= ENABLE_EXCHANGE_OFFLD;
+ if (semaphore)
+ mcp->mb[11] |= EXE_FW_FORCE_SEMAPHORE;
+
mcp->out_mb |= MBX_4 | MBX_3 | MBX_2 | MBX_1 | MBX_11;
mcp->in_mb |= MBX_3 | MBX_2 | MBX_1;
} else {
@@ -755,6 +725,15 @@
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
+ if (IS_QLA28XX(ha) && rval == QLA_COMMAND_ERROR &&
+ mcp->mb[1] == 0x27 && retry) {
+ semaphore = 1;
+ retry--;
+ ql_dbg(ql_dbg_async, vha, 0x1026,
+ "Exe FW: force semaphore.\n");
+ goto again;
+ }
+
ql_dbg(ql_dbg_mbx, vha, 0x1026,
"Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
return rval;
@@ -865,7 +844,7 @@
* Context:
* Kernel context.
*/
-#define CONFIG_XLOGINS_MEM 0x3
+#define CONFIG_XLOGINS_MEM 0x9
int
qla_set_exlogin_mem_cfg(scsi_qla_host_t *vha, dma_addr_t phys_addr)
{
@@ -892,8 +871,9 @@
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
- /*EMPTY*/
- ql_dbg(ql_dbg_mbx, vha, 0x111b, "Failed=%x.\n", rval);
+ ql_dbg(ql_dbg_mbx, vha, 0x111b,
+ "EXlogin Failed=%x. MB0=%x MB11=%x\n",
+ rval, mcp->mb[0], mcp->mb[11]);
} else {
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c,
"Done %s.\n", __func__);
@@ -1112,6 +1092,14 @@
"%s: FC-NVMe is Enabled (0x%x)\n",
__func__, ha->fw_attributes_h);
}
+
+ /* BIT_13 of Extended FW Attributes informs about NVMe2 support */
+ if (ha->fw_attributes_ext[0] & FW_ATTR_EXT0_NVME2) {
+ ql_log(ql_log_info, vha, 0xd302,
+ "Firmware supports NVMe2 0x%x\n",
+ ha->fw_attributes_ext[0]);
+ vha->flags.nvme2_enabled = 1;
+ }
}
if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
@@ -1129,11 +1117,29 @@
ha->fw_ddr_ram_start = (mcp->mb[23] << 16) | mcp->mb[22];
ha->fw_ddr_ram_end = (mcp->mb[25] << 16) | mcp->mb[24];
if (IS_QLA28XX(ha)) {
- if (mcp->mb[16] & BIT_10) {
- ql_log(ql_log_info, vha, 0xffff,
- "FW support secure flash updates\n");
+ if (mcp->mb[16] & BIT_10)
ha->flags.secure_fw = 1;
- }
+
+ ql_log(ql_log_info, vha, 0xffff,
+ "Secure Flash Update in FW: %s\n",
+ (ha->flags.secure_fw) ? "Supported" :
+ "Not Supported");
+ }
+
+ if (ha->flags.scm_supported_a &&
+ (ha->fw_attributes_ext[0] & FW_ATTR_EXT0_SCM_SUPPORTED)) {
+ ha->flags.scm_supported_f = 1;
+ ha->sf_init_cb->flags |= cpu_to_le16(BIT_13);
+ }
+ ql_log(ql_log_info, vha, 0x11a3, "SCM in FW: %s\n",
+ (ha->flags.scm_supported_f) ? "Supported" :
+ "Not Supported");
+
+ if (vha->flags.nvme2_enabled) {
+ /* set BIT_15 of special feature control block for SLER */
+ ha->sf_init_cb->flags |= cpu_to_le16(BIT_15);
+ /* set BIT_14 of special feature control block for PI CTRL*/
+ ha->sf_init_cb->flags |= cpu_to_le16(BIT_14);
}
}
@@ -1397,17 +1403,20 @@
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ if (!vha->hw->flags.fw_started)
+ return QLA_INVALID_COMMAND;
+
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1038,
"Entered %s.\n", __func__);
mcp->mb[0] = MBC_IOCB_COMMAND_A64;
mcp->mb[1] = 0;
- mcp->mb[2] = MSW(phys_addr);
- mcp->mb[3] = LSW(phys_addr);
+ mcp->mb[2] = MSW(LSD(phys_addr));
+ mcp->mb[3] = LSW(LSD(phys_addr));
mcp->mb[6] = MSW(MSD(phys_addr));
mcp->mb[7] = LSW(MSD(phys_addr));
mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
- mcp->in_mb = MBX_2|MBX_0;
+ mcp->in_mb = MBX_1|MBX_0;
mcp->tov = tov;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
@@ -1416,13 +1425,14 @@
/*EMPTY*/
ql_dbg(ql_dbg_mbx, vha, 0x1039, "Failed=%x.\n", rval);
} else {
- sts_entry_t *sts_entry = (sts_entry_t *) buffer;
+ sts_entry_t *sts_entry = buffer;
/* Mask reserved bits. */
sts_entry->entry_status &=
IS_FWI2_CAPABLE(vha->hw) ? RF_MASK_24XX : RF_MASK;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103a,
- "Done %s.\n", __func__);
+ "Done %s (status=%x).\n", __func__,
+ sts_entry->entry_status);
}
return rval;
@@ -1467,7 +1477,7 @@
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103b,
"Entered %s.\n", __func__);
- if (vha->flags.qpairs_available && sp->qpair)
+ if (sp->qpair)
req = sp->qpair->req;
else
req = vha->req;
@@ -1641,7 +1651,8 @@
if (IS_FWI2_CAPABLE(vha->hw))
mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16;
if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw))
- mcp->in_mb |= MBX_15;
+ mcp->in_mb |= MBX_15|MBX_21|MBX_22|MBX_23;
+
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
@@ -1694,8 +1705,22 @@
}
}
- if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw))
+ if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) {
vha->bbcr = mcp->mb[15];
+ if (mcp->mb[7] & SCM_EDC_ACC_RECEIVED) {
+ ql_log(ql_log_info, vha, 0x11a4,
+ "SCM: EDC ELS completed, flags 0x%x\n",
+ mcp->mb[21]);
+ }
+ if (mcp->mb[7] & SCM_RDF_ACC_RECEIVED) {
+ vha->hw->flags.scm_enabled = 1;
+ vha->scm_fabric_connection_flags |=
+ SCM_FLAG_RDF_COMPLETED;
+ ql_log(ql_log_info, vha, 0x11a5,
+ "SCM: RDF ELS completed, flags 0x%x\n",
+ mcp->mb[23]);
+ }
+ }
}
return rval;
@@ -1808,6 +1833,17 @@
mcp->mb[14] = sizeof(*ha->ex_init_cb);
mcp->out_mb |= MBX_14|MBX_13|MBX_12|MBX_11|MBX_10;
}
+
+ if (ha->flags.scm_supported_f || vha->flags.nvme2_enabled) {
+ mcp->mb[1] |= BIT_1;
+ mcp->mb[16] = MSW(ha->sf_init_cb_dma);
+ mcp->mb[17] = LSW(ha->sf_init_cb_dma);
+ mcp->mb[18] = MSW(MSD(ha->sf_init_cb_dma));
+ mcp->mb[19] = LSW(MSD(ha->sf_init_cb_dma));
+ mcp->mb[15] = sizeof(*ha->sf_init_cb);
+ mcp->out_mb |= MBX_19|MBX_18|MBX_17|MBX_16|MBX_15;
+ }
+
/* 1 and 2 should normally be captured. */
mcp->in_mb = MBX_2|MBX_1|MBX_0;
if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
@@ -2037,6 +2073,57 @@
return rval;
}
+int
+qla24xx_get_port_database(scsi_qla_host_t *vha, u16 nport_handle,
+ struct port_database_24xx *pdb)
+{
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ dma_addr_t pdb_dma;
+ int rval;
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1115,
+ "Entered %s.\n", __func__);
+
+ memset(pdb, 0, sizeof(*pdb));
+
+ pdb_dma = dma_map_single(&vha->hw->pdev->dev, pdb,
+ sizeof(*pdb), DMA_FROM_DEVICE);
+ if (!pdb_dma) {
+ ql_log(ql_log_warn, vha, 0x1116, "Failed to map dma buffer.\n");
+ return QLA_MEMORY_ALLOC_FAILED;
+ }
+
+ mcp->mb[0] = MBC_GET_PORT_DATABASE;
+ mcp->mb[1] = nport_handle;
+ mcp->mb[2] = MSW(LSD(pdb_dma));
+ mcp->mb[3] = LSW(LSD(pdb_dma));
+ mcp->mb[6] = MSW(MSD(pdb_dma));
+ mcp->mb[7] = LSW(MSD(pdb_dma));
+ mcp->mb[9] = 0;
+ mcp->mb[10] = 0;
+ mcp->out_mb = MBX_10|MBX_9|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_1|MBX_0;
+ mcp->buf_size = sizeof(*pdb);
+ mcp->flags = MBX_DMA_IN;
+ mcp->tov = vha->hw->login_timeout * 2;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x111a,
+ "Failed=%x mb[0]=%x mb[1]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1]);
+ } else {
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x111b,
+ "Done %s.\n", __func__);
+ }
+
+ dma_unmap_single(&vha->hw->pdev->dev, pdb_dma,
+ sizeof(*pdb), DMA_FROM_DEVICE);
+
+ return rval;
+}
+
/*
* qla2x00_get_firmware_state
* Get adapter firmware state.
@@ -2376,7 +2463,7 @@
lg->entry_type = LOGINOUT_PORT_IOCB_TYPE;
lg->entry_count = 1;
- lg->handle = MAKE_HANDLE(req->id, lg->handle);
+ lg->handle = make_handle(req->id, lg->handle);
lg->nport_handle = cpu_to_le16(loop_id);
lg->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI);
if (opt & BIT_0)
@@ -2646,7 +2733,7 @@
req = vha->req;
lg->entry_type = LOGINOUT_PORT_IOCB_TYPE;
lg->entry_count = 1;
- lg->handle = MAKE_HANDLE(req->id, lg->handle);
+ lg->handle = make_handle(req->id, lg->handle);
lg->nport_handle = cpu_to_le16(loop_id);
lg->control_flags =
cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO|
@@ -2993,7 +3080,7 @@
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- uint32_t *iter = (void *)stats;
+ uint32_t *iter = (uint32_t *)stats;
ushort dwords = offsetof(typeof(*stats), link_up_cnt)/sizeof(*iter);
struct qla_hw_data *ha = vha->hw;
@@ -3052,20 +3139,21 @@
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- uint32_t *iter, dwords;
+ uint32_t *iter = (uint32_t *)stats;
+ ushort dwords = sizeof(*stats)/sizeof(*iter);
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1088,
"Entered %s.\n", __func__);
memset(&mc, 0, sizeof(mc));
mc.mb[0] = MBC_GET_LINK_PRIV_STATS;
- mc.mb[2] = MSW(stats_dma);
- mc.mb[3] = LSW(stats_dma);
+ mc.mb[2] = MSW(LSD(stats_dma));
+ mc.mb[3] = LSW(LSD(stats_dma));
mc.mb[6] = MSW(MSD(stats_dma));
mc.mb[7] = LSW(MSD(stats_dma));
- mc.mb[8] = sizeof(struct link_statistics) / 4;
- mc.mb[9] = cpu_to_le16(vha->vp_idx);
- mc.mb[10] = cpu_to_le16(options);
+ mc.mb[8] = dwords;
+ mc.mb[9] = vha->vp_idx;
+ mc.mb[10] = options;
rval = qla24xx_send_mb_cmd(vha, &mc);
@@ -3078,8 +3166,6 @@
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108a,
"Done %s.\n", __func__);
/* Re-endianize - firmware data is le32. */
- dwords = sizeof(struct link_statistics) / 4;
- iter = &stats->link_fail_cnt;
for ( ; dwords--; iter++)
le32_to_cpus(iter);
}
@@ -3137,9 +3223,9 @@
abt->entry_type = ABORT_IOCB_TYPE;
abt->entry_count = 1;
- abt->handle = MAKE_HANDLE(req->id, abt->handle);
+ abt->handle = make_handle(req->id, abt->handle);
abt->nport_handle = cpu_to_le16(fcport->loop_id);
- abt->handle_to_abort = MAKE_HANDLE(req->id, handle);
+ abt->handle_to_abort = make_handle(req->id, handle);
abt->port_id[0] = fcport->d_id.b.al_pa;
abt->port_id[1] = fcport->d_id.b.area;
abt->port_id[2] = fcport->d_id.b.domain;
@@ -3160,7 +3246,7 @@
ql_dbg(ql_dbg_mbx, vha, 0x1090,
"Failed to complete IOCB -- completion status (%x).\n",
le16_to_cpu(abt->nport_handle));
- if (abt->nport_handle == CS_IOCB_ERROR)
+ if (abt->nport_handle == cpu_to_le16(CS_IOCB_ERROR))
rval = QLA_FUNCTION_PARAMETER_ERROR;
else
rval = QLA_FUNCTION_FAILED;
@@ -3216,7 +3302,7 @@
tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE;
tsk->p.tsk.entry_count = 1;
- tsk->p.tsk.handle = MAKE_HANDLE(req->id, tsk->p.tsk.handle);
+ tsk->p.tsk.handle = make_handle(req->id, tsk->p.tsk.handle);
tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id);
tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
tsk->p.tsk.control_flags = cpu_to_le32(type);
@@ -3880,20 +3966,41 @@
fcport->scan_state = QLA_FCPORT_SCAN;
fcport->n2n_flag = 0;
}
+ id.b24 = 0;
+ if (wwn_to_u64(vha->port_name) >
+ wwn_to_u64(rptid_entry->u.f1.port_name)) {
+ vha->d_id.b24 = 0;
+ vha->d_id.b.al_pa = 1;
+ ha->flags.n2n_bigger = 1;
+
+ id.b.al_pa = 2;
+ ql_dbg(ql_dbg_async, vha, 0x5075,
+ "Format 1: assign local id %x remote id %x\n",
+ vha->d_id.b24, id.b24);
+ } else {
+ ql_dbg(ql_dbg_async, vha, 0x5075,
+ "Format 1: Remote login - Waiting for WWPN %8phC.\n",
+ rptid_entry->u.f1.port_name);
+ ha->flags.n2n_bigger = 0;
+ }
fcport = qla2x00_find_fcport_by_wwpn(vha,
rptid_entry->u.f1.port_name, 1);
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
if (fcport) {
fcport->plogi_nack_done_deadline = jiffies + HZ;
- fcport->dm_login_expire = jiffies + 2*HZ;
+ fcport->dm_login_expire = jiffies +
+ QLA_N2N_WAIT_TIME * HZ;
fcport->scan_state = QLA_FCPORT_FOUND;
fcport->n2n_flag = 1;
fcport->keep_nport_handle = 1;
- fcport->fc4_type = FS_FC4TYPE_FCP;
- if (vha->flags.nvme_enabled)
- fcport->fc4_type |= FS_FC4TYPE_NVME;
+
+ if (wwn_to_u64(vha->port_name) >
+ wwn_to_u64(fcport->port_name)) {
+ fcport->d_id = id;
+ }
switch (fcport->disc_state) {
case DSC_DELETED:
@@ -3907,25 +4014,6 @@
break;
}
} else {
- id.b24 = 0;
- if (wwn_to_u64(vha->port_name) >
- wwn_to_u64(rptid_entry->u.f1.port_name)) {
- vha->d_id.b24 = 0;
- vha->d_id.b.al_pa = 1;
- ha->flags.n2n_bigger = 1;
- ha->flags.n2n_ae = 0;
-
- id.b.al_pa = 2;
- ql_dbg(ql_dbg_async, vha, 0x5075,
- "Format 1: assign local id %x remote id %x\n",
- vha->d_id.b24, id.b24);
- } else {
- ql_dbg(ql_dbg_async, vha, 0x5075,
- "Format 1: Remote login - Waiting for WWPN %8phC.\n",
- rptid_entry->u.f1.port_name);
- ha->flags.n2n_bigger = 0;
- ha->flags.n2n_ae = 1;
- }
qla24xx_post_newsess_work(vha, &id,
rptid_entry->u.f1.port_name,
rptid_entry->u.f1.node_name,
@@ -4187,7 +4275,8 @@
if (MSW(addr) || IS_FWI2_CAPABLE(vha->hw)) {
mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED;
mcp->mb[8] = MSW(addr);
- mcp->out_mb = MBX_8|MBX_0;
+ mcp->mb[10] = 0;
+ mcp->out_mb = MBX_10|MBX_8|MBX_0;
} else {
mcp->mb[0] = MBC_DUMP_RISC_RAM;
mcp->out_mb = MBX_0;
@@ -4379,9 +4468,9 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!(req->options & BIT_0)) {
- WRT_REG_DWORD(req->req_q_in, 0);
+ wrt_reg_dword(req->req_q_in, 0);
if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
- WRT_REG_DWORD(req->req_q_out, 0);
+ wrt_reg_dword(req->req_q_out, 0);
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -4450,9 +4539,9 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!(rsp->options & BIT_0)) {
- WRT_REG_DWORD(rsp->rsp_q_out, 0);
+ wrt_reg_dword(rsp->rsp_q_out, 0);
if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
- WRT_REG_DWORD(rsp->rsp_q_in, 0);
+ wrt_reg_dword(rsp->rsp_q_in, 0);
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -4679,7 +4768,7 @@
mbx_cmd_t *mcp = &mc;
int i;
int len;
- uint16_t *str;
+ __le16 *str;
struct qla_hw_data *ha = vha->hw;
if (!IS_P3P_TYPE(ha))
@@ -4688,14 +4777,14 @@
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x117b,
"Entered %s.\n", __func__);
- str = (void *)version;
+ str = (__force __le16 *)version;
len = strlen(version);
mcp->mb[0] = MBC_SET_RNID_PARAMS;
mcp->mb[1] = RNID_TYPE_SET_VERSION << 8;
mcp->out_mb = MBX_1|MBX_0;
for (i = 4; i < 16 && len; i++, str++, len -= 2) {
- mcp->mb[i] = cpu_to_le16p(str);
+ mcp->mb[i] = le16_to_cpup(str);
mcp->out_mb |= 1<<i;
}
for (; i < 16; i++) {
@@ -4813,12 +4902,77 @@
"Done %s.\n", __func__);
bp = (uint32_t *) buf;
for (i = 0; i < (bufsiz-4)/4; i++, bp++)
- *bp = le32_to_cpu(*bp);
+ *bp = le32_to_cpu((__force __le32)*bp);
}
return rval;
}
+#define PUREX_CMD_COUNT 2
+int
+qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ uint8_t *els_cmd_map;
+ dma_addr_t els_cmd_map_dma;
+ uint8_t cmd_opcode[PUREX_CMD_COUNT];
+ uint8_t i, index, purex_bit;
+ struct qla_hw_data *ha = vha->hw;
+
+ if (!IS_QLA25XX(ha) && !IS_QLA2031(ha) &&
+ !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+ return QLA_SUCCESS;
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1197,
+ "Entered %s.\n", __func__);
+
+ els_cmd_map = dma_alloc_coherent(&ha->pdev->dev, ELS_CMD_MAP_SIZE,
+ &els_cmd_map_dma, GFP_KERNEL);
+ if (!els_cmd_map) {
+ ql_log(ql_log_warn, vha, 0x7101,
+ "Failed to allocate RDP els command param.\n");
+ return QLA_MEMORY_ALLOC_FAILED;
+ }
+
+ /* List of Purex ELS */
+ cmd_opcode[0] = ELS_FPIN;
+ cmd_opcode[1] = ELS_RDP;
+
+ for (i = 0; i < PUREX_CMD_COUNT; i++) {
+ index = cmd_opcode[i] / 8;
+ purex_bit = cmd_opcode[i] % 8;
+ els_cmd_map[index] |= 1 << purex_bit;
+ }
+
+ mcp->mb[0] = MBC_SET_RNID_PARAMS;
+ mcp->mb[1] = RNID_TYPE_ELS_CMD << 8;
+ mcp->mb[2] = MSW(LSD(els_cmd_map_dma));
+ mcp->mb[3] = LSW(LSD(els_cmd_map_dma));
+ mcp->mb[6] = MSW(MSD(els_cmd_map_dma));
+ mcp->mb[7] = LSW(MSD(els_cmd_map_dma));
+ mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_1|MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = MBX_DMA_OUT;
+ mcp->buf_size = ELS_CMD_MAP_SIZE;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x118d,
+ "Failed=%x (%x,%x).\n", rval, mcp->mb[0], mcp->mb[1]);
+ } else {
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x118c,
+ "Done %s.\n", __func__);
+ }
+
+ dma_free_coherent(&ha->pdev->dev, ELS_CMD_MAP_SIZE,
+ els_cmd_map, els_cmd_map_dma);
+
+ return rval;
+}
+
static int
qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp)
{
@@ -4872,8 +5026,8 @@
mcp->mb[0] = MBC_READ_SFP;
mcp->mb[1] = dev;
- mcp->mb[2] = MSW(sfp_dma);
- mcp->mb[3] = LSW(sfp_dma);
+ mcp->mb[2] = MSW(LSD(sfp_dma));
+ mcp->mb[3] = LSW(LSD(sfp_dma));
mcp->mb[6] = MSW(MSD(sfp_dma));
mcp->mb[7] = LSW(MSD(sfp_dma));
mcp->mb[8] = len;
@@ -4926,8 +5080,8 @@
mcp->mb[0] = MBC_WRITE_SFP;
mcp->mb[1] = dev;
- mcp->mb[2] = MSW(sfp_dma);
- mcp->mb[3] = LSW(sfp_dma);
+ mcp->mb[2] = MSW(LSD(sfp_dma));
+ mcp->mb[3] = LSW(LSD(sfp_dma));
mcp->mb[6] = MSW(MSD(sfp_dma));
mcp->mb[7] = LSW(MSD(sfp_dma));
mcp->mb[8] = len;
@@ -5048,7 +5202,7 @@
mcp->mb[8] = MSW(risc_addr);
mcp->out_mb = MBX_8|MBX_1|MBX_0;
mcp->in_mb = MBX_3|MBX_2|MBX_0;
- mcp->tov = 30;
+ mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
@@ -5162,10 +5316,11 @@
mcp->out_mb |= MBX_2;
mcp->in_mb = MBX_0;
- if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) ||
- IS_CNA_CAPABLE(ha) || IS_QLA2031(ha))
+ if (IS_CNA_CAPABLE(ha) || IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) ||
+ IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
mcp->in_mb |= MBX_1;
- if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha))
+ if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha))
mcp->in_mb |= MBX_3;
mcp->tov = MBX_TOV_SECONDS;
@@ -5235,7 +5390,7 @@
mcp->mb[8] = MSW(risc_addr);
mcp->out_mb = MBX_8|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_1|MBX_0;
- mcp->tov = 30;
+ mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
@@ -5267,18 +5422,18 @@
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
/* Write the MBC data to the registers */
- WRT_REG_WORD(®->mailbox0, MBC_WRITE_MPI_REGISTER);
- WRT_REG_WORD(®->mailbox1, mb[0]);
- WRT_REG_WORD(®->mailbox2, mb[1]);
- WRT_REG_WORD(®->mailbox3, mb[2]);
- WRT_REG_WORD(®->mailbox4, mb[3]);
+ wrt_reg_word(®->mailbox0, MBC_WRITE_MPI_REGISTER);
+ wrt_reg_word(®->mailbox1, mb[0]);
+ wrt_reg_word(®->mailbox2, mb[1]);
+ wrt_reg_word(®->mailbox3, mb[2]);
+ wrt_reg_word(®->mailbox4, mb[3]);
- WRT_REG_DWORD(®->hccr, HCCRX_SET_HOST_INT);
+ wrt_reg_dword(®->hccr, HCCRX_SET_HOST_INT);
/* Poll for MBC interrupt */
for (timer = 6000000; timer; timer--) {
/* Check for pending interrupts. */
- stat = RD_REG_DWORD(®->host_status);
+ stat = rd_reg_dword(®->host_status);
if (stat & HSRX_RISC_INT) {
stat &= 0xff;
@@ -5286,10 +5441,10 @@
stat == 0x10 || stat == 0x11) {
set_bit(MBX_INTERRUPT,
&ha->mbx_cmd_flags);
- mb0 = RD_REG_WORD(®->mailbox0);
- WRT_REG_DWORD(®->hccr,
+ mb0 = rd_reg_word(®->mailbox0);
+ wrt_reg_dword(®->hccr,
HCCRX_CLR_RISC_INT);
- RD_REG_DWORD(®->hccr);
+ rd_reg_dword(®->hccr);
break;
}
}
@@ -5399,6 +5554,15 @@
ql_dbg(ql_dbg_mbx, vha, 0x1107,
"Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
} else {
+ if (mcp->mb[1] != 0x7)
+ ha->link_data_rate = mcp->mb[1];
+
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ if (mcp->mb[4] & BIT_0)
+ ql_log(ql_log_info, vha, 0x11a2,
+ "FEC=enabled (data rate).\n");
+ }
+
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108,
"Done %s.\n", __func__);
if (mcp->mb[1] != 0x7)
@@ -5498,7 +5662,7 @@
mcp->mb[9] = vha->vp_idx;
mcp->out_mb = MBX_9|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_4|MBX_3|MBX_1|MBX_0;
- mcp->tov = 30;
+ mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (mb != NULL) {
@@ -5585,7 +5749,7 @@
mcp->out_mb = MBX_1|MBX_0;
mcp->in_mb = MBX_0;
- mcp->tov = 30;
+ mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
@@ -5620,7 +5784,7 @@
mcp->out_mb = MBX_1|MBX_0;
mcp->in_mb = MBX_0;
- mcp->tov = 30;
+ mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
@@ -5812,7 +5976,7 @@
if (IS_QLA8031(ha))
mcp->out_mb |= MBX_6|MBX_5|MBX_4|MBX_3;
mcp->in_mb = MBX_0;
- mcp->tov = 30;
+ mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
@@ -5848,7 +6012,7 @@
mcp->in_mb = MBX_2|MBX_1|MBX_0;
if (IS_QLA8031(ha))
mcp->in_mb |= MBX_6|MBX_5|MBX_4|MBX_3;
- mcp->tov = 30;
+ mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
@@ -6058,7 +6222,7 @@
ql_dbg(ql_dbg_mbx, vha, 0x1144,
"Failed=%x mb[0]=%x mb[1]=%x.\n",
rval, mcp->mb[0], mcp->mb[1]);
- ha->isp_ops->fw_dump(vha, 0);
+ qla2xxx_dump_fw(vha);
} else {
ql_dbg(ql_dbg_mbx, vha, 0x1145, "Done %s.\n", __func__);
}
@@ -6103,7 +6267,7 @@
"Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x mb[3]=%x mb[4]=%x.\n",
rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3],
mcp->mb[4]);
- ha->isp_ops->fw_dump(vha, 0);
+ qla2xxx_dump_fw(vha);
} else {
if (subcode & BIT_5)
*sector_size = mcp->mb[1];
@@ -6317,13 +6481,13 @@
memset(&mc, 0, sizeof(mc));
mc.mb[0] = MBC_GET_PORT_DATABASE;
- mc.mb[1] = cpu_to_le16(fcport->loop_id);
+ mc.mb[1] = fcport->loop_id;
mc.mb[2] = MSW(pd_dma);
mc.mb[3] = LSW(pd_dma);
mc.mb[6] = MSW(MSD(pd_dma));
mc.mb[7] = LSW(MSD(pd_dma));
- mc.mb[9] = cpu_to_le16(vha->vp_idx);
- mc.mb[10] = cpu_to_le16((uint16_t)opt);
+ mc.mb[9] = vha->vp_idx;
+ mc.mb[10] = opt;
rval = qla24xx_send_mb_cmd(vha, &mc);
if (rval != QLA_SUCCESS) {
@@ -6434,7 +6598,7 @@
mc.mb[6] = MSW(MSD(id_list_dma));
mc.mb[7] = LSW(MSD(id_list_dma));
mc.mb[8] = 0;
- mc.mb[9] = cpu_to_le16(vha->vp_idx);
+ mc.mb[9] = vha->vp_idx;
rval = qla24xx_send_mb_cmd(vha, &mc);
if (rval != QLA_SUCCESS) {
@@ -6460,8 +6624,8 @@
memset(mcp->mb, 0 , sizeof(mcp->mb));
mcp->mb[0] = MBC_GET_SET_ZIO_THRESHOLD;
- mcp->mb[1] = cpu_to_le16(1);
- mcp->mb[2] = cpu_to_le16(value);
+ mcp->mb[1] = 1;
+ mcp->mb[2] = value;
mcp->out_mb = MBX_2 | MBX_1 | MBX_0;
mcp->in_mb = MBX_2 | MBX_0;
mcp->tov = MBX_TOV_SECONDS;
@@ -6486,7 +6650,7 @@
memset(mcp->mb, 0, sizeof(mcp->mb));
mcp->mb[0] = MBC_GET_SET_ZIO_THRESHOLD;
- mcp->mb[1] = cpu_to_le16(0);
+ mcp->mb[1] = 0;
mcp->out_mb = MBX_1 | MBX_0;
mcp->in_mb = MBX_2 | MBX_0;
mcp->tov = MBX_TOV_SECONDS;
@@ -6680,3 +6844,60 @@
return rval;
}
+
+int
+ql26xx_led_config(scsi_qla_host_t *vha, uint16_t options, uint16_t *led)
+{
+ struct qla_hw_data *ha = vha->hw;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ int rval;
+
+ if (!IS_QLA2031(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+ return QLA_FUNCTION_FAILED;
+
+ ql_dbg(ql_dbg_mbx, vha, 0x7070, "Entered %s (options=%x).\n",
+ __func__, options);
+
+ mcp->mb[0] = MBC_SET_GET_FC_LED_CONFIG;
+ mcp->mb[1] = options;
+ mcp->out_mb = MBX_1|MBX_0;
+ mcp->in_mb = MBX_1|MBX_0;
+ if (options & BIT_0) {
+ if (options & BIT_1) {
+ mcp->mb[2] = led[2];
+ mcp->out_mb |= MBX_2;
+ }
+ if (options & BIT_2) {
+ mcp->mb[3] = led[0];
+ mcp->out_mb |= MBX_3;
+ }
+ if (options & BIT_3) {
+ mcp->mb[4] = led[1];
+ mcp->out_mb |= MBX_4;
+ }
+ } else {
+ mcp->in_mb |= MBX_4|MBX_3|MBX_2;
+ }
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+ if (rval) {
+ ql_dbg(ql_dbg_mbx, vha, 0x7071, "Failed %s %x (mb=%x,%x)\n",
+ __func__, rval, mcp->mb[0], mcp->mb[1]);
+ return rval;
+ }
+
+ if (options & BIT_0) {
+ ha->beacon_blink_led = 0;
+ ql_dbg(ql_dbg_mbx, vha, 0x7072, "Done %s\n", __func__);
+ } else {
+ led[2] = mcp->mb[2];
+ led[0] = mcp->mb[3];
+ led[1] = mcp->mb[4];
+ ql_dbg(ql_dbg_mbx, vha, 0x7073, "Done %s (led=%x,%x,%x)\n",
+ __func__, led[0], led[1], led[2]);
+ }
+
+ return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index eabc512..c7caf32 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
#include "qla_gbl.h"
@@ -147,7 +146,7 @@
"Marking port dead, loop_id=0x%04x : %x.\n",
fcport->loop_id, fcport->vha->vp_idx);
- qla2x00_mark_device_lost(vha, fcport, 0, 0);
+ qla2x00_mark_device_lost(vha, fcport, 0);
qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED);
}
}
@@ -167,7 +166,7 @@
list_for_each_entry(fcport, &vha->vp_fcports, list)
fcport->logout_on_delete = 0;
- qla2x00_mark_all_devices_lost(vha, 0);
+ qla2x00_mark_all_devices_lost(vha);
/* Remove port id from vp target map */
spin_lock_irqsave(&vha->hw->hardware_lock, flags);
@@ -327,7 +326,7 @@
*/
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
atomic_set(&vha->loop_state, LOOP_DOWN);
- qla2x00_mark_all_devices_lost(vha, 0);
+ qla2x00_mark_all_devices_lost(vha);
} else {
if (!atomic_read(&vha->loop_down_timer))
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
@@ -361,6 +360,13 @@
}
}
+ if (test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags)) {
+ if (atomic_read(&vha->loop_state) == LOOP_READY) {
+ qla24xx_process_purex_list(&vha->purex_list);
+ clear_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags);
+ }
+ }
+
if (test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags)) {
ql_dbg(ql_dbg_dpc, vha, 0x4016,
"FCPort update scheduled.\n");
@@ -509,6 +515,9 @@
vha->mgmt_svr_loop_id = qla2x00_reserve_mgmt_server_loop_id(vha);
vha->dpc_flags = 0L;
+ ha->dpc_active = 0;
+ set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
+ set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
/*
* To fix the issue of processing a parent's RSCN for the vport before
@@ -760,7 +769,7 @@
req->req_q_in = ®->isp25mq.req_q_in;
req->req_q_out = ®->isp25mq.req_q_out;
req->max_q_depth = ha->req_q_map[0]->max_q_depth;
- req->out_ptr = (void *)(req->ring + req->length);
+ req->out_ptr = (uint16_t *)(req->ring + req->length);
mutex_unlock(&ha->mq_lock);
ql_dbg(ql_dbg_multiq, base_vha, 0xc004,
"ring_ptr=%p ring_index=%d, "
@@ -798,11 +807,9 @@
{
unsigned long flags;
struct qla_qpair *qpair = container_of(work, struct qla_qpair, q_work);
- struct scsi_qla_host *vha;
- struct qla_hw_data *ha = qpair->hw;
+ struct scsi_qla_host *vha = qpair->vha;
spin_lock_irqsave(&qpair->qp_lock, flags);
- vha = pci_get_drvdata(ha->pdev);
qla24xx_process_response_queue(vha, qpair->rsp);
spin_unlock_irqrestore(&qpair->qp_lock, flags);
@@ -874,7 +881,7 @@
reg = ISP_QUE_REG(ha, que_id);
rsp->rsp_q_in = ®->isp25mq.rsp_q_in;
rsp->rsp_q_out = ®->isp25mq.rsp_q_out;
- rsp->in_ptr = (void *)(rsp->ring + rsp->length);
+ rsp->in_ptr = (uint16_t *)(rsp->ring + rsp->length);
mutex_unlock(&ha->mq_lock);
ql_dbg(ql_dbg_multiq, base_vha, 0xc00b,
"options=%x id=%d rsp_q_in=%p rsp_q_out=%p\n",
@@ -886,7 +893,8 @@
rsp->rsp_q_out);
ret = qla25xx_request_irq(ha, qpair, qpair->msix,
- QLA_MSIX_QPAIR_MULTIQ_RSP_Q);
+ ha->flags.disable_msix_handshake ?
+ QLA_MSIX_QPAIR_MULTIQ_RSP_Q : QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS);
if (ret)
goto que_failed;
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
index 605b59c..7178646 100644
--- a/drivers/scsi/qla2xxx/qla_mr.c
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
#include <linux/delay.h>
@@ -46,17 +45,16 @@
uint8_t io_lock_on;
uint16_t command = 0;
uint32_t *iptr;
- uint32_t __iomem *optr;
+ __le32 __iomem *optr;
uint32_t cnt;
uint32_t mboxes;
unsigned long wait_time;
struct qla_hw_data *ha = vha->hw;
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
- if (ha->pdev->error_state > pci_channel_io_frozen) {
+ if (ha->pdev->error_state == pci_channel_io_perm_failure) {
ql_log(ql_log_warn, vha, 0x115c,
- "error_state is greater than pci_channel_io_frozen, "
- "exiting.\n");
+ "PCI channel failed permanently, exiting.\n");
return QLA_FUNCTION_TIMEOUT;
}
@@ -110,7 +108,7 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
/* Load mailbox registers. */
- optr = (uint32_t __iomem *)®->ispfx00.mailbox0;
+ optr = ®->ispfx00.mailbox0;
iptr = mcp->mb;
command = mcp->mb[0];
@@ -118,7 +116,7 @@
for (cnt = 0; cnt < ha->mbx_count; cnt++) {
if (mboxes & BIT_0)
- WRT_REG_DWORD(optr, *iptr);
+ wrt_reg_dword(optr, *iptr);
mboxes >>= 1;
optr++;
@@ -677,14 +675,14 @@
struct qla_hw_data *ha = vha->hw;
struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
- WRT_REG_DWORD(®->req_q_in, 0);
- WRT_REG_DWORD(®->req_q_out, 0);
+ wrt_reg_dword(®->req_q_in, 0);
+ wrt_reg_dword(®->req_q_out, 0);
- WRT_REG_DWORD(®->rsp_q_in, 0);
- WRT_REG_DWORD(®->rsp_q_out, 0);
+ wrt_reg_dword(®->rsp_q_in, 0);
+ wrt_reg_dword(®->rsp_q_out, 0);
/* PCI posting */
- RD_REG_DWORD(®->rsp_q_out);
+ rd_reg_dword(®->rsp_q_out);
}
char *
@@ -741,29 +739,6 @@
}
int
-qlafx00_loop_reset(scsi_qla_host_t *vha)
-{
- int ret;
- struct fc_port *fcport;
- struct qla_hw_data *ha = vha->hw;
-
- if (ql2xtargetreset) {
- list_for_each_entry(fcport, &vha->vp_fcports, list) {
- if (fcport->port_type != FCT_TARGET)
- continue;
-
- ret = ha->isp_ops->target_reset(fcport, 0, 0);
- if (ret != QLA_SUCCESS) {
- ql_dbg(ql_dbg_taskm, vha, 0x803d,
- "Bus Reset failed: Reset=%d "
- "d_id=%x.\n", ret, fcport->d_id.b24);
- }
- }
- }
- return QLA_SUCCESS;
-}
-
-int
qlafx00_iospace_config(struct qla_hw_data *ha)
{
if (pci_request_selected_regions(ha->pdev, ha->bars,
@@ -789,7 +764,7 @@
}
ha->cregbase =
- ioremap_nocache(pci_resource_start(ha->pdev, 0), BAR0_LEN_FX00);
+ ioremap(pci_resource_start(ha->pdev, 0), BAR0_LEN_FX00);
if (!ha->cregbase) {
ql_log_pci(ql_log_fatal, ha->pdev, 0x0128,
"cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));
@@ -810,7 +785,7 @@
}
ha->iobase =
- ioremap_nocache(pci_resource_start(ha->pdev, 2), BAR2_LEN_FX00);
+ ioremap(pci_resource_start(ha->pdev, 2), BAR2_LEN_FX00);
if (!ha->iobase) {
ql_log_pci(ql_log_fatal, ha->pdev, 0x012b,
"cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));
@@ -913,9 +888,9 @@
/* 30 seconds wait - Adjust if required */
wait_time = 30;
- pseudo_aen = RD_REG_DWORD(®->pseudoaen);
+ pseudo_aen = rd_reg_dword(®->pseudoaen);
if (pseudo_aen == 1) {
- aenmbx7 = RD_REG_DWORD(®->initval7);
+ aenmbx7 = rd_reg_dword(®->initval7);
ha->mbx_intr_code = MSW(aenmbx7);
ha->rqstq_intr_code = LSW(aenmbx7);
rval = qlafx00_driver_shutdown(vha, 10);
@@ -926,7 +901,7 @@
/* wait time before firmware ready */
wtime = jiffies + (wait_time * HZ);
do {
- aenmbx = RD_REG_DWORD(®->aenmailbox0);
+ aenmbx = rd_reg_dword(®->aenmailbox0);
barrier();
ql_dbg(ql_dbg_mbx, vha, 0x0133,
"aenmbx: 0x%x\n", aenmbx);
@@ -945,15 +920,15 @@
case MBA_FW_RESTART_CMPLT:
/* Set the mbx and rqstq intr code */
- aenmbx7 = RD_REG_DWORD(®->aenmailbox7);
+ aenmbx7 = rd_reg_dword(®->aenmailbox7);
ha->mbx_intr_code = MSW(aenmbx7);
ha->rqstq_intr_code = LSW(aenmbx7);
- ha->req_que_off = RD_REG_DWORD(®->aenmailbox1);
- ha->rsp_que_off = RD_REG_DWORD(®->aenmailbox3);
- ha->req_que_len = RD_REG_DWORD(®->aenmailbox5);
- ha->rsp_que_len = RD_REG_DWORD(®->aenmailbox6);
- WRT_REG_DWORD(®->aenmailbox0, 0);
- RD_REG_DWORD_RELAXED(®->aenmailbox0);
+ ha->req_que_off = rd_reg_dword(®->aenmailbox1);
+ ha->rsp_que_off = rd_reg_dword(®->aenmailbox3);
+ ha->req_que_len = rd_reg_dword(®->aenmailbox5);
+ ha->rsp_que_len = rd_reg_dword(®->aenmailbox6);
+ wrt_reg_dword(®->aenmailbox0, 0);
+ rd_reg_dword_relaxed(®->aenmailbox0);
ql_dbg(ql_dbg_init, vha, 0x0134,
"f/w returned mbx_intr_code: 0x%x, "
"rqstq_intr_code: 0x%x\n",
@@ -983,13 +958,13 @@
* 3. issue Get FW State Mbox cmd to determine fw state
* Set the mbx and rqstq intr code from Shadow Regs
*/
- aenmbx7 = RD_REG_DWORD(®->initval7);
+ aenmbx7 = rd_reg_dword(®->initval7);
ha->mbx_intr_code = MSW(aenmbx7);
ha->rqstq_intr_code = LSW(aenmbx7);
- ha->req_que_off = RD_REG_DWORD(®->initval1);
- ha->rsp_que_off = RD_REG_DWORD(®->initval3);
- ha->req_que_len = RD_REG_DWORD(®->initval5);
- ha->rsp_que_len = RD_REG_DWORD(®->initval6);
+ ha->req_que_off = rd_reg_dword(®->initval1);
+ ha->rsp_que_off = rd_reg_dword(®->initval3);
+ ha->req_que_len = rd_reg_dword(®->initval5);
+ ha->rsp_que_len = rd_reg_dword(®->initval6);
ql_dbg(ql_dbg_init, vha, 0x0135,
"f/w returned mbx_intr_code: 0x%x, "
"rqstq_intr_code: 0x%x\n",
@@ -1035,7 +1010,7 @@
if (time_after_eq(jiffies, wtime)) {
ql_dbg(ql_dbg_init, vha, 0x0137,
"Init f/w failed: aen[7]: 0x%x\n",
- RD_REG_DWORD(®->aenmailbox7));
+ rd_reg_dword(®->aenmailbox7));
rval = QLA_FUNCTION_FAILED;
done = true;
break;
@@ -1210,9 +1185,9 @@
" Existing TGT-ID %x did not get "
" offline event from firmware.\n",
fcport->old_tgt_id);
- qla2x00_mark_device_lost(vha, fcport, 0, 0);
+ qla2x00_mark_device_lost(vha, fcport, 0);
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
- kfree(new_fcport);
+ qla2x00_free_fcport(new_fcport);
return rval;
}
break;
@@ -1230,7 +1205,7 @@
return QLA_MEMORY_ALLOC_FAILED;
}
- kfree(new_fcport);
+ qla2x00_free_fcport(new_fcport);
return rval;
}
@@ -1274,7 +1249,7 @@
if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) {
if (fcport->port_type != FCT_INITIATOR)
- qla2x00_mark_device_lost(vha, fcport, 0, 0);
+ qla2x00_mark_device_lost(vha, fcport, 0);
}
}
@@ -1298,7 +1273,7 @@
/* Free all new device structures not processed. */
list_for_each_entry_safe(fcport, rmptemp, &new_fcports, list) {
list_del(&fcport->list);
- kfree(fcport);
+ qla2x00_free_fcport(fcport);
}
return rval;
@@ -1429,7 +1404,7 @@
pkt = rsp->ring_ptr;
for (cnt = 0; cnt < rsp->length; cnt++) {
pkt->signature = RESPONSE_PROCESSED;
- WRT_REG_DWORD((void __force __iomem *)&pkt->signature,
+ wrt_reg_dword((void __force __iomem *)&pkt->signature,
RESPONSE_PROCESSED);
pkt++;
}
@@ -1445,13 +1420,13 @@
qla2x00_request_irqs(ha, ha->rsp_q_map[0]);
- aenmbx7 = RD_REG_DWORD(®->aenmailbox7);
+ aenmbx7 = rd_reg_dword(®->aenmailbox7);
ha->mbx_intr_code = MSW(aenmbx7);
ha->rqstq_intr_code = LSW(aenmbx7);
- ha->req_que_off = RD_REG_DWORD(®->aenmailbox1);
- ha->rsp_que_off = RD_REG_DWORD(®->aenmailbox3);
- ha->req_que_len = RD_REG_DWORD(®->aenmailbox5);
- ha->rsp_que_len = RD_REG_DWORD(®->aenmailbox6);
+ ha->req_que_off = rd_reg_dword(®->aenmailbox1);
+ ha->rsp_que_off = rd_reg_dword(®->aenmailbox3);
+ ha->req_que_len = rd_reg_dword(®->aenmailbox5);
+ ha->rsp_que_len = rd_reg_dword(®->aenmailbox6);
ql_dbg(ql_dbg_disc, vha, 0x2094,
"fw returned mbx_intr_code: 0x%x, rqstq_intr_code: 0x%x "
@@ -1496,7 +1471,7 @@
(!test_bit(UNLOADING, &vha->dpc_flags)) &&
(!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) &&
(ha->mr.fw_hbt_en)) {
- fw_heart_beat = RD_REG_DWORD(®->fwheartbeat);
+ fw_heart_beat = rd_reg_dword(®->fwheartbeat);
if (fw_heart_beat != ha->mr.old_fw_hbt_cnt) {
ha->mr.old_fw_hbt_cnt = fw_heart_beat;
ha->mr.fw_hbt_miss_cnt = 0;
@@ -1516,7 +1491,7 @@
if (test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags)) {
/* Reset recovery to be performed in timer routine */
- aenmbx0 = RD_REG_DWORD(®->aenmailbox0);
+ aenmbx0 = rd_reg_dword(®->aenmailbox0);
if (ha->mr.fw_reset_timer_exp) {
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
@@ -1706,15 +1681,14 @@
if (!fcport)
return;
- qla2x00_mark_device_lost(vha, fcport, 0, 0);
+ qla2x00_mark_device_lost(vha, fcport, 0);
return;
}
-int
+void
qlafx00_process_aen(struct scsi_qla_host *vha, struct qla_work_evt *evt)
{
- int rval = 0;
uint32_t aen_code, aen_data;
aen_code = FCH_EVT_VENDOR_UNIQUE;
@@ -1740,7 +1714,7 @@
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
} else if (evt->u.aenfx.mbx[2] == 2) {
vha->device_flags |= DFLG_NO_CABLE;
- qla2x00_mark_all_devices_lost(vha, 1);
+ qla2x00_mark_all_devices_lost(vha);
}
}
break;
@@ -1765,8 +1739,6 @@
fc_host_post_event(vha->host, fc_get_event_number(),
aen_code, aen_data);
-
- return rval;
}
static void
@@ -2513,7 +2485,7 @@
atomic_read(&fcport->state));
if (atomic_read(&fcport->state) == FCS_ONLINE)
- qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
+ qla2x00_mark_device_lost(fcport->vha, fcport, 1);
break;
case CS_ABORTED:
@@ -2722,7 +2694,7 @@
uint16_t lreq_q_in = 0;
uint16_t lreq_q_out = 0;
- lreq_q_in = RD_REG_DWORD(rsp->rsp_q_in);
+ lreq_q_in = rd_reg_dword(rsp->rsp_q_in);
lreq_q_out = rsp->ring_index;
while (lreq_q_in != lreq_q_out) {
@@ -2784,7 +2756,7 @@
}
/* Adjust ring index */
- WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index);
+ wrt_reg_dword(rsp->rsp_q_out, rsp->ring_index);
}
/**
@@ -2815,9 +2787,9 @@
break;
case QLAFX00_MBA_PORT_UPDATE: /* Port database update */
- ha->aenmb[1] = RD_REG_DWORD(®->aenmailbox1);
- ha->aenmb[2] = RD_REG_DWORD(®->aenmailbox2);
- ha->aenmb[3] = RD_REG_DWORD(®->aenmailbox3);
+ ha->aenmb[1] = rd_reg_dword(®->aenmailbox1);
+ ha->aenmb[2] = rd_reg_dword(®->aenmailbox2);
+ ha->aenmb[3] = rd_reg_dword(®->aenmailbox3);
ql_dbg(ql_dbg_async, vha, 0x5077,
"Asynchronous port Update received "
"aenmb[0]: %x, aenmb[1]: %x, aenmb[2]: %x, aenmb[3]: %x\n",
@@ -2847,13 +2819,13 @@
break;
default:
- ha->aenmb[1] = RD_REG_WORD(®->aenmailbox1);
- ha->aenmb[2] = RD_REG_WORD(®->aenmailbox2);
- ha->aenmb[3] = RD_REG_WORD(®->aenmailbox3);
- ha->aenmb[4] = RD_REG_WORD(®->aenmailbox4);
- ha->aenmb[5] = RD_REG_WORD(®->aenmailbox5);
- ha->aenmb[6] = RD_REG_WORD(®->aenmailbox6);
- ha->aenmb[7] = RD_REG_WORD(®->aenmailbox7);
+ ha->aenmb[1] = rd_reg_dword(®->aenmailbox1);
+ ha->aenmb[2] = rd_reg_dword(®->aenmailbox2);
+ ha->aenmb[3] = rd_reg_dword(®->aenmailbox3);
+ ha->aenmb[4] = rd_reg_dword(®->aenmailbox4);
+ ha->aenmb[5] = rd_reg_dword(®->aenmailbox5);
+ ha->aenmb[6] = rd_reg_dword(®->aenmailbox6);
+ ha->aenmb[7] = rd_reg_dword(®->aenmailbox7);
ql_dbg(ql_dbg_async, vha, 0x5078,
"AEN:%04x %04x %04x %04x :%04x %04x %04x %04x\n",
ha->aenmb[0], ha->aenmb[1], ha->aenmb[2], ha->aenmb[3],
@@ -2873,7 +2845,7 @@
qlafx00_mbx_completion(scsi_qla_host_t *vha, uint32_t mb0)
{
uint16_t cnt;
- uint32_t __iomem *wptr;
+ __le32 __iomem *wptr;
struct qla_hw_data *ha = vha->hw;
struct device_reg_fx00 __iomem *reg = &ha->iobase->ispfx00;
@@ -2883,10 +2855,10 @@
/* Load return mailbox registers. */
ha->flags.mbox_int = 1;
ha->mailbox_out32[0] = mb0;
- wptr = (uint32_t __iomem *)®->mailbox17;
+ wptr = ®->mailbox17;
for (cnt = 1; cnt < ha->mbx_count; cnt++) {
- ha->mailbox_out32[cnt] = RD_REG_DWORD(wptr);
+ ha->mailbox_out32[cnt] = rd_reg_dword(wptr);
wptr++;
}
}
@@ -2940,13 +2912,13 @@
break;
if (stat & QLAFX00_INTR_MB_CMPLT) {
- mb[0] = RD_REG_WORD(®->mailbox16);
+ mb[0] = rd_reg_dword(®->mailbox16);
qlafx00_mbx_completion(vha, mb[0]);
status |= MBX_INTERRUPT;
clr_intr |= QLAFX00_INTR_MB_CMPLT;
}
if (intr_stat & QLAFX00_INTR_ASYNC_CMPLT) {
- ha->aenmb[0] = RD_REG_WORD(®->aenmailbox0);
+ ha->aenmb[0] = rd_reg_dword(®->aenmailbox0);
qlafx00_async_event(vha);
clr_intr |= QLAFX00_INTR_ASYNC_CMPLT;
}
@@ -3114,7 +3086,7 @@
tot_dsds = nseg;
req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
if (req->cnt < (req_cnt + 2)) {
- cnt = RD_REG_DWORD_RELAXED(req->req_q_out);
+ cnt = rd_reg_dword_relaxed(req->req_q_out);
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
@@ -3136,7 +3108,7 @@
memset(&lcmd_pkt, 0, REQUEST_ENTRY_SIZE);
- lcmd_pkt.handle = MAKE_HANDLE(req->id, sp->handle);
+ lcmd_pkt.handle = make_handle(req->id, sp->handle);
lcmd_pkt.reserved_0 = 0;
lcmd_pkt.port_path_ctrl = 0;
lcmd_pkt.reserved_1 = 0;
@@ -3179,7 +3151,7 @@
sp->flags |= SRB_DMA_VALID;
/* Set chip new ring index. */
- WRT_REG_DWORD(req->req_q_in, req->ring_index);
+ wrt_reg_dword(req->req_q_in, req->ring_index);
QLAFX00_SET_HST_INTR(ha, ha->rqstq_intr_code);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -3206,7 +3178,7 @@
memset(&tm_iocb, 0, sizeof(struct tsk_mgmt_entry_fx00));
tm_iocb.entry_type = TSK_MGMT_IOCB_TYPE_FX00;
tm_iocb.entry_count = 1;
- tm_iocb.handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle));
+ tm_iocb.handle = make_handle(req->id, sp->handle);
tm_iocb.reserved_0 = 0;
tm_iocb.tgt_id = cpu_to_le16(sp->fcport->tgt_id);
tm_iocb.control_flags = cpu_to_le32(fxio->u.tmf.flags);
@@ -3216,7 +3188,7 @@
sizeof(struct scsi_lun));
}
- memcpy((void *)ptm_iocb, &tm_iocb,
+ memcpy(ptm_iocb, &tm_iocb,
sizeof(struct tsk_mgmt_entry_fx00));
wmb();
}
@@ -3232,13 +3204,12 @@
memset(&abt_iocb, 0, sizeof(struct abort_iocb_entry_fx00));
abt_iocb.entry_type = ABORT_IOCB_TYPE_FX00;
abt_iocb.entry_count = 1;
- abt_iocb.handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle));
- abt_iocb.abort_handle =
- cpu_to_le32(MAKE_HANDLE(req->id, fxio->u.abt.cmd_hndl));
+ abt_iocb.handle = make_handle(req->id, sp->handle);
+ abt_iocb.abort_handle = make_handle(req->id, fxio->u.abt.cmd_hndl);
abt_iocb.tgt_id_sts = cpu_to_le16(sp->fcport->tgt_id);
abt_iocb.req_que_no = cpu_to_le16(req->id);
- memcpy((void *)pabt_iocb, &abt_iocb,
+ memcpy(pabt_iocb, &abt_iocb,
sizeof(struct abort_iocb_entry_fx00));
wmb();
}
@@ -3255,7 +3226,7 @@
memset(&fx_iocb, 0, sizeof(struct fxdisc_entry_fx00));
fx_iocb.entry_type = FX00_IOCB_TYPE;
- fx_iocb.handle = cpu_to_le32(sp->handle);
+ fx_iocb.handle = sp->handle;
fx_iocb.entry_count = entry_cnt;
if (sp->type == SRB_FXIOCB_DCMD) {
diff --git a/drivers/scsi/qla2xxx/qla_mr.h b/drivers/scsi/qla2xxx/qla_mr.h
index 4567f0c..73be834 100644
--- a/drivers/scsi/qla2xxx/qla_mr.h
+++ b/drivers/scsi/qla2xxx/qla_mr.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#ifndef __QLA_MR_H
#define __QLA_MR_H
@@ -96,7 +95,7 @@
uint8_t sys_define;
uint8_t entry_status; /* Entry Status. */
- __le32 handle; /* System handle. */
+ uint32_t handle; /* System handle. */
uint32_t reserved_0;
@@ -121,13 +120,13 @@
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
- __le32 handle; /* System handle. */
+ uint32_t handle; /* System handle. */
__le32 reserved_0;
__le16 tgt_id_sts; /* Completion status. */
__le16 options;
- __le32 abort_handle; /* System handle. */
+ uint32_t abort_handle; /* System handle. */
__le32 reserved_2;
__le16 req_que_no;
@@ -166,7 +165,7 @@
uint8_t sys_define; /* System Defined. */
uint8_t entry_status; /* Entry Status. */
- __le32 handle; /* System handle. */
+ uint32_t handle; /* System handle. */
__le32 reserved_0; /* System handle. */
__le16 func_num;
@@ -359,47 +358,47 @@
#define CONTINUE_A64_TYPE_FX00 0x03 /* Continuation entry. */
#define QLAFX00_SET_HST_INTR(ha, value) \
- WRT_REG_DWORD((ha)->cregbase + QLAFX00_HST_TO_HBA_REG, \
+ wrt_reg_dword((ha)->cregbase + QLAFX00_HST_TO_HBA_REG, \
value)
#define QLAFX00_CLR_HST_INTR(ha, value) \
- WRT_REG_DWORD((ha)->cregbase + QLAFX00_HBA_TO_HOST_REG, \
+ wrt_reg_dword((ha)->cregbase + QLAFX00_HBA_TO_HOST_REG, \
~value)
#define QLAFX00_RD_INTR_REG(ha) \
- RD_REG_DWORD((ha)->cregbase + QLAFX00_HBA_TO_HOST_REG)
+ rd_reg_dword((ha)->cregbase + QLAFX00_HBA_TO_HOST_REG)
#define QLAFX00_CLR_INTR_REG(ha, value) \
- WRT_REG_DWORD((ha)->cregbase + QLAFX00_HBA_TO_HOST_REG, \
+ wrt_reg_dword((ha)->cregbase + QLAFX00_HBA_TO_HOST_REG, \
~value)
#define QLAFX00_SET_HBA_SOC_REG(ha, off, val)\
- WRT_REG_DWORD((ha)->cregbase + off, val)
+ wrt_reg_dword((ha)->cregbase + off, val)
#define QLAFX00_GET_HBA_SOC_REG(ha, off)\
- RD_REG_DWORD((ha)->cregbase + off)
+ rd_reg_dword((ha)->cregbase + off)
#define QLAFX00_HBA_RST_REG(ha, val)\
- WRT_REG_DWORD((ha)->cregbase + QLAFX00_HST_RST_REG, val)
+ wrt_reg_dword((ha)->cregbase + QLAFX00_HST_RST_REG, val)
#define QLAFX00_RD_ICNTRL_REG(ha) \
- RD_REG_DWORD((ha)->cregbase + QLAFX00_HBA_ICNTRL_REG)
+ rd_reg_dword((ha)->cregbase + QLAFX00_HBA_ICNTRL_REG)
#define QLAFX00_ENABLE_ICNTRL_REG(ha) \
- WRT_REG_DWORD((ha)->cregbase + QLAFX00_HBA_ICNTRL_REG, \
+ wrt_reg_dword((ha)->cregbase + QLAFX00_HBA_ICNTRL_REG, \
(QLAFX00_GET_HBA_SOC_REG(ha, QLAFX00_HBA_ICNTRL_REG) | \
QLAFX00_ICR_ENB_MASK))
#define QLAFX00_DISABLE_ICNTRL_REG(ha) \
- WRT_REG_DWORD((ha)->cregbase + QLAFX00_HBA_ICNTRL_REG, \
+ wrt_reg_dword((ha)->cregbase + QLAFX00_HBA_ICNTRL_REG, \
(QLAFX00_GET_HBA_SOC_REG(ha, QLAFX00_HBA_ICNTRL_REG) & \
QLAFX00_ICR_DIS_MASK))
#define QLAFX00_RD_REG(ha, off) \
- RD_REG_DWORD((ha)->cregbase + off)
+ rd_reg_dword((ha)->cregbase + off)
#define QLAFX00_WR_REG(ha, off, val) \
- WRT_REG_DWORD((ha)->cregbase + off, val)
+ wrt_reg_dword((ha)->cregbase + off, val)
struct qla_mt_iocb_rqst_fx00 {
__le32 reserved_0;
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
index 97453c1..5acee3c 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.c
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2017 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_nvme.h"
#include <linux/scatterlist.h>
@@ -42,7 +41,7 @@
req.port_name = wwn_to_u64(fcport->port_name);
req.node_name = wwn_to_u64(fcport->node_name);
req.port_role = 0;
- req.dev_loss_tmo = NVME_FC_DEV_LOSS_TMO;
+ req.dev_loss_tmo = 0;
if (fcport->nvme_prli_service_param & NVME_PRLI_SP_INITIATOR)
req.port_role = FC_PORT_ROLE_NVME_INITIATOR;
@@ -69,6 +68,14 @@
return ret;
}
+ if (fcport->nvme_prli_service_param & NVME_PRLI_SP_SLER)
+ ql_log(ql_log_info, vha, 0x212a,
+ "PortID:%06x Supports SLER\n", req.port_id);
+
+ if (fcport->nvme_prli_service_param & NVME_PRLI_SP_PI_CTRL)
+ ql_log(ql_log_info, vha, 0x212b,
+ "PortID:%06x Supports PI control\n", req.port_id);
+
rport = fcport->nvme_remote_port->private;
rport->fcport = fcport;
@@ -102,19 +109,24 @@
return -EINVAL;
}
- if (ha->queue_pair_map[qidx]) {
- *handle = ha->queue_pair_map[qidx];
- ql_log(ql_log_info, vha, 0x2121,
- "Returning existing qpair of %p for idx=%x\n",
- *handle, qidx);
- return 0;
- }
+ /* Use base qpair if max_qpairs is 0 */
+ if (!ha->max_qpairs) {
+ qpair = ha->base_qpair;
+ } else {
+ if (ha->queue_pair_map[qidx]) {
+ *handle = ha->queue_pair_map[qidx];
+ ql_log(ql_log_info, vha, 0x2121,
+ "Returning existing qpair of %p for idx=%x\n",
+ *handle, qidx);
+ return 0;
+ }
- qpair = qla2xxx_create_qpair(vha, 5, vha->vp_idx, true);
- if (qpair == NULL) {
- ql_log(ql_log_warn, vha, 0x2122,
- "Failed to allocate qpair\n");
- return -EINVAL;
+ qpair = qla2xxx_create_qpair(vha, 5, vha->vp_idx, true);
+ if (!qpair) {
+ ql_log(ql_log_warn, vha, 0x2122,
+ "Failed to allocate qpair\n");
+ return -EINVAL;
+ }
}
*handle = qpair;
@@ -139,12 +151,13 @@
priv->sp = NULL;
sp->priv = NULL;
if (priv->comp_status == QLA_SUCCESS) {
- fd->rcv_rsplen = nvme->u.nvme.rsp_pyld_len;
+ fd->rcv_rsplen = le16_to_cpu(nvme->u.nvme.rsp_pyld_len);
+ fd->status = NVME_SC_SUCCESS;
} else {
fd->rcv_rsplen = 0;
fd->transferred_length = 0;
+ fd->status = NVME_SC_INTERNAL;
}
- fd->status = 0;
spin_unlock_irqrestore(&priv->cmd_lock, flags);
fd->done(fd);
@@ -296,7 +309,7 @@
sp->name = "nvme_ls";
sp->done = qla_nvme_sp_ls_done;
sp->put_fn = qla_nvme_release_ls_cmd_kref;
- sp->priv = (void *)priv;
+ sp->priv = priv;
priv->sp = sp;
kref_init(&sp->cmd_kref);
spin_lock_init(&priv->cmd_lock);
@@ -368,6 +381,7 @@
struct srb_iocb *nvme = &sp->u.iocb_cmd;
struct scatterlist *sgl, *sg;
struct nvmefc_fcp_req *fd = nvme->u.nvme.desc;
+ struct nvme_fc_cmd_iu *cmd = fd->cmdaddr;
uint32_t rval = QLA_SUCCESS;
/* Setup qpair pointers */
@@ -385,7 +399,7 @@
req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
if (req->cnt < (req_cnt + 2)) {
cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr :
- RD_REG_DWORD_RELAXED(req->req_q_out);
+ rd_reg_dword_relaxed(req->req_q_out);
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
@@ -399,8 +413,6 @@
}
if (unlikely(!fd->sqid)) {
- struct nvme_fc_cmd_iu *cmd = fd->cmdaddr;
-
if (cmd->sqe.common.opcode == nvme_admin_async_event) {
nvme->u.nvme.aen_op = 1;
atomic_inc(&ha->nvme_active_aen_cnt);
@@ -414,7 +426,7 @@
req->cnt -= req_cnt;
cmd_pkt = (struct cmd_nvme *)req->ring_ptr;
- cmd_pkt->handle = MAKE_HANDLE(req->id, handle);
+ cmd_pkt->handle = make_handle(req->id, handle);
/* Zero out remaining portion of packet. */
clr_ptr = (uint32_t *)cmd_pkt + 2;
@@ -427,11 +439,11 @@
/* No data transfer how do we check buffer len == 0?? */
if (fd->io_dir == NVMEFC_FCP_READ) {
- cmd_pkt->control_flags = CF_READ_DATA;
- vha->qla_stats.input_bytes += fd->payload_length;
- vha->qla_stats.input_requests++;
+ cmd_pkt->control_flags = cpu_to_le16(CF_READ_DATA);
+ qpair->counters.input_bytes += fd->payload_length;
+ qpair->counters.input_requests++;
} else if (fd->io_dir == NVMEFC_FCP_WRITE) {
- cmd_pkt->control_flags = CF_WRITE_DATA;
+ cmd_pkt->control_flags = cpu_to_le16(CF_WRITE_DATA);
if ((vha->flags.nvme_first_burst) &&
(sp->fcport->nvme_prli_service_param &
NVME_PRLI_SP_FIRST_BURST)) {
@@ -439,13 +451,18 @@
sp->fcport->nvme_first_burst_size) ||
(sp->fcport->nvme_first_burst_size == 0))
cmd_pkt->control_flags |=
- CF_NVME_FIRST_BURST_ENABLE;
+ cpu_to_le16(CF_NVME_FIRST_BURST_ENABLE);
}
- vha->qla_stats.output_bytes += fd->payload_length;
- vha->qla_stats.output_requests++;
+ qpair->counters.output_bytes += fd->payload_length;
+ qpair->counters.output_requests++;
} else if (fd->io_dir == 0) {
cmd_pkt->control_flags = 0;
}
+ /* Set BIT_13 of control flags for Async event */
+ if (vha->flags.nvme2_enabled &&
+ cmd->sqe.common.opcode == nvme_admin_async_event) {
+ cmd_pkt->control_flags |= cpu_to_le16(CF_ADMIN_ASYNC_EVENT);
+ }
/* Set NPORT-ID */
cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id);
@@ -515,7 +532,7 @@
}
/* Set chip new ring index. */
- WRT_REG_DWORD(req->req_q_in, req->ring_index);
+ wrt_reg_dword(req->req_q_in, req->ring_index);
queuing_error:
spin_unlock_irqrestore(&qpair->qp_lock, flags);
@@ -530,7 +547,7 @@
fc_port_t *fcport;
struct srb_iocb *nvme;
struct scsi_qla_host *vha;
- int rval = -ENODEV;
+ int rval;
srb_t *sp;
struct qla_qpair *qpair = hw_queue_handle;
struct nvme_private *priv = fd->private;
@@ -538,16 +555,26 @@
if (!priv) {
/* nvme association has been torn down */
- return rval;
+ return -ENODEV;
}
fcport = qla_rport->fcport;
- if (!qpair || !fcport || (qpair && !qpair->fw_started) ||
- (fcport && fcport->deleted))
- return rval;
+ if (!qpair || !fcport)
+ return -ENODEV;
+
+ if (!qpair->fw_started || fcport->deleted)
+ return -EBUSY;
vha = fcport->vha;
+
+ if (!(fcport->nvme_flag & NVME_FLAG_REGISTERED))
+ return -ENODEV;
+
+ if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
+ (qpair && !qpair->fw_started) || fcport->deleted)
+ return -EBUSY;
+
/*
* If we know the dev is going away while the transport is still sending
* IO's return busy back to stall the IO Q. This happens when the
@@ -566,7 +593,7 @@
init_waitqueue_head(&sp->nvme_ls_waitq);
kref_init(&sp->cmd_kref);
spin_lock_init(&priv->cmd_lock);
- sp->priv = (void *)priv;
+ sp->priv = priv;
priv->sp = sp;
sp->type = SRB_NVME_CMD;
sp->name = "nvme_cmd";
@@ -692,11 +719,10 @@
tmpl = &qla_nvme_fc_transport;
WARN_ON(vha->nvme_local_port);
- WARN_ON(ha->max_req_queues < 3);
qla_nvme_fc_transport.max_hw_queues =
min((uint8_t)(qla_nvme_fc_transport.max_hw_queues),
- (uint8_t)(ha->max_req_queues - 2));
+ (uint8_t)(ha->max_qpairs ? ha->max_qpairs : 1));
pinfo.node_name = wwn_to_u64(vha->node_name);
pinfo.port_name = wwn_to_u64(vha->port_name);
diff --git a/drivers/scsi/qla2xxx/qla_nvme.h b/drivers/scsi/qla2xxx/qla_nvme.h
index ef91290..f81f219 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.h
+++ b/drivers/scsi/qla2xxx/qla_nvme.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2017 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#ifndef __QLA_NVME_H
#define __QLA_NVME_H
@@ -14,9 +13,6 @@
#include "qla_def.h"
#include "qla_dsd.h"
-/* default dev loss time (seconds) before transport tears down ctrl */
-#define NVME_FC_DEV_LOSS_TMO 30
-
#define NVME_ATIO_CMD_OFF 32
#define NVME_FIRST_PACKET_CMDLEN (64 - NVME_ATIO_CMD_OFF)
#define Q2T_NVME_NUM_TAGS 2048
@@ -48,26 +44,27 @@
uint8_t entry_status; /* Entry Status. */
uint32_t handle; /* System handle. */
- uint16_t nport_handle; /* N_PORT handle. */
- uint16_t timeout; /* Command timeout. */
+ __le16 nport_handle; /* N_PORT handle. */
+ __le16 timeout; /* Command timeout. */
- uint16_t dseg_count; /* Data segment count. */
- uint16_t nvme_rsp_dsd_len; /* NVMe RSP DSD length */
+ __le16 dseg_count; /* Data segment count. */
+ __le16 nvme_rsp_dsd_len; /* NVMe RSP DSD length */
uint64_t rsvd;
- uint16_t control_flags; /* Control Flags */
+ __le16 control_flags; /* Control Flags */
+#define CF_ADMIN_ASYNC_EVENT BIT_13
#define CF_NVME_FIRST_BURST_ENABLE BIT_11
#define CF_DIF_SEG_DESCR_ENABLE BIT_3
#define CF_DATA_SEG_DESCR_ENABLE BIT_2
#define CF_READ_DATA BIT_1
#define CF_WRITE_DATA BIT_0
- uint16_t nvme_cmnd_dseg_len; /* Data segment length. */
+ __le16 nvme_cmnd_dseg_len; /* Data segment length. */
__le64 nvme_cmnd_dseg_address __packed;/* Data segment address. */
__le64 nvme_rsp_dseg_address __packed; /* Data segment address. */
- uint32_t byte_count; /* Total byte count. */
+ __le32 byte_count; /* Total byte count. */
uint8_t port_id[3]; /* PortID of destination port. */
uint8_t vp_index;
@@ -82,24 +79,24 @@
uint8_t sys_define;
uint8_t entry_status;
uint32_t handle;
- uint16_t status;
- uint16_t nport_handle;
- uint16_t tx_dseg_count;
+ __le16 status;
+ __le16 nport_handle;
+ __le16 tx_dseg_count;
uint8_t vp_index;
uint8_t rsvd;
- uint16_t timeout;
- uint16_t control_flags;
+ __le16 timeout;
+ __le16 control_flags;
#define CF_LS4_SHIFT 13
#define CF_LS4_ORIGINATOR 0
#define CF_LS4_RESPONDER 1
#define CF_LS4_RESPONDER_TERM 2
- uint16_t rx_dseg_count;
- uint16_t rsvd2;
- uint32_t exchange_address;
- uint32_t rsvd3;
- uint32_t rx_byte_count;
- uint32_t tx_byte_count;
+ __le16 rx_dseg_count;
+ __le16 rsvd2;
+ __le32 exchange_address;
+ __le32 rsvd3;
+ __le32 rx_byte_count;
+ __le32 tx_byte_count;
struct dsd64 dsd[2];
};
@@ -107,32 +104,32 @@
struct pt_ls4_rx_unsol {
uint8_t entry_type;
uint8_t entry_count;
- uint16_t rsvd0;
- uint16_t rsvd1;
+ __le16 rsvd0;
+ __le16 rsvd1;
uint8_t vp_index;
uint8_t rsvd2;
- uint16_t rsvd3;
- uint16_t nport_handle;
- uint16_t frame_size;
- uint16_t rsvd4;
- uint32_t exchange_address;
+ __le16 rsvd3;
+ __le16 nport_handle;
+ __le16 frame_size;
+ __le16 rsvd4;
+ __le32 exchange_address;
uint8_t d_id[3];
uint8_t r_ctl;
be_id_t s_id;
uint8_t cs_ctl;
uint8_t f_ctl[3];
uint8_t type;
- uint16_t seq_cnt;
+ __le16 seq_cnt;
uint8_t df_ctl;
uint8_t seq_id;
- uint16_t rx_id;
- uint16_t ox_id;
- uint32_t param;
- uint32_t desc0;
+ __le16 rx_id;
+ __le16 ox_id;
+ __le32 param;
+ __le32 desc0;
#define PT_LS4_PAYLOAD_OFFSET 0x2c
#define PT_LS4_FIRST_PACKET_LEN 20
- uint32_t desc_len;
- uint32_t payload[3];
+ __le32 desc_len;
+ __le32 payload[3];
};
/*
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index de567a0..0563c95 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
#include <linux/delay.h>
@@ -370,7 +369,7 @@
/* Read back value to make sure write has gone through before trying
* to use it.
*/
- win_read = RD_REG_DWORD(CRB_WINDOW_2M + ha->nx_pcibase);
+ win_read = rd_reg_dword(CRB_WINDOW_2M + ha->nx_pcibase);
if (win_read != ha->crb_win) {
ql_dbg(ql_dbg_p3p, vha, 0xb000,
"%s: Written crbwin (0x%x) "
@@ -380,47 +379,6 @@
*off_out = (off_in & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase;
}
-static inline unsigned long
-qla82xx_pci_set_crbwindow(struct qla_hw_data *ha, u64 off)
-{
- scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
- /* See if we are currently pointing to the region we want to use next */
- if ((off >= QLA82XX_CRB_PCIX_HOST) && (off < QLA82XX_CRB_DDR_NET)) {
- /* No need to change window. PCIX and PCIEregs are in both
- * regs are in both windows.
- */
- return off;
- }
-
- if ((off >= QLA82XX_CRB_PCIX_HOST) && (off < QLA82XX_CRB_PCIX_HOST2)) {
- /* We are in first CRB window */
- if (ha->curr_window != 0)
- WARN_ON(1);
- return off;
- }
-
- if ((off > QLA82XX_CRB_PCIX_HOST2) && (off < QLA82XX_CRB_MAX)) {
- /* We are in second CRB window */
- off = off - QLA82XX_CRB_PCIX_HOST2 + QLA82XX_CRB_PCIX_HOST;
-
- if (ha->curr_window != 1)
- return off;
-
- /* We are in the QM or direct access
- * register region - do nothing
- */
- if ((off >= QLA82XX_PCI_DIRECT_CRB) &&
- (off < QLA82XX_PCI_CAMQM_MAX))
- return off;
- }
- /* strange address given */
- ql_dbg(ql_dbg_p3p, vha, 0xb001,
- "%s: Warning: unm_nic_pci_set_crbwindow "
- "called with an unknown address(%llx).\n",
- QLA2XXX_DRIVER_NAME, off);
- return off;
-}
-
static int
qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, ulong off_in,
void __iomem **off_out)
@@ -520,7 +478,7 @@
qla82xx_crb_win_lock(ha);
qla82xx_pci_set_crbwindow_2M(ha, off_in, &off);
}
- data = RD_REG_DWORD(off);
+ data = rd_reg_dword(off);
if (rv == 1) {
qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK));
@@ -937,17 +895,17 @@
{
uint32_t off_value, rval = 0;
- WRT_REG_DWORD(CRB_WINDOW_2M + ha->nx_pcibase, off & 0xFFFF0000);
+ wrt_reg_dword(CRB_WINDOW_2M + ha->nx_pcibase, off & 0xFFFF0000);
/* Read back value to make sure write has gone through */
- RD_REG_DWORD(CRB_WINDOW_2M + ha->nx_pcibase);
+ rd_reg_dword(CRB_WINDOW_2M + ha->nx_pcibase);
off_value = (off & 0x0000FFFF);
if (flag)
- WRT_REG_DWORD(off_value + CRB_INDIRECT_2M + ha->nx_pcibase,
+ wrt_reg_dword(off_value + CRB_INDIRECT_2M + ha->nx_pcibase,
data);
else
- rval = RD_REG_DWORD(off_value + CRB_INDIRECT_2M +
+ rval = rd_reg_dword(off_value + CRB_INDIRECT_2M +
ha->nx_pcibase);
return rval;
@@ -1007,26 +965,21 @@
static int
qla82xx_flash_wait_write_finish(struct qla_hw_data *ha)
{
- long timeout = 0;
- uint32_t done = 1 ;
uint32_t val;
- int ret = 0;
+ int i, ret;
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0);
- while ((done != 0) && (ret == 0)) {
+ for (i = 0; i < 50000; i++) {
ret = qla82xx_read_status_reg(ha, &val);
- done = val & 1;
- timeout++;
+ if (ret < 0 || (val & 1) == 0)
+ return ret;
udelay(10);
cond_resched();
- if (timeout >= 50000) {
- ql_log(ql_log_warn, vha, 0xb00d,
- "Timeout reached waiting for write finish.\n");
- return -1;
- }
}
- return ret;
+ ql_log(ql_log_warn, vha, 0xb00d,
+ "Timeout reached waiting for write finish.\n");
+ return -1;
}
static int
@@ -1214,6 +1167,7 @@
* Offset 4: Offset and number of addr/value pairs
* that present in CRB initialize sequence
*/
+ n = 0;
if (qla82xx_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafeUL ||
qla82xx_rom_fast_read(ha, 4, &n) != 0) {
ql_log(ql_log_fatal, vha, 0x006e,
@@ -1562,14 +1516,14 @@
uint32_t i;
struct qla82xx_uri_table_desc *directory =
(struct qla82xx_uri_table_desc *)&unirom[0];
- __le32 offset;
- __le32 tab_type;
- __le32 entries = cpu_to_le32(directory->num_entries);
+ uint32_t offset;
+ uint32_t tab_type;
+ uint32_t entries = le32_to_cpu(directory->num_entries);
for (i = 0; i < entries; i++) {
- offset = cpu_to_le32(directory->findex) +
- (i * cpu_to_le32(directory->entry_size));
- tab_type = cpu_to_le32(*((u32 *)&unirom[offset] + 8));
+ offset = le32_to_cpu(directory->findex) +
+ (i * le32_to_cpu(directory->entry_size));
+ tab_type = get_unaligned_le32((u32 *)&unirom[offset] + 8);
if (tab_type == section)
return (struct qla82xx_uri_table_desc *)&unirom[offset];
@@ -1583,16 +1537,17 @@
u32 section, u32 idx_offset)
{
const u8 *unirom = ha->hablob->fw->data;
- int idx = cpu_to_le32(*((int *)&unirom[ha->file_prd_off] + idx_offset));
+ int idx = get_unaligned_le32((u32 *)&unirom[ha->file_prd_off] +
+ idx_offset);
struct qla82xx_uri_table_desc *tab_desc = NULL;
- __le32 offset;
+ uint32_t offset;
tab_desc = qla82xx_get_table_desc(unirom, section);
if (!tab_desc)
return NULL;
- offset = cpu_to_le32(tab_desc->findex) +
- (cpu_to_le32(tab_desc->entry_size) * idx);
+ offset = le32_to_cpu(tab_desc->findex) +
+ (le32_to_cpu(tab_desc->entry_size) * idx);
return (struct qla82xx_uri_data_desc *)&unirom[offset];
}
@@ -1607,7 +1562,7 @@
uri_desc = qla82xx_get_data_desc(ha,
QLA82XX_URI_DIR_SECT_BOOTLD, QLA82XX_URI_BOOTLD_IDX_OFF);
if (uri_desc)
- offset = cpu_to_le32(uri_desc->findex);
+ offset = le32_to_cpu(uri_desc->findex);
}
return (u8 *)&ha->hablob->fw->data[offset];
@@ -1621,7 +1576,7 @@
uri_desc = qla82xx_get_data_desc(ha, QLA82XX_URI_DIR_SECT_FW,
QLA82XX_URI_FIRMWARE_IDX_OFF);
if (uri_desc)
- return cpu_to_le32(uri_desc->size);
+ return le32_to_cpu(uri_desc->size);
}
return get_unaligned_le32(&ha->hablob->fw->data[FW_SIZE_OFFSET]);
@@ -1637,7 +1592,7 @@
uri_desc = qla82xx_get_data_desc(ha, QLA82XX_URI_DIR_SECT_FW,
QLA82XX_URI_FIRMWARE_IDX_OFF);
if (uri_desc)
- offset = cpu_to_le32(uri_desc->findex);
+ offset = le32_to_cpu(uri_desc->findex);
}
return (u8 *)&ha->hablob->fw->data[offset];
@@ -1791,9 +1746,9 @@
put_unaligned_le64(req->dma, &icb->request_q_address);
put_unaligned_le64(rsp->dma, &icb->response_q_address);
- WRT_REG_DWORD(®->req_q_out[0], 0);
- WRT_REG_DWORD(®->rsp_q_in[0], 0);
- WRT_REG_DWORD(®->rsp_q_out[0], 0);
+ wrt_reg_dword(®->req_q_out[0], 0);
+ wrt_reg_dword(®->rsp_q_in[0], 0);
+ wrt_reg_dword(®->rsp_q_out[0], 0);
}
static int
@@ -1848,8 +1803,8 @@
struct qla82xx_uri_table_desc *ptab_desc = NULL;
const uint8_t *unirom = ha->hablob->fw->data;
uint32_t i;
- __le32 entries;
- __le32 flags, file_chiprev, offset;
+ uint32_t entries;
+ uint32_t flags, file_chiprev, offset;
uint8_t chiprev = ha->chip_revision;
/* Hardcoding mn_present flag for P3P */
int mn_present = 0;
@@ -1860,14 +1815,14 @@
if (!ptab_desc)
return -1;
- entries = cpu_to_le32(ptab_desc->num_entries);
+ entries = le32_to_cpu(ptab_desc->num_entries);
for (i = 0; i < entries; i++) {
- offset = cpu_to_le32(ptab_desc->findex) +
- (i * cpu_to_le32(ptab_desc->entry_size));
- flags = cpu_to_le32(*((int *)&unirom[offset] +
+ offset = le32_to_cpu(ptab_desc->findex) +
+ (i * le32_to_cpu(ptab_desc->entry_size));
+ flags = le32_to_cpu(*((__le32 *)&unirom[offset] +
QLA82XX_URI_FLAGS_OFF));
- file_chiprev = cpu_to_le32(*((int *)&unirom[offset] +
+ file_chiprev = le32_to_cpu(*((__le32 *)&unirom[offset] +
QLA82XX_URI_CHIP_REV_OFF));
flagbit = mn_present ? 1 : 2;
@@ -1883,7 +1838,7 @@
static int
qla82xx_validate_firmware_blob(scsi_qla_host_t *vha, uint8_t fw_type)
{
- __le32 val;
+ uint32_t val;
uint32_t min_size;
struct qla_hw_data *ha = vha->hw;
const struct firmware *fw = ha->hablob->fw;
@@ -1896,8 +1851,8 @@
min_size = QLA82XX_URI_FW_MIN_SIZE;
} else {
- val = cpu_to_le32(*(u32 *)&fw->data[QLA82XX_FW_MAGIC_OFFSET]);
- if ((__force u32)val != QLA82XX_BDINFO_MAGIC)
+ val = get_unaligned_le32(&fw->data[QLA82XX_FW_MAGIC_OFFSET]);
+ if (val != QLA82XX_BDINFO_MAGIC)
return -EINVAL;
min_size = QLA82XX_FW_MIN_SIZE;
@@ -1997,18 +1952,18 @@
qla82xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
{
uint16_t cnt;
- uint16_t __iomem *wptr;
+ __le16 __iomem *wptr;
struct qla_hw_data *ha = vha->hw;
struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
- wptr = (uint16_t __iomem *)®->mailbox_out[1];
+ wptr = ®->mailbox_out[1];
/* Load return mailbox registers. */
ha->flags.mbox_int = 1;
ha->mailbox_out[0] = mb0;
for (cnt = 1; cnt < ha->mbx_count; cnt++) {
- ha->mailbox_out[cnt] = RD_REG_WORD(wptr);
+ ha->mailbox_out[cnt] = rd_reg_word(wptr);
wptr++;
}
@@ -2070,8 +2025,8 @@
vha = pci_get_drvdata(ha->pdev);
for (iter = 1; iter--; ) {
- if (RD_REG_DWORD(®->host_int)) {
- stat = RD_REG_DWORD(®->host_status);
+ if (rd_reg_dword(®->host_int)) {
+ stat = rd_reg_dword(®->host_status);
switch (stat & 0xff) {
case 0x1:
@@ -2083,9 +2038,9 @@
break;
case 0x12:
mb[0] = MSW(stat);
- mb[1] = RD_REG_WORD(®->mailbox_out[1]);
- mb[2] = RD_REG_WORD(®->mailbox_out[2]);
- mb[3] = RD_REG_WORD(®->mailbox_out[3]);
+ mb[1] = rd_reg_word(®->mailbox_out[1]);
+ mb[2] = rd_reg_word(®->mailbox_out[2]);
+ mb[3] = rd_reg_word(®->mailbox_out[3]);
qla2x00_async_event(vha, rsp, mb);
break;
case 0x13:
@@ -2098,7 +2053,7 @@
break;
}
}
- WRT_REG_DWORD(®->host_int, 0);
+ wrt_reg_dword(®->host_int, 0);
}
qla2x00_handle_mbx_completion(ha, status);
@@ -2136,11 +2091,11 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
vha = pci_get_drvdata(ha->pdev);
do {
- host_int = RD_REG_DWORD(®->host_int);
+ host_int = rd_reg_dword(®->host_int);
if (qla2x00_check_reg32_for_disconnect(vha, host_int))
break;
if (host_int) {
- stat = RD_REG_DWORD(®->host_status);
+ stat = rd_reg_dword(®->host_status);
switch (stat & 0xff) {
case 0x1:
@@ -2152,9 +2107,9 @@
break;
case 0x12:
mb[0] = MSW(stat);
- mb[1] = RD_REG_WORD(®->mailbox_out[1]);
- mb[2] = RD_REG_WORD(®->mailbox_out[2]);
- mb[3] = RD_REG_WORD(®->mailbox_out[3]);
+ mb[1] = rd_reg_word(®->mailbox_out[1]);
+ mb[2] = rd_reg_word(®->mailbox_out[2]);
+ mb[3] = rd_reg_word(®->mailbox_out[3]);
qla2x00_async_event(vha, rsp, mb);
break;
case 0x13:
@@ -2167,7 +2122,7 @@
break;
}
}
- WRT_REG_DWORD(®->host_int, 0);
+ wrt_reg_dword(®->host_int, 0);
} while (0);
qla2x00_handle_mbx_completion(ha, status);
@@ -2197,11 +2152,11 @@
reg = &ha->iobase->isp82;
spin_lock_irqsave(&ha->hardware_lock, flags);
vha = pci_get_drvdata(ha->pdev);
- host_int = RD_REG_DWORD(®->host_int);
+ host_int = rd_reg_dword(®->host_int);
if (qla2x00_check_reg32_for_disconnect(vha, host_int))
goto out;
qla24xx_process_response_queue(vha, rsp);
- WRT_REG_DWORD(®->host_int, 0);
+ wrt_reg_dword(®->host_int, 0);
out:
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return IRQ_HANDLED;
@@ -2232,11 +2187,11 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
vha = pci_get_drvdata(ha->pdev);
- host_int = RD_REG_DWORD(®->host_int);
+ host_int = rd_reg_dword(®->host_int);
if (qla2x00_check_reg32_for_disconnect(vha, host_int))
goto out;
if (host_int) {
- stat = RD_REG_DWORD(®->host_status);
+ stat = rd_reg_dword(®->host_status);
switch (stat & 0xff) {
case 0x1:
case 0x2:
@@ -2247,9 +2202,9 @@
break;
case 0x12:
mb[0] = MSW(stat);
- mb[1] = RD_REG_WORD(®->mailbox_out[1]);
- mb[2] = RD_REG_WORD(®->mailbox_out[2]);
- mb[3] = RD_REG_WORD(®->mailbox_out[3]);
+ mb[1] = rd_reg_word(®->mailbox_out[1]);
+ mb[2] = rd_reg_word(®->mailbox_out[2]);
+ mb[3] = rd_reg_word(®->mailbox_out[3]);
qla2x00_async_event(vha, rsp, mb);
break;
case 0x13:
@@ -2261,7 +2216,7 @@
stat * 0xff);
break;
}
- WRT_REG_DWORD(®->host_int, 0);
+ wrt_reg_dword(®->host_int, 0);
}
out:
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -2550,8 +2505,8 @@
return qla82xx_check_rcvpeg_state(ha);
}
-static uint32_t *
-qla82xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
+static __le32 *
+qla82xx_read_flash_data(scsi_qla_host_t *vha, __le32 *dwptr, uint32_t faddr,
uint32_t length)
{
uint32_t i;
@@ -2676,13 +2631,13 @@
uint32_t offset, uint32_t length)
{
scsi_block_requests(vha->host);
- qla82xx_read_flash_data(vha, (uint32_t *)buf, offset, length);
+ qla82xx_read_flash_data(vha, buf, offset, length);
scsi_unblock_requests(vha->host);
return buf;
}
static int
-qla82xx_write_flash_data(struct scsi_qla_host *vha, uint32_t *dwptr,
+qla82xx_write_flash_data(struct scsi_qla_host *vha, __le32 *dwptr,
uint32_t faddr, uint32_t dwords)
{
int ret;
@@ -2759,7 +2714,7 @@
}
ret = qla82xx_write_flash_dword(ha, faddr,
- cpu_to_le32(*dwptr));
+ le32_to_cpu(*dwptr));
if (ret) {
ql_dbg(ql_dbg_p3p, vha, 0xb020,
"Unable to program flash address=%x data=%x.\n",
@@ -2819,10 +2774,10 @@
if (ql2xdbwr)
qla82xx_wr_32(ha, (unsigned long)ha->nxdb_wr_ptr, dbval);
else {
- WRT_REG_DWORD(ha->nxdb_wr_ptr, dbval);
+ wrt_reg_dword(ha->nxdb_wr_ptr, dbval);
wmb();
- while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) {
- WRT_REG_DWORD(ha->nxdb_wr_ptr, dbval);
+ while (rd_reg_dword(ha->nxdb_rd_ptr) != dbval) {
+ wrt_reg_dword(ha->nxdb_wr_ptr, dbval);
wmb();
}
}
@@ -3030,7 +2985,7 @@
/* Set DEV_FAILED flag to disable timer */
vha->device_flags |= DFLG_DEV_FAILED;
qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
- qla2x00_mark_all_devices_lost(vha, 0);
+ qla2x00_mark_all_devices_lost(vha);
vha->flags.online = 0;
vha->flags.init_done = 0;
}
@@ -3725,7 +3680,7 @@
/* Minidump related functions */
static int
qla82xx_minidump_process_control(scsi_qla_host_t *vha,
- qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+ qla82xx_md_entry_hdr_t *entry_hdr, __le32 **d_ptr)
{
struct qla_hw_data *ha = vha->hw;
struct qla82xx_md_entry_crb *crb_entry;
@@ -3842,12 +3797,12 @@
static void
qla82xx_minidump_process_rdocm(scsi_qla_host_t *vha,
- qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+ qla82xx_md_entry_hdr_t *entry_hdr, __le32 **d_ptr)
{
struct qla_hw_data *ha = vha->hw;
uint32_t r_addr, r_stride, loop_cnt, i, r_value;
struct qla82xx_md_entry_rdocm *ocm_hdr;
- uint32_t *data_ptr = *d_ptr;
+ __le32 *data_ptr = *d_ptr;
ocm_hdr = (struct qla82xx_md_entry_rdocm *)entry_hdr;
r_addr = ocm_hdr->read_addr;
@@ -3855,7 +3810,7 @@
loop_cnt = ocm_hdr->op_count;
for (i = 0; i < loop_cnt; i++) {
- r_value = RD_REG_DWORD(r_addr + ha->nx_pcibase);
+ r_value = rd_reg_dword(r_addr + ha->nx_pcibase);
*data_ptr++ = cpu_to_le32(r_value);
r_addr += r_stride;
}
@@ -3864,12 +3819,12 @@
static void
qla82xx_minidump_process_rdmux(scsi_qla_host_t *vha,
- qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+ qla82xx_md_entry_hdr_t *entry_hdr, __le32 **d_ptr)
{
struct qla_hw_data *ha = vha->hw;
uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value;
struct qla82xx_md_entry_mux *mux_hdr;
- uint32_t *data_ptr = *d_ptr;
+ __le32 *data_ptr = *d_ptr;
mux_hdr = (struct qla82xx_md_entry_mux *)entry_hdr;
r_addr = mux_hdr->read_addr;
@@ -3890,12 +3845,12 @@
static void
qla82xx_minidump_process_rdcrb(scsi_qla_host_t *vha,
- qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+ qla82xx_md_entry_hdr_t *entry_hdr, __le32 **d_ptr)
{
struct qla_hw_data *ha = vha->hw;
uint32_t r_addr, r_stride, loop_cnt, i, r_value;
struct qla82xx_md_entry_crb *crb_hdr;
- uint32_t *data_ptr = *d_ptr;
+ __le32 *data_ptr = *d_ptr;
crb_hdr = (struct qla82xx_md_entry_crb *)entry_hdr;
r_addr = crb_hdr->addr;
@@ -3913,7 +3868,7 @@
static int
qla82xx_minidump_process_l2tag(scsi_qla_host_t *vha,
- qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+ qla82xx_md_entry_hdr_t *entry_hdr, __le32 **d_ptr)
{
struct qla_hw_data *ha = vha->hw;
uint32_t addr, r_addr, c_addr, t_r_addr;
@@ -3922,7 +3877,7 @@
uint32_t c_value_w, c_value_r;
struct qla82xx_md_entry_cache *cache_hdr;
int rval = QLA_FUNCTION_FAILED;
- uint32_t *data_ptr = *d_ptr;
+ __le32 *data_ptr = *d_ptr;
cache_hdr = (struct qla82xx_md_entry_cache *)entry_hdr;
loop_count = cache_hdr->op_count;
@@ -3972,14 +3927,14 @@
static void
qla82xx_minidump_process_l1cache(scsi_qla_host_t *vha,
- qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+ qla82xx_md_entry_hdr_t *entry_hdr, __le32 **d_ptr)
{
struct qla_hw_data *ha = vha->hw;
uint32_t addr, r_addr, c_addr, t_r_addr;
uint32_t i, k, loop_count, t_value, r_cnt, r_value;
uint32_t c_value_w;
struct qla82xx_md_entry_cache *cache_hdr;
- uint32_t *data_ptr = *d_ptr;
+ __le32 *data_ptr = *d_ptr;
cache_hdr = (struct qla82xx_md_entry_cache *)entry_hdr;
loop_count = cache_hdr->op_count;
@@ -4007,14 +3962,14 @@
static void
qla82xx_minidump_process_queue(scsi_qla_host_t *vha,
- qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+ qla82xx_md_entry_hdr_t *entry_hdr, __le32 **d_ptr)
{
struct qla_hw_data *ha = vha->hw;
uint32_t s_addr, r_addr;
uint32_t r_stride, r_value, r_cnt, qid = 0;
uint32_t i, k, loop_cnt;
struct qla82xx_md_entry_queue *q_hdr;
- uint32_t *data_ptr = *d_ptr;
+ __le32 *data_ptr = *d_ptr;
q_hdr = (struct qla82xx_md_entry_queue *)entry_hdr;
s_addr = q_hdr->select_addr;
@@ -4037,13 +3992,13 @@
static void
qla82xx_minidump_process_rdrom(scsi_qla_host_t *vha,
- qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+ qla82xx_md_entry_hdr_t *entry_hdr, __le32 **d_ptr)
{
struct qla_hw_data *ha = vha->hw;
uint32_t r_addr, r_value;
uint32_t i, loop_cnt;
struct qla82xx_md_entry_rdrom *rom_hdr;
- uint32_t *data_ptr = *d_ptr;
+ __le32 *data_ptr = *d_ptr;
rom_hdr = (struct qla82xx_md_entry_rdrom *)entry_hdr;
r_addr = rom_hdr->read_addr;
@@ -4063,7 +4018,7 @@
static int
qla82xx_minidump_process_rdmem(scsi_qla_host_t *vha,
- qla82xx_md_entry_hdr_t *entry_hdr, uint32_t **d_ptr)
+ qla82xx_md_entry_hdr_t *entry_hdr, __le32 **d_ptr)
{
struct qla_hw_data *ha = vha->hw;
uint32_t r_addr, r_value, r_data;
@@ -4071,7 +4026,7 @@
struct qla82xx_md_entry_rdmem *m_hdr;
unsigned long flags;
int rval = QLA_FUNCTION_FAILED;
- uint32_t *data_ptr = *d_ptr;
+ __le32 *data_ptr = *d_ptr;
m_hdr = (struct qla82xx_md_entry_rdmem *)entry_hdr;
r_addr = m_hdr->read_addr;
@@ -4164,12 +4119,12 @@
int no_entry_hdr = 0;
qla82xx_md_entry_hdr_t *entry_hdr;
struct qla82xx_md_template_hdr *tmplt_hdr;
- uint32_t *data_ptr;
+ __le32 *data_ptr;
uint32_t total_data_size = 0, f_capture_mask, data_collected = 0;
int i = 0, rval = QLA_FUNCTION_FAILED;
tmplt_hdr = (struct qla82xx_md_template_hdr *)ha->md_tmplt_hdr;
- data_ptr = (uint32_t *)ha->md_dump;
+ data_ptr = ha->md_dump;
if (ha->fw_dumped) {
ql_log(ql_log_warn, vha, 0xb037,
@@ -4178,7 +4133,7 @@
goto md_failed;
}
- ha->fw_dumped = 0;
+ ha->fw_dumped = false;
if (!ha->md_tmplt_hdr || !ha->md_dump) {
ql_log(ql_log_warn, vha, 0xb038,
@@ -4358,7 +4313,7 @@
ql_log(ql_log_info, vha, 0xb044,
"Firmware dump saved to temp buffer (%ld/%p %ld/%p).\n",
vha->host_no, ha->md_tmplt_hdr, vha->host_no, ha->md_dump);
- ha->fw_dumped = 1;
+ ha->fw_dumped = true;
qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP);
md_failed:
@@ -4515,7 +4470,7 @@
}
void
-qla82xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
+qla82xx_fw_dump(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h
index 230abee..8567eaf 100644
--- a/drivers/scsi/qla2xxx/qla_nx.h
+++ b/drivers/scsi/qla2xxx/qla_nx.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#ifndef __QLA_NX_H
#define __QLA_NX_H
@@ -800,16 +799,16 @@
#define QLA82XX_URI_FIRMWARE_IDX_OFF 29
struct qla82xx_uri_table_desc{
- uint32_t findex;
- uint32_t num_entries;
- uint32_t entry_size;
- uint32_t reserved[5];
+ __le32 findex;
+ __le32 num_entries;
+ __le32 entry_size;
+ __le32 reserved[5];
};
struct qla82xx_uri_data_desc{
- uint32_t findex;
- uint32_t size;
- uint32_t reserved[5];
+ __le32 findex;
+ __le32 size;
+ __le32 reserved[5];
};
/* UNIFIED ROMIMAGE END */
@@ -829,22 +828,22 @@
* ISP 8021 I/O Register Set structure definitions.
*/
struct device_reg_82xx {
- uint32_t req_q_out[64]; /* Request Queue out-Pointer (64 * 4) */
- uint32_t rsp_q_in[64]; /* Response Queue In-Pointer. */
- uint32_t rsp_q_out[64]; /* Response Queue Out-Pointer. */
+ __le32 req_q_out[64]; /* Request Queue out-Pointer (64 * 4) */
+ __le32 rsp_q_in[64]; /* Response Queue In-Pointer. */
+ __le32 rsp_q_out[64]; /* Response Queue Out-Pointer. */
- uint16_t mailbox_in[32]; /* Mail box In registers */
- uint16_t unused_1[32];
- uint32_t hint; /* Host interrupt register */
+ __le16 mailbox_in[32]; /* Mailbox In registers */
+ __le16 unused_1[32];
+ __le32 hint; /* Host interrupt register */
#define HINT_MBX_INT_PENDING BIT_0
- uint16_t unused_2[62];
- uint16_t mailbox_out[32]; /* Mail box Out registers */
- uint32_t unused_3[48];
+ __le16 unused_2[62];
+ __le16 mailbox_out[32]; /* Mailbox Out registers */
+ __le32 unused_3[48];
- uint32_t host_status; /* host status */
+ __le32 host_status; /* host status */
#define HSRX_RISC_INT BIT_15 /* RISC to Host interrupt. */
#define HSRX_RISC_PAUSED BIT_8 /* RISC Paused. */
- uint32_t host_int; /* Interrupt status. */
+ __le32 host_int; /* Interrupt status. */
#define ISRX_NX_RISC_INT BIT_0 /* RISC interrupt. */
};
diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c
index c056f46..01ccd45 100644
--- a/drivers/scsi/qla2xxx/qla_nx2.c
+++ b/drivers/scsi/qla2xxx/qla_nx2.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include <linux/vmalloc.h>
@@ -660,7 +659,7 @@
qla8044_poll_reg(struct scsi_qla_host *vha, uint32_t addr,
int duration, uint32_t test_mask, uint32_t test_result)
{
- uint32_t value;
+ uint32_t value = 0;
int timeout_error;
uint8_t retries;
int ret_val = QLA_SUCCESS;
@@ -1441,7 +1440,7 @@
if (idc_ctrl & GRACEFUL_RESET_BIT1) {
qla8044_wr_reg(ha, QLA8044_IDC_DRV_CTRL,
(idc_ctrl & ~GRACEFUL_RESET_BIT1));
- ha->fw_dumped = 0;
+ ha->fw_dumped = false;
}
dev_ready:
@@ -2965,7 +2964,7 @@
/* Prepare: Write pex-dma descriptor to MS memory. */
rval = qla8044_ms_mem_write_128b(vha,
- m_hdr->desc_card_addr, (void *)&dma_desc,
+ m_hdr->desc_card_addr, (uint32_t *)&dma_desc,
(sizeof(struct qla8044_pex_dma_descriptor)/16));
if (rval) {
ql_log(ql_log_warn, vha, 0xb14a,
@@ -2987,7 +2986,7 @@
read_size += chunk_size;
}
- *d_ptr = (void *)data_ptr;
+ *d_ptr = (uint32_t *)data_ptr;
error_exit:
if (rdmem_buffer)
@@ -3249,7 +3248,7 @@
goto md_failed;
}
- ha->fw_dumped = 0;
+ ha->fw_dumped = false;
if (!ha->md_tmplt_hdr || !ha->md_dump) {
ql_log(ql_log_warn, vha, 0xb10e,
@@ -3470,7 +3469,7 @@
ql_log(ql_log_info, vha, 0xb110,
"Firmware dump saved to temp buffer (%ld/%p %ld/%p).\n",
vha->host_no, ha->md_tmplt_hdr, vha->host_no, ha->md_dump);
- ha->fw_dumped = 1;
+ ha->fw_dumped = true;
qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP);
@@ -3487,7 +3486,7 @@
struct qla_hw_data *ha = vha->hw;
if (!qla8044_collect_md_data(vha)) {
- ha->fw_dumped = 1;
+ ha->fw_dumped = true;
ha->prev_minidump_failed = 0;
} else {
ql_log(ql_log_fatal, vha, 0xb0db,
@@ -3946,8 +3945,8 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
for (iter = 1; iter--; ) {
- if (RD_REG_DWORD(®->host_int)) {
- stat = RD_REG_DWORD(®->host_status);
+ if (rd_reg_dword(®->host_int)) {
+ stat = rd_reg_dword(®->host_status);
if ((stat & HSRX_RISC_INT) == 0)
break;
@@ -3961,9 +3960,9 @@
break;
case 0x12:
mb[0] = MSW(stat);
- mb[1] = RD_REG_WORD(®->mailbox_out[1]);
- mb[2] = RD_REG_WORD(®->mailbox_out[2]);
- mb[3] = RD_REG_WORD(®->mailbox_out[3]);
+ mb[1] = rd_reg_word(®->mailbox_out[1]);
+ mb[2] = rd_reg_word(®->mailbox_out[2]);
+ mb[3] = rd_reg_word(®->mailbox_out[3]);
qla2x00_async_event(vha, rsp, mb);
break;
case 0x13:
@@ -3976,7 +3975,7 @@
break;
}
}
- WRT_REG_DWORD(®->host_int, 0);
+ wrt_reg_dword(®->host_int, 0);
}
qla2x00_handle_mbx_completion(ha, status);
@@ -4070,7 +4069,7 @@
}
void
-qla8044_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
+qla8044_fw_dump(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
diff --git a/drivers/scsi/qla2xxx/qla_nx2.h b/drivers/scsi/qla2xxx/qla_nx2.h
index 8ba7c1d..2fc902a 100644
--- a/drivers/scsi/qla2xxx/qla_nx2.h
+++ b/drivers/scsi/qla2xxx/qla_nx2.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#ifndef __QLA_NX2_H
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 28cbefe..e7f73a1 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
@@ -36,6 +35,16 @@
*/
struct kmem_cache *srb_cachep;
+int ql2xfulldump_on_mpifail;
+module_param(ql2xfulldump_on_mpifail, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ql2xfulldump_on_mpifail,
+ "Set this to take full dump on MPI hang.");
+
+int ql2xenforce_iocb_limit = 1;
+module_param(ql2xenforce_iocb_limit, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ql2xenforce_iocb_limit,
+ "Enforce IOCB throttling, to avoid FW congestion. (default: 1)");
+
/*
* CT6 CTX allocation cache
*/
@@ -114,7 +123,8 @@
module_param_named(fdmi, ql2xfdmienable, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xfdmienable,
"Enables FDMI registrations. "
- "0 - no FDMI. Default is 1 - perform FDMI.");
+ "0 - no FDMI registrations. "
+ "1 - provide FDMI registrations (default).");
#define MAX_Q_DEPTH 64
static int ql2xmaxqdepth = MAX_Q_DEPTH;
@@ -123,11 +133,7 @@
"Maximum queue depth to set for each LUN. "
"Default is 64.");
-#if (IS_ENABLED(CONFIG_NVME_FC))
-int ql2xenabledif;
-#else
int ql2xenabledif = 2;
-#endif
module_param(ql2xenabledif, int, S_IRUGO);
MODULE_PARM_DESC(ql2xenabledif,
" Enable T10-CRC-DIF:\n"
@@ -191,12 +197,6 @@
" 0 -- Regular doorbell.\n"
" 1 -- CAMRAM doorbell (faster).\n");
-int ql2xtargetreset = 1;
-module_param(ql2xtargetreset, int, S_IRUGO);
-MODULE_PARM_DESC(ql2xtargetreset,
- "Enable target reset."
- "Default is 1 - use hw defaults.");
-
int ql2xgffidenable;
module_param(ql2xgffidenable, int, S_IRUGO);
MODULE_PARM_DESC(ql2xgffidenable,
@@ -307,6 +307,22 @@
"0 (Default). Based on check.\n"
"1 Force using internal buffers\n");
+int ql2xsmartsan;
+module_param(ql2xsmartsan, int, 0444);
+module_param_named(smartsan, ql2xsmartsan, int, 0444);
+MODULE_PARM_DESC(ql2xsmartsan,
+ "Send SmartSAN Management Attributes for FDMI Registration."
+ " Default is 0 - No SmartSAN registration,"
+ " 1 - Register SmartSAN Management Attributes.");
+
+int ql2xrdpenable;
+module_param(ql2xrdpenable, int, 0444);
+module_param_named(rdpenable, ql2xrdpenable, int, 0444);
+MODULE_PARM_DESC(ql2xrdpenable,
+ "Enables RDP responses. "
+ "0 - no RDP responses (default). "
+ "1 - provide RDP responses.");
+
static void qla2x00_clear_drv_active(struct qla_hw_data *);
static void qla2x00_free_device(scsi_qla_host_t *);
static int qla2xxx_map_queues(struct Scsi_Host *shost);
@@ -584,6 +600,9 @@
case 3:
speed_str = "8.0GT/s";
break;
+ case 4:
+ speed_str = "16.0GT/s";
+ break;
default:
speed_str = "<unknown>";
break;
@@ -865,7 +884,7 @@
goto qc24_fail_command;
}
- if (atomic_read(&fcport->state) != FCS_ONLINE) {
+ if (atomic_read(&fcport->state) != FCS_ONLINE || fcport->deleted) {
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
ql_dbg(ql_dbg_io, vha, 0x3005,
@@ -947,7 +966,7 @@
goto qc24_fail_command;
}
- if (atomic_read(&fcport->state) != FCS_ONLINE) {
+ if (atomic_read(&fcport->state) != FCS_ONLINE || fcport->deleted) {
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
ql_dbg(ql_dbg_io, vha, 0x3077,
@@ -1104,7 +1123,7 @@
{
u8 i;
- qla2x00_mark_all_devices_lost(vha, 0);
+ qla2x00_mark_all_devices_lost(vha);
for (i = 0; i < 10; i++) {
if (wait_event_timeout(vha->fcport_waitQ,
@@ -1194,9 +1213,9 @@
struct device_reg_82xx __iomem *reg82 = &ha->iobase->isp82;
if (IS_P3P_TYPE(ha))
- return ((RD_REG_DWORD(®82->host_int)) == ISP_REG_DISCONNECT);
+ return ((rd_reg_dword(®82->host_int)) == ISP_REG_DISCONNECT);
else
- return ((RD_REG_DWORD(®->host_status)) ==
+ return ((rd_reg_dword(®->host_status)) ==
ISP_REG_DISCONNECT);
}
@@ -1229,6 +1248,7 @@
uint32_t ratov_j;
struct qla_qpair *qpair;
unsigned long flags;
+ int fast_fail_status = SUCCESS;
if (qla2x00_isp_reg_stat(ha)) {
ql_log(ql_log_info, vha, 0x8042,
@@ -1236,28 +1256,18 @@
return FAILED;
}
+ /* Save any FAST_IO_FAIL value to return later if abort succeeds */
ret = fc_block_scsi_eh(cmd);
if (ret != 0)
- return ret;
+ fast_fail_status = ret;
sp = scsi_cmd_priv(cmd);
qpair = sp->qpair;
if ((sp->fcport && sp->fcport->deleted) || !qpair)
- return SUCCESS;
+ return fast_fail_status != SUCCESS ? fast_fail_status : FAILED;
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
- if (sp->completed) {
- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
- return SUCCESS;
- }
-
- if (sp->abort || sp->aborted) {
- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
- return FAILED;
- }
-
- sp->abort = 1;
sp->comp = ∁
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
@@ -1290,7 +1300,7 @@
__func__, ha->r_a_tov/10);
ret = FAILED;
} else {
- ret = SUCCESS;
+ ret = fast_fail_status;
}
break;
default:
@@ -1636,32 +1646,15 @@
qla2x00_loop_reset(scsi_qla_host_t *vha)
{
int ret;
- struct fc_port *fcport;
struct qla_hw_data *ha = vha->hw;
- if (IS_QLAFX00(ha)) {
- return qlafx00_loop_reset(vha);
- }
-
- if (ql2xtargetreset == 1 && ha->flags.enable_target_reset) {
- list_for_each_entry(fcport, &vha->vp_fcports, list) {
- if (fcport->port_type != FCT_TARGET)
- continue;
-
- ret = ha->isp_ops->target_reset(fcport, 0, 0);
- if (ret != QLA_SUCCESS) {
- ql_dbg(ql_dbg_taskm, vha, 0x802c,
- "Bus Reset failed: Reset=%d "
- "d_id=%x.\n", ret, fcport->d_id.b24);
- }
- }
- }
-
+ if (IS_QLAFX00(ha))
+ return QLA_SUCCESS;
if (ha->flags.enable_lip_full_login && !IS_CNA_CAPABLE(ha)) {
atomic_set(&vha->loop_state, LOOP_DOWN);
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
- qla2x00_mark_all_devices_lost(vha, 0);
+ qla2x00_mark_all_devices_lost(vha);
ret = qla2x00_full_login_lip(vha);
if (ret != QLA_SUCCESS) {
ql_dbg(ql_dbg_taskm, vha, 0x802d,
@@ -1682,6 +1675,10 @@
return QLA_SUCCESS;
}
+/*
+ * The caller must ensure that no completion interrupts will happen
+ * while this function is in progress.
+ */
static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res,
unsigned long *flags)
__releases(qp->qp_lock_ptr)
@@ -1690,10 +1687,13 @@
DECLARE_COMPLETION_ONSTACK(comp);
scsi_qla_host_t *vha = qp->vha;
struct qla_hw_data *ha = vha->hw;
+ struct scsi_cmnd *cmd = GET_CMD_SP(sp);
int rval;
bool ret_cmd;
uint32_t ratov_j;
+ lockdep_assert_held(qp->qp_lock_ptr);
+
if (qla2x00_chip_is_down(vha)) {
sp->done(sp, res);
return;
@@ -1709,7 +1709,6 @@
}
sp->comp = ∁
- sp->abort = 1;
spin_unlock_irqrestore(qp->qp_lock_ptr, *flags);
rval = ha->isp_ops->abort_command(sp);
@@ -1733,13 +1732,17 @@
}
spin_lock_irqsave(qp->qp_lock_ptr, *flags);
- if (ret_cmd && (!sp->completed || !sp->aborted))
+ if (ret_cmd && blk_mq_request_started(cmd->request))
sp->done(sp, res);
} else {
sp->done(sp, res);
}
}
+/*
+ * The caller must ensure that no completion interrupts will happen
+ * while this function is in progress.
+ */
static void
__qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
{
@@ -1786,6 +1789,10 @@
spin_unlock_irqrestore(qp->qp_lock_ptr, flags);
}
+/*
+ * The caller must ensure that no completion interrupts will happen
+ * while this function is in progress.
+ */
void
qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
{
@@ -1855,7 +1862,7 @@
if (!dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(64))) {
/* Any upper-dword bits set? */
if (MSD(dma_get_required_mask(&ha->pdev->dev)) &&
- !pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(64))) {
+ !dma_set_coherent_mask(&ha->pdev->dev, DMA_BIT_MASK(64))) {
/* Ok, a 64bit DMA mask is applicable. */
ha->flags.enable_64bit_addressing = 1;
ha->isp_ops->calc_req_entries = qla2x00_calc_iocbs_64;
@@ -1865,7 +1872,7 @@
}
dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(32));
- pci_set_consistent_dma_mask(ha->pdev, DMA_BIT_MASK(32));
+ dma_set_coherent_mask(&ha->pdev->dev, DMA_BIT_MASK(32));
}
static void
@@ -1877,8 +1884,8 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->interrupts_on = 1;
/* enable risc and host interrupts */
- WRT_REG_WORD(®->ictrl, ICR_EN_INT | ICR_EN_RISC);
- RD_REG_WORD(®->ictrl);
+ wrt_reg_word(®->ictrl, ICR_EN_INT | ICR_EN_RISC);
+ rd_reg_word(®->ictrl);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
@@ -1892,8 +1899,8 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->interrupts_on = 0;
/* disable risc and host interrupts */
- WRT_REG_WORD(®->ictrl, 0);
- RD_REG_WORD(®->ictrl);
+ wrt_reg_word(®->ictrl, 0);
+ rd_reg_word(®->ictrl);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
@@ -1905,8 +1912,8 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->interrupts_on = 1;
- WRT_REG_DWORD(®->ictrl, ICRX_EN_RISC_INT);
- RD_REG_DWORD(®->ictrl);
+ wrt_reg_dword(®->ictrl, ICRX_EN_RISC_INT);
+ rd_reg_dword(®->ictrl);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
@@ -1920,8 +1927,8 @@
return;
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->interrupts_on = 0;
- WRT_REG_DWORD(®->ictrl, 0);
- RD_REG_DWORD(®->ictrl);
+ wrt_reg_dword(®->ictrl, 0);
+ rd_reg_dword(®->ictrl);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
@@ -2284,7 +2291,7 @@
.config_rings = qla24xx_config_rings,
.reset_adapter = qla24xx_reset_adapter,
.nvram_config = qla81xx_nvram_config,
- .update_fw_options = qla81xx_update_fw_options,
+ .update_fw_options = qla24xx_update_fw_options,
.load_risc = qla81xx_load_risc,
.pci_info_str = qla24xx_pci_info_str,
.fw_version_str = qla24xx_fw_version_str,
@@ -2401,7 +2408,7 @@
.config_rings = qla24xx_config_rings,
.reset_adapter = qla24xx_reset_adapter,
.nvram_config = qla81xx_nvram_config,
- .update_fw_options = qla81xx_update_fw_options,
+ .update_fw_options = qla24xx_update_fw_options,
.load_risc = qla81xx_load_risc,
.pci_info_str = qla24xx_pci_info_str,
.fw_version_str = qla24xx_fw_version_str,
@@ -2498,6 +2505,7 @@
.read_nvram = NULL,
.write_nvram = NULL,
.fw_dump = qla27xx_fwdump,
+ .mpi_fw_dump = qla27xx_mpi_fwdump,
.beacon_on = qla24xx_beacon_on,
.beacon_off = qla24xx_beacon_off,
.beacon_blink = qla83xx_beacon_blink,
@@ -3290,6 +3298,7 @@
for (i = 0; i < ha->max_qpairs; i++)
qla2xxx_create_qpair(base_vha, 5, 0, startit);
}
+ qla_init_iocb_limit(base_vha);
if (ha->flags.running_gold_fw)
goto skip_dpc;
@@ -3439,13 +3448,6 @@
if (test_bit(UNLOADING, &base_vha->dpc_flags))
return -ENODEV;
- if (ha->flags.detected_lr_sfp) {
- ql_log(ql_log_info, base_vha, 0xffff,
- "Reset chip to pick up LR SFP setting\n");
- set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
- qla2xxx_wake_dpc(base_vha);
- }
-
return 0;
probe_failed:
@@ -3502,6 +3504,29 @@
return ret;
}
+static void __qla_set_remove_flag(scsi_qla_host_t *base_vha)
+{
+ scsi_qla_host_t *vp;
+ unsigned long flags;
+ struct qla_hw_data *ha;
+
+ if (!base_vha)
+ return;
+
+ ha = base_vha->hw;
+
+ spin_lock_irqsave(&ha->vport_slock, flags);
+ list_for_each_entry(vp, &ha->vp_list, list)
+ set_bit(PFLG_DRIVER_REMOVING, &vp->pci_flags);
+
+ /*
+ * Indicate device removal to prevent future board_disable
+ * and wait until any pending board_disable has completed.
+ */
+ set_bit(PFLG_DRIVER_REMOVING, &base_vha->pci_flags);
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
+}
+
static void
qla2x00_shutdown(struct pci_dev *pdev)
{
@@ -3518,7 +3543,7 @@
* Prevent future board_disable and wait
* until any pending board_disable has completed.
*/
- set_bit(PFLG_DRIVER_REMOVING, &vha->pci_flags);
+ __qla_set_remove_flag(vha);
cancel_work_sync(&ha->board_disable);
if (!atomic_read(&pdev->enable_cnt))
@@ -3678,10 +3703,7 @@
ha = base_vha->hw;
ql_log(ql_log_info, base_vha, 0xb079,
"Removing driver\n");
-
- /* Indicate device removal to prevent future board_disable and wait
- * until any pending board_disable has completed. */
- set_bit(PFLG_DRIVER_REMOVING, &base_vha->pci_flags);
+ __qla_set_remove_flag(base_vha);
cancel_work_sync(&ha->board_disable);
/*
@@ -3784,6 +3806,20 @@
pci_disable_device(pdev);
}
+static inline void
+qla24xx_free_purex_list(struct purex_list *list)
+{
+ struct list_head *item, *next;
+ ulong flags;
+
+ spin_lock_irqsave(&list->lock, flags);
+ list_for_each_safe(item, next, &list->head) {
+ list_del(item);
+ kfree(list_entry(item, struct purex_item, list));
+ }
+ spin_unlock_irqrestore(&list->lock, flags);
+}
+
static void
qla2x00_free_device(scsi_qla_host_t *vha)
{
@@ -3816,6 +3852,8 @@
}
+ qla24xx_free_purex_list(&vha->purex_list);
+
qla2x00_mem_free(ha);
qla82xx_md_free(vha);
@@ -3832,37 +3870,21 @@
}
static inline void
-qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
- int defer)
+qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport)
{
- struct fc_rport *rport;
- scsi_qla_host_t *base_vha;
- unsigned long flags;
+ int now;
if (!fcport->rport)
return;
- rport = fcport->rport;
- if (defer) {
- base_vha = pci_get_drvdata(vha->hw->pdev);
- spin_lock_irqsave(vha->host->host_lock, flags);
- fcport->drport = rport;
- spin_unlock_irqrestore(vha->host->host_lock, flags);
- qlt_do_generation_tick(vha, &base_vha->total_fcport_update_gen);
- set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
- qla2xxx_wake_dpc(base_vha);
- } else {
- int now;
-
- if (rport) {
- ql_dbg(ql_dbg_disc, fcport->vha, 0x2109,
- "%s %8phN. rport %p roles %x\n",
- __func__, fcport->port_name, rport,
- rport->roles);
- fc_remote_port_delete(rport);
- }
- qlt_do_generation_tick(vha, &now);
+ if (fcport->rport) {
+ ql_dbg(ql_dbg_disc, fcport->vha, 0x2109,
+ "%s %8phN. rport %p roles %x\n",
+ __func__, fcport->port_name, fcport->rport,
+ fcport->rport->roles);
+ fc_remote_port_delete(fcport->rport);
}
+ qlt_do_generation_tick(vha, &now);
}
/*
@@ -3875,18 +3897,18 @@
* Context:
*/
void qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport,
- int do_login, int defer)
+ int do_login)
{
if (IS_QLAFX00(vha->hw)) {
qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
- qla2x00_schedule_rport_del(vha, fcport, defer);
+ qla2x00_schedule_rport_del(vha, fcport);
return;
}
if (atomic_read(&fcport->state) == FCS_ONLINE &&
vha->vp_idx == fcport->vha->vp_idx) {
qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
- qla2x00_schedule_rport_del(vha, fcport, defer);
+ qla2x00_schedule_rport_del(vha, fcport);
}
/*
* We may need to retry the login, so don't change the state of the
@@ -3901,21 +3923,8 @@
set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
}
-/*
- * qla2x00_mark_all_devices_lost
- * Updates fcport state when device goes offline.
- *
- * Input:
- * ha = adapter block pointer.
- * fcport = port structure pointer.
- *
- * Return:
- * None.
- *
- * Context:
- */
void
-qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer)
+qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha)
{
fc_port_t *fcport;
@@ -3923,25 +3932,18 @@
"Mark all dev lost\n");
list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if (fcport->loop_id != FC_NO_LOOP_ID &&
+ (fcport->flags & FCF_FCP2_DEVICE) &&
+ fcport->port_type == FCT_TARGET &&
+ !qla2x00_reset_active(vha)) {
+ ql_dbg(ql_dbg_disc, vha, 0x211a,
+ "Delaying session delete for FCP2 flags 0x%x port_type = 0x%x port_id=%06x %phC",
+ fcport->flags, fcport->port_type,
+ fcport->d_id.b24, fcport->port_name);
+ continue;
+ }
fcport->scan_state = 0;
qlt_schedule_sess_for_deletion(fcport);
-
- if (vha->vp_idx != 0 && vha->vp_idx != fcport->vha->vp_idx)
- continue;
-
- /*
- * No point in marking the device as lost, if the device is
- * already DEAD.
- */
- if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
- continue;
- if (atomic_read(&fcport->state) == FCS_ONLINE) {
- qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
- if (defer)
- qla2x00_schedule_rport_del(vha, fcport, defer);
- else if (vha->vp_idx == fcport->vha->vp_idx)
- qla2x00_schedule_rport_del(vha, fcport, defer);
- }
}
}
@@ -4064,7 +4066,7 @@
ql_dbg_pci(ql_dbg_init, ha->pdev,
0xe0ee, "%s: failed alloc dsd\n",
__func__);
- return 1;
+ return -ENOMEM;
}
ha->dif_bundle_kallocs++;
@@ -4210,6 +4212,17 @@
"ex_init_cb=%p.\n", ha->ex_init_cb);
}
+ /* Get consistent memory allocated for Special Features-CB. */
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ ha->sf_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
+ &ha->sf_init_cb_dma);
+ if (!ha->sf_init_cb)
+ goto fail_sf_init_cb;
+ memset(ha->sf_init_cb, 0, sizeof(struct init_sf_cb));
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0199,
+ "sf_init_cb=%p.\n", ha->sf_init_cb);
+ }
+
INIT_LIST_HEAD(&ha->gbl_dsd_list);
/* Get consistent memory allocated for Async Port-Database. */
@@ -4263,6 +4276,8 @@
fail_loop_id_map:
dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma);
fail_async_pd:
+ dma_pool_free(ha->s_dma_pool, ha->sf_init_cb, ha->sf_init_cb_dma);
+fail_sf_init_cb:
dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma);
fail_ex_init_cb:
kfree(ha->npiv_info);
@@ -4358,11 +4373,12 @@
qla2x00_set_exlogins_buffer(scsi_qla_host_t *vha)
{
int rval;
- uint16_t size, max_cnt, temp;
+ uint16_t size, max_cnt;
+ uint32_t temp;
struct qla_hw_data *ha = vha->hw;
/* Return if we don't need to alloacate any extended logins */
- if (!ql2xexlogins)
+ if (ql2xexlogins <= MAX_FIBRE_DEVICES_2400)
return QLA_SUCCESS;
if (!IS_EXLOGIN_OFFLD_CAPABLE(ha))
@@ -4612,7 +4628,7 @@
ha->flags.fce_enabled = 0;
ha->eft = NULL;
ha->eft_dma = 0;
- ha->fw_dumped = 0;
+ ha->fw_dumped = false;
ha->fw_dump_cap_flags = 0;
ha->fw_dump_reading = 0;
ha->fw_dump = NULL;
@@ -4685,6 +4701,10 @@
ha->ms_iocb = NULL;
ha->ms_iocb_dma = 0;
+ if (ha->sf_init_cb)
+ dma_pool_free(ha->s_dma_pool,
+ ha->sf_init_cb, ha->sf_init_cb_dma);
+
if (ha->ex_init_cb)
dma_pool_free(ha->s_dma_pool,
ha->ex_init_cb, ha->ex_init_cb_dma);
@@ -4772,6 +4792,8 @@
kfree(ha->swl);
ha->swl = NULL;
kfree(ha->loop_id_map);
+ ha->sf_init_cb = NULL;
+ ha->sf_init_cb_dma = 0;
ha->loop_id_map = NULL;
}
@@ -4812,6 +4834,9 @@
INIT_LIST_HEAD(&vha->gpnid_list);
INIT_WORK(&vha->iocb_work, qla2x00_iocb_work_fn);
+ INIT_LIST_HEAD(&vha->purex_list.head);
+ spin_lock_init(&vha->purex_list.lock);
+
spin_lock_init(&vha->work_lock);
spin_lock_init(&vha->cmd_list_lock);
init_waitqueue_head(&vha->fcport_waitQ);
@@ -4842,7 +4867,7 @@
}
INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn);
- sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
+ sprintf(vha->host_str, "%s_%lu", QLA2XXX_DRIVER_NAME, vha->host_no);
ql_dbg(ql_dbg_init, vha, 0x0041,
"Allocated the host=%p hw=%p vha=%p dev_name=%s",
vha->host, vha->hw, vha,
@@ -4946,7 +4971,6 @@
qla2x00_post_async_work(login, QLA_EVT_ASYNC_LOGIN);
qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT);
-qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE);
qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC);
qla2x00_post_async_work(prlo, QLA_EVT_ASYNC_PRLO);
qla2x00_post_async_work(prlo_done, QLA_EVT_ASYNC_PRLO_DONE);
@@ -4972,7 +4996,7 @@
switch (code) {
case QLA_UEVENT_CODE_FW_DUMP:
- snprintf(event_string, sizeof(event_string), "FW_DUMP=%ld",
+ snprintf(event_string, sizeof(event_string), "FW_DUMP=%lu",
vha->host_no);
break;
default:
@@ -5060,6 +5084,8 @@
fcport->fc4_type = e->u.new_sess.fc4_type;
if (e->u.new_sess.fc4_type & FS_FCP_IS_N2N) {
+ fcport->dm_login_expire = jiffies +
+ QLA_N2N_WAIT_TIME * HZ;
fcport->fc4_type = FS_FC4TYPE_FCP;
fcport->n2n_flag = 1;
if (vha->flags.nvme_enabled)
@@ -5173,9 +5199,8 @@
fcport->n2n_flag = 1;
}
fcport->fw_login_state = 0;
- /*
- * wait link init done before sending login
- */
+
+ schedule_delayed_work(&vha->scan.scan_work, 5);
} else {
qla24xx_fcport_handle_login(vha, fcport);
}
@@ -5234,10 +5259,6 @@
case QLA_EVT_ASYNC_LOGOUT:
rc = qla2x00_async_logout(vha, e->u.logio.fcport);
break;
- case QLA_EVT_ASYNC_LOGOUT_DONE:
- qla2x00_async_logout_done(vha, e->u.logio.fcport,
- e->u.logio.data);
- break;
case QLA_EVT_ASYNC_ADISC:
qla2x00_async_adisc(vha, e->u.logio.fcport,
e->u.logio.data);
@@ -5740,6 +5761,492 @@
return;
}
+static bool
+qla25xx_rdp_rsp_reduce_size(struct scsi_qla_host *vha,
+ struct purex_entry_24xx *purex)
+{
+ char fwstr[16];
+ u32 sid = purex->s_id[2] << 16 | purex->s_id[1] << 8 | purex->s_id[0];
+ struct port_database_24xx *pdb;
+
+ /* Domain Controller is always logged-out. */
+ /* if RDP request is not from Domain Controller: */
+ if (sid != 0xfffc01)
+ return false;
+
+ ql_dbg(ql_dbg_init, vha, 0x0181, "%s: s_id=%#x\n", __func__, sid);
+
+ pdb = kzalloc(sizeof(*pdb), GFP_KERNEL);
+ if (!pdb) {
+ ql_dbg(ql_dbg_init, vha, 0x0181,
+ "%s: Failed allocate pdb\n", __func__);
+ } else if (qla24xx_get_port_database(vha,
+ le16_to_cpu(purex->nport_handle), pdb)) {
+ ql_dbg(ql_dbg_init, vha, 0x0181,
+ "%s: Failed get pdb sid=%x\n", __func__, sid);
+ } else if (pdb->current_login_state != PDS_PLOGI_COMPLETE &&
+ pdb->current_login_state != PDS_PRLI_COMPLETE) {
+ ql_dbg(ql_dbg_init, vha, 0x0181,
+ "%s: Port not logged in sid=%#x\n", __func__, sid);
+ } else {
+ /* RDP request is from logged in port */
+ kfree(pdb);
+ return false;
+ }
+ kfree(pdb);
+
+ vha->hw->isp_ops->fw_version_str(vha, fwstr, sizeof(fwstr));
+ fwstr[strcspn(fwstr, " ")] = 0;
+ /* if FW version allows RDP response length upto 2048 bytes: */
+ if (strcmp(fwstr, "8.09.00") > 0 || strcmp(fwstr, "8.05.65") == 0)
+ return false;
+
+ ql_dbg(ql_dbg_init, vha, 0x0181, "%s: fw=%s\n", __func__, fwstr);
+
+ /* RDP response length is to be reduced to maximum 256 bytes */
+ return true;
+}
+
+/*
+ * Function Name: qla24xx_process_purex_iocb
+ *
+ * Description:
+ * Prepare a RDP response and send to Fabric switch
+ *
+ * PARAMETERS:
+ * vha: SCSI qla host
+ * purex: RDP request received by HBA
+ */
+void qla24xx_process_purex_rdp(struct scsi_qla_host *vha,
+ struct purex_item *item)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct purex_entry_24xx *purex =
+ (struct purex_entry_24xx *)&item->iocb;
+ dma_addr_t rsp_els_dma;
+ dma_addr_t rsp_payload_dma;
+ dma_addr_t stat_dma;
+ dma_addr_t sfp_dma;
+ struct els_entry_24xx *rsp_els = NULL;
+ struct rdp_rsp_payload *rsp_payload = NULL;
+ struct link_statistics *stat = NULL;
+ uint8_t *sfp = NULL;
+ uint16_t sfp_flags = 0;
+ uint rsp_payload_length = sizeof(*rsp_payload);
+ int rval;
+
+ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0180,
+ "%s: Enter\n", __func__);
+
+ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0181,
+ "-------- ELS REQ -------\n");
+ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0182,
+ purex, sizeof(*purex));
+
+ if (qla25xx_rdp_rsp_reduce_size(vha, purex)) {
+ rsp_payload_length =
+ offsetof(typeof(*rsp_payload), optical_elmt_desc);
+ ql_dbg(ql_dbg_init, vha, 0x0181,
+ "Reducing RSP payload length to %u bytes...\n",
+ rsp_payload_length);
+ }
+
+ rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els),
+ &rsp_els_dma, GFP_KERNEL);
+ if (!rsp_els) {
+ ql_log(ql_log_warn, vha, 0x0183,
+ "Failed allocate dma buffer ELS RSP.\n");
+ goto dealloc;
+ }
+
+ rsp_payload = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_payload),
+ &rsp_payload_dma, GFP_KERNEL);
+ if (!rsp_payload) {
+ ql_log(ql_log_warn, vha, 0x0184,
+ "Failed allocate dma buffer ELS RSP payload.\n");
+ goto dealloc;
+ }
+
+ sfp = dma_alloc_coherent(&ha->pdev->dev, SFP_RTDI_LEN,
+ &sfp_dma, GFP_KERNEL);
+
+ stat = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stat),
+ &stat_dma, GFP_KERNEL);
+
+ /* Prepare Response IOCB */
+ rsp_els->entry_type = ELS_IOCB_TYPE;
+ rsp_els->entry_count = 1;
+ rsp_els->sys_define = 0;
+ rsp_els->entry_status = 0;
+ rsp_els->handle = 0;
+ rsp_els->nport_handle = purex->nport_handle;
+ rsp_els->tx_dsd_count = cpu_to_le16(1);
+ rsp_els->vp_index = purex->vp_idx;
+ rsp_els->sof_type = EST_SOFI3;
+ rsp_els->rx_xchg_address = purex->rx_xchg_addr;
+ rsp_els->rx_dsd_count = 0;
+ rsp_els->opcode = purex->els_frame_payload[0];
+
+ rsp_els->d_id[0] = purex->s_id[0];
+ rsp_els->d_id[1] = purex->s_id[1];
+ rsp_els->d_id[2] = purex->s_id[2];
+
+ rsp_els->control_flags = cpu_to_le16(EPD_ELS_ACC);
+ rsp_els->rx_byte_count = 0;
+ rsp_els->tx_byte_count = cpu_to_le32(rsp_payload_length);
+
+ put_unaligned_le64(rsp_payload_dma, &rsp_els->tx_address);
+ rsp_els->tx_len = rsp_els->tx_byte_count;
+
+ rsp_els->rx_address = 0;
+ rsp_els->rx_len = 0;
+
+ /* Prepare Response Payload */
+ rsp_payload->hdr.cmd = cpu_to_be32(0x2 << 24); /* LS_ACC */
+ rsp_payload->hdr.len = cpu_to_be32(le32_to_cpu(rsp_els->tx_byte_count) -
+ sizeof(rsp_payload->hdr));
+
+ /* Link service Request Info Descriptor */
+ rsp_payload->ls_req_info_desc.desc_tag = cpu_to_be32(0x1);
+ rsp_payload->ls_req_info_desc.desc_len =
+ cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_req_info_desc));
+ rsp_payload->ls_req_info_desc.req_payload_word_0 =
+ cpu_to_be32p((uint32_t *)purex->els_frame_payload);
+
+ /* Link service Request Info Descriptor 2 */
+ rsp_payload->ls_req_info_desc2.desc_tag = cpu_to_be32(0x1);
+ rsp_payload->ls_req_info_desc2.desc_len =
+ cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_req_info_desc2));
+ rsp_payload->ls_req_info_desc2.req_payload_word_0 =
+ cpu_to_be32p((uint32_t *)purex->els_frame_payload);
+
+
+ rsp_payload->sfp_diag_desc.desc_tag = cpu_to_be32(0x10000);
+ rsp_payload->sfp_diag_desc.desc_len =
+ cpu_to_be32(RDP_DESC_LEN(rsp_payload->sfp_diag_desc));
+
+ if (sfp) {
+ /* SFP Flags */
+ memset(sfp, 0, SFP_RTDI_LEN);
+ rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 0x7, 2, 0);
+ if (!rval) {
+ /* SFP Flags bits 3-0: Port Tx Laser Type */
+ if (sfp[0] & BIT_2 || sfp[1] & (BIT_6|BIT_5))
+ sfp_flags |= BIT_0; /* short wave */
+ else if (sfp[0] & BIT_1)
+ sfp_flags |= BIT_1; /* long wave 1310nm */
+ else if (sfp[1] & BIT_4)
+ sfp_flags |= BIT_1|BIT_0; /* long wave 1550nm */
+ }
+
+ /* SFP Type */
+ memset(sfp, 0, SFP_RTDI_LEN);
+ rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 0x0, 1, 0);
+ if (!rval) {
+ sfp_flags |= BIT_4; /* optical */
+ if (sfp[0] == 0x3)
+ sfp_flags |= BIT_6; /* sfp+ */
+ }
+
+ rsp_payload->sfp_diag_desc.sfp_flags = cpu_to_be16(sfp_flags);
+
+ /* SFP Diagnostics */
+ memset(sfp, 0, SFP_RTDI_LEN);
+ rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0x60, 10, 0);
+ if (!rval) {
+ __be16 *trx = (__force __be16 *)sfp; /* already be16 */
+ rsp_payload->sfp_diag_desc.temperature = trx[0];
+ rsp_payload->sfp_diag_desc.vcc = trx[1];
+ rsp_payload->sfp_diag_desc.tx_bias = trx[2];
+ rsp_payload->sfp_diag_desc.tx_power = trx[3];
+ rsp_payload->sfp_diag_desc.rx_power = trx[4];
+ }
+ }
+
+ /* Port Speed Descriptor */
+ rsp_payload->port_speed_desc.desc_tag = cpu_to_be32(0x10001);
+ rsp_payload->port_speed_desc.desc_len =
+ cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_speed_desc));
+ rsp_payload->port_speed_desc.speed_capab = cpu_to_be16(
+ qla25xx_fdmi_port_speed_capability(ha));
+ rsp_payload->port_speed_desc.operating_speed = cpu_to_be16(
+ qla25xx_fdmi_port_speed_currently(ha));
+
+ /* Link Error Status Descriptor */
+ rsp_payload->ls_err_desc.desc_tag = cpu_to_be32(0x10002);
+ rsp_payload->ls_err_desc.desc_len =
+ cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_err_desc));
+
+ if (stat) {
+ rval = qla24xx_get_isp_stats(vha, stat, stat_dma, 0);
+ if (!rval) {
+ rsp_payload->ls_err_desc.link_fail_cnt =
+ cpu_to_be32(le32_to_cpu(stat->link_fail_cnt));
+ rsp_payload->ls_err_desc.loss_sync_cnt =
+ cpu_to_be32(le32_to_cpu(stat->loss_sync_cnt));
+ rsp_payload->ls_err_desc.loss_sig_cnt =
+ cpu_to_be32(le32_to_cpu(stat->loss_sig_cnt));
+ rsp_payload->ls_err_desc.prim_seq_err_cnt =
+ cpu_to_be32(le32_to_cpu(stat->prim_seq_err_cnt));
+ rsp_payload->ls_err_desc.inval_xmit_word_cnt =
+ cpu_to_be32(le32_to_cpu(stat->inval_xmit_word_cnt));
+ rsp_payload->ls_err_desc.inval_crc_cnt =
+ cpu_to_be32(le32_to_cpu(stat->inval_crc_cnt));
+ rsp_payload->ls_err_desc.pn_port_phy_type |= BIT_6;
+ }
+ }
+
+ /* Portname Descriptor */
+ rsp_payload->port_name_diag_desc.desc_tag = cpu_to_be32(0x10003);
+ rsp_payload->port_name_diag_desc.desc_len =
+ cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_name_diag_desc));
+ memcpy(rsp_payload->port_name_diag_desc.WWNN,
+ vha->node_name,
+ sizeof(rsp_payload->port_name_diag_desc.WWNN));
+ memcpy(rsp_payload->port_name_diag_desc.WWPN,
+ vha->port_name,
+ sizeof(rsp_payload->port_name_diag_desc.WWPN));
+
+ /* F-Port Portname Descriptor */
+ rsp_payload->port_name_direct_desc.desc_tag = cpu_to_be32(0x10003);
+ rsp_payload->port_name_direct_desc.desc_len =
+ cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_name_direct_desc));
+ memcpy(rsp_payload->port_name_direct_desc.WWNN,
+ vha->fabric_node_name,
+ sizeof(rsp_payload->port_name_direct_desc.WWNN));
+ memcpy(rsp_payload->port_name_direct_desc.WWPN,
+ vha->fabric_port_name,
+ sizeof(rsp_payload->port_name_direct_desc.WWPN));
+
+ /* Bufer Credit Descriptor */
+ rsp_payload->buffer_credit_desc.desc_tag = cpu_to_be32(0x10006);
+ rsp_payload->buffer_credit_desc.desc_len =
+ cpu_to_be32(RDP_DESC_LEN(rsp_payload->buffer_credit_desc));
+ rsp_payload->buffer_credit_desc.fcport_b2b = 0;
+ rsp_payload->buffer_credit_desc.attached_fcport_b2b = cpu_to_be32(0);
+ rsp_payload->buffer_credit_desc.fcport_rtt = cpu_to_be32(0);
+
+ if (ha->flags.plogi_template_valid) {
+ uint32_t tmp =
+ be16_to_cpu(ha->plogi_els_payld.fl_csp.sp_bb_cred);
+ rsp_payload->buffer_credit_desc.fcport_b2b = cpu_to_be32(tmp);
+ }
+
+ if (rsp_payload_length < sizeof(*rsp_payload))
+ goto send;
+
+ /* Optical Element Descriptor, Temperature */
+ rsp_payload->optical_elmt_desc[0].desc_tag = cpu_to_be32(0x10007);
+ rsp_payload->optical_elmt_desc[0].desc_len =
+ cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc));
+ /* Optical Element Descriptor, Voltage */
+ rsp_payload->optical_elmt_desc[1].desc_tag = cpu_to_be32(0x10007);
+ rsp_payload->optical_elmt_desc[1].desc_len =
+ cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc));
+ /* Optical Element Descriptor, Tx Bias Current */
+ rsp_payload->optical_elmt_desc[2].desc_tag = cpu_to_be32(0x10007);
+ rsp_payload->optical_elmt_desc[2].desc_len =
+ cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc));
+ /* Optical Element Descriptor, Tx Power */
+ rsp_payload->optical_elmt_desc[3].desc_tag = cpu_to_be32(0x10007);
+ rsp_payload->optical_elmt_desc[3].desc_len =
+ cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc));
+ /* Optical Element Descriptor, Rx Power */
+ rsp_payload->optical_elmt_desc[4].desc_tag = cpu_to_be32(0x10007);
+ rsp_payload->optical_elmt_desc[4].desc_len =
+ cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc));
+
+ if (sfp) {
+ memset(sfp, 0, SFP_RTDI_LEN);
+ rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0, 64, 0);
+ if (!rval) {
+ __be16 *trx = (__force __be16 *)sfp; /* already be16 */
+
+ /* Optical Element Descriptor, Temperature */
+ rsp_payload->optical_elmt_desc[0].high_alarm = trx[0];
+ rsp_payload->optical_elmt_desc[0].low_alarm = trx[1];
+ rsp_payload->optical_elmt_desc[0].high_warn = trx[2];
+ rsp_payload->optical_elmt_desc[0].low_warn = trx[3];
+ rsp_payload->optical_elmt_desc[0].element_flags =
+ cpu_to_be32(1 << 28);
+
+ /* Optical Element Descriptor, Voltage */
+ rsp_payload->optical_elmt_desc[1].high_alarm = trx[4];
+ rsp_payload->optical_elmt_desc[1].low_alarm = trx[5];
+ rsp_payload->optical_elmt_desc[1].high_warn = trx[6];
+ rsp_payload->optical_elmt_desc[1].low_warn = trx[7];
+ rsp_payload->optical_elmt_desc[1].element_flags =
+ cpu_to_be32(2 << 28);
+
+ /* Optical Element Descriptor, Tx Bias Current */
+ rsp_payload->optical_elmt_desc[2].high_alarm = trx[8];
+ rsp_payload->optical_elmt_desc[2].low_alarm = trx[9];
+ rsp_payload->optical_elmt_desc[2].high_warn = trx[10];
+ rsp_payload->optical_elmt_desc[2].low_warn = trx[11];
+ rsp_payload->optical_elmt_desc[2].element_flags =
+ cpu_to_be32(3 << 28);
+
+ /* Optical Element Descriptor, Tx Power */
+ rsp_payload->optical_elmt_desc[3].high_alarm = trx[12];
+ rsp_payload->optical_elmt_desc[3].low_alarm = trx[13];
+ rsp_payload->optical_elmt_desc[3].high_warn = trx[14];
+ rsp_payload->optical_elmt_desc[3].low_warn = trx[15];
+ rsp_payload->optical_elmt_desc[3].element_flags =
+ cpu_to_be32(4 << 28);
+
+ /* Optical Element Descriptor, Rx Power */
+ rsp_payload->optical_elmt_desc[4].high_alarm = trx[16];
+ rsp_payload->optical_elmt_desc[4].low_alarm = trx[17];
+ rsp_payload->optical_elmt_desc[4].high_warn = trx[18];
+ rsp_payload->optical_elmt_desc[4].low_warn = trx[19];
+ rsp_payload->optical_elmt_desc[4].element_flags =
+ cpu_to_be32(5 << 28);
+ }
+
+ memset(sfp, 0, SFP_RTDI_LEN);
+ rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 112, 64, 0);
+ if (!rval) {
+ /* Temperature high/low alarm/warning */
+ rsp_payload->optical_elmt_desc[0].element_flags |=
+ cpu_to_be32(
+ (sfp[0] >> 7 & 1) << 3 |
+ (sfp[0] >> 6 & 1) << 2 |
+ (sfp[4] >> 7 & 1) << 1 |
+ (sfp[4] >> 6 & 1) << 0);
+
+ /* Voltage high/low alarm/warning */
+ rsp_payload->optical_elmt_desc[1].element_flags |=
+ cpu_to_be32(
+ (sfp[0] >> 5 & 1) << 3 |
+ (sfp[0] >> 4 & 1) << 2 |
+ (sfp[4] >> 5 & 1) << 1 |
+ (sfp[4] >> 4 & 1) << 0);
+
+ /* Tx Bias Current high/low alarm/warning */
+ rsp_payload->optical_elmt_desc[2].element_flags |=
+ cpu_to_be32(
+ (sfp[0] >> 3 & 1) << 3 |
+ (sfp[0] >> 2 & 1) << 2 |
+ (sfp[4] >> 3 & 1) << 1 |
+ (sfp[4] >> 2 & 1) << 0);
+
+ /* Tx Power high/low alarm/warning */
+ rsp_payload->optical_elmt_desc[3].element_flags |=
+ cpu_to_be32(
+ (sfp[0] >> 1 & 1) << 3 |
+ (sfp[0] >> 0 & 1) << 2 |
+ (sfp[4] >> 1 & 1) << 1 |
+ (sfp[4] >> 0 & 1) << 0);
+
+ /* Rx Power high/low alarm/warning */
+ rsp_payload->optical_elmt_desc[4].element_flags |=
+ cpu_to_be32(
+ (sfp[1] >> 7 & 1) << 3 |
+ (sfp[1] >> 6 & 1) << 2 |
+ (sfp[5] >> 7 & 1) << 1 |
+ (sfp[5] >> 6 & 1) << 0);
+ }
+ }
+
+ /* Optical Product Data Descriptor */
+ rsp_payload->optical_prod_desc.desc_tag = cpu_to_be32(0x10008);
+ rsp_payload->optical_prod_desc.desc_len =
+ cpu_to_be32(RDP_DESC_LEN(rsp_payload->optical_prod_desc));
+
+ if (sfp) {
+ memset(sfp, 0, SFP_RTDI_LEN);
+ rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 20, 64, 0);
+ if (!rval) {
+ memcpy(rsp_payload->optical_prod_desc.vendor_name,
+ sfp + 0,
+ sizeof(rsp_payload->optical_prod_desc.vendor_name));
+ memcpy(rsp_payload->optical_prod_desc.part_number,
+ sfp + 20,
+ sizeof(rsp_payload->optical_prod_desc.part_number));
+ memcpy(rsp_payload->optical_prod_desc.revision,
+ sfp + 36,
+ sizeof(rsp_payload->optical_prod_desc.revision));
+ memcpy(rsp_payload->optical_prod_desc.serial_number,
+ sfp + 48,
+ sizeof(rsp_payload->optical_prod_desc.serial_number));
+ }
+
+ memset(sfp, 0, SFP_RTDI_LEN);
+ rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 84, 8, 0);
+ if (!rval) {
+ memcpy(rsp_payload->optical_prod_desc.date,
+ sfp + 0,
+ sizeof(rsp_payload->optical_prod_desc.date));
+ }
+ }
+
+send:
+ ql_dbg(ql_dbg_init, vha, 0x0183,
+ "Sending ELS Response to RDP Request...\n");
+ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0184,
+ "-------- ELS RSP -------\n");
+ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0185,
+ rsp_els, sizeof(*rsp_els));
+ ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0186,
+ "-------- ELS RSP PAYLOAD -------\n");
+ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0187,
+ rsp_payload, rsp_payload_length);
+
+ rval = qla2x00_issue_iocb(vha, rsp_els, rsp_els_dma, 0);
+
+ if (rval) {
+ ql_log(ql_log_warn, vha, 0x0188,
+ "%s: iocb failed to execute -> %x\n", __func__, rval);
+ } else if (rsp_els->comp_status) {
+ ql_log(ql_log_warn, vha, 0x0189,
+ "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n",
+ __func__, rsp_els->comp_status,
+ rsp_els->error_subcode_1, rsp_els->error_subcode_2);
+ } else {
+ ql_dbg(ql_dbg_init, vha, 0x018a, "%s: done.\n", __func__);
+ }
+
+dealloc:
+ if (stat)
+ dma_free_coherent(&ha->pdev->dev, sizeof(*stat),
+ stat, stat_dma);
+ if (sfp)
+ dma_free_coherent(&ha->pdev->dev, SFP_RTDI_LEN,
+ sfp, sfp_dma);
+ if (rsp_payload)
+ dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_payload),
+ rsp_payload, rsp_payload_dma);
+ if (rsp_els)
+ dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els),
+ rsp_els, rsp_els_dma);
+}
+
+void
+qla24xx_free_purex_item(struct purex_item *item)
+{
+ if (item == &item->vha->default_item)
+ memset(&item->vha->default_item, 0, sizeof(struct purex_item));
+ else
+ kfree(item);
+}
+
+void qla24xx_process_purex_list(struct purex_list *list)
+{
+ struct list_head head = LIST_HEAD_INIT(head);
+ struct purex_item *item, *next;
+ ulong flags;
+
+ spin_lock_irqsave(&list->lock, flags);
+ list_splice_init(&list->head, &head);
+ spin_unlock_irqrestore(&list->lock, flags);
+
+ list_for_each_entry_safe(item, next, &head, list) {
+ list_del(&item->list);
+ item->process_item(item->vha, item);
+ qla24xx_free_purex_item(item);
+ }
+}
+
void
qla83xx_idc_unlock(scsi_qla_host_t *base_vha, uint16_t requester_id)
{
@@ -6261,13 +6768,14 @@
}
if (test_and_clear_bit(DETECT_SFP_CHANGE,
- &base_vha->dpc_flags) &&
- !test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) {
- qla24xx_detect_sfp(base_vha);
-
- if (ha->flags.detected_lr_sfp !=
- ha->flags.using_lr_setting)
- set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
+ &base_vha->dpc_flags)) {
+ /* Semantic:
+ * - NO-OP -- await next ISP-ABORT. Preferred method
+ * to minimize disruptions that will occur
+ * when a forced chip-reset occurs.
+ * - Force -- ISP-ABORT scheduled.
+ */
+ /* set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); */
}
if (test_and_clear_bit
@@ -6309,6 +6817,15 @@
}
}
+ if (test_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags)) {
+ if (atomic_read(&base_vha->loop_state) == LOOP_READY) {
+ qla24xx_process_purex_list
+ (&base_vha->purex_list);
+ clear_bit(PROCESS_PUREX_IOCB,
+ &base_vha->dpc_flags);
+ }
+ }
+
if (test_and_clear_bit(FCPORT_UPDATE_NEEDED,
&base_vha->dpc_flags)) {
qla2x00_update_fcports(base_vha);
@@ -6666,8 +7183,10 @@
* FC-NVME
* see if the active AEN count has changed from what was last reported.
*/
+ index = atomic_read(&ha->nvme_active_aen_cnt);
if (!vha->vp_idx &&
- (atomic_read(&ha->nvme_active_aen_cnt) != ha->nvme_last_rptd_aen) &&
+ (index != ha->nvme_last_rptd_aen) &&
+ (index >= DEFAULT_ZIO_THRESHOLD) &&
ha->zio_mode == QLA_ZIO_MODE_6 &&
!ha->flags.host_shutting_down) {
ql_log(ql_log_info, vha, 0x3002,
@@ -6679,9 +7198,8 @@
}
if (!vha->vp_idx &&
- (atomic_read(&ha->zio_threshold) != ha->last_zio_threshold) &&
- (ha->zio_mode == QLA_ZIO_MODE_6) &&
- (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))) {
+ atomic_read(&ha->zio_threshold) != ha->last_zio_threshold &&
+ IS_ZIO_THRESHOLD_CAPABLE(ha)) {
ql_log(ql_log_info, vha, 0x3002,
"Sched: Set ZIO exchange threshold to %d.\n",
ha->last_zio_threshold);
@@ -6700,7 +7218,8 @@
test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) ||
test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) ||
test_bit(VP_DPC_NEEDED, &vha->dpc_flags) ||
- test_bit(RELOGIN_NEEDED, &vha->dpc_flags))) {
+ test_bit(RELOGIN_NEEDED, &vha->dpc_flags) ||
+ test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags))) {
ql_dbg(ql_dbg_timer, vha, 0x600b,
"isp_abort_needed=%d loop_resync_needed=%d "
"fcport_update_needed=%d start_dpc=%d "
@@ -6713,12 +7232,13 @@
ql_dbg(ql_dbg_timer, vha, 0x600c,
"beacon_blink_needed=%d isp_unrecoverable=%d "
"fcoe_ctx_reset_needed=%d vp_dpc_needed=%d "
- "relogin_needed=%d.\n",
+ "relogin_needed=%d, Process_purex_iocb=%d.\n",
test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags),
test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags),
test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags),
test_bit(VP_DPC_NEEDED, &vha->dpc_flags),
- test_bit(RELOGIN_NEEDED, &vha->dpc_flags));
+ test_bit(RELOGIN_NEEDED, &vha->dpc_flags),
+ test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags));
qla2xxx_wake_dpc(vha);
}
@@ -6879,13 +7399,13 @@
qpair->online = 0;
mutex_unlock(&ha->mq_lock);
- qla2x00_mark_all_devices_lost(vha, 0);
+ qla2x00_mark_all_devices_lost(vha);
spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry(vp, &ha->vp_list, list) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);
- qla2x00_mark_all_devices_lost(vp, 0);
+ qla2x00_mark_all_devices_lost(vp);
spin_lock_irqsave(&ha->vport_slock, flags);
atomic_dec(&vp->vref_count);
}
@@ -6963,15 +7483,15 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
if (IS_QLA2100(ha) || IS_QLA2200(ha)){
- stat = RD_REG_DWORD(®->hccr);
+ stat = rd_reg_word(®->hccr);
if (stat & HCCR_RISC_PAUSE)
risc_paused = 1;
} else if (IS_QLA23XX(ha)) {
- stat = RD_REG_DWORD(®->u.isp2300.host_status);
+ stat = rd_reg_dword(®->u.isp2300.host_status);
if (stat & HSR_RISC_PAUSED)
risc_paused = 1;
} else if (IS_FWI2_CAPABLE(ha)) {
- stat = RD_REG_DWORD(®24->host_status);
+ stat = rd_reg_dword(®24->host_status);
if (stat & HSRX_RISC_PAUSED)
risc_paused = 1;
}
@@ -6980,7 +7500,7 @@
if (risc_paused) {
ql_log(ql_log_info, base_vha, 0x9003,
"RISC paused -- mmio_enabled, Dumping firmware.\n");
- ha->isp_ops->fw_dump(base_vha, 0);
+ qla2xxx_dump_fw(base_vha);
return PCI_ERS_RESULT_NEED_RESET;
} else
@@ -7227,13 +7747,19 @@
{
int ret = 0;
+ BUILD_BUG_ON(sizeof(cmd_a64_entry_t) != 64);
BUILD_BUG_ON(sizeof(cmd_entry_t) != 64);
BUILD_BUG_ON(sizeof(cont_a64_entry_t) != 64);
BUILD_BUG_ON(sizeof(cont_entry_t) != 64);
BUILD_BUG_ON(sizeof(init_cb_t) != 96);
+ BUILD_BUG_ON(sizeof(mrk_entry_t) != 64);
BUILD_BUG_ON(sizeof(ms_iocb_entry_t) != 64);
BUILD_BUG_ON(sizeof(request_t) != 64);
+ BUILD_BUG_ON(sizeof(struct abort_entry_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct abort_iocb_entry_fx00) != 64);
+ BUILD_BUG_ON(sizeof(struct abts_entry_24xx) != 64);
BUILD_BUG_ON(sizeof(struct access_chip_84xx) != 64);
+ BUILD_BUG_ON(sizeof(struct access_chip_rsp_84xx) != 64);
BUILD_BUG_ON(sizeof(struct cmd_bidir) != 64);
BUILD_BUG_ON(sizeof(struct cmd_nvme) != 64);
BUILD_BUG_ON(sizeof(struct cmd_type_6) != 64);
@@ -7241,15 +7767,70 @@
BUILD_BUG_ON(sizeof(struct cmd_type_7_fx00) != 64);
BUILD_BUG_ON(sizeof(struct cmd_type_crc_2) != 64);
BUILD_BUG_ON(sizeof(struct ct_entry_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct ct_fdmi1_hba_attributes) != 2344);
+ BUILD_BUG_ON(sizeof(struct ct_fdmi2_hba_attributes) != 4424);
+ BUILD_BUG_ON(sizeof(struct ct_fdmi2_port_attributes) != 4164);
+ BUILD_BUG_ON(sizeof(struct ct_fdmi_hba_attr) != 260);
+ BUILD_BUG_ON(sizeof(struct ct_fdmi_port_attr) != 260);
+ BUILD_BUG_ON(sizeof(struct ct_rsp_hdr) != 16);
BUILD_BUG_ON(sizeof(struct ctio_crc2_to_fw) != 64);
+ BUILD_BUG_ON(sizeof(struct device_reg_24xx) != 256);
+ BUILD_BUG_ON(sizeof(struct device_reg_25xxmq) != 24);
+ BUILD_BUG_ON(sizeof(struct device_reg_2xxx) != 256);
+ BUILD_BUG_ON(sizeof(struct device_reg_82xx) != 1288);
+ BUILD_BUG_ON(sizeof(struct device_reg_fx00) != 216);
BUILD_BUG_ON(sizeof(struct els_entry_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct els_sts_entry_24xx) != 64);
BUILD_BUG_ON(sizeof(struct fxdisc_entry_fx00) != 64);
+ BUILD_BUG_ON(sizeof(struct imm_ntfy_from_isp) != 64);
BUILD_BUG_ON(sizeof(struct init_cb_24xx) != 128);
BUILD_BUG_ON(sizeof(struct init_cb_81xx) != 128);
+ BUILD_BUG_ON(sizeof(struct logio_entry_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct mbx_entry) != 64);
+ BUILD_BUG_ON(sizeof(struct mid_init_cb_24xx) != 5252);
+ BUILD_BUG_ON(sizeof(struct mrk_entry_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct nvram_24xx) != 512);
+ BUILD_BUG_ON(sizeof(struct nvram_81xx) != 512);
BUILD_BUG_ON(sizeof(struct pt_ls4_request) != 64);
+ BUILD_BUG_ON(sizeof(struct pt_ls4_rx_unsol) != 64);
+ BUILD_BUG_ON(sizeof(struct purex_entry_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct qla2100_fw_dump) != 123634);
+ BUILD_BUG_ON(sizeof(struct qla2300_fw_dump) != 136100);
+ BUILD_BUG_ON(sizeof(struct qla24xx_fw_dump) != 37976);
+ BUILD_BUG_ON(sizeof(struct qla25xx_fw_dump) != 39228);
+ BUILD_BUG_ON(sizeof(struct qla2xxx_fce_chain) != 52);
+ BUILD_BUG_ON(sizeof(struct qla2xxx_fw_dump) != 136172);
+ BUILD_BUG_ON(sizeof(struct qla2xxx_mq_chain) != 524);
+ BUILD_BUG_ON(sizeof(struct qla2xxx_mqueue_chain) != 8);
+ BUILD_BUG_ON(sizeof(struct qla2xxx_mqueue_header) != 12);
+ BUILD_BUG_ON(sizeof(struct qla2xxx_offld_chain) != 24);
+ BUILD_BUG_ON(sizeof(struct qla81xx_fw_dump) != 39420);
+ BUILD_BUG_ON(sizeof(struct qla82xx_uri_data_desc) != 28);
+ BUILD_BUG_ON(sizeof(struct qla82xx_uri_table_desc) != 32);
+ BUILD_BUG_ON(sizeof(struct qla83xx_fw_dump) != 51196);
+ BUILD_BUG_ON(sizeof(struct qla_fcp_prio_cfg) != FCP_PRIO_CFG_SIZE);
+ BUILD_BUG_ON(sizeof(struct qla_fdt_layout) != 128);
+ BUILD_BUG_ON(sizeof(struct qla_flt_header) != 8);
+ BUILD_BUG_ON(sizeof(struct qla_flt_region) != 16);
+ BUILD_BUG_ON(sizeof(struct qla_npiv_entry) != 24);
+ BUILD_BUG_ON(sizeof(struct qla_npiv_header) != 16);
+ BUILD_BUG_ON(sizeof(struct rdp_rsp_payload) != 336);
BUILD_BUG_ON(sizeof(struct sns_cmd_pkt) != 2064);
+ BUILD_BUG_ON(sizeof(struct sts_entry_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct tsk_mgmt_entry) != 64);
+ BUILD_BUG_ON(sizeof(struct tsk_mgmt_entry_fx00) != 64);
BUILD_BUG_ON(sizeof(struct verify_chip_entry_84xx) != 64);
+ BUILD_BUG_ON(sizeof(struct verify_chip_rsp_84xx) != 52);
BUILD_BUG_ON(sizeof(struct vf_evfp_entry_24xx) != 56);
+ BUILD_BUG_ON(sizeof(struct vp_config_entry_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct vp_ctrl_entry_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct vp_rpt_id_entry_24xx) != 64);
+ BUILD_BUG_ON(sizeof(sts21_entry_t) != 64);
+ BUILD_BUG_ON(sizeof(sts22_entry_t) != 64);
+ BUILD_BUG_ON(sizeof(sts_cont_entry_t) != 64);
+ BUILD_BUG_ON(sizeof(sts_entry_t) != 64);
+ BUILD_BUG_ON(sizeof(sw_info_t) != 32);
+ BUILD_BUG_ON(sizeof(target_id_t) != 2);
/* Allocate cache for SRBs. */
srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
@@ -7358,7 +7939,6 @@
MODULE_AUTHOR("QLogic Corporation");
MODULE_DESCRIPTION("QLogic Fibre Channel HBA Driver");
MODULE_LICENSE("GPL");
-MODULE_VERSION(QLA2XXX_VERSION);
MODULE_FIRMWARE(FW_FILE_ISP21XX);
MODULE_FIRMWARE(FW_FILE_ISP22XX);
MODULE_FIRMWARE(FW_FILE_ISP2300);
diff --git a/drivers/scsi/qla2xxx/qla_settings.h b/drivers/scsi/qla2xxx/qla_settings.h
index 2fb7ebf..a5f3000 100644
--- a/drivers/scsi/qla2xxx/qla_settings.h
+++ b/drivers/scsi/qla2xxx/qla_settings.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#define MAX_RETRIES_OF_ISP_ABORT 5
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index bbe9035..0f92e9a 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
@@ -26,24 +25,24 @@
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) {
- data = RD_REG_WORD(®->nvram);
+ data = rd_reg_word(®->nvram);
while (data & NVR_BUSY) {
udelay(100);
- data = RD_REG_WORD(®->nvram);
+ data = rd_reg_word(®->nvram);
}
/* Lock resource */
- WRT_REG_WORD(®->u.isp2300.host_semaphore, 0x1);
- RD_REG_WORD(®->u.isp2300.host_semaphore);
+ wrt_reg_word(®->u.isp2300.host_semaphore, 0x1);
+ rd_reg_word(®->u.isp2300.host_semaphore);
udelay(5);
- data = RD_REG_WORD(®->u.isp2300.host_semaphore);
+ data = rd_reg_word(®->u.isp2300.host_semaphore);
while ((data & BIT_0) == 0) {
/* Lock failed */
udelay(100);
- WRT_REG_WORD(®->u.isp2300.host_semaphore, 0x1);
- RD_REG_WORD(®->u.isp2300.host_semaphore);
+ wrt_reg_word(®->u.isp2300.host_semaphore, 0x1);
+ rd_reg_word(®->u.isp2300.host_semaphore);
udelay(5);
- data = RD_REG_WORD(®->u.isp2300.host_semaphore);
+ data = rd_reg_word(®->u.isp2300.host_semaphore);
}
}
}
@@ -58,8 +57,8 @@
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) {
- WRT_REG_WORD(®->u.isp2300.host_semaphore, 0);
- RD_REG_WORD(®->u.isp2300.host_semaphore);
+ wrt_reg_word(®->u.isp2300.host_semaphore, 0);
+ rd_reg_word(®->u.isp2300.host_semaphore);
}
}
@@ -73,15 +72,15 @@
{
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
- WRT_REG_WORD(®->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
- RD_REG_WORD(®->nvram); /* PCI Posting. */
+ wrt_reg_word(®->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
+ rd_reg_word(®->nvram); /* PCI Posting. */
NVRAM_DELAY();
- WRT_REG_WORD(®->nvram, data | NVR_SELECT | NVR_CLOCK |
+ wrt_reg_word(®->nvram, data | NVR_SELECT | NVR_CLOCK |
NVR_WRT_ENABLE);
- RD_REG_WORD(®->nvram); /* PCI Posting. */
+ rd_reg_word(®->nvram); /* PCI Posting. */
NVRAM_DELAY();
- WRT_REG_WORD(®->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
- RD_REG_WORD(®->nvram); /* PCI Posting. */
+ wrt_reg_word(®->nvram, data | NVR_SELECT | NVR_WRT_ENABLE);
+ rd_reg_word(®->nvram); /* PCI Posting. */
NVRAM_DELAY();
}
@@ -120,21 +119,21 @@
/* Read data from NVRAM. */
for (cnt = 0; cnt < 16; cnt++) {
- WRT_REG_WORD(®->nvram, NVR_SELECT | NVR_CLOCK);
- RD_REG_WORD(®->nvram); /* PCI Posting. */
+ wrt_reg_word(®->nvram, NVR_SELECT | NVR_CLOCK);
+ rd_reg_word(®->nvram); /* PCI Posting. */
NVRAM_DELAY();
data <<= 1;
- reg_data = RD_REG_WORD(®->nvram);
+ reg_data = rd_reg_word(®->nvram);
if (reg_data & NVR_DATA_IN)
data |= BIT_0;
- WRT_REG_WORD(®->nvram, NVR_SELECT);
- RD_REG_WORD(®->nvram); /* PCI Posting. */
+ wrt_reg_word(®->nvram, NVR_SELECT);
+ rd_reg_word(®->nvram); /* PCI Posting. */
NVRAM_DELAY();
}
/* Deselect chip. */
- WRT_REG_WORD(®->nvram, NVR_DESELECT);
- RD_REG_WORD(®->nvram); /* PCI Posting. */
+ wrt_reg_word(®->nvram, NVR_DESELECT);
+ rd_reg_word(®->nvram); /* PCI Posting. */
NVRAM_DELAY();
return data;
@@ -171,8 +170,8 @@
{
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
- WRT_REG_WORD(®->nvram, NVR_DESELECT);
- RD_REG_WORD(®->nvram); /* PCI Posting. */
+ wrt_reg_word(®->nvram, NVR_DESELECT);
+ rd_reg_word(®->nvram); /* PCI Posting. */
NVRAM_DELAY();
}
@@ -183,7 +182,7 @@
* @data: word to program
*/
static void
-qla2x00_write_nvram_word(struct qla_hw_data *ha, uint32_t addr, uint16_t data)
+qla2x00_write_nvram_word(struct qla_hw_data *ha, uint32_t addr, __le16 data)
{
int count;
uint16_t word;
@@ -202,7 +201,7 @@
/* Write data */
nv_cmd = (addr << 16) | NV_WRITE_OP;
- nv_cmd |= data;
+ nv_cmd |= (__force u16)data;
nv_cmd <<= 5;
for (count = 0; count < 27; count++) {
if (nv_cmd & BIT_31)
@@ -216,8 +215,8 @@
qla2x00_nv_deselect(ha);
/* Wait for NVRAM to become ready */
- WRT_REG_WORD(®->nvram, NVR_SELECT);
- RD_REG_WORD(®->nvram); /* PCI Posting. */
+ wrt_reg_word(®->nvram, NVR_SELECT);
+ rd_reg_word(®->nvram); /* PCI Posting. */
wait_cnt = NVR_WAIT_CNT;
do {
if (!--wait_cnt) {
@@ -226,7 +225,7 @@
break;
}
NVRAM_DELAY();
- word = RD_REG_WORD(®->nvram);
+ word = rd_reg_word(®->nvram);
} while ((word & NVR_DATA_IN) == 0);
qla2x00_nv_deselect(ha);
@@ -241,7 +240,7 @@
static int
qla2x00_write_nvram_word_tmo(struct qla_hw_data *ha, uint32_t addr,
- uint16_t data, uint32_t tmo)
+ __le16 data, uint32_t tmo)
{
int ret, count;
uint16_t word;
@@ -261,7 +260,7 @@
/* Write data */
nv_cmd = (addr << 16) | NV_WRITE_OP;
- nv_cmd |= data;
+ nv_cmd |= (__force u16)data;
nv_cmd <<= 5;
for (count = 0; count < 27; count++) {
if (nv_cmd & BIT_31)
@@ -275,11 +274,11 @@
qla2x00_nv_deselect(ha);
/* Wait for NVRAM to become ready */
- WRT_REG_WORD(®->nvram, NVR_SELECT);
- RD_REG_WORD(®->nvram); /* PCI Posting. */
+ wrt_reg_word(®->nvram, NVR_SELECT);
+ rd_reg_word(®->nvram); /* PCI Posting. */
do {
NVRAM_DELAY();
- word = RD_REG_WORD(®->nvram);
+ word = rd_reg_word(®->nvram);
if (!--tmo) {
ret = QLA_FUNCTION_FAILED;
break;
@@ -308,7 +307,7 @@
int ret, stat;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
uint32_t word, wait_cnt;
- uint16_t wprot, wprot_old;
+ __le16 wprot, wprot_old;
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
/* Clear NVRAM write protection. */
@@ -318,7 +317,7 @@
stat = qla2x00_write_nvram_word_tmo(ha, ha->nvram_base,
cpu_to_le16(0x1234), 100000);
wprot = cpu_to_le16(qla2x00_get_nvram_word(ha, ha->nvram_base));
- if (stat != QLA_SUCCESS || wprot != 0x1234) {
+ if (stat != QLA_SUCCESS || wprot != cpu_to_le16(0x1234)) {
/* Write enable. */
qla2x00_nv_write(ha, NVR_DATA_OUT);
qla2x00_nv_write(ha, 0);
@@ -347,8 +346,8 @@
qla2x00_nv_deselect(ha);
/* Wait for NVRAM to become ready. */
- WRT_REG_WORD(®->nvram, NVR_SELECT);
- RD_REG_WORD(®->nvram); /* PCI Posting. */
+ wrt_reg_word(®->nvram, NVR_SELECT);
+ rd_reg_word(®->nvram); /* PCI Posting. */
wait_cnt = NVR_WAIT_CNT;
do {
if (!--wait_cnt) {
@@ -357,7 +356,7 @@
break;
}
NVRAM_DELAY();
- word = RD_REG_WORD(®->nvram);
+ word = rd_reg_word(®->nvram);
} while ((word & NVR_DATA_IN) == 0);
if (wait_cnt)
@@ -407,8 +406,8 @@
qla2x00_nv_deselect(ha);
/* Wait for NVRAM to become ready. */
- WRT_REG_WORD(®->nvram, NVR_SELECT);
- RD_REG_WORD(®->nvram); /* PCI Posting. */
+ wrt_reg_word(®->nvram, NVR_SELECT);
+ rd_reg_word(®->nvram); /* PCI Posting. */
wait_cnt = NVR_WAIT_CNT;
do {
if (!--wait_cnt) {
@@ -417,7 +416,7 @@
break;
}
NVRAM_DELAY();
- word = RD_REG_WORD(®->nvram);
+ word = rd_reg_word(®->nvram);
} while ((word & NVR_DATA_IN) == 0);
}
@@ -456,11 +455,11 @@
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
ulong cnt = 30000;
- WRT_REG_DWORD(®->flash_addr, addr & ~FARX_DATA_FLAG);
+ wrt_reg_dword(®->flash_addr, addr & ~FARX_DATA_FLAG);
while (cnt--) {
- if (RD_REG_DWORD(®->flash_addr) & FARX_DATA_FLAG) {
- *data = RD_REG_DWORD(®->flash_data);
+ if (rd_reg_dword(®->flash_addr) & FARX_DATA_FLAG) {
+ *data = rd_reg_dword(®->flash_data);
return QLA_SUCCESS;
}
udelay(10);
@@ -499,11 +498,11 @@
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
ulong cnt = 500000;
- WRT_REG_DWORD(®->flash_data, data);
- WRT_REG_DWORD(®->flash_addr, addr | FARX_DATA_FLAG);
+ wrt_reg_dword(®->flash_data, data);
+ wrt_reg_dword(®->flash_addr, addr | FARX_DATA_FLAG);
while (cnt--) {
- if (!(RD_REG_DWORD(®->flash_addr) & FARX_DATA_FLAG))
+ if (!(rd_reg_dword(®->flash_addr) & FARX_DATA_FLAG))
return QLA_SUCCESS;
udelay(10);
cond_resched();
@@ -549,11 +548,12 @@
{
const char *loc, *locations[] = { "DEF", "PCI" };
uint32_t pcihdr, pcids;
- uint16_t cnt, chksum, *wptr;
+ uint16_t cnt, chksum;
+ __le16 *wptr;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
struct qla_flt_location *fltl = (void *)req->ring;
- uint32_t *dcode = (void *)req->ring;
+ uint32_t *dcode = (uint32_t *)req->ring;
uint8_t *buf = (void *)req->ring, *bcode, last_image;
/*
@@ -610,7 +610,7 @@
if (memcmp(fltl->sig, "QFLT", 4))
goto end;
- wptr = (void *)req->ring;
+ wptr = (__force __le16 *)req->ring;
cnt = sizeof(*fltl) / sizeof(*wptr);
for (chksum = 0; cnt--; wptr++)
chksum += le16_to_cpu(*wptr);
@@ -669,9 +669,10 @@
struct qla_hw_data *ha = vha->hw;
uint32_t def = IS_QLA81XX(ha) ? 2 : IS_QLA25XX(ha) ? 1 : 0;
- struct qla_flt_header *flt = (void *)ha->flt;
- struct qla_flt_region *region = (void *)&flt[1];
- uint16_t *wptr, cnt, chksum;
+ struct qla_flt_header *flt = ha->flt;
+ struct qla_flt_region *region = &flt->region[0];
+ __le16 *wptr;
+ uint16_t cnt, chksum;
uint32_t start;
/* Assign FCP prio region since older adapters may not have FLT, or
@@ -681,8 +682,8 @@
fcp_prio_cfg0[def] : fcp_prio_cfg1[def];
ha->flt_region_flt = flt_addr;
- wptr = (uint16_t *)ha->flt;
- ha->isp_ops->read_optrom(vha, (void *)flt, flt_addr << 2,
+ wptr = (__force __le16 *)ha->flt;
+ ha->isp_ops->read_optrom(vha, flt, flt_addr << 2,
(sizeof(struct qla_flt_header) + FLT_REGIONS_SIZE));
if (le16_to_cpu(*wptr) == 0xffff)
@@ -949,7 +950,7 @@
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
uint16_t cnt, chksum;
- uint16_t *wptr = (void *)req->ring;
+ __le16 *wptr = (__force __le16 *)req->ring;
struct qla_fdt_layout *fdt = (struct qla_fdt_layout *)req->ring;
uint8_t man_id, flash_id;
uint16_t mid = 0, fid = 0;
@@ -1042,14 +1043,14 @@
qla2xxx_get_idc_param(scsi_qla_host_t *vha)
{
#define QLA82XX_IDC_PARAM_ADDR 0x003e885c
- uint32_t *wptr;
+ __le32 *wptr;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
if (!(IS_P3P_TYPE(ha)))
return;
- wptr = (uint32_t *)req->ring;
+ wptr = (__force __le32 *)req->ring;
ha->isp_ops->read_optrom(vha, req->ring, QLA82XX_IDC_PARAM_ADDR, 8);
if (*wptr == cpu_to_le32(0xffffffff)) {
@@ -1095,7 +1096,7 @@
{
#define NPIV_CONFIG_SIZE (16*1024)
void *data;
- uint16_t *wptr;
+ __le16 *wptr;
uint16_t cnt, chksum;
int i;
struct qla_npiv_header hdr;
@@ -1197,9 +1198,9 @@
return qla81xx_fac_do_write_enable(vha, 1);
/* Enable flash write. */
- WRT_REG_DWORD(®->ctrl_status,
- RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE);
- RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_dword(®->ctrl_status,
+ rd_reg_dword(®->ctrl_status) | CSRX_FLASH_ENABLE);
+ rd_reg_dword(®->ctrl_status); /* PCI Posting. */
if (!ha->fdt_wrt_disable)
goto done;
@@ -1240,8 +1241,8 @@
skip_wrt_protect:
/* Disable flash write. */
- WRT_REG_DWORD(®->ctrl_status,
- RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE);
+ wrt_reg_dword(®->ctrl_status,
+ rd_reg_dword(®->ctrl_status) & ~CSRX_FLASH_ENABLE);
return QLA_SUCCESS;
}
@@ -1265,7 +1266,7 @@
}
static int
-qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
+qla24xx_write_flash_data(scsi_qla_host_t *vha, __le32 *dwptr, uint32_t faddr,
uint32_t dwords)
{
int ret;
@@ -1352,7 +1353,7 @@
/* Slow write */
ret = qla24xx_write_flash_dword(ha,
- flash_data_addr(ha, faddr), cpu_to_le32(*dwptr));
+ flash_data_addr(ha, faddr), le32_to_cpu(*dwptr));
if (ret) {
ql_dbg(ql_dbg_user, vha, 0x7006,
"Failed slopw write %x (%x)\n", faddr, *dwptr);
@@ -1379,11 +1380,11 @@
uint32_t bytes)
{
uint32_t i;
- uint16_t *wptr;
+ __le16 *wptr;
struct qla_hw_data *ha = vha->hw;
/* Word reads to NVRAM via registers. */
- wptr = (uint16_t *)buf;
+ wptr = buf;
qla2x00_lock_nvram_access(ha);
for (i = 0; i < bytes >> 1; i++, naddr++)
wptr[i] = cpu_to_le16(qla2x00_get_nvram_word(ha,
@@ -1456,7 +1457,7 @@
{
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
- uint32_t *dwptr = buf;
+ __le32 *dwptr = buf;
uint32_t i;
int ret;
@@ -1466,9 +1467,9 @@
return ret;
/* Enable flash write. */
- WRT_REG_DWORD(®->ctrl_status,
- RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE);
- RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_dword(®->ctrl_status,
+ rd_reg_dword(®->ctrl_status) | CSRX_FLASH_ENABLE);
+ rd_reg_dword(®->ctrl_status); /* PCI Posting. */
/* Disable NVRAM write-protection. */
qla24xx_write_flash_dword(ha, nvram_conf_addr(ha, 0x101), 0);
@@ -1478,7 +1479,7 @@
naddr = nvram_data_addr(ha, naddr);
bytes >>= 2;
for (i = 0; i < bytes; i++, naddr++, dwptr++) {
- if (qla24xx_write_flash_dword(ha, naddr, cpu_to_le32(*dwptr))) {
+ if (qla24xx_write_flash_dword(ha, naddr, le32_to_cpu(*dwptr))) {
ql_dbg(ql_dbg_user, vha, 0x709a,
"Unable to program nvram address=%x data=%x.\n",
naddr, *dwptr);
@@ -1490,9 +1491,9 @@
qla24xx_write_flash_dword(ha, nvram_conf_addr(ha, 0x101), 0x8c);
/* Disable flash write. */
- WRT_REG_DWORD(®->ctrl_status,
- RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE);
- RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_dword(®->ctrl_status,
+ rd_reg_dword(®->ctrl_status) & ~CSRX_FLASH_ENABLE);
+ rd_reg_dword(®->ctrl_status); /* PCI Posting. */
return ret;
}
@@ -1588,8 +1589,8 @@
gpio_enable = RD_REG_WORD_PIO(PIO_REG(ha, gpioe));
gpio_data = RD_REG_WORD_PIO(PIO_REG(ha, gpiod));
} else {
- gpio_enable = RD_REG_WORD(®->gpioe);
- gpio_data = RD_REG_WORD(®->gpiod);
+ gpio_enable = rd_reg_word(®->gpioe);
+ gpio_data = rd_reg_word(®->gpiod);
}
/* Set the modified gpio_enable values */
@@ -1598,8 +1599,8 @@
if (ha->pio_address) {
WRT_REG_WORD_PIO(PIO_REG(ha, gpioe), gpio_enable);
} else {
- WRT_REG_WORD(®->gpioe, gpio_enable);
- RD_REG_WORD(®->gpioe);
+ wrt_reg_word(®->gpioe, gpio_enable);
+ rd_reg_word(®->gpioe);
}
qla2x00_flip_colors(ha, &led_color);
@@ -1614,8 +1615,8 @@
if (ha->pio_address) {
WRT_REG_WORD_PIO(PIO_REG(ha, gpiod), gpio_data);
} else {
- WRT_REG_WORD(®->gpiod, gpio_data);
- RD_REG_WORD(®->gpiod);
+ wrt_reg_word(®->gpiod, gpio_data);
+ rd_reg_word(®->gpiod);
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -1645,8 +1646,8 @@
gpio_enable = RD_REG_WORD_PIO(PIO_REG(ha, gpioe));
gpio_data = RD_REG_WORD_PIO(PIO_REG(ha, gpiod));
} else {
- gpio_enable = RD_REG_WORD(®->gpioe);
- gpio_data = RD_REG_WORD(®->gpiod);
+ gpio_enable = rd_reg_word(®->gpioe);
+ gpio_data = rd_reg_word(®->gpiod);
}
gpio_enable |= GPIO_LED_MASK;
@@ -1654,8 +1655,8 @@
if (ha->pio_address) {
WRT_REG_WORD_PIO(PIO_REG(ha, gpioe), gpio_enable);
} else {
- WRT_REG_WORD(®->gpioe, gpio_enable);
- RD_REG_WORD(®->gpioe);
+ wrt_reg_word(®->gpioe, gpio_enable);
+ rd_reg_word(®->gpioe);
}
/* Clear out previously set LED colour. */
@@ -1663,8 +1664,8 @@
if (ha->pio_address) {
WRT_REG_WORD_PIO(PIO_REG(ha, gpiod), gpio_data);
} else {
- WRT_REG_WORD(®->gpiod, gpio_data);
- RD_REG_WORD(®->gpiod);
+ wrt_reg_word(®->gpiod, gpio_data);
+ rd_reg_word(®->gpiod);
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -1731,13 +1732,13 @@
/* Save the Original GPIOD. */
spin_lock_irqsave(&ha->hardware_lock, flags);
- gpio_data = RD_REG_DWORD(®->gpiod);
+ gpio_data = rd_reg_dword(®->gpiod);
/* Enable the gpio_data reg for update. */
gpio_data |= GPDX_LED_UPDATE_MASK;
- WRT_REG_DWORD(®->gpiod, gpio_data);
- gpio_data = RD_REG_DWORD(®->gpiod);
+ wrt_reg_dword(®->gpiod, gpio_data);
+ gpio_data = rd_reg_dword(®->gpiod);
/* Set the color bits. */
qla24xx_flip_colors(ha, &led_color);
@@ -1749,8 +1750,8 @@
gpio_data |= led_color;
/* Set the modified gpio_data values. */
- WRT_REG_DWORD(®->gpiod, gpio_data);
- gpio_data = RD_REG_DWORD(®->gpiod);
+ wrt_reg_dword(®->gpiod, gpio_data);
+ gpio_data = rd_reg_dword(®->gpiod);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
@@ -1881,12 +1882,12 @@
goto skip_gpio;
spin_lock_irqsave(&ha->hardware_lock, flags);
- gpio_data = RD_REG_DWORD(®->gpiod);
+ gpio_data = rd_reg_dword(®->gpiod);
/* Enable the gpio_data reg for update. */
gpio_data |= GPDX_LED_UPDATE_MASK;
- WRT_REG_DWORD(®->gpiod, gpio_data);
- RD_REG_DWORD(®->gpiod);
+ wrt_reg_dword(®->gpiod, gpio_data);
+ rd_reg_dword(®->gpiod);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
@@ -1929,12 +1930,12 @@
/* Give control back to firmware. */
spin_lock_irqsave(&ha->hardware_lock, flags);
- gpio_data = RD_REG_DWORD(®->gpiod);
+ gpio_data = rd_reg_dword(®->gpiod);
/* Disable the gpio_data reg for update. */
gpio_data &= ~GPDX_LED_UPDATE_MASK;
- WRT_REG_DWORD(®->gpiod, gpio_data);
- RD_REG_DWORD(®->gpiod);
+ wrt_reg_dword(®->gpiod, gpio_data);
+ rd_reg_dword(®->gpiod);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
set_fw_options:
@@ -1970,10 +1971,10 @@
uint16_t data;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
- data = RD_REG_WORD(®->ctrl_status);
+ data = rd_reg_word(®->ctrl_status);
data |= CSR_FLASH_ENABLE;
- WRT_REG_WORD(®->ctrl_status, data);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->ctrl_status, data);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
}
/**
@@ -1986,10 +1987,10 @@
uint16_t data;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
- data = RD_REG_WORD(®->ctrl_status);
+ data = rd_reg_word(®->ctrl_status);
data &= ~(CSR_FLASH_ENABLE);
- WRT_REG_WORD(®->ctrl_status, data);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->ctrl_status, data);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
}
/**
@@ -2008,7 +2009,7 @@
uint16_t bank_select;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
- bank_select = RD_REG_WORD(®->ctrl_status);
+ bank_select = rd_reg_word(®->ctrl_status);
if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
/* Specify 64K address range: */
@@ -2016,11 +2017,11 @@
bank_select &= ~0xf8;
bank_select |= addr >> 12 & 0xf0;
bank_select |= CSR_FLASH_64K_BANK;
- WRT_REG_WORD(®->ctrl_status, bank_select);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->ctrl_status, bank_select);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
- WRT_REG_WORD(®->flash_address, (uint16_t)addr);
- data = RD_REG_WORD(®->flash_data);
+ wrt_reg_word(®->flash_address, (uint16_t)addr);
+ data = rd_reg_word(®->flash_data);
return (uint8_t)data;
}
@@ -2028,13 +2029,13 @@
/* Setup bit 16 of flash address. */
if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) {
bank_select |= CSR_FLASH_64K_BANK;
- WRT_REG_WORD(®->ctrl_status, bank_select);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->ctrl_status, bank_select);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
} else if (((addr & BIT_16) == 0) &&
(bank_select & CSR_FLASH_64K_BANK)) {
bank_select &= ~(CSR_FLASH_64K_BANK);
- WRT_REG_WORD(®->ctrl_status, bank_select);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->ctrl_status, bank_select);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
}
/* Always perform IO mapped accesses to the FLASH registers. */
@@ -2049,7 +2050,7 @@
data2 = RD_REG_WORD_PIO(PIO_REG(ha, flash_data));
} while (data != data2);
} else {
- WRT_REG_WORD(®->flash_address, (uint16_t)addr);
+ wrt_reg_word(®->flash_address, (uint16_t)addr);
data = qla2x00_debounce_register(®->flash_data);
}
@@ -2068,20 +2069,20 @@
uint16_t bank_select;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
- bank_select = RD_REG_WORD(®->ctrl_status);
+ bank_select = rd_reg_word(®->ctrl_status);
if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
/* Specify 64K address range: */
/* clear out Module Select and Flash Address bits [19:16]. */
bank_select &= ~0xf8;
bank_select |= addr >> 12 & 0xf0;
bank_select |= CSR_FLASH_64K_BANK;
- WRT_REG_WORD(®->ctrl_status, bank_select);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->ctrl_status, bank_select);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
- WRT_REG_WORD(®->flash_address, (uint16_t)addr);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
- WRT_REG_WORD(®->flash_data, (uint16_t)data);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->flash_address, (uint16_t)addr);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->flash_data, (uint16_t)data);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
return;
}
@@ -2089,13 +2090,13 @@
/* Setup bit 16 of flash address. */
if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) {
bank_select |= CSR_FLASH_64K_BANK;
- WRT_REG_WORD(®->ctrl_status, bank_select);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->ctrl_status, bank_select);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
} else if (((addr & BIT_16) == 0) &&
(bank_select & CSR_FLASH_64K_BANK)) {
bank_select &= ~(CSR_FLASH_64K_BANK);
- WRT_REG_WORD(®->ctrl_status, bank_select);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->ctrl_status, bank_select);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
}
/* Always perform IO mapped accesses to the FLASH registers. */
@@ -2103,10 +2104,10 @@
WRT_REG_WORD_PIO(PIO_REG(ha, flash_address), (uint16_t)addr);
WRT_REG_WORD_PIO(PIO_REG(ha, flash_data), (uint16_t)data);
} else {
- WRT_REG_WORD(®->flash_address, (uint16_t)addr);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
- WRT_REG_WORD(®->flash_data, (uint16_t)data);
- RD_REG_WORD(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->flash_address, (uint16_t)addr);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
+ wrt_reg_word(®->flash_data, (uint16_t)data);
+ rd_reg_word(®->ctrl_status); /* PCI Posting. */
}
}
@@ -2289,12 +2290,12 @@
midpoint = length / 2;
- WRT_REG_WORD(®->nvram, 0);
- RD_REG_WORD(®->nvram);
+ wrt_reg_word(®->nvram, 0);
+ rd_reg_word(®->nvram);
for (ilength = 0; ilength < length; saddr++, ilength++, tmp_buf++) {
if (ilength == midpoint) {
- WRT_REG_WORD(®->nvram, NVR_SELECT);
- RD_REG_WORD(®->nvram);
+ wrt_reg_word(®->nvram, NVR_SELECT);
+ rd_reg_word(®->nvram);
}
data = qla2x00_read_flash_byte(ha, saddr);
if (saddr % 100)
@@ -2319,11 +2320,11 @@
/* Pause RISC. */
spin_lock_irqsave(&ha->hardware_lock, flags);
- WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC);
- RD_REG_WORD(®->hccr);
+ wrt_reg_word(®->hccr, HCCR_PAUSE_RISC);
+ rd_reg_word(®->hccr);
if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
for (cnt = 0; cnt < 30000; cnt++) {
- if ((RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) != 0)
+ if ((rd_reg_word(®->hccr) & HCCR_RISC_PAUSE) != 0)
break;
udelay(100);
}
@@ -2362,12 +2363,12 @@
midpoint = ha->optrom_size / 2;
qla2x00_flash_enable(ha);
- WRT_REG_WORD(®->nvram, 0);
- RD_REG_WORD(®->nvram); /* PCI Posting. */
+ wrt_reg_word(®->nvram, 0);
+ rd_reg_word(®->nvram); /* PCI Posting. */
for (addr = offset, data = buf; addr < length; addr++, data++) {
if (addr == midpoint) {
- WRT_REG_WORD(®->nvram, NVR_SELECT);
- RD_REG_WORD(®->nvram); /* PCI Posting. */
+ wrt_reg_word(®->nvram, NVR_SELECT);
+ rd_reg_word(®->nvram); /* PCI Posting. */
}
*data = qla2x00_read_flash_byte(ha, addr);
@@ -2399,7 +2400,7 @@
sec_number = 0;
/* Reset ISP chip. */
- WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET);
+ wrt_reg_word(®->ctrl_status, CSR_ISP_SOFT_RESET);
pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
/* Go with write. */
@@ -2455,7 +2456,7 @@
sec_mask = 0x10000;
break;
}
- /* Fall through... */
+ fallthrough;
case 0x1f: /* Atmel flash. */
/* 512k sector size. */
@@ -2464,7 +2465,7 @@
sec_mask = 0x80000000;
break;
}
- /* Fall through... */
+ fallthrough;
case 0x01: /* AMD flash. */
if (flash_id == 0x38 || flash_id == 0x40 ||
@@ -2497,7 +2498,7 @@
sec_mask = 0x1e000;
break;
}
- /* fall through */
+ fallthrough;
default:
/* Default to 16 kb sector size. */
rest_addr = 0x3fff;
@@ -2548,8 +2549,8 @@
}
}
} else if (addr == ha->optrom_size / 2) {
- WRT_REG_WORD(®->nvram, NVR_SELECT);
- RD_REG_WORD(®->nvram);
+ wrt_reg_word(®->nvram, NVR_SELECT);
+ rd_reg_word(®->nvram);
}
if (flash_id == 0xda && man_id == 0xc1) {
@@ -2610,7 +2611,7 @@
set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
/* Go with read. */
- qla24xx_read_flash_data(vha, (void *)buf, offset >> 2, length >> 2);
+ qla24xx_read_flash_data(vha, buf, offset >> 2, length >> 2);
/* Resume HBA. */
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
@@ -2652,20 +2653,17 @@
struct qla_flt_region *region)
{
struct qla_hw_data *ha = vha->hw;
- struct qla_flt_header *flt;
- struct qla_flt_region *flt_reg;
+ struct qla_flt_header *flt = ha->flt;
+ struct qla_flt_region *flt_reg = &flt->region[0];
uint16_t cnt;
int rval = QLA_FUNCTION_FAILED;
if (!ha->flt)
return QLA_FUNCTION_FAILED;
- flt = (struct qla_flt_header *)ha->flt;
- flt_reg = (struct qla_flt_region *)&flt[1];
cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region);
-
for (; cnt; cnt--, flt_reg++) {
- if (flt_reg->start == start) {
+ if (le32_to_cpu(flt_reg->start) == start) {
memcpy((uint8_t *)region, flt_reg,
sizeof(struct qla_flt_region));
rval = QLA_SUCCESS;
@@ -2686,7 +2684,7 @@
uint32_t sec_mask, rest_addr, fdata;
void *optrom = NULL;
dma_addr_t optrom_dma;
- int rval;
+ int rval, ret;
struct secure_flash_update_block *sfub;
dma_addr_t sfub_dma;
uint32_t offset = faddr << 2;
@@ -2694,7 +2692,7 @@
struct qla_flt_region region;
bool reset_to_rom = false;
uint32_t risc_size, risc_attr = 0;
- uint32_t *fw_array = NULL;
+ __be32 *fw_array = NULL;
/* Retrieve region info - must be a start address passed in */
rval = qla28xx_get_flash_region(vha, offset, ®ion);
@@ -2725,12 +2723,12 @@
ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
"Region %x is secure\n", region.code);
- switch (region.code) {
+ switch (le16_to_cpu(region.code)) {
case FLT_REG_FW:
case FLT_REG_FW_SEC_27XX:
case FLT_REG_MPI_PRI_28XX:
case FLT_REG_MPI_SEC_28XX:
- fw_array = dwptr;
+ fw_array = (__force __be32 *)dwptr;
/* 1st fw array */
risc_size = be32_to_cpu(fw_array[3]);
@@ -2764,7 +2762,7 @@
case FLT_REG_PEP_PRI_28XX:
case FLT_REG_PEP_SEC_28XX:
- fw_array = dwptr;
+ fw_array = (__force __be32 *)dwptr;
/* 1st fw array */
risc_size = be32_to_cpu(fw_array[3]);
@@ -2895,7 +2893,8 @@
if (region.attribute && buf_size_without_sfub) {
ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
"Sending Secure Flash MB Cmd\n");
- rval = qla28xx_secure_flash_update(vha, 0, region.code,
+ rval = qla28xx_secure_flash_update(vha, 0,
+ le16_to_cpu(region.code),
buf_size_without_sfub, sfub_dma,
sizeof(struct secure_flash_update_block) >> 2);
if (rval != QLA_SUCCESS) {
@@ -2942,11 +2941,12 @@
write_protect:
ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
"Protect flash...\n");
- rval = qla24xx_protect_flash(vha);
- if (rval) {
+ ret = qla24xx_protect_flash(vha);
+ if (ret) {
qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK);
ql_log(ql_log_warn, vha, 0x7099,
"Failed protect flash\n");
+ rval = QLA_COMMAND_ERROR;
}
if (reset_to_rom == true) {
@@ -2954,10 +2954,12 @@
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
- rval = qla2x00_wait_for_hba_online(vha);
- if (rval != QLA_SUCCESS)
+ ret = qla2x00_wait_for_hba_online(vha);
+ if (ret != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0xffff,
"Adapter did not come out of reset\n");
+ rval = QLA_COMMAND_ERROR;
+ }
}
done:
@@ -2981,11 +2983,11 @@
/* Go with write. */
if (IS_QLA28XX(ha))
- rval = qla28xx_write_flash_data(vha, (uint32_t *)buf,
- offset >> 2, length >> 2);
+ rval = qla28xx_write_flash_data(vha, buf, offset >> 2,
+ length >> 2);
else
- rval = qla24xx_write_flash_data(vha, (uint32_t *)buf,
- offset >> 2, length >> 2);
+ rval = qla24xx_write_flash_data(vha, buf, offset >> 2,
+ length >> 2);
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
scsi_unblock_requests(vha->host);
@@ -3513,7 +3515,8 @@
ql_dump_buffer(ql_dbg_init, vha, 0x005f, dcode, 32);
} else {
for (i = 0; i < 4; i++)
- ha->fw_revision[i] = be32_to_cpu(dcode[4+i]);
+ ha->fw_revision[i] =
+ be32_to_cpu((__force __be32)dcode[4+i]);
ql_dbg(ql_dbg_init, vha, 0x0060,
"Firmware revision (flash) %u.%u.%u (%x).\n",
ha->fw_revision[0], ha->fw_revision[1],
@@ -3528,7 +3531,7 @@
memset(ha->gold_fw_version, 0, sizeof(ha->gold_fw_version));
faddr = ha->flt_region_gold_fw;
- qla24xx_read_flash_data(vha, (void *)dcode, ha->flt_region_gold_fw, 8);
+ qla24xx_read_flash_data(vha, dcode, ha->flt_region_gold_fw, 8);
if (qla24xx_risc_firmware_invalid(dcode)) {
ql_log(ql_log_warn, vha, 0x0056,
"Unrecognized golden fw at %#x.\n", faddr);
@@ -3537,7 +3540,8 @@
}
for (i = 0; i < 4; i++)
- ha->gold_fw_version[i] = be32_to_cpu(dcode[4+i]);
+ ha->gold_fw_version[i] =
+ be32_to_cpu((__force __be32)dcode[4+i]);
return ret;
}
@@ -3617,7 +3621,7 @@
/* read remaining FCP CMD config data from flash */
fcp_prio_addr += (FCP_PRIO_CFG_HDR_SIZE >> 2);
- len = ha->fcp_prio_cfg->num_entries * FCP_PRIO_CFG_ENTRY_SIZE;
+ len = ha->fcp_prio_cfg->num_entries * sizeof(struct qla_fcp_prio_entry);
max_len = FCP_PRIO_CFG_SIZE - FCP_PRIO_CFG_HDR_SIZE;
ha->isp_ops->read_optrom(vha, &ha->fcp_prio_cfg->entry[0],
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 57068e2..ebed14b 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -27,8 +27,6 @@
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
-#include <target/target_core_base.h>
-#include <target/target_core_fabric.h>
#include "qla_def.h"
#include "qla_target.h"
@@ -380,7 +378,7 @@
qlt_issue_marker(vha, ha_locked);
if ((entry->u.isp24.vp_index != 0xFF) &&
- (entry->u.isp24.nport_handle != 0xFFFF)) {
+ (entry->u.isp24.nport_handle != cpu_to_le16(0xFFFF))) {
host = qlt_find_host_by_vp_idx(vha,
entry->u.isp24.vp_index);
if (unlikely(!host)) {
@@ -444,7 +442,7 @@
ql_dbg(ql_dbg_tgt, vha, 0xe073,
"qla_target(%d):%s: CRC2 Response pkt\n",
vha->vp_idx, __func__);
- /* fall through */
+ fallthrough;
case CTIO_TYPE7:
{
struct ctio7_from_24xx *entry = (struct ctio7_from_24xx *)pkt;
@@ -463,7 +461,7 @@
case IMMED_NOTIFY_TYPE:
{
- struct scsi_qla_host *host = vha;
+ struct scsi_qla_host *host;
struct imm_ntfy_from_isp *entry =
(struct imm_ntfy_from_isp *)pkt;
@@ -967,7 +965,7 @@
sess->send_els_logo);
if (!IS_SW_RESV_ADDR(sess->d_id)) {
- qla2x00_mark_device_lost(vha, sess, 0, 0);
+ qla2x00_mark_device_lost(vha, sess, 0);
if (sess->send_els_logo) {
qlt_port_logo_t logo;
@@ -1113,6 +1111,8 @@
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
sess->free_pending = 0;
+ qla2x00_dfs_remove_rport(vha, sess);
+
ql_dbg(ql_dbg_disc, vha, 0xf001,
"Unregistration of sess %p %8phC finished fcp_cnt %d\n",
sess, sess->port_name, vha->fcport_count);
@@ -1702,7 +1702,7 @@
nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle;
if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) {
nack->u.isp24.flags = ntfy->u.isp24.flags &
- cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB);
+ cpu_to_le16(NOTIFY24XX_FLAGS_PUREX_IOCB);
}
nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id;
nack->u.isp24.status = ntfy->u.isp24.status;
@@ -1730,7 +1730,8 @@
struct scsi_qla_host *vha = mcmd->vha;
struct qla_hw_data *ha = vha->hw;
struct abts_resp_to_24xx *resp;
- uint32_t f_ctl, h;
+ __le32 f_ctl;
+ uint32_t h;
uint8_t *p;
int rc;
struct abts_recv_from_24xx *abts = &mcmd->orig_iocb.abts;
@@ -1763,7 +1764,7 @@
qpair->req->outstanding_cmds[h] = (srb_t *)mcmd;
}
- resp->handle = MAKE_HANDLE(qpair->req->id, h);
+ resp->handle = make_handle(qpair->req->id, h);
resp->entry_type = ABTS_RESP_24XX;
resp->entry_count = 1;
resp->nport_handle = abts->nport_handle;
@@ -1787,7 +1788,7 @@
resp->fcp_hdr_le.r_ctl = R_CTL_BASIC_LINK_SERV | R_CTL_B_ACC;
resp->payload.ba_acct.seq_id_valid = SEQ_ID_INVALID;
resp->payload.ba_acct.low_seq_cnt = 0x0000;
- resp->payload.ba_acct.high_seq_cnt = 0xFFFF;
+ resp->payload.ba_acct.high_seq_cnt = cpu_to_le16(0xFFFF);
resp->payload.ba_acct.ox_id = abts->fcp_hdr_le.ox_id;
resp->payload.ba_acct.rx_id = abts->fcp_hdr_le.rx_id;
} else {
@@ -1819,7 +1820,7 @@
struct scsi_qla_host *vha = qpair->vha;
struct qla_hw_data *ha = vha->hw;
struct abts_resp_to_24xx *resp;
- uint32_t f_ctl;
+ __le32 f_ctl;
uint8_t *p;
ql_dbg(ql_dbg_tgt, vha, 0xe006,
@@ -1862,7 +1863,7 @@
resp->fcp_hdr_le.r_ctl = R_CTL_BASIC_LINK_SERV | R_CTL_B_ACC;
resp->payload.ba_acct.seq_id_valid = SEQ_ID_INVALID;
resp->payload.ba_acct.low_seq_cnt = 0x0000;
- resp->payload.ba_acct.high_seq_cnt = 0xFFFF;
+ resp->payload.ba_acct.high_seq_cnt = cpu_to_le16(0xFFFF);
resp->payload.ba_acct.ox_id = abts->fcp_hdr_le.ox_id;
resp->payload.ba_acct.rx_id = abts->fcp_hdr_le.rx_id;
} else {
@@ -2029,13 +2030,13 @@
struct qla_tgt_mgmt_cmd *mcmd =
container_of(work, struct qla_tgt_mgmt_cmd, work);
struct qla_hw_data *ha = mcmd->vha->hw;
- int rc = EIO;
+ int rc;
uint32_t tag;
unsigned long flags;
switch (mcmd->tmr_func) {
case QLA_TGT_ABTS:
- tag = mcmd->orig_iocb.abts.exchange_addr_to_abort;
+ tag = le32_to_cpu(mcmd->orig_iocb.abts.exchange_addr_to_abort);
break;
default:
tag = 0;
@@ -2115,7 +2116,7 @@
struct qla_tgt_cmd *abort_cmd;
abort_cmd = ha->tgt.tgt_ops->find_cmd_by_tag(sess,
- abts->exchange_addr_to_abort);
+ le32_to_cpu(abts->exchange_addr_to_abort));
if (abort_cmd && abort_cmd->qpair) {
mcmd->qpair = abort_cmd->qpair;
mcmd->se_cmd.cpuid = abort_cmd->se_cmd.cpuid;
@@ -2138,7 +2139,7 @@
{
struct qla_hw_data *ha = vha->hw;
struct fc_port *sess;
- uint32_t tag = abts->exchange_addr_to_abort;
+ uint32_t tag = le32_to_cpu(abts->exchange_addr_to_abort);
be_id_t s_id;
int rc;
unsigned long flags;
@@ -2228,7 +2229,7 @@
ctio->entry_type = CTIO_TYPE7;
ctio->entry_count = 1;
ctio->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
- ctio->nport_handle = mcmd->sess->loop_id;
+ ctio->nport_handle = cpu_to_le16(mcmd->sess->loop_id);
ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
ctio->vp_index = ha->vp_idx;
ctio->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id);
@@ -2285,7 +2286,7 @@
ctio->entry_type = CTIO_TYPE7;
ctio->entry_count = 1;
ctio->handle = QLA_TGT_SKIP_HANDLE;
- ctio->nport_handle = cmd->sess->loop_id;
+ ctio->nport_handle = cpu_to_le16(cmd->sess->loop_id);
ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
ctio->vp_index = vha->vp_idx;
ctio->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id);
@@ -2489,7 +2490,7 @@
if (req->cnt < (req_cnt + 2)) {
cnt = (uint16_t)(qpair->use_shadow_reg ? *req->out_ptr :
- RD_REG_DWORD_RELAXED(req->req_q_out));
+ rd_reg_dword_relaxed(req->req_q_out));
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
@@ -2585,7 +2586,7 @@
} else
qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd;
- pkt->handle = MAKE_HANDLE(qpair->req->id, h);
+ pkt->handle = make_handle(qpair->req->id, h);
pkt->handle |= CTIO_COMPLETION_HANDLE_MARK;
pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id);
pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
@@ -2845,10 +2846,14 @@
cpu_to_le16(SS_SENSE_LEN_VALID);
ctio->u.status1.sense_length =
cpu_to_le16(prm->sense_buffer_len);
- for (i = 0; i < prm->sense_buffer_len/4; i++)
- ((uint32_t *)ctio->u.status1.sense_data)[i] =
- cpu_to_be32(((uint32_t *)prm->sense_buffer)[i]);
+ for (i = 0; i < prm->sense_buffer_len/4; i++) {
+ uint32_t v;
+ v = get_unaligned_be32(
+ &((uint32_t *)prm->sense_buffer)[i]);
+ put_unaligned_le32(v,
+ &((uint32_t *)ctio->u.status1.sense_data)[i]);
+ }
qlt_print_dif_err(prm);
} else {
@@ -3098,7 +3103,7 @@
} else
qpair->req->outstanding_cmds[h] = (srb_t *)prm->cmd;
- pkt->handle = MAKE_HANDLE(qpair->req->id, h);
+ pkt->handle = make_handle(qpair->req->id, h);
pkt->handle |= CTIO_COMPLETION_HANDLE_MARK;
pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id);
pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
@@ -3119,7 +3124,7 @@
else if (cmd->dma_data_direction == DMA_FROM_DEVICE)
pkt->flags = cpu_to_le16(CTIO7_FLAGS_DATA_OUT);
- pkt->dseg_count = prm->tot_dsds;
+ pkt->dseg_count = cpu_to_le16(prm->tot_dsds);
/* Fibre channel byte count */
pkt->transfer_length = cpu_to_le32(transfer_length);
@@ -3141,7 +3146,7 @@
qla_tgt_set_dif_tags(cmd, crc_ctx_pkt, &fw_prot_opts);
put_unaligned_le64(crc_ctx_dma, &pkt->crc_context_address);
- pkt->crc_context_len = CRC_CONTEXT_LEN_FW;
+ pkt->crc_context_len = cpu_to_le16(CRC_CONTEXT_LEN_FW);
if (!bundling) {
cur_dsd = &crc_ctx_pkt->u.nobundling.data_dsd[0];
@@ -3251,8 +3256,7 @@
"RESET-RSP online/active/old-count/new-count = %d/%d/%d/%d.\n",
vha->flags.online, qla2x00_reset_active(vha),
cmd->reset_count, qpair->chip_reset);
- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
- return 0;
+ goto out_unmap_unlock;
}
/* Does F/W have an IOCBs for this request */
@@ -3375,10 +3379,6 @@
prm.sg = NULL;
prm.req_cnt = 1;
- /* Calculate number of entries and segments required */
- if (qlt_pci_map_calc_cnt(&prm) != 0)
- return -EAGAIN;
-
if (!qpair->fw_started || (cmd->reset_count != qpair->chip_reset) ||
(cmd->sess && cmd->sess->deleted)) {
/*
@@ -3396,6 +3396,10 @@
return 0;
}
+ /* Calculate number of entries and segments required */
+ if (qlt_pci_map_calc_cnt(&prm) != 0)
+ return -EAGAIN;
+
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
/* Does F/W have an IOCBs for this request */
res = qlt_check_reserve_free_req(qpair, prm.req_cnt);
@@ -3457,13 +3461,13 @@
cmd->trc_flags |= TRC_DIF_ERR;
- cmd->a_guard = be16_to_cpu(*(uint16_t *)(ap + 0));
- cmd->a_app_tag = be16_to_cpu(*(uint16_t *)(ap + 2));
- cmd->a_ref_tag = be32_to_cpu(*(uint32_t *)(ap + 4));
+ cmd->a_guard = get_unaligned_be16(ap + 0);
+ cmd->a_app_tag = get_unaligned_be16(ap + 2);
+ cmd->a_ref_tag = get_unaligned_be32(ap + 4);
- cmd->e_guard = be16_to_cpu(*(uint16_t *)(ep + 0));
- cmd->e_app_tag = be16_to_cpu(*(uint16_t *)(ep + 2));
- cmd->e_ref_tag = be32_to_cpu(*(uint32_t *)(ep + 4));
+ cmd->e_guard = get_unaligned_be16(ep + 0);
+ cmd->e_app_tag = get_unaligned_be16(ep + 2);
+ cmd->e_ref_tag = get_unaligned_be32(ep + 4);
ql_dbg(ql_dbg_tgt_dif, vha, 0xf075,
"%s: aborted %d state %d\n", __func__, cmd->aborted, cmd->state);
@@ -3575,7 +3579,7 @@
nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle;
if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) {
nack->u.isp24.flags = ntfy->u.isp24.flags &
- __constant_cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB);
+ cpu_to_le16(NOTIFY24XX_FLAGS_PUREX_IOCB);
}
/* terminate */
@@ -3649,7 +3653,7 @@
ctio24 = (struct ctio7_to_24xx *)pkt;
ctio24->entry_type = CTIO_TYPE7;
- ctio24->nport_handle = CTIO7_NHANDLE_UNRECOGNIZED;
+ ctio24->nport_handle = cpu_to_le16(CTIO7_NHANDLE_UNRECOGNIZED);
ctio24->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
ctio24->vp_index = vha->vp_idx;
ctio24->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id);
@@ -3778,7 +3782,7 @@
"multiple abort. %p transport_state %x, t_state %x, "
"se_cmd_flags %x\n", cmd, cmd->se_cmd.transport_state,
cmd->se_cmd.t_state, cmd->se_cmd.se_cmd_flags);
- return EIO;
+ return -EIO;
}
cmd->aborted = 1;
cmd->trc_flags |= TRC_ABORT;
@@ -3800,9 +3804,6 @@
BUG_ON(cmd->cmd_in_wq);
- if (cmd->sg_mapped)
- qlt_unmap_sg(cmd->vha, cmd);
-
if (!cmd->q_full)
qlt_decr_num_pend_cmds(cmd->vha);
@@ -3816,7 +3817,7 @@
return;
}
cmd->jiffies_at_free = get_jiffies_64();
- target_free_tag(sess->se_sess, &cmd->se_cmd);
+ cmd->vha->hw->tgt.tgt_ops->rel_cmd(cmd);
}
EXPORT_SYMBOL(qlt_free_cmd);
@@ -3887,7 +3888,7 @@
return NULL;
}
- cmd = (void *) req->outstanding_cmds[h];
+ cmd = req->outstanding_cmds[h];
if (unlikely(cmd == NULL)) {
ql_dbg(ql_dbg_async, vha, 0xe053,
"qla_target(%d): Suspicious: unable to find the command with handle %x req->id %d rsp->id %d\n",
@@ -4112,7 +4113,7 @@
spin_lock_init(&cmd->cmd_lock);
cdb = &atio->u.isp24.fcp_cmnd.cdb[0];
- cmd->se_cmd.tag = atio->u.isp24.exchange_addr;
+ cmd->se_cmd.tag = le32_to_cpu(atio->u.isp24.exchange_addr);
if (atio->u.isp24.fcp_cmnd.rddata &&
atio->u.isp24.fcp_cmnd.wrdata) {
@@ -4150,7 +4151,7 @@
qlt_send_term_exchange(qpair, NULL, &cmd->atio, 1, 0);
qlt_decr_num_pend_cmds(vha);
- target_free_tag(sess->se_sess, &cmd->se_cmd);
+ cmd->vha->hw->tgt.tgt_ops->rel_cmd(cmd);
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
ha->tgt.tgt_ops->put_sess(sess);
@@ -4277,24 +4278,18 @@
struct fc_port *sess,
struct atio_from_isp *atio)
{
- struct se_session *se_sess = sess->se_sess;
struct qla_tgt_cmd *cmd;
- int tag, cpu;
- tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
- if (tag < 0)
+ cmd = vha->hw->tgt.tgt_ops->get_cmd(sess);
+ if (!cmd)
return NULL;
- cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag];
- memset(cmd, 0, sizeof(struct qla_tgt_cmd));
cmd->cmd_type = TYPE_TGT_CMD;
memcpy(&cmd->atio, atio, sizeof(*atio));
cmd->state = QLA_TGT_STATE_NEW;
cmd->tgt = vha->vha_tgt.qla_tgt;
qlt_incr_num_pend_cmds(vha);
cmd->vha = vha;
- cmd->se_cmd.map_tag = tag;
- cmd->se_cmd.map_cpu = cpu;
cmd->sess = sess;
cmd->loop_id = sess->loop_id;
cmd->conf_compl_supported = sess->conf_compl_supported;
@@ -4426,7 +4421,7 @@
case QLA_TGT_CLEAR_TS:
case QLA_TGT_ABORT_TS:
abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id);
- /* fall through */
+ fallthrough;
case QLA_TGT_CLEAR_ACA:
h = qlt_find_qphint(vha, mcmd->unpacked_lun);
mcmd->qpair = h->qpair;
@@ -4747,11 +4742,11 @@
qla24xx_post_newsess_work(vha, &port_id,
iocb->u.isp24.port_name,
iocb->u.isp24.u.plogi.node_name,
- pla, FC4_TYPE_UNKNOWN);
+ pla, 0);
else
qla24xx_post_newsess_work(vha, &port_id,
iocb->u.isp24.port_name, NULL,
- pla, FC4_TYPE_UNKNOWN);
+ pla, 0);
goto out;
}
@@ -5060,7 +5055,7 @@
res = 1;
break;
}
- /* fall through */
+ fallthrough;
case ELS_LOGO:
case ELS_PRLO:
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
@@ -5310,7 +5305,7 @@
ctio24 = (struct ctio7_to_24xx *)pkt;
ctio24->entry_type = CTIO_TYPE7;
- ctio24->nport_handle = sess->loop_id;
+ ctio24->nport_handle = cpu_to_le16(sess->loop_id);
ctio24->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
ctio24->vp_index = vha->vp_idx;
ctio24->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id);
@@ -5323,13 +5318,14 @@
* CTIO from fw w/o se_cmd doesn't provide enough info to retry it,
* if the explicit conformation is used.
*/
- ctio24->u.status1.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id);
+ ctio24->u.status1.ox_id =
+ cpu_to_le16(be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id));
ctio24->u.status1.scsi_status = cpu_to_le16(status);
- ctio24->u.status1.residual = get_datalen_for_atio(atio);
+ ctio24->u.status1.residual = cpu_to_le32(get_datalen_for_atio(atio));
if (ctio24->u.status1.residual != 0)
- ctio24->u.status1.scsi_status |= SS_RESIDUAL_UNDER;
+ ctio24->u.status1.scsi_status |= cpu_to_le16(SS_RESIDUAL_UNDER);
/* Memory Barrier */
wmb();
@@ -5352,9 +5348,7 @@
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
struct qla_hw_data *ha = vha->hw;
struct fc_port *sess;
- struct se_session *se_sess;
struct qla_tgt_cmd *cmd;
- int tag, cpu;
unsigned long flags;
if (unlikely(tgt->tgt_stop)) {
@@ -5384,10 +5378,8 @@
if (!sess)
return;
- se_sess = sess->se_sess;
-
- tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
- if (tag < 0) {
+ cmd = ha->tgt.tgt_ops->get_cmd(sess);
+ if (!cmd) {
ql_dbg(ql_dbg_io, vha, 0x3009,
"qla_target(%d): %s: Allocation of cmd failed\n",
vha->vp_idx, __func__);
@@ -5402,9 +5394,6 @@
return;
}
- cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag];
- memset(cmd, 0, sizeof(struct qla_tgt_cmd));
-
qlt_incr_num_pend_cmds(vha);
INIT_LIST_HEAD(&cmd->cmd_list);
memcpy(&cmd->atio, atio, sizeof(*atio));
@@ -5414,7 +5403,6 @@
cmd->reset_count = ha->base_qpair->chip_reset;
cmd->q_full = 1;
cmd->qpair = ha->base_qpair;
- cmd->se_cmd.map_cpu = cpu;
if (qfull) {
cmd->q_full = 1;
@@ -5566,7 +5554,7 @@
switch (atio->u.raw.entry_type) {
case ATIO_TYPE7:
if (unlikely(atio->u.isp24.exchange_addr ==
- ATIO_EXCHANGE_ADDRESS_UNKNOWN)) {
+ cpu_to_le32(ATIO_EXCHANGE_ADDRESS_UNKNOWN))) {
ql_dbg(ql_dbg_io, vha, 0x3065,
"qla_target(%d): ATIO_TYPE7 "
"received with UNKNOWN exchange address, "
@@ -5686,9 +5674,9 @@
vha, 0xffff, (uint8_t *)entry, sizeof(*entry));
if (qpair == ha->base_qpair)
- ha->isp_ops->fw_dump(vha, 1);
+ ha->isp_ops->fw_dump(vha);
else
- ha->isp_ops->fw_dump(vha, 0);
+ qla2xxx_dump_fw(vha);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
@@ -5729,8 +5717,8 @@
entry->compl_status);
if (le16_to_cpu(entry->compl_status) != ABTS_RESP_COMPL_SUCCESS) {
- if ((entry->error_subcode1 == 0x1E) &&
- (entry->error_subcode2 == 0)) {
+ if (le32_to_cpu(entry->error_subcode1) == 0x1E &&
+ le32_to_cpu(entry->error_subcode2) == 0) {
if (qlt_chk_unresolv_exchg(vha, rsp->qpair, entry)) {
ha->tgt.tgt_ops->free_mcmd(mcmd);
return;
@@ -5944,11 +5932,10 @@
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03b,
"qla_target(%d): Async LOOP_UP occurred "
"(m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx,
- le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
- le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
+ mailbox[0], mailbox[1], mailbox[2], mailbox[3]);
if (tgt->link_reinit_iocb_pending) {
qlt_send_notify_ack(ha->base_qpair,
- (void *)&tgt->link_reinit_iocb,
+ &tgt->link_reinit_iocb,
0, 0, 0, 0, 0, 0);
tgt->link_reinit_iocb_pending = 0;
}
@@ -5962,18 +5949,16 @@
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03c,
"qla_target(%d): Async event %#x occurred "
"(m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)", vha->vp_idx, code,
- le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
- le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
+ mailbox[0], mailbox[1], mailbox[2], mailbox[3]);
break;
case MBA_REJECTED_FCP_CMD:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf017,
"qla_target(%d): Async event LS_REJECT occurred (m[0]=%x, m[1]=%x, m[2]=%x, m[3]=%x)",
vha->vp_idx,
- le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
- le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
+ mailbox[0], mailbox[1], mailbox[2], mailbox[3]);
- if (le16_to_cpu(mailbox[3]) == 1) {
+ if (mailbox[3] == 1) {
/* exchange starvation. */
vha->hw->exch_starvation++;
if (vha->hw->exch_starvation > 5) {
@@ -5997,10 +5982,9 @@
"qla_target(%d): Port update async event %#x "
"occurred: updating the ports database (m[0]=%x, m[1]=%x, "
"m[2]=%x, m[3]=%x)", vha->vp_idx, code,
- le16_to_cpu(mailbox[0]), le16_to_cpu(mailbox[1]),
- le16_to_cpu(mailbox[2]), le16_to_cpu(mailbox[3]));
+ mailbox[0], mailbox[1], mailbox[2], mailbox[3]);
- login_code = le16_to_cpu(mailbox[2]);
+ login_code = mailbox[2];
if (login_code == 0x4) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf03e,
"Async MB 2: Got PLOGI Complete\n");
@@ -6677,9 +6661,14 @@
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
+
+ /*
+ * We are expecting the offline state.
+ * QLA_FUNCTION_FAILED means that adapter is offline.
+ */
if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
ql_dbg(ql_dbg_tgt, vha, 0xe081,
- "qla2x00_wait_for_hba_online() failed\n");
+ "adapter is offline\n");
}
/*
@@ -6745,7 +6734,7 @@
return;
for (cnt = 0; cnt < ha->tgt.atio_q_length; cnt++) {
- pkt->u.raw.signature = ATIO_PROCESSED;
+ pkt->u.raw.signature = cpu_to_le32(ATIO_PROCESSED);
pkt++;
}
@@ -6780,7 +6769,7 @@
"corrupted fcp frame SID[%3phN] OXID[%04x] EXCG[%x] %64phN\n",
&pkt->u.isp24.fcp_hdr.s_id,
be16_to_cpu(pkt->u.isp24.fcp_hdr.ox_id),
- le32_to_cpu(pkt->u.isp24.exchange_addr), pkt);
+ pkt->u.isp24.exchange_addr, pkt);
adjust_corrupted_atio(pkt);
qlt_send_term_exchange(ha->base_qpair, NULL, pkt,
@@ -6798,14 +6787,14 @@
} else
ha->tgt.atio_ring_ptr++;
- pkt->u.raw.signature = ATIO_PROCESSED;
+ pkt->u.raw.signature = cpu_to_le32(ATIO_PROCESSED);
pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr;
}
wmb();
}
/* Adjust ring index */
- WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), ha->tgt.atio_ring_index);
+ wrt_reg_dword(ISP_ATIO_Q_OUT(vha), ha->tgt.atio_ring_index);
}
void
@@ -6818,19 +6807,19 @@
if (!QLA_TGT_MODE_ENABLED())
return;
- WRT_REG_DWORD(ISP_ATIO_Q_IN(vha), 0);
- WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), 0);
- RD_REG_DWORD(ISP_ATIO_Q_OUT(vha));
+ wrt_reg_dword(ISP_ATIO_Q_IN(vha), 0);
+ wrt_reg_dword(ISP_ATIO_Q_OUT(vha), 0);
+ rd_reg_dword(ISP_ATIO_Q_OUT(vha));
if (ha->flags.msix_enabled) {
if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
if (IS_QLA2071(ha)) {
/* 4 ports Baker: Enable Interrupt Handshake */
icb->msix_atio = 0;
- icb->firmware_options_2 |= BIT_26;
+ icb->firmware_options_2 |= cpu_to_le32(BIT_26);
} else {
icb->msix_atio = cpu_to_le16(msix->entry);
- icb->firmware_options_2 &= ~BIT_26;
+ icb->firmware_options_2 &= cpu_to_le32(~BIT_26);
}
ql_dbg(ql_dbg_init, vha, 0xf072,
"Registering ICB vector 0x%x for atio que.\n",
@@ -6840,7 +6829,7 @@
/* INTx|MSI */
if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
icb->msix_atio = 0;
- icb->firmware_options_2 |= BIT_26;
+ icb->firmware_options_2 |= cpu_to_le32(BIT_26);
ql_dbg(ql_dbg_init, vha, 0xf072,
"%s: Use INTx for ATIOQ.\n", __func__);
}
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 2236751..1e94586 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -134,37 +134,37 @@
uint8_t entry_status; /* Entry Status. */
union {
struct {
- uint32_t sys_define_2; /* System defined. */
+ __le32 sys_define_2; /* System defined. */
target_id_t target;
uint8_t target_id;
uint8_t reserved_1;
- uint16_t flags;
- uint16_t resp_code;
- uint16_t status;
- uint16_t task_flags;
- uint16_t seq_id;
- uint16_t srr_rx_id;
- uint32_t srr_rel_offs;
- uint16_t srr_ui;
- uint16_t srr_flags;
- uint16_t srr_reject_code;
+ __le16 flags;
+ __le16 resp_code;
+ __le16 status;
+ __le16 task_flags;
+ __le16 seq_id;
+ __le16 srr_rx_id;
+ __le32 srr_rel_offs;
+ __le16 srr_ui;
+ __le16 srr_flags;
+ __le16 srr_reject_code;
uint8_t srr_reject_vendor_uniq;
uint8_t srr_reject_code_expl;
uint8_t reserved_2[24];
} isp2x;
struct {
uint32_t handle;
- uint16_t nport_handle;
+ __le16 nport_handle;
uint16_t reserved_1;
- uint16_t flags;
- uint16_t srr_rx_id;
- uint16_t status;
+ __le16 flags;
+ __le16 srr_rx_id;
+ __le16 status;
uint8_t status_subcode;
uint8_t fw_handle;
- uint32_t exchange_address;
- uint32_t srr_rel_offs;
- uint16_t srr_ui;
- uint16_t srr_flags;
+ __le32 exchange_address;
+ __le32 srr_rel_offs;
+ __le16 srr_ui;
+ __le16 srr_flags;
uint8_t reserved_4[19];
uint8_t vp_index;
uint8_t srr_reject_vendor_uniq;
@@ -174,7 +174,7 @@
} isp24;
} u;
uint8_t reserved[2];
- uint16_t ox_id;
+ __le16 ox_id;
} __packed;
#define NOTIFY_ACK_FLAGS_TERMINATE BIT_3
#define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0
@@ -205,16 +205,16 @@
uint8_t entry_status; /* Entry Status. */
uint32_t handle; /* System defined handle */
target_id_t target;
- uint16_t rx_id;
- uint16_t flags;
- uint16_t status;
- uint16_t timeout; /* 0 = 30 seconds, 0xFFFF = disable */
- uint16_t dseg_count; /* Data segment count. */
- uint32_t relative_offset;
- uint32_t residual;
- uint16_t reserved_1[3];
- uint16_t scsi_status;
- uint32_t transfer_length;
+ __le16 rx_id;
+ __le16 flags;
+ __le16 status;
+ __le16 timeout; /* 0 = 30 seconds, 0xFFFF = disable */
+ __le16 dseg_count; /* Data segment count. */
+ __le32 relative_offset;
+ __le32 residual;
+ __le16 reserved_1[3];
+ __le16 scsi_status;
+ __le32 transfer_length;
struct dsd32 dsd[3];
} __packed;
#define ATIO_PATH_INVALID 0x07
@@ -257,8 +257,8 @@
uint16_t seq_cnt;
__be16 ox_id;
uint16_t rx_id;
- uint32_t parameter;
-} __packed;
+ __le32 parameter;
+};
struct fcp_hdr_le {
le_id_t d_id;
@@ -267,13 +267,13 @@
uint8_t cs_ctl;
uint8_t f_ctl[3];
uint8_t type;
- uint16_t seq_cnt;
+ __le16 seq_cnt;
uint8_t df_ctl;
uint8_t seq_id;
- uint16_t rx_id;
- uint16_t ox_id;
- uint32_t parameter;
-} __packed;
+ __le16 rx_id;
+ __le16 ox_id;
+ __le32 parameter;
+};
#define F_CTL_EXCH_CONTEXT_RESP BIT_23
#define F_CTL_SEQ_CONTEXT_RESIP BIT_22
@@ -306,7 +306,7 @@
* BUILD_BUG_ON in qlt_init().
*/
uint8_t add_cdb[4];
- /* uint32_t data_length; */
+ /* __le32 data_length; */
} __packed;
/*
@@ -316,31 +316,31 @@
struct atio_from_isp {
union {
struct {
- uint16_t entry_hdr;
+ __le16 entry_hdr;
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
- uint32_t sys_define_2; /* System defined. */
+ __le32 sys_define_2; /* System defined. */
target_id_t target;
- uint16_t rx_id;
- uint16_t flags;
- uint16_t status;
+ __le16 rx_id;
+ __le16 flags;
+ __le16 status;
uint8_t command_ref;
uint8_t task_codes;
uint8_t task_flags;
uint8_t execution_codes;
uint8_t cdb[MAX_CMDSZ];
- uint32_t data_length;
- uint16_t lun;
+ __le32 data_length;
+ __le16 lun;
uint8_t initiator_port_name[WWN_SIZE]; /* on qla23xx */
- uint16_t reserved_32[6];
- uint16_t ox_id;
+ __le16 reserved_32[6];
+ __le16 ox_id;
} isp2x;
struct {
- uint16_t entry_hdr;
+ __le16 entry_hdr;
uint8_t fcp_cmnd_len_low;
uint8_t fcp_cmnd_len_high:4;
uint8_t attr:4;
- uint32_t exchange_addr;
+ __le32 exchange_addr;
#define ATIO_EXCHANGE_ADDRESS_UNKNOWN 0xFFFFFFFF
struct fcp_hdr fcp_hdr;
struct atio7_fcp_cmnd fcp_cmnd;
@@ -352,7 +352,7 @@
#define FCP_CMD_LENGTH_MASK 0x0fff
#define FCP_CMD_LENGTH_MIN 0x38
uint8_t data[56];
- uint32_t signature;
+ __le32 signature;
#define ATIO_PROCESSED 0xDEADDEAD /* Signature */
} raw;
} u;
@@ -379,8 +379,7 @@
{
int len = atio->u.isp24.fcp_cmnd.add_cdb_len;
- return (be32_to_cpu(get_unaligned((uint32_t *)
- &atio->u.isp24.fcp_cmnd.add_cdb[len * 4])));
+ return get_unaligned_be32(&atio->u.isp24.fcp_cmnd.add_cdb[len * 4]);
}
#define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */
@@ -396,36 +395,36 @@
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
uint32_t handle; /* System defined handle */
- uint16_t nport_handle;
+ __le16 nport_handle;
#define CTIO7_NHANDLE_UNRECOGNIZED 0xFFFF
- uint16_t timeout;
- uint16_t dseg_count; /* Data segment count. */
+ __le16 timeout;
+ __le16 dseg_count; /* Data segment count. */
uint8_t vp_index;
uint8_t add_flags;
le_id_t initiator_id;
uint8_t reserved;
- uint32_t exchange_addr;
+ __le32 exchange_addr;
union {
struct {
- uint16_t reserved1;
+ __le16 reserved1;
__le16 flags;
- uint32_t residual;
+ __le32 residual;
__le16 ox_id;
- uint16_t scsi_status;
- uint32_t relative_offset;
- uint32_t reserved2;
- uint32_t transfer_length;
- uint32_t reserved3;
+ __le16 scsi_status;
+ __le32 relative_offset;
+ __le32 reserved2;
+ __le32 transfer_length;
+ __le32 reserved3;
struct dsd64 dsd;
} status0;
struct {
- uint16_t sense_length;
+ __le16 sense_length;
__le16 flags;
- uint32_t residual;
+ __le32 residual;
__le16 ox_id;
- uint16_t scsi_status;
- uint16_t response_len;
- uint16_t reserved;
+ __le16 scsi_status;
+ __le16 response_len;
+ __le16 reserved;
uint8_t sense_data[24];
} status1;
} u;
@@ -441,18 +440,18 @@
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
uint32_t handle; /* System defined handle */
- uint16_t status;
- uint16_t timeout;
- uint16_t dseg_count; /* Data segment count. */
+ __le16 status;
+ __le16 timeout;
+ __le16 dseg_count; /* Data segment count. */
uint8_t vp_index;
uint8_t reserved1[5];
- uint32_t exchange_address;
- uint16_t reserved2;
- uint16_t flags;
- uint32_t residual;
- uint16_t ox_id;
- uint16_t reserved3;
- uint32_t relative_offset;
+ __le32 exchange_address;
+ __le16 reserved2;
+ __le16 flags;
+ __le32 residual;
+ __le16 ox_id;
+ __le16 reserved3;
+ __le32 relative_offset;
uint8_t reserved4[24];
} __packed;
@@ -490,29 +489,29 @@
uint8_t entry_status; /* Entry Status. */
uint32_t handle; /* System handle. */
- uint16_t nport_handle; /* N_PORT handle. */
+ __le16 nport_handle; /* N_PORT handle. */
__le16 timeout; /* Command timeout. */
- uint16_t dseg_count; /* Data segment count. */
+ __le16 dseg_count; /* Data segment count. */
uint8_t vp_index;
uint8_t add_flags; /* additional flags */
#define CTIO_CRC2_AF_DIF_DSD_ENA BIT_3
le_id_t initiator_id; /* initiator ID */
uint8_t reserved1;
- uint32_t exchange_addr; /* rcv exchange address */
- uint16_t reserved2;
+ __le32 exchange_addr; /* rcv exchange address */
+ __le16 reserved2;
__le16 flags; /* refer to CTIO7 flags values */
- uint32_t residual;
+ __le32 residual;
__le16 ox_id;
- uint16_t scsi_status;
+ __le16 scsi_status;
__le32 relative_offset;
- uint32_t reserved5;
+ __le32 reserved5;
__le32 transfer_length; /* total fc transfer length */
- uint32_t reserved6;
+ __le32 reserved6;
__le64 crc_context_address __packed; /* Data segment address. */
- uint16_t crc_context_len; /* Data segment length. */
- uint16_t reserved_1; /* MUST be set to 0. */
+ __le16 crc_context_len; /* Data segment length. */
+ __le16 reserved_1; /* MUST be set to 0. */
};
/* CTIO Type CRC_x Status IOCB */
@@ -523,20 +522,20 @@
uint8_t entry_status; /* Entry Status. */
uint32_t handle; /* System handle. */
- uint16_t status;
- uint16_t timeout; /* Command timeout. */
- uint16_t dseg_count; /* Data segment count. */
- uint32_t reserved1;
- uint16_t state_flags;
+ __le16 status;
+ __le16 timeout; /* Command timeout. */
+ __le16 dseg_count; /* Data segment count. */
+ __le32 reserved1;
+ __le16 state_flags;
#define CTIO_CRC_SF_DIF_CHOPPED BIT_4
- uint32_t exchange_address; /* rcv exchange address */
- uint16_t reserved2;
- uint16_t flags;
- uint32_t resid_xfer_length;
- uint16_t ox_id;
+ __le32 exchange_address; /* rcv exchange address */
+ __le16 reserved2;
+ __le16 flags;
+ __le32 resid_xfer_length;
+ __le16 ox_id;
uint8_t reserved3[12];
- uint16_t runt_guard; /* reported runt blk guard */
+ __le16 runt_guard; /* reported runt blk guard */
uint8_t actual_dif[8];
uint8_t expected_dif[8];
} __packed;
@@ -559,29 +558,29 @@
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
uint8_t reserved_1[6];
- uint16_t nport_handle;
+ __le16 nport_handle;
uint8_t reserved_2[2];
uint8_t vp_index;
uint8_t reserved_3:4;
uint8_t sof_type:4;
- uint32_t exchange_address;
+ __le32 exchange_address;
struct fcp_hdr_le fcp_hdr_le;
uint8_t reserved_4[16];
- uint32_t exchange_addr_to_abort;
+ __le32 exchange_addr_to_abort;
} __packed;
#define ABTS_PARAM_ABORT_SEQ BIT_0
struct ba_acc_le {
- uint16_t reserved;
+ __le16 reserved;
uint8_t seq_id_last;
uint8_t seq_id_valid;
#define SEQ_ID_VALID 0x80
#define SEQ_ID_INVALID 0x00
- uint16_t rx_id;
- uint16_t ox_id;
- uint16_t high_seq_cnt;
- uint16_t low_seq_cnt;
+ __le16 rx_id;
+ __le16 ox_id;
+ __le16 high_seq_cnt;
+ __le16 low_seq_cnt;
} __packed;
struct ba_rjt_le {
@@ -605,21 +604,21 @@
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
uint32_t handle;
- uint16_t reserved_1;
- uint16_t nport_handle;
- uint16_t control_flags;
+ __le16 reserved_1;
+ __le16 nport_handle;
+ __le16 control_flags;
#define ABTS_CONTR_FLG_TERM_EXCHG BIT_0
uint8_t vp_index;
uint8_t reserved_3:4;
uint8_t sof_type:4;
- uint32_t exchange_address;
+ __le32 exchange_address;
struct fcp_hdr_le fcp_hdr_le;
union {
struct ba_acc_le ba_acct;
struct ba_rjt_le ba_rjt;
} __packed payload;
- uint32_t reserved_4;
- uint32_t exchange_addr_to_abort;
+ __le32 reserved_4;
+ __le32 exchange_addr_to_abort;
} __packed;
/*
@@ -635,21 +634,21 @@
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
uint32_t handle;
- uint16_t compl_status;
+ __le16 compl_status;
#define ABTS_RESP_COMPL_SUCCESS 0
#define ABTS_RESP_COMPL_SUBCODE_ERROR 0x31
- uint16_t nport_handle;
- uint16_t reserved_1;
+ __le16 nport_handle;
+ __le16 reserved_1;
uint8_t reserved_2;
uint8_t reserved_3:4;
uint8_t sof_type:4;
- uint32_t exchange_address;
+ __le32 exchange_address;
struct fcp_hdr_le fcp_hdr_le;
uint8_t reserved_4[8];
- uint32_t error_subcode1;
+ __le32 error_subcode1;
#define ABTS_RESP_SUBCODE_ERR_ABORTED_EXCH_NOT_TERM 0x1E
- uint32_t error_subcode2;
- uint32_t exchange_addr_to_abort;
+ __le32 error_subcode2;
+ __le32 exchange_addr_to_abort;
} __packed;
/********************************************************************\
@@ -672,6 +671,8 @@
void (*handle_data)(struct qla_tgt_cmd *);
int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, u64, uint16_t,
uint32_t);
+ struct qla_tgt_cmd *(*get_cmd)(struct fc_port *);
+ void (*rel_cmd)(struct qla_tgt_cmd *);
void (*free_cmd)(struct qla_tgt_cmd *);
void (*free_mcmd)(struct qla_tgt_mgmt_cmd *);
void (*free_session)(struct fc_port *);
diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c
index f169292..26c13a9 100644
--- a/drivers/scsi/qla2xxx/qla_tmpl.c
+++ b/drivers/scsi/qla2xxx/qla_tmpl.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#include "qla_def.h"
#include "qla_tmpl.h"
@@ -10,6 +9,7 @@
#define ISPREG(vha) (&(vha)->hw->iobase->isp24)
#define IOBAR(reg) offsetof(typeof(*(reg)), iobase_addr)
#define IOBASE(vha) IOBAR(ISPREG(vha))
+#define INVALID_ENTRY ((struct qla27xx_fwdt_entry *)0xffffffffffffffffUL)
static inline void
qla27xx_insert16(uint16_t value, void *buf, ulong *len)
@@ -47,7 +47,7 @@
uint8_t value = ~0;
if (buf) {
- value = RD_REG_BYTE(window);
+ value = rd_reg_byte(window);
}
qla27xx_insert32(value, buf, len);
}
@@ -58,7 +58,7 @@
uint16_t value = ~0;
if (buf) {
- value = RD_REG_WORD(window);
+ value = rd_reg_word(window);
}
qla27xx_insert32(value, buf, len);
}
@@ -69,7 +69,7 @@
uint32_t value = ~0;
if (buf) {
- value = RD_REG_DWORD(window);
+ value = rd_reg_dword(window);
}
qla27xx_insert32(value, buf, len);
}
@@ -98,7 +98,7 @@
if (buf) {
void __iomem *window = (void __iomem *)reg + offset;
- WRT_REG_DWORD(window, data);
+ wrt_reg_dword(window, data);
}
}
@@ -261,6 +261,7 @@
ulong start = le32_to_cpu(ent->t262.start_addr);
ulong end = le32_to_cpu(ent->t262.end_addr);
ulong dwords;
+ int rc;
ql_dbg(ql_dbg_misc, vha, 0xd206,
"%s: rdram(%x) [%lx]\n", __func__, ent->t262.ram_area, *len);
@@ -308,7 +309,13 @@
dwords = end - start + 1;
if (buf) {
buf += *len;
- qla24xx_dump_ram(vha->hw, start, buf, dwords, &buf);
+ rc = qla24xx_dump_ram(vha->hw, start, buf, dwords, &buf);
+ if (rc != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_async, vha, 0xffff,
+ "%s: dump ram MB failed. Area %xh start %lxh end %lxh\n",
+ __func__, area, start, end);
+ return INVALID_ENTRY;
+ }
}
*len += dwords * sizeof(uint32_t);
done:
@@ -838,6 +845,13 @@
ent = qla27xx_find_entry(type)(vha, ent, buf, len);
if (!ent)
break;
+
+ if (ent == INVALID_ENTRY) {
+ *len = 0;
+ ql_dbg(ql_dbg_async, vha, 0xffff,
+ "Unable to capture FW dump");
+ goto bailout;
+ }
}
if (tmp->count)
@@ -847,12 +861,15 @@
if (ent)
ql_dbg(ql_dbg_misc, vha, 0xd019,
"%s: missing end entry\n", __func__);
+
+bailout:
+ cpu_to_le32s(&tmp->count); /* endianize residual count */
}
static void
qla27xx_time_stamp(struct qla27xx_fwdt_template *tmp)
{
- tmp->capture_timestamp = jiffies;
+ tmp->capture_timestamp = cpu_to_le32(jiffies);
}
static void
@@ -861,25 +878,26 @@
uint8_t v[] = { 0, 0, 0, 0, 0, 0 };
WARN_ON_ONCE(sscanf(qla2x00_version_str,
- "%hhu.%hhu.%hhu.%hhu.%hhu.%hhu",
- v+0, v+1, v+2, v+3, v+4, v+5) != 6);
+ "%hhu.%hhu.%hhu.%hhu",
+ v + 0, v + 1, v + 2, v + 3) != 4);
- tmp->driver_info[0] = v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0];
- tmp->driver_info[1] = v[5] << 8 | v[4];
- tmp->driver_info[2] = 0x12345678;
+ tmp->driver_info[0] = cpu_to_le32(
+ v[3] << 24 | v[2] << 16 | v[1] << 8 | v[0]);
+ tmp->driver_info[1] = cpu_to_le32(v[5] << 8 | v[4]);
+ tmp->driver_info[2] = __constant_cpu_to_le32(0x12345678);
}
static void
qla27xx_firmware_info(struct scsi_qla_host *vha,
struct qla27xx_fwdt_template *tmp)
{
- tmp->firmware_version[0] = vha->hw->fw_major_version;
- tmp->firmware_version[1] = vha->hw->fw_minor_version;
- tmp->firmware_version[2] = vha->hw->fw_subminor_version;
- tmp->firmware_version[3] =
- vha->hw->fw_attributes_h << 16 | vha->hw->fw_attributes;
- tmp->firmware_version[4] =
- vha->hw->fw_attributes_ext[1] << 16 | vha->hw->fw_attributes_ext[0];
+ tmp->firmware_version[0] = cpu_to_le32(vha->hw->fw_major_version);
+ tmp->firmware_version[1] = cpu_to_le32(vha->hw->fw_minor_version);
+ tmp->firmware_version[2] = cpu_to_le32(vha->hw->fw_subminor_version);
+ tmp->firmware_version[3] = cpu_to_le32(
+ vha->hw->fw_attributes_h << 16 | vha->hw->fw_attributes);
+ tmp->firmware_version[4] = cpu_to_le32(
+ vha->hw->fw_attributes_ext[1] << 16 | vha->hw->fw_attributes_ext[0]);
}
static void
@@ -980,14 +998,65 @@
}
void
-qla27xx_fwdump(scsi_qla_host_t *vha, int hardware_locked)
+qla27xx_mpi_fwdump(scsi_qla_host_t *vha, int hardware_locked)
{
ulong flags = 0;
-#ifndef __CHECKER__
if (!hardware_locked)
spin_lock_irqsave(&vha->hw->hardware_lock, flags);
-#endif
+ if (!vha->hw->mpi_fw_dump) {
+ ql_log(ql_log_warn, vha, 0x02f3, "-> mpi_fwdump no buffer\n");
+ } else {
+ struct fwdt *fwdt = &vha->hw->fwdt[1];
+ ulong len;
+ void *buf = vha->hw->mpi_fw_dump;
+ bool walk_template_only = false;
+
+ if (vha->hw->mpi_fw_dumped) {
+ /* Use the spare area for any further dumps. */
+ buf += fwdt->dump_size;
+ walk_template_only = true;
+ ql_log(ql_log_warn, vha, 0x02f4,
+ "-> MPI firmware already dumped -- dump saving to temporary buffer %p.\n",
+ buf);
+ }
+
+ ql_log(ql_log_warn, vha, 0x02f5, "-> fwdt1 running...\n");
+ if (!fwdt->template) {
+ ql_log(ql_log_warn, vha, 0x02f6,
+ "-> fwdt1 no template\n");
+ goto bailout;
+ }
+ len = qla27xx_execute_fwdt_template(vha, fwdt->template, buf);
+ if (len == 0) {
+ goto bailout;
+ } else if (len != fwdt->dump_size) {
+ ql_log(ql_log_warn, vha, 0x02f7,
+ "-> fwdt1 fwdump residual=%+ld\n",
+ fwdt->dump_size - len);
+ }
+ vha->hw->stat.num_mpi_reset++;
+ if (walk_template_only)
+ goto bailout;
+
+ vha->hw->mpi_fw_dump_len = len;
+ vha->hw->mpi_fw_dumped = 1;
+
+ ql_log(ql_log_warn, vha, 0x02f8,
+ "-> MPI firmware dump saved to buffer (%lu/%p)\n",
+ vha->host_no, vha->hw->mpi_fw_dump);
+ qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP);
+ }
+
+bailout:
+ if (!hardware_locked)
+ spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
+}
+
+void
+qla27xx_fwdump(scsi_qla_host_t *vha)
+{
+ lockdep_assert_held(&vha->hw->hardware_lock);
if (!vha->hw->fw_dump) {
ql_log(ql_log_warn, vha, 0xd01e, "-> fwdump no buffer\n");
@@ -997,37 +1066,30 @@
vha->hw->fw_dump);
} else {
struct fwdt *fwdt = vha->hw->fwdt;
- uint j;
ulong len;
void *buf = vha->hw->fw_dump;
- for (j = 0; j < 2; j++, fwdt++, buf += len) {
- ql_log(ql_log_warn, vha, 0xd011,
- "-> fwdt%u running...\n", j);
- if (!fwdt->template) {
- ql_log(ql_log_warn, vha, 0xd012,
- "-> fwdt%u no template\n", j);
- break;
- }
- len = qla27xx_execute_fwdt_template(vha,
- fwdt->template, buf);
- if (len != fwdt->dump_size) {
- ql_log(ql_log_warn, vha, 0xd013,
- "-> fwdt%u fwdump residual=%+ld\n",
- j, fwdt->dump_size - len);
- }
+ ql_log(ql_log_warn, vha, 0xd011, "-> fwdt0 running...\n");
+ if (!fwdt->template) {
+ ql_log(ql_log_warn, vha, 0xd012,
+ "-> fwdt0 no template\n");
+ return;
}
- vha->hw->fw_dump_len = buf - (void *)vha->hw->fw_dump;
- vha->hw->fw_dumped = 1;
+ len = qla27xx_execute_fwdt_template(vha, fwdt->template, buf);
+ if (len == 0) {
+ return;
+ } else if (len != fwdt->dump_size) {
+ ql_log(ql_log_warn, vha, 0xd013,
+ "-> fwdt0 fwdump residual=%+ld\n",
+ fwdt->dump_size - len);
+ }
+
+ vha->hw->fw_dump_len = len;
+ vha->hw->fw_dumped = true;
ql_log(ql_log_warn, vha, 0xd015,
"-> Firmware dump saved to buffer (%lu/%p) <%lx>\n",
vha->host_no, vha->hw->fw_dump, vha->hw->fw_dump_cap_flags);
qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP);
}
-
-#ifndef __CHECKER__
- if (!hardware_locked)
- spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
-#endif
}
diff --git a/drivers/scsi/qla2xxx/qla_tmpl.h b/drivers/scsi/qla2xxx/qla_tmpl.h
index fb8ab3b..6e0987e 100644
--- a/drivers/scsi/qla2xxx/qla_tmpl.h
+++ b/drivers/scsi/qla2xxx/qla_tmpl.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
#ifndef __QLA_DMP27_H__
@@ -18,16 +17,16 @@
__le32 entry_count;
uint32_t template_version;
- uint32_t capture_timestamp;
+ __le32 capture_timestamp;
uint32_t template_checksum;
uint32_t reserved_2;
- uint32_t driver_info[3];
+ __le32 driver_info[3];
uint32_t saved_state[16];
uint32_t reserved_3[8];
- uint32_t firmware_version[5];
+ __le32 firmware_version[5];
};
#define TEMPLATE_TYPE_FWDUMP 99
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index a8f2a95..c2d4da5 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -1,15 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
*/
/*
* Driver version
*/
-#define QLA2XXX_VERSION "10.01.00.19-k"
+#define QLA2XXX_VERSION "10.02.00.103-k"
#define QLA_DRIVER_MAJOR_VER 10
-#define QLA_DRIVER_MINOR_VER 1
+#define QLA_DRIVER_MINOR_VER 2
#define QLA_DRIVER_PATCH_VER 0
-#define QLA_DRIVER_BETA_VER 0
+#define QLA_DRIVER_BETA_VER 103
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index df8644d..7405fab 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -268,6 +268,29 @@
transport_generic_free_cmd(&cmd->se_cmd, 0);
}
+static struct qla_tgt_cmd *tcm_qla2xxx_get_cmd(struct fc_port *sess)
+{
+ struct se_session *se_sess = sess->se_sess;
+ struct qla_tgt_cmd *cmd;
+ int tag, cpu;
+
+ tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
+ if (tag < 0)
+ return NULL;
+
+ cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag];
+ memset(cmd, 0, sizeof(struct qla_tgt_cmd));
+ cmd->se_cmd.map_tag = tag;
+ cmd->se_cmd.map_cpu = cpu;
+
+ return cmd;
+}
+
+static void tcm_qla2xxx_rel_cmd(struct qla_tgt_cmd *cmd)
+{
+ target_free_tag(cmd->sess->se_sess, &cmd->se_cmd);
+}
+
/*
* Called from qla_target_template->free_cmd(), and will call
* tcm_qla2xxx_release_cmd via normal struct target_core_fabric_ops
@@ -823,7 +846,7 @@
struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, \
struct tcm_qla2xxx_tpg, se_tpg); \
\
- return sprintf(page, "%u\n", tpg->tpg_attrib.name); \
+ return sprintf(page, "%d\n", tpg->tpg_attrib.name); \
} \
\
static ssize_t tcm_qla2xxx_tpg_attrib_##name##_store( \
@@ -1547,6 +1570,8 @@
.handle_cmd = tcm_qla2xxx_handle_cmd,
.handle_data = tcm_qla2xxx_handle_data,
.handle_tmr = tcm_qla2xxx_handle_tmr,
+ .get_cmd = tcm_qla2xxx_get_cmd,
+ .rel_cmd = tcm_qla2xxx_rel_cmd,
.free_cmd = tcm_qla2xxx_free_cmd,
.free_mcmd = tcm_qla2xxx_free_mcmd,
.free_session = tcm_qla2xxx_free_session,
@@ -1931,6 +1956,21 @@
{
int ret;
+ BUILD_BUG_ON(sizeof(struct abts_recv_from_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct abts_resp_from_24xx_fw) != 64);
+ BUILD_BUG_ON(sizeof(struct atio7_fcp_cmnd) != 32);
+ BUILD_BUG_ON(sizeof(struct atio_from_isp) != 64);
+ BUILD_BUG_ON(sizeof(struct ba_acc_le) != 12);
+ BUILD_BUG_ON(sizeof(struct ba_rjt_le) != 4);
+ BUILD_BUG_ON(sizeof(struct ctio7_from_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct ctio7_to_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct ctio_crc2_to_fw) != 64);
+ BUILD_BUG_ON(sizeof(struct ctio_crc_from_fw) != 64);
+ BUILD_BUG_ON(sizeof(struct ctio_to_2xxx) != 64);
+ BUILD_BUG_ON(sizeof(struct fcp_hdr) != 24);
+ BUILD_BUG_ON(sizeof(struct fcp_hdr_le) != 24);
+ BUILD_BUG_ON(sizeof(struct nack_to_isp) != 64);
+
ret = tcm_qla2xxx_register_configfs();
if (ret < 0)
return ret;
diff --git a/drivers/scsi/qla4xxx/Kconfig b/drivers/scsi/qla4xxx/Kconfig
index 4bdf31b..2fa249d 100644
--- a/drivers/scsi/qla4xxx/Kconfig
+++ b/drivers/scsi/qla4xxx/Kconfig
@@ -4,6 +4,6 @@
depends on PCI && SCSI && NET
select SCSI_ISCSI_ATTRS
select ISCSI_BOOT_SYSFS
- ---help---
+ help
This driver supports the QLogic 40xx (ISP4XXX), 8022 (ISP82XX)
and 8032 (ISP83XX) iSCSI host adapter family.
diff --git a/drivers/scsi/qla4xxx/ql4_83xx.c b/drivers/scsi/qla4xxx/ql4_83xx.c
index 638f72c..5f56122 100644
--- a/drivers/scsi/qla4xxx/ql4_83xx.c
+++ b/drivers/scsi/qla4xxx/ql4_83xx.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#include <linux/ratelimit.h>
@@ -1406,16 +1405,16 @@
static void qla4_83xx_dump_pause_control_regs(struct scsi_qla_host *ha)
{
u32 val = 0, val1 = 0;
- int i, status = QLA_SUCCESS;
+ int i;
- status = qla4_83xx_rd_reg_indirect(ha, QLA83XX_SRE_SHIM_CONTROL, &val);
+ qla4_83xx_rd_reg_indirect(ha, QLA83XX_SRE_SHIM_CONTROL, &val);
DEBUG2(ql4_printk(KERN_INFO, ha, "SRE-Shim Ctrl:0x%x\n", val));
/* Port 0 Rx Buffer Pause Threshold Registers. */
DEBUG2(ql4_printk(KERN_INFO, ha,
"Port 0 Rx Buffer Pause Threshold Registers[TC7..TC0]:"));
for (i = 0; i < 8; i++) {
- status = qla4_83xx_rd_reg_indirect(ha,
+ qla4_83xx_rd_reg_indirect(ha,
QLA83XX_PORT0_RXB_PAUSE_THRS + (i * 0x4), &val);
DEBUG2(pr_info("0x%x ", val));
}
@@ -1426,7 +1425,7 @@
DEBUG2(ql4_printk(KERN_INFO, ha,
"Port 1 Rx Buffer Pause Threshold Registers[TC7..TC0]:"));
for (i = 0; i < 8; i++) {
- status = qla4_83xx_rd_reg_indirect(ha,
+ qla4_83xx_rd_reg_indirect(ha,
QLA83XX_PORT1_RXB_PAUSE_THRS + (i * 0x4), &val);
DEBUG2(pr_info("0x%x ", val));
}
@@ -1437,7 +1436,7 @@
DEBUG2(ql4_printk(KERN_INFO, ha,
"Port 0 RxB Traffic Class Max Cell Registers[3..0]:"));
for (i = 0; i < 4; i++) {
- status = qla4_83xx_rd_reg_indirect(ha,
+ qla4_83xx_rd_reg_indirect(ha,
QLA83XX_PORT0_RXB_TC_MAX_CELL + (i * 0x4), &val);
DEBUG2(pr_info("0x%x ", val));
}
@@ -1448,7 +1447,7 @@
DEBUG2(ql4_printk(KERN_INFO, ha,
"Port 1 RxB Traffic Class Max Cell Registers[3..0]:"));
for (i = 0; i < 4; i++) {
- status = qla4_83xx_rd_reg_indirect(ha,
+ qla4_83xx_rd_reg_indirect(ha,
QLA83XX_PORT1_RXB_TC_MAX_CELL + (i * 0x4), &val);
DEBUG2(pr_info("0x%x ", val));
}
@@ -1459,15 +1458,11 @@
DEBUG2(ql4_printk(KERN_INFO, ha,
"Port 0 RxB Rx Traffic Class Stats [TC7..TC0]"));
for (i = 7; i >= 0; i--) {
- status = qla4_83xx_rd_reg_indirect(ha,
- QLA83XX_PORT0_RXB_TC_STATS,
- &val);
+ qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT0_RXB_TC_STATS, &val);
val &= ~(0x7 << 29); /* Reset bits 29 to 31 */
qla4_83xx_wr_reg_indirect(ha, QLA83XX_PORT0_RXB_TC_STATS,
(val | (i << 29)));
- status = qla4_83xx_rd_reg_indirect(ha,
- QLA83XX_PORT0_RXB_TC_STATS,
- &val);
+ qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT0_RXB_TC_STATS, &val);
DEBUG2(pr_info("0x%x ", val));
}
@@ -1477,24 +1472,18 @@
DEBUG2(ql4_printk(KERN_INFO, ha,
"Port 1 RxB Rx Traffic Class Stats [TC7..TC0]"));
for (i = 7; i >= 0; i--) {
- status = qla4_83xx_rd_reg_indirect(ha,
- QLA83XX_PORT1_RXB_TC_STATS,
- &val);
+ qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT1_RXB_TC_STATS, &val);
val &= ~(0x7 << 29); /* Reset bits 29 to 31 */
qla4_83xx_wr_reg_indirect(ha, QLA83XX_PORT1_RXB_TC_STATS,
(val | (i << 29)));
- status = qla4_83xx_rd_reg_indirect(ha,
- QLA83XX_PORT1_RXB_TC_STATS,
- &val);
+ qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT1_RXB_TC_STATS, &val);
DEBUG2(pr_info("0x%x ", val));
}
DEBUG2(pr_info("\n"));
- status = qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT2_IFB_PAUSE_THRS,
- &val);
- status = qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT3_IFB_PAUSE_THRS,
- &val1);
+ qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT2_IFB_PAUSE_THRS, &val);
+ qla4_83xx_rd_reg_indirect(ha, QLA83XX_PORT3_IFB_PAUSE_THRS, &val1);
DEBUG2(ql4_printk(KERN_INFO, ha,
"IFB-Pause Thresholds: Port 2:0x%x, Port 3:0x%x\n",
diff --git a/drivers/scsi/qla4xxx/ql4_83xx.h b/drivers/scsi/qla4xxx/ql4_83xx.h
index 775fdf9..f10167c 100644
--- a/drivers/scsi/qla4xxx/ql4_83xx.h
+++ b/drivers/scsi/qla4xxx/ql4_83xx.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#ifndef __QL483XX_H
@@ -87,23 +86,6 @@
#define QLA83XX_FW_API 0x356C
#define QLA83XX_DRV_OP_MODE 0x3570
-static const uint32_t qla4_83xx_reg_tbl[] = {
- QLA83XX_PEG_HALT_STATUS1,
- QLA83XX_PEG_HALT_STATUS2,
- QLA83XX_PEG_ALIVE_COUNTER,
- QLA83XX_CRB_DRV_ACTIVE,
- QLA83XX_CRB_DEV_STATE,
- QLA83XX_CRB_DRV_STATE,
- QLA83XX_CRB_DRV_SCRATCH,
- QLA83XX_CRB_DEV_PART_INFO1,
- QLA83XX_CRB_IDC_VER_MAJOR,
- QLA83XX_FW_VER_MAJOR,
- QLA83XX_FW_VER_MINOR,
- QLA83XX_FW_VER_SUB,
- QLA83XX_CMDPEG_STATE,
- QLA83XX_ASIC_TEMP,
-};
-
#define QLA83XX_CRB_WIN_BASE 0x3800
#define QLA83XX_CRB_WIN_FUNC(f) (QLA83XX_CRB_WIN_BASE+((f)*4))
#define QLA83XX_SEM_LOCK_BASE 0x3840
diff --git a/drivers/scsi/qla4xxx/ql4_attr.c b/drivers/scsi/qla4xxx/ql4_attr.c
index 463239c..ec43528 100644
--- a/drivers/scsi/qla4xxx/ql4_attr.c
+++ b/drivers/scsi/qla4xxx/ql4_attr.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#include "ql4_def.h"
diff --git a/drivers/scsi/qla4xxx/ql4_bsg.c b/drivers/scsi/qla4xxx/ql4_bsg.c
index 415ee5e..c447a9d 100644
--- a/drivers/scsi/qla4xxx/ql4_bsg.c
+++ b/drivers/scsi/qla4xxx/ql4_bsg.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2011-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#include "ql4_def.h"
@@ -805,7 +804,7 @@
/**
* qla4xxx_process_vendor_specific - handle vendor specific bsg request
- * @job: iscsi_bsg_job to handle
+ * @bsg_job: iscsi_bsg_job to handle
**/
int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job)
{
@@ -852,7 +851,7 @@
/**
* qla4xxx_bsg_request - handle bsg request from ISCSI transport
- * @job: iscsi_bsg_job to handle
+ * @bsg_job: iscsi_bsg_job to handle
*/
int qla4xxx_bsg_request(struct bsg_job *bsg_job)
{
diff --git a/drivers/scsi/qla4xxx/ql4_bsg.h b/drivers/scsi/qla4xxx/ql4_bsg.h
index 88c2401..06db385 100644
--- a/drivers/scsi/qla4xxx/ql4_bsg.h
+++ b/drivers/scsi/qla4xxx/ql4_bsg.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2011 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#ifndef __QL4_BSG_H
#define __QL4_BSG_H
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.c b/drivers/scsi/qla4xxx/ql4_dbg.c
index 5649e9e..f43e675 100644
--- a/drivers/scsi/qla4xxx/ql4_dbg.c
+++ b/drivers/scsi/qla4xxx/ql4_dbg.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2012 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#include "ql4_def.h"
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.h b/drivers/scsi/qla4xxx/ql4_dbg.h
index 51c365b..171c891 100644
--- a/drivers/scsi/qla4xxx/ql4_dbg.h
+++ b/drivers/scsi/qla4xxx/ql4_dbg.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2012 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
/*
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 817f312..f5b382e 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#ifndef __QL4_DEF_H
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 699575e..b914246 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#ifndef _QLA4X_FW_H
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index bce96a5..b8f0221 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#ifndef __QLA4x_GBL_H
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 2bf5e3e..f786ac2 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#include <scsi/iscsi_if.h>
@@ -14,7 +13,6 @@
static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
{
uint32_t value;
- uint8_t func_number;
unsigned long flags;
/* Get the function number */
@@ -22,7 +20,6 @@
value = readw(&ha->reg->ctrl_status);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- func_number = (uint8_t) ((value >> 4) & 0x30);
switch (value & ISP_CONTROL_FN_MASK) {
case ISP_CONTROL_FN0_SCSI:
ha->mac_index = 1;
@@ -667,6 +664,9 @@
pci_set_master(ha->pdev);
status = pci_set_mwi(ha->pdev);
+ if (status)
+ ql4_printk(KERN_WARNING, ha, "Failed to set MWI\n");
+
/*
* We want to respect framework's setting of PCI configuration space
* command register and also want to make sure that all bits of
@@ -945,6 +945,7 @@
/**
* qla4xxx_initialize_adapter - initiailizes hba
* @ha: Pointer to host adapter structure.
+ * @is_reset: Is this init path or reset path
*
* This routine parforms all of the steps necessary to initialize the adapter.
*
@@ -1156,9 +1157,10 @@
/**
* qla4xxx_process_ddb_changed - process ddb state change
- * @ha - Pointer to host adapter structure.
- * @fw_ddb_index - Firmware's device database index
- * @state - Device state
+ * @ha: Pointer to host adapter structure.
+ * @fw_ddb_index: Firmware's device database index
+ * @state: Device state
+ * @conn_err: Unused
*
* This routine processes a Decive Database Changed AEN Event.
**/
@@ -1167,7 +1169,6 @@
uint32_t state, uint32_t conn_err)
{
struct ddb_entry *ddb_entry;
- int status = QLA_ERROR;
/* check for out of range index */
if (fw_ddb_index >= MAX_DDB_ENTRIES)
@@ -1189,7 +1190,7 @@
ddb_entry->ddb_change(ha, fw_ddb_index, ddb_entry, state);
exit_ddb_event:
- return status;
+ return QLA_ERROR;
}
/**
diff --git a/drivers/scsi/qla4xxx/ql4_inline.h b/drivers/scsi/qla4xxx/ql4_inline.h
index 655b7bb..9ced6b3 100644
--- a/drivers/scsi/qla4xxx/ql4_inline.h
+++ b/drivers/scsi/qla4xxx/ql4_inline.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
/*
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
index 17222eb..cbd1e6f 100644
--- a/drivers/scsi/qla4xxx/ql4_iocb.c
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#include "ql4_def.h"
@@ -78,7 +77,7 @@
* @ha: Pointer to host adapter structure.
* @ddb_entry: Pointer to device database entry
* @lun: SCSI LUN
- * @marker_type: marker identifier
+ * @mrkr_mod: marker identifier
*
* This routine issues a marker IOCB.
**/
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index d2cd33d..a51910a 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#include "ql4_def.h"
@@ -582,7 +581,7 @@
/**
* qla4_83xx_loopback_in_progress: Is loopback in progress?
* @ha: Pointer to host adapter structure.
- * @ret: 1 = loopback in progress, 0 = loopback not in progress
+ * returns: 1 = loopback in progress, 0 = loopback not in progress
**/
static int qla4_83xx_loopback_in_progress(struct scsi_qla_host *ha)
{
@@ -651,7 +650,7 @@
/**
* qla4xxx_isr_decode_mailbox - decodes mailbox status
* @ha: Pointer to host adapter structure.
- * @mailbox_status: Mailbox status.
+ * @mbox_status: Mailbox status.
*
* This routine decodes the mailbox status during the ISR.
* Hardware_lock locked upon entry. runs in interrupt context.
@@ -1044,6 +1043,7 @@
/**
* qla4_82xx_interrupt_service_routine - isr
* @ha: pointer to host adapter structure.
+ * @intr_status: Local interrupt status/type.
*
* This is the main interrupt service routine.
* hardware_lock locked upon entry. runs in interrupt context.
@@ -1069,6 +1069,7 @@
/**
* qla4xxx_interrupt_service_routine - isr
* @ha: pointer to host adapter structure.
+ * @intr_status: Local interrupt status/type.
*
* This is the main interrupt service routine.
* hardware_lock locked upon entry. runs in interrupt context.
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index 02636b4..17b719a 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#include <linux/ctype.h>
@@ -47,7 +46,7 @@
/**
* qla4xxx_is_intr_poll_mode – Are we allowed to poll for interrupts?
* @ha: Pointer to host adapter structure.
- * @ret: 1=polling mode, 0=non-polling mode
+ * returns: 1=polling mode, 0=non-polling mode
**/
static int qla4xxx_is_intr_poll_mode(struct scsi_qla_host *ha)
{
@@ -810,7 +809,7 @@
return QLA_SUCCESS;
}
-/**
+/*
* qla4xxx_get_fwddb_entry - retrieves firmware ddb entry
* @ha: Pointer to host adapter structure.
* @fw_ddb_index: Firmware's device database index
@@ -1259,8 +1258,7 @@
/**
* qla4xxx_reset_target - issues target Reset
* @ha: Pointer to host adapter structure.
- * @db_entry: Pointer to device database entry
- * @un_entry: Pointer to lun entry structure
+ * @ddb_entry: Pointer to device database entry
*
* This routine performs a TARGET RESET on the specified target.
* The caller must ensure that the ddb_entry pointers
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c
index 3bf418f..f08a5ab 100644
--- a/drivers/scsi/qla4xxx/ql4_nvram.c
+++ b/drivers/scsi/qla4xxx/ql4_nvram.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#include "ql4_def.h"
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.h b/drivers/scsi/qla4xxx/ql4_nvram.h
index e97d79f..b96c06f 100644
--- a/drivers/scsi/qla4xxx/ql4_nvram.h
+++ b/drivers/scsi/qla4xxx/ql4_nvram.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#ifndef _QL4XNVRM_H_
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index 5a31877..f1767b2 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#include <linux/delay.h>
#include <linux/io.h>
@@ -974,10 +973,10 @@
return ret;
}
-/**
+/*
* This routine does CRB initialize sequence
* to put the ISP into operational state
- **/
+ */
static int
qla4_82xx_pinit_from_rom(struct scsi_qla_host *ha, int verbose)
{
@@ -2645,7 +2644,7 @@
uint32_t addr1, addr2, value, data, temp, wrval;
uint8_t stride, stride2;
uint16_t count;
- uint32_t poll, mask, data_size, modify_mask;
+ uint32_t poll, mask, modify_mask;
uint32_t wait_count = 0;
uint32_t *data_ptr = *d_ptr;
struct qla8044_minidump_entry_rddfe *rddfe;
@@ -2661,7 +2660,6 @@
poll = le32_to_cpu(rddfe->poll);
mask = le32_to_cpu(rddfe->mask);
modify_mask = le32_to_cpu(rddfe->modify_mask);
- data_size = le32_to_cpu(rddfe->data_size);
addr2 = addr1 + stride;
@@ -2742,7 +2740,7 @@
uint8_t stride1, stride2;
uint32_t addr3, addr4, addr5, addr6, addr7;
uint16_t count, loop_cnt;
- uint32_t poll, mask;
+ uint32_t mask;
uint32_t *data_ptr = *d_ptr;
struct qla8044_minidump_entry_rdmdio *rdmdio;
@@ -2754,7 +2752,6 @@
stride2 = le32_to_cpu(rdmdio->stride_2);
count = le32_to_cpu(rdmdio->count);
- poll = le32_to_cpu(rdmdio->poll);
mask = le32_to_cpu(rdmdio->mask);
value2 = le32_to_cpu(rdmdio->value_2);
@@ -2813,7 +2810,7 @@
struct qla8xxx_minidump_entry_hdr *entry_hdr,
uint32_t **d_ptr)
{
- uint32_t addr1, addr2, value1, value2, poll, mask, r_value;
+ uint32_t addr1, addr2, value1, value2, poll, r_value;
struct qla8044_minidump_entry_pollwr *pollwr_hdr;
uint32_t wait_count = 0;
uint32_t rval = QLA_SUCCESS;
@@ -2825,7 +2822,6 @@
value2 = le32_to_cpu(pollwr_hdr->value_2);
poll = le32_to_cpu(pollwr_hdr->poll);
- mask = le32_to_cpu(pollwr_hdr->mask);
while (wait_count < poll) {
ha->isp_ops->rd_reg_indirect(ha, addr1, &r_value);
@@ -3220,6 +3216,7 @@
/**
* qla4_8xxx_uevent_emit - Send uevent when the firmware dump is ready.
* @ha: pointer to adapter structure
+ * @code: uevent code to act upon
**/
static void qla4_8xxx_uevent_emit(struct scsi_qla_host *ha, u32 code)
{
@@ -3228,7 +3225,7 @@
switch (code) {
case QL4_UEVENT_CODE_FW_DUMP:
- snprintf(event_string, sizeof(event_string), "FW_DUMP=%ld",
+ snprintf(event_string, sizeof(event_string), "FW_DUMP=%lu",
ha->host_no);
break;
default:
@@ -3688,9 +3685,9 @@
return dwptr;
}
-/**
+/*
* Address and length are byte address
- **/
+ */
static uint8_t *
qla4_82xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf,
uint32_t offset, uint32_t length)
diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h
index 98fe786..52a5209 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.h
+++ b/drivers/scsi/qla4xxx/ql4_nx.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#ifndef __QLA_NX_H
#define __QLA_NX_H
@@ -599,23 +598,6 @@
QLA8XXX_CRB_TEMP_STATE,
};
-static const uint32_t qla4_82xx_reg_tbl[] = {
- QLA82XX_PEG_HALT_STATUS1,
- QLA82XX_PEG_HALT_STATUS2,
- QLA82XX_PEG_ALIVE_COUNTER,
- QLA82XX_CRB_DRV_ACTIVE,
- QLA82XX_CRB_DEV_STATE,
- QLA82XX_CRB_DRV_STATE,
- QLA82XX_CRB_DRV_SCRATCH,
- QLA82XX_CRB_DEV_PART_INFO,
- QLA82XX_CRB_DRV_IDC_VERSION,
- QLA82XX_FW_VERSION_MAJOR,
- QLA82XX_FW_VERSION_MINOR,
- QLA82XX_FW_VERSION_SUB,
- CRB_CMDPEG_STATE,
- CRB_TEMP_STATE,
-};
-
/* Every driver should use these Device State */
#define QLA8XXX_DEV_COLD 1
#define QLA8XXX_DEV_INITIALIZING 2
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index df43cf6..2c23b69 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#include <linux/moduleparam.h>
#include <linux/slab.h>
@@ -188,6 +187,40 @@
static struct qla4_8xxx_legacy_intr_set legacy_intr[] =
QLA82XX_LEGACY_INTR_CONFIG;
+static const uint32_t qla4_82xx_reg_tbl[] = {
+ QLA82XX_PEG_HALT_STATUS1,
+ QLA82XX_PEG_HALT_STATUS2,
+ QLA82XX_PEG_ALIVE_COUNTER,
+ QLA82XX_CRB_DRV_ACTIVE,
+ QLA82XX_CRB_DEV_STATE,
+ QLA82XX_CRB_DRV_STATE,
+ QLA82XX_CRB_DRV_SCRATCH,
+ QLA82XX_CRB_DEV_PART_INFO,
+ QLA82XX_CRB_DRV_IDC_VERSION,
+ QLA82XX_FW_VERSION_MAJOR,
+ QLA82XX_FW_VERSION_MINOR,
+ QLA82XX_FW_VERSION_SUB,
+ CRB_CMDPEG_STATE,
+ CRB_TEMP_STATE,
+};
+
+static const uint32_t qla4_83xx_reg_tbl[] = {
+ QLA83XX_PEG_HALT_STATUS1,
+ QLA83XX_PEG_HALT_STATUS2,
+ QLA83XX_PEG_ALIVE_COUNTER,
+ QLA83XX_CRB_DRV_ACTIVE,
+ QLA83XX_CRB_DEV_STATE,
+ QLA83XX_CRB_DRV_STATE,
+ QLA83XX_CRB_DRV_SCRATCH,
+ QLA83XX_CRB_DEV_PART_INFO1,
+ QLA83XX_CRB_IDC_VER_MAJOR,
+ QLA83XX_FW_VER_MAJOR,
+ QLA83XX_FW_VER_MINOR,
+ QLA83XX_FW_VER_SUB,
+ QLA83XX_CMDPEG_STATE,
+ QLA83XX_ASIC_TEMP,
+};
+
static struct scsi_host_template qla4xxx_driver_template = {
.module = THIS_MODULE,
.name = DRIVER_NAME,
@@ -966,7 +999,7 @@
"%s: No such sysfs attribute\n", __func__);
rc = -ENOSYS;
goto exit_set_chap;
- };
+ }
}
if (chap_rec.chap_type == CHAP_TYPE_IN)
@@ -1845,12 +1878,10 @@
static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc)
{
struct iscsi_cls_session *session;
- struct iscsi_session *sess;
unsigned long flags;
enum blk_eh_timer_return ret = BLK_EH_DONE;
session = starget_to_session(scsi_target(sc->device));
- sess = session->dd_data;
spin_lock_irqsave(&session->lock, flags);
if (session->state == ISCSI_SESSION_FAILED)
@@ -2875,7 +2906,7 @@
chap_tbl.secret_len);
}
}
- /* fall through */
+ fallthrough;
default:
return iscsi_session_get_param(cls_sess, param, buf);
}
@@ -3059,7 +3090,6 @@
struct ddb_entry *ddb_entry;
uint16_t ddb_index;
struct iscsi_session *sess;
- struct sockaddr *dst_addr;
int ret;
if (!ep) {
@@ -3068,7 +3098,6 @@
}
qla_ep = ep->dd_data;
- dst_addr = (struct sockaddr *)&qla_ep->dst_addr;
ha = to_qla_host(qla_ep->host);
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: host: %ld\n", __func__,
ha->host_no));
@@ -4515,7 +4544,7 @@
/**
* qla4xxx_timer - checks every second for work to do.
- * @ha: Pointer to host adapter structure.
+ * @t: Context to obtain pointer to host adapter structure.
**/
static void qla4xxx_timer(struct timer_list *t)
{
@@ -5269,7 +5298,7 @@
/**
* qla4xxx_do_dpc - dpc routine
- * @data: in our case pointer to adapter structure
+ * @work: Context to obtain pointer to host adapter structure.
*
* This routine is a task that is schedule by the interrupt handler
* to perform the background processing for interrupts. We put it
@@ -5492,7 +5521,7 @@
int qla4_8xxx_iospace_config(struct scsi_qla_host *ha)
{
int status = 0;
- unsigned long mem_base, mem_len, db_base, db_len;
+ unsigned long mem_base, mem_len;
struct pci_dev *pdev = ha->pdev;
status = pci_request_regions(pdev, DRIVER_NAME);
@@ -5536,9 +5565,6 @@
((uint8_t *)ha->nx_pcibase);
}
- db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */
- db_len = pci_resource_len(pdev, 4);
-
return 0;
iospace_error_exit:
return -ENOMEM;
@@ -6249,14 +6275,12 @@
static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry,
struct ql4_tuple_ddb *tddb)
{
- struct scsi_qla_host *ha;
struct iscsi_cls_session *cls_sess;
struct iscsi_cls_conn *cls_conn;
struct iscsi_session *sess;
struct iscsi_conn *conn;
DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));
- ha = ddb_entry->ha;
cls_sess = ddb_entry->sess;
sess = cls_sess->dd_data;
cls_conn = ddb_entry->conn;
@@ -8591,7 +8615,7 @@
/**
* qla4xxx_probe_adapter - callback function to probe HBA
* @pdev: pointer to pci_dev structure
- * @pci_device_id: pointer to pci_device entry
+ * @ent: pointer to pci_device entry
*
* This routine will probe for Qlogic 4xxx iSCSI host adapters.
* It returns zero if successful. It also initializes all data necessary for
@@ -8977,7 +9001,7 @@
}
/**
* qla4xxx_remove_adapter - callback function to remove adapter.
- * @pci_dev: PCI device pointer
+ * @pdev: PCI device pointer
**/
static void qla4xxx_remove_adapter(struct pci_dev *pdev)
{
@@ -9144,8 +9168,8 @@
/**
* qla4xxx_eh_wait_for_commands - wait for active cmds to finish.
* @ha: pointer to HBA
- * @t: target id
- * @l: lun id
+ * @stgt: pointer to SCSI target
+ * @sdev: pointer to SCSI device
*
* This function waits for all outstanding commands to a lun to complete. It
* returns 0 if all pending commands are returned and 1 otherwise.
@@ -9615,6 +9639,7 @@
* qla4xxx_pci_mmio_enabled() gets called if
* qla4xxx_pci_error_detected() returns PCI_ERS_RESULT_CAN_RECOVER
* and read/write to the device still works.
+ * @pdev: PCI device pointer
**/
static pci_ers_result_t
qla4xxx_pci_mmio_enabled(struct pci_dev *pdev)
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index f11eaa7..fb1c142 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* QLogic iSCSI HBA Driver
* Copyright (c) 2003-2013 QLogic Corporation
- *
- * See LICENSE.qla4xxx for copyright and licensing details.
*/
#define QLA4XXX_DRIVER_VERSION "5.04.00-k6"
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index d539bee..d84e218 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -30,6 +30,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/firmware.h>
+#include <linux/pgtable.h>
#include <asm/byteorder.h>
@@ -37,7 +38,6 @@
#include <asm/dma.h>
#include <asm/ptrace.h>
-#include <asm/pgtable.h>
#include <asm/oplib.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -200,15 +200,15 @@
/* Write mailbox command registers. */
switch (mbox_param[param[0]] >> 4) {
case 6: sbus_writew(param[5], qpti->qregs + MBOX5);
- /* Fall through */
+ fallthrough;
case 5: sbus_writew(param[4], qpti->qregs + MBOX4);
- /* Fall through */
+ fallthrough;
case 4: sbus_writew(param[3], qpti->qregs + MBOX3);
- /* Fall through */
+ fallthrough;
case 3: sbus_writew(param[2], qpti->qregs + MBOX2);
- /* Fall through */
+ fallthrough;
case 2: sbus_writew(param[1], qpti->qregs + MBOX1);
- /* Fall through */
+ fallthrough;
case 1: sbus_writew(param[0], qpti->qregs + MBOX0);
}
@@ -259,15 +259,15 @@
/* Read back output parameters. */
switch (mbox_param[param[0]] & 0xf) {
case 6: param[5] = sbus_readw(qpti->qregs + MBOX5);
- /* Fall through */
+ fallthrough;
case 5: param[4] = sbus_readw(qpti->qregs + MBOX4);
- /* Fall through */
+ fallthrough;
case 4: param[3] = sbus_readw(qpti->qregs + MBOX3);
- /* Fall through */
+ fallthrough;
case 3: param[2] = sbus_readw(qpti->qregs + MBOX2);
- /* Fall through */
+ fallthrough;
case 2: param[1] = sbus_readw(qpti->qregs + MBOX1);
- /* Fall through */
+ fallthrough;
case 1: param[0] = sbus_readw(qpti->qregs + MBOX0);
}
@@ -1468,22 +1468,10 @@
.probe = qpti_sbus_probe,
.remove = qpti_sbus_remove,
};
-
-static int __init qpti_init(void)
-{
- return platform_driver_register(&qpti_sbus_driver);
-}
-
-static void __exit qpti_exit(void)
-{
- platform_driver_unregister(&qpti_sbus_driver);
-}
+module_platform_driver(qpti_sbus_driver);
MODULE_DESCRIPTION("QlogicISP SBUS driver");
MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
MODULE_LICENSE("GPL");
MODULE_VERSION("2.1");
MODULE_FIRMWARE("qlogic/isp1000.bin");
-
-module_init(qpti_init);
-module_exit(qpti_exit);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 1f5b5c8..6ad834d 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -94,20 +94,6 @@
ASYNC_DOMAIN_EXCLUSIVE(scsi_sd_pm_domain);
EXPORT_SYMBOL(scsi_sd_pm_domain);
-/**
- * scsi_put_command - Free a scsi command block
- * @cmd: command block to free
- *
- * Returns: Nothing.
- *
- * Notes: The command must not belong to any lists.
- */
-void scsi_put_command(struct scsi_cmnd *cmd)
-{
- scsi_del_cmd_from_list(cmd);
- BUG_ON(delayed_work_pending(&cmd->abort_work));
-}
-
#ifdef CONFIG_SCSI_LOGGING
void scsi_log_send(struct scsi_cmnd *cmd)
{
@@ -186,7 +172,7 @@
struct scsi_driver *drv;
unsigned int good_bytes;
- scsi_device_unbusy(sdev);
+ scsi_device_unbusy(sdev, cmd);
/*
* Clear the flags that say that the device/target/host is no longer
@@ -434,8 +420,8 @@
return;
mutex_lock(&sdev->inquiry_mutex);
- rcu_swap_protected(*sdev_vpd_buf, vpd_buf,
- lockdep_is_held(&sdev->inquiry_mutex));
+ vpd_buf = rcu_replace_pointer(*sdev_vpd_buf, vpd_buf,
+ lockdep_is_held(&sdev->inquiry_mutex));
mutex_unlock(&sdev->inquiry_mutex);
if (vpd_buf)
@@ -465,10 +451,14 @@
return;
for (i = 4; i < vpd_buf->len; i++) {
+ if (vpd_buf->data[i] == 0x0)
+ scsi_update_vpd_page(sdev, 0x0, &sdev->vpd_pg0);
if (vpd_buf->data[i] == 0x80)
scsi_update_vpd_page(sdev, 0x80, &sdev->vpd_pg80);
if (vpd_buf->data[i] == 0x83)
scsi_update_vpd_page(sdev, 0x83, &sdev->vpd_pg83);
+ if (vpd_buf->data[i] == 0x89)
+ scsi_update_vpd_page(sdev, 0x89, &sdev->vpd_pg89);
}
kfree(vpd_buf);
}
@@ -555,8 +545,10 @@
*/
void scsi_device_put(struct scsi_device *sdev)
{
- module_put(sdev->host->hostt->module);
+ struct module *mod = sdev->host->hostt->module;
+
put_device(&sdev->sdev_gendev);
+ module_put(mod);
}
EXPORT_SYMBOL(scsi_device_put);
@@ -760,17 +752,10 @@
module_param(scsi_logging_level, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(scsi_logging_level, "a bit mask of logging levels");
-/* This should go away in the future, it doesn't do anything anymore */
-bool scsi_use_blk_mq = true;
-module_param_named(use_blk_mq, scsi_use_blk_mq, bool, S_IWUSR | S_IRUGO);
-
static int __init init_scsi(void)
{
int error;
- error = scsi_init_queue();
- if (error)
- return error;
error = scsi_init_procfs();
if (error)
goto cleanup_queue;
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 44181a2..6b00de6 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -7,9 +7,9 @@
* anything out of the ordinary is seen.
* ^^^^^^^^^^^^^^^^^^^^^^^ Original ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*
- * Copyright (C) 2001 - 2018 Douglas Gilbert
+ * Copyright (C) 2001 - 2020 Douglas Gilbert
*
- * For documentation see http://sg.danny.cz/sg/sdebug26.html
+ * For documentation see http://sg.danny.cz/sg/scsi_debug.html
*/
@@ -38,6 +38,10 @@
#include <linux/hrtimer.h>
#include <linux/uuid.h>
#include <linux/t10-pi.h>
+#include <linux/msdos_partition.h>
+#include <linux/random.h>
+#include <linux/xarray.h>
+#include <linux/prefetch.h>
#include <net/checksum.h>
@@ -56,8 +60,8 @@
#include "scsi_logging.h"
/* make sure inq_product_rev string corresponds to this version */
-#define SDEBUG_VERSION "0188" /* format to fit INQUIRY revision field */
-static const char *sdebug_version_date = "20190125";
+#define SDEBUG_VERSION "0190" /* format to fit INQUIRY revision field */
+static const char *sdebug_version_date = "20200710";
#define MY_NAME "scsi_debug"
@@ -90,6 +94,11 @@
#define MICROCODE_CHANGED_ASCQ 0x1 /* with TARGET_CHANGED_ASC */
#define MICROCODE_CHANGED_WO_RESET_ASCQ 0x16
#define WRITE_ERROR_ASC 0xc
+#define UNALIGNED_WRITE_ASCQ 0x4
+#define WRITE_BOUNDARY_ASCQ 0x5
+#define READ_INVDATA_ASCQ 0x6
+#define READ_BOUNDARY_ASCQ 0x7
+#define INSUFF_ZONE_ASCQ 0xe
/* Additional Sense Code Qualifier (ASCQ) */
#define ACK_NAK_TO 0x3
@@ -104,9 +113,12 @@
#define DEF_ATO 1
#define DEF_CDB_LEN 10
#define DEF_JDELAY 1 /* if > 0 unit is a jiffy */
+#define DEF_DEV_SIZE_PRE_INIT 0
#define DEF_DEV_SIZE_MB 8
+#define DEF_ZBC_DEV_SIZE_MB 128
#define DEF_DIF 0
#define DEF_DIX 0
+#define DEF_PER_HOST_STORE false
#define DEF_D_SENSE 0
#define DEF_EVERY_NTH 0
#define DEF_FAKE_RW 0
@@ -125,6 +137,7 @@
#define DEF_PHYSBLK_EXP 0
#define DEF_OPT_XFERLEN_EXP 0
#define DEF_PTYPE TYPE_DISK
+#define DEF_RANDOM false
#define DEF_REMOVABLE false
#define DEF_SCSI_LEVEL 7 /* INQUIRY, byte2 [6->SPC-4; 7->SPC-5] */
#define DEF_SECTOR_SIZE 512
@@ -138,9 +151,15 @@
#define DEF_STRICT 0
#define DEF_STATISTICS false
#define DEF_SUBMIT_QUEUES 1
+#define DEF_TUR_MS_TO_READY 0
#define DEF_UUID_CTL 0
#define JDELAY_OVERRIDDEN -9999
+/* Default parameters for ZBC drives */
+#define DEF_ZBC_ZONE_SIZE_MB 128
+#define DEF_ZBC_MAX_OPEN_ZONES 8
+#define DEF_ZBC_NR_CONV_ZONES 1
+
#define SDEBUG_LUN_0_VAL 0
/* bit mask values for sdebug_opts */
@@ -169,21 +188,8 @@
SDEBUG_OPT_SHORT_TRANSFER | \
SDEBUG_OPT_HOST_BUSY | \
SDEBUG_OPT_CMD_ABORT)
-/* When "every_nth" > 0 then modulo "every_nth" commands:
- * - a missing response is simulated if SDEBUG_OPT_TIMEOUT is set
- * - a RECOVERED_ERROR is simulated on successful read and write
- * commands if SDEBUG_OPT_RECOVERED_ERR is set.
- * - a TRANSPORT_ERROR is simulated on successful read and write
- * commands if SDEBUG_OPT_TRANSPORT_ERR is set.
- * - similarly for DIF_ERR, DIX_ERR, SHORT_TRANSFER, HOST_BUSY and
- * CMD_ABORT
- *
- * When "every_nth" < 0 then after "- every_nth" commands the selected
- * error will be injected. The error will be injected on every subsequent
- * command until some other action occurs; for example, the user writing
- * a new value (other than -1 or 1) to every_nth:
- * echo 0 > /sys/bus/pseudo/drivers/scsi_debug/every_nth
- */
+#define SDEBUG_OPT_RECOV_DIF_DIX (SDEBUG_OPT_RECOVERED_ERR | \
+ SDEBUG_OPT_DIF_ERR | SDEBUG_OPT_DIX_ERR)
/* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs) are returned in
* priority order. In the subset implemented here lower numbers have higher
@@ -203,10 +209,6 @@
#define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */
#define OPT_MEDIUM_ERR_NUM 10 /* number of consecutive medium errs */
-/* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1)
- * or "peripheral device" addressing (value 0) */
-#define SAM2_LUN_ADDRESS_METHOD 0
-
/* SDEBUG_CANQUEUE is the maximum number of commands that can be queued
* (for response) per submit queue at one time. Can be reduced by max_queue
* option. Command responses are not queued when jdelay=0 and ndelay=0. The
@@ -218,21 +220,23 @@
#define SDEBUG_CANQUEUE (SDEBUG_CANQUEUE_WORDS * BITS_PER_LONG)
#define DEF_CMD_PER_LUN 255
-#define F_D_IN 1
-#define F_D_OUT 2
+/* UA - Unit Attention; SA - Service Action; SSU - Start Stop Unit */
+#define F_D_IN 1 /* Data-in command (e.g. READ) */
+#define F_D_OUT 2 /* Data-out command (e.g. WRITE) */
#define F_D_OUT_MAYBE 4 /* WRITE SAME, NDOB bit */
#define F_D_UNKN 8
-#define F_RL_WLUN_OK 0x10
-#define F_SKIP_UA 0x20
-#define F_DELAY_OVERR 0x40
-#define F_SA_LOW 0x80 /* cdb byte 1, bits 4 to 0 */
-#define F_SA_HIGH 0x100 /* as used by variable length cdbs */
-#define F_INV_OP 0x200
-#define F_FAKE_RW 0x400
-#define F_M_ACCESS 0x800 /* media access */
-#define F_SSU_DELAY 0x1000
-#define F_SYNC_DELAY 0x2000
+#define F_RL_WLUN_OK 0x10 /* allowed with REPORT LUNS W-LUN */
+#define F_SKIP_UA 0x20 /* bypass UAs (e.g. INQUIRY command) */
+#define F_DELAY_OVERR 0x40 /* for commands like INQUIRY */
+#define F_SA_LOW 0x80 /* SA is in cdb byte 1, bits 4 to 0 */
+#define F_SA_HIGH 0x100 /* SA is in cdb bytes 8 and 9 */
+#define F_INV_OP 0x200 /* invalid opcode (not supported) */
+#define F_FAKE_RW 0x400 /* bypass resp_*() when fake_rw set */
+#define F_M_ACCESS 0x800 /* media access, reacts to SSU state */
+#define F_SSU_DELAY 0x1000 /* SSU command delay (long-ish) */
+#define F_SYNC_DELAY 0x2000 /* SYNCHRONIZE CACHE delay */
+/* Useful combinations of the above flags */
#define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR)
#define FF_MEDIA_IO (F_M_ACCESS | F_FAKE_RW)
#define FF_SA (F_SA_HIGH | F_SA_LOW)
@@ -242,6 +246,35 @@
#define SDEBUG_MAX_CMD_LEN 32
+#define SDEB_XA_NOT_IN_USE XA_MARK_1
+
+/* Zone types (zbcr05 table 25) */
+enum sdebug_z_type {
+ ZBC_ZONE_TYPE_CNV = 0x1,
+ ZBC_ZONE_TYPE_SWR = 0x2,
+ ZBC_ZONE_TYPE_SWP = 0x3,
+};
+
+/* enumeration names taken from table 26, zbcr05 */
+enum sdebug_z_cond {
+ ZBC_NOT_WRITE_POINTER = 0x0,
+ ZC1_EMPTY = 0x1,
+ ZC2_IMPLICIT_OPEN = 0x2,
+ ZC3_EXPLICIT_OPEN = 0x3,
+ ZC4_CLOSED = 0x4,
+ ZC6_READ_ONLY = 0xd,
+ ZC5_FULL = 0xe,
+ ZC7_OFFLINE = 0xf,
+};
+
+struct sdeb_zone_state { /* ZBC: per zone state */
+ enum sdebug_z_type z_type;
+ enum sdebug_z_cond z_cond;
+ bool z_non_seq_resource;
+ unsigned int z_size;
+ sector_t z_start;
+ sector_t z_wp;
+};
struct sdebug_dev_info {
struct list_head dev_list;
@@ -252,17 +285,39 @@
struct sdebug_host_info *sdbg_host;
unsigned long uas_bm[1];
atomic_t num_in_q;
- atomic_t stopped;
+ atomic_t stopped; /* 1: by SSU, 2: device start */
bool used;
+
+ /* For ZBC devices */
+ enum blk_zoned_model zmodel;
+ unsigned int zsize;
+ unsigned int zsize_shift;
+ unsigned int nr_zones;
+ unsigned int nr_conv_zones;
+ unsigned int nr_imp_open;
+ unsigned int nr_exp_open;
+ unsigned int nr_closed;
+ unsigned int max_open;
+ ktime_t create_ts; /* time since bootup that this device was created */
+ struct sdeb_zone_state *zstate;
};
struct sdebug_host_info {
struct list_head host_list;
+ int si_idx; /* sdeb_store_info (per host) xarray index */
struct Scsi_Host *shost;
struct device dev;
struct list_head dev_info_list;
};
+/* There is an xarray of pointers to this struct's objects, one per host */
+struct sdeb_store_info {
+ rwlock_t macc_lck; /* for atomic media access on this store */
+ u8 *storep; /* user data storage (ram) */
+ struct t10_pi_tuple *dif_storep; /* protection info */
+ void *map_storep; /* provisioning map */
+};
+
#define to_sdebug_host(d) \
container_of(d, struct sdebug_host_info, dev)
@@ -274,6 +329,7 @@
struct execute_work ew;
int sqa_idx; /* index of sdebug_queue array */
int qc_idx; /* index of sdebug_queued_cmd array within sqa_idx */
+ int hc_idx; /* hostwide tag index */
int issuing_cpu;
bool init_hrt;
bool init_wq;
@@ -287,13 +343,6 @@
*/
struct sdebug_defer *sd_dp;
struct scsi_cmnd *a_cmnd;
- unsigned int inj_recovered:1;
- unsigned int inj_transport:1;
- unsigned int inj_dif:1;
- unsigned int inj_dix:1;
- unsigned int inj_short:1;
- unsigned int inj_host_busy:1;
- unsigned int inj_cmd_abort:1;
};
struct sdebug_queue {
@@ -307,6 +356,7 @@
static atomic_t sdebug_completions; /* count of deferred completions */
static atomic_t sdebug_miss_cpus; /* submission + completion cpus differ */
static atomic_t sdebug_a_tsf; /* 'almost task set full' counter */
+static atomic_t sdeb_inject_pending;
struct opcode_info_t {
u8 num_attached; /* 0 if this is it (i.e. a leaf); use 0xff */
@@ -338,7 +388,7 @@
SDEB_I_SERV_ACT_OUT_16 = 13, /* add ...SERV_ACT_OUT_12 if needed */
SDEB_I_MAINT_IN = 14,
SDEB_I_MAINT_OUT = 15,
- SDEB_I_VERIFY = 16, /* 10 only */
+ SDEB_I_VERIFY = 16, /* VERIFY(10), VERIFY(16) */
SDEB_I_VARIABLE_LEN = 17, /* READ(32), WRITE(32), WR_SCAT(32) */
SDEB_I_RESERVE = 18, /* 6, 10 */
SDEB_I_RELEASE = 19, /* 6, 10 */
@@ -351,7 +401,10 @@
SDEB_I_WRITE_SAME = 26, /* 10, 16 */
SDEB_I_SYNC_CACHE = 27, /* 10, 16 */
SDEB_I_COMP_WRITE = 28,
- SDEB_I_LAST_ELEMENT = 29, /* keep this last (previous + 1) */
+ SDEB_I_PRE_FETCH = 29, /* 10, 16 */
+ SDEB_I_ZONE_OUT = 30, /* 0x94+SA; includes no data xfer */
+ SDEB_I_ZONE_IN = 31, /* 0x95+SA; all have data-in */
+ SDEB_I_LAST_ELEM_P1 = 32, /* keep this last (previous + 1) */
};
@@ -367,7 +420,7 @@
/* 0x20; 0x20->0x3f: 10 byte cdbs */
0, 0, 0, 0, 0, SDEB_I_READ_CAPACITY, 0, 0,
SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, SDEB_I_VERIFY,
- 0, 0, 0, 0, 0, SDEB_I_SYNC_CACHE, 0, 0,
+ 0, 0, 0, 0, SDEB_I_PRE_FETCH, SDEB_I_SYNC_CACHE, 0, 0,
0, 0, 0, SDEB_I_WRITE_BUFFER, 0, 0, 0, 0,
/* 0x40; 0x40->0x5f: 10 byte cdbs */
0, SDEB_I_WRITE_SAME, SDEB_I_UNMAP, 0, 0, 0, 0, 0,
@@ -381,8 +434,10 @@
0, SDEB_I_VARIABLE_LEN,
/* 0x80; 0x80->0x9f: 16 byte cdbs */
0, 0, 0, 0, 0, SDEB_I_ATA_PT, 0, 0,
- SDEB_I_READ, SDEB_I_COMP_WRITE, SDEB_I_WRITE, 0, 0, 0, 0, 0,
- 0, SDEB_I_SYNC_CACHE, 0, SDEB_I_WRITE_SAME, 0, 0, 0, 0,
+ SDEB_I_READ, SDEB_I_COMP_WRITE, SDEB_I_WRITE, 0,
+ 0, 0, 0, SDEB_I_VERIFY,
+ SDEB_I_PRE_FETCH, SDEB_I_SYNC_CACHE, 0, SDEB_I_WRITE_SAME,
+ SDEB_I_ZONE_OUT, SDEB_I_ZONE_IN, 0, 0,
0, 0, 0, 0, 0, 0, SDEB_I_SERV_ACT_IN_16, SDEB_I_SERV_ACT_OUT_16,
/* 0xa0; 0xa0->0xbf: 12 byte cdbs */
SDEB_I_REPORT_LUNS, SDEB_I_ATA_PT, 0, SDEB_I_MAINT_IN,
@@ -423,11 +478,25 @@
static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_rsup_opcodes(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_rsup_tmfs(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_verify(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_write_same_10(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_write_same_16(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_comp_write(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_write_buffer(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_sync_cache(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_pre_fetch(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_report_zones(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_open_zone(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_close_zone(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_finish_zone(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_rwp_zone(struct scsi_cmnd *, struct sdebug_dev_info *);
+
+static int sdebug_do_add_host(bool mk_new_store);
+static int sdebug_add_host_helper(int per_host_idx);
+static void sdebug_do_remove_host(bool the_end);
+static int sdebug_add_store(void);
+static void sdebug_erase_store(int idx, struct sdeb_store_info *sip);
+static void sdebug_erase_all_stores(bool apart_from_first);
/*
* The following are overflow arrays for cdbs that "hit" the same index in
@@ -467,6 +536,12 @@
0xbf, 0xc7, 0, 0, 0, 0} },
};
+static const struct opcode_info_t verify_iarr[] = {
+ {0, 0x2f, 0, F_D_OUT_MAYBE | FF_MEDIA_IO, resp_verify,/* VERIFY(10) */
+ NULL, {10, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xc7,
+ 0, 0, 0, 0, 0, 0} },
+};
+
static const struct opcode_info_t sa_in_16_iarr[] = {
{0, 0x9e, 0x12, F_SA_LOW | F_D_IN, resp_get_lba_status, NULL,
{16, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -513,11 +588,35 @@
0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} }, /* SYNC_CACHE (16) */
};
+static const struct opcode_info_t pre_fetch_iarr[] = {
+ {0, 0x90, 0, F_SYNC_DELAY | FF_MEDIA_IO, resp_pre_fetch, NULL,
+ {16, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} }, /* PRE-FETCH (16) */
+};
+
+static const struct opcode_info_t zone_out_iarr[] = { /* ZONE OUT(16) */
+ {0, 0x94, 0x1, F_SA_LOW | F_M_ACCESS, resp_close_zone, NULL,
+ {16, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0, 0, 0xff, 0xff, 0x1, 0xc7} }, /* CLOSE ZONE */
+ {0, 0x94, 0x2, F_SA_LOW | F_M_ACCESS, resp_finish_zone, NULL,
+ {16, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0, 0, 0xff, 0xff, 0x1, 0xc7} }, /* FINISH ZONE */
+ {0, 0x94, 0x4, F_SA_LOW | F_M_ACCESS, resp_rwp_zone, NULL,
+ {16, 0x4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0, 0, 0xff, 0xff, 0x1, 0xc7} }, /* RESET WRITE POINTER */
+};
+
+static const struct opcode_info_t zone_in_iarr[] = { /* ZONE IN(16) */
+ {0, 0x95, 0x6, F_SA_LOW | F_D_IN | F_M_ACCESS, NULL, NULL,
+ {16, 0x6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} }, /* REPORT ZONES */
+};
+
/* This array is accessed via SDEB_I_* values. Make sure all are mapped,
* plus the terminating elements for logic that scans this table such as
* REPORT SUPPORTED OPERATION CODES. */
-static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
+static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEM_P1 + 1] = {
/* 0 */
{0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* unknown opcodes */
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
@@ -567,9 +666,10 @@
/* 15 */
{0, 0, 0, F_INV_OP | FF_RESPOND, NULL, NULL, /* MAINT OUT */
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
- {0, 0x2f, 0, F_D_OUT_MAYBE | FF_MEDIA_IO, NULL, NULL, /* VERIFY(10) */
- {10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7,
- 0, 0, 0, 0, 0, 0} },
+ {ARRAY_SIZE(verify_iarr), 0x8f, 0,
+ F_D_OUT_MAYBE | FF_MEDIA_IO, resp_verify, /* VERIFY(16) */
+ verify_iarr, {16, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} },
{ARRAY_SIZE(vl_iarr), 0x7f, 0x9, F_SA_HIGH | F_D_IN | FF_MEDIA_IO,
resp_read_dt0, vl_iarr, /* VARIABLE LENGTH, READ(32) */
{32, 0xc7, 0, 0, 0, 0, 0x3f, 0x18, 0x0, 0x9, 0xfe, 0, 0xff, 0xff,
@@ -608,23 +708,38 @@
{0, 0x89, 0, F_D_OUT | FF_MEDIA_IO, resp_comp_write, NULL,
{16, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0,
0, 0xff, 0x3f, 0xc7} }, /* COMPARE AND WRITE */
+ {ARRAY_SIZE(pre_fetch_iarr), 0x34, 0, F_SYNC_DELAY | FF_MEDIA_IO,
+ resp_pre_fetch, pre_fetch_iarr,
+ {10, 0x2, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, 0, 0,
+ 0, 0, 0, 0} }, /* PRE-FETCH (10) */
-/* 29 */
+/* 30 */
+ {ARRAY_SIZE(zone_out_iarr), 0x94, 0x3, F_SA_LOW | F_M_ACCESS,
+ resp_open_zone, zone_out_iarr, /* ZONE_OUT(16), OPEN ZONE) */
+ {16, 0x3 /* SA */, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x1, 0xc7} },
+ {ARRAY_SIZE(zone_in_iarr), 0x95, 0x0, F_SA_LOW | F_M_ACCESS,
+ resp_report_zones, zone_in_iarr, /* ZONE_IN(16), REPORT ZONES) */
+ {16, 0x0 /* SA */, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xc7} },
+/* sentinel */
{0xff, 0, 0, 0, NULL, NULL, /* terminating element */
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
};
-static int sdebug_add_host = DEF_NUM_HOST;
+static int sdebug_num_hosts;
+static int sdebug_add_host = DEF_NUM_HOST; /* in sysfs this is relative */
static int sdebug_ato = DEF_ATO;
static int sdebug_cdb_len = DEF_CDB_LEN;
static int sdebug_jdelay = DEF_JDELAY; /* if > 0 then unit is jiffies */
-static int sdebug_dev_size_mb = DEF_DEV_SIZE_MB;
+static int sdebug_dev_size_mb = DEF_DEV_SIZE_PRE_INIT;
static int sdebug_dif = DEF_DIF;
static int sdebug_dix = DEF_DIX;
static int sdebug_dsense = DEF_D_SENSE;
static int sdebug_every_nth = DEF_EVERY_NTH;
static int sdebug_fake_rw = DEF_FAKE_RW;
static unsigned int sdebug_guard = DEF_GUARD;
+static int sdebug_host_max_queue; /* per host */
static int sdebug_lowest_aligned = DEF_LOWEST_ALIGNED;
static int sdebug_max_luns = DEF_MAX_LUNS;
static int sdebug_max_queue = SDEBUG_CANQUEUE; /* per submit queue */
@@ -643,6 +758,7 @@
static int sdebug_ptype = DEF_PTYPE; /* SCSI peripheral device type */
static int sdebug_scsi_level = DEF_SCSI_LEVEL;
static int sdebug_sector_size = DEF_SECTOR_SIZE;
+static int sdeb_tur_ms_to_ready = DEF_TUR_MS_TO_READY;
static int sdebug_virtual_gb = DEF_VIRTUAL_GB;
static int sdebug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
static unsigned int sdebug_lbpu = DEF_LBPU;
@@ -655,6 +771,8 @@
static unsigned int sdebug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
static unsigned int sdebug_write_same_length = DEF_WRITESAME_LENGTH;
static int sdebug_uuid_ctl = DEF_UUID_CTL;
+static bool sdebug_random = DEF_RANDOM;
+static bool sdebug_per_host_store = DEF_PER_HOST_STORE;
static bool sdebug_removable = DEF_REMOVABLE;
static bool sdebug_clustering;
static bool sdebug_host_lock = DEF_HOST_LOCK;
@@ -665,6 +783,16 @@
static bool write_since_sync;
static bool sdebug_statistics = DEF_STATISTICS;
static bool sdebug_wp;
+/* Following enum: 0: no zbc, def; 1: host aware; 2: host managed */
+static enum blk_zoned_model sdeb_zbc_model = BLK_ZONED_NONE;
+static char *sdeb_zbc_model_s;
+
+enum sam_lun_addr_method {SAM_LUN_AM_PERIPHERAL = 0x0,
+ SAM_LUN_AM_FLAT = 0x1,
+ SAM_LUN_AM_LOGICAL_UNIT = 0x2,
+ SAM_LUN_AM_EXTENDED = 0x3};
+static enum sam_lun_addr_method sdebug_lun_am = SAM_LUN_AM_PERIPHERAL;
+static int sdebug_lun_am_i = (int)SAM_LUN_AM_PERIPHERAL;
static unsigned int sdebug_store_sectors;
static sector_t sdebug_capacity; /* in sectors */
@@ -678,9 +806,11 @@
static LIST_HEAD(sdebug_host_list);
static DEFINE_SPINLOCK(sdebug_host_list_lock);
-static unsigned char *fake_storep; /* ramdisk storage */
-static struct t10_pi_tuple *dif_storep; /* protection info */
-static void *map_storep; /* provisioning map */
+static struct xarray per_store_arr;
+static struct xarray *per_store_ap = &per_store_arr;
+static int sdeb_first_idx = -1; /* invalid index ==> none created */
+static int sdeb_most_recent_idx = -1;
+static DEFINE_RWLOCK(sdeb_fake_rw_lck); /* need a RW lock when fake_rw=1 */
static unsigned long map_size;
static int num_aborts;
@@ -692,10 +822,19 @@
static int dix_reads;
static int dif_errors;
+/* ZBC global data */
+static bool sdeb_zbc_in_use; /* true for host-aware and host-managed disks */
+static int sdeb_zbc_zone_size_mb;
+static int sdeb_zbc_max_open = DEF_ZBC_MAX_OPEN_ZONES;
+static int sdeb_zbc_nr_conv = DEF_ZBC_NR_CONV_ZONES;
+
static int submit_queues = DEF_SUBMIT_QUEUES; /* > 1 for multi-queue (mq) */
static struct sdebug_queue *sdebug_q_arr; /* ptr to array of submit queues */
static DEFINE_RWLOCK(atomic_rw);
+static DEFINE_RWLOCK(atomic_rw2);
+
+static rwlock_t *ramdisk_lck_a[2];
static char sdebug_proc_name[] = MY_NAME;
static const char *my_name = MY_NAME;
@@ -716,6 +855,8 @@
static const int device_qfull_result =
(DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL;
+static const int condition_met_result = SAM_STAT_CONDITION_MET;
+
/* Only do the extra work involved in logical block provisioning if one or
* more of the lbpu, lbpws or lbpws10 parameters are given and we are doing
@@ -727,18 +868,25 @@
(sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10);
}
-static void *lba2fake_store(unsigned long long lba)
+static void *lba2fake_store(struct sdeb_store_info *sip,
+ unsigned long long lba)
{
- lba = do_div(lba, sdebug_store_sectors);
+ struct sdeb_store_info *lsip = sip;
- return fake_storep + lba * sdebug_sector_size;
+ lba = do_div(lba, sdebug_store_sectors);
+ if (!sip || !sip->storep) {
+ WARN_ON_ONCE(true);
+ lsip = xa_load(per_store_ap, 0); /* should never be NULL */
+ }
+ return lsip->storep + lba * sdebug_sector_size;
}
-static struct t10_pi_tuple *dif_store(sector_t sector)
+static struct t10_pi_tuple *dif_store(struct sdeb_store_info *sip,
+ sector_t sector)
{
sector = sector_div(sector, sdebug_store_sectors);
- return dif_storep + sector;
+ return sip->dif_storep + sector;
}
static void sdebug_max_tgts_luns(void)
@@ -1025,7 +1173,7 @@
static int p_fill_from_dev_buffer(struct scsi_cmnd *scp, const void *arr,
int arr_len, unsigned int off_dst)
{
- int act_len, n;
+ unsigned int act_len, n;
struct scsi_data_buffer *sdb = &scp->sdb;
off_t skip = off_dst;
@@ -1039,8 +1187,8 @@
pr_debug("%s: off_dst=%u, scsi_bufflen=%u, act_len=%u, resid=%d\n",
__func__, off_dst, scsi_bufflen(scp), act_len,
scsi_get_resid(scp));
- n = (int)scsi_bufflen(scp) - ((int)off_dst + act_len);
- scsi_set_resid(scp, min(scsi_get_resid(scp), n));
+ n = scsi_bufflen(scp) - (off_dst + act_len);
+ scsi_set_resid(scp, min_t(u32, scsi_get_resid(scp), n));
return 0;
}
@@ -1353,13 +1501,15 @@
}
/* Block device characteristics VPD page (SBC-3) */
-static int inquiry_vpd_b1(unsigned char *arr)
+static int inquiry_vpd_b1(struct sdebug_dev_info *devip, unsigned char *arr)
{
memset(arr, 0, 0x3c);
arr[0] = 0;
arr[1] = 1; /* non rotating medium (e.g. solid state) */
arr[2] = 0;
arr[3] = 5; /* less than 1.8" */
+ if (devip->zmodel == BLK_ZONED_HA)
+ arr[4] = 1 << 4; /* zoned field = 01b */
return 0x3c;
}
@@ -1383,6 +1533,26 @@
return 0x4;
}
+/* Zoned block device characteristics VPD page (ZBC mandatory) */
+static int inquiry_vpd_b6(struct sdebug_dev_info *devip, unsigned char *arr)
+{
+ memset(arr, 0, 0x3c);
+ arr[0] = 0x1; /* set URSWRZ (unrestricted read in seq. wr req zone) */
+ /*
+ * Set Optimal number of open sequential write preferred zones and
+ * Optimal number of non-sequentially written sequential write
+ * preferred zones fields to 'not reported' (0xffffffff). Leave other
+ * fields set to zero, apart from Max. number of open swrz_s field.
+ */
+ put_unaligned_be32(0xffffffff, &arr[4]);
+ put_unaligned_be32(0xffffffff, &arr[8]);
+ if (sdeb_zbc_model == BLK_ZONED_HM && devip->max_open)
+ put_unaligned_be32(devip->max_open, &arr[12]);
+ else
+ put_unaligned_be32(0xffffffff, &arr[12]);
+ return 0x3c;
+}
+
#define SDEBUG_LONG_INQ_SZ 96
#define SDEBUG_MAX_INQ_ARR_SZ 584
@@ -1391,14 +1561,17 @@
unsigned char pq_pdt;
unsigned char *arr;
unsigned char *cmd = scp->cmnd;
- int alloc_len, n, ret;
- bool have_wlun, is_disk;
+ u32 alloc_len, n;
+ int ret;
+ bool have_wlun, is_disk, is_zbc, is_disk_zbc;
alloc_len = get_unaligned_be16(cmd + 3);
arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC);
if (! arr)
return DID_REQUEUE << 16;
is_disk = (sdebug_ptype == TYPE_DISK);
+ is_zbc = (devip->zmodel != BLK_ZONED_NONE);
+ is_disk_zbc = (is_disk || is_zbc);
have_wlun = scsi_is_wlun(scp->device->lun);
if (have_wlun)
pq_pdt = TYPE_WLUN; /* present, wlun */
@@ -1412,7 +1585,8 @@
kfree(arr);
return check_condition_result;
} else if (0x1 & cmd[1]) { /* EVPD bit set */
- int lu_id_num, port_group_id, target_dev_id, len;
+ int lu_id_num, port_group_id, target_dev_id;
+ u32 len;
char lu_id_str[6];
int host_no = devip->sdbg_host->shost->host_no;
@@ -1436,11 +1610,14 @@
arr[n++] = 0x86; /* extended inquiry */
arr[n++] = 0x87; /* mode page policy */
arr[n++] = 0x88; /* SCSI ports */
- if (is_disk) { /* SBC only */
+ if (is_disk_zbc) { /* SBC or ZBC */
arr[n++] = 0x89; /* ATA information */
arr[n++] = 0xb0; /* Block limits */
arr[n++] = 0xb1; /* Block characteristics */
- arr[n++] = 0xb2; /* Logical Block Prov */
+ if (is_disk)
+ arr[n++] = 0xb2; /* LB Provisioning */
+ if (is_zbc)
+ arr[n++] = 0xb6; /* ZB dev. char. */
}
arr[3] = n - 4; /* number of supported VPD pages */
} else if (0x80 == cmd[2]) { /* unit serial number */
@@ -1479,27 +1656,30 @@
} else if (0x88 == cmd[2]) { /* SCSI Ports */
arr[1] = cmd[2]; /*sanity */
arr[3] = inquiry_vpd_88(&arr[4], target_dev_id);
- } else if (is_disk && 0x89 == cmd[2]) { /* ATA information */
+ } else if (is_disk_zbc && 0x89 == cmd[2]) { /* ATA info */
arr[1] = cmd[2]; /*sanity */
n = inquiry_vpd_89(&arr[4]);
put_unaligned_be16(n, arr + 2);
- } else if (is_disk && 0xb0 == cmd[2]) { /* Block limits */
+ } else if (is_disk_zbc && 0xb0 == cmd[2]) { /* Block limits */
arr[1] = cmd[2]; /*sanity */
arr[3] = inquiry_vpd_b0(&arr[4]);
- } else if (is_disk && 0xb1 == cmd[2]) { /* Block char. */
+ } else if (is_disk_zbc && 0xb1 == cmd[2]) { /* Block char. */
arr[1] = cmd[2]; /*sanity */
- arr[3] = inquiry_vpd_b1(&arr[4]);
+ arr[3] = inquiry_vpd_b1(devip, &arr[4]);
} else if (is_disk && 0xb2 == cmd[2]) { /* LB Prov. */
arr[1] = cmd[2]; /*sanity */
arr[3] = inquiry_vpd_b2(&arr[4]);
+ } else if (is_zbc && cmd[2] == 0xb6) { /* ZB dev. charact. */
+ arr[1] = cmd[2]; /*sanity */
+ arr[3] = inquiry_vpd_b6(devip, &arr[4]);
} else {
mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
kfree(arr);
return check_condition_result;
}
- len = min(get_unaligned_be16(arr + 2) + 4, alloc_len);
+ len = min_t(u32, get_unaligned_be16(arr + 2) + 4, alloc_len);
ret = fill_from_dev_buffer(scp, arr,
- min(len, SDEBUG_MAX_INQ_ARR_SZ));
+ min_t(u32, len, SDEBUG_MAX_INQ_ARR_SZ));
kfree(arr);
return ret;
}
@@ -1529,83 +1709,79 @@
} else if (sdebug_ptype == TYPE_TAPE) { /* SSC-4 rev 3 */
put_unaligned_be16(0x525, arr + n);
n += 2;
+ } else if (is_zbc) { /* ZBC BSR INCITS 536 revision 05 */
+ put_unaligned_be16(0x624, arr + n);
+ n += 2;
}
put_unaligned_be16(0x2100, arr + n); /* SPL-4 no version claimed */
ret = fill_from_dev_buffer(scp, arr,
- min(alloc_len, SDEBUG_LONG_INQ_SZ));
+ min_t(u32, alloc_len, SDEBUG_LONG_INQ_SZ));
kfree(arr);
return ret;
}
+/* See resp_iec_m_pg() for how this data is manipulated */
static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
0, 0, 0x0, 0x0};
static int resp_requests(struct scsi_cmnd *scp,
struct sdebug_dev_info *devip)
{
- unsigned char *sbuff;
unsigned char *cmd = scp->cmnd;
- unsigned char arr[SCSI_SENSE_BUFFERSIZE];
- bool dsense;
- int len = 18;
+ unsigned char arr[SCSI_SENSE_BUFFERSIZE]; /* assume >= 18 bytes */
+ bool dsense = !!(cmd[1] & 1);
+ u32 alloc_len = cmd[4];
+ u32 len = 18;
+ int stopped_state = atomic_read(&devip->stopped);
memset(arr, 0, sizeof(arr));
- dsense = !!(cmd[1] & 1);
- sbuff = scp->sense_buffer;
- if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
+ if (stopped_state > 0) { /* some "pollable" data [spc6r02: 5.12.2] */
+ if (dsense) {
+ arr[0] = 0x72;
+ arr[1] = NOT_READY;
+ arr[2] = LOGICAL_UNIT_NOT_READY;
+ arr[3] = (stopped_state == 2) ? 0x1 : 0x2;
+ len = 8;
+ } else {
+ arr[0] = 0x70;
+ arr[2] = NOT_READY; /* NO_SENSE in sense_key */
+ arr[7] = 0xa; /* 18 byte sense buffer */
+ arr[12] = LOGICAL_UNIT_NOT_READY;
+ arr[13] = (stopped_state == 2) ? 0x1 : 0x2;
+ }
+ } else if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) {
+ /* Information exceptions control mode page: TEST=1, MRIE=6 */
if (dsense) {
arr[0] = 0x72;
arr[1] = 0x0; /* NO_SENSE in sense_key */
arr[2] = THRESHOLD_EXCEEDED;
- arr[3] = 0xff; /* TEST set and MRIE==6 */
+ arr[3] = 0xff; /* Failure prediction(false) */
len = 8;
} else {
arr[0] = 0x70;
arr[2] = 0x0; /* NO_SENSE in sense_key */
arr[7] = 0xa; /* 18 byte sense buffer */
arr[12] = THRESHOLD_EXCEEDED;
- arr[13] = 0xff; /* TEST set and MRIE==6 */
+ arr[13] = 0xff; /* Failure prediction(false) */
}
- } else {
- memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE);
- if (arr[0] >= 0x70 && dsense == sdebug_dsense)
- ; /* have sense and formats match */
- else if (arr[0] <= 0x70) {
- if (dsense) {
- memset(arr, 0, 8);
- arr[0] = 0x72;
- len = 8;
- } else {
- memset(arr, 0, 18);
- arr[0] = 0x70;
- arr[7] = 0xa;
- }
- } else if (dsense) {
- memset(arr, 0, 8);
- arr[0] = 0x72;
- arr[1] = sbuff[2]; /* sense key */
- arr[2] = sbuff[12]; /* asc */
- arr[3] = sbuff[13]; /* ascq */
+ } else { /* nothing to report */
+ if (dsense) {
len = 8;
+ memset(arr, 0, len);
+ arr[0] = 0x72;
} else {
- memset(arr, 0, 18);
+ memset(arr, 0, len);
arr[0] = 0x70;
- arr[2] = sbuff[1];
arr[7] = 0xa;
- arr[12] = sbuff[1];
- arr[13] = sbuff[3];
}
-
}
- mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0);
- return fill_from_dev_buffer(scp, arr, len);
+ return fill_from_dev_buffer(scp, arr, min_t(u32, len, alloc_len));
}
-static int resp_start_stop(struct scsi_cmnd *scp,
- struct sdebug_dev_info *devip)
+static int resp_start_stop(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
{
unsigned char *cmd = scp->cmnd;
- int power_cond, stop;
+ int power_cond, want_stop, stopped_state;
bool changing;
power_cond = (cmd[4] & 0xf0) >> 4;
@@ -1613,10 +1789,33 @@
mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 7);
return check_condition_result;
}
- stop = !(cmd[4] & 1);
- changing = atomic_read(&devip->stopped) == !stop;
- atomic_xchg(&devip->stopped, stop);
- if (!changing || cmd[1] & 0x1) /* state unchanged or IMMED set */
+ want_stop = !(cmd[4] & 1);
+ stopped_state = atomic_read(&devip->stopped);
+ if (stopped_state == 2) {
+ ktime_t now_ts = ktime_get_boottime();
+
+ if (ktime_to_ns(now_ts) > ktime_to_ns(devip->create_ts)) {
+ u64 diff_ns = ktime_to_ns(ktime_sub(now_ts, devip->create_ts));
+
+ if (diff_ns >= ((u64)sdeb_tur_ms_to_ready * 1000000)) {
+ /* tur_ms_to_ready timer extinguished */
+ atomic_set(&devip->stopped, 0);
+ stopped_state = 0;
+ }
+ }
+ if (stopped_state == 2) {
+ if (want_stop) {
+ stopped_state = 1; /* dummy up success */
+ } else { /* Disallow tur_ms_to_ready delay to be overridden */
+ mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 0 /* START bit */);
+ return check_condition_result;
+ }
+ }
+ }
+ changing = (stopped_state != want_stop);
+ if (changing)
+ atomic_xchg(&devip->stopped, want_stop);
+ if (!changing || (cmd[1] & 0x1)) /* state unchanged or IMMED bit set in cdb */
return SDEG_RES_IMMED_MASK;
else
return 0;
@@ -1658,7 +1857,7 @@
{
unsigned char *cmd = scp->cmnd;
unsigned char arr[SDEBUG_READCAP16_ARR_SZ];
- int alloc_len;
+ u32 alloc_len;
alloc_len = get_unaligned_be32(cmd + 10);
/* following just in case virtual_gb changed */
@@ -1687,7 +1886,7 @@
}
return fill_from_dev_buffer(scp, arr,
- min(alloc_len, SDEBUG_READCAP16_ARR_SZ));
+ min_t(u32, alloc_len, SDEBUG_READCAP16_ARR_SZ));
}
#define SDEBUG_MAX_TGTPGS_ARR_SZ 1412
@@ -1698,8 +1897,9 @@
unsigned char *cmd = scp->cmnd;
unsigned char *arr;
int host_no = devip->sdbg_host->shost->host_no;
- int n, ret, alen, rlen;
int port_group_a, port_group_b, port_a, port_b;
+ u32 alen, n, rlen;
+ int ret;
alen = get_unaligned_be32(cmd + 6);
arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC);
@@ -1761,9 +1961,9 @@
* - The constructed command length
* - The maximum array size
*/
- rlen = min(alen,n);
+ rlen = min(alen, n);
ret = fill_from_dev_buffer(scp, arr,
- min(rlen, SDEBUG_MAX_TGTPGS_ARR_SZ));
+ min_t(u32, rlen, SDEBUG_MAX_TGTPGS_ARR_SZ));
kfree(arr);
return ret;
}
@@ -2113,12 +2313,13 @@
{
int pcontrol, pcode, subpcode, bd_len;
unsigned char dev_spec;
- int alloc_len, offset, len, target_dev_id;
+ u32 alloc_len, offset, len;
+ int target_dev_id;
int target = scp->device->id;
unsigned char *ap;
unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
unsigned char *cmd = scp->cmnd;
- bool dbd, llbaa, msense_6, is_disk, bad_pcode;
+ bool dbd, llbaa, msense_6, is_disk, is_zbc, bad_pcode;
dbd = !!(cmd[1] & 0x8); /* disable block descriptors */
pcontrol = (cmd[2] & 0xc0) >> 6;
@@ -2127,7 +2328,8 @@
msense_6 = (MODE_SENSE == cmd[0]);
llbaa = msense_6 ? false : !!(cmd[1] & 0x10);
is_disk = (sdebug_ptype == TYPE_DISK);
- if (is_disk && !dbd)
+ is_zbc = (devip->zmodel != BLK_ZONED_NONE);
+ if ((is_disk || is_zbc) && !dbd)
bd_len = llbaa ? 16 : 8;
else
bd_len = 0;
@@ -2139,8 +2341,8 @@
}
target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) +
(devip->target * 1000) - 3;
- /* for disks set DPOFUA bit and clear write protect (WP) bit */
- if (is_disk) {
+ /* for disks+zbc set DPOFUA bit and clear write protect (WP) bit */
+ if (is_disk || is_zbc) {
dev_spec = 0x10; /* =0x90 if WP=1 implies read-only */
if (sdebug_wp)
dev_spec |= 0x80;
@@ -2200,7 +2402,7 @@
bad_pcode = true;
break;
case 0x8: /* Caching page, direct access */
- if (is_disk) {
+ if (is_disk || is_zbc) {
len = resp_caching_pg(ap, pcontrol, target);
offset += len;
} else
@@ -2238,6 +2440,9 @@
target);
len += resp_caching_pg(ap + len, pcontrol,
target);
+ } else if (is_zbc) {
+ len += resp_caching_pg(ap + len, pcontrol,
+ target);
}
len += resp_ctrl_m_pg(ap + len, pcontrol, target);
len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
@@ -2265,7 +2470,7 @@
arr[0] = offset - 1;
else
put_unaligned_be16((offset - 2), arr + 0);
- return fill_from_dev_buffer(scp, arr, min(alloc_len, offset));
+ return fill_from_dev_buffer(scp, arr, min_t(u32, alloc_len, offset));
}
#define SDEBUG_MAX_MSELECT_SZ 512
@@ -2296,11 +2501,11 @@
__func__, param_len, res);
md_len = mselect6 ? (arr[0] + 1) : (get_unaligned_be16(arr + 0) + 2);
bd_len = mselect6 ? arr[3] : get_unaligned_be16(arr + 6);
- if (md_len > 2) {
+ off = bd_len + (mselect6 ? 4 : 8);
+ if (md_len > 2 || off >= res) {
mk_sense_invalid_fld(scp, SDEB_IN_DATA, 0, -1);
return check_condition_result;
}
- off = bd_len + (mselect6 ? 4 : 8);
mpage = arr[off] & 0x3f;
ps = !!(arr[off] & 0x80);
if (ps) {
@@ -2380,7 +2585,8 @@
static int resp_log_sense(struct scsi_cmnd *scp,
struct sdebug_dev_info *devip)
{
- int ppc, sp, pcode, subpcode, alloc_len, len, n;
+ int ppc, sp, pcode, subpcode;
+ u32 alloc_len, len, n;
unsigned char arr[SDEBUG_MAX_LSENSE_SZ];
unsigned char *cmd = scp->cmnd;
@@ -2450,14 +2656,217 @@
mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
return check_condition_result;
}
- len = min(get_unaligned_be16(arr + 2) + 4, alloc_len);
+ len = min_t(u32, get_unaligned_be16(arr + 2) + 4, alloc_len);
return fill_from_dev_buffer(scp, arr,
- min(len, SDEBUG_MAX_INQ_ARR_SZ));
+ min_t(u32, len, SDEBUG_MAX_INQ_ARR_SZ));
}
-static inline int check_device_access_params(struct scsi_cmnd *scp,
- unsigned long long lba, unsigned int num, bool write)
+static inline bool sdebug_dev_is_zoned(struct sdebug_dev_info *devip)
{
+ return devip->nr_zones != 0;
+}
+
+static struct sdeb_zone_state *zbc_zone(struct sdebug_dev_info *devip,
+ unsigned long long lba)
+{
+ return &devip->zstate[lba >> devip->zsize_shift];
+}
+
+static inline bool zbc_zone_is_conv(struct sdeb_zone_state *zsp)
+{
+ return zsp->z_type == ZBC_ZONE_TYPE_CNV;
+}
+
+static void zbc_close_zone(struct sdebug_dev_info *devip,
+ struct sdeb_zone_state *zsp)
+{
+ enum sdebug_z_cond zc;
+
+ if (zbc_zone_is_conv(zsp))
+ return;
+
+ zc = zsp->z_cond;
+ if (!(zc == ZC2_IMPLICIT_OPEN || zc == ZC3_EXPLICIT_OPEN))
+ return;
+
+ if (zc == ZC2_IMPLICIT_OPEN)
+ devip->nr_imp_open--;
+ else
+ devip->nr_exp_open--;
+
+ if (zsp->z_wp == zsp->z_start) {
+ zsp->z_cond = ZC1_EMPTY;
+ } else {
+ zsp->z_cond = ZC4_CLOSED;
+ devip->nr_closed++;
+ }
+}
+
+static void zbc_close_imp_open_zone(struct sdebug_dev_info *devip)
+{
+ struct sdeb_zone_state *zsp = &devip->zstate[0];
+ unsigned int i;
+
+ for (i = 0; i < devip->nr_zones; i++, zsp++) {
+ if (zsp->z_cond == ZC2_IMPLICIT_OPEN) {
+ zbc_close_zone(devip, zsp);
+ return;
+ }
+ }
+}
+
+static void zbc_open_zone(struct sdebug_dev_info *devip,
+ struct sdeb_zone_state *zsp, bool explicit)
+{
+ enum sdebug_z_cond zc;
+
+ if (zbc_zone_is_conv(zsp))
+ return;
+
+ zc = zsp->z_cond;
+ if ((explicit && zc == ZC3_EXPLICIT_OPEN) ||
+ (!explicit && zc == ZC2_IMPLICIT_OPEN))
+ return;
+
+ /* Close an implicit open zone if necessary */
+ if (explicit && zsp->z_cond == ZC2_IMPLICIT_OPEN)
+ zbc_close_zone(devip, zsp);
+ else if (devip->max_open &&
+ devip->nr_imp_open + devip->nr_exp_open >= devip->max_open)
+ zbc_close_imp_open_zone(devip);
+
+ if (zsp->z_cond == ZC4_CLOSED)
+ devip->nr_closed--;
+ if (explicit) {
+ zsp->z_cond = ZC3_EXPLICIT_OPEN;
+ devip->nr_exp_open++;
+ } else {
+ zsp->z_cond = ZC2_IMPLICIT_OPEN;
+ devip->nr_imp_open++;
+ }
+}
+
+static void zbc_inc_wp(struct sdebug_dev_info *devip,
+ unsigned long long lba, unsigned int num)
+{
+ struct sdeb_zone_state *zsp = zbc_zone(devip, lba);
+ unsigned long long n, end, zend = zsp->z_start + zsp->z_size;
+
+ if (zbc_zone_is_conv(zsp))
+ return;
+
+ if (zsp->z_type == ZBC_ZONE_TYPE_SWR) {
+ zsp->z_wp += num;
+ if (zsp->z_wp >= zend)
+ zsp->z_cond = ZC5_FULL;
+ return;
+ }
+
+ while (num) {
+ if (lba != zsp->z_wp)
+ zsp->z_non_seq_resource = true;
+
+ end = lba + num;
+ if (end >= zend) {
+ n = zend - lba;
+ zsp->z_wp = zend;
+ } else if (end > zsp->z_wp) {
+ n = num;
+ zsp->z_wp = end;
+ } else {
+ n = num;
+ }
+ if (zsp->z_wp >= zend)
+ zsp->z_cond = ZC5_FULL;
+
+ num -= n;
+ lba += n;
+ if (num) {
+ zsp++;
+ zend = zsp->z_start + zsp->z_size;
+ }
+ }
+}
+
+static int check_zbc_access_params(struct scsi_cmnd *scp,
+ unsigned long long lba, unsigned int num, bool write)
+{
+ struct scsi_device *sdp = scp->device;
+ struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdp->hostdata;
+ struct sdeb_zone_state *zsp = zbc_zone(devip, lba);
+ struct sdeb_zone_state *zsp_end = zbc_zone(devip, lba + num - 1);
+
+ if (!write) {
+ if (devip->zmodel == BLK_ZONED_HA)
+ return 0;
+ /* For host-managed, reads cannot cross zone types boundaries */
+ if (zsp_end != zsp &&
+ zbc_zone_is_conv(zsp) &&
+ !zbc_zone_is_conv(zsp_end)) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST,
+ LBA_OUT_OF_RANGE,
+ READ_INVDATA_ASCQ);
+ return check_condition_result;
+ }
+ return 0;
+ }
+
+ /* No restrictions for writes within conventional zones */
+ if (zbc_zone_is_conv(zsp)) {
+ if (!zbc_zone_is_conv(zsp_end)) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST,
+ LBA_OUT_OF_RANGE,
+ WRITE_BOUNDARY_ASCQ);
+ return check_condition_result;
+ }
+ return 0;
+ }
+
+ if (zsp->z_type == ZBC_ZONE_TYPE_SWR) {
+ /* Writes cannot cross sequential zone boundaries */
+ if (zsp_end != zsp) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST,
+ LBA_OUT_OF_RANGE,
+ WRITE_BOUNDARY_ASCQ);
+ return check_condition_result;
+ }
+ /* Cannot write full zones */
+ if (zsp->z_cond == ZC5_FULL) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST,
+ INVALID_FIELD_IN_CDB, 0);
+ return check_condition_result;
+ }
+ /* Writes must be aligned to the zone WP */
+ if (lba != zsp->z_wp) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST,
+ LBA_OUT_OF_RANGE,
+ UNALIGNED_WRITE_ASCQ);
+ return check_condition_result;
+ }
+ }
+
+ /* Handle implicit open of closed and empty zones */
+ if (zsp->z_cond == ZC1_EMPTY || zsp->z_cond == ZC4_CLOSED) {
+ if (devip->max_open &&
+ devip->nr_exp_open >= devip->max_open) {
+ mk_sense_buffer(scp, DATA_PROTECT,
+ INSUFF_RES_ASC,
+ INSUFF_ZONE_ASCQ);
+ return check_condition_result;
+ }
+ zbc_open_zone(devip, zsp, false);
+ }
+
+ return 0;
+}
+
+static inline int check_device_access_params
+ (struct scsi_cmnd *scp, unsigned long long lba,
+ unsigned int num, bool write)
+{
+ struct scsi_device *sdp = scp->device;
+ struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdp->hostdata;
+
if (lba + num > sdebug_capacity) {
mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
return check_condition_result;
@@ -2472,17 +2881,37 @@
mk_sense_buffer(scp, DATA_PROTECT, WRITE_PROTECTED, 0x2);
return check_condition_result;
}
+ if (sdebug_dev_is_zoned(devip))
+ return check_zbc_access_params(scp, lba, num, write);
+
return 0;
}
+/*
+ * Note: if BUG_ON() fires it usually indicates a problem with the parser
+ * tables. Perhaps a missing F_FAKE_RW or FF_MEDIA_IO flag. Response functions
+ * that access any of the "stores" in struct sdeb_store_info should call this
+ * function with bug_if_fake_rw set to true.
+ */
+static inline struct sdeb_store_info *devip2sip(struct sdebug_dev_info *devip,
+ bool bug_if_fake_rw)
+{
+ if (sdebug_fake_rw) {
+ BUG_ON(bug_if_fake_rw); /* See note above */
+ return NULL;
+ }
+ return xa_load(per_store_ap, devip->sdbg_host->si_idx);
+}
+
/* Returns number of bytes copied or -1 if error. */
-static int do_device_access(struct scsi_cmnd *scmd, u32 sg_skip, u64 lba,
- u32 num, bool do_write)
+static int do_device_access(struct sdeb_store_info *sip, struct scsi_cmnd *scp,
+ u32 sg_skip, u64 lba, u32 num, bool do_write)
{
int ret;
u64 block, rest = 0;
- struct scsi_data_buffer *sdb = &scmd->sdb;
enum dma_data_direction dir;
+ struct scsi_data_buffer *sdb = &scp->sdb;
+ u8 *fsp;
if (do_write) {
dir = DMA_TO_DEVICE;
@@ -2491,24 +2920,25 @@
dir = DMA_FROM_DEVICE;
}
- if (!sdb->length)
+ if (!sdb->length || !sip)
return 0;
- if (scmd->sc_data_direction != dir)
+ if (scp->sc_data_direction != dir)
return -1;
+ fsp = sip->storep;
block = do_div(lba, sdebug_store_sectors);
if (block + num > sdebug_store_sectors)
rest = block + num - sdebug_store_sectors;
ret = sg_copy_buffer(sdb->table.sgl, sdb->table.nents,
- fake_storep + (block * sdebug_sector_size),
+ fsp + (block * sdebug_sector_size),
(num - rest) * sdebug_sector_size, sg_skip, do_write);
if (ret != (num - rest) * sdebug_sector_size)
return ret;
if (rest) {
ret += sg_copy_buffer(sdb->table.sgl, sdb->table.nents,
- fake_storep, rest * sdebug_sector_size,
+ fsp, rest * sdebug_sector_size,
sg_skip + ((num - rest) * sdebug_sector_size),
do_write);
}
@@ -2516,34 +2946,49 @@
return ret;
}
-/* If lba2fake_store(lba,num) compares equal to arr(num), then copy top half of
- * arr into lba2fake_store(lba,num) and return true. If comparison fails then
+/* Returns number of bytes copied or -1 if error. */
+static int do_dout_fetch(struct scsi_cmnd *scp, u32 num, u8 *doutp)
+{
+ struct scsi_data_buffer *sdb = &scp->sdb;
+
+ if (!sdb->length)
+ return 0;
+ if (scp->sc_data_direction != DMA_TO_DEVICE)
+ return -1;
+ return sg_copy_buffer(sdb->table.sgl, sdb->table.nents, doutp,
+ num * sdebug_sector_size, 0, true);
+}
+
+/* If sip->storep+lba compares equal to arr(num), then copy top half of
+ * arr into sip->storep+lba and return true. If comparison fails then
* return false. */
-static bool comp_write_worker(u64 lba, u32 num, const u8 *arr)
+static bool comp_write_worker(struct sdeb_store_info *sip, u64 lba, u32 num,
+ const u8 *arr, bool compare_only)
{
bool res;
u64 block, rest = 0;
u32 store_blks = sdebug_store_sectors;
u32 lb_size = sdebug_sector_size;
+ u8 *fsp = sip->storep;
block = do_div(lba, store_blks);
if (block + num > store_blks)
rest = block + num - store_blks;
- res = !memcmp(fake_storep + (block * lb_size), arr,
- (num - rest) * lb_size);
+ res = !memcmp(fsp + (block * lb_size), arr, (num - rest) * lb_size);
if (!res)
return res;
if (rest)
- res = memcmp(fake_storep, arr + ((num - rest) * lb_size),
+ res = memcmp(fsp, arr + ((num - rest) * lb_size),
rest * lb_size);
if (!res)
return res;
+ if (compare_only)
+ return true;
arr += num * lb_size;
- memcpy(fake_storep + (block * lb_size), arr, (num - rest) * lb_size);
+ memcpy(fsp + (block * lb_size), arr, (num - rest) * lb_size);
if (rest)
- memcpy(fake_storep, arr + ((num - rest) * lb_size),
- rest * lb_size);
+ memcpy(fsp, arr + ((num - rest) * lb_size), rest * lb_size);
return res;
}
@@ -2586,24 +3031,27 @@
return 0;
}
-static void dif_copy_prot(struct scsi_cmnd *SCpnt, sector_t sector,
+static void dif_copy_prot(struct scsi_cmnd *scp, sector_t sector,
unsigned int sectors, bool read)
{
size_t resid;
void *paddr;
+ struct sdeb_store_info *sip = devip2sip((struct sdebug_dev_info *)
+ scp->device->hostdata, true);
+ struct t10_pi_tuple *dif_storep = sip->dif_storep;
const void *dif_store_end = dif_storep + sdebug_store_sectors;
struct sg_mapping_iter miter;
/* Bytes of protection data to copy into sgl */
resid = sectors * sizeof(*dif_storep);
- sg_miter_start(&miter, scsi_prot_sglist(SCpnt),
- scsi_prot_sg_count(SCpnt), SG_MITER_ATOMIC |
- (read ? SG_MITER_TO_SG : SG_MITER_FROM_SG));
+ sg_miter_start(&miter, scsi_prot_sglist(scp),
+ scsi_prot_sg_count(scp), SG_MITER_ATOMIC |
+ (read ? SG_MITER_TO_SG : SG_MITER_FROM_SG));
while (sg_miter_next(&miter) && resid > 0) {
- size_t len = min(miter.length, resid);
- void *start = dif_store(sector);
+ size_t len = min_t(size_t, miter.length, resid);
+ void *start = dif_store(sip, sector);
size_t rest = 0;
if (dif_store_end < start + len)
@@ -2629,30 +3077,33 @@
sg_miter_stop(&miter);
}
-static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
+static int prot_verify_read(struct scsi_cmnd *scp, sector_t start_sec,
unsigned int sectors, u32 ei_lba)
{
unsigned int i;
- struct t10_pi_tuple *sdt;
sector_t sector;
+ struct sdeb_store_info *sip = devip2sip((struct sdebug_dev_info *)
+ scp->device->hostdata, true);
+ struct t10_pi_tuple *sdt;
for (i = 0; i < sectors; i++, ei_lba++) {
int ret;
sector = start_sec + i;
- sdt = dif_store(sector);
+ sdt = dif_store(sip, sector);
if (sdt->app_tag == cpu_to_be16(0xffff))
continue;
- ret = dif_verify(sdt, lba2fake_store(sector), sector, ei_lba);
+ ret = dif_verify(sdt, lba2fake_store(sip, sector), sector,
+ ei_lba);
if (ret) {
dif_errors++;
return ret;
}
}
- dif_copy_prot(SCpnt, start_sec, sectors, true);
+ dif_copy_prot(scp, start_sec, sectors, true);
dix_reads++;
return 0;
@@ -2660,14 +3111,14 @@
static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
{
- u8 *cmd = scp->cmnd;
- struct sdebug_queued_cmd *sqcp;
- u64 lba;
+ bool check_prot;
u32 num;
u32 ei_lba;
- unsigned long iflags;
int ret;
- bool check_prot;
+ u64 lba;
+ struct sdeb_store_info *sip = devip2sip(devip, true);
+ rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
+ u8 *cmd = scp->cmnd;
switch (cmd[0]) {
case READ_16:
@@ -2720,15 +3171,11 @@
sdev_printk(KERN_ERR, scp->device, "Unprotected RD "
"to DIF device\n");
}
- if (unlikely(sdebug_any_injecting_opt)) {
- sqcp = (struct sdebug_queued_cmd *)scp->host_scribble;
-
- if (sqcp) {
- if (sqcp->inj_short)
- num /= 2;
- }
- } else
- sqcp = NULL;
+ if (unlikely((sdebug_opts & SDEBUG_OPT_SHORT_TRANSFER) &&
+ atomic_read(&sdeb_inject_pending))) {
+ num /= 2;
+ atomic_set(&sdeb_inject_pending, 0);
+ }
ret = check_device_access_params(scp, lba, num, false);
if (ret)
@@ -2749,41 +3196,40 @@
return check_condition_result;
}
- read_lock_irqsave(&atomic_rw, iflags);
+ read_lock(macc_lckp);
/* DIX + T10 DIF */
if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) {
int prot_ret = prot_verify_read(scp, lba, num, ei_lba);
if (prot_ret) {
- read_unlock_irqrestore(&atomic_rw, iflags);
+ read_unlock(macc_lckp);
mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, prot_ret);
return illegal_condition_result;
}
}
- ret = do_device_access(scp, 0, lba, num, false);
- read_unlock_irqrestore(&atomic_rw, iflags);
+ ret = do_device_access(sip, scp, 0, lba, num, false);
+ read_unlock(macc_lckp);
if (unlikely(ret == -1))
return DID_ERROR << 16;
scsi_set_resid(scp, scsi_bufflen(scp) - ret);
- if (unlikely(sqcp)) {
- if (sqcp->inj_recovered) {
- mk_sense_buffer(scp, RECOVERED_ERROR,
- THRESHOLD_EXCEEDED, 0);
+ if (unlikely((sdebug_opts & SDEBUG_OPT_RECOV_DIF_DIX) &&
+ atomic_read(&sdeb_inject_pending))) {
+ if (sdebug_opts & SDEBUG_OPT_RECOVERED_ERR) {
+ mk_sense_buffer(scp, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0);
+ atomic_set(&sdeb_inject_pending, 0);
return check_condition_result;
- } else if (sqcp->inj_transport) {
- mk_sense_buffer(scp, ABORTED_COMMAND,
- TRANSPORT_PROBLEM, ACK_NAK_TO);
- return check_condition_result;
- } else if (sqcp->inj_dif) {
+ } else if (sdebug_opts & SDEBUG_OPT_DIF_ERR) {
/* Logical block guard check failed */
mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
+ atomic_set(&sdeb_inject_pending, 0);
return illegal_condition_result;
- } else if (sqcp->inj_dix) {
+ } else if (SDEBUG_OPT_DIX_ERR & sdebug_opts) {
mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
+ atomic_set(&sdeb_inject_pending, 0);
return illegal_condition_result;
}
}
@@ -2901,7 +3347,8 @@
return lba;
}
-static unsigned int map_state(sector_t lba, unsigned int *num)
+static unsigned int map_state(struct sdeb_store_info *sip, sector_t lba,
+ unsigned int *num)
{
sector_t end;
unsigned int mapped;
@@ -2909,19 +3356,20 @@
unsigned long next;
index = lba_to_map_index(lba);
- mapped = test_bit(index, map_storep);
+ mapped = test_bit(index, sip->map_storep);
if (mapped)
- next = find_next_zero_bit(map_storep, map_size, index);
+ next = find_next_zero_bit(sip->map_storep, map_size, index);
else
- next = find_next_bit(map_storep, map_size, index);
+ next = find_next_bit(sip->map_storep, map_size, index);
end = min_t(sector_t, sdebug_store_sectors, map_index_to_lba(next));
*num = end - lba;
return mapped;
}
-static void map_region(sector_t lba, unsigned int len)
+static void map_region(struct sdeb_store_info *sip, sector_t lba,
+ unsigned int len)
{
sector_t end = lba + len;
@@ -2929,15 +3377,17 @@
unsigned long index = lba_to_map_index(lba);
if (index < map_size)
- set_bit(index, map_storep);
+ set_bit(index, sip->map_storep);
lba = map_index_to_lba(index + 1);
}
}
-static void unmap_region(sector_t lba, unsigned int len)
+static void unmap_region(struct sdeb_store_info *sip, sector_t lba,
+ unsigned int len)
{
sector_t end = lba + len;
+ u8 *fsp = sip->storep;
while (lba < end) {
unsigned long index = lba_to_map_index(lba);
@@ -2945,17 +3395,16 @@
if (lba == map_index_to_lba(index) &&
lba + sdebug_unmap_granularity <= end &&
index < map_size) {
- clear_bit(index, map_storep);
+ clear_bit(index, sip->map_storep);
if (sdebug_lbprz) { /* for LBPRZ=2 return 0xff_s */
- memset(fake_storep +
- lba * sdebug_sector_size,
+ memset(fsp + lba * sdebug_sector_size,
(sdebug_lbprz & 1) ? 0 : 0xff,
sdebug_sector_size *
sdebug_unmap_granularity);
}
- if (dif_storep) {
- memset(dif_storep + lba, 0xff,
- sizeof(*dif_storep) *
+ if (sip->dif_storep) {
+ memset(sip->dif_storep + lba, 0xff,
+ sizeof(*sip->dif_storep) *
sdebug_unmap_granularity);
}
}
@@ -2965,13 +3414,14 @@
static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
{
- u8 *cmd = scp->cmnd;
- u64 lba;
+ bool check_prot;
u32 num;
u32 ei_lba;
- unsigned long iflags;
int ret;
- bool check_prot;
+ u64 lba;
+ struct sdeb_store_info *sip = devip2sip(devip, true);
+ rwlock_t *macc_lckp = &sip->macc_lck;
+ u8 *cmd = scp->cmnd;
switch (cmd[0]) {
case WRITE_16:
@@ -3024,26 +3474,32 @@
sdev_printk(KERN_ERR, scp->device, "Unprotected WR "
"to DIF device\n");
}
+
+ write_lock(macc_lckp);
ret = check_device_access_params(scp, lba, num, true);
- if (ret)
+ if (ret) {
+ write_unlock(macc_lckp);
return ret;
- write_lock_irqsave(&atomic_rw, iflags);
+ }
/* DIX + T10 DIF */
if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) {
int prot_ret = prot_verify_write(scp, lba, num, ei_lba);
if (prot_ret) {
- write_unlock_irqrestore(&atomic_rw, iflags);
+ write_unlock(macc_lckp);
mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, prot_ret);
return illegal_condition_result;
}
}
- ret = do_device_access(scp, 0, lba, num, true);
+ ret = do_device_access(sip, scp, 0, lba, num, true);
if (unlikely(scsi_debug_lbp()))
- map_region(lba, num);
- write_unlock_irqrestore(&atomic_rw, iflags);
+ map_region(sip, lba, num);
+ /* If ZBC zone then bump its write pointer */
+ if (sdebug_dev_is_zoned(devip))
+ zbc_inc_wp(devip, lba, num);
+ write_unlock(macc_lckp);
if (unlikely(-1 == ret))
return DID_ERROR << 16;
else if (unlikely(sdebug_verbose &&
@@ -3052,23 +3508,21 @@
"%s: write: cdb indicated=%u, IO sent=%d bytes\n",
my_name, num * sdebug_sector_size, ret);
- if (unlikely(sdebug_any_injecting_opt)) {
- struct sdebug_queued_cmd *sqcp =
- (struct sdebug_queued_cmd *)scp->host_scribble;
-
- if (sqcp) {
- if (sqcp->inj_recovered) {
- mk_sense_buffer(scp, RECOVERED_ERROR,
- THRESHOLD_EXCEEDED, 0);
- return check_condition_result;
- } else if (sqcp->inj_dif) {
- /* Logical block guard check failed */
- mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
- return illegal_condition_result;
- } else if (sqcp->inj_dix) {
- mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
- return illegal_condition_result;
- }
+ if (unlikely((sdebug_opts & SDEBUG_OPT_RECOV_DIF_DIX) &&
+ atomic_read(&sdeb_inject_pending))) {
+ if (sdebug_opts & SDEBUG_OPT_RECOVERED_ERR) {
+ mk_sense_buffer(scp, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0);
+ atomic_set(&sdeb_inject_pending, 0);
+ return check_condition_result;
+ } else if (sdebug_opts & SDEBUG_OPT_DIF_ERR) {
+ /* Logical block guard check failed */
+ mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
+ atomic_set(&sdeb_inject_pending, 0);
+ return illegal_condition_result;
+ } else if (sdebug_opts & SDEBUG_OPT_DIX_ERR) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
+ atomic_set(&sdeb_inject_pending, 0);
+ return illegal_condition_result;
}
}
return 0;
@@ -3084,13 +3538,14 @@
u8 *cmd = scp->cmnd;
u8 *lrdp = NULL;
u8 *up;
+ struct sdeb_store_info *sip = devip2sip(devip, true);
+ rwlock_t *macc_lckp = &sip->macc_lck;
u8 wrprotect;
u16 lbdof, num_lrd, k;
u32 num, num_by, bt_len, lbdof_blen, sg_off, cum_lb;
u32 lb_size = sdebug_sector_size;
u32 ei_lba;
u64 lba;
- unsigned long iflags;
int ret, res;
bool is_16;
static const u32 lrd_size = 32; /* + parameter list header size */
@@ -3152,7 +3607,7 @@
goto err_out;
}
- write_lock_irqsave(&atomic_rw, iflags);
+ write_lock(macc_lckp);
sg_off = lbdof_blen;
/* Spec says Buffer xfer Length field in number of LBs in dout */
cum_lb = 0;
@@ -3195,9 +3650,12 @@
}
}
- ret = do_device_access(scp, sg_off, lba, num, true);
+ ret = do_device_access(sip, scp, sg_off, lba, num, true);
+ /* If ZBC zone then bump its write pointer */
+ if (sdebug_dev_is_zoned(devip))
+ zbc_inc_wp(devip, lba, num);
if (unlikely(scsi_debug_lbp()))
- map_region(lba, num);
+ map_region(sip, lba, num);
if (unlikely(-1 == ret)) {
ret = DID_ERROR << 16;
goto err_out_unlock;
@@ -3206,28 +3664,24 @@
"%s: write: cdb indicated=%u, IO sent=%d bytes\n",
my_name, num_by, ret);
- if (unlikely(sdebug_any_injecting_opt)) {
- struct sdebug_queued_cmd *sqcp =
- (struct sdebug_queued_cmd *)scp->host_scribble;
-
- if (sqcp) {
- if (sqcp->inj_recovered) {
- mk_sense_buffer(scp, RECOVERED_ERROR,
- THRESHOLD_EXCEEDED, 0);
- ret = illegal_condition_result;
- goto err_out_unlock;
- } else if (sqcp->inj_dif) {
- /* Logical block guard check failed */
- mk_sense_buffer(scp, ABORTED_COMMAND,
- 0x10, 1);
- ret = illegal_condition_result;
- goto err_out_unlock;
- } else if (sqcp->inj_dix) {
- mk_sense_buffer(scp, ILLEGAL_REQUEST,
- 0x10, 1);
- ret = illegal_condition_result;
- goto err_out_unlock;
- }
+ if (unlikely((sdebug_opts & SDEBUG_OPT_RECOV_DIF_DIX) &&
+ atomic_read(&sdeb_inject_pending))) {
+ if (sdebug_opts & SDEBUG_OPT_RECOVERED_ERR) {
+ mk_sense_buffer(scp, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0);
+ atomic_set(&sdeb_inject_pending, 0);
+ ret = check_condition_result;
+ goto err_out_unlock;
+ } else if (sdebug_opts & SDEBUG_OPT_DIF_ERR) {
+ /* Logical block guard check failed */
+ mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
+ atomic_set(&sdeb_inject_pending, 0);
+ ret = illegal_condition_result;
+ goto err_out_unlock;
+ } else if (sdebug_opts & SDEBUG_OPT_DIX_ERR) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
+ atomic_set(&sdeb_inject_pending, 0);
+ ret = illegal_condition_result;
+ goto err_out_unlock;
}
}
sg_off += num_by;
@@ -3235,7 +3689,7 @@
}
ret = 0;
err_out_unlock:
- write_unlock_irqrestore(&atomic_rw, iflags);
+ write_unlock(macc_lckp);
err_out:
kfree(lrdp);
return ret;
@@ -3244,27 +3698,35 @@
static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
u32 ei_lba, bool unmap, bool ndob)
{
- int ret;
- unsigned long iflags;
+ struct scsi_device *sdp = scp->device;
+ struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdp->hostdata;
unsigned long long i;
- u32 lb_size = sdebug_sector_size;
u64 block, lbaa;
+ u32 lb_size = sdebug_sector_size;
+ int ret;
+ struct sdeb_store_info *sip = devip2sip((struct sdebug_dev_info *)
+ scp->device->hostdata, true);
+ rwlock_t *macc_lckp = &sip->macc_lck;
u8 *fs1p;
+ u8 *fsp;
+
+ write_lock(macc_lckp);
ret = check_device_access_params(scp, lba, num, true);
- if (ret)
+ if (ret) {
+ write_unlock(macc_lckp);
return ret;
-
- write_lock_irqsave(&atomic_rw, iflags);
+ }
if (unmap && scsi_debug_lbp()) {
- unmap_region(lba, num);
+ unmap_region(sip, lba, num);
goto out;
}
lbaa = lba;
block = do_div(lbaa, sdebug_store_sectors);
/* if ndob then zero 1 logical block, else fetch 1 logical block */
- fs1p = fake_storep + (block * lb_size);
+ fsp = sip->storep;
+ fs1p = fsp + (block * lb_size);
if (ndob) {
memset(fs1p, 0, lb_size);
ret = 0;
@@ -3272,7 +3734,7 @@
ret = fetch_to_dev_buffer(scp, fs1p, lb_size);
if (-1 == ret) {
- write_unlock_irqrestore(&atomic_rw, iflags);
+ write_unlock(&sip->macc_lck);
return DID_ERROR << 16;
} else if (sdebug_verbose && !ndob && (ret < lb_size))
sdev_printk(KERN_INFO, scp->device,
@@ -3283,12 +3745,15 @@
for (i = 1 ; i < num ; i++) {
lbaa = lba + i;
block = do_div(lbaa, sdebug_store_sectors);
- memmove(fake_storep + (block * lb_size), fs1p, lb_size);
+ memmove(fsp + (block * lb_size), fs1p, lb_size);
}
if (scsi_debug_lbp())
- map_region(lba, num);
+ map_region(sip, lba, num);
+ /* If ZBC zone then bump its write pointer */
+ if (sdebug_dev_is_zoned(devip))
+ zbc_inc_wp(devip, lba, num);
out:
- write_unlock_irqrestore(&atomic_rw, iflags);
+ write_unlock(macc_lckp);
return 0;
}
@@ -3400,12 +3865,12 @@
{
u8 *cmd = scp->cmnd;
u8 *arr;
- u8 *fake_storep_hold;
+ struct sdeb_store_info *sip = devip2sip(devip, true);
+ rwlock_t *macc_lckp = &sip->macc_lck;
u64 lba;
u32 dnum;
u32 lb_size = sdebug_sector_size;
u8 num;
- unsigned long iflags;
int ret;
int retval = 0;
@@ -3434,14 +3899,9 @@
return check_condition_result;
}
- write_lock_irqsave(&atomic_rw, iflags);
+ write_lock(macc_lckp);
- /* trick do_device_access() to fetch both compare and write buffers
- * from data-in into arr. Safe (atomic) since write_lock held. */
- fake_storep_hold = fake_storep;
- fake_storep = arr;
- ret = do_device_access(scp, 0, 0, dnum, true);
- fake_storep = fake_storep_hold;
+ ret = do_dout_fetch(scp, dnum, arr);
if (ret == -1) {
retval = DID_ERROR << 16;
goto cleanup;
@@ -3449,15 +3909,15 @@
sdev_printk(KERN_INFO, scp->device, "%s: compare_write: cdb "
"indicated=%u, IO sent=%d bytes\n", my_name,
dnum * lb_size, ret);
- if (!comp_write_worker(lba, num, arr)) {
+ if (!comp_write_worker(sip, lba, num, arr, false)) {
mk_sense_buffer(scp, MISCOMPARE, MISCOMPARE_VERIFY_ASC, 0);
retval = check_condition_result;
goto cleanup;
}
if (scsi_debug_lbp())
- map_region(lba, num);
+ map_region(sip, lba, num);
cleanup:
- write_unlock_irqrestore(&atomic_rw, iflags);
+ write_unlock(macc_lckp);
kfree(arr);
return retval;
}
@@ -3472,10 +3932,10 @@
{
unsigned char *buf;
struct unmap_block_desc *desc;
+ struct sdeb_store_info *sip = devip2sip(devip, true);
+ rwlock_t *macc_lckp = &sip->macc_lck;
unsigned int i, payload_len, descriptors;
int ret;
- unsigned long iflags;
-
if (!scsi_debug_lbp())
return 0; /* fib and say its done */
@@ -3502,7 +3962,7 @@
desc = (void *)&buf[8];
- write_lock_irqsave(&atomic_rw, iflags);
+ write_lock(macc_lckp);
for (i = 0 ; i < descriptors ; i++) {
unsigned long long lba = get_unaligned_be64(&desc[i].lba);
@@ -3512,13 +3972,13 @@
if (ret)
goto out;
- unmap_region(lba, num);
+ unmap_region(sip, lba, num);
}
ret = 0;
out:
- write_unlock_irqrestore(&atomic_rw, iflags);
+ write_unlock(macc_lckp);
kfree(buf);
return ret;
@@ -3532,8 +3992,8 @@
u8 *cmd = scp->cmnd;
u64 lba;
u32 alloc_len, mapped, num;
- u8 arr[SDEBUG_GET_LBA_STATUS_LEN];
int ret;
+ u8 arr[SDEBUG_GET_LBA_STATUS_LEN];
lba = get_unaligned_be64(cmd + 2);
alloc_len = get_unaligned_be32(cmd + 10);
@@ -3545,9 +4005,11 @@
if (ret)
return ret;
- if (scsi_debug_lbp())
- mapped = map_state(lba, &num);
- else {
+ if (scsi_debug_lbp()) {
+ struct sdeb_store_info *sip = devip2sip(devip, true);
+
+ mapped = map_state(sip, lba, &num);
+ } else {
mapped = 1;
/* following just in case virtual_gb changed */
sdebug_capacity = get_sdebug_capacity();
@@ -3585,13 +4047,63 @@
mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
return check_condition_result;
}
- if (!write_since_sync || cmd[1] & 0x2)
+ if (!write_since_sync || (cmd[1] & 0x2))
res = SDEG_RES_IMMED_MASK;
else /* delay if write_since_sync and IMMED clear */
write_since_sync = false;
return res;
}
+/*
+ * Assuming the LBA+num_blocks is not out-of-range, this function will return
+ * CONDITION MET if the specified blocks will/have fitted in the cache, and
+ * a GOOD status otherwise. Model a disk with a big cache and yield
+ * CONDITION MET. Actually tries to bring range in main memory into the
+ * cache associated with the CPU(s).
+ */
+static int resp_pre_fetch(struct scsi_cmnd *scp,
+ struct sdebug_dev_info *devip)
+{
+ int res = 0;
+ u64 lba;
+ u64 block, rest = 0;
+ u32 nblks;
+ u8 *cmd = scp->cmnd;
+ struct sdeb_store_info *sip = devip2sip(devip, true);
+ rwlock_t *macc_lckp = &sip->macc_lck;
+ u8 *fsp = sip->storep;
+
+ if (cmd[0] == PRE_FETCH) { /* 10 byte cdb */
+ lba = get_unaligned_be32(cmd + 2);
+ nblks = get_unaligned_be16(cmd + 7);
+ } else { /* PRE-FETCH(16) */
+ lba = get_unaligned_be64(cmd + 2);
+ nblks = get_unaligned_be32(cmd + 10);
+ }
+ if (lba + nblks > sdebug_capacity) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
+ return check_condition_result;
+ }
+ if (!fsp)
+ goto fini;
+ /* PRE-FETCH spec says nothing about LBP or PI so skip them */
+ block = do_div(lba, sdebug_store_sectors);
+ if (block + nblks > sdebug_store_sectors)
+ rest = block + nblks - sdebug_store_sectors;
+
+ /* Try to bring the PRE-FETCH range into CPU's cache */
+ read_lock(macc_lckp);
+ prefetch_range(fsp + (sdebug_sector_size * block),
+ (nblks - rest) * sdebug_sector_size);
+ if (rest)
+ prefetch_range(fsp, rest * sdebug_sector_size);
+ read_unlock(macc_lckp);
+fini:
+ if (cmd[1] & 0x2)
+ res = SDEG_RES_IMMED_MASK;
+ return res | condition_met_result;
+}
+
#define RL_BUCKET_ELEMS 8
/* Even though each pseudo target has a REPORT LUNS "well known logical unit"
@@ -3675,6 +4187,8 @@
if ((k * RL_BUCKET_ELEMS) + j > lun_cnt)
break;
int_to_scsilun(lun++, lun_p);
+ if (lun > 1 && sdebug_lun_am == SAM_LUN_AM_FLAT)
+ lun_p->scsi_lun[0] |= 0x40;
}
if (j < RL_BUCKET_ELEMS)
break;
@@ -3693,17 +4207,530 @@
return res;
}
+static int resp_verify(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+{
+ bool is_bytchk3 = false;
+ u8 bytchk;
+ int ret, j;
+ u32 vnum, a_num, off;
+ const u32 lb_size = sdebug_sector_size;
+ u64 lba;
+ u8 *arr;
+ u8 *cmd = scp->cmnd;
+ struct sdeb_store_info *sip = devip2sip(devip, true);
+ rwlock_t *macc_lckp = &sip->macc_lck;
+
+ bytchk = (cmd[1] >> 1) & 0x3;
+ if (bytchk == 0) {
+ return 0; /* always claim internal verify okay */
+ } else if (bytchk == 2) {
+ mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 2);
+ return check_condition_result;
+ } else if (bytchk == 3) {
+ is_bytchk3 = true; /* 1 block sent, compared repeatedly */
+ }
+ switch (cmd[0]) {
+ case VERIFY_16:
+ lba = get_unaligned_be64(cmd + 2);
+ vnum = get_unaligned_be32(cmd + 10);
+ break;
+ case VERIFY: /* is VERIFY(10) */
+ lba = get_unaligned_be32(cmd + 2);
+ vnum = get_unaligned_be16(cmd + 7);
+ break;
+ default:
+ mk_sense_invalid_opcode(scp);
+ return check_condition_result;
+ }
+ if (vnum == 0)
+ return 0; /* not an error */
+ a_num = is_bytchk3 ? 1 : vnum;
+ /* Treat following check like one for read (i.e. no write) access */
+ ret = check_device_access_params(scp, lba, a_num, false);
+ if (ret)
+ return ret;
+
+ arr = kcalloc(lb_size, vnum, GFP_ATOMIC);
+ if (!arr) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
+ INSUFF_RES_ASCQ);
+ return check_condition_result;
+ }
+ /* Not changing store, so only need read access */
+ read_lock(macc_lckp);
+
+ ret = do_dout_fetch(scp, a_num, arr);
+ if (ret == -1) {
+ ret = DID_ERROR << 16;
+ goto cleanup;
+ } else if (sdebug_verbose && (ret < (a_num * lb_size))) {
+ sdev_printk(KERN_INFO, scp->device,
+ "%s: %s: cdb indicated=%u, IO sent=%d bytes\n",
+ my_name, __func__, a_num * lb_size, ret);
+ }
+ if (is_bytchk3) {
+ for (j = 1, off = lb_size; j < vnum; ++j, off += lb_size)
+ memcpy(arr + off, arr, lb_size);
+ }
+ ret = 0;
+ if (!comp_write_worker(sip, lba, vnum, arr, true)) {
+ mk_sense_buffer(scp, MISCOMPARE, MISCOMPARE_VERIFY_ASC, 0);
+ ret = check_condition_result;
+ goto cleanup;
+ }
+cleanup:
+ read_unlock(macc_lckp);
+ kfree(arr);
+ return ret;
+}
+
+#define RZONES_DESC_HD 64
+
+/* Report zones depending on start LBA nad reporting options */
+static int resp_report_zones(struct scsi_cmnd *scp,
+ struct sdebug_dev_info *devip)
+{
+ unsigned int i, max_zones, rep_max_zones, nrz = 0;
+ int ret = 0;
+ u32 alloc_len, rep_opts, rep_len;
+ bool partial;
+ u64 lba, zs_lba;
+ u8 *arr = NULL, *desc;
+ u8 *cmd = scp->cmnd;
+ struct sdeb_zone_state *zsp;
+ struct sdeb_store_info *sip = devip2sip(devip, false);
+ rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
+
+ if (!sdebug_dev_is_zoned(devip)) {
+ mk_sense_invalid_opcode(scp);
+ return check_condition_result;
+ }
+ zs_lba = get_unaligned_be64(cmd + 2);
+ alloc_len = get_unaligned_be32(cmd + 10);
+ if (alloc_len == 0)
+ return 0; /* not an error */
+ rep_opts = cmd[14] & 0x3f;
+ partial = cmd[14] & 0x80;
+
+ if (zs_lba >= sdebug_capacity) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
+ return check_condition_result;
+ }
+
+ max_zones = devip->nr_zones - (zs_lba >> devip->zsize_shift);
+ rep_max_zones = min((alloc_len - 64) >> ilog2(RZONES_DESC_HD),
+ max_zones);
+
+ arr = kzalloc(alloc_len, GFP_ATOMIC);
+ if (!arr) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
+ INSUFF_RES_ASCQ);
+ return check_condition_result;
+ }
+
+ read_lock(macc_lckp);
+
+ desc = arr + 64;
+ for (i = 0; i < max_zones; i++) {
+ lba = zs_lba + devip->zsize * i;
+ if (lba > sdebug_capacity)
+ break;
+ zsp = zbc_zone(devip, lba);
+ switch (rep_opts) {
+ case 0x00:
+ /* All zones */
+ break;
+ case 0x01:
+ /* Empty zones */
+ if (zsp->z_cond != ZC1_EMPTY)
+ continue;
+ break;
+ case 0x02:
+ /* Implicit open zones */
+ if (zsp->z_cond != ZC2_IMPLICIT_OPEN)
+ continue;
+ break;
+ case 0x03:
+ /* Explicit open zones */
+ if (zsp->z_cond != ZC3_EXPLICIT_OPEN)
+ continue;
+ break;
+ case 0x04:
+ /* Closed zones */
+ if (zsp->z_cond != ZC4_CLOSED)
+ continue;
+ break;
+ case 0x05:
+ /* Full zones */
+ if (zsp->z_cond != ZC5_FULL)
+ continue;
+ break;
+ case 0x06:
+ case 0x07:
+ case 0x10:
+ /*
+ * Read-only, offline, reset WP recommended are
+ * not emulated: no zones to report;
+ */
+ continue;
+ case 0x11:
+ /* non-seq-resource set */
+ if (!zsp->z_non_seq_resource)
+ continue;
+ break;
+ case 0x3f:
+ /* Not write pointer (conventional) zones */
+ if (!zbc_zone_is_conv(zsp))
+ continue;
+ break;
+ default:
+ mk_sense_buffer(scp, ILLEGAL_REQUEST,
+ INVALID_FIELD_IN_CDB, 0);
+ ret = check_condition_result;
+ goto fini;
+ }
+
+ if (nrz < rep_max_zones) {
+ /* Fill zone descriptor */
+ desc[0] = zsp->z_type;
+ desc[1] = zsp->z_cond << 4;
+ if (zsp->z_non_seq_resource)
+ desc[1] |= 1 << 1;
+ put_unaligned_be64((u64)zsp->z_size, desc + 8);
+ put_unaligned_be64((u64)zsp->z_start, desc + 16);
+ put_unaligned_be64((u64)zsp->z_wp, desc + 24);
+ desc += 64;
+ }
+
+ if (partial && nrz >= rep_max_zones)
+ break;
+
+ nrz++;
+ }
+
+ /* Report header */
+ put_unaligned_be32(nrz * RZONES_DESC_HD, arr + 0);
+ put_unaligned_be64(sdebug_capacity - 1, arr + 8);
+
+ rep_len = (unsigned long)desc - (unsigned long)arr;
+ ret = fill_from_dev_buffer(scp, arr, min_t(u32, alloc_len, rep_len));
+
+fini:
+ read_unlock(macc_lckp);
+ kfree(arr);
+ return ret;
+}
+
+/* Logic transplanted from tcmu-runner, file_zbc.c */
+static void zbc_open_all(struct sdebug_dev_info *devip)
+{
+ struct sdeb_zone_state *zsp = &devip->zstate[0];
+ unsigned int i;
+
+ for (i = 0; i < devip->nr_zones; i++, zsp++) {
+ if (zsp->z_cond == ZC4_CLOSED)
+ zbc_open_zone(devip, &devip->zstate[i], true);
+ }
+}
+
+static int resp_open_zone(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+{
+ int res = 0;
+ u64 z_id;
+ enum sdebug_z_cond zc;
+ u8 *cmd = scp->cmnd;
+ struct sdeb_zone_state *zsp;
+ bool all = cmd[14] & 0x01;
+ struct sdeb_store_info *sip = devip2sip(devip, false);
+ rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
+
+ if (!sdebug_dev_is_zoned(devip)) {
+ mk_sense_invalid_opcode(scp);
+ return check_condition_result;
+ }
+
+ write_lock(macc_lckp);
+
+ if (all) {
+ /* Check if all closed zones can be open */
+ if (devip->max_open &&
+ devip->nr_exp_open + devip->nr_closed > devip->max_open) {
+ mk_sense_buffer(scp, DATA_PROTECT, INSUFF_RES_ASC,
+ INSUFF_ZONE_ASCQ);
+ res = check_condition_result;
+ goto fini;
+ }
+ /* Open all closed zones */
+ zbc_open_all(devip);
+ goto fini;
+ }
+
+ /* Open the specified zone */
+ z_id = get_unaligned_be64(cmd + 2);
+ if (z_id >= sdebug_capacity) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
+ res = check_condition_result;
+ goto fini;
+ }
+
+ zsp = zbc_zone(devip, z_id);
+ if (z_id != zsp->z_start) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+ res = check_condition_result;
+ goto fini;
+ }
+ if (zbc_zone_is_conv(zsp)) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+ res = check_condition_result;
+ goto fini;
+ }
+
+ zc = zsp->z_cond;
+ if (zc == ZC3_EXPLICIT_OPEN || zc == ZC5_FULL)
+ goto fini;
+
+ if (devip->max_open && devip->nr_exp_open >= devip->max_open) {
+ mk_sense_buffer(scp, DATA_PROTECT, INSUFF_RES_ASC,
+ INSUFF_ZONE_ASCQ);
+ res = check_condition_result;
+ goto fini;
+ }
+
+ zbc_open_zone(devip, zsp, true);
+fini:
+ write_unlock(macc_lckp);
+ return res;
+}
+
+static void zbc_close_all(struct sdebug_dev_info *devip)
+{
+ unsigned int i;
+
+ for (i = 0; i < devip->nr_zones; i++)
+ zbc_close_zone(devip, &devip->zstate[i]);
+}
+
+static int resp_close_zone(struct scsi_cmnd *scp,
+ struct sdebug_dev_info *devip)
+{
+ int res = 0;
+ u64 z_id;
+ u8 *cmd = scp->cmnd;
+ struct sdeb_zone_state *zsp;
+ bool all = cmd[14] & 0x01;
+ struct sdeb_store_info *sip = devip2sip(devip, false);
+ rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
+
+ if (!sdebug_dev_is_zoned(devip)) {
+ mk_sense_invalid_opcode(scp);
+ return check_condition_result;
+ }
+
+ write_lock(macc_lckp);
+
+ if (all) {
+ zbc_close_all(devip);
+ goto fini;
+ }
+
+ /* Close specified zone */
+ z_id = get_unaligned_be64(cmd + 2);
+ if (z_id >= sdebug_capacity) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
+ res = check_condition_result;
+ goto fini;
+ }
+
+ zsp = zbc_zone(devip, z_id);
+ if (z_id != zsp->z_start) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+ res = check_condition_result;
+ goto fini;
+ }
+ if (zbc_zone_is_conv(zsp)) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+ res = check_condition_result;
+ goto fini;
+ }
+
+ zbc_close_zone(devip, zsp);
+fini:
+ write_unlock(macc_lckp);
+ return res;
+}
+
+static void zbc_finish_zone(struct sdebug_dev_info *devip,
+ struct sdeb_zone_state *zsp, bool empty)
+{
+ enum sdebug_z_cond zc = zsp->z_cond;
+
+ if (zc == ZC4_CLOSED || zc == ZC2_IMPLICIT_OPEN ||
+ zc == ZC3_EXPLICIT_OPEN || (empty && zc == ZC1_EMPTY)) {
+ if (zc == ZC2_IMPLICIT_OPEN || zc == ZC3_EXPLICIT_OPEN)
+ zbc_close_zone(devip, zsp);
+ if (zsp->z_cond == ZC4_CLOSED)
+ devip->nr_closed--;
+ zsp->z_wp = zsp->z_start + zsp->z_size;
+ zsp->z_cond = ZC5_FULL;
+ }
+}
+
+static void zbc_finish_all(struct sdebug_dev_info *devip)
+{
+ unsigned int i;
+
+ for (i = 0; i < devip->nr_zones; i++)
+ zbc_finish_zone(devip, &devip->zstate[i], false);
+}
+
+static int resp_finish_zone(struct scsi_cmnd *scp,
+ struct sdebug_dev_info *devip)
+{
+ struct sdeb_zone_state *zsp;
+ int res = 0;
+ u64 z_id;
+ u8 *cmd = scp->cmnd;
+ bool all = cmd[14] & 0x01;
+ struct sdeb_store_info *sip = devip2sip(devip, false);
+ rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
+
+ if (!sdebug_dev_is_zoned(devip)) {
+ mk_sense_invalid_opcode(scp);
+ return check_condition_result;
+ }
+
+ write_lock(macc_lckp);
+
+ if (all) {
+ zbc_finish_all(devip);
+ goto fini;
+ }
+
+ /* Finish the specified zone */
+ z_id = get_unaligned_be64(cmd + 2);
+ if (z_id >= sdebug_capacity) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
+ res = check_condition_result;
+ goto fini;
+ }
+
+ zsp = zbc_zone(devip, z_id);
+ if (z_id != zsp->z_start) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+ res = check_condition_result;
+ goto fini;
+ }
+ if (zbc_zone_is_conv(zsp)) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+ res = check_condition_result;
+ goto fini;
+ }
+
+ zbc_finish_zone(devip, zsp, true);
+fini:
+ write_unlock(macc_lckp);
+ return res;
+}
+
+static void zbc_rwp_zone(struct sdebug_dev_info *devip,
+ struct sdeb_zone_state *zsp)
+{
+ enum sdebug_z_cond zc;
+ struct sdeb_store_info *sip = devip2sip(devip, false);
+
+ if (zbc_zone_is_conv(zsp))
+ return;
+
+ zc = zsp->z_cond;
+ if (zc == ZC2_IMPLICIT_OPEN || zc == ZC3_EXPLICIT_OPEN)
+ zbc_close_zone(devip, zsp);
+
+ if (zsp->z_cond == ZC4_CLOSED)
+ devip->nr_closed--;
+
+ if (zsp->z_wp > zsp->z_start)
+ memset(sip->storep + zsp->z_start * sdebug_sector_size, 0,
+ (zsp->z_wp - zsp->z_start) * sdebug_sector_size);
+
+ zsp->z_non_seq_resource = false;
+ zsp->z_wp = zsp->z_start;
+ zsp->z_cond = ZC1_EMPTY;
+}
+
+static void zbc_rwp_all(struct sdebug_dev_info *devip)
+{
+ unsigned int i;
+
+ for (i = 0; i < devip->nr_zones; i++)
+ zbc_rwp_zone(devip, &devip->zstate[i]);
+}
+
+static int resp_rwp_zone(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+{
+ struct sdeb_zone_state *zsp;
+ int res = 0;
+ u64 z_id;
+ u8 *cmd = scp->cmnd;
+ bool all = cmd[14] & 0x01;
+ struct sdeb_store_info *sip = devip2sip(devip, false);
+ rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
+
+ if (!sdebug_dev_is_zoned(devip)) {
+ mk_sense_invalid_opcode(scp);
+ return check_condition_result;
+ }
+
+ write_lock(macc_lckp);
+
+ if (all) {
+ zbc_rwp_all(devip);
+ goto fini;
+ }
+
+ z_id = get_unaligned_be64(cmd + 2);
+ if (z_id >= sdebug_capacity) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
+ res = check_condition_result;
+ goto fini;
+ }
+
+ zsp = zbc_zone(devip, z_id);
+ if (z_id != zsp->z_start) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+ res = check_condition_result;
+ goto fini;
+ }
+ if (zbc_zone_is_conv(zsp)) {
+ mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0);
+ res = check_condition_result;
+ goto fini;
+ }
+
+ zbc_rwp_zone(devip, zsp);
+fini:
+ write_unlock(macc_lckp);
+ return res;
+}
+
static struct sdebug_queue *get_queue(struct scsi_cmnd *cmnd)
{
+ u16 hwq;
u32 tag = blk_mq_unique_tag(cmnd->request);
- u16 hwq = blk_mq_unique_tag_to_hwq(tag);
+
+ hwq = blk_mq_unique_tag_to_hwq(tag);
pr_debug("tag=%#x, hwq=%d\n", tag, hwq);
if (WARN_ON_ONCE(hwq >= submit_queues))
hwq = 0;
+
return sdebug_q_arr + hwq;
}
+static u32 get_tag(struct scsi_cmnd *cmnd)
+{
+ return blk_mq_unique_tag(cmnd->request);
+}
+
/* Queued (deferred) command completions converge here. */
static void sdebug_q_cmd_complete(struct sdebug_defer *sd_dp)
{
@@ -3735,8 +4762,8 @@
scp = sqcp->a_cmnd;
if (unlikely(scp == NULL)) {
spin_unlock_irqrestore(&sqp->qc_lock, iflags);
- pr_err("scp is NULL, sqa_idx=%d, qc_idx=%d\n",
- sd_dp->sqa_idx, qc_idx);
+ pr_err("scp is NULL, sqa_idx=%d, qc_idx=%d, hc_idx=%d\n",
+ sd_dp->sqa_idx, qc_idx, sd_dp->hc_idx);
return;
}
devip = (struct sdebug_dev_info *)scp->device->hostdata;
@@ -3798,6 +4825,92 @@
static bool got_shared_uuid;
static uuid_t shared_uuid;
+static int sdebug_device_create_zones(struct sdebug_dev_info *devip)
+{
+ struct sdeb_zone_state *zsp;
+ sector_t capacity = get_sdebug_capacity();
+ sector_t zstart = 0;
+ unsigned int i;
+
+ /*
+ * Set the zone size: if sdeb_zbc_zone_size_mb is not set, figure out
+ * a zone size allowing for at least 4 zones on the device. Otherwise,
+ * use the specified zone size checking that at least 2 zones can be
+ * created for the device.
+ */
+ if (!sdeb_zbc_zone_size_mb) {
+ devip->zsize = (DEF_ZBC_ZONE_SIZE_MB * SZ_1M)
+ >> ilog2(sdebug_sector_size);
+ while (capacity < devip->zsize << 2 && devip->zsize >= 2)
+ devip->zsize >>= 1;
+ if (devip->zsize < 2) {
+ pr_err("Device capacity too small\n");
+ return -EINVAL;
+ }
+ } else {
+ if (!is_power_of_2(sdeb_zbc_zone_size_mb)) {
+ pr_err("Zone size is not a power of 2\n");
+ return -EINVAL;
+ }
+ devip->zsize = (sdeb_zbc_zone_size_mb * SZ_1M)
+ >> ilog2(sdebug_sector_size);
+ if (devip->zsize >= capacity) {
+ pr_err("Zone size too large for device capacity\n");
+ return -EINVAL;
+ }
+ }
+
+ devip->zsize_shift = ilog2(devip->zsize);
+ devip->nr_zones = (capacity + devip->zsize - 1) >> devip->zsize_shift;
+
+ if (sdeb_zbc_nr_conv >= devip->nr_zones) {
+ pr_err("Number of conventional zones too large\n");
+ return -EINVAL;
+ }
+ devip->nr_conv_zones = sdeb_zbc_nr_conv;
+
+ if (devip->zmodel == BLK_ZONED_HM) {
+ /* zbc_max_open_zones can be 0, meaning "not reported" */
+ if (sdeb_zbc_max_open >= devip->nr_zones - 1)
+ devip->max_open = (devip->nr_zones - 1) / 2;
+ else
+ devip->max_open = sdeb_zbc_max_open;
+ }
+
+ devip->zstate = kcalloc(devip->nr_zones,
+ sizeof(struct sdeb_zone_state), GFP_KERNEL);
+ if (!devip->zstate)
+ return -ENOMEM;
+
+ for (i = 0; i < devip->nr_zones; i++) {
+ zsp = &devip->zstate[i];
+
+ zsp->z_start = zstart;
+
+ if (i < devip->nr_conv_zones) {
+ zsp->z_type = ZBC_ZONE_TYPE_CNV;
+ zsp->z_cond = ZBC_NOT_WRITE_POINTER;
+ zsp->z_wp = (sector_t)-1;
+ } else {
+ if (devip->zmodel == BLK_ZONED_HM)
+ zsp->z_type = ZBC_ZONE_TYPE_SWR;
+ else
+ zsp->z_type = ZBC_ZONE_TYPE_SWP;
+ zsp->z_cond = ZC1_EMPTY;
+ zsp->z_wp = zsp->z_start;
+ }
+
+ if (zsp->z_start + devip->zsize < capacity)
+ zsp->z_size = devip->zsize;
+ else
+ zsp->z_size = capacity - zsp->z_start;
+
+ zstart += zsp->z_size;
+ }
+
+ return 0;
+}
+
static struct sdebug_dev_info *sdebug_device_create(
struct sdebug_host_info *sdbg_host, gfp_t flags)
{
@@ -3817,6 +4930,18 @@
}
}
devip->sdbg_host = sdbg_host;
+ if (sdeb_zbc_in_use) {
+ devip->zmodel = sdeb_zbc_model;
+ if (sdebug_device_create_zones(devip)) {
+ kfree(devip);
+ return NULL;
+ }
+ } else {
+ devip->zmodel = BLK_ZONED_NONE;
+ }
+ devip->sdbg_host = sdbg_host;
+ devip->create_ts = ktime_get_boottime();
+ atomic_set(&devip->stopped, (sdeb_tur_ms_to_ready > 0 ? 2 : 0));
list_add_tail(&devip->dev_list, &sdbg_host->dev_info_list);
}
return devip;
@@ -3833,6 +4958,7 @@
pr_err("Host info NULL\n");
return NULL;
}
+
list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) {
if ((devip->used) && (devip->channel == sdev->channel) &&
(devip->target == sdev->id) &&
@@ -4143,11 +5269,10 @@
return SUCCESS;
}
-static void __init sdebug_build_parts(unsigned char *ramp,
- unsigned long store_size)
+static void sdebug_build_parts(unsigned char *ramp, unsigned long store_size)
{
- struct partition *pp;
- int starts[SDEBUG_MAX_PARTS + 2];
+ struct msdos_partition *pp;
+ int starts[SDEBUG_MAX_PARTS + 2], max_part_secs;
int sectors_per_part, num_sectors, k;
int heads_by_sects, start_sec, end_sec;
@@ -4158,23 +5283,27 @@
sdebug_num_parts = SDEBUG_MAX_PARTS;
pr_warn("reducing partitions to %d\n", SDEBUG_MAX_PARTS);
}
- num_sectors = (int)sdebug_store_sectors;
+ num_sectors = (int)get_sdebug_capacity();
sectors_per_part = (num_sectors - sdebug_sectors_per)
/ sdebug_num_parts;
heads_by_sects = sdebug_heads * sdebug_sectors_per;
starts[0] = sdebug_sectors_per;
- for (k = 1; k < sdebug_num_parts; ++k)
+ max_part_secs = sectors_per_part;
+ for (k = 1; k < sdebug_num_parts; ++k) {
starts[k] = ((k * sectors_per_part) / heads_by_sects)
* heads_by_sects;
+ if (starts[k] - starts[k - 1] < max_part_secs)
+ max_part_secs = starts[k] - starts[k - 1];
+ }
starts[sdebug_num_parts] = num_sectors;
starts[sdebug_num_parts + 1] = 0;
ramp[510] = 0x55; /* magic partition markings */
ramp[511] = 0xAA;
- pp = (struct partition *)(ramp + 0x1be);
+ pp = (struct msdos_partition *)(ramp + 0x1be);
for (k = 0; starts[k + 1]; ++k, ++pp) {
start_sec = starts[k];
- end_sec = starts[k + 1] - 1;
+ end_sec = starts[k] + max_part_secs - 1;
pp->boot_ind = 0;
pp->cyl = start_sec / heads_by_sects;
@@ -4226,26 +5355,15 @@
atomic_set(&sdebug_a_tsf, 0);
}
-static void setup_inject(struct sdebug_queue *sqp,
- struct sdebug_queued_cmd *sqcp)
+static bool inject_on_this_cmd(void)
{
- if ((atomic_read(&sdebug_cmnd_count) % abs(sdebug_every_nth)) > 0) {
- if (sdebug_every_nth > 0)
- sqcp->inj_recovered = sqcp->inj_transport
- = sqcp->inj_dif
- = sqcp->inj_dix = sqcp->inj_short
- = sqcp->inj_host_busy = sqcp->inj_cmd_abort = 0;
- return;
- }
- sqcp->inj_recovered = !!(SDEBUG_OPT_RECOVERED_ERR & sdebug_opts);
- sqcp->inj_transport = !!(SDEBUG_OPT_TRANSPORT_ERR & sdebug_opts);
- sqcp->inj_dif = !!(SDEBUG_OPT_DIF_ERR & sdebug_opts);
- sqcp->inj_dix = !!(SDEBUG_OPT_DIX_ERR & sdebug_opts);
- sqcp->inj_short = !!(SDEBUG_OPT_SHORT_TRANSFER & sdebug_opts);
- sqcp->inj_host_busy = !!(SDEBUG_OPT_HOST_BUSY & sdebug_opts);
- sqcp->inj_cmd_abort = !!(SDEBUG_OPT_CMD_ABORT & sdebug_opts);
+ if (sdebug_every_nth == 0)
+ return false;
+ return (atomic_read(&sdebug_cmnd_count) % abs(sdebug_every_nth)) == 0;
}
+#define INCLUSIVE_TIMING_MAX_NS 1000000 /* 1 millisecond */
+
/* Complete the processing of the thread that queued a SCSI command to this
* driver. It either completes the command by calling cmnd_done() or
* schedules a hr timer or work queue then returns 0. Returns
@@ -4257,8 +5375,11 @@
struct sdebug_dev_info *),
int delta_jiff, int ndelay)
{
+ bool new_sd_dp;
+ bool inject = false;
+ int k, num_in_q, qdepth;
unsigned long iflags;
- int k, num_in_q, qdepth, inject;
+ u64 ns_from_boot = 0;
struct sdebug_queue *sqp;
struct sdebug_queued_cmd *sqcp;
struct scsi_device *sdp;
@@ -4274,7 +5395,6 @@
if (delta_jiff == 0)
goto respond_in_thread;
- /* schedule the response at a later time if resources permit */
sqp = get_queue(cmnd);
spin_lock_irqsave(&sqp->qc_lock, iflags);
if (unlikely(atomic_read(&sqp->blocked))) {
@@ -4283,7 +5403,6 @@
}
num_in_q = atomic_read(&devip->num_in_q);
qdepth = cmnd->device->queue_depth;
- inject = 0;
if (unlikely((qdepth > 0) && (num_in_q >= qdepth))) {
if (scsi_result) {
spin_unlock_irqrestore(&sqp->qc_lock, iflags);
@@ -4297,7 +5416,7 @@
(atomic_inc_return(&sdebug_a_tsf) >=
abs(sdebug_every_nth))) {
atomic_set(&sdebug_a_tsf, 0);
- inject = 1;
+ inject = true;
scsi_result = device_qfull_result;
}
}
@@ -4320,31 +5439,47 @@
else
return SCSI_MLQUEUE_HOST_BUSY;
}
- __set_bit(k, sqp->in_use_bm);
+ set_bit(k, sqp->in_use_bm);
atomic_inc(&devip->num_in_q);
sqcp = &sqp->qc_arr[k];
sqcp->a_cmnd = cmnd;
cmnd->host_scribble = (unsigned char *)sqcp;
sd_dp = sqcp->sd_dp;
spin_unlock_irqrestore(&sqp->qc_lock, iflags);
- if (unlikely(sdebug_every_nth && sdebug_any_injecting_opt))
- setup_inject(sqp, sqcp);
- if (sd_dp == NULL) {
+ if (!sd_dp) {
sd_dp = kzalloc(sizeof(*sd_dp), GFP_ATOMIC);
- if (sd_dp == NULL)
+ if (!sd_dp) {
+ atomic_dec(&devip->num_in_q);
+ clear_bit(k, sqp->in_use_bm);
return SCSI_MLQUEUE_HOST_BUSY;
+ }
+ new_sd_dp = true;
+ } else {
+ new_sd_dp = false;
}
- cmnd->result = pfp != NULL ? pfp(cmnd, devip) : 0;
+ /* Set the hostwide tag */
+ if (sdebug_host_max_queue)
+ sd_dp->hc_idx = get_tag(cmnd);
+
+ if (ndelay > 0 && ndelay < INCLUSIVE_TIMING_MAX_NS)
+ ns_from_boot = ktime_get_boottime_ns();
+
+ /* one of the resp_*() response functions is called here */
+ cmnd->result = pfp ? pfp(cmnd, devip) : 0;
if (cmnd->result & SDEG_RES_IMMED_MASK) {
- /*
- * This is the F_DELAY_OVERR case. No delay.
- */
cmnd->result &= ~SDEG_RES_IMMED_MASK;
delta_jiff = ndelay = 0;
}
if (cmnd->result == 0 && scsi_result != 0)
cmnd->result = scsi_result;
+ if (cmnd->result == 0 && unlikely(sdebug_opts & SDEBUG_OPT_TRANSPORT_ERR)) {
+ if (atomic_read(&sdeb_inject_pending)) {
+ mk_sense_buffer(cmnd, ABORTED_COMMAND, TRANSPORT_PROBLEM, ACK_NAK_TO);
+ atomic_set(&sdeb_inject_pending, 0);
+ cmnd->result = check_condition_result;
+ }
+ }
if (unlikely(sdebug_verbose && cmnd->result))
sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
@@ -4354,9 +5489,39 @@
ktime_t kt;
if (delta_jiff > 0) {
- kt = ns_to_ktime((u64)delta_jiff * (NSEC_PER_SEC / HZ));
- } else
- kt = ndelay;
+ u64 ns = jiffies_to_nsecs(delta_jiff);
+
+ if (sdebug_random && ns < U32_MAX) {
+ ns = prandom_u32_max((u32)ns);
+ } else if (sdebug_random) {
+ ns >>= 12; /* scale to 4 usec precision */
+ if (ns < U32_MAX) /* over 4 hours max */
+ ns = prandom_u32_max((u32)ns);
+ ns <<= 12;
+ }
+ kt = ns_to_ktime(ns);
+ } else { /* ndelay has a 4.2 second max */
+ kt = sdebug_random ? prandom_u32_max((u32)ndelay) :
+ (u32)ndelay;
+ if (ndelay < INCLUSIVE_TIMING_MAX_NS) {
+ u64 d = ktime_get_boottime_ns() - ns_from_boot;
+
+ if (kt <= d) { /* elapsed duration >= kt */
+ spin_lock_irqsave(&sqp->qc_lock, iflags);
+ sqcp->a_cmnd = NULL;
+ atomic_dec(&devip->num_in_q);
+ clear_bit(k, sqp->in_use_bm);
+ spin_unlock_irqrestore(&sqp->qc_lock, iflags);
+ if (new_sd_dp)
+ kfree(sd_dp);
+ /* call scsi_done() from this thread */
+ cmnd->scsi_done(cmnd);
+ return 0;
+ }
+ /* otherwise reduce kt by elapsed time */
+ kt -= d;
+ }
+ }
if (!sd_dp->init_hrt) {
sd_dp->init_hrt = true;
sqcp->sd_dp = sd_dp;
@@ -4369,6 +5534,7 @@
if (sdebug_statistics)
sd_dp->issuing_cpu = raw_smp_processor_id();
sd_dp->defer_t = SDEB_DEFER_HRT;
+ /* schedule the invocation of scsi_done() for a later time */
hrtimer_start(&sd_dp->hrt, kt, HRTIMER_MODE_REL_PINNED);
} else { /* jdelay < 0, use work queue */
if (!sd_dp->init_wq) {
@@ -4381,21 +5547,20 @@
if (sdebug_statistics)
sd_dp->issuing_cpu = raw_smp_processor_id();
sd_dp->defer_t = SDEB_DEFER_WQ;
- if (unlikely(sqcp->inj_cmd_abort))
+ if (unlikely((sdebug_opts & SDEBUG_OPT_CMD_ABORT) &&
+ atomic_read(&sdeb_inject_pending)))
sd_dp->aborted = true;
schedule_work(&sd_dp->ew.work);
- if (unlikely(sqcp->inj_cmd_abort)) {
- sdev_printk(KERN_INFO, sdp, "abort request tag %d\n",
- cmnd->request->tag);
+ if (unlikely((sdebug_opts & SDEBUG_OPT_CMD_ABORT) &&
+ atomic_read(&sdeb_inject_pending))) {
+ sdev_printk(KERN_INFO, sdp, "abort request tag %d\n", cmnd->request->tag);
blk_abort_request(cmnd->request);
+ atomic_set(&sdeb_inject_pending, 0);
}
}
- if (unlikely((SDEBUG_OPT_Q_NOISE & sdebug_opts) &&
- (scsi_result == device_qfull_result)))
- sdev_printk(KERN_INFO, sdp,
- "%s: num_in_q=%d +1, %s%s\n", __func__,
- num_in_q, (inject ? "<inject> " : ""),
- "status: TASK SET FULL");
+ if (unlikely((SDEBUG_OPT_Q_NOISE & sdebug_opts) && scsi_result == device_qfull_result))
+ sdev_printk(KERN_INFO, sdp, "%s: num_in_q=%d +1, %s%s\n", __func__,
+ num_in_q, (inject ? "<inject> " : ""), "status: TASK SET FULL");
return 0;
respond_in_thread: /* call back to mid-layer using invocation thread */
@@ -4426,55 +5591,67 @@
module_param_named(fake_rw, sdebug_fake_rw, int, S_IRUGO | S_IWUSR);
module_param_named(guard, sdebug_guard, uint, S_IRUGO);
module_param_named(host_lock, sdebug_host_lock, bool, S_IRUGO | S_IWUSR);
-module_param_string(inq_vendor, sdebug_inq_vendor_id,
- sizeof(sdebug_inq_vendor_id), S_IRUGO|S_IWUSR);
+module_param_named(host_max_queue, sdebug_host_max_queue, int, S_IRUGO);
module_param_string(inq_product, sdebug_inq_product_id,
- sizeof(sdebug_inq_product_id), S_IRUGO|S_IWUSR);
+ sizeof(sdebug_inq_product_id), S_IRUGO | S_IWUSR);
module_param_string(inq_rev, sdebug_inq_product_rev,
- sizeof(sdebug_inq_product_rev), S_IRUGO|S_IWUSR);
+ sizeof(sdebug_inq_product_rev), S_IRUGO | S_IWUSR);
+module_param_string(inq_vendor, sdebug_inq_vendor_id,
+ sizeof(sdebug_inq_vendor_id), S_IRUGO | S_IWUSR);
+module_param_named(lbprz, sdebug_lbprz, int, S_IRUGO);
module_param_named(lbpu, sdebug_lbpu, int, S_IRUGO);
module_param_named(lbpws, sdebug_lbpws, int, S_IRUGO);
module_param_named(lbpws10, sdebug_lbpws10, int, S_IRUGO);
-module_param_named(lbprz, sdebug_lbprz, int, S_IRUGO);
module_param_named(lowest_aligned, sdebug_lowest_aligned, int, S_IRUGO);
+module_param_named(lun_format, sdebug_lun_am_i, int, S_IRUGO | S_IWUSR);
module_param_named(max_luns, sdebug_max_luns, int, S_IRUGO | S_IWUSR);
module_param_named(max_queue, sdebug_max_queue, int, S_IRUGO | S_IWUSR);
-module_param_named(medium_error_start, sdebug_medium_error_start, int, S_IRUGO | S_IWUSR);
-module_param_named(medium_error_count, sdebug_medium_error_count, int, S_IRUGO | S_IWUSR);
+module_param_named(medium_error_count, sdebug_medium_error_count, int,
+ S_IRUGO | S_IWUSR);
+module_param_named(medium_error_start, sdebug_medium_error_start, int,
+ S_IRUGO | S_IWUSR);
module_param_named(ndelay, sdebug_ndelay, int, S_IRUGO | S_IWUSR);
module_param_named(no_lun_0, sdebug_no_lun_0, int, S_IRUGO | S_IWUSR);
module_param_named(no_uld, sdebug_no_uld, int, S_IRUGO);
module_param_named(num_parts, sdebug_num_parts, int, S_IRUGO);
module_param_named(num_tgts, sdebug_num_tgts, int, S_IRUGO | S_IWUSR);
module_param_named(opt_blks, sdebug_opt_blks, int, S_IRUGO);
-module_param_named(opts, sdebug_opts, int, S_IRUGO | S_IWUSR);
-module_param_named(physblk_exp, sdebug_physblk_exp, int, S_IRUGO);
module_param_named(opt_xferlen_exp, sdebug_opt_xferlen_exp, int, S_IRUGO);
+module_param_named(opts, sdebug_opts, int, S_IRUGO | S_IWUSR);
+module_param_named(per_host_store, sdebug_per_host_store, bool,
+ S_IRUGO | S_IWUSR);
+module_param_named(physblk_exp, sdebug_physblk_exp, int, S_IRUGO);
module_param_named(ptype, sdebug_ptype, int, S_IRUGO | S_IWUSR);
+module_param_named(random, sdebug_random, bool, S_IRUGO | S_IWUSR);
module_param_named(removable, sdebug_removable, bool, S_IRUGO | S_IWUSR);
module_param_named(scsi_level, sdebug_scsi_level, int, S_IRUGO);
module_param_named(sector_size, sdebug_sector_size, int, S_IRUGO);
module_param_named(statistics, sdebug_statistics, bool, S_IRUGO | S_IWUSR);
module_param_named(strict, sdebug_strict, bool, S_IRUGO | S_IWUSR);
module_param_named(submit_queues, submit_queues, int, S_IRUGO);
+module_param_named(tur_ms_to_ready, sdeb_tur_ms_to_ready, int, S_IRUGO);
module_param_named(unmap_alignment, sdebug_unmap_alignment, int, S_IRUGO);
module_param_named(unmap_granularity, sdebug_unmap_granularity, int, S_IRUGO);
module_param_named(unmap_max_blocks, sdebug_unmap_max_blocks, int, S_IRUGO);
module_param_named(unmap_max_desc, sdebug_unmap_max_desc, int, S_IRUGO);
-module_param_named(virtual_gb, sdebug_virtual_gb, int, S_IRUGO | S_IWUSR);
module_param_named(uuid_ctl, sdebug_uuid_ctl, int, S_IRUGO);
+module_param_named(virtual_gb, sdebug_virtual_gb, int, S_IRUGO | S_IWUSR);
module_param_named(vpd_use_hostno, sdebug_vpd_use_hostno, int,
S_IRUGO | S_IWUSR);
module_param_named(wp, sdebug_wp, bool, S_IRUGO | S_IWUSR);
module_param_named(write_same_length, sdebug_write_same_length, int,
S_IRUGO | S_IWUSR);
+module_param_named(zbc, sdeb_zbc_model_s, charp, S_IRUGO);
+module_param_named(zone_max_open, sdeb_zbc_max_open, int, S_IRUGO);
+module_param_named(zone_nr_conv, sdeb_zbc_nr_conv, int, S_IRUGO);
+module_param_named(zone_size_mb, sdeb_zbc_zone_size_mb, int, S_IRUGO);
MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
MODULE_DESCRIPTION("SCSI debug adapter driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(SDEBUG_VERSION);
-MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
+MODULE_PARM_DESC(add_host, "add n hosts, in sysfs if negative remove host(s) (def=1)");
MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
MODULE_PARM_DESC(cdb_len, "suggest CDB lengths to drivers (def=10)");
MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)");
@@ -4487,36 +5664,42 @@
MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
MODULE_PARM_DESC(host_lock, "host_lock is ignored (def=0)");
-MODULE_PARM_DESC(inq_vendor, "SCSI INQUIRY vendor string (def=\"Linux\")");
+MODULE_PARM_DESC(host_max_queue,
+ "host max # of queued cmds (0 to max(def) [max_queue fixed equal for !0])");
MODULE_PARM_DESC(inq_product, "SCSI INQUIRY product string (def=\"scsi_debug\")");
MODULE_PARM_DESC(inq_rev, "SCSI INQUIRY revision string (def=\""
SDEBUG_VERSION "\")");
+MODULE_PARM_DESC(inq_vendor, "SCSI INQUIRY vendor string (def=\"Linux\")");
+MODULE_PARM_DESC(lbprz,
+ "on read unmapped LBs return 0 when 1 (def), return 0xff when 2");
MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
-MODULE_PARM_DESC(lbprz,
- "on read unmapped LBs return 0 when 1 (def), return 0xff when 2");
MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
+MODULE_PARM_DESC(lun_format, "LUN format: 0->peripheral (def); 1 --> flat address method");
MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))");
-MODULE_PARM_DESC(medium_error_start, "starting sector number to return MEDIUM error");
MODULE_PARM_DESC(medium_error_count, "count of sectors to return follow on MEDIUM error");
+MODULE_PARM_DESC(medium_error_start, "starting sector number to return MEDIUM error");
MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)");
MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))");
MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)");
MODULE_PARM_DESC(opt_blks, "optimal transfer length in blocks (def=1024)");
-MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)");
-MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
MODULE_PARM_DESC(opt_xferlen_exp, "optimal transfer length granularity exponent (def=physblk_exp)");
+MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)");
+MODULE_PARM_DESC(per_host_store, "If set, next positive add_host will get new store (def=0)");
+MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
+MODULE_PARM_DESC(random, "If set, uniformly randomize command duration between 0 and delay_in_ns");
MODULE_PARM_DESC(removable, "claim to have removable media (def=0)");
MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=7[SPC-5])");
MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)");
MODULE_PARM_DESC(statistics, "collect statistics on commands, queues (def=0)");
MODULE_PARM_DESC(strict, "stricter checks: reserved field in cdb (def=0)");
MODULE_PARM_DESC(submit_queues, "support for block multi-queue (def=1)");
+MODULE_PARM_DESC(tur_ms_to_ready, "TEST UNIT READY millisecs before initial good status (def=0)");
MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
@@ -4527,6 +5710,10 @@
MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
MODULE_PARM_DESC(wp, "Write Protect (def=0)");
MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)");
+MODULE_PARM_DESC(zbc, "'none' [0]; 'aware' [1]; 'managed' [2] (def=0). Can have 'host-' prefix");
+MODULE_PARM_DESC(zone_max_open, "Maximum number of open zones; [0] for no limit (def=auto)");
+MODULE_PARM_DESC(zone_nr_conv, "Number of conventional zones (def=1)");
+MODULE_PARM_DESC(zone_size_mb, "Zone size in MiB (def=auto)");
#define SDEBUG_INFO_LEN 256
static char sdebug_info[SDEBUG_INFO_LEN];
@@ -4575,6 +5762,7 @@
{
int f, j, l;
struct sdebug_queue *sqp;
+ struct sdebug_host_info *sdhp;
seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n",
SDEBUG_VERSION, sdebug_version_date);
@@ -4610,6 +5798,34 @@
"first,last bits", f, l);
}
}
+
+ seq_printf(m, "this host_no=%d\n", host->host_no);
+ if (!xa_empty(per_store_ap)) {
+ bool niu;
+ int idx;
+ unsigned long l_idx;
+ struct sdeb_store_info *sip;
+
+ seq_puts(m, "\nhost list:\n");
+ j = 0;
+ list_for_each_entry(sdhp, &sdebug_host_list, host_list) {
+ idx = sdhp->si_idx;
+ seq_printf(m, " %d: host_no=%d, si_idx=%d\n", j,
+ sdhp->shost->host_no, idx);
+ ++j;
+ }
+ seq_printf(m, "\nper_store array [most_recent_idx=%d]:\n",
+ sdeb_most_recent_idx);
+ j = 0;
+ xa_for_each(per_store_ap, l_idx, sip) {
+ niu = xa_get_mark(per_store_ap, l_idx,
+ SDEB_XA_NOT_IN_USE);
+ idx = (int)l_idx;
+ seq_printf(m, " %d: idx=%d%s\n", j, idx,
+ (niu ? " not_in_use" : ""));
+ ++j;
+ }
+ }
return 0;
}
@@ -4733,7 +5949,13 @@
{
int n;
+ /* Cannot change from or to TYPE_ZBC with sysfs */
+ if (sdebug_ptype == TYPE_ZBC)
+ return -EINVAL;
+
if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+ if (n == TYPE_ZBC)
+ return -EINVAL;
sdebug_ptype = n;
return count;
}
@@ -4765,25 +5987,41 @@
static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf,
size_t count)
{
- int n;
+ int n, idx;
if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
+ bool want_store = (n == 0);
+ struct sdebug_host_info *sdhp;
+
n = (n > 0);
sdebug_fake_rw = (sdebug_fake_rw > 0);
- if (sdebug_fake_rw != n) {
- if ((0 == n) && (NULL == fake_storep)) {
- unsigned long sz =
- (unsigned long)sdebug_dev_size_mb *
- 1048576;
+ if (sdebug_fake_rw == n)
+ return count; /* not transitioning so do nothing */
- fake_storep = vzalloc(sz);
- if (NULL == fake_storep) {
- pr_err("out of memory, 9\n");
- return -ENOMEM;
+ if (want_store) { /* 1 --> 0 transition, set up store */
+ if (sdeb_first_idx < 0) {
+ idx = sdebug_add_store();
+ if (idx < 0)
+ return idx;
+ } else {
+ idx = sdeb_first_idx;
+ xa_clear_mark(per_store_ap, idx,
+ SDEB_XA_NOT_IN_USE);
+ }
+ /* make all hosts use same store */
+ list_for_each_entry(sdhp, &sdebug_host_list,
+ host_list) {
+ if (sdhp->si_idx != idx) {
+ xa_set_mark(per_store_ap, sdhp->si_idx,
+ SDEB_XA_NOT_IN_USE);
+ sdhp->si_idx = idx;
}
}
- sdebug_fake_rw = n;
+ sdeb_most_recent_idx = idx;
+ } else { /* 0 --> 1 transition is trigger for shrink */
+ sdebug_erase_all_stores(true /* apart from first */);
}
+ sdebug_fake_rw = n;
return count;
}
return -EINVAL;
@@ -4831,6 +6069,24 @@
}
static DRIVER_ATTR_RO(dev_size_mb);
+static ssize_t per_host_store_show(struct device_driver *ddp, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_per_host_store);
+}
+
+static ssize_t per_host_store_store(struct device_driver *ddp, const char *buf,
+ size_t count)
+{
+ bool v;
+
+ if (kstrtobool(buf, &v))
+ return -EINVAL;
+
+ sdebug_per_host_store = v;
+ return count;
+}
+static DRIVER_ATTR_RW(per_host_store);
+
static ssize_t num_parts_show(struct device_driver *ddp, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_num_parts);
@@ -4845,19 +6101,66 @@
size_t count)
{
int nth;
+ char work[20];
- if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) {
- sdebug_every_nth = nth;
- if (nth && !sdebug_statistics) {
- pr_info("every_nth needs statistics=1, set it\n");
- sdebug_statistics = true;
+ if (sscanf(buf, "%10s", work) == 1) {
+ if (strncasecmp(work, "0x", 2) == 0) {
+ if (kstrtoint(work + 2, 16, &nth) == 0)
+ goto every_nth_done;
+ } else {
+ if (kstrtoint(work, 10, &nth) == 0)
+ goto every_nth_done;
}
- tweak_cmnd_count();
+ }
+ return -EINVAL;
+
+every_nth_done:
+ sdebug_every_nth = nth;
+ if (nth && !sdebug_statistics) {
+ pr_info("every_nth needs statistics=1, set it\n");
+ sdebug_statistics = true;
+ }
+ tweak_cmnd_count();
+ return count;
+}
+static DRIVER_ATTR_RW(every_nth);
+
+static ssize_t lun_format_show(struct device_driver *ddp, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%d\n", (int)sdebug_lun_am);
+}
+static ssize_t lun_format_store(struct device_driver *ddp, const char *buf,
+ size_t count)
+{
+ int n;
+ bool changed;
+
+ if (kstrtoint(buf, 0, &n))
+ return -EINVAL;
+ if (n >= 0) {
+ if (n > (int)SAM_LUN_AM_FLAT) {
+ pr_warn("only LUN address methods 0 and 1 are supported\n");
+ return -EINVAL;
+ }
+ changed = ((int)sdebug_lun_am != n);
+ sdebug_lun_am = n;
+ if (changed && sdebug_scsi_level >= 5) { /* >= SPC-3 */
+ struct sdebug_host_info *sdhp;
+ struct sdebug_dev_info *dp;
+
+ spin_lock(&sdebug_host_list_lock);
+ list_for_each_entry(sdhp, &sdebug_host_list, host_list) {
+ list_for_each_entry(dp, &sdhp->dev_info_list, dev_list) {
+ set_bit(SDEBUG_UA_LUNS_CHANGED, dp->uas_bm);
+ }
+ }
+ spin_unlock(&sdebug_host_list_lock);
+ }
return count;
}
return -EINVAL;
}
-static DRIVER_ATTR_RW(every_nth);
+static DRIVER_ATTR_RW(lun_format);
static ssize_t max_luns_show(struct device_driver *ddp, char *buf)
{
@@ -4911,7 +6214,8 @@
struct sdebug_queue *sqp;
if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) &&
- (n <= SDEBUG_CANQUEUE)) {
+ (n <= SDEBUG_CANQUEUE) &&
+ (sdebug_host_max_queue == 0)) {
block_unblock_all_queues(true);
k = 0;
for (j = 0, sqp = sdebug_q_arr; j < submit_queues;
@@ -4934,6 +6238,17 @@
}
static DRIVER_ATTR_RW(max_queue);
+static ssize_t host_max_queue_show(struct device_driver *ddp, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_host_max_queue);
+}
+
+/*
+ * Since this is used for .can_queue, and we get the hc_idx tag from the bitmap
+ * in range [0, sdebug_host_max_queue), we can't change it.
+ */
+static DRIVER_ATTR_RO(host_max_queue);
+
static ssize_t no_uld_show(struct device_driver *ddp, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_no_uld);
@@ -4956,6 +6271,10 @@
int n;
bool changed;
+ /* Ignore capacity change for ZBC drives for now */
+ if (sdeb_zbc_in_use)
+ return -ENOTSUPP;
+
if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) {
changed = (sdebug_virtual_gb != n);
sdebug_virtual_gb = n;
@@ -4983,26 +6302,42 @@
static ssize_t add_host_show(struct device_driver *ddp, char *buf)
{
- return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_add_host);
+ /* absolute number of hosts currently active is what is shown */
+ return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_num_hosts);
}
-static int sdebug_add_adapter(void);
-static void sdebug_remove_adapter(void);
-
static ssize_t add_host_store(struct device_driver *ddp, const char *buf,
size_t count)
{
+ bool found;
+ unsigned long idx;
+ struct sdeb_store_info *sip;
+ bool want_phs = (sdebug_fake_rw == 0) && sdebug_per_host_store;
int delta_hosts;
if (sscanf(buf, "%d", &delta_hosts) != 1)
return -EINVAL;
if (delta_hosts > 0) {
do {
- sdebug_add_adapter();
+ found = false;
+ if (want_phs) {
+ xa_for_each_marked(per_store_ap, idx, sip,
+ SDEB_XA_NOT_IN_USE) {
+ sdeb_most_recent_idx = (int)idx;
+ found = true;
+ break;
+ }
+ if (found) /* re-use case */
+ sdebug_add_host_helper((int)idx);
+ else
+ sdebug_do_add_host(true);
+ } else {
+ sdebug_do_add_host(false);
+ }
} while (--delta_hosts);
} else if (delta_hosts < 0) {
do {
- sdebug_remove_adapter();
+ sdebug_do_remove_host(false);
} while (++delta_hosts);
}
return count;
@@ -5086,14 +6421,19 @@
static ssize_t map_show(struct device_driver *ddp, char *buf)
{
- ssize_t count;
+ ssize_t count = 0;
if (!scsi_debug_lbp())
return scnprintf(buf, PAGE_SIZE, "0-%u\n",
sdebug_store_sectors);
- count = scnprintf(buf, PAGE_SIZE - 1, "%*pbl",
- (int)map_size, map_storep);
+ if (sdebug_fake_rw == 0 && !xa_empty(per_store_ap)) {
+ struct sdeb_store_info *sip = xa_load(per_store_ap, 0);
+
+ if (sip)
+ count = scnprintf(buf, PAGE_SIZE - 1, "%*pbl",
+ (int)map_size, sip->map_storep);
+ }
buf[count++] = '\n';
buf[count] = '\0';
@@ -5101,6 +6441,24 @@
}
static DRIVER_ATTR_RO(map);
+static ssize_t random_show(struct device_driver *ddp, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_random);
+}
+
+static ssize_t random_store(struct device_driver *ddp, const char *buf,
+ size_t count)
+{
+ bool v;
+
+ if (kstrtobool(buf, &v))
+ return -EINVAL;
+
+ sdebug_random = v;
+ return count;
+}
+static DRIVER_ATTR_RW(random);
+
static ssize_t removable_show(struct device_driver *ddp, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_removable ? 1 : 0);
@@ -5177,12 +6535,57 @@
}
static DRIVER_ATTR_RW(cdb_len);
+static const char * const zbc_model_strs_a[] = {
+ [BLK_ZONED_NONE] = "none",
+ [BLK_ZONED_HA] = "host-aware",
+ [BLK_ZONED_HM] = "host-managed",
+};
+
+static const char * const zbc_model_strs_b[] = {
+ [BLK_ZONED_NONE] = "no",
+ [BLK_ZONED_HA] = "aware",
+ [BLK_ZONED_HM] = "managed",
+};
+
+static const char * const zbc_model_strs_c[] = {
+ [BLK_ZONED_NONE] = "0",
+ [BLK_ZONED_HA] = "1",
+ [BLK_ZONED_HM] = "2",
+};
+
+static int sdeb_zbc_model_str(const char *cp)
+{
+ int res = sysfs_match_string(zbc_model_strs_a, cp);
+
+ if (res < 0) {
+ res = sysfs_match_string(zbc_model_strs_b, cp);
+ if (res < 0) {
+ res = sysfs_match_string(zbc_model_strs_c, cp);
+ if (res < 0)
+ return -EINVAL;
+ }
+ }
+ return res;
+}
+
+static ssize_t zbc_show(struct device_driver *ddp, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%s\n",
+ zbc_model_strs_a[sdeb_zbc_model]);
+}
+static DRIVER_ATTR_RO(zbc);
+
+static ssize_t tur_ms_to_ready_show(struct device_driver *ddp, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%d\n", sdeb_tur_ms_to_ready);
+}
+static DRIVER_ATTR_RO(tur_ms_to_ready);
/* Note: The following array creates attribute files in the
/sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
files (over those found in the /sys/module/scsi_debug/parameters
directory) is that auxiliary actions can be triggered when an attribute
- is changed. For example see: sdebug_add_host_store() above.
+ is changed. For example see: add_host_store() above.
*/
static struct attribute *sdebug_drv_attrs[] = {
@@ -5191,17 +6594,20 @@
&driver_attr_ptype.attr,
&driver_attr_dsense.attr,
&driver_attr_fake_rw.attr,
+ &driver_attr_host_max_queue.attr,
&driver_attr_no_lun_0.attr,
&driver_attr_num_tgts.attr,
&driver_attr_dev_size_mb.attr,
&driver_attr_num_parts.attr,
&driver_attr_every_nth.attr,
+ &driver_attr_lun_format.attr,
&driver_attr_max_luns.attr,
&driver_attr_max_queue.attr,
&driver_attr_no_uld.attr,
&driver_attr_scsi_level.attr,
&driver_attr_virtual_gb.attr,
&driver_attr_add_host.attr,
+ &driver_attr_per_host_store.attr,
&driver_attr_vpd_use_hostno.attr,
&driver_attr_sector_size.attr,
&driver_attr_statistics.attr,
@@ -5211,12 +6617,15 @@
&driver_attr_guard.attr,
&driver_attr_ato.attr,
&driver_attr_map.attr,
+ &driver_attr_random.attr,
&driver_attr_removable.attr,
&driver_attr_host_lock.attr,
&driver_attr_ndelay.attr,
&driver_attr_strict.attr,
&driver_attr_uuid_ctl.attr,
&driver_attr_cdb_len.attr,
+ &driver_attr_tur_ms_to_ready.attr,
+ &driver_attr_zbc.attr,
NULL,
};
ATTRIBUTE_GROUPS(sdebug_drv);
@@ -5225,11 +6634,13 @@
static int __init scsi_debug_init(void)
{
+ bool want_store = (sdebug_fake_rw == 0);
unsigned long sz;
- int host_to_add;
- int k;
- int ret;
+ int k, ret, hosts_to_add;
+ int idx = -1;
+ ramdisk_lck_a[0] = &atomic_rw;
+ ramdisk_lck_a[1] = &atomic_rw2;
atomic_set(&retired_max_queue, 0);
if (sdebug_ndelay >= 1000 * 1000 * 1000) {
@@ -5282,9 +6693,19 @@
pr_err("invalid physblk_exp %u\n", sdebug_physblk_exp);
return -EINVAL;
}
+
+ sdebug_lun_am = sdebug_lun_am_i;
+ if (sdebug_lun_am > SAM_LUN_AM_FLAT) {
+ pr_warn("Invalid LUN format %u, using default\n", (int)sdebug_lun_am);
+ sdebug_lun_am = SAM_LUN_AM_PERIPHERAL;
+ }
+
if (sdebug_max_luns > 256) {
- pr_warn("max_luns can be no more than 256, use default\n");
- sdebug_max_luns = DEF_MAX_LUNS;
+ if (sdebug_max_luns > 16384) {
+ pr_warn("max_luns can be no more than 16384, use default\n");
+ sdebug_max_luns = DEF_MAX_LUNS;
+ }
+ sdebug_lun_am = SAM_LUN_AM_FLAT;
}
if (sdebug_lowest_aligned > 0x3fff) {
@@ -5302,6 +6723,20 @@
return -EINVAL;
}
+ if ((sdebug_host_max_queue > SDEBUG_CANQUEUE) ||
+ (sdebug_host_max_queue < 0)) {
+ pr_err("host_max_queue must be in range [0 %d]\n",
+ SDEBUG_CANQUEUE);
+ return -EINVAL;
+ }
+
+ if (sdebug_host_max_queue &&
+ (sdebug_max_queue != sdebug_host_max_queue)) {
+ sdebug_max_queue = sdebug_host_max_queue;
+ pr_warn("fixing max submit queue depth to host max queue depth, %d\n",
+ sdebug_max_queue);
+ }
+
sdebug_q_arr = kcalloc(submit_queues, sizeof(struct sdebug_queue),
GFP_KERNEL);
if (sdebug_q_arr == NULL)
@@ -5309,6 +6744,41 @@
for (k = 0; k < submit_queues; ++k)
spin_lock_init(&sdebug_q_arr[k].qc_lock);
+ /*
+ * check for host managed zoned block device specified with
+ * ptype=0x14 or zbc=XXX.
+ */
+ if (sdebug_ptype == TYPE_ZBC) {
+ sdeb_zbc_model = BLK_ZONED_HM;
+ } else if (sdeb_zbc_model_s && *sdeb_zbc_model_s) {
+ k = sdeb_zbc_model_str(sdeb_zbc_model_s);
+ if (k < 0) {
+ ret = k;
+ goto free_q_arr;
+ }
+ sdeb_zbc_model = k;
+ switch (sdeb_zbc_model) {
+ case BLK_ZONED_NONE:
+ case BLK_ZONED_HA:
+ sdebug_ptype = TYPE_DISK;
+ break;
+ case BLK_ZONED_HM:
+ sdebug_ptype = TYPE_ZBC;
+ break;
+ default:
+ pr_err("Invalid ZBC model\n");
+ ret = -EINVAL;
+ goto free_q_arr;
+ }
+ }
+ if (sdeb_zbc_model != BLK_ZONED_NONE) {
+ sdeb_zbc_in_use = true;
+ if (sdebug_dev_size_mb == DEF_DEV_SIZE_PRE_INIT)
+ sdebug_dev_size_mb = DEF_ZBC_DEV_SIZE_MB;
+ }
+
+ if (sdebug_dev_size_mb == DEF_DEV_SIZE_PRE_INIT)
+ sdebug_dev_size_mb = DEF_DEV_SIZE_MB;
if (sdebug_dev_size_mb < 1)
sdebug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
sz = (unsigned long)sdebug_dev_size_mb * 1048576;
@@ -5331,36 +6801,6 @@
sdebug_cylinders_per = (unsigned long)sdebug_capacity /
(sdebug_sectors_per * sdebug_heads);
}
-
- if (sdebug_fake_rw == 0) {
- fake_storep = vzalloc(sz);
- if (NULL == fake_storep) {
- pr_err("out of memory, 1\n");
- ret = -ENOMEM;
- goto free_q_arr;
- }
- if (sdebug_num_parts > 0)
- sdebug_build_parts(fake_storep, sz);
- }
-
- if (sdebug_dix) {
- int dif_size;
-
- dif_size = sdebug_store_sectors * sizeof(struct t10_pi_tuple);
- dif_storep = vmalloc(dif_size);
-
- pr_err("dif_storep %u bytes @ %p\n", dif_size, dif_storep);
-
- if (dif_storep == NULL) {
- pr_err("out of mem. (DIX)\n");
- ret = -ENOMEM;
- goto free_vm;
- }
-
- memset(dif_storep, 0xff, dif_size);
- }
-
- /* Logical Block Provisioning */
if (scsi_debug_lbp()) {
sdebug_unmap_max_blocks =
clamp(sdebug_unmap_max_blocks, 0U, 0xffffffffU);
@@ -5376,26 +6816,16 @@
sdebug_unmap_alignment) {
pr_err("ERR: unmap_granularity <= unmap_alignment\n");
ret = -EINVAL;
- goto free_vm;
+ goto free_q_arr;
}
-
- map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
- map_storep = vmalloc(array_size(sizeof(long),
- BITS_TO_LONGS(map_size)));
-
- pr_info("%lu provisioning blocks\n", map_size);
-
- if (map_storep == NULL) {
- pr_err("out of mem. (MAP)\n");
- ret = -ENOMEM;
- goto free_vm;
+ }
+ xa_init_flags(per_store_ap, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ);
+ if (want_store) {
+ idx = sdebug_add_store();
+ if (idx < 0) {
+ ret = idx;
+ goto free_q_arr;
}
-
- bitmap_zero(map_storep, map_size);
-
- /* Map first 1KB for partition table */
- if (sdebug_num_parts)
- map_region(0, 2);
}
pseudo_primary = root_device_register("pseudo_0");
@@ -5415,18 +6845,28 @@
goto bus_unreg;
}
- host_to_add = sdebug_add_host;
+ hosts_to_add = sdebug_add_host;
sdebug_add_host = 0;
- for (k = 0; k < host_to_add; k++) {
- if (sdebug_add_adapter()) {
- pr_err("sdebug_add_adapter failed k=%d\n", k);
- break;
+ for (k = 0; k < hosts_to_add; k++) {
+ if (want_store && k == 0) {
+ ret = sdebug_add_host_helper(idx);
+ if (ret < 0) {
+ pr_err("add_host_helper k=%d, error=%d\n",
+ k, -ret);
+ break;
+ }
+ } else {
+ ret = sdebug_do_add_host(want_store &&
+ sdebug_per_host_store);
+ if (ret < 0) {
+ pr_err("add_host k=%d error=%d\n", k, -ret);
+ break;
+ }
}
}
-
if (sdebug_verbose)
- pr_info("built %d host(s)\n", sdebug_add_host);
+ pr_info("built %d host(s)\n", sdebug_num_hosts);
return 0;
@@ -5435,9 +6875,7 @@
dev_unreg:
root_device_unregister(pseudo_primary);
free_vm:
- vfree(map_storep);
- vfree(dif_storep);
- vfree(fake_storep);
+ sdebug_erase_store(idx, NULL);
free_q_arr:
kfree(sdebug_q_arr);
return ret;
@@ -5445,19 +6883,18 @@
static void __exit scsi_debug_exit(void)
{
- int k = sdebug_add_host;
+ int k = sdebug_num_hosts;
stop_all_queued();
for (; k; k--)
- sdebug_remove_adapter();
+ sdebug_do_remove_host(true);
free_all_queued();
driver_unregister(&sdebug_driverfs_driver);
bus_unregister(&pseudo_lld_bus);
root_device_unregister(pseudo_primary);
- vfree(map_storep);
- vfree(dif_storep);
- vfree(fake_storep);
+ sdebug_erase_all_stores(false);
+ xa_destroy(per_store_ap);
kfree(sdebug_q_arr);
}
@@ -5472,29 +6909,146 @@
kfree(sdbg_host);
}
-static int sdebug_add_adapter(void)
+/* idx must be valid, if sip is NULL then it will be obtained using idx */
+static void sdebug_erase_store(int idx, struct sdeb_store_info *sip)
{
- int k, devs_per_host;
- int error = 0;
+ if (idx < 0)
+ return;
+ if (!sip) {
+ if (xa_empty(per_store_ap))
+ return;
+ sip = xa_load(per_store_ap, idx);
+ if (!sip)
+ return;
+ }
+ vfree(sip->map_storep);
+ vfree(sip->dif_storep);
+ vfree(sip->storep);
+ xa_erase(per_store_ap, idx);
+ kfree(sip);
+}
+
+/* Assume apart_from_first==false only in shutdown case. */
+static void sdebug_erase_all_stores(bool apart_from_first)
+{
+ unsigned long idx;
+ struct sdeb_store_info *sip = NULL;
+
+ xa_for_each(per_store_ap, idx, sip) {
+ if (apart_from_first)
+ apart_from_first = false;
+ else
+ sdebug_erase_store(idx, sip);
+ }
+ if (apart_from_first)
+ sdeb_most_recent_idx = sdeb_first_idx;
+}
+
+/*
+ * Returns store xarray new element index (idx) if >=0 else negated errno.
+ * Limit the number of stores to 65536.
+ */
+static int sdebug_add_store(void)
+{
+ int res;
+ u32 n_idx;
+ unsigned long iflags;
+ unsigned long sz = (unsigned long)sdebug_dev_size_mb * 1048576;
+ struct sdeb_store_info *sip = NULL;
+ struct xa_limit xal = { .max = 1 << 16, .min = 0 };
+
+ sip = kzalloc(sizeof(*sip), GFP_KERNEL);
+ if (!sip)
+ return -ENOMEM;
+
+ xa_lock_irqsave(per_store_ap, iflags);
+ res = __xa_alloc(per_store_ap, &n_idx, sip, xal, GFP_ATOMIC);
+ if (unlikely(res < 0)) {
+ xa_unlock_irqrestore(per_store_ap, iflags);
+ kfree(sip);
+ pr_warn("%s: xa_alloc() errno=%d\n", __func__, -res);
+ return res;
+ }
+ sdeb_most_recent_idx = n_idx;
+ if (sdeb_first_idx < 0)
+ sdeb_first_idx = n_idx;
+ xa_unlock_irqrestore(per_store_ap, iflags);
+
+ res = -ENOMEM;
+ sip->storep = vzalloc(sz);
+ if (!sip->storep) {
+ pr_err("user data oom\n");
+ goto err;
+ }
+ if (sdebug_num_parts > 0)
+ sdebug_build_parts(sip->storep, sz);
+
+ /* DIF/DIX: what T10 calls Protection Information (PI) */
+ if (sdebug_dix) {
+ int dif_size;
+
+ dif_size = sdebug_store_sectors * sizeof(struct t10_pi_tuple);
+ sip->dif_storep = vmalloc(dif_size);
+
+ pr_info("dif_storep %u bytes @ %pK\n", dif_size,
+ sip->dif_storep);
+
+ if (!sip->dif_storep) {
+ pr_err("DIX oom\n");
+ goto err;
+ }
+ memset(sip->dif_storep, 0xff, dif_size);
+ }
+ /* Logical Block Provisioning */
+ if (scsi_debug_lbp()) {
+ map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
+ sip->map_storep = vmalloc(array_size(sizeof(long),
+ BITS_TO_LONGS(map_size)));
+
+ pr_info("%lu provisioning blocks\n", map_size);
+
+ if (!sip->map_storep) {
+ pr_err("LBP map oom\n");
+ goto err;
+ }
+
+ bitmap_zero(sip->map_storep, map_size);
+
+ /* Map first 1KB for partition table */
+ if (sdebug_num_parts)
+ map_region(sip, 0, 2);
+ }
+
+ rwlock_init(&sip->macc_lck);
+ return (int)n_idx;
+err:
+ sdebug_erase_store((int)n_idx, sip);
+ pr_warn("%s: failed, errno=%d\n", __func__, -res);
+ return res;
+}
+
+static int sdebug_add_host_helper(int per_host_idx)
+{
+ int k, devs_per_host, idx;
+ int error = -ENOMEM;
struct sdebug_host_info *sdbg_host;
struct sdebug_dev_info *sdbg_devinfo, *tmp;
sdbg_host = kzalloc(sizeof(*sdbg_host), GFP_KERNEL);
- if (sdbg_host == NULL) {
- pr_err("out of memory at line %d\n", __LINE__);
+ if (!sdbg_host)
return -ENOMEM;
- }
+ idx = (per_host_idx < 0) ? sdeb_first_idx : per_host_idx;
+ if (xa_get_mark(per_store_ap, idx, SDEB_XA_NOT_IN_USE))
+ xa_clear_mark(per_store_ap, idx, SDEB_XA_NOT_IN_USE);
+ sdbg_host->si_idx = idx;
INIT_LIST_HEAD(&sdbg_host->dev_info_list);
devs_per_host = sdebug_num_tgts * sdebug_max_luns;
for (k = 0; k < devs_per_host; k++) {
sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL);
- if (!sdbg_devinfo) {
- pr_err("out of memory at line %d\n", __LINE__);
- error = -ENOMEM;
+ if (!sdbg_devinfo)
goto clean;
- }
}
spin_lock(&sdebug_host_list_lock);
@@ -5504,44 +7058,77 @@
sdbg_host->dev.bus = &pseudo_lld_bus;
sdbg_host->dev.parent = pseudo_primary;
sdbg_host->dev.release = &sdebug_release_adapter;
- dev_set_name(&sdbg_host->dev, "adapter%d", sdebug_add_host);
+ dev_set_name(&sdbg_host->dev, "adapter%d", sdebug_num_hosts);
error = device_register(&sdbg_host->dev);
-
if (error)
goto clean;
- ++sdebug_add_host;
- return error;
+ ++sdebug_num_hosts;
+ return 0;
clean:
list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
dev_list) {
list_del(&sdbg_devinfo->dev_list);
+ kfree(sdbg_devinfo->zstate);
kfree(sdbg_devinfo);
}
-
kfree(sdbg_host);
+ pr_warn("%s: failed, errno=%d\n", __func__, -error);
return error;
}
-static void sdebug_remove_adapter(void)
+static int sdebug_do_add_host(bool mk_new_store)
{
+ int ph_idx = sdeb_most_recent_idx;
+
+ if (mk_new_store) {
+ ph_idx = sdebug_add_store();
+ if (ph_idx < 0)
+ return ph_idx;
+ }
+ return sdebug_add_host_helper(ph_idx);
+}
+
+static void sdebug_do_remove_host(bool the_end)
+{
+ int idx = -1;
struct sdebug_host_info *sdbg_host = NULL;
+ struct sdebug_host_info *sdbg_host2;
spin_lock(&sdebug_host_list_lock);
if (!list_empty(&sdebug_host_list)) {
sdbg_host = list_entry(sdebug_host_list.prev,
struct sdebug_host_info, host_list);
- list_del(&sdbg_host->host_list);
+ idx = sdbg_host->si_idx;
}
+ if (!the_end && idx >= 0) {
+ bool unique = true;
+
+ list_for_each_entry(sdbg_host2, &sdebug_host_list, host_list) {
+ if (sdbg_host2 == sdbg_host)
+ continue;
+ if (idx == sdbg_host2->si_idx) {
+ unique = false;
+ break;
+ }
+ }
+ if (unique) {
+ xa_set_mark(per_store_ap, idx, SDEB_XA_NOT_IN_USE);
+ if (idx == sdeb_most_recent_idx)
+ --sdeb_most_recent_idx;
+ }
+ }
+ if (sdbg_host)
+ list_del(&sdbg_host->host_list);
spin_unlock(&sdebug_host_list_lock);
if (!sdbg_host)
return;
device_unregister(&sdbg_host->dev);
- --sdebug_add_host;
+ --sdebug_num_hosts;
}
static int sdebug_change_qdepth(struct scsi_device *sdev, int qdepth)
@@ -5586,10 +7173,47 @@
return false;
}
-static bool fake_host_busy(struct scsi_cmnd *scp)
+/* Response to TUR or media access command when device stopped */
+static int resp_not_ready(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
{
- return (sdebug_opts & SDEBUG_OPT_HOST_BUSY) &&
- (atomic_read(&sdebug_cmnd_count) % abs(sdebug_every_nth)) == 0;
+ int stopped_state;
+ u64 diff_ns = 0;
+ ktime_t now_ts = ktime_get_boottime();
+ struct scsi_device *sdp = scp->device;
+
+ stopped_state = atomic_read(&devip->stopped);
+ if (stopped_state == 2) {
+ if (ktime_to_ns(now_ts) > ktime_to_ns(devip->create_ts)) {
+ diff_ns = ktime_to_ns(ktime_sub(now_ts, devip->create_ts));
+ if (diff_ns >= ((u64)sdeb_tur_ms_to_ready * 1000000)) {
+ /* tur_ms_to_ready timer extinguished */
+ atomic_set(&devip->stopped, 0);
+ return 0;
+ }
+ }
+ mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x1);
+ if (sdebug_verbose)
+ sdev_printk(KERN_INFO, sdp,
+ "%s: Not ready: in process of becoming ready\n", my_name);
+ if (scp->cmnd[0] == TEST_UNIT_READY) {
+ u64 tur_nanosecs_to_ready = (u64)sdeb_tur_ms_to_ready * 1000000;
+
+ if (diff_ns <= tur_nanosecs_to_ready)
+ diff_ns = tur_nanosecs_to_ready - diff_ns;
+ else
+ diff_ns = tur_nanosecs_to_ready;
+ /* As per 20-061r2 approved for spc6 by T10 on 20200716 */
+ do_div(diff_ns, 1000000); /* diff_ns becomes milliseconds */
+ scsi_set_sense_information(scp->sense_buffer, SCSI_SENSE_BUFFERSIZE,
+ diff_ns);
+ return check_condition_result;
+ }
+ }
+ mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2);
+ if (sdebug_verbose)
+ sdev_printk(KERN_INFO, sdp, "%s: Not ready: initializing command required\n",
+ my_name);
+ return check_condition_result;
}
static int scsi_debug_queuecommand(struct Scsi_Host *shost,
@@ -5605,14 +7229,20 @@
int (*pfp)(struct scsi_cmnd *, struct sdebug_dev_info *) = NULL;
int k, na;
int errsts = 0;
+ u64 lun_index = sdp->lun & 0x3FFF;
u32 flags;
u16 sa;
u8 opcode = cmd[0];
bool has_wlun_rl;
+ bool inject_now;
scsi_set_resid(scp, 0);
- if (sdebug_statistics)
+ if (sdebug_statistics) {
atomic_inc(&sdebug_cmnd_count);
+ inject_now = inject_on_this_cmd();
+ } else {
+ inject_now = false;
+ }
if (unlikely(sdebug_verbose &&
!(SDEBUG_OPT_NO_CDB_NOISE & sdebug_opts))) {
char b[120];
@@ -5630,10 +7260,10 @@
sdev_printk(KERN_INFO, sdp, "%s: tag=%#x, cmd %s\n", my_name,
blk_mq_unique_tag(scp->request), b);
}
- if (fake_host_busy(scp))
+ if (unlikely(inject_now && (sdebug_opts & SDEBUG_OPT_HOST_BUSY)))
return SCSI_MLQUEUE_HOST_BUSY;
has_wlun_rl = (sdp->lun == SCSI_W_LUN_REPORT_LUNS);
- if (unlikely((sdp->lun >= sdebug_max_luns) && !has_wlun_rl))
+ if (unlikely(lun_index >= sdebug_max_luns && !has_wlun_rl))
goto err_out;
sdeb_i = opcode_ind_arr[opcode]; /* fully mapped */
@@ -5644,6 +7274,9 @@
if (NULL == devip)
goto err_out;
}
+ if (unlikely(inject_now && !atomic_read(&sdeb_inject_pending)))
+ atomic_set(&sdeb_inject_pending, 1);
+
na = oip->num_attached;
r_pfp = oip->pfp;
if (na) { /* multiple commands with this opcode */
@@ -5708,14 +7341,11 @@
if (errsts)
goto check_cond;
}
- if (unlikely((F_M_ACCESS & flags) && atomic_read(&devip->stopped))) {
- mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2);
- if (sdebug_verbose)
- sdev_printk(KERN_INFO, sdp, "%s reports: Not ready: "
- "%s\n", my_name, "initializing command "
- "required");
- errsts = check_condition_result;
- goto fini;
+ if (unlikely(((F_M_ACCESS & flags) || scp->cmnd[0] == TEST_UNIT_READY) &&
+ atomic_read(&devip->stopped))) {
+ errsts = resp_not_ready(scp, devip);
+ if (errsts)
+ goto fini;
}
if (sdebug_fake_rw && (F_FAKE_RW & flags))
goto fini;
@@ -5729,7 +7359,7 @@
pfp = r_pfp; /* if leaf function ptr NULL, try the root's */
fini:
- if (F_DELAY_OVERR & flags)
+ if (F_DELAY_OVERR & flags) /* cmds like INQUIRY respond asap */
return schedule_resp(scp, devip, errsts, pfp, 0, 0);
else if ((flags & F_LONG_DELAY) && (sdebug_jdelay > 0 ||
sdebug_ndelay > 10000)) {
@@ -5804,9 +7434,13 @@
my_name, submit_queues, nr_cpu_ids);
submit_queues = nr_cpu_ids;
}
- /* Decide whether to tell scsi subsystem that we want mq */
- /* Following should give the same answer for each host */
+ /*
+ * Decide whether to tell scsi subsystem that we want mq. The
+ * following should give the same answer for each host.
+ */
hpnt->nr_hw_queues = submit_queues;
+ if (sdebug_host_max_queue)
+ hpnt->host_tagset = 1;
sdbg_host->shost = hpnt;
*((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host;
@@ -5871,8 +7505,9 @@
pr_err("scsi_add_host failed\n");
error = -ENODEV;
scsi_host_put(hpnt);
- } else
+ } else {
scsi_scan_host(hpnt);
+ }
return error;
}
@@ -5894,6 +7529,7 @@
list_for_each_entry_safe(sdbg_devinfo, tmp, &sdbg_host->dev_info_list,
dev_list) {
list_del(&sdbg_devinfo->dev_list);
+ kfree(sdbg_devinfo->zstate);
kfree(sdbg_devinfo);
}
diff --git a/drivers/scsi/scsi_debugfs.c b/drivers/scsi/scsi_debugfs.c
index c19ea7a..d9a1812 100644
--- a/drivers/scsi/scsi_debugfs.c
+++ b/drivers/scsi/scsi_debugfs.c
@@ -10,6 +10,7 @@
SCSI_CMD_FLAG_NAME(TAGGED),
SCSI_CMD_FLAG_NAME(UNCHECKED_ISA_DMA),
SCSI_CMD_FLAG_NAME(INITIALIZED),
+ SCSI_CMD_FLAG_NAME(LAST),
};
#undef SCSI_CMD_FLAG_NAME
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 7f76bf5..9a8f9f9 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -738,13 +738,12 @@
return err;
}
-static const struct file_operations scsi_devinfo_proc_fops = {
- .owner = THIS_MODULE,
- .open = proc_scsi_devinfo_open,
- .read = seq_read,
- .write = proc_scsi_devinfo_write,
- .llseek = seq_lseek,
- .release = seq_release,
+static const struct proc_ops scsi_devinfo_proc_ops = {
+ .proc_open = proc_scsi_devinfo_open,
+ .proc_read = seq_read,
+ .proc_write = proc_scsi_devinfo_write,
+ .proc_lseek = seq_lseek,
+ .proc_release = seq_release,
};
#endif /* CONFIG_SCSI_PROC_FS */
@@ -869,7 +868,7 @@
}
#ifdef CONFIG_SCSI_PROC_FS
- p = proc_create("scsi/device_info", 0, NULL, &scsi_devinfo_proc_fops);
+ p = proc_create("scsi/device_info", 0, NULL, &scsi_devinfo_proc_ops);
if (!p) {
error = -ENOMEM;
goto out;
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index ae2fa17..f11f51e 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -116,6 +116,14 @@
return 1;
}
+static bool scsi_cmd_retry_allowed(struct scsi_cmnd *cmd)
+{
+ if (cmd->allowed == SCSI_CMD_RETRIES_NO_LIMIT)
+ return true;
+
+ return ++cmd->retries <= cmd->allowed;
+}
+
/**
* scmd_eh_abort_handler - Handle command aborts
* @work: command to be aborted.
@@ -151,7 +159,7 @@
"eh timeout, not retrying "
"aborted command\n"));
} else if (!scsi_noretry_cmd(scmd) &&
- (++scmd->retries <= scmd->allowed)) {
+ scsi_cmd_retry_allowed(scmd)) {
SCSI_LOG_ERROR_RECOVERY(3,
scmd_printk(KERN_WARNING, scmd,
"retry aborted command\n"));
@@ -599,7 +607,7 @@
set_host_byte(scmd, DID_ALLOC_FAILURE);
return SUCCESS;
}
- /* FALLTHROUGH */
+ fallthrough;
case COPY_ABORTED:
case VOLUME_OVERFLOW:
case MISCOMPARE:
@@ -621,7 +629,7 @@
return ADD_TO_MLQUEUE;
else
set_host_byte(scmd, DID_TARGET_FAILURE);
- /* FALLTHROUGH */
+ fallthrough;
case ILLEGAL_REQUEST:
if (sshdr.asc == 0x20 || /* Invalid command operation code */
@@ -734,7 +742,7 @@
switch (status_byte(scmd->result)) {
case GOOD:
scsi_handle_queue_ramp_up(scmd->device);
- /* FALLTHROUGH */
+ fallthrough;
case COMMAND_TERMINATED:
return SUCCESS;
case CHECK_CONDITION:
@@ -755,7 +763,7 @@
return FAILED;
case QUEUE_FULL:
scsi_handle_queue_full(scmd->device);
- /* fall through */
+ fallthrough;
case BUSY:
return NEEDS_RETRY;
default:
@@ -1264,11 +1272,18 @@
* upper level.
*/
if (rtn == SUCCESS)
- /* we don't want this command reissued, just
- * finished with the sense data, so set
- * retries to the max allowed to ensure it
- * won't get reissued */
- scmd->retries = scmd->allowed;
+ /*
+ * We don't want this command reissued, just finished
+ * with the sense data, so set retries to the max
+ * allowed to ensure it won't get reissued. If the user
+ * has requested infinite retries, we also want to
+ * finish this command, so force completion by setting
+ * retries and allowed to the same value.
+ */
+ if (scmd->allowed == SCSI_CMD_RETRIES_NO_LIMIT)
+ scmd->retries = scmd->allowed = 1;
+ else
+ scmd->retries = scmd->allowed;
else if (rtn != NEEDS_RETRY)
continue;
@@ -1302,7 +1317,7 @@
case NEEDS_RETRY:
if (retry_cnt--)
goto retry_tur;
- /*FALLTHRU*/
+ fallthrough;
case SUCCESS:
return 0;
default:
@@ -1412,6 +1427,7 @@
sdev_printk(KERN_INFO, sdev,
"%s: skip START_UNIT, past eh deadline\n",
current->comm));
+ scsi_device_put(sdev);
break;
}
stu_scmd = NULL;
@@ -1478,6 +1494,7 @@
sdev_printk(KERN_INFO, sdev,
"%s: skip BDR, past eh deadline\n",
current->comm));
+ scsi_device_put(sdev);
break;
}
bdr_scmd = NULL;
@@ -1737,7 +1754,7 @@
if (msg_byte(scmd->result) == COMMAND_COMPLETE &&
status_byte(scmd->result) == RESERVATION_CONFLICT)
return 0;
- /* fall through */
+ fallthrough;
case DID_SOFT_ERROR:
return (scmd->request->cmd_flags & REQ_FAILFAST_DRIVER);
}
@@ -1753,8 +1770,8 @@
if (scmd->request->cmd_flags & REQ_FAILFAST_DEV ||
blk_rq_is_passthrough(scmd->request))
return 1;
- else
- return 0;
+
+ return 0;
}
/**
@@ -1808,7 +1825,7 @@
set_host_byte(scmd, DID_TIME_OUT);
return SUCCESS;
}
- /* FALLTHROUGH */
+ fallthrough;
case DID_NO_CONNECT:
case DID_BAD_TARGET:
/*
@@ -1852,7 +1869,7 @@
* lower down
*/
break;
- /* fallthrough */
+ fallthrough;
case DID_BUS_BUSY:
case DID_PARITY:
goto maybe_retry;
@@ -1890,7 +1907,7 @@
* the case of trying to send too many commands to a
* tagged queueing device.
*/
- /* FALLTHROUGH */
+ fallthrough;
case BUSY:
/*
* device can't talk to us at the moment. Should only
@@ -1903,7 +1920,7 @@
if (scmd->cmnd[0] == REPORT_LUNS)
scmd->device->sdev_target->expecting_lun_change = 0;
scsi_handle_queue_ramp_up(scmd->device);
- /* FALLTHROUGH */
+ fallthrough;
case COMMAND_TERMINATED:
return SUCCESS;
case TASK_ABORTED:
@@ -1942,8 +1959,7 @@
* the request was not marked fast fail. Note that above,
* even if the request is marked fast fail, we still requeue
* for queue congestion conditions (QUEUE_FULL or BUSY) */
- if ((++scmd->retries) <= scmd->allowed
- && !scsi_noretry_cmd(scmd)) {
+ if (scsi_cmd_retry_allowed(scmd) && !scsi_noretry_cmd(scmd)) {
return NEEDS_RETRY;
} else {
/*
@@ -2089,8 +2105,7 @@
list_for_each_entry_safe(scmd, next, done_q, eh_entry) {
list_del_init(&scmd->eh_entry);
if (scsi_device_online(scmd->device) &&
- !scsi_noretry_cmd(scmd) &&
- (++scmd->retries <= scmd->allowed)) {
+ !scsi_noretry_cmd(scmd) && scsi_cmd_retry_allowed(scmd)) {
SCSI_LOG_ERROR_RECOVERY(3,
scmd_printk(KERN_INFO, scmd,
"%s: flush retry cmd\n",
@@ -2374,22 +2389,22 @@
rtn = scsi_try_bus_device_reset(scmd);
if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
break;
- /* FALLTHROUGH */
+ fallthrough;
case SG_SCSI_RESET_TARGET:
rtn = scsi_try_target_reset(scmd);
if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
break;
- /* FALLTHROUGH */
+ fallthrough;
case SG_SCSI_RESET_BUS:
rtn = scsi_try_bus_reset(scmd);
if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE))
break;
- /* FALLTHROUGH */
+ fallthrough;
case SG_SCSI_RESET_HOST:
rtn = scsi_try_host_reset(scmd);
if (rtn == SUCCESS)
break;
- /* FALLTHROUGH */
+ fallthrough;
default:
rtn = FAILED;
break;
@@ -2412,7 +2427,6 @@
wake_up(&shost->host_wait);
scsi_run_host_queues(shost);
- scsi_put_command(scmd);
kfree(rq);
out_put_autopm_host:
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 57bcd05..14872c9 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -117,14 +117,14 @@
case NOT_READY: /* This happens if there is no disc in drive */
if (sdev->removable)
break;
- /* FALLTHROUGH */
+ fallthrough;
case UNIT_ATTENTION:
if (sdev->removable) {
sdev->changed = 1;
result = 0; /* This is no longer considered an error */
break;
}
- /* FALLTHROUGH -- for non-removable media */
+ fallthrough; /* for non-removable media */
default:
sdev_printk(KERN_INFO, sdev,
"ioctl_internal_command return code = %x\n",
@@ -189,17 +189,7 @@
}
-/**
- * scsi_ioctl - Dispatch ioctl to scsi device
- * @sdev: scsi device receiving ioctl
- * @cmd: which ioctl is it
- * @arg: data associated with ioctl
- *
- * Description: The scsi_ioctl() function differs from most ioctls in that it
- * does not take a major/minor number as the dev field. Rather, it takes
- * a pointer to a &struct scsi_device.
- */
-int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
+static int scsi_ioctl_common(struct scsi_device *sdev, int cmd, void __user *arg)
{
char scsi_cmd[MAX_COMMAND_SIZE];
struct scsi_sense_hdr sense_hdr;
@@ -221,18 +211,18 @@
}
switch (cmd) {
- case SCSI_IOCTL_GET_IDLUN:
- if (!access_ok(arg, sizeof(struct scsi_idlun)))
+ case SCSI_IOCTL_GET_IDLUN: {
+ struct scsi_idlun v = {
+ .dev_id = (sdev->id & 0xff)
+ + ((sdev->lun & 0xff) << 8)
+ + ((sdev->channel & 0xff) << 16)
+ + ((sdev->host->host_no & 0xff) << 24),
+ .host_unique_id = sdev->host->unique_id
+ };
+ if (copy_to_user(arg, &v, sizeof(struct scsi_idlun)))
return -EFAULT;
-
- __put_user((sdev->id & 0xff)
- + ((sdev->lun & 0xff) << 8)
- + ((sdev->channel & 0xff) << 16)
- + ((sdev->host->host_no & 0xff) << 24),
- &((struct scsi_idlun __user *)arg)->dev_id);
- __put_user(sdev->host->unique_id,
- &((struct scsi_idlun __user *)arg)->host_unique_id);
return 0;
+ }
case SCSI_IOCTL_GET_BUS_NUMBER:
return put_user(sdev->host->host_no, (int __user *)arg);
case SCSI_IOCTL_PROBE_HOST:
@@ -266,14 +256,50 @@
return scsi_ioctl_get_pci(sdev, arg);
case SG_SCSI_RESET:
return scsi_ioctl_reset(sdev, arg);
- default:
- if (sdev->host->hostt->ioctl)
- return sdev->host->hostt->ioctl(sdev, cmd, arg);
}
+ return -ENOIOCTLCMD;
+}
+
+/**
+ * scsi_ioctl - Dispatch ioctl to scsi device
+ * @sdev: scsi device receiving ioctl
+ * @cmd: which ioctl is it
+ * @arg: data associated with ioctl
+ *
+ * Description: The scsi_ioctl() function differs from most ioctls in that it
+ * does not take a major/minor number as the dev field. Rather, it takes
+ * a pointer to a &struct scsi_device.
+ */
+int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
+{
+ int ret = scsi_ioctl_common(sdev, cmd, arg);
+
+ if (ret != -ENOIOCTLCMD)
+ return ret;
+
+ if (sdev->host->hostt->ioctl)
+ return sdev->host->hostt->ioctl(sdev, cmd, arg);
+
return -EINVAL;
}
EXPORT_SYMBOL(scsi_ioctl);
+#ifdef CONFIG_COMPAT
+int scsi_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
+{
+ int ret = scsi_ioctl_common(sdev, cmd, arg);
+
+ if (ret != -ENOIOCTLCMD)
+ return ret;
+
+ if (sdev->host->hostt->compat_ioctl)
+ return sdev->host->hostt->compat_ioctl(sdev, cmd, arg);
+
+ return ret;
+}
+EXPORT_SYMBOL(scsi_compat_ioctl);
+#endif
+
/*
* We can process a reset even when a device isn't fully operable.
*/
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 8e6d7ba..6f3d29d 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -52,7 +52,6 @@
#define SCSI_INLINE_SG_CNT 2
#endif
-static struct kmem_cache *scsi_sdb_cache;
static struct kmem_cache *scsi_sense_cache;
static struct kmem_cache *scsi_sense_isadma_cache;
static DEFINE_MUTEX(scsi_sense_cache_mutex);
@@ -189,7 +188,7 @@
* active on the host/device.
*/
if (unbusy)
- scsi_device_unbusy(device);
+ scsi_device_unbusy(device, cmd);
/*
* Requeue this command. It will go before all other commands
@@ -202,24 +201,17 @@
blk_mq_requeue_request(cmd->request, true);
}
-/*
- * Function: scsi_queue_insert()
+/**
+ * scsi_queue_insert - Reinsert a command in the queue.
+ * @cmd: command that we are adding to queue.
+ * @reason: why we are inserting command to queue.
*
- * Purpose: Insert a command in the midlevel queue.
+ * We do this for one of two cases. Either the host is busy and it cannot accept
+ * any more commands for the time being, or the device returned QUEUE_FULL and
+ * can accept no more commands.
*
- * Arguments: cmd - command that we are adding to queue.
- * reason - why we are inserting command to queue.
- *
- * Lock status: Assumed that lock is not held upon entry.
- *
- * Returns: Nothing.
- *
- * Notes: We do this for one of two cases. Either the host is busy
- * and it cannot accept any more commands for the time being,
- * or the device returned QUEUE_FULL and can accept no more
- * commands.
- * Notes: This could be called either from an interrupt context or a
- * normal process context.
+ * Context: This could be called either from an interrupt context or a normal
+ * process context.
*/
void scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
{
@@ -257,7 +249,8 @@
req = blk_get_request(sdev->request_queue,
data_direction == DMA_TO_DEVICE ?
- REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN, BLK_MQ_REQ_PREEMPT);
+ REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN,
+ rq_flags & RQF_PM ? BLK_MQ_REQ_PM : 0);
if (IS_ERR(req))
return ret;
rq = scsi_req(req);
@@ -302,39 +295,20 @@
EXPORT_SYMBOL(__scsi_execute);
/*
- * Function: scsi_init_cmd_errh()
- *
- * Purpose: Initialize cmd fields related to error handling.
- *
- * Arguments: cmd - command that is ready to be queued.
- *
- * Notes: This function has the job of initializing a number of
- * fields related to error handling. Typically this will
- * be called once for each command, as required.
- */
-static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)
-{
- scsi_set_resid(cmd, 0);
- memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
- if (cmd->cmd_len == 0)
- cmd->cmd_len = scsi_command_size(cmd->cmnd);
-}
-
-/*
- * Decrement the host_busy counter and wake up the error handler if necessary.
- * Avoid as follows that the error handler is not woken up if shost->host_busy
- * == shost->host_failed: use call_rcu() in scsi_eh_scmd_add() in combination
- * with an RCU read lock in this function to ensure that this function in its
- * entirety either finishes before scsi_eh_scmd_add() increases the
+ * Wake up the error handler if necessary. Avoid as follows that the error
+ * handler is not woken up if host in-flight requests number ==
+ * shost->host_failed: use call_rcu() in scsi_eh_scmd_add() in combination
+ * with an RCU read lock in this function to ensure that this function in
+ * its entirety either finishes before scsi_eh_scmd_add() increases the
* host_failed counter or that it notices the shost state change made by
* scsi_eh_scmd_add().
*/
-static void scsi_dec_host_busy(struct Scsi_Host *shost)
+static void scsi_dec_host_busy(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
{
unsigned long flags;
rcu_read_lock();
- atomic_dec(&shost->host_busy);
+ __clear_bit(SCMD_STATE_INFLIGHT, &cmd->state);
if (unlikely(scsi_host_in_recovery(shost))) {
spin_lock_irqsave(shost->host_lock, flags);
if (shost->host_failed || shost->host_eh_scheduled)
@@ -344,12 +318,12 @@
rcu_read_unlock();
}
-void scsi_device_unbusy(struct scsi_device *sdev)
+void scsi_device_unbusy(struct scsi_device *sdev, struct scsi_cmnd *cmd)
{
struct Scsi_Host *shost = sdev->host;
struct scsi_target *starget = scsi_target(sdev);
- scsi_dec_host_busy(shost);
+ scsi_dec_host_busy(shost, cmd);
if (starget->can_queue > 0)
atomic_dec(&starget->target_busy);
@@ -401,7 +375,7 @@
spin_unlock_irqrestore(shost->host_lock, flags);
scsi_kick_queue(sdev->request_queue);
spin_lock_irqsave(shost->host_lock, flags);
-
+
scsi_device_put(sdev);
}
out:
@@ -430,9 +404,6 @@
static inline bool scsi_host_is_busy(struct Scsi_Host *shost)
{
- if (shost->can_queue > 0 &&
- atomic_read(&shost->host_busy) >= shost->can_queue)
- return true;
if (atomic_read(&shost->host_blocked) > 0)
return true;
if (shost->host_self_blocked)
@@ -499,17 +470,11 @@
spin_unlock_irqrestore(shost->host_lock, flags);
}
-/*
- * Function: scsi_run_queue()
+/**
+ * scsi_run_queue - Select a proper request queue to serve next.
+ * @q: last request's queue
*
- * Purpose: Select a proper request queue to serve next
- *
- * Arguments: q - last request's queue
- *
- * Returns: Nothing
- *
- * Notes: The previous command was completely finished, start
- * a new one if possible.
+ * The previous command was completely finished, start a new one if possible.
*/
static void scsi_run_queue(struct request_queue *q)
{
@@ -551,7 +516,7 @@
}
}
-static void scsi_free_sgtables(struct scsi_cmnd *cmd)
+void scsi_free_sgtables(struct scsi_cmnd *cmd)
{
if (cmd->sdb.table.nents)
sg_free_table_chained(&cmd->sdb.table,
@@ -560,21 +525,38 @@
sg_free_table_chained(&cmd->prot_sdb->table,
SCSI_INLINE_PROT_SG_CNT);
}
+EXPORT_SYMBOL_GPL(scsi_free_sgtables);
static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd)
{
scsi_free_sgtables(cmd);
scsi_uninit_cmd(cmd);
- scsi_del_cmd_from_list(cmd);
}
static void scsi_run_queue_async(struct scsi_device *sdev)
{
if (scsi_target(sdev)->single_lun ||
- !list_empty(&sdev->host->starved_list))
+ !list_empty(&sdev->host->starved_list)) {
kblockd_schedule_work(&sdev->requeue_work);
- else
- blk_mq_run_hw_queues(sdev->request_queue, true);
+ } else {
+ /*
+ * smp_mb() present in sbitmap_queue_clear() or implied in
+ * .end_io is for ordering writing .device_busy in
+ * scsi_device_unbusy() and reading sdev->restarts.
+ */
+ int old = atomic_read(&sdev->restarts);
+
+ /*
+ * ->restarts has to be kept as non-zero if new budget
+ * contention occurs.
+ *
+ * No need to run queue when either another re-run
+ * queue wins in updating ->restarts or a new budget
+ * contention occurs.
+ */
+ if (old && atomic_cmpxchg(&sdev->restarts, old, 0) == old)
+ blk_mq_run_hw_queues(sdev->request_queue, true);
+ }
}
/* Returns false when no more bytes to process, true if there are more */
@@ -674,6 +656,23 @@
scsi_mq_requeue_cmd(cmd);
}
+static bool scsi_cmd_runtime_exceeced(struct scsi_cmnd *cmd)
+{
+ struct request *req = cmd->request;
+ unsigned long wait_for;
+
+ if (cmd->allowed == SCSI_CMD_RETRIES_NO_LIMIT)
+ return false;
+
+ wait_for = (cmd->allowed + 1) * req->timeout;
+ if (time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
+ scmd_printk(KERN_ERR, cmd, "timing out command, waited %lus\n",
+ wait_for/HZ);
+ return true;
+ }
+ return false;
+}
+
/* Helper for scsi_io_completion() when special action required. */
static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
{
@@ -682,7 +681,6 @@
int level = 0;
enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY,
ACTION_DELAYED_RETRY} action;
- unsigned long wait_for = (cmd->allowed + 1) * req->timeout;
struct scsi_sense_hdr sshdr;
bool sense_valid;
bool sense_current = true; /* false implies "deferred sense" */
@@ -781,6 +779,15 @@
/* See SSC3rXX or current. */
action = ACTION_FAIL;
break;
+ case DATA_PROTECT:
+ action = ACTION_FAIL;
+ if ((sshdr.asc == 0x0C && sshdr.ascq == 0x12) ||
+ (sshdr.asc == 0x55 &&
+ (sshdr.ascq == 0x0E || sshdr.ascq == 0x0F))) {
+ /* Insufficient zone resources */
+ blk_stat = BLK_STS_ZONE_OPEN_RESOURCE;
+ }
+ break;
default:
action = ACTION_FAIL;
break;
@@ -788,8 +795,7 @@
} else
action = ACTION_FAIL;
- if (action != ACTION_FAIL &&
- time_before(cmd->jiffies_at_alloc + wait_for, jiffies))
+ if (action != ACTION_FAIL && scsi_cmd_runtime_exceeced(cmd))
action = ACTION_FAIL;
switch (action) {
@@ -818,7 +824,7 @@
}
if (!scsi_end_request(req, blk_stat, blk_rq_err_bytes(req)))
return;
- /*FALLTHRU*/
+ fallthrough;
case ACTION_REPREP:
scsi_io_completion_reprep(cmd, q);
break;
@@ -906,34 +912,27 @@
return result;
}
-/*
- * Function: scsi_io_completion()
+/**
+ * scsi_io_completion - Completion processing for SCSI commands.
+ * @cmd: command that is finished.
+ * @good_bytes: number of processed bytes.
*
- * Purpose: Completion processing for block device I/O requests.
+ * We will finish off the specified number of sectors. If we are done, the
+ * command block will be released and the queue function will be goosed. If we
+ * are not done then we have to figure out what to do next:
*
- * Arguments: cmd - command that is finished.
+ * a) We can call scsi_io_completion_reprep(). The request will be
+ * unprepared and put back on the queue. Then a new command will
+ * be created for it. This should be used if we made forward
+ * progress, or if we want to switch from READ(10) to READ(6) for
+ * example.
*
- * Lock status: Assumed that no lock is held upon entry.
+ * b) We can call scsi_io_completion_action(). The request will be
+ * put back on the queue and retried using the same command as
+ * before, possibly after a delay.
*
- * Returns: Nothing
- *
- * Notes: We will finish off the specified number of sectors. If we
- * are done, the command block will be released and the queue
- * function will be goosed. If we are not done then we have to
- * figure out what to do next:
- *
- * a) We can call scsi_requeue_command(). The request
- * will be unprepared and put back on the queue. Then
- * a new command will be created for it. This should
- * be used if we made forward progress, or if we want
- * to switch from READ(10) to READ(6) for example.
- *
- * b) We can call __scsi_queue_insert(). The request will
- * be put back on the queue and retried using the same
- * command as before, possibly after a delay.
- *
- * c) We can call scsi_end_request() with blk_stat other than
- * BLK_STS_OK, to fail the remainder of the request.
+ * c) We can call scsi_end_request() with blk_stat other than
+ * BLK_STS_OK, to fail the remainder of the request.
*/
void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
{
@@ -961,8 +960,7 @@
blk_rq_sectors(req), good_bytes));
/*
- * Next deal with any sectors which we were able to correctly
- * handle. Failed, zero length commands always need to drop down
+ * Failed, zero length commands always need to drop down
* to retry code. Fast path should return in this block.
*/
if (likely(blk_rq_bytes(req) > 0 || blk_stat == BLK_STS_OK)) {
@@ -988,56 +986,81 @@
scsi_io_completion_action(cmd, result);
}
-static blk_status_t scsi_init_sgtable(struct request *req,
- struct scsi_data_buffer *sdb)
+static inline bool scsi_cmd_needs_dma_drain(struct scsi_device *sdev,
+ struct request *rq)
{
+ return sdev->dma_drain_len && blk_rq_is_passthrough(rq) &&
+ !op_is_write(req_op(rq)) &&
+ sdev->host->hostt->dma_need_drain(rq);
+}
+
+/**
+ * scsi_alloc_sgtables - allocate S/G tables for a command
+ * @cmd: command descriptor we wish to initialize
+ *
+ * Returns:
+ * * BLK_STS_OK - on success
+ * * BLK_STS_RESOURCE - if the failure is retryable
+ * * BLK_STS_IOERR - if the failure is fatal
+ */
+blk_status_t scsi_alloc_sgtables(struct scsi_cmnd *cmd)
+{
+ struct scsi_device *sdev = cmd->device;
+ struct request *rq = cmd->request;
+ unsigned short nr_segs = blk_rq_nr_phys_segments(rq);
+ struct scatterlist *last_sg = NULL;
+ blk_status_t ret;
+ bool need_drain = scsi_cmd_needs_dma_drain(sdev, rq);
int count;
+ if (WARN_ON_ONCE(!nr_segs))
+ return BLK_STS_IOERR;
+
+ /*
+ * Make sure there is space for the drain. The driver must adjust
+ * max_hw_segments to be prepared for this.
+ */
+ if (need_drain)
+ nr_segs++;
+
/*
* If sg table allocation fails, requeue request later.
*/
- if (unlikely(sg_alloc_table_chained(&sdb->table,
- blk_rq_nr_phys_segments(req), sdb->table.sgl,
- SCSI_INLINE_SG_CNT)))
+ if (unlikely(sg_alloc_table_chained(&cmd->sdb.table, nr_segs,
+ cmd->sdb.table.sgl, SCSI_INLINE_SG_CNT)))
return BLK_STS_RESOURCE;
- /*
+ /*
* Next, walk the list, and fill in the addresses and sizes of
* each segment.
*/
- count = blk_rq_map_sg(req->q, req, sdb->table.sgl);
- BUG_ON(count > sdb->table.nents);
- sdb->table.nents = count;
- sdb->length = blk_rq_payload_bytes(req);
- return BLK_STS_OK;
-}
+ count = __blk_rq_map_sg(rq->q, rq, cmd->sdb.table.sgl, &last_sg);
-/*
- * Function: scsi_init_io()
- *
- * Purpose: SCSI I/O initialize function.
- *
- * Arguments: cmd - Command descriptor we wish to initialize
- *
- * Returns: BLK_STS_OK on success
- * BLK_STS_RESOURCE if the failure is retryable
- * BLK_STS_IOERR if the failure is fatal
- */
-blk_status_t scsi_init_io(struct scsi_cmnd *cmd)
-{
- struct request *rq = cmd->request;
- blk_status_t ret;
+ if (blk_rq_bytes(rq) & rq->q->dma_pad_mask) {
+ unsigned int pad_len =
+ (rq->q->dma_pad_mask & ~blk_rq_bytes(rq)) + 1;
- if (WARN_ON_ONCE(!blk_rq_nr_phys_segments(rq)))
- return BLK_STS_IOERR;
+ last_sg->length += pad_len;
+ cmd->extra_len += pad_len;
+ }
- ret = scsi_init_sgtable(rq, &cmd->sdb);
- if (ret)
- return ret;
+ if (need_drain) {
+ sg_unmark_end(last_sg);
+ last_sg = sg_next(last_sg);
+ sg_set_buf(last_sg, sdev->dma_drain_buf, sdev->dma_drain_len);
+ sg_mark_end(last_sg);
+
+ cmd->extra_len += sdev->dma_drain_len;
+ count++;
+ }
+
+ BUG_ON(count > cmd->sdb.table.nents);
+ cmd->sdb.table.nents = count;
+ cmd->sdb.length = blk_rq_payload_bytes(rq);
if (blk_integrity_rq(rq)) {
struct scsi_data_buffer *prot_sdb = cmd->prot_sdb;
- int ivecs, count;
+ int ivecs;
if (WARN_ON_ONCE(!prot_sdb)) {
/*
@@ -1072,7 +1095,7 @@
scsi_free_sgtables(cmd);
return ret;
}
-EXPORT_SYMBOL(scsi_init_io);
+EXPORT_SYMBOL(scsi_alloc_sgtables);
/**
* scsi_initialize_rq - initialize struct scsi_cmnd partially
@@ -1107,36 +1130,7 @@
}
}
-/* Add a command to the list used by the aacraid and dpt_i2o drivers */
-void scsi_add_cmd_to_list(struct scsi_cmnd *cmd)
-{
- struct scsi_device *sdev = cmd->device;
- struct Scsi_Host *shost = sdev->host;
- unsigned long flags;
-
- if (shost->use_cmd_list) {
- spin_lock_irqsave(&sdev->list_lock, flags);
- list_add_tail(&cmd->list, &sdev->cmd_list);
- spin_unlock_irqrestore(&sdev->list_lock, flags);
- }
-}
-
-/* Remove a command from the list used by the aacraid and dpt_i2o drivers */
-void scsi_del_cmd_from_list(struct scsi_cmnd *cmd)
-{
- struct scsi_device *sdev = cmd->device;
- struct Scsi_Host *shost = sdev->host;
- unsigned long flags;
-
- if (shost->use_cmd_list) {
- spin_lock_irqsave(&sdev->list_lock, flags);
- BUG_ON(list_empty(&cmd->list));
- list_del_init(&cmd->list);
- spin_unlock_irqrestore(&sdev->list_lock, flags);
- }
-}
-
-/* Called after a request has been started. */
+/* Called before a request is prepared. See also scsi_mq_prep_fn(). */
void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd)
{
void *buf = cmd->sense_buffer;
@@ -1144,7 +1138,8 @@
struct request *rq = blk_mq_rq_from_pdu(cmd);
unsigned int flags = cmd->flags & SCMD_PRESERVED_FLAGS;
unsigned long jiffies_at_alloc;
- int retries;
+ int retries, to_clear;
+ bool in_flight;
if (!blk_rq_is_scsi(rq) && !(flags & SCMD_INITIALIZED)) {
flags |= SCMD_INITIALIZED;
@@ -1153,9 +1148,16 @@
jiffies_at_alloc = cmd->jiffies_at_alloc;
retries = cmd->retries;
- /* zero out the cmd, except for the embedded scsi_request */
- memset((char *)cmd + sizeof(cmd->req), 0,
- sizeof(*cmd) - sizeof(cmd->req) + dev->host->hostt->cmd_size);
+ in_flight = test_bit(SCMD_STATE_INFLIGHT, &cmd->state);
+ /*
+ * Zero out the cmd, except for the embedded scsi_request. Only clear
+ * the driver-private command data if the LLD does not supply a
+ * function to initialize that data.
+ */
+ to_clear = sizeof(*cmd) - sizeof(cmd->req);
+ if (!dev->host->hostt->init_cmd_priv)
+ to_clear += dev->host->hostt->cmd_size;
+ memset((char *)cmd + sizeof(cmd->req), 0, to_clear);
cmd->device = dev;
cmd->sense_buffer = buf;
@@ -1164,8 +1166,9 @@
INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler);
cmd->jiffies_at_alloc = jiffies_at_alloc;
cmd->retries = retries;
+ if (in_flight)
+ __set_bit(SCMD_STATE_INFLIGHT, &cmd->state);
- scsi_add_cmd_to_list(cmd);
}
static blk_status_t scsi_setup_scsi_cmnd(struct scsi_device *sdev,
@@ -1180,7 +1183,7 @@
* submit a request without an attached bio.
*/
if (req->bio) {
- blk_status_t ret = scsi_init_io(cmd);
+ blk_status_t ret = scsi_alloc_sgtables(cmd);
if (unlikely(ret != BLK_STS_OK))
return ret;
} else {
@@ -1196,54 +1199,12 @@
return BLK_STS_OK;
}
-/*
- * Setup a normal block command. These are simple request from filesystems
- * that still need to be translated to SCSI CDBs from the ULD.
- */
-static blk_status_t scsi_setup_fs_cmnd(struct scsi_device *sdev,
- struct request *req)
-{
- struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
-
- if (unlikely(sdev->handler && sdev->handler->prep_fn)) {
- blk_status_t ret = sdev->handler->prep_fn(sdev, req);
- if (ret != BLK_STS_OK)
- return ret;
- }
-
- cmd->cmnd = scsi_req(req)->cmd = scsi_req(req)->__cmd;
- memset(cmd->cmnd, 0, BLK_MAX_CDB);
- return scsi_cmd_to_driver(cmd)->init_command(cmd);
-}
-
-static blk_status_t scsi_setup_cmnd(struct scsi_device *sdev,
- struct request *req)
-{
- struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
- blk_status_t ret;
-
- if (!blk_rq_bytes(req))
- cmd->sc_data_direction = DMA_NONE;
- else if (rq_data_dir(req) == WRITE)
- cmd->sc_data_direction = DMA_TO_DEVICE;
- else
- cmd->sc_data_direction = DMA_FROM_DEVICE;
-
- if (blk_rq_is_scsi(req))
- ret = scsi_setup_scsi_cmnd(sdev, req);
- else
- ret = scsi_setup_fs_cmnd(sdev, req);
-
- if (ret != BLK_STS_OK)
- scsi_free_sgtables(cmd);
-
- return ret;
-}
-
static blk_status_t
-scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
+scsi_device_state_check(struct scsi_device *sdev, struct request *req)
{
switch (sdev->sdev_state) {
+ case SDEV_CREATED:
+ return BLK_STS_OK;
case SDEV_OFFLINE:
case SDEV_TRANSPORT_OFFLINE:
/*
@@ -1251,8 +1212,11 @@
* commands. The device must be brought online
* before trying any recovery commands.
*/
- sdev_printk(KERN_ERR, sdev,
- "rejecting I/O to offline device\n");
+ if (!sdev->offline_already) {
+ sdev->offline_already = true;
+ sdev_printk(KERN_ERR, sdev,
+ "rejecting I/O to offline device\n");
+ }
return BLK_STS_IOERR;
case SDEV_DEL:
/*
@@ -1267,18 +1231,18 @@
return BLK_STS_RESOURCE;
case SDEV_QUIESCE:
/*
- * If the devices is blocked we defer normal commands.
+ * If the device is blocked we only accept power management
+ * commands.
*/
- if (req && !(req->rq_flags & RQF_PREEMPT))
+ if (req && WARN_ON_ONCE(!(req->rq_flags & RQF_PM)))
return BLK_STS_RESOURCE;
return BLK_STS_OK;
default:
/*
* For any other not fully online state we only allow
- * special commands. In particular any user initiated
- * command is not allowed.
+ * power management commands.
*/
- if (req && !(req->rq_flags & RQF_PREEMPT))
+ if (req && !(req->rq_flags & RQF_PM))
return BLK_STS_IOERR;
return BLK_STS_OK;
}
@@ -1379,16 +1343,14 @@
*/
static inline int scsi_host_queue_ready(struct request_queue *q,
struct Scsi_Host *shost,
- struct scsi_device *sdev)
+ struct scsi_device *sdev,
+ struct scsi_cmnd *cmd)
{
- unsigned int busy;
-
if (scsi_host_in_recovery(shost))
return 0;
- busy = atomic_inc_return(&shost->host_busy) - 1;
if (atomic_read(&shost->host_blocked) > 0) {
- if (busy)
+ if (scsi_host_busy(shost) > 0)
goto starved;
/*
@@ -1402,8 +1364,6 @@
"unblocking host at zero depth\n"));
}
- if (shost->can_queue > 0 && busy >= shost->can_queue)
- goto starved;
if (shost->host_self_blocked)
goto starved;
@@ -1415,6 +1375,8 @@
spin_unlock_irq(shost->host_lock);
}
+ __set_bit(SCMD_STATE_INFLIGHT, &cmd->state);
+
return 1;
starved:
@@ -1423,7 +1385,7 @@
list_add_tail(&sdev->starved_entry, &shost->starved_list);
spin_unlock_irq(shost->host_lock);
out_dec:
- scsi_dec_host_busy(shost);
+ scsi_dec_host_busy(shost, cmd);
return 0;
}
@@ -1464,7 +1426,6 @@
static void scsi_softirq_done(struct request *rq)
{
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
- unsigned long wait_for = (cmd->allowed + 1) * rq->timeout;
int disposition;
INIT_LIST_HEAD(&cmd->eh_entry);
@@ -1474,29 +1435,24 @@
atomic_inc(&cmd->device->ioerr_cnt);
disposition = scsi_decide_disposition(cmd);
- if (disposition != SUCCESS &&
- time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
- scmd_printk(KERN_ERR, cmd,
- "timing out command, waited %lus\n",
- wait_for/HZ);
+ if (disposition != SUCCESS && scsi_cmd_runtime_exceeced(cmd))
disposition = SUCCESS;
- }
scsi_log_completion(cmd, disposition);
switch (disposition) {
- case SUCCESS:
- scsi_finish_command(cmd);
- break;
- case NEEDS_RETRY:
- scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY);
- break;
- case ADD_TO_MLQUEUE:
- scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
- break;
- default:
- scsi_eh_scmd_add(cmd);
- break;
+ case SUCCESS:
+ scsi_finish_command(cmd);
+ break;
+ case NEEDS_RETRY:
+ scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY);
+ break;
+ case ADD_TO_MLQUEUE:
+ scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
+ break;
+ default:
+ scsi_eh_scmd_add(cmd);
+ break;
}
}
@@ -1588,7 +1544,7 @@
sizeof(struct scatterlist);
}
-static blk_status_t scsi_mq_prep_fn(struct request *req)
+static blk_status_t scsi_prepare_cmd(struct request *req)
{
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
struct scsi_device *sdev = req->q->queuedata;
@@ -1600,6 +1556,10 @@
cmd->request = req;
cmd->tag = req->tag;
cmd->prot_op = SCSI_PROT_NORMAL;
+ if (blk_rq_bytes(req))
+ cmd->sc_data_direction = rq_dma_dir(req);
+ else
+ cmd->sc_data_direction = DMA_NONE;
sg = (void *)cmd + sizeof(struct scsi_cmnd) + shost->hostt->cmd_size;
cmd->sdb.table.sgl = sg;
@@ -1611,45 +1571,69 @@
(struct scatterlist *)(cmd->prot_sdb + 1);
}
- blk_mq_start_request(req);
+ /*
+ * Special handling for passthrough commands, which don't go to the ULP
+ * at all:
+ */
+ if (blk_rq_is_scsi(req))
+ return scsi_setup_scsi_cmnd(sdev, req);
- return scsi_setup_cmnd(sdev, req);
+ if (sdev->handler && sdev->handler->prep_fn) {
+ blk_status_t ret = sdev->handler->prep_fn(sdev, req);
+
+ if (ret != BLK_STS_OK)
+ return ret;
+ }
+
+ cmd->cmnd = scsi_req(req)->cmd = scsi_req(req)->__cmd;
+ memset(cmd->cmnd, 0, BLK_MAX_CDB);
+ return scsi_cmd_to_driver(cmd)->init_command(cmd);
}
static void scsi_mq_done(struct scsi_cmnd *cmd)
{
+ if (unlikely(blk_should_fake_timeout(cmd->request->q)))
+ return;
if (unlikely(test_and_set_bit(SCMD_STATE_COMPLETE, &cmd->state)))
return;
trace_scsi_dispatch_cmd_done(cmd);
-
- /*
- * If the block layer didn't complete the request due to a timeout
- * injection, scsi must clear its internal completed state so that the
- * timeout handler will see it needs to escalate its own error
- * recovery.
- */
- if (unlikely(!blk_mq_complete_request(cmd->request)))
- clear_bit(SCMD_STATE_COMPLETE, &cmd->state);
+ blk_mq_complete_request(cmd->request);
}
-static void scsi_mq_put_budget(struct blk_mq_hw_ctx *hctx)
+static void scsi_mq_put_budget(struct request_queue *q)
{
- struct request_queue *q = hctx->queue;
struct scsi_device *sdev = q->queuedata;
atomic_dec(&sdev->device_busy);
}
-static bool scsi_mq_get_budget(struct blk_mq_hw_ctx *hctx)
+static bool scsi_mq_get_budget(struct request_queue *q)
{
- struct request_queue *q = hctx->queue;
struct scsi_device *sdev = q->queuedata;
if (scsi_dev_queue_ready(q, sdev))
return true;
- if (atomic_read(&sdev->device_busy) == 0 && !scsi_device_blocked(sdev))
- blk_mq_delay_run_hw_queue(hctx, SCSI_QUEUE_DELAY);
+ atomic_inc(&sdev->restarts);
+
+ /*
+ * Orders atomic_inc(&sdev->restarts) and atomic_read(&sdev->device_busy).
+ * .restarts must be incremented before .device_busy is read because the
+ * code in scsi_run_queue_async() depends on the order of these operations.
+ */
+ smp_mb__after_atomic();
+
+ /*
+ * If all in-flight requests originated from this LUN are completed
+ * before reading .device_busy, sdev->device_busy will be observed as
+ * zero, then blk_mq_delay_run_hw_queues() will dispatch this request
+ * soon. Otherwise, completion of one of these requests will observe
+ * the .restarts flag, and the request queue will be run for handling
+ * this request, see scsi_end_request().
+ */
+ if (unlikely(atomic_read(&sdev->device_busy) == 0 &&
+ !scsi_device_blocked(sdev)))
+ blk_mq_delay_run_hw_queues(sdev->request_queue, SCSI_QUEUE_DELAY);
return false;
}
@@ -1669,7 +1653,7 @@
* commands.
*/
if (unlikely(sdev->sdev_state != SDEV_RUNNING)) {
- ret = scsi_prep_state_check(sdev, req);
+ ret = scsi_device_state_check(sdev, req);
if (ret != BLK_STS_OK)
goto out_put_budget;
}
@@ -1677,17 +1661,16 @@
ret = BLK_STS_RESOURCE;
if (!scsi_target_queue_ready(shost, sdev))
goto out_put_budget;
- if (!scsi_host_queue_ready(q, shost, sdev))
+ if (!scsi_host_queue_ready(q, shost, sdev, cmd))
goto out_dec_target_busy;
if (!(req->rq_flags & RQF_DONTPREP)) {
- ret = scsi_mq_prep_fn(req);
+ ret = scsi_prepare_cmd(req);
if (ret != BLK_STS_OK)
goto out_dec_host_busy;
req->rq_flags |= RQF_DONTPREP;
} else {
clear_bit(SCMD_STATE_COMPLETE, &cmd->state);
- blk_mq_start_request(req);
}
cmd->flags &= SCMD_PRESERVED_FLAGS;
@@ -1696,9 +1679,11 @@
if (bd->last)
cmd->flags |= SCMD_LAST;
- scsi_init_cmd_errh(cmd);
+ scsi_set_resid(cmd, 0);
+ memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
cmd->scsi_done = scsi_mq_done;
+ blk_mq_start_request(req);
reason = scsi_dispatch_cmd(cmd);
if (reason) {
scsi_set_blocked(cmd, reason);
@@ -1709,18 +1694,18 @@
return BLK_STS_OK;
out_dec_host_busy:
- scsi_dec_host_busy(shost);
+ scsi_dec_host_busy(shost, cmd);
out_dec_target_busy:
if (scsi_target(sdev)->can_queue > 0)
atomic_dec(&scsi_target(sdev)->target_busy);
out_put_budget:
- scsi_mq_put_budget(hctx);
+ scsi_mq_put_budget(q);
switch (ret) {
case BLK_STS_OK:
break;
case BLK_STS_RESOURCE:
- if (atomic_read(&sdev->device_busy) ||
- scsi_device_blocked(sdev))
+ case BLK_STS_ZONE_RESOURCE:
+ if (scsi_device_blocked(sdev))
ret = BLK_STS_DEV_RESOURCE;
break;
default:
@@ -1756,6 +1741,7 @@
const bool unchecked_isa_dma = shost->unchecked_isa_dma;
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
struct scatterlist *sg;
+ int ret = 0;
if (unchecked_isa_dma)
cmd->flags |= SCMD_UNCHECKED_ISA_DMA;
@@ -1771,14 +1757,24 @@
cmd->prot_sdb = (void *)sg + scsi_mq_inline_sgl_size(shost);
}
- return 0;
+ if (shost->hostt->init_cmd_priv) {
+ ret = shost->hostt->init_cmd_priv(shost, cmd);
+ if (ret < 0)
+ scsi_free_sense_buffer(unchecked_isa_dma,
+ cmd->sense_buffer);
+ }
+
+ return ret;
}
static void scsi_mq_exit_request(struct blk_mq_tag_set *set, struct request *rq,
unsigned int hctx_idx)
{
+ struct Scsi_Host *shost = set->driver_data;
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
+ if (shost->hostt->exit_cmd_priv)
+ shost->hostt->exit_cmd_priv(shost, cmd);
scsi_free_sense_buffer(cmd->flags & SCMD_UNCHECKED_ISA_DMA,
cmd->sense_buffer);
}
@@ -1895,6 +1891,7 @@
int scsi_mq_setup_tags(struct Scsi_Host *shost)
{
unsigned int cmd_size, sgl_size;
+ struct blk_mq_tag_set *tag_set = &shost->tag_set;
sgl_size = max_t(unsigned int, sizeof(struct scatterlist),
scsi_mq_inline_sgl_size(shost));
@@ -1903,21 +1900,23 @@
cmd_size += sizeof(struct scsi_data_buffer) +
sizeof(struct scatterlist) * SCSI_INLINE_PROT_SG_CNT;
- memset(&shost->tag_set, 0, sizeof(shost->tag_set));
+ memset(tag_set, 0, sizeof(*tag_set));
if (shost->hostt->commit_rqs)
- shost->tag_set.ops = &scsi_mq_ops;
+ tag_set->ops = &scsi_mq_ops;
else
- shost->tag_set.ops = &scsi_mq_ops_no_commit;
- shost->tag_set.nr_hw_queues = shost->nr_hw_queues ? : 1;
- shost->tag_set.queue_depth = shost->can_queue;
- shost->tag_set.cmd_size = cmd_size;
- shost->tag_set.numa_node = NUMA_NO_NODE;
- shost->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
- shost->tag_set.flags |=
+ tag_set->ops = &scsi_mq_ops_no_commit;
+ tag_set->nr_hw_queues = shost->nr_hw_queues ? : 1;
+ tag_set->queue_depth = shost->can_queue;
+ tag_set->cmd_size = cmd_size;
+ tag_set->numa_node = NUMA_NO_NODE;
+ tag_set->flags = BLK_MQ_F_SHOULD_MERGE;
+ tag_set->flags |=
BLK_ALLOC_POLICY_TO_MQ_FLAG(shost->hostt->tag_alloc_policy);
- shost->tag_set.driver_data = shost;
+ tag_set->driver_data = shost;
+ if (shost->host_tagset)
+ tag_set->flags |= BLK_MQ_F_TAG_HCTX_SHARED;
- return blk_mq_alloc_tag_set(&shost->tag_set);
+ return blk_mq_alloc_tag_set(tag_set);
}
void scsi_mq_destroy_tags(struct Scsi_Host *shost)
@@ -1944,23 +1943,14 @@
return sdev;
}
-EXPORT_SYMBOL_GPL(scsi_device_from_queue);
-/*
- * Function: scsi_block_requests()
+/**
+ * scsi_block_requests - Utility function used by low-level drivers to prevent
+ * further commands from being queued to the device.
+ * @shost: host in question
*
- * Purpose: Utility function used by low-level drivers to prevent further
- * commands from being queued to the device.
- *
- * Arguments: shost - Host in question
- *
- * Returns: Nothing
- *
- * Lock status: No locks are assumed held.
- *
- * Notes: There is no timer nor any other means by which the requests
- * get unblocked other than the low-level driver calling
- * scsi_unblock_requests().
+ * There is no timer nor any other means by which the requests get unblocked
+ * other than the low-level driver calling scsi_unblock_requests().
*/
void scsi_block_requests(struct Scsi_Host *shost)
{
@@ -1968,25 +1958,15 @@
}
EXPORT_SYMBOL(scsi_block_requests);
-/*
- * Function: scsi_unblock_requests()
+/**
+ * scsi_unblock_requests - Utility function used by low-level drivers to allow
+ * further commands to be queued to the device.
+ * @shost: host in question
*
- * Purpose: Utility function used by low-level drivers to allow further
- * commands from being queued to the device.
- *
- * Arguments: shost - Host in question
- *
- * Returns: Nothing
- *
- * Lock status: No locks are assumed held.
- *
- * Notes: There is no timer nor any other means by which the requests
- * get unblocked other than the low-level driver calling
- * scsi_unblock_requests().
- *
- * This is done as an API function so that changes to the
- * internals of the scsi mid-layer won't require wholesale
- * changes to drivers that use this feature.
+ * There is no timer nor any other means by which the requests get unblocked
+ * other than the low-level driver calling scsi_unblock_requests(). This is done
+ * as an API function so that changes to the internals of the scsi mid-layer
+ * won't require wholesale changes to drivers that use this feature.
*/
void scsi_unblock_requests(struct Scsi_Host *shost)
{
@@ -1995,24 +1975,10 @@
}
EXPORT_SYMBOL(scsi_unblock_requests);
-int __init scsi_init_queue(void)
-{
- scsi_sdb_cache = kmem_cache_create("scsi_data_buffer",
- sizeof(struct scsi_data_buffer),
- 0, 0, NULL);
- if (!scsi_sdb_cache) {
- printk(KERN_ERR "SCSI: can't init scsi sdb cache\n");
- return -ENOMEM;
- }
-
- return 0;
-}
-
void scsi_exit_queue(void)
{
kmem_cache_destroy(scsi_sense_cache);
kmem_cache_destroy(scsi_sense_isadma_cache);
- kmem_cache_destroy(scsi_sdb_cache);
}
/**
@@ -2079,7 +2045,6 @@
real_buffer[1] = data->medium_type;
real_buffer[2] = data->device_specific;
real_buffer[3] = data->block_descriptor_length;
-
cmd[0] = MODE_SELECT;
cmd[4] = len;
@@ -2105,9 +2070,7 @@
* @sshdr: place to put sense data (or NULL if no sense to be collected).
* must be SCSI_SENSE_BUFFERSIZE big.
*
- * Returns zero if unsuccessful, or the header offset (either 4
- * or 8 depending on whether a six or ten byte command was
- * issued) if successful.
+ * Returns zero if successful, or a negative error number on failure
*/
int
scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
@@ -2122,6 +2085,8 @@
memset(data, 0, sizeof(*data));
memset(&cmd[0], 0, 12);
+
+ dbd = sdev->set_dbd_for_ms ? 8 : dbd;
cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */
cmd[2] = modepage;
@@ -2152,6 +2117,8 @@
result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len,
sshdr, timeout, retries, NULL);
+ if (result < 0)
+ return result;
/* This code looks awful: what it's doing is making sure an
* ILLEGAL REQUEST sense return identifies the actual command
@@ -2163,7 +2130,7 @@
if (scsi_sense_valid(sshdr)) {
if ((sshdr->sense_key == ILLEGAL_REQUEST) &&
(sshdr->asc == 0x20) && (sshdr->ascq == 0)) {
- /*
+ /*
* Invalid command operation code
*/
sdev->use_10_for_ms = 0;
@@ -2172,7 +2139,7 @@
}
}
- if(scsi_status_is_good(result)) {
+ if (scsi_status_is_good(result)) {
if (unlikely(buffer[0] == 0x86 && buffer[1] == 0x0b &&
(modepage == 6 || modepage == 8))) {
/* Initio breakage? */
@@ -2182,7 +2149,7 @@
data->device_specific = 0;
data->longlba = 0;
data->block_descriptor_length = 0;
- } else if(use_10_for_ms) {
+ } else if (use_10_for_ms) {
data->length = buffer[0]*256 + buffer[1] + 2;
data->medium_type = buffer[2];
data->device_specific = buffer[3];
@@ -2196,13 +2163,15 @@
data->block_descriptor_length = buffer[3];
}
data->header_length = header_length;
+ result = 0;
} else if ((status_byte(result) == CHECK_CONDITION) &&
scsi_sense_valid(sshdr) &&
sshdr->sense_key == UNIT_ATTENTION && retry_count) {
retry_count--;
goto retry;
}
-
+ if (result > 0)
+ result = -EIO;
return result;
}
EXPORT_SYMBOL(scsi_mode_sense);
@@ -2265,7 +2234,7 @@
goto illegal;
}
break;
-
+
case SDEV_RUNNING:
switch (oldstate) {
case SDEV_CREATED:
@@ -2307,6 +2276,7 @@
switch (oldstate) {
case SDEV_RUNNING:
case SDEV_CREATED_BLOCK:
+ case SDEV_QUIESCE:
case SDEV_OFFLINE:
break;
default:
@@ -2352,6 +2322,7 @@
break;
}
+ sdev->offline_already = false;
sdev->sdev_state = state;
return 0;
@@ -2541,15 +2512,13 @@
EXPORT_SYMBOL_GPL(sdev_evt_send_simple);
/**
- * scsi_device_quiesce - Block user issued commands.
+ * scsi_device_quiesce - Block all commands except power management.
* @sdev: scsi device to quiesce.
*
* This works by trying to transition to the SDEV_QUIESCE state
* (which must be a legal transition). When the device is in this
- * state, only special requests will be accepted, all others will
- * be deferred. Since special requests may also be requeued requests,
- * a successful return doesn't guarantee the device will be
- * totally quiescent.
+ * state, only power management requests will be accepted, all others will
+ * be deferred.
*
* Must be called with user context, may sleep.
*
@@ -2611,12 +2580,12 @@
* device deleted during suspend)
*/
mutex_lock(&sdev->state_mutex);
+ if (sdev->sdev_state == SDEV_QUIESCE)
+ scsi_device_set_state(sdev, SDEV_RUNNING);
if (sdev->quiesced_by) {
sdev->quiesced_by = NULL;
blk_clear_pm_only(sdev->request_queue);
}
- if (sdev->sdev_state == SDEV_QUIESCE)
- scsi_device_set_state(sdev, SDEV_RUNNING);
mutex_unlock(&sdev->state_mutex);
}
EXPORT_SYMBOL(scsi_device_resume);
@@ -2674,10 +2643,10 @@
return err;
}
- /*
+ /*
* The device has transitioned to SDEV_BLOCK. Stop the
* block layer from calling the midlayer with this device's
- * request queue.
+ * request queue.
*/
blk_mq_quiesce_queue_nowait(q);
return 0;
@@ -2712,7 +2681,7 @@
return err;
}
-
+
void scsi_start_queue(struct scsi_device *sdev)
{
struct request_queue *q = sdev->request_queue;
@@ -2857,6 +2826,56 @@
}
EXPORT_SYMBOL_GPL(scsi_target_unblock);
+int
+scsi_host_block(struct Scsi_Host *shost)
+{
+ struct scsi_device *sdev;
+ int ret = 0;
+
+ /*
+ * Call scsi_internal_device_block_nowait so we can avoid
+ * calling synchronize_rcu() for each LUN.
+ */
+ shost_for_each_device(sdev, shost) {
+ mutex_lock(&sdev->state_mutex);
+ ret = scsi_internal_device_block_nowait(sdev);
+ mutex_unlock(&sdev->state_mutex);
+ if (ret) {
+ scsi_device_put(sdev);
+ break;
+ }
+ }
+
+ /*
+ * SCSI never enables blk-mq's BLK_MQ_F_BLOCKING flag so
+ * calling synchronize_rcu() once is enough.
+ */
+ WARN_ON_ONCE(shost->tag_set.flags & BLK_MQ_F_BLOCKING);
+
+ if (!ret)
+ synchronize_rcu();
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(scsi_host_block);
+
+int
+scsi_host_unblock(struct Scsi_Host *shost, int new_state)
+{
+ struct scsi_device *sdev;
+ int ret = 0;
+
+ shost_for_each_device(sdev, shost) {
+ ret = scsi_internal_device_unblock(sdev, new_state);
+ if (ret) {
+ scsi_device_put(sdev);
+ break;
+ }
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(scsi_host_unblock);
+
/**
* scsi_kmap_atomic_sg - find and atomically map an sg-elemnt
* @sgl: scatter-gather list
diff --git a/drivers/scsi/scsi_logging.c b/drivers/scsi/scsi_logging.c
index c6ed0b1..8ea44c6 100644
--- a/drivers/scsi/scsi_logging.c
+++ b/drivers/scsi/scsi_logging.c
@@ -205,13 +205,9 @@
/* Print opcode in one line and use separate lines for CDB */
off += scnprintf(logbuf + off, logbuf_len - off, "\n");
dev_printk(KERN_INFO, &cmd->device->sdev_gendev, "%s", logbuf);
- scsi_log_release_buffer(logbuf);
for (k = 0; k < cmd->cmd_len; k += 16) {
size_t linelen = min(cmd->cmd_len - k, 16);
- logbuf = scsi_log_reserve_buffer(&logbuf_len);
- if (!logbuf)
- break;
off = sdev_format_header(logbuf, logbuf_len,
scmd_name(cmd),
cmd->request->tag);
@@ -224,9 +220,8 @@
}
dev_printk(KERN_INFO, &cmd->device->sdev_gendev, "%s",
logbuf);
- scsi_log_release_buffer(logbuf);
}
- return;
+ goto out;
}
if (!WARN_ON(off > logbuf_len - 49)) {
off += scnprintf(logbuf + off, logbuf_len - off, " ");
@@ -236,6 +231,7 @@
}
out_printk:
dev_printk(KERN_INFO, &cmd->device->sdev_gendev, "%s", logbuf);
+out:
scsi_log_release_buffer(logbuf);
}
EXPORT_SYMBOL(scsi_print_command);
@@ -390,6 +386,7 @@
const char *mlret_string = scsi_mlreturn_string(disposition);
const char *hb_string = scsi_hostbyte_string(cmd->result);
const char *db_string = scsi_driverbyte_string(cmd->result);
+ unsigned long cmd_age = (jiffies - cmd->jiffies_at_alloc) / HZ;
logbuf = scsi_log_reserve_buffer(&logbuf_len);
if (!logbuf)
@@ -431,10 +428,15 @@
if (db_string)
off += scnprintf(logbuf + off, logbuf_len - off,
- "driverbyte=%s", db_string);
+ "driverbyte=%s ", db_string);
else
off += scnprintf(logbuf + off, logbuf_len - off,
- "driverbyte=0x%02x", driver_byte(cmd->result));
+ "driverbyte=0x%02x ",
+ driver_byte(cmd->result));
+
+ off += scnprintf(logbuf + off, logbuf_len - off,
+ "cmd_age=%lus", cmd_age);
+
out_printk:
dev_printk(KERN_INFO, &cmd->device->sdev_gendev, "%s", logbuf);
scsi_log_release_buffer(logbuf);
diff --git a/drivers/scsi/scsi_logging.h b/drivers/scsi/scsi_logging.h
index 836185d..3df8778 100644
--- a/drivers/scsi/scsi_logging.h
+++ b/drivers/scsi/scsi_logging.h
@@ -53,7 +53,7 @@
} while (0)
#else
#define SCSI_LOG_LEVEL(SHIFT, BITS) 0
-#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD)
+#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) do { } while (0)
#endif /* CONFIG_SCSI_LOGGING */
/*
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index 5f0ad8b..e91a0a5 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -80,10 +80,6 @@
dev_dbg(dev, "scsi resume: %d\n", err);
if (err == 0) {
- bool was_runtime_suspended;
-
- was_runtime_suspended = pm_runtime_suspended(dev);
-
pm_runtime_disable(dev);
err = pm_runtime_set_active(dev);
pm_runtime_enable(dev);
@@ -97,10 +93,8 @@
*/
if (!err && scsi_is_sdev_device(dev)) {
struct scsi_device *sdev = to_scsi_device(dev);
- if (was_runtime_suspended)
- blk_post_runtime_resume(sdev->request_queue, 0);
- else
- blk_set_runtime_active(sdev->request_queue);
+
+ blk_set_runtime_active(sdev->request_queue);
}
}
@@ -268,7 +262,7 @@
blk_pre_runtime_resume(sdev->request_queue);
if (pm && pm->runtime_resume)
err = pm->runtime_resume(dev);
- blk_post_runtime_resume(sdev->request_queue, err);
+ blk_post_runtime_resume(sdev->request_queue);
return err;
}
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index cc2859d..180636d 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -15,6 +15,7 @@
struct Scsi_Host;
struct scsi_nl_hdr;
+#define SCSI_CMD_RETRIES_NO_LIMIT -1
/*
* Scsi Error Handler Flags
@@ -29,7 +30,6 @@
extern void scsi_exit_hosts(void);
/* scsi.c */
-extern bool scsi_use_blk_mq;
int scsi_init_sense_cache(struct Scsi_Host *shost);
void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd);
#ifdef CONFIG_SCSI_LOGGING
@@ -84,10 +84,8 @@
int scsi_noretry_cmd(struct scsi_cmnd *scmd);
/* scsi_lib.c */
-extern void scsi_add_cmd_to_list(struct scsi_cmnd *cmd);
-extern void scsi_del_cmd_from_list(struct scsi_cmnd *cmd);
extern int scsi_maybe_unblock_host(struct scsi_device *sdev);
-extern void scsi_device_unbusy(struct scsi_device *sdev);
+extern void scsi_device_unbusy(struct scsi_device *sdev, struct scsi_cmnd *cmd);
extern void scsi_queue_insert(struct scsi_cmnd *cmd, int reason);
extern void scsi_io_completion(struct scsi_cmnd *, unsigned int);
extern void scsi_run_host_queues(struct Scsi_Host *shost);
@@ -96,7 +94,6 @@
extern void scsi_start_queue(struct scsi_device *sdev);
extern int scsi_mq_setup_tags(struct Scsi_Host *shost);
extern void scsi_mq_destroy_tags(struct Scsi_Host *shost);
-extern int scsi_init_queue(void);
extern void scsi_exit_queue(void);
extern void scsi_evt_thread(struct work_struct *work);
struct request_queue;
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index 5b31322..d6982d3 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -83,12 +83,12 @@
4 * PAGE_SIZE);
}
-static const struct file_operations proc_scsi_fops = {
- .open = proc_scsi_host_open,
- .release = single_release,
- .read = seq_read,
- .llseek = seq_lseek,
- .write = proc_scsi_host_write
+static const struct proc_ops proc_scsi_ops = {
+ .proc_open = proc_scsi_host_open,
+ .proc_release = single_release,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_write = proc_scsi_host_write
};
/**
@@ -146,7 +146,7 @@
sprintf(name,"%d", shost->host_no);
p = proc_create_data(name, S_IRUGO | S_IWUSR,
- sht->proc_dir, &proc_scsi_fops, shost);
+ sht->proc_dir, &proc_scsi_ops, shost);
if (!p)
printk(KERN_ERR "%s: Failed to register host %d in"
"%s\n", __func__, shost->host_no,
@@ -436,13 +436,12 @@
return seq_open(file, &scsi_seq_ops);
}
-static const struct file_operations proc_scsi_operations = {
- .owner = THIS_MODULE,
- .open = proc_scsi_open,
- .read = seq_read,
- .write = proc_scsi_write,
- .llseek = seq_lseek,
- .release = seq_release,
+static const struct proc_ops scsi_scsi_proc_ops = {
+ .proc_open = proc_scsi_open,
+ .proc_read = seq_read,
+ .proc_write = proc_scsi_write,
+ .proc_lseek = seq_lseek,
+ .proc_release = seq_release,
};
/**
@@ -456,7 +455,7 @@
if (!proc_scsi)
goto err1;
- pde = proc_create("scsi/scsi", 0, NULL, &proc_scsi_operations);
+ pde = proc_create("scsi/scsi", 0, NULL, &scsi_scsi_proc_ops);
if (!pde)
goto err2;
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 3fd109f..8e474b1 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -236,7 +236,6 @@
sdev->sdev_state = SDEV_CREATED;
INIT_LIST_HEAD(&sdev->siblings);
INIT_LIST_HEAD(&sdev->same_target_siblings);
- INIT_LIST_HEAD(&sdev->cmd_list);
INIT_LIST_HEAD(&sdev->starved_entry);
INIT_LIST_HEAD(&sdev->event_list);
spin_lock_init(&sdev->list_lock);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 6aeb79e..42db9c5 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -393,6 +393,16 @@
}
static DEVICE_ATTR(use_blk_mq, S_IRUGO, show_use_blk_mq, NULL);
+static ssize_t
+show_nr_hw_queues(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct blk_mq_tag_set *tag_set = &shost->tag_set;
+
+ return snprintf(buf, 20, "%d\n", tag_set->nr_hw_queues);
+}
+static DEVICE_ATTR(nr_hw_queues, S_IRUGO, show_nr_hw_queues, NULL);
+
static struct attribute *scsi_sysfs_shost_attrs[] = {
&dev_attr_use_blk_mq.attr,
&dev_attr_unique_id.attr,
@@ -411,6 +421,7 @@
&dev_attr_prot_guard_type.attr,
&dev_attr_host_reset.attr,
&dev_attr_eh_deadline.attr,
+ &dev_attr_nr_hw_queues.attr,
NULL
};
@@ -437,10 +448,14 @@
struct device *parent;
struct list_head *this, *tmp;
struct scsi_vpd *vpd_pg80 = NULL, *vpd_pg83 = NULL;
+ struct scsi_vpd *vpd_pg0 = NULL, *vpd_pg89 = NULL;
unsigned long flags;
+ struct module *mod;
sdev = container_of(work, struct scsi_device, ew.work);
+ mod = sdev->host->hostt->module;
+
scsi_dh_release_device(sdev);
parent = sdev->sdev_gendev.parent;
@@ -466,26 +481,40 @@
sdev->request_queue = NULL;
mutex_lock(&sdev->inquiry_mutex);
- rcu_swap_protected(sdev->vpd_pg80, vpd_pg80,
- lockdep_is_held(&sdev->inquiry_mutex));
- rcu_swap_protected(sdev->vpd_pg83, vpd_pg83,
- lockdep_is_held(&sdev->inquiry_mutex));
+ vpd_pg0 = rcu_replace_pointer(sdev->vpd_pg0, vpd_pg0,
+ lockdep_is_held(&sdev->inquiry_mutex));
+ vpd_pg80 = rcu_replace_pointer(sdev->vpd_pg80, vpd_pg80,
+ lockdep_is_held(&sdev->inquiry_mutex));
+ vpd_pg83 = rcu_replace_pointer(sdev->vpd_pg83, vpd_pg83,
+ lockdep_is_held(&sdev->inquiry_mutex));
+ vpd_pg89 = rcu_replace_pointer(sdev->vpd_pg89, vpd_pg89,
+ lockdep_is_held(&sdev->inquiry_mutex));
mutex_unlock(&sdev->inquiry_mutex);
+ if (vpd_pg0)
+ kfree_rcu(vpd_pg0, rcu);
if (vpd_pg83)
kfree_rcu(vpd_pg83, rcu);
if (vpd_pg80)
kfree_rcu(vpd_pg80, rcu);
+ if (vpd_pg89)
+ kfree_rcu(vpd_pg89, rcu);
kfree(sdev->inquiry);
kfree(sdev);
if (parent)
put_device(parent);
+ module_put(mod);
}
static void scsi_device_dev_release(struct device *dev)
{
struct scsi_device *sdp = to_scsi_device(dev);
+
+ /* Set module pointer as NULL in case of module unloading */
+ if (!try_module_get(sdp->host->hostt->module))
+ sdp->host->hostt->module = NULL;
+
execute_in_process_context(scsi_device_dev_release_usercontext,
&sdp->ew);
}
@@ -767,6 +796,7 @@
int i, ret;
struct scsi_device *sdev = to_scsi_device(dev);
enum scsi_device_state state = 0;
+ bool rescan_dev = false;
for (i = 0; i < ARRAY_SIZE(sdev_states); i++) {
const int len = strlen(sdev_states[i].name);
@@ -785,20 +815,27 @@
}
mutex_lock(&sdev->state_mutex);
- ret = scsi_device_set_state(sdev, state);
- /*
- * If the device state changes to SDEV_RUNNING, we need to
- * run the queue to avoid I/O hang, and rescan the device
- * to revalidate it. Running the queue first is necessary
- * because another thread may be waiting inside
- * blk_mq_freeze_queue_wait() and because that call may be
- * waiting for pending I/O to finish.
- */
- if (ret == 0 && state == SDEV_RUNNING) {
+ if (sdev->sdev_state == SDEV_RUNNING && state == SDEV_RUNNING) {
+ ret = 0;
+ } else {
+ ret = scsi_device_set_state(sdev, state);
+ if (ret == 0 && state == SDEV_RUNNING)
+ rescan_dev = true;
+ }
+ mutex_unlock(&sdev->state_mutex);
+
+ if (rescan_dev) {
+ /*
+ * If the device state changes to SDEV_RUNNING, we need to
+ * run the queue to avoid I/O hang, and rescan the device
+ * to revalidate it. Running the queue first is necessary
+ * because another thread may be waiting inside
+ * blk_mq_freeze_queue_wait() and because that call may be
+ * waiting for pending I/O to finish.
+ */
blk_mq_run_hw_queues(sdev->request_queue, true);
scsi_rescan_device(dev);
}
- mutex_unlock(&sdev->state_mutex);
return ret == 0 ? count : -EINVAL;
}
@@ -853,7 +890,7 @@
struct bin_attribute *bin_attr, \
char *buf, loff_t off, size_t count) \
{ \
- struct device *dev = container_of(kobj, struct device, kobj); \
+ struct device *dev = kobj_to_dev(kobj); \
struct scsi_device *sdev = to_scsi_device(dev); \
struct scsi_vpd *vpd_page; \
int ret = -EINVAL; \
@@ -874,12 +911,14 @@
sdev_vpd_pg_attr(pg83);
sdev_vpd_pg_attr(pg80);
+sdev_vpd_pg_attr(pg89);
+sdev_vpd_pg_attr(pg0);
static ssize_t show_inquiry(struct file *filep, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct scsi_device *sdev = to_scsi_device(dev);
if (!sdev->inquiry)
@@ -1040,14 +1079,14 @@
name = sdev_bflags_name[i];
if (name)
- len += snprintf(buf + len, PAGE_SIZE - len,
- "%s%s", len ? " " : "", name);
+ len += scnprintf(buf + len, PAGE_SIZE - len,
+ "%s%s", len ? " " : "", name);
else
- len += snprintf(buf + len, PAGE_SIZE - len,
- "%sINVALID_BIT(%d)", len ? " " : "", i);
+ len += scnprintf(buf + len, PAGE_SIZE - len,
+ "%sINVALID_BIT(%d)", len ? " " : "", i);
}
if (len)
- len += snprintf(buf + len, PAGE_SIZE - len, "\n");
+ len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
return len;
}
static DEVICE_ATTR(blacklist, S_IRUGO, sdev_show_blacklist, NULL);
@@ -1176,7 +1215,7 @@
static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int i)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct scsi_device *sdev = to_scsi_device(dev);
@@ -1202,16 +1241,22 @@
static umode_t scsi_sdev_bin_attr_is_visible(struct kobject *kobj,
struct bin_attribute *attr, int i)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct scsi_device *sdev = to_scsi_device(dev);
+ if (attr == &dev_attr_vpd_pg0 && !sdev->vpd_pg0)
+ return 0;
+
if (attr == &dev_attr_vpd_pg80 && !sdev->vpd_pg80)
return 0;
if (attr == &dev_attr_vpd_pg83 && !sdev->vpd_pg83)
return 0;
+ if (attr == &dev_attr_vpd_pg89 && !sdev->vpd_pg89)
+ return 0;
+
return S_IRUGO;
}
@@ -1254,8 +1299,10 @@
};
static struct bin_attribute *scsi_sdev_bin_attrs[] = {
+ &dev_attr_vpd_pg0,
&dev_attr_vpd_pg83,
&dev_attr_vpd_pg80,
+ &dev_attr_vpd_pg89,
&dev_attr_inquiry,
NULL
};
@@ -1315,7 +1362,8 @@
device_enable_async_suspend(&sdev->sdev_gendev);
scsi_autopm_get_target(starget);
pm_runtime_set_active(&sdev->sdev_gendev);
- pm_runtime_forbid(&sdev->sdev_gendev);
+ if (!sdev->rpm_autosuspend)
+ pm_runtime_forbid(&sdev->sdev_gendev);
pm_runtime_enable(&sdev->sdev_gendev);
scsi_autopm_put_target(starget);
diff --git a/drivers/scsi/scsi_trace.c b/drivers/scsi/scsi_trace.c
index ac35c30..41a9500 100644
--- a/drivers/scsi/scsi_trace.c
+++ b/drivers/scsi/scsi_trace.c
@@ -18,11 +18,9 @@
scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len)
{
const char *ret = trace_seq_buffer_ptr(p);
- u32 lba = 0, txlen;
+ u32 lba, txlen;
- lba |= ((cdb[1] & 0x1F) << 16);
- lba |= (cdb[2] << 8);
- lba |= cdb[3];
+ lba = get_unaligned_be24(&cdb[1]) & 0x1fffff;
/*
* From SBC-2: a TRANSFER LENGTH field set to zero specifies that 256
* logical blocks shall be read (READ(6)) or written (WRITE(6)).
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 2732fa6..2ff7f06 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -253,6 +253,7 @@
{ FC_PORTSPEED_25GBIT, "25 Gbit" },
{ FC_PORTSPEED_64GBIT, "64 Gbit" },
{ FC_PORTSPEED_128GBIT, "128 Gbit" },
+ { FC_PORTSPEED_256GBIT, "256 Gbit" },
{ FC_PORTSPEED_NOT_NEGOTIATED, "Not Negotiated" },
};
fc_bitfield_name_search(port_speed, fc_port_speed_names)
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 77bba91..a5759d0 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -86,9 +86,17 @@
struct transport_container session_cont;
};
+/* Worker to perform connection failure on unresponsive connections
+ * completely in kernel space.
+ */
+static void stop_conn_work_fn(struct work_struct *work);
+static DECLARE_WORK(stop_conn_work, stop_conn_work_fn);
+
static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
static struct workqueue_struct *iscsi_eh_timer_workq;
+static struct workqueue_struct *iscsi_destroy_workq;
+
static DEFINE_IDA(iscsi_sess_ida);
/*
* list of registered transports and lock that must
@@ -434,9 +442,7 @@
struct iscsi_transport *t = iface->transport;
int param = -1;
- if (attr == &dev_attr_iface_enabled.attr)
- param = ISCSI_NET_PARAM_IFACE_ENABLE;
- else if (attr == &dev_attr_iface_def_taskmgmt_tmo.attr)
+ if (attr == &dev_attr_iface_def_taskmgmt_tmo.attr)
param = ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO;
else if (attr == &dev_attr_iface_header_digest.attr)
param = ISCSI_IFACE_PARAM_HDRDGST_EN;
@@ -476,7 +482,9 @@
if (param != -1)
return t->attr_is_visible(ISCSI_IFACE_PARAM, param);
- if (attr == &dev_attr_iface_vlan_id.attr)
+ if (attr == &dev_attr_iface_enabled.attr)
+ param = ISCSI_NET_PARAM_IFACE_ENABLE;
+ else if (attr == &dev_attr_iface_vlan_id.attr)
param = ISCSI_NET_PARAM_VLAN_ID;
else if (attr == &dev_attr_iface_vlan_priority.attr)
param = ISCSI_NET_PARAM_VLAN_PRIORITY;
@@ -1590,9 +1598,16 @@
static struct sock *nls;
static DEFINE_MUTEX(rx_queue_mutex);
+/*
+ * conn_mutex protects the {start,bind,stop,destroy}_conn from racing
+ * against the kernel stop_connection recovery mechanism
+ */
+static DEFINE_MUTEX(conn_mutex);
+
static LIST_HEAD(sesslist);
static DEFINE_SPINLOCK(sesslock);
static LIST_HEAD(connlist);
+static LIST_HEAD(connlist_err);
static DEFINE_SPINLOCK(connlock);
static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn)
@@ -1894,12 +1909,12 @@
}
spin_unlock_irqrestore(&session->lock, flags);
- if (session->transport->session_recovery_timedout)
- session->transport->session_recovery_timedout(session);
-
ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n");
scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n");
+
+ if (session->transport->session_recovery_timedout)
+ session->transport->session_recovery_timedout(session);
}
static void __iscsi_unblock_session(struct work_struct *work)
@@ -1942,12 +1957,15 @@
*/
void iscsi_unblock_session(struct iscsi_cls_session *session)
{
+ flush_work(&session->block_work);
+
queue_work(iscsi_eh_timer_workq, &session->unblock_work);
/*
- * make sure all the events have completed before tell the driver
- * it is safe
+ * Blocking the session can be done from any context so we only
+ * queue the block work. Make sure the unblock work has completed
+ * because it flushes/cancels the other works and updates the state.
*/
- flush_workqueue(iscsi_eh_timer_workq);
+ flush_work(&session->unblock_work);
}
EXPORT_SYMBOL_GPL(iscsi_unblock_session);
@@ -2002,16 +2020,24 @@
spin_unlock_irqrestore(&session->lock, flags);
mutex_unlock(&ihost->mutex);
+ scsi_remove_target(&session->dev);
+
if (session->ida_used)
ida_simple_remove(&iscsi_sess_ida, target_id);
- scsi_remove_target(&session->dev);
-
unbind_session_exit:
iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n");
}
+static void __iscsi_destroy_session(struct work_struct *work)
+{
+ struct iscsi_cls_session *session =
+ container_of(work, struct iscsi_cls_session, destroy_work);
+
+ session->transport->destroy_session(session);
+}
+
struct iscsi_cls_session *
iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
int dd_size)
@@ -2034,6 +2060,7 @@
INIT_WORK(&session->block_work, __iscsi_block_session);
INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
INIT_WORK(&session->scan_work, iscsi_scan_session);
+ INIT_WORK(&session->destroy_work, __iscsi_destroy_session);
spin_lock_init(&session->lock);
/* this is released in the dev's release function */
@@ -2077,7 +2104,12 @@
"could not register session's dev\n");
goto release_ida;
}
- transport_register_device(&session->dev);
+ err = transport_register_device(&session->dev);
+ if (err) {
+ iscsi_cls_session_printk(KERN_ERR, session,
+ "could not register transport's dev\n");
+ goto release_dev;
+ }
spin_lock_irqsave(&sesslock, flags);
list_add(&session->sess_list, &sesslist);
@@ -2087,6 +2119,8 @@
ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
return 0;
+release_dev:
+ device_del(&session->dev);
release_ida:
if (session->ida_used)
ida_simple_remove(&iscsi_sess_ida, session->target_id);
@@ -2152,14 +2186,13 @@
ISCSI_DBG_TRANS_SESSION(session, "Removing session\n");
spin_lock_irqsave(&sesslock, flags);
- list_del(&session->sess_list);
+ if (!list_empty(&session->sess_list))
+ list_del(&session->sess_list);
spin_unlock_irqrestore(&sesslock, flags);
- /* make sure there are no blocks/unblocks queued */
- flush_workqueue(iscsi_eh_timer_workq);
- /* make sure the timedout callout is not running */
- if (!cancel_delayed_work(&session->recovery_work))
- flush_workqueue(iscsi_eh_timer_workq);
+ flush_work(&session->block_work);
+ flush_work(&session->unblock_work);
+ cancel_delayed_work_sync(&session->recovery_work);
/*
* If we are blocked let commands flow again. The lld or iscsi
* layer should set up the queuecommand to fail commands.
@@ -2231,8 +2264,10 @@
mutex_init(&conn->ep_mutex);
INIT_LIST_HEAD(&conn->conn_list);
+ INIT_LIST_HEAD(&conn->conn_list_err);
conn->transport = transport;
conn->cid = cid;
+ conn->state = ISCSI_CONN_DOWN;
/* this is released in the dev's release function */
if (!get_device(&session->dev))
@@ -2247,7 +2282,12 @@
"register connection's dev\n");
goto release_parent_ref;
}
- transport_register_device(&conn->dev);
+ err = transport_register_device(&conn->dev);
+ if (err) {
+ iscsi_cls_session_printk(KERN_ERR, session, "could not "
+ "register transport's dev\n");
+ goto release_conn_ref;
+ }
spin_lock_irqsave(&connlock, flags);
list_add(&conn->conn_list, &connlist);
@@ -2256,6 +2296,10 @@
ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n");
return conn;
+release_conn_ref:
+ device_unregister(&conn->dev);
+ put_device(&session->dev);
+ return NULL;
release_parent_ref:
put_device(&session->dev);
free_conn:
@@ -2277,6 +2321,7 @@
spin_lock_irqsave(&connlock, flags);
list_del(&conn->conn_list);
+ list_del(&conn->conn_list_err);
spin_unlock_irqrestore(&connlock, flags);
transport_unregister_device(&conn->dev);
@@ -2403,6 +2448,77 @@
}
EXPORT_SYMBOL_GPL(iscsi_offload_mesg);
+/*
+ * This can be called without the rx_queue_mutex, if invoked by the kernel
+ * stop work. But, in that case, it is guaranteed not to race with
+ * iscsi_destroy by conn_mutex.
+ */
+static void iscsi_if_stop_conn(struct iscsi_cls_conn *conn, int flag)
+{
+ /*
+ * It is important that this path doesn't rely on
+ * rx_queue_mutex, otherwise, a thread doing allocation on a
+ * start_session/start_connection could sleep waiting on a
+ * writeback to a failed iscsi device, that cannot be recovered
+ * because the lock is held. If we don't hold it here, the
+ * kernel stop_conn_work_fn has a chance to stop the broken
+ * session and resolve the allocation.
+ *
+ * Still, the user invoked .stop_conn() needs to be serialized
+ * with stop_conn_work_fn by a private mutex. Not pretty, but
+ * it works.
+ */
+ mutex_lock(&conn_mutex);
+ switch (flag) {
+ case STOP_CONN_RECOVER:
+ conn->state = ISCSI_CONN_FAILED;
+ break;
+ case STOP_CONN_TERM:
+ conn->state = ISCSI_CONN_DOWN;
+ break;
+ default:
+ iscsi_cls_conn_printk(KERN_ERR, conn,
+ "invalid stop flag %d\n", flag);
+ goto unlock;
+ }
+
+ conn->transport->stop_conn(conn, flag);
+unlock:
+ mutex_unlock(&conn_mutex);
+}
+
+static void stop_conn_work_fn(struct work_struct *work)
+{
+ struct iscsi_cls_conn *conn, *tmp;
+ unsigned long flags;
+ LIST_HEAD(recovery_list);
+
+ spin_lock_irqsave(&connlock, flags);
+ if (list_empty(&connlist_err)) {
+ spin_unlock_irqrestore(&connlock, flags);
+ return;
+ }
+ list_splice_init(&connlist_err, &recovery_list);
+ spin_unlock_irqrestore(&connlock, flags);
+
+ list_for_each_entry_safe(conn, tmp, &recovery_list, conn_list_err) {
+ uint32_t sid = iscsi_conn_get_sid(conn);
+ struct iscsi_cls_session *session;
+
+ session = iscsi_session_lookup(sid);
+ if (session) {
+ if (system_state != SYSTEM_RUNNING) {
+ session->recovery_tmo = 0;
+ iscsi_if_stop_conn(conn, STOP_CONN_TERM);
+ } else {
+ iscsi_if_stop_conn(conn, STOP_CONN_RECOVER);
+ }
+ }
+
+ list_del_init(&conn->conn_list_err);
+ }
+}
+
void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
{
struct nlmsghdr *nlh;
@@ -2410,6 +2526,12 @@
struct iscsi_uevent *ev;
struct iscsi_internal *priv;
int len = nlmsg_total_size(sizeof(*ev));
+ unsigned long flags;
+
+ spin_lock_irqsave(&connlock, flags);
+ list_add(&conn->conn_list_err, &connlist_err);
+ spin_unlock_irqrestore(&connlock, flags);
+ queue_work(system_unbound_wq, &stop_conn_work);
priv = iscsi_if_transport_lookup(conn->transport);
if (!priv)
@@ -2739,14 +2861,25 @@
iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
{
struct iscsi_cls_conn *conn;
+ unsigned long flags;
conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
if (!conn)
return -EINVAL;
+ spin_lock_irqsave(&connlock, flags);
+ if (!list_empty(&conn->conn_list_err)) {
+ spin_unlock_irqrestore(&connlock, flags);
+ return -EAGAIN;
+ }
+ spin_unlock_irqrestore(&connlock, flags);
+
ISCSI_DBG_TRANS_CONN(conn, "Destroying transport conn\n");
+
+ mutex_lock(&conn_mutex);
if (transport->destroy_conn)
transport->destroy_conn(conn);
+ mutex_unlock(&conn_mutex);
return 0;
}
@@ -2774,8 +2907,13 @@
session->recovery_tmo = value;
break;
default:
- err = transport->set_param(conn, ev->u.set_param.param,
- data, ev->u.set_param.len);
+ if ((conn->state == ISCSI_CONN_BOUND) ||
+ (conn->state == ISCSI_CONN_UP)) {
+ err = transport->set_param(conn, ev->u.set_param.param,
+ data, ev->u.set_param.len);
+ } else {
+ return -ENOTCONN;
+ }
}
return err;
@@ -2835,6 +2973,7 @@
mutex_lock(&conn->ep_mutex);
conn->ep = NULL;
mutex_unlock(&conn->ep_mutex);
+ conn->state = ISCSI_CONN_FAILED;
}
transport->ep_disconnect(ep);
@@ -3555,6 +3694,23 @@
else
transport->destroy_session(session);
break;
+ case ISCSI_UEVENT_DESTROY_SESSION_ASYNC:
+ session = iscsi_session_lookup(ev->u.d_session.sid);
+ if (!session)
+ err = -EINVAL;
+ else if (iscsi_session_has_conns(ev->u.d_session.sid))
+ err = -EBUSY;
+ else {
+ unsigned long flags;
+
+ /* Prevent this session from being found again */
+ spin_lock_irqsave(&sesslock, flags);
+ list_del_init(&session->sess_list);
+ spin_unlock_irqrestore(&sesslock, flags);
+
+ queue_work(iscsi_destroy_workq, &session->destroy_work);
+ }
+ break;
case ISCSI_UEVENT_UNBIND_SESSION:
session = iscsi_session_lookup(ev->u.d_session.sid);
if (session)
@@ -3581,9 +3737,14 @@
break;
}
+ mutex_lock(&conn_mutex);
ev->r.retcode = transport->bind_conn(session, conn,
ev->u.b_conn.transport_eph,
ev->u.b_conn.is_leading);
+ if (!ev->r.retcode)
+ conn->state = ISCSI_CONN_BOUND;
+ mutex_unlock(&conn_mutex);
+
if (ev->r.retcode || !transport->ep_connect)
break;
@@ -3604,15 +3765,20 @@
break;
case ISCSI_UEVENT_START_CONN:
conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid);
- if (conn)
+ if (conn) {
+ mutex_lock(&conn_mutex);
ev->r.retcode = transport->start_conn(conn);
+ if (!ev->r.retcode)
+ conn->state = ISCSI_CONN_UP;
+ mutex_unlock(&conn_mutex);
+ }
else
err = -EINVAL;
break;
case ISCSI_UEVENT_STOP_CONN:
conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
if (conn)
- transport->stop_conn(conn, ev->u.stop_conn.flag);
+ iscsi_if_stop_conn(conn, ev->u.stop_conn.flag);
else
err = -EINVAL;
break;
@@ -3626,11 +3792,14 @@
}
conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
- if (conn)
+ if (conn) {
+ mutex_lock(&conn_mutex);
ev->r.retcode = transport->send_pdu(conn,
(struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
(char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
ev->u.send_pdu.data_size);
+ mutex_unlock(&conn_mutex);
+ }
else
err = -EINVAL;
break;
@@ -3810,6 +3979,27 @@
iscsi_conn_attr(tcp_recv_wsf, ISCSI_PARAM_TCP_RECV_WSF);
iscsi_conn_attr(local_ipaddr, ISCSI_PARAM_LOCAL_IPADDR);
+static const char *const connection_state_names[] = {
+ [ISCSI_CONN_UP] = "up",
+ [ISCSI_CONN_DOWN] = "down",
+ [ISCSI_CONN_FAILED] = "failed",
+ [ISCSI_CONN_BOUND] = "bound"
+};
+
+static ssize_t show_conn_state(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);
+ const char *state = "unknown";
+
+ if (conn->state >= 0 &&
+ conn->state < ARRAY_SIZE(connection_state_names))
+ state = connection_state_names[conn->state];
+
+ return sysfs_emit(buf, "%s\n", state);
+}
+static ISCSI_CLASS_ATTR(conn, state, S_IRUGO, show_conn_state,
+ NULL);
#define iscsi_conn_ep_attr_show(param) \
static ssize_t show_conn_ep_param_##param(struct device *dev, \
@@ -3879,6 +4069,7 @@
&dev_attr_conn_tcp_xmit_wsf.attr,
&dev_attr_conn_tcp_recv_wsf.attr,
&dev_attr_conn_local_ipaddr.attr,
+ &dev_attr_conn_state.attr,
NULL,
};
@@ -3950,6 +4141,8 @@
param = ISCSI_PARAM_TCP_RECV_WSF;
else if (attr == &dev_attr_conn_local_ipaddr.attr)
param = ISCSI_PARAM_LOCAL_IPADDR;
+ else if (attr == &dev_attr_conn_state.attr)
+ return S_IRUGO;
else {
WARN_ONCE(1, "Invalid conn attr");
return 0;
@@ -4602,14 +4795,26 @@
goto unregister_flashnode_bus;
}
- iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh");
+ iscsi_eh_timer_workq = alloc_workqueue("%s",
+ WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND,
+ 1, "iscsi_eh");
if (!iscsi_eh_timer_workq) {
err = -ENOMEM;
goto release_nls;
}
+ iscsi_destroy_workq = alloc_workqueue("%s",
+ WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND,
+ 1, "iscsi_destroy");
+ if (!iscsi_destroy_workq) {
+ err = -ENOMEM;
+ goto destroy_wq;
+ }
+
return 0;
+destroy_wq:
+ destroy_workqueue(iscsi_eh_timer_workq);
release_nls:
netlink_kernel_release(nls);
unregister_flashnode_bus:
@@ -4631,6 +4836,7 @@
static void __exit iscsi_transport_exit(void)
{
+ destroy_workqueue(iscsi_destroy_workq);
destroy_workqueue(iscsi_eh_timer_workq);
netlink_kernel_release(nls);
bus_unregister(&iscsi_flashnode_bus);
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 182fd25..4a96fb0 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -563,7 +563,7 @@
{
struct sas_phy *phy = transport_class_to_phy(dev);
- return snprintf(buf, 20, "%d", phy->enabled);
+ return snprintf(buf, 20, "%d\n", phy->enabled);
}
static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable,
@@ -1229,16 +1229,15 @@
char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata;
struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
struct scsi_mode_data mode_data;
- int res, error;
+ int error;
if (!buffer)
return -ENOMEM;
- res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3,
- &mode_data, NULL);
+ error = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3,
+ &mode_data, NULL);
- error = -EINVAL;
- if (!scsi_status_is_good(res))
+ if (error)
goto out;
msdata = buffer + mode_data.header_length +
@@ -1526,7 +1525,7 @@
list_add_tail(&rphy->list, &sas_host->rphy_list);
if (identify->device_type == SAS_END_DEVICE &&
(identify->target_port_protocols &
- (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA)))
+ (SAS_PROTOCOL_SSP | SAS_PROTOCOL_STP | SAS_PROTOCOL_SATA)))
rphy->scsi_target_id = sas_host->next_target_id++;
else if (identify->device_type == SAS_END_DEVICE)
rphy->scsi_target_id = -1;
diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c
index 9fee851..98a34ed 100644
--- a/drivers/scsi/scsi_transport_srp.c
+++ b/drivers/scsi/scsi_transport_srp.c
@@ -395,6 +395,10 @@
}
}
+/*
+ * scsi_target_block() must have been called before this function is
+ * called to guarantee that no .queuecommand() calls are in progress.
+ */
static void __rport_fail_io_fast(struct srp_rport *rport)
{
struct Scsi_Host *shost = rport_to_shost(rport);
@@ -404,11 +408,7 @@
if (srp_rport_set_state(rport, SRP_RPORT_FAIL_FAST))
return;
- /*
- * Call scsi_target_block() to wait for ongoing shost->queuecommand()
- * calls before invoking i->f->terminate_rport_io().
- */
- scsi_target_block(rport->dev.parent);
+
scsi_target_unblock(rport->dev.parent, SDEV_TRANSPORT_OFFLINE);
/* Involve the LLD if possible to terminate all I/O on the rport. */
@@ -577,8 +577,6 @@
* failure timers if these had not yet been started.
*/
__rport_fail_io_fast(rport);
- scsi_target_unblock(&shost->shost_gendev,
- SDEV_TRANSPORT_OFFLINE);
__srp_start_tl_fail_timers(rport);
} else if (rport->state != SRP_RPORT_BLOCKED) {
scsi_target_unblock(&shost->shost_gendev,
diff --git a/drivers/scsi/scsicam.c b/drivers/scsi/scsicam.c
index e969138..682cf08 100644
--- a/drivers/scsi/scsicam.c
+++ b/drivers/scsi/scsicam.c
@@ -17,14 +17,11 @@
#include <linux/genhd.h>
#include <linux/kernel.h>
#include <linux/blkdev.h>
+#include <linux/msdos_partition.h>
#include <asm/unaligned.h>
#include <scsi/scsicam.h>
-
-static int setsize(unsigned long capacity, unsigned int *cyls, unsigned int *hds,
- unsigned int *secs);
-
/**
* scsi_bios_ptable - Read PC partition table out of first sector of device.
* @dev: from this device
@@ -35,105 +32,48 @@
*/
unsigned char *scsi_bios_ptable(struct block_device *dev)
{
- unsigned char *res = kmalloc(66, GFP_KERNEL);
- if (res) {
- struct block_device *bdev = dev->bd_contains;
- Sector sect;
- void *data = read_dev_sector(bdev, 0, §);
- if (data) {
- memcpy(res, data + 0x1be, 66);
- put_dev_sector(sect);
- } else {
- kfree(res);
- res = NULL;
- }
- }
+ struct address_space *mapping = dev->bd_contains->bd_inode->i_mapping;
+ unsigned char *res = NULL;
+ struct page *page;
+
+ page = read_mapping_page(mapping, 0, NULL);
+ if (IS_ERR(page))
+ return NULL;
+
+ if (!PageError(page))
+ res = kmemdup(page_address(page) + 0x1be, 66, GFP_KERNEL);
+ put_page(page);
return res;
}
EXPORT_SYMBOL(scsi_bios_ptable);
/**
- * scsicam_bios_param - Determine geometry of a disk in cylinders/heads/sectors.
- * @bdev: which device
- * @capacity: size of the disk in sectors
- * @ip: return value: ip[0]=heads, ip[1]=sectors, ip[2]=cylinders
- *
- * Description : determine the BIOS mapping/geometry used for a drive in a
- * SCSI-CAM system, storing the results in ip as required
- * by the HDIO_GETGEO ioctl().
- *
- * Returns : -1 on failure, 0 on success.
- */
-
-int scsicam_bios_param(struct block_device *bdev, sector_t capacity, int *ip)
-{
- unsigned char *p;
- u64 capacity64 = capacity; /* Suppress gcc warning */
- int ret;
-
- p = scsi_bios_ptable(bdev);
- if (!p)
- return -1;
-
- /* try to infer mapping from partition table */
- ret = scsi_partsize(p, (unsigned long)capacity, (unsigned int *)ip + 2,
- (unsigned int *)ip + 0, (unsigned int *)ip + 1);
- kfree(p);
-
- if (ret == -1 && capacity64 < (1ULL << 32)) {
- /* pick some standard mapping with at most 1024 cylinders,
- and at most 62 sectors per track - this works up to
- 7905 MB */
- ret = setsize((unsigned long)capacity, (unsigned int *)ip + 2,
- (unsigned int *)ip + 0, (unsigned int *)ip + 1);
- }
-
- /* if something went wrong, then apparently we have to return
- a geometry with more than 1024 cylinders */
- if (ret || ip[0] > 255 || ip[1] > 63) {
- if ((capacity >> 11) > 65534) {
- ip[0] = 255;
- ip[1] = 63;
- } else {
- ip[0] = 64;
- ip[1] = 32;
- }
-
- if (capacity > 65535*63*255)
- ip[2] = 65535;
- else
- ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
- }
-
- return 0;
-}
-EXPORT_SYMBOL(scsicam_bios_param);
-
-/**
* scsi_partsize - Parse cylinders/heads/sectors from PC partition table
- * @buf: partition table, see scsi_bios_ptable()
+ * @bdev: block device to parse
* @capacity: size of the disk in sectors
- * @cyls: put cylinders here
- * @hds: put heads here
- * @secs: put sectors here
+ * @geom: output in form of [hds, cylinders, sectors]
*
* Determine the BIOS mapping/geometry used to create the partition
- * table, storing the results in @cyls, @hds, and @secs
+ * table, storing the results in @geom.
*
- * Returns: -1 on failure, 0 on success.
+ * Returns: %false on failure, %true on success.
*/
-
-int scsi_partsize(unsigned char *buf, unsigned long capacity,
- unsigned int *cyls, unsigned int *hds, unsigned int *secs)
+bool scsi_partsize(struct block_device *bdev, sector_t capacity, int geom[3])
{
- struct partition *p = (struct partition *)buf, *largest = NULL;
- int i, largest_cyl;
int cyl, ext_cyl, end_head, end_cyl, end_sector;
unsigned int logical_end, physical_end, ext_physical_end;
+ struct msdos_partition *p, *largest = NULL;
+ void *buf;
+ int ret = false;
+ buf = scsi_bios_ptable(bdev);
+ if (!buf)
+ return false;
if (*(unsigned short *) (buf + 64) == 0xAA55) {
- for (largest_cyl = -1, i = 0; i < 4; ++i, ++p) {
+ int largest_cyl = -1, i;
+
+ for (i = 0, p = buf; i < 4; i++, p++) {
if (!p->sys_ind)
continue;
#ifdef DEBUG
@@ -153,7 +93,7 @@
end_sector = largest->end_sector & 0x3f;
if (end_head + 1 == 0 || end_sector == 0)
- return -1;
+ goto out_free_buf;
#ifdef DEBUG
printk("scsicam_bios_param : end at h = %d, c = %d, s = %d\n",
@@ -178,19 +118,24 @@
,logical_end, physical_end, ext_physical_end, ext_cyl);
#endif
- if ((logical_end == physical_end) ||
- (end_cyl == 1023 && ext_physical_end == logical_end)) {
- *secs = end_sector;
- *hds = end_head + 1;
- *cyls = capacity / ((end_head + 1) * end_sector);
- return 0;
+ if (logical_end == physical_end ||
+ (end_cyl == 1023 && ext_physical_end == logical_end)) {
+ geom[0] = end_head + 1;
+ geom[1] = end_sector;
+ geom[2] = (unsigned long)capacity /
+ ((end_head + 1) * end_sector);
+ ret = true;
+ goto out_free_buf;
}
#ifdef DEBUG
printk("scsicam_bios_param : logical (%u) != physical (%u)\n",
logical_end, physical_end);
#endif
}
- return -1;
+
+out_free_buf:
+ kfree(buf);
+ return ret;
}
EXPORT_SYMBOL(scsi_partsize);
@@ -258,3 +203,56 @@
*hds = (unsigned int) heads;
return (rv);
}
+
+/**
+ * scsicam_bios_param - Determine geometry of a disk in cylinders/heads/sectors.
+ * @bdev: which device
+ * @capacity: size of the disk in sectors
+ * @ip: return value: ip[0]=heads, ip[1]=sectors, ip[2]=cylinders
+ *
+ * Description : determine the BIOS mapping/geometry used for a drive in a
+ * SCSI-CAM system, storing the results in ip as required
+ * by the HDIO_GETGEO ioctl().
+ *
+ * Returns : -1 on failure, 0 on success.
+ */
+int scsicam_bios_param(struct block_device *bdev, sector_t capacity, int *ip)
+{
+ u64 capacity64 = capacity; /* Suppress gcc warning */
+ int ret = 0;
+
+ /* try to infer mapping from partition table */
+ if (scsi_partsize(bdev, capacity, ip))
+ return 0;
+
+ if (capacity64 < (1ULL << 32)) {
+ /*
+ * Pick some standard mapping with at most 1024 cylinders, and
+ * at most 62 sectors per track - this works up to 7905 MB.
+ */
+ ret = setsize((unsigned long)capacity, (unsigned int *)ip + 2,
+ (unsigned int *)ip + 0, (unsigned int *)ip + 1);
+ }
+
+ /*
+ * If something went wrong, then apparently we have to return a geometry
+ * with more than 1024 cylinders.
+ */
+ if (ret || ip[0] > 255 || ip[1] > 63) {
+ if ((capacity >> 11) > 65534) {
+ ip[0] = 255;
+ ip[1] = 63;
+ } else {
+ ip[0] = 64;
+ ip[1] = 32;
+ }
+
+ if (capacity > 65535*63*255)
+ ip[2] = 65535;
+ else
+ ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(scsicam_bios_param);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index f552497..56e2917 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -122,8 +122,6 @@
static int sd_eh_action(struct scsi_cmnd *, int);
static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer);
static void scsi_disk_release(struct device *cdev);
-static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
-static void sd_print_result(const struct scsi_disk *, const char *, int);
static DEFINE_IDA(sd_index_ida);
@@ -196,7 +194,7 @@
}
if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT,
- SD_MAX_RETRIES, &data, NULL))
+ sdkp->max_retries, &data, NULL))
return -EINVAL;
len = min_t(size_t, sizeof(buffer), data.length - data.header_length -
data.block_descriptor_length);
@@ -214,12 +212,12 @@
data.device_specific = 0;
if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT,
- SD_MAX_RETRIES, &data, &sshdr)) {
+ sdkp->max_retries, &data, &sshdr)) {
if (scsi_sense_valid(&sshdr))
sd_print_sense_hdr(sdkp, &sshdr);
return -EINVAL;
}
- revalidate_disk(sdkp->disk);
+ sd_revalidate_disk(sdkp->disk);
return count;
}
@@ -530,6 +528,54 @@
}
static DEVICE_ATTR_RW(max_write_same_blocks);
+static ssize_t
+zoned_cap_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+ if (sdkp->device->type == TYPE_ZBC)
+ return sprintf(buf, "host-managed\n");
+ if (sdkp->zoned == 1)
+ return sprintf(buf, "host-aware\n");
+ if (sdkp->zoned == 2)
+ return sprintf(buf, "drive-managed\n");
+ return sprintf(buf, "none\n");
+}
+static DEVICE_ATTR_RO(zoned_cap);
+
+static ssize_t
+max_retries_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_disk *sdkp = to_scsi_disk(dev);
+ struct scsi_device *sdev = sdkp->device;
+ int retries, err;
+
+ err = kstrtoint(buf, 10, &retries);
+ if (err)
+ return err;
+
+ if (retries == SCSI_CMD_RETRIES_NO_LIMIT || retries <= SD_MAX_RETRIES) {
+ sdkp->max_retries = retries;
+ return count;
+ }
+
+ sdev_printk(KERN_ERR, sdev, "max_retries must be between -1 and %d\n",
+ SD_MAX_RETRIES);
+ return -EINVAL;
+}
+
+static ssize_t
+max_retries_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+ return sprintf(buf, "%d\n", sdkp->max_retries);
+}
+
+static DEVICE_ATTR_RW(max_retries);
+
static struct attribute *sd_disk_attrs[] = {
&dev_attr_cache_type.attr,
&dev_attr_FUA.attr,
@@ -543,6 +589,8 @@
&dev_attr_zeroing_mode.attr,
&dev_attr_max_write_same_blocks.attr,
&dev_attr_max_medium_access_timeouts.attr,
+ &dev_attr_zoned_cap.attr,
+ &dev_attr_max_retries.attr,
NULL,
};
ATTRIBUTE_GROUPS(sd_disk);
@@ -651,7 +699,8 @@
static int sd_sec_submit(void *data, u16 spsp, u8 secp, void *buffer,
size_t len, bool send)
{
- struct scsi_device *sdev = data;
+ struct scsi_disk *sdkp = data;
+ struct scsi_device *sdev = sdkp->device;
u8 cdb[12] = { 0, };
int ret;
@@ -660,9 +709,9 @@
put_unaligned_be16(spsp, &cdb[2]);
put_unaligned_be32(len, &cdb[6]);
- ret = scsi_execute_req(sdev, cdb,
- send ? DMA_TO_DEVICE : DMA_FROM_DEVICE,
- buffer, len, NULL, SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+ ret = scsi_execute(sdev, cdb, send ? DMA_TO_DEVICE : DMA_FROM_DEVICE,
+ buffer, len, NULL, NULL, SD_TIMEOUT, sdkp->max_retries, 0,
+ RQF_PM, NULL);
return ret <= 0 ? ret : -EIO;
}
#endif /* CONFIG_BLK_SED_OPAL */
@@ -825,6 +874,7 @@
{
struct scsi_device *sdp = cmd->device;
struct request *rq = cmd->request;
+ struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq));
u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
unsigned int data_len = 24;
@@ -848,11 +898,11 @@
put_unaligned_be64(lba, &buf[8]);
put_unaligned_be32(nr_blocks, &buf[16]);
- cmd->allowed = SD_MAX_RETRIES;
+ cmd->allowed = sdkp->max_retries;
cmd->transfersize = data_len;
rq->timeout = SD_TIMEOUT;
- return scsi_init_io(cmd);
+ return scsi_alloc_sgtables(cmd);
}
static blk_status_t sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd,
@@ -860,6 +910,7 @@
{
struct scsi_device *sdp = cmd->device;
struct request *rq = cmd->request;
+ struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq));
u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
u32 data_len = sdp->sector_size;
@@ -879,11 +930,11 @@
put_unaligned_be64(lba, &cmd->cmnd[2]);
put_unaligned_be32(nr_blocks, &cmd->cmnd[10]);
- cmd->allowed = SD_MAX_RETRIES;
+ cmd->allowed = sdkp->max_retries;
cmd->transfersize = data_len;
rq->timeout = unmap ? SD_TIMEOUT : SD_WRITE_SAME_TIMEOUT;
- return scsi_init_io(cmd);
+ return scsi_alloc_sgtables(cmd);
}
static blk_status_t sd_setup_write_same10_cmnd(struct scsi_cmnd *cmd,
@@ -891,6 +942,7 @@
{
struct scsi_device *sdp = cmd->device;
struct request *rq = cmd->request;
+ struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq));
u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
u32 data_len = sdp->sector_size;
@@ -910,11 +962,11 @@
put_unaligned_be32(lba, &cmd->cmnd[2]);
put_unaligned_be16(nr_blocks, &cmd->cmnd[7]);
- cmd->allowed = SD_MAX_RETRIES;
+ cmd->allowed = sdkp->max_retries;
cmd->transfersize = data_len;
rq->timeout = unmap ? SD_TIMEOUT : SD_WRITE_SAME_TIMEOUT;
- return scsi_init_io(cmd);
+ return scsi_alloc_sgtables(cmd);
}
static blk_status_t sd_setup_write_zeroes_cmnd(struct scsi_cmnd *cmd)
@@ -1044,7 +1096,7 @@
}
cmd->transfersize = sdp->sector_size;
- cmd->allowed = SD_MAX_RETRIES;
+ cmd->allowed = sdkp->max_retries;
/*
* For WRITE SAME the data transferred via the DATA OUT buffer is
@@ -1057,7 +1109,7 @@
* knows how much to actually write.
*/
rq->__data_len = sdp->sector_size;
- ret = scsi_init_io(cmd);
+ ret = scsi_alloc_sgtables(cmd);
rq->__data_len = blk_rq_bytes(rq);
return ret;
@@ -1066,6 +1118,7 @@
static blk_status_t sd_setup_flush_cmnd(struct scsi_cmnd *cmd)
{
struct request *rq = cmd->request;
+ struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
/* flush requests don't perform I/O, zero the S/G table */
memset(&cmd->sdb, 0, sizeof(cmd->sdb));
@@ -1073,7 +1126,7 @@
cmd->cmnd[0] = SYNCHRONIZE_CACHE;
cmd->cmd_len = 10;
cmd->transfersize = 0;
- cmd->allowed = SD_MAX_RETRIES;
+ cmd->allowed = sdkp->max_retries;
rq->timeout = rq->q->rq_timeout * SD_FLUSH_TIMEOUT_MULTIPLIER;
return BLK_STS_OK;
@@ -1175,23 +1228,24 @@
unsigned int dif;
bool dix;
- ret = scsi_init_io(cmd);
+ ret = scsi_alloc_sgtables(cmd);
if (ret != BLK_STS_OK)
return ret;
+ ret = BLK_STS_IOERR;
if (!scsi_device_online(sdp) || sdp->changed) {
scmd_printk(KERN_ERR, cmd, "device offline or changed\n");
- return BLK_STS_IOERR;
+ goto fail;
}
if (blk_rq_pos(rq) + blk_rq_sectors(rq) > get_capacity(rq->rq_disk)) {
scmd_printk(KERN_ERR, cmd, "access beyond end of device\n");
- return BLK_STS_IOERR;
+ goto fail;
}
if ((blk_rq_pos(rq) & mask) || (blk_rq_sectors(rq) & mask)) {
scmd_printk(KERN_ERR, cmd, "request not aligned to the logical block size\n");
- return BLK_STS_IOERR;
+ goto fail;
}
/*
@@ -1210,6 +1264,12 @@
}
}
+ if (req_op(rq) == REQ_OP_ZONE_APPEND) {
+ ret = sd_zbc_prepare_zone_append(cmd, &lba, nr_blocks);
+ if (ret)
+ goto fail;
+ }
+
fua = rq->cmd_flags & REQ_FUA ? 0x8 : 0;
dix = scsi_prot_sg_count(cmd);
dif = scsi_host_dif_capable(cmd->device->host, sdkp->protection_type);
@@ -1235,7 +1295,7 @@
}
if (unlikely(ret != BLK_STS_OK))
- return ret;
+ goto fail;
/*
* We shouldn't disconnect in the middle of a sector, so with a dumb
@@ -1244,7 +1304,7 @@
*/
cmd->transfersize = sdp->sector_size;
cmd->underflow = nr_blocks << 9;
- cmd->allowed = SD_MAX_RETRIES;
+ cmd->allowed = sdkp->max_retries;
cmd->sdb.length = nr_blocks * sdp->sector_size;
SCSI_LOG_HLQUEUE(1,
@@ -1259,10 +1319,12 @@
blk_rq_sectors(rq)));
/*
- * This indicates that the command is ready from our end to be
- * queued.
+ * This indicates that the command is ready from our end to be queued.
*/
return BLK_STS_OK;
+fail:
+ scsi_free_sgtables(cmd);
+ return ret;
}
static blk_status_t sd_init_command(struct scsi_cmnd *cmd)
@@ -1291,11 +1353,20 @@
return sd_setup_flush_cmnd(cmd);
case REQ_OP_READ:
case REQ_OP_WRITE:
+ case REQ_OP_ZONE_APPEND:
return sd_setup_read_write_cmnd(cmd);
case REQ_OP_ZONE_RESET:
- return sd_zbc_setup_reset_cmnd(cmd, false);
+ return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_RESET_WRITE_POINTER,
+ false);
case REQ_OP_ZONE_RESET_ALL:
- return sd_zbc_setup_reset_cmnd(cmd, true);
+ return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_RESET_WRITE_POINTER,
+ true);
+ case REQ_OP_ZONE_OPEN:
+ return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_OPEN_ZONE, false);
+ case REQ_OP_ZONE_CLOSE:
+ return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_CLOSE_ZONE, false);
+ case REQ_OP_ZONE_FINISH:
+ return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_FINISH_ZONE, false);
default:
WARN_ON_ONCE(1);
return BLK_STS_NOTSUPP;
@@ -1318,6 +1389,22 @@
}
}
+static bool sd_need_revalidate(struct block_device *bdev,
+ struct scsi_disk *sdkp)
+{
+ if (sdkp->device->removable || sdkp->write_prot) {
+ if (bdev_check_media_change(bdev))
+ return true;
+ }
+
+ /*
+ * Force a full rescan after ioctl(BLKRRPART). While the disk state has
+ * nothing to do with partitions, BLKRRPART is used to force a full
+ * revalidate after things like a format for historical reasons.
+ */
+ return test_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state);
+}
+
/**
* sd_open - open a scsi disk device
* @bdev: Block device of the scsi disk to open
@@ -1354,8 +1441,8 @@
if (!scsi_block_when_processing_errors(sdev))
goto error_out;
- if (sdev->removable || sdkp->write_prot)
- check_disk_change(bdev);
+ if (sd_need_revalidate(bdev, sdkp))
+ sd_revalidate_disk(bdev->bd_disk);
/*
* If the drive is empty, just let the open fail.
@@ -1452,7 +1539,7 @@
* @bdev: target block device
* @mode: FMODE_* mask
* @cmd: ioctl command number
- * @arg: this is third argument given to ioctl(2) system call.
+ * @p: this is third argument given to ioctl(2) system call.
* Often contains a pointer.
*
* Returns 0 if successful (some ioctls return positive numbers on
@@ -1461,13 +1548,12 @@
* Note: most ioctls are forward onto the block subsystem or further
* down in the scsi subsystem.
**/
-static int sd_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
+static int sd_ioctl_common(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, void __user *p)
{
struct gendisk *disk = bdev->bd_disk;
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdp = sdkp->device;
- void __user *p = (void __user *)arg;
int error;
SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, "
@@ -1503,9 +1589,6 @@
break;
default:
error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p);
- if (error != -ENOTTY)
- break;
- error = scsi_ioctl(sdp, cmd, p);
break;
}
out:
@@ -1586,7 +1669,7 @@
if (scsi_block_when_processing_errors(sdp)) {
struct scsi_sense_hdr sshdr = { 0, };
- retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES,
+ retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, sdkp->max_retries,
&sshdr);
/* failed to execute TUR, assume media not present */
@@ -1643,7 +1726,7 @@
* flush everything.
*/
res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, sshdr,
- timeout, SD_MAX_RETRIES, 0, RQF_PM, NULL);
+ timeout, sdkp->max_retries, 0, RQF_PM, NULL);
if (res == 0)
break;
}
@@ -1683,43 +1766,37 @@
static void sd_rescan(struct device *dev)
{
struct scsi_disk *sdkp = dev_get_drvdata(dev);
+ int ret;
- revalidate_disk(sdkp->disk);
+ ret = sd_revalidate_disk(sdkp->disk);
+ revalidate_disk_size(sdkp->disk, ret == 0);
}
+static int sd_ioctl(struct block_device *bdev, fmode_t mode,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *p = (void __user *)arg;
+ int ret;
+
+ ret = sd_ioctl_common(bdev, mode, cmd, p);
+ if (ret != -ENOTTY)
+ return ret;
+
+ return scsi_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p);
+}
#ifdef CONFIG_COMPAT
-/*
- * This gets directly called from VFS. When the ioctl
- * is not recognized we go back to the other translation paths.
- */
static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct gendisk *disk = bdev->bd_disk;
- struct scsi_disk *sdkp = scsi_disk(disk);
- struct scsi_device *sdev = sdkp->device;
void __user *p = compat_ptr(arg);
- int error;
+ int ret;
- error = scsi_verify_blk_ioctl(bdev, cmd);
- if (error < 0)
- return error;
+ ret = sd_ioctl_common(bdev, mode, cmd, p);
+ if (ret != -ENOTTY)
+ return ret;
- error = scsi_ioctl_block_when_processing_errors(sdev, cmd,
- (mode & FMODE_NDELAY) != 0);
- if (error)
- return error;
-
- if (is_sed_ioctl(cmd))
- return sed_ioctl(sdkp->opal_dev, cmd, p);
-
- /*
- * Let the static ioctl translation table take care of it.
- */
- if (!sdev->host->hostt->compat_ioctl)
- return -ENOIOCTLCMD;
- return sdev->host->hostt->compat_ioctl(sdev, cmd, p);
+ return scsi_compat_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p);
}
#endif
@@ -1746,7 +1823,8 @@
static int sd_pr_command(struct block_device *bdev, u8 sa,
u64 key, u64 sa_key, u8 type, u8 flags)
{
- struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device;
+ struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
+ struct scsi_device *sdev = sdkp->device;
struct scsi_sense_hdr sshdr;
int result;
u8 cmd[16] = { 0, };
@@ -1762,7 +1840,7 @@
data[20] = flags;
result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, &data, sizeof(data),
- &sshdr, SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+ &sshdr, SD_TIMEOUT, sdkp->max_retries, NULL);
if (driver_byte(result) == DRIVER_SENSE &&
scsi_sense_valid(&sshdr)) {
@@ -1826,7 +1904,6 @@
.compat_ioctl = sd_compat_ioctl,
#endif
.check_events = sd_check_events,
- .revalidate_disk = sd_revalidate_disk,
.unlock_native_capacity = sd_unlock_native_capacity,
.report_zones = sd_zbc_report_zones,
.pr_ops = &sd_pr_ops,
@@ -1973,6 +2050,9 @@
case REQ_OP_WRITE_SAME:
case REQ_OP_ZONE_RESET:
case REQ_OP_ZONE_RESET_ALL:
+ case REQ_OP_ZONE_OPEN:
+ case REQ_OP_ZONE_CLOSE:
+ case REQ_OP_ZONE_FINISH:
if (!result) {
good_bytes = blk_rq_bytes(req);
scsi_set_resid(SCpnt, 0);
@@ -2060,7 +2140,7 @@
out:
if (sd_is_zoned(sdkp))
- sd_zbc_complete(SCpnt, good_bytes, &sshdr);
+ good_bytes = sd_zbc_complete(SCpnt, good_bytes, &sshdr);
SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt,
"sd_done: completed %d of %d bytes\n",
@@ -2096,7 +2176,7 @@
the_result = scsi_execute_req(sdkp->device, cmd,
DMA_NONE, NULL, 0,
&sshdr, SD_TIMEOUT,
- SD_MAX_RETRIES, NULL);
+ sdkp->max_retries, NULL);
/*
* If the drive has indicated to us that it
@@ -2152,7 +2232,7 @@
cmd[4] |= 1 << 4;
scsi_execute_req(sdkp->device, cmd, DMA_NONE,
NULL, 0, &sshdr,
- SD_TIMEOUT, SD_MAX_RETRIES,
+ SD_TIMEOUT, sdkp->max_retries,
NULL);
spintime_expire = jiffies + 100 * HZ;
spintime = 1;
@@ -2294,7 +2374,7 @@
the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
buffer, RC16_LEN, &sshdr,
- SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+ SD_TIMEOUT, sdkp->max_retries, NULL);
if (media_not_present(sdkp, &sshdr))
return -ENODEV;
@@ -2379,7 +2459,7 @@
the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
buffer, 8, &sshdr,
- SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+ SD_TIMEOUT, sdkp->max_retries, NULL);
if (media_not_present(sdkp, &sshdr))
return -ENODEV;
@@ -2560,18 +2640,16 @@
sd_printk(KERN_NOTICE, sdkp,
"%u-byte physical blocks\n",
sdkp->physical_block_size);
-
- sd_zbc_print_zones(sdkp);
}
/* called with buffer of length 512 */
static inline int
-sd_do_mode_sense(struct scsi_device *sdp, int dbd, int modepage,
+sd_do_mode_sense(struct scsi_disk *sdkp, int dbd, int modepage,
unsigned char *buffer, int len, struct scsi_mode_data *data,
struct scsi_sense_hdr *sshdr)
{
- return scsi_mode_sense(sdp, dbd, modepage, buffer, len,
- SD_TIMEOUT, SD_MAX_RETRIES, data,
+ return scsi_mode_sense(sdkp->device, dbd, modepage, buffer, len,
+ SD_TIMEOUT, sdkp->max_retries, data,
sshdr);
}
@@ -2594,14 +2672,14 @@
}
if (sdp->use_192_bytes_for_3f) {
- res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 192, &data, NULL);
+ res = sd_do_mode_sense(sdkp, 0, 0x3F, buffer, 192, &data, NULL);
} else {
/*
* First attempt: ask for all pages (0x3F), but only 4 bytes.
* We have to start carefully: some devices hang if we ask
* for more than is available.
*/
- res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 4, &data, NULL);
+ res = sd_do_mode_sense(sdkp, 0, 0x3F, buffer, 4, &data, NULL);
/*
* Second attempt: ask for page 0 When only page 0 is
@@ -2609,18 +2687,18 @@
* 5: Illegal Request, Sense Code 24: Invalid field in
* CDB.
*/
- if (!scsi_status_is_good(res))
- res = sd_do_mode_sense(sdp, 0, 0, buffer, 4, &data, NULL);
+ if (res < 0)
+ res = sd_do_mode_sense(sdkp, 0, 0, buffer, 4, &data, NULL);
/*
* Third attempt: ask 255 bytes, as we did earlier.
*/
- if (!scsi_status_is_good(res))
- res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 255,
+ if (res < 0)
+ res = sd_do_mode_sense(sdkp, 0, 0x3F, buffer, 255,
&data, NULL);
}
- if (!scsi_status_is_good(res)) {
+ if (res < 0) {
sd_first_printk(KERN_WARNING, sdkp,
"Test WP failed, assume Write Enabled\n");
} else {
@@ -2678,10 +2756,10 @@
}
/* cautiously ask */
- res = sd_do_mode_sense(sdp, dbd, modepage, buffer, first_len,
+ res = sd_do_mode_sense(sdkp, dbd, modepage, buffer, first_len,
&data, &sshdr);
- if (!scsi_status_is_good(res))
+ if (res < 0)
goto bad_sense;
if (!data.header_length) {
@@ -2710,10 +2788,10 @@
/* Get the data */
if (len > first_len)
- res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len,
+ res = sd_do_mode_sense(sdkp, dbd, modepage, buffer, len,
&data, &sshdr);
- if (scsi_status_is_good(res)) {
+ if (!res) {
int offset = data.header_length + data.block_descriptor_length;
while (offset < len) {
@@ -2829,9 +2907,9 @@
return;
res = scsi_mode_sense(sdp, 1, 0x0a, buffer, 36, SD_TIMEOUT,
- SD_MAX_RETRIES, &data, &sshdr);
+ sdkp->max_retries, &data, &sshdr);
- if (!scsi_status_is_good(res) || !data.header_length ||
+ if (res < 0 || !data.header_length ||
data.length < 6) {
sd_first_printk(KERN_WARNING, sdkp,
"getting Control mode page failed, assume no ATO\n");
@@ -2948,22 +3026,32 @@
if (sdkp->device->type == TYPE_ZBC) {
/* Host-managed */
- q->limits.zoned = BLK_ZONED_HM;
+ blk_queue_set_zoned(sdkp->disk, BLK_ZONED_HM);
} else {
sdkp->zoned = (buffer[8] >> 4) & 3;
- if (sdkp->zoned == 1)
+ if (sdkp->zoned == 1) {
/* Host-aware */
- q->limits.zoned = BLK_ZONED_HA;
- else
- /*
- * Treat drive-managed devices as
- * regular block devices.
- */
- q->limits.zoned = BLK_ZONED_NONE;
+ blk_queue_set_zoned(sdkp->disk, BLK_ZONED_HA);
+ } else {
+ /* Regular disk or drive managed disk */
+ blk_queue_set_zoned(sdkp->disk, BLK_ZONED_NONE);
+ }
}
- if (blk_queue_is_zoned(q) && sdkp->first_scan)
+
+ if (!sdkp->first_scan)
+ goto out;
+
+ if (blk_queue_is_zoned(q)) {
sd_printk(KERN_NOTICE, sdkp, "Host-%s zoned block device\n",
q->limits.zoned == BLK_ZONED_HM ? "managed" : "aware");
+ } else {
+ if (sdkp->zoned == 1)
+ sd_printk(KERN_NOTICE, sdkp,
+ "Host-aware SMR disk used as regular disk\n");
+ else if (sdkp->zoned == 2)
+ sd_printk(KERN_NOTICE, sdkp,
+ "Drive-managed SMR disk\n");
+ }
out:
kfree(buffer);
@@ -3193,10 +3281,19 @@
sdkp->first_scan = 0;
- set_capacity(disk, logical_to_sectors(sdp, sdkp->capacity));
+ set_capacity_revalidate_and_notify(disk,
+ logical_to_sectors(sdp, sdkp->capacity), false);
sd_config_write_same(sdkp);
kfree(buffer);
+ /*
+ * For a zoned drive, revalidating the zones can be done only once
+ * the gendisk capacity is set. So if this fails, set back the gendisk
+ * capacity to 0.
+ */
+ if (sd_zbc_revalidate_zones(sdkp))
+ set_capacity_revalidate_and_notify(disk, 0, false);
+
out:
return 0;
}
@@ -3333,6 +3430,7 @@
sdkp->driver = &sd_template;
sdkp->disk = gd;
sdkp->index = index;
+ sdkp->max_retries = SD_MAX_RETRIES;
atomic_set(&sdkp->openers, 0);
atomic_set(&sdkp->device->ioerr_cnt, 0);
@@ -3345,15 +3443,16 @@
}
device_initialize(&sdkp->dev);
- sdkp->dev.parent = dev;
+ sdkp->dev.parent = get_device(dev);
sdkp->dev.class = &sd_disk_class;
dev_set_name(&sdkp->dev, "%s", dev_name(dev));
error = device_add(&sdkp->dev);
- if (error)
- goto out_free_index;
+ if (error) {
+ put_device(&sdkp->dev);
+ goto out;
+ }
- get_device(dev);
dev_set_drvdata(dev, sdkp);
gd->major = sd_major((index & 0xf0) >> 4);
@@ -3385,6 +3484,10 @@
}
blk_pm_runtime_init(sdp->request_queue, dev);
+ if (sdp->rpm_autosuspend) {
+ pm_runtime_set_autosuspend_delay(dev,
+ sdp->host->hostt->rpm_autosuspend_delay);
+ }
device_add_disk(dev, gd, NULL);
if (sdkp->capacity)
sd_dif_config_host(sdkp);
@@ -3392,7 +3495,7 @@
sd_revalidate_disk(gd);
if (sdkp->security) {
- sdkp->opal_dev = init_opal_dev(sdp, &sd_sec_submit);
+ sdkp->opal_dev = init_opal_dev(sdkp, &sd_sec_submit);
if (sdkp->opal_dev)
sd_printk(KERN_NOTICE, sdkp, "supports TCG Opal\n");
}
@@ -3408,6 +3511,7 @@
out_put:
put_disk(gd);
out_free:
+ sd_zbc_release_disk(sdkp);
kfree(sdkp);
out:
scsi_autopm_put_device(sdp);
@@ -3484,6 +3588,8 @@
put_disk(disk);
put_device(&sdkp->device->sdev_gendev);
+ sd_zbc_release_disk(sdkp);
+
kfree(sdkp);
}
@@ -3504,7 +3610,7 @@
return -ENODEV;
res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr,
- SD_TIMEOUT, SD_MAX_RETRIES, 0, RQF_PM, NULL);
+ SD_TIMEOUT, sdkp->max_retries, 0, RQF_PM, NULL);
if (res) {
sd_print_result(sdkp, "Start/Stop Unit failed", res);
if (driver_byte(res) == DRIVER_SENSE)
@@ -3717,15 +3823,13 @@
module_init(init_sd);
module_exit(exit_sd);
-static void sd_print_sense_hdr(struct scsi_disk *sdkp,
- struct scsi_sense_hdr *sshdr)
+void sd_print_sense_hdr(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr)
{
scsi_print_sense_hdr(sdkp->device,
sdkp->disk ? sdkp->disk->disk_name : NULL, sshdr);
}
-static void sd_print_result(const struct scsi_disk *sdkp, const char *msg,
- int result)
+void sd_print_result(const struct scsi_disk *sdkp, const char *msg, int result)
{
const char *hb_string = scsi_hostbyte_string(result);
const char *db_string = scsi_driverbyte_string(result);
@@ -3740,4 +3844,3 @@
"%s: Result: hostbyte=0x%02x driverbyte=0x%02x\n",
msg, host_byte(result), driver_byte(result));
}
-
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 1eab779..b59136c 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -75,13 +75,22 @@
struct opal_dev *opal_dev;
#ifdef CONFIG_BLK_DEV_ZONED
u32 nr_zones;
+ u32 rev_nr_zones;
u32 zone_blocks;
+ u32 rev_zone_blocks;
u32 zones_optimal_open;
u32 zones_optimal_nonseq;
u32 zones_max_open;
+ u32 *zones_wp_offset;
+ spinlock_t zones_wp_offset_lock;
+ u32 *rev_wp_offset;
+ struct mutex rev_mutex;
+ struct work_struct zone_wp_offset_work;
+ char *zone_wp_update_buf;
#endif
atomic_t openers;
sector_t capacity; /* size in logical blocks */
+ int max_retries;
u32 max_xfer_blocks;
u32 opt_xfer_blocks;
u32 max_ws_blocks;
@@ -207,36 +216,59 @@
#ifdef CONFIG_BLK_DEV_ZONED
-extern int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buffer);
-extern void sd_zbc_print_zones(struct scsi_disk *sdkp);
-extern blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd, bool all);
-extern void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes,
- struct scsi_sense_hdr *sshdr);
-extern int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
- struct blk_zone *zones, unsigned int *nr_zones);
+void sd_zbc_release_disk(struct scsi_disk *sdkp);
+int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buffer);
+int sd_zbc_revalidate_zones(struct scsi_disk *sdkp);
+blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
+ unsigned char op, bool all);
+unsigned int sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes,
+ struct scsi_sense_hdr *sshdr);
+int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
+ unsigned int nr_zones, report_zones_cb cb, void *data);
+
+blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
+ unsigned int nr_blocks);
#else /* CONFIG_BLK_DEV_ZONED */
+static inline void sd_zbc_release_disk(struct scsi_disk *sdkp) {}
+
static inline int sd_zbc_read_zones(struct scsi_disk *sdkp,
unsigned char *buf)
{
return 0;
}
-static inline void sd_zbc_print_zones(struct scsi_disk *sdkp) {}
+static inline int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
+{
+ return 0;
+}
-static inline blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd,
- bool all)
+static inline blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
+ unsigned char op,
+ bool all)
{
return BLK_STS_TARGET;
}
-static inline void sd_zbc_complete(struct scsi_cmnd *cmd,
- unsigned int good_bytes,
- struct scsi_sense_hdr *sshdr) {}
+static inline unsigned int sd_zbc_complete(struct scsi_cmnd *cmd,
+ unsigned int good_bytes, struct scsi_sense_hdr *sshdr)
+{
+ return good_bytes;
+}
+
+static inline blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd,
+ sector_t *lba,
+ unsigned int nr_blocks)
+{
+ return BLK_STS_TARGET;
+}
#define sd_zbc_report_zones NULL
#endif /* CONFIG_BLK_DEV_ZONED */
+void sd_print_sense_hdr(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr);
+void sd_print_result(const struct scsi_disk *sdkp, const char *msg, int result);
+
#endif /* _SCSI_DISK_H */
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index 1efc69e..01088f3 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -11,6 +11,7 @@
#include <linux/blkdev.h>
#include <linux/vmalloc.h>
#include <linux/sched/mm.h>
+#include <linux/mutex.h>
#include <asm/unaligned.h>
@@ -19,34 +20,60 @@
#include "sd.h"
-/**
- * sd_zbc_parse_report - Convert a zone descriptor to a struct blk_zone,
- * @sdkp: The disk the report originated from
- * @buf: Address of the report zone descriptor
- * @zone: the destination zone structure
- *
- * All LBA sized values are converted to 512B sectors unit.
- */
-static void sd_zbc_parse_report(struct scsi_disk *sdkp, u8 *buf,
- struct blk_zone *zone)
+static unsigned int sd_zbc_get_zone_wp_offset(struct blk_zone *zone)
+{
+ if (zone->type == ZBC_ZONE_TYPE_CONV)
+ return 0;
+
+ switch (zone->cond) {
+ case BLK_ZONE_COND_IMP_OPEN:
+ case BLK_ZONE_COND_EXP_OPEN:
+ case BLK_ZONE_COND_CLOSED:
+ return zone->wp - zone->start;
+ case BLK_ZONE_COND_FULL:
+ return zone->len;
+ case BLK_ZONE_COND_EMPTY:
+ case BLK_ZONE_COND_OFFLINE:
+ case BLK_ZONE_COND_READONLY:
+ default:
+ /*
+ * Offline and read-only zones do not have a valid
+ * write pointer. Use 0 as for an empty zone.
+ */
+ return 0;
+ }
+}
+
+static int sd_zbc_parse_report(struct scsi_disk *sdkp, u8 *buf,
+ unsigned int idx, report_zones_cb cb, void *data)
{
struct scsi_device *sdp = sdkp->device;
+ struct blk_zone zone = { 0 };
+ int ret;
- memset(zone, 0, sizeof(struct blk_zone));
-
- zone->type = buf[0] & 0x0f;
- zone->cond = (buf[1] >> 4) & 0xf;
+ zone.type = buf[0] & 0x0f;
+ zone.cond = (buf[1] >> 4) & 0xf;
if (buf[1] & 0x01)
- zone->reset = 1;
+ zone.reset = 1;
if (buf[1] & 0x02)
- zone->non_seq = 1;
+ zone.non_seq = 1;
- zone->len = logical_to_sectors(sdp, get_unaligned_be64(&buf[8]));
- zone->start = logical_to_sectors(sdp, get_unaligned_be64(&buf[16]));
- zone->wp = logical_to_sectors(sdp, get_unaligned_be64(&buf[24]));
- if (zone->type != ZBC_ZONE_TYPE_CONV &&
- zone->cond == ZBC_ZONE_COND_FULL)
- zone->wp = zone->start + zone->len;
+ zone.len = logical_to_sectors(sdp, get_unaligned_be64(&buf[8]));
+ zone.capacity = zone.len;
+ zone.start = logical_to_sectors(sdp, get_unaligned_be64(&buf[16]));
+ zone.wp = logical_to_sectors(sdp, get_unaligned_be64(&buf[24]));
+ if (zone.type != ZBC_ZONE_TYPE_CONV &&
+ zone.cond == ZBC_ZONE_COND_FULL)
+ zone.wp = zone.start + zone.len;
+
+ ret = cb(&zone, idx, data);
+ if (ret)
+ return ret;
+
+ if (sdkp->rev_wp_offset)
+ sdkp->rev_wp_offset[idx] = sd_zbc_get_zone_wp_offset(&zone);
+
+ return 0;
}
/**
@@ -87,9 +114,11 @@
timeout, SD_MAX_RETRIES, NULL);
if (result) {
sd_printk(KERN_ERR, sdkp,
- "REPORT ZONES lba %llu failed with %d/%d\n",
- (unsigned long long)lba,
- host_byte(result), driver_byte(result));
+ "REPORT ZONES start lba %llu failed\n", lba);
+ sd_print_result(sdkp, "REPORT ZONES", result);
+ if (driver_byte(result) == DRIVER_SENSE &&
+ scsi_sense_valid(&sshdr))
+ sd_print_sense_hdr(sdkp, &sshdr);
return -EIO;
}
@@ -104,11 +133,6 @@
return 0;
}
-/*
- * Maximum number of zones to get with one report zones command.
- */
-#define SD_ZBC_REPORT_MAX_ZONES 8192U
-
/**
* Allocate a buffer for report zones reply.
* @sdkp: The target disk
@@ -131,70 +155,30 @@
/*
* Report zone buffer size should be at most 64B times the number of
- * zones requested plus the 64B reply header, but should be at least
- * SECTOR_SIZE for ATA devices.
+ * zones requested plus the 64B reply header, but should be aligned
+ * to SECTOR_SIZE for ATA devices.
* Make sure that this size does not exceed the hardware capabilities.
* Furthermore, since the report zone command cannot be split, make
* sure that the allocated buffer can always be mapped by limiting the
* number of pages allocated to the HBA max segments limit.
*/
- nr_zones = min(nr_zones, SD_ZBC_REPORT_MAX_ZONES);
- bufsize = roundup((nr_zones + 1) * 64, 512);
+ nr_zones = min(nr_zones, sdkp->nr_zones);
+ bufsize = roundup((nr_zones + 1) * 64, SECTOR_SIZE);
bufsize = min_t(size_t, bufsize,
queue_max_hw_sectors(q) << SECTOR_SHIFT);
bufsize = min_t(size_t, bufsize, queue_max_segments(q) << PAGE_SHIFT);
- buf = vzalloc(bufsize);
- if (buf)
- *buflen = bufsize;
-
- return buf;
-}
-
-/**
- * sd_zbc_report_zones - Disk report zones operation.
- * @disk: The target disk
- * @sector: Start 512B sector of the report
- * @zones: Array of zone descriptors
- * @nr_zones: Number of descriptors in the array
- *
- * Execute a report zones command on the target disk.
- */
-int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
- struct blk_zone *zones, unsigned int *nr_zones)
-{
- struct scsi_disk *sdkp = scsi_disk(disk);
- unsigned int i, nrz = *nr_zones;
- unsigned char *buf;
- size_t buflen = 0, offset = 0;
- int ret = 0;
-
- if (!sd_is_zoned(sdkp))
- /* Not a zoned device */
- return -EOPNOTSUPP;
-
- buf = sd_zbc_alloc_report_buffer(sdkp, nrz, &buflen);
- if (!buf)
- return -ENOMEM;
-
- ret = sd_zbc_do_report_zones(sdkp, buf, buflen,
- sectors_to_logical(sdkp->device, sector), true);
- if (ret)
- goto out;
-
- nrz = min(nrz, get_unaligned_be32(&buf[0]) / 64);
- for (i = 0; i < nrz; i++) {
- offset += 64;
- sd_zbc_parse_report(sdkp, buf + offset, zones);
- zones++;
+ while (bufsize >= SECTOR_SIZE) {
+ buf = __vmalloc(bufsize,
+ GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY);
+ if (buf) {
+ *buflen = bufsize;
+ return buf;
+ }
+ bufsize = rounddown(bufsize >> 1, SECTOR_SIZE);
}
- *nr_zones = nrz;
-
-out:
- kvfree(buf);
-
- return ret;
+ return NULL;
}
/**
@@ -206,19 +190,63 @@
return logical_to_sectors(sdkp->device, sdkp->zone_blocks);
}
-/**
- * sd_zbc_setup_reset_cmnd - Prepare a RESET WRITE POINTER scsi command.
- * @cmd: the command to setup
- * @all: Reset all zones control.
- *
- * Called from sd_init_command() for a REQ_OP_ZONE_RESET request.
- */
-blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd, bool all)
+int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
+ unsigned int nr_zones, report_zones_cb cb, void *data)
+{
+ struct scsi_disk *sdkp = scsi_disk(disk);
+ sector_t capacity = logical_to_sectors(sdkp->device, sdkp->capacity);
+ unsigned int nr, i;
+ unsigned char *buf;
+ size_t offset, buflen = 0;
+ int zone_idx = 0;
+ int ret;
+
+ if (!sd_is_zoned(sdkp))
+ /* Not a zoned device */
+ return -EOPNOTSUPP;
+
+ if (!capacity)
+ /* Device gone or invalid */
+ return -ENODEV;
+
+ buf = sd_zbc_alloc_report_buffer(sdkp, nr_zones, &buflen);
+ if (!buf)
+ return -ENOMEM;
+
+ while (zone_idx < nr_zones && sector < capacity) {
+ ret = sd_zbc_do_report_zones(sdkp, buf, buflen,
+ sectors_to_logical(sdkp->device, sector), true);
+ if (ret)
+ goto out;
+
+ offset = 0;
+ nr = min(nr_zones, get_unaligned_be32(&buf[0]) / 64);
+ if (!nr)
+ break;
+
+ for (i = 0; i < nr && zone_idx < nr_zones; i++) {
+ offset += 64;
+ ret = sd_zbc_parse_report(sdkp, buf + offset, zone_idx,
+ cb, data);
+ if (ret)
+ goto out;
+ zone_idx++;
+ }
+
+ sector += sd_zbc_zone_sectors(sdkp) * i;
+ }
+
+ ret = zone_idx;
+out:
+ kvfree(buf);
+ return ret;
+}
+
+static blk_status_t sd_zbc_cmnd_checks(struct scsi_cmnd *cmd)
{
struct request *rq = cmd->request;
struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
sector_t sector = blk_rq_pos(rq);
- sector_t block = sectors_to_logical(sdkp->device, sector);
if (!sd_is_zoned(sdkp))
/* Not a zoned device */
@@ -231,10 +259,146 @@
/* Unaligned request */
return BLK_STS_IOERR;
+ return BLK_STS_OK;
+}
+
+#define SD_ZBC_INVALID_WP_OFST (~0u)
+#define SD_ZBC_UPDATING_WP_OFST (SD_ZBC_INVALID_WP_OFST - 1)
+
+static int sd_zbc_update_wp_offset_cb(struct blk_zone *zone, unsigned int idx,
+ void *data)
+{
+ struct scsi_disk *sdkp = data;
+
+ lockdep_assert_held(&sdkp->zones_wp_offset_lock);
+
+ sdkp->zones_wp_offset[idx] = sd_zbc_get_zone_wp_offset(zone);
+
+ return 0;
+}
+
+static void sd_zbc_update_wp_offset_workfn(struct work_struct *work)
+{
+ struct scsi_disk *sdkp;
+ unsigned int zno;
+ int ret;
+
+ sdkp = container_of(work, struct scsi_disk, zone_wp_offset_work);
+
+ spin_lock_bh(&sdkp->zones_wp_offset_lock);
+ for (zno = 0; zno < sdkp->nr_zones; zno++) {
+ if (sdkp->zones_wp_offset[zno] != SD_ZBC_UPDATING_WP_OFST)
+ continue;
+
+ spin_unlock_bh(&sdkp->zones_wp_offset_lock);
+ ret = sd_zbc_do_report_zones(sdkp, sdkp->zone_wp_update_buf,
+ SD_BUF_SIZE,
+ zno * sdkp->zone_blocks, true);
+ spin_lock_bh(&sdkp->zones_wp_offset_lock);
+ if (!ret)
+ sd_zbc_parse_report(sdkp, sdkp->zone_wp_update_buf + 64,
+ zno, sd_zbc_update_wp_offset_cb,
+ sdkp);
+ }
+ spin_unlock_bh(&sdkp->zones_wp_offset_lock);
+
+ scsi_device_put(sdkp->device);
+}
+
+/**
+ * sd_zbc_prepare_zone_append() - Prepare an emulated ZONE_APPEND command.
+ * @cmd: the command to setup
+ * @lba: the LBA to patch
+ * @nr_blocks: the number of LBAs to be written
+ *
+ * Called from sd_setup_read_write_cmnd() for REQ_OP_ZONE_APPEND.
+ * @sd_zbc_prepare_zone_append() handles the necessary zone wrote locking and
+ * patching of the lba for an emulated ZONE_APPEND command.
+ *
+ * In case the cached write pointer offset is %SD_ZBC_INVALID_WP_OFST it will
+ * schedule a REPORT ZONES command and return BLK_STS_IOERR.
+ */
+blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
+ unsigned int nr_blocks)
+{
+ struct request *rq = cmd->request;
+ struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+ unsigned int wp_offset, zno = blk_rq_zone_no(rq);
+ blk_status_t ret;
+
+ ret = sd_zbc_cmnd_checks(cmd);
+ if (ret != BLK_STS_OK)
+ return ret;
+
+ if (!blk_rq_zone_is_seq(rq))
+ return BLK_STS_IOERR;
+
+ /* Unlock of the write lock will happen in sd_zbc_complete() */
+ if (!blk_req_zone_write_trylock(rq))
+ return BLK_STS_ZONE_RESOURCE;
+
+ spin_lock_bh(&sdkp->zones_wp_offset_lock);
+ wp_offset = sdkp->zones_wp_offset[zno];
+ switch (wp_offset) {
+ case SD_ZBC_INVALID_WP_OFST:
+ /*
+ * We are about to schedule work to update a zone write pointer
+ * offset, which will cause the zone append command to be
+ * requeued. So make sure that the scsi device does not go away
+ * while the work is being processed.
+ */
+ if (scsi_device_get(sdkp->device)) {
+ ret = BLK_STS_IOERR;
+ break;
+ }
+ sdkp->zones_wp_offset[zno] = SD_ZBC_UPDATING_WP_OFST;
+ schedule_work(&sdkp->zone_wp_offset_work);
+ fallthrough;
+ case SD_ZBC_UPDATING_WP_OFST:
+ ret = BLK_STS_DEV_RESOURCE;
+ break;
+ default:
+ wp_offset = sectors_to_logical(sdkp->device, wp_offset);
+ if (wp_offset + nr_blocks > sdkp->zone_blocks) {
+ ret = BLK_STS_IOERR;
+ break;
+ }
+
+ *lba += wp_offset;
+ }
+ spin_unlock_bh(&sdkp->zones_wp_offset_lock);
+ if (ret)
+ blk_req_zone_write_unlock(rq);
+ return ret;
+}
+
+/**
+ * sd_zbc_setup_zone_mgmt_cmnd - Prepare a zone ZBC_OUT command. The operations
+ * can be RESET WRITE POINTER, OPEN, CLOSE or FINISH.
+ * @cmd: the command to setup
+ * @op: Operation to be performed
+ * @all: All zones control
+ *
+ * Called from sd_init_command() for REQ_OP_ZONE_RESET, REQ_OP_ZONE_RESET_ALL,
+ * REQ_OP_ZONE_OPEN, REQ_OP_ZONE_CLOSE or REQ_OP_ZONE_FINISH requests.
+ */
+blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
+ unsigned char op, bool all)
+{
+ struct request *rq = cmd->request;
+ sector_t sector = blk_rq_pos(rq);
+ struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+ sector_t block = sectors_to_logical(sdkp->device, sector);
+ blk_status_t ret;
+
+ ret = sd_zbc_cmnd_checks(cmd);
+ if (ret != BLK_STS_OK)
+ return ret;
+
cmd->cmd_len = 16;
memset(cmd->cmnd, 0, cmd->cmd_len);
cmd->cmnd[0] = ZBC_OUT;
- cmd->cmnd[1] = ZO_RESET_WRITE_POINTER;
+ cmd->cmnd[1] = op;
if (all)
cmd->cmnd[14] = 0x1;
else
@@ -248,32 +412,127 @@
return BLK_STS_OK;
}
+static bool sd_zbc_need_zone_wp_update(struct request *rq)
+{
+ switch (req_op(rq)) {
+ case REQ_OP_ZONE_APPEND:
+ case REQ_OP_ZONE_FINISH:
+ case REQ_OP_ZONE_RESET:
+ case REQ_OP_ZONE_RESET_ALL:
+ return true;
+ case REQ_OP_WRITE:
+ case REQ_OP_WRITE_ZEROES:
+ case REQ_OP_WRITE_SAME:
+ return blk_rq_zone_is_seq(rq);
+ default:
+ return false;
+ }
+}
+
+/**
+ * sd_zbc_zone_wp_update - Update cached zone write pointer upon cmd completion
+ * @cmd: Completed command
+ * @good_bytes: Command reply bytes
+ *
+ * Called from sd_zbc_complete() to handle the update of the cached zone write
+ * pointer value in case an update is needed.
+ */
+static unsigned int sd_zbc_zone_wp_update(struct scsi_cmnd *cmd,
+ unsigned int good_bytes)
+{
+ int result = cmd->result;
+ struct request *rq = cmd->request;
+ struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+ unsigned int zno = blk_rq_zone_no(rq);
+ enum req_opf op = req_op(rq);
+
+ /*
+ * If we got an error for a command that needs updating the write
+ * pointer offset cache, we must mark the zone wp offset entry as
+ * invalid to force an update from disk the next time a zone append
+ * command is issued.
+ */
+ spin_lock_bh(&sdkp->zones_wp_offset_lock);
+
+ if (result && op != REQ_OP_ZONE_RESET_ALL) {
+ if (op == REQ_OP_ZONE_APPEND) {
+ /* Force complete completion (no retry) */
+ good_bytes = 0;
+ scsi_set_resid(cmd, blk_rq_bytes(rq));
+ }
+
+ /*
+ * Force an update of the zone write pointer offset on
+ * the next zone append access.
+ */
+ if (sdkp->zones_wp_offset[zno] != SD_ZBC_UPDATING_WP_OFST)
+ sdkp->zones_wp_offset[zno] = SD_ZBC_INVALID_WP_OFST;
+ goto unlock_wp_offset;
+ }
+
+ switch (op) {
+ case REQ_OP_ZONE_APPEND:
+ rq->__sector += sdkp->zones_wp_offset[zno];
+ fallthrough;
+ case REQ_OP_WRITE_ZEROES:
+ case REQ_OP_WRITE_SAME:
+ case REQ_OP_WRITE:
+ if (sdkp->zones_wp_offset[zno] < sd_zbc_zone_sectors(sdkp))
+ sdkp->zones_wp_offset[zno] +=
+ good_bytes >> SECTOR_SHIFT;
+ break;
+ case REQ_OP_ZONE_RESET:
+ sdkp->zones_wp_offset[zno] = 0;
+ break;
+ case REQ_OP_ZONE_FINISH:
+ sdkp->zones_wp_offset[zno] = sd_zbc_zone_sectors(sdkp);
+ break;
+ case REQ_OP_ZONE_RESET_ALL:
+ memset(sdkp->zones_wp_offset, 0,
+ sdkp->nr_zones * sizeof(unsigned int));
+ break;
+ default:
+ break;
+ }
+
+unlock_wp_offset:
+ spin_unlock_bh(&sdkp->zones_wp_offset_lock);
+
+ return good_bytes;
+}
+
/**
* sd_zbc_complete - ZBC command post processing.
* @cmd: Completed command
* @good_bytes: Command reply bytes
* @sshdr: command sense header
*
- * Called from sd_done(). Process report zones reply and handle reset zone
- * and write commands errors.
+ * Called from sd_done() to handle zone commands errors and updates to the
+ * device queue zone write pointer offset cahce.
*/
-void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes,
+unsigned int sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes,
struct scsi_sense_hdr *sshdr)
{
int result = cmd->result;
struct request *rq = cmd->request;
- if (req_op(rq) == REQ_OP_ZONE_RESET &&
+ if (op_is_zone_mgmt(req_op(rq)) &&
result &&
sshdr->sense_key == ILLEGAL_REQUEST &&
sshdr->asc == 0x24) {
/*
- * INVALID FIELD IN CDB error: reset of a conventional
- * zone was attempted. Nothing to worry about, so be
- * quiet about the error.
+ * INVALID FIELD IN CDB error: a zone management command was
+ * attempted on a conventional zone. Nothing to worry about,
+ * so be quiet about the error.
*/
rq->rq_flags |= RQF_QUIET;
- }
+ } else if (sd_zbc_need_zone_wp_update(rq))
+ good_bytes = sd_zbc_zone_wp_update(cmd, good_bytes);
+
+ if (req_op(rq) == REQ_OP_ZONE_APPEND)
+ blk_req_zone_write_unlock(rq);
+
+ return good_bytes;
}
/**
@@ -323,44 +582,29 @@
}
/**
- * sd_zbc_check_zones - Check the device capacity and zone sizes
+ * sd_zbc_check_capacity - Check the device capacity
* @sdkp: Target disk
+ * @buf: command buffer
+ * @zblocks: zone size in number of blocks
*
- * Check that the device capacity as reported by READ CAPACITY matches the
- * max_lba value (plus one)of the report zones command reply. Also check that
- * all zones of the device have an equal size, only allowing the last zone of
- * the disk to have a smaller size (runt zone). The zone size must also be a
- * power of two.
+ * Get the device zone size and check that the device capacity as reported
+ * by READ CAPACITY matches the max_lba value (plus one) of the report zones
+ * command reply for devices with RC_BASIS == 0.
*
- * Returns the zone size in number of blocks upon success or an error code
- * upon failure.
+ * Returns 0 upon success or an error code upon failure.
*/
-static int sd_zbc_check_zones(struct scsi_disk *sdkp, u32 *zblocks)
+static int sd_zbc_check_capacity(struct scsi_disk *sdkp, unsigned char *buf,
+ u32 *zblocks)
{
- size_t bufsize, buflen;
- unsigned int noio_flag;
- u64 zone_blocks = 0;
- sector_t max_lba, block = 0;
- unsigned char *buf;
+ u64 zone_blocks;
+ sector_t max_lba;
unsigned char *rec;
int ret;
- u8 same;
- /* Do all memory allocations as if GFP_NOIO was specified */
- noio_flag = memalloc_noio_save();
-
- /* Get a buffer */
- buf = sd_zbc_alloc_report_buffer(sdkp, SD_ZBC_REPORT_MAX_ZONES,
- &bufsize);
- if (!buf) {
- ret = -ENOMEM;
- goto out;
- }
-
- /* Do a report zone to get max_lba and the same field */
- ret = sd_zbc_do_report_zones(sdkp, buf, bufsize, 0, false);
+ /* Do a report zone to get max_lba and the size of the first zone */
+ ret = sd_zbc_do_report_zones(sdkp, buf, SD_BUF_SIZE, 0, false);
if (ret)
- goto out_free;
+ return ret;
if (sdkp->rc_basis == 0) {
/* The max_lba field is the capacity of this device */
@@ -375,80 +619,141 @@
}
}
- /*
- * Check same field: for any value other than 0, we know that all zones
- * have the same size.
- */
- same = buf[4] & 0x0f;
- if (same > 0) {
- rec = &buf[64];
- zone_blocks = get_unaligned_be64(&rec[8]);
- goto out;
- }
-
- /*
- * Check the size of all zones: all zones must be of
- * equal size, except the last zone which can be smaller
- * than other zones.
- */
- do {
-
- /* Parse REPORT ZONES header */
- buflen = min_t(size_t, get_unaligned_be32(&buf[0]) + 64,
- bufsize);
- rec = buf + 64;
-
- /* Parse zone descriptors */
- while (rec < buf + buflen) {
- u64 this_zone_blocks = get_unaligned_be64(&rec[8]);
-
- if (zone_blocks == 0) {
- zone_blocks = this_zone_blocks;
- } else if (this_zone_blocks != zone_blocks &&
- (block + this_zone_blocks < sdkp->capacity
- || this_zone_blocks > zone_blocks)) {
- zone_blocks = 0;
- goto out;
- }
- block += this_zone_blocks;
- rec += 64;
- }
-
- if (block < sdkp->capacity) {
- ret = sd_zbc_do_report_zones(sdkp, buf, bufsize, block,
- true);
- if (ret)
- goto out_free;
- }
-
- } while (block < sdkp->capacity);
-
-out:
- if (!zone_blocks) {
- if (sdkp->first_scan)
- sd_printk(KERN_NOTICE, sdkp,
- "Devices with non constant zone "
- "size are not supported\n");
- ret = -ENODEV;
- } else if (!is_power_of_2(zone_blocks)) {
- if (sdkp->first_scan)
- sd_printk(KERN_NOTICE, sdkp,
- "Devices with non power of 2 zone "
- "size are not supported\n");
- ret = -ENODEV;
- } else if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) {
+ /* Get the size of the first reported zone */
+ rec = buf + 64;
+ zone_blocks = get_unaligned_be64(&rec[8]);
+ if (logical_to_sectors(sdkp->device, zone_blocks) > UINT_MAX) {
if (sdkp->first_scan)
sd_printk(KERN_NOTICE, sdkp,
"Zone size too large\n");
- ret = -EFBIG;
- } else {
- *zblocks = zone_blocks;
- ret = 0;
+ return -EFBIG;
}
-out_free:
- memalloc_noio_restore(noio_flag);
- kvfree(buf);
+ *zblocks = zone_blocks;
+
+ return 0;
+}
+
+static void sd_zbc_print_zones(struct scsi_disk *sdkp)
+{
+ if (!sd_is_zoned(sdkp) || !sdkp->capacity)
+ return;
+
+ if (sdkp->capacity & (sdkp->zone_blocks - 1))
+ sd_printk(KERN_NOTICE, sdkp,
+ "%u zones of %u logical blocks + 1 runt zone\n",
+ sdkp->nr_zones - 1,
+ sdkp->zone_blocks);
+ else
+ sd_printk(KERN_NOTICE, sdkp,
+ "%u zones of %u logical blocks\n",
+ sdkp->nr_zones,
+ sdkp->zone_blocks);
+}
+
+static int sd_zbc_init_disk(struct scsi_disk *sdkp)
+{
+ sdkp->zones_wp_offset = NULL;
+ spin_lock_init(&sdkp->zones_wp_offset_lock);
+ sdkp->rev_wp_offset = NULL;
+ mutex_init(&sdkp->rev_mutex);
+ INIT_WORK(&sdkp->zone_wp_offset_work, sd_zbc_update_wp_offset_workfn);
+ sdkp->zone_wp_update_buf = kzalloc(SD_BUF_SIZE, GFP_KERNEL);
+ if (!sdkp->zone_wp_update_buf)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void sd_zbc_release_disk(struct scsi_disk *sdkp)
+{
+ kvfree(sdkp->zones_wp_offset);
+ sdkp->zones_wp_offset = NULL;
+ kfree(sdkp->zone_wp_update_buf);
+ sdkp->zone_wp_update_buf = NULL;
+}
+
+static void sd_zbc_revalidate_zones_cb(struct gendisk *disk)
+{
+ struct scsi_disk *sdkp = scsi_disk(disk);
+
+ swap(sdkp->zones_wp_offset, sdkp->rev_wp_offset);
+}
+
+int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
+{
+ struct gendisk *disk = sdkp->disk;
+ struct request_queue *q = disk->queue;
+ u32 zone_blocks = sdkp->rev_zone_blocks;
+ unsigned int nr_zones = sdkp->rev_nr_zones;
+ u32 max_append;
+ int ret = 0;
+ unsigned int flags;
+
+ /*
+ * For all zoned disks, initialize zone append emulation data if not
+ * already done. This is necessary also for host-aware disks used as
+ * regular disks due to the presence of partitions as these partitions
+ * may be deleted and the disk zoned model changed back from
+ * BLK_ZONED_NONE to BLK_ZONED_HA.
+ */
+ if (sd_is_zoned(sdkp) && !sdkp->zone_wp_update_buf) {
+ ret = sd_zbc_init_disk(sdkp);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * There is nothing to do for regular disks, including host-aware disks
+ * that have partitions.
+ */
+ if (!blk_queue_is_zoned(q))
+ return 0;
+
+ /*
+ * Make sure revalidate zones are serialized to ensure exclusive
+ * updates of the scsi disk data.
+ */
+ mutex_lock(&sdkp->rev_mutex);
+
+ if (sdkp->zone_blocks == zone_blocks &&
+ sdkp->nr_zones == nr_zones &&
+ disk->queue->nr_zones == nr_zones)
+ goto unlock;
+
+ flags = memalloc_noio_save();
+ sdkp->zone_blocks = zone_blocks;
+ sdkp->nr_zones = nr_zones;
+ sdkp->rev_wp_offset = kvcalloc(nr_zones, sizeof(u32), GFP_KERNEL);
+ if (!sdkp->rev_wp_offset) {
+ ret = -ENOMEM;
+ memalloc_noio_restore(flags);
+ goto unlock;
+ }
+
+ ret = blk_revalidate_disk_zones(disk, sd_zbc_revalidate_zones_cb);
+
+ memalloc_noio_restore(flags);
+ kvfree(sdkp->rev_wp_offset);
+ sdkp->rev_wp_offset = NULL;
+
+ if (ret) {
+ sdkp->zone_blocks = 0;
+ sdkp->nr_zones = 0;
+ sdkp->capacity = 0;
+ goto unlock;
+ }
+
+ max_append = min_t(u32, logical_to_sectors(sdkp->device, zone_blocks),
+ q->limits.max_segments << (PAGE_SHIFT - 9));
+ max_append = min_t(u32, max_append, queue_max_hw_sectors(q));
+
+ blk_queue_max_zone_append_sectors(q, max_append);
+
+ sd_zbc_print_zones(sdkp);
+
+unlock:
+ mutex_unlock(&sdkp->rev_mutex);
return ret;
}
@@ -456,6 +761,7 @@
int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf)
{
struct gendisk *disk = sdkp->disk;
+ struct request_queue *q = disk->queue;
unsigned int nr_zones;
u32 zone_blocks = 0;
int ret;
@@ -472,46 +778,27 @@
if (ret)
goto err;
- /*
- * Check zone size: only devices with a constant zone size (except
- * an eventual last runt zone) that is a power of 2 are supported.
- */
- ret = sd_zbc_check_zones(sdkp, &zone_blocks);
+ /* Check the device capacity reported by report zones */
+ ret = sd_zbc_check_capacity(sdkp, buf, &zone_blocks);
if (ret != 0)
goto err;
/* The drive satisfies the kernel restrictions: set it up */
- blk_queue_chunk_sectors(sdkp->disk->queue,
- logical_to_sectors(sdkp->device, zone_blocks));
- blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, sdkp->disk->queue);
- blk_queue_required_elevator_features(sdkp->disk->queue,
- ELEVATOR_F_ZBD_SEQ_WRITE);
+ blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q);
+ blk_queue_required_elevator_features(q, ELEVATOR_F_ZBD_SEQ_WRITE);
+ if (sdkp->zones_max_open == U32_MAX)
+ blk_queue_max_open_zones(q, 0);
+ else
+ blk_queue_max_open_zones(q, sdkp->zones_max_open);
+ blk_queue_max_active_zones(q, 0);
nr_zones = round_up(sdkp->capacity, zone_blocks) >> ilog2(zone_blocks);
/* READ16/WRITE16 is mandatory for ZBC disks */
sdkp->device->use_16_for_rw = 1;
sdkp->device->use_10_for_rw = 0;
- /*
- * Revalidate the disk zone bitmaps once the block device capacity is
- * set on the second revalidate execution during disk scan and if
- * something changed when executing a normal revalidate.
- */
- if (sdkp->first_scan) {
- sdkp->zone_blocks = zone_blocks;
- sdkp->nr_zones = nr_zones;
- return 0;
- }
-
- if (sdkp->zone_blocks != zone_blocks ||
- sdkp->nr_zones != nr_zones ||
- disk->queue->nr_zones != nr_zones) {
- ret = blk_revalidate_disk_zones(disk);
- if (ret != 0)
- goto err;
- sdkp->zone_blocks = zone_blocks;
- sdkp->nr_zones = nr_zones;
- }
+ sdkp->rev_nr_zones = nr_zones;
+ sdkp->rev_zone_blocks = zone_blocks;
return 0;
@@ -520,20 +807,3 @@
return ret;
}
-
-void sd_zbc_print_zones(struct scsi_disk *sdkp)
-{
- if (!sd_is_zoned(sdkp) || !sdkp->capacity)
- return;
-
- if (sdkp->capacity & (sdkp->zone_blocks - 1))
- sd_printk(KERN_NOTICE, sdkp,
- "%u zones of %u logical blocks + 1 runt zone\n",
- sdkp->nr_zones - 1,
- sdkp->zone_blocks);
- else
- sd_printk(KERN_NOTICE, sdkp,
- "%u zones of %u logical blocks\n",
- sdkp->nr_zones,
- sdkp->zone_blocks);
-}
diff --git a/drivers/scsi/sense_codes.h b/drivers/scsi/sense_codes.h
index 201a536..805d4c1 100644
--- a/drivers/scsi/sense_codes.h
+++ b/drivers/scsi/sense_codes.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* The canonical list of T10 Additional Sense Codes is available at:
- * http://www.t10.org/lists/asc-num.txt [most recent: 20141221]
+ * http://www.t10.org/lists/asc-num.txt [most recent: 20200817]
*/
SENSE_CODE(0x0000, "No additional sense information")
@@ -29,6 +29,7 @@
SENSE_CODE(0x001F, "Logical unit transitioning to another power condition")
SENSE_CODE(0x0020, "Extended copy information available")
SENSE_CODE(0x0021, "Atomic command aborted due to ACA")
+SENSE_CODE(0x0022, "Deferred microcode is pending")
SENSE_CODE(0x0100, "No index/sector signal")
@@ -72,6 +73,9 @@
SENSE_CODE(0x0420, "Logical unit not ready, logical unit reset required")
SENSE_CODE(0x0421, "Logical unit not ready, hard reset required")
SENSE_CODE(0x0422, "Logical unit not ready, power cycle required")
+SENSE_CODE(0x0423, "Logical unit not ready, affiliation required")
+SENSE_CODE(0x0424, "Depopulation in progress")
+SENSE_CODE(0x0425, "Depopulation restoration in progress")
SENSE_CODE(0x0500, "Logical unit does not respond to selection")
@@ -104,6 +108,17 @@
SENSE_CODE(0x0B07, "Warning - degraded power to non-volatile cache")
SENSE_CODE(0x0B08, "Warning - power loss expected")
SENSE_CODE(0x0B09, "Warning - device statistics notification active")
+SENSE_CODE(0x0B0A, "Warning - high critical temperature limit exceeded")
+SENSE_CODE(0x0B0B, "Warning - low critical temperature limit exceeded")
+SENSE_CODE(0x0B0C, "Warning - high operating temperature limit exceeded")
+SENSE_CODE(0x0B0D, "Warning - low operating temperature limit exceeded")
+SENSE_CODE(0x0B0E, "Warning - high critical humidity limit exceeded")
+SENSE_CODE(0x0B0F, "Warning - low critical humidity limit exceeded")
+SENSE_CODE(0x0B10, "Warning - high operating humidity limit exceeded")
+SENSE_CODE(0x0B11, "Warning - low operating humidity limit exceeded")
+SENSE_CODE(0x0B12, "Warning - microcode security at risk")
+SENSE_CODE(0x0B13, "Warning - microcode digital signature validation failure")
+SENSE_CODE(0x0B14, "Warning - physical element status change")
SENSE_CODE(0x0C00, "Write error")
SENSE_CODE(0x0C01, "Write error - recovered with auto reallocation")
@@ -122,6 +137,8 @@
SENSE_CODE(0x0C0E, "Multiple write errors")
SENSE_CODE(0x0C0F, "Defects in error window")
SENSE_CODE(0x0C10, "Incomplete multiple atomic write operations")
+SENSE_CODE(0x0C11, "Write error - recovery scan needed")
+SENSE_CODE(0x0C12, "Write error - insufficient zone resources")
SENSE_CODE(0x0D00, "Error detected by third party temporary initiator")
SENSE_CODE(0x0D01, "Third party device failure")
@@ -242,6 +259,9 @@
SENSE_CODE(0x200A, "Access denied - invalid proxy token")
SENSE_CODE(0x200B, "Access denied - ACL LUN conflict")
SENSE_CODE(0x200C, "Illegal command when not in append-only mode")
+SENSE_CODE(0x200D, "Not an administrative logical unit")
+SENSE_CODE(0x200E, "Not a subsidiary logical unit")
+SENSE_CODE(0x200F, "Not a conglomerate logical unit")
SENSE_CODE(0x2100, "Logical block address out of range")
SENSE_CODE(0x2101, "Invalid element address")
@@ -251,6 +271,8 @@
SENSE_CODE(0x2105, "Write boundary violation")
SENSE_CODE(0x2106, "Attempt to read invalid data")
SENSE_CODE(0x2107, "Read boundary violation")
+SENSE_CODE(0x2108, "Misaligned write command")
+SENSE_CODE(0x2109, "Attempt to access gap zone")
SENSE_CODE(0x2200, "Illegal function (use 20 00, 24 00, or 26 00)")
@@ -275,6 +297,7 @@
SENSE_CODE(0x2406, "Nonce not unique")
SENSE_CODE(0x2407, "Nonce timestamp out of range")
SENSE_CODE(0x2408, "Invalid XCDB")
+SENSE_CODE(0x2409, "Invalid fast format")
SENSE_CODE(0x2500, "Logical unit not supported")
@@ -297,6 +320,10 @@
SENSE_CODE(0x2610, "Data decryption key fail limit reached")
SENSE_CODE(0x2611, "Incomplete key-associated data set")
SENSE_CODE(0x2612, "Vendor specific key reference not found")
+SENSE_CODE(0x2613, "Application tag mode page is invalid")
+SENSE_CODE(0x2614, "Tape stream mirroring prevented")
+SENSE_CODE(0x2615, "Copy source or copy destination not authorized")
+SENSE_CODE(0x2616, "Fast copy not possible")
SENSE_CODE(0x2700, "Write protected")
SENSE_CODE(0x2701, "Hardware write protected")
@@ -342,6 +369,7 @@
SENSE_CODE(0x2A13, "Data encryption key instance counter has changed")
SENSE_CODE(0x2A14, "SA creation capabilities data has changed")
SENSE_CODE(0x2A15, "Medium removal prevention preempted")
+SENSE_CODE(0x2A16, "Zone reset write pointer recommended")
SENSE_CODE(0x2B00, "Copy cannot execute since host cannot disconnect")
@@ -360,6 +388,11 @@
SENSE_CODE(0x2C0C, "Orwrite generation does not match")
SENSE_CODE(0x2C0D, "Reset write pointer not allowed")
SENSE_CODE(0x2C0E, "Zone is offline")
+SENSE_CODE(0x2C0F, "Stream not open")
+SENSE_CODE(0x2C10, "Unwritten data in zone")
+SENSE_CODE(0x2C11, "Descriptor format sense data required")
+SENSE_CODE(0x2C12, "Zone is inactive")
+SENSE_CODE(0x2C13, "Well known logical unit access required")
SENSE_CODE(0x2D00, "Overwrite error on update in place")
@@ -395,6 +428,8 @@
SENSE_CODE(0x3101, "Format command failed")
SENSE_CODE(0x3102, "Zoned formatting failed due to spare linking")
SENSE_CODE(0x3103, "Sanitize command failed")
+SENSE_CODE(0x3104, "Depopulation failed")
+SENSE_CODE(0x3105, "Depopulation restoration failed")
SENSE_CODE(0x3200, "No defect spare location available")
SENSE_CODE(0x3201, "Defect list update failure")
@@ -419,6 +454,7 @@
SENSE_CODE(0x3804, "Esn - media class event")
SENSE_CODE(0x3806, "Esn - device busy class event")
SENSE_CODE(0x3807, "Thin Provisioning soft threshold reached")
+SENSE_CODE(0x3808, "Depopulation interrupted")
SENSE_CODE(0x3900, "Saving parameters not supported")
@@ -456,6 +492,7 @@
SENSE_CODE(0x3B1A, "Data transfer device removed")
SENSE_CODE(0x3B1B, "Data transfer device inserted")
SENSE_CODE(0x3B1C, "Too many logical objects on partition to support operation")
+SENSE_CODE(0x3B20, "Element static information changed")
SENSE_CODE(0x3D00, "Invalid bits in identify message")
@@ -488,6 +525,11 @@
SENSE_CODE(0x3F14, "iSCSI IP address changed")
SENSE_CODE(0x3F15, "Inspect referrals sense descriptors")
SENSE_CODE(0x3F16, "Microcode has been changed without reset")
+SENSE_CODE(0x3F17, "Zone transition to full")
+SENSE_CODE(0x3F18, "Bind completed")
+SENSE_CODE(0x3F19, "Bind redirected")
+SENSE_CODE(0x3F1A, "Subsidiary binding changed")
+
/*
* SENSE_CODE(0x40NN, "Ram failure")
* SENSE_CODE(0x40NN, "Diagnostic failure on component nn")
@@ -589,6 +631,9 @@
SENSE_CODE(0x550C, "Insufficient resources to create rod")
SENSE_CODE(0x550D, "Insufficient resources to create rod token")
SENSE_CODE(0x550E, "Insufficient zone resources")
+SENSE_CODE(0x550F, "Insufficient zone resources to complete write")
+SENSE_CODE(0x5510, "Maximum number of streams open")
+SENSE_CODE(0x5511, "Insufficient resources to bind")
SENSE_CODE(0x5700, "Unable to recover table-of-contents")
@@ -692,6 +737,7 @@
SENSE_CODE(0x5D6A, "Firmware impending failure seek time performance")
SENSE_CODE(0x5D6B, "Firmware impending failure spin-up retry count")
SENSE_CODE(0x5D6C, "Firmware impending failure drive calibration retry count")
+SENSE_CODE(0x5D73, "Media impending failure endurance limit met")
SENSE_CODE(0x5DFF, "Failure prediction threshold exceeded (false)")
SENSE_CODE(0x5E00, "Low power condition on")
@@ -744,6 +790,8 @@
SENSE_CODE(0x6709, "Multiply assigned logical unit")
SENSE_CODE(0x670A, "Set target port groups command failed")
SENSE_CODE(0x670B, "ATA device feature not enabled")
+SENSE_CODE(0x670C, "Command rejected")
+SENSE_CODE(0x670D, "Explicit bind not allowed")
SENSE_CODE(0x6800, "Logical unit not configured")
SENSE_CODE(0x6801, "Subsidiary logical unit not configured")
@@ -772,6 +820,10 @@
SENSE_CODE(0x6F05, "Drive region must be permanent/region reset count error")
SENSE_CODE(0x6F06, "Insufficient block count for binding nonce recording")
SENSE_CODE(0x6F07, "Conflict in binding nonce recording")
+SENSE_CODE(0x6F08, "Insufficient permission")
+SENSE_CODE(0x6F09, "Invalid drive-host pairing server")
+SENSE_CODE(0x6F0A, "Drive-host pairing suspended")
+
/*
* SENSE_CODE(0x70NN, "Decompression exception short algorithm id of nn")
*/
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index c2afba2..0a1734f 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -87,9 +87,16 @@
0
};
unsigned char recv_page_code;
+ unsigned int retries = SES_RETRIES;
+ struct scsi_sense_hdr sshdr;
- ret = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen,
- NULL, SES_TIMEOUT, SES_RETRIES, NULL);
+ do {
+ ret = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen,
+ &sshdr, SES_TIMEOUT, 1, NULL);
+ } while (ret > 0 && --retries && scsi_sense_valid(&sshdr) &&
+ (sshdr.sense_key == NOT_READY ||
+ (sshdr.sense_key == UNIT_ATTENTION && sshdr.asc == 0x29)));
+
if (unlikely(ret))
return ret;
@@ -111,7 +118,7 @@
static int ses_send_diag(struct scsi_device *sdev, int page_code,
void *buf, int bufflen)
{
- u32 result;
+ int result;
unsigned char cmd[] = {
SEND_DIAGNOSTIC,
@@ -121,9 +128,16 @@
bufflen & 0xff,
0
};
+ struct scsi_sense_hdr sshdr;
+ unsigned int retries = SES_RETRIES;
- result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, buf, bufflen,
- NULL, SES_TIMEOUT, SES_RETRIES, NULL);
+ do {
+ result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, buf, bufflen,
+ &sshdr, SES_TIMEOUT, 1, NULL);
+ } while (result > 0 && --retries && scsi_sense_valid(&sshdr) &&
+ (sshdr.sense_key == NOT_READY ||
+ (sshdr.sense_key == UNIT_ATTENTION && sshdr.asc == 0x29)));
+
if (result)
sdev_printk(KERN_ERR, sdev, "SEND DIAGNOSTIC result: %8x\n",
result);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 9c6bf13..bfa8d77 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -405,6 +405,38 @@
return 0;
}
+static int get_sg_io_pack_id(int *pack_id, void __user *buf, size_t count)
+{
+ struct sg_header __user *old_hdr = buf;
+ int reply_len;
+
+ if (count >= SZ_SG_HEADER) {
+ /* negative reply_len means v3 format, otherwise v1/v2 */
+ if (get_user(reply_len, &old_hdr->reply_len))
+ return -EFAULT;
+
+ if (reply_len >= 0)
+ return get_user(*pack_id, &old_hdr->pack_id);
+
+ if (in_compat_syscall() &&
+ count >= sizeof(struct compat_sg_io_hdr)) {
+ struct compat_sg_io_hdr __user *hp = buf;
+
+ return get_user(*pack_id, &hp->pack_id);
+ }
+
+ if (count >= sizeof(struct sg_io_hdr)) {
+ struct sg_io_hdr __user *hp = buf;
+
+ return get_user(*pack_id, &hp->pack_id);
+ }
+ }
+
+ /* no valid header was passed, so ignore the pack_id */
+ *pack_id = -1;
+ return 0;
+}
+
static ssize_t
sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
{
@@ -413,8 +445,8 @@
Sg_request *srp;
int req_pack_id = -1;
sg_io_hdr_t *hp;
- struct sg_header *old_hdr = NULL;
- int retval = 0;
+ struct sg_header *old_hdr;
+ int retval;
/*
* This could cause a response to be stranded. Close the associated
@@ -429,72 +461,34 @@
SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
"sg_read: count=%d\n", (int) count));
- if (!access_ok(buf, count))
- return -EFAULT;
- if (sfp->force_packid && (count >= SZ_SG_HEADER)) {
- old_hdr = kmalloc(SZ_SG_HEADER, GFP_KERNEL);
- if (!old_hdr)
- return -ENOMEM;
- if (__copy_from_user(old_hdr, buf, SZ_SG_HEADER)) {
- retval = -EFAULT;
- goto free_old_hdr;
- }
- if (old_hdr->reply_len < 0) {
- if (count >= SZ_SG_IO_HDR) {
- sg_io_hdr_t *new_hdr;
- new_hdr = kmalloc(SZ_SG_IO_HDR, GFP_KERNEL);
- if (!new_hdr) {
- retval = -ENOMEM;
- goto free_old_hdr;
- }
- retval =__copy_from_user
- (new_hdr, buf, SZ_SG_IO_HDR);
- req_pack_id = new_hdr->pack_id;
- kfree(new_hdr);
- if (retval) {
- retval = -EFAULT;
- goto free_old_hdr;
- }
- }
- } else
- req_pack_id = old_hdr->pack_id;
- }
+ if (sfp->force_packid)
+ retval = get_sg_io_pack_id(&req_pack_id, buf, count);
+ if (retval)
+ return retval;
+
srp = sg_get_rq_mark(sfp, req_pack_id);
if (!srp) { /* now wait on packet to arrive */
- if (atomic_read(&sdp->detaching)) {
- retval = -ENODEV;
- goto free_old_hdr;
- }
- if (filp->f_flags & O_NONBLOCK) {
- retval = -EAGAIN;
- goto free_old_hdr;
- }
+ if (atomic_read(&sdp->detaching))
+ return -ENODEV;
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
retval = wait_event_interruptible(sfp->read_wait,
(atomic_read(&sdp->detaching) ||
(srp = sg_get_rq_mark(sfp, req_pack_id))));
- if (atomic_read(&sdp->detaching)) {
- retval = -ENODEV;
- goto free_old_hdr;
- }
- if (retval) {
+ if (atomic_read(&sdp->detaching))
+ return -ENODEV;
+ if (retval)
/* -ERESTARTSYS as signal hit process */
- goto free_old_hdr;
- }
+ return retval;
}
- if (srp->header.interface_id != '\0') {
- retval = sg_new_read(sfp, buf, count, srp);
- goto free_old_hdr;
- }
+ if (srp->header.interface_id != '\0')
+ return sg_new_read(sfp, buf, count, srp);
hp = &srp->header;
- if (old_hdr == NULL) {
- old_hdr = kmalloc(SZ_SG_HEADER, GFP_KERNEL);
- if (! old_hdr) {
- retval = -ENOMEM;
- goto free_old_hdr;
- }
- }
- memset(old_hdr, 0, SZ_SG_HEADER);
+ old_hdr = kzalloc(SZ_SG_HEADER, GFP_KERNEL);
+ if (!old_hdr)
+ return -ENOMEM;
+
old_hdr->reply_len = (int) hp->timeout;
old_hdr->pack_len = old_hdr->reply_len; /* old, strange behaviour */
old_hdr->pack_id = hp->pack_id;
@@ -538,7 +532,7 @@
/* Now copy the result back to the user buffer. */
if (count >= SZ_SG_HEADER) {
- if (__copy_to_user(buf, old_hdr, SZ_SG_HEADER)) {
+ if (copy_to_user(buf, old_hdr, SZ_SG_HEADER)) {
retval = -EFAULT;
goto free_old_hdr;
}
@@ -568,7 +562,12 @@
int err = 0, err2;
int len;
- if (count < SZ_SG_IO_HDR) {
+ if (in_compat_syscall()) {
+ if (count < sizeof(struct compat_sg_io_hdr)) {
+ err = -EINVAL;
+ goto err_out;
+ }
+ } else if (count < SZ_SG_IO_HDR) {
err = -EINVAL;
goto err_out;
}
@@ -589,10 +588,7 @@
}
if (hp->masked_status || hp->host_status || hp->driver_status)
hp->info |= SG_INFO_CHECK;
- if (copy_to_user(buf, hp, SZ_SG_IO_HDR)) {
- err = -EFAULT;
- goto err_out;
- }
+ err = put_sg_io_hdr(hp, buf);
err_out:
err2 = sg_finish_rem_req(srp);
sg_remove_request(sfp, srp);
@@ -627,11 +623,9 @@
scsi_block_when_processing_errors(sdp->device)))
return -ENXIO;
- if (!access_ok(buf, count))
- return -EFAULT; /* protects following copy_from_user()s + get_user()s */
if (count < SZ_SG_HEADER)
return -EIO;
- if (__copy_from_user(&old_hdr, buf, SZ_SG_HEADER))
+ if (copy_from_user(&old_hdr, buf, SZ_SG_HEADER))
return -EFAULT;
blocking = !(filp->f_flags & O_NONBLOCK);
if (old_hdr.reply_len < 0)
@@ -640,13 +634,15 @@
if (count < (SZ_SG_HEADER + 6))
return -EIO; /* The minimum scsi command length is 6 bytes. */
+ buf += SZ_SG_HEADER;
+ if (get_user(opcode, buf))
+ return -EFAULT;
+
if (!(srp = sg_add_request(sfp))) {
SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sdp,
"sg_write: queue full\n"));
return -EDOM;
}
- buf += SZ_SG_HEADER;
- __get_user(opcode, buf);
mutex_lock(&sfp->f_mutex);
if (sfp->next_cmd_len > 0) {
cmd_size = sfp->next_cmd_len;
@@ -689,7 +685,7 @@
hp->flags = input_size; /* structure abuse ... */
hp->pack_id = old_hdr.pack_id;
hp->usr_ptr = NULL;
- if (__copy_from_user(cmnd, buf, cmd_size)) {
+ if (copy_from_user(cmnd, buf, cmd_size)) {
sg_remove_request(sfp, srp);
return -EFAULT;
}
@@ -726,8 +722,6 @@
if (count < SZ_SG_IO_HDR)
return -EINVAL;
- if (!access_ok(buf, count))
- return -EFAULT; /* protects following copy_from_user()s + get_user()s */
sfp->cmd_q = 1; /* when sg_io_hdr seen, set command queuing on */
if (!(srp = sg_add_request(sfp))) {
@@ -737,7 +731,7 @@
}
srp->sg_io_owned = sg_io_owned;
hp = &srp->header;
- if (__copy_from_user(hp, buf, SZ_SG_IO_HDR)) {
+ if (get_sg_io_hdr(hp, buf)) {
sg_remove_request(sfp, srp);
return -EFAULT;
}
@@ -765,11 +759,7 @@
sg_remove_request(sfp, srp);
return -EMSGSIZE;
}
- if (!access_ok(hp->cmdp, hp->cmd_len)) {
- sg_remove_request(sfp, srp);
- return -EFAULT; /* protects following copy_from_user()s + get_user()s */
- }
- if (__copy_from_user(cmnd, hp->cmdp, hp->cmd_len)) {
+ if (copy_from_user(cmnd, hp->cmdp, hp->cmd_len)) {
sg_remove_request(sfp, srp);
return -EFAULT;
}
@@ -897,20 +887,42 @@
}
}
-static long
-sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
+#ifdef CONFIG_COMPAT
+struct compat_sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
+ char req_state;
+ char orphan;
+ char sg_io_owned;
+ char problem;
+ int pack_id;
+ compat_uptr_t usr_ptr;
+ unsigned int duration;
+ int unused;
+};
+
+static int put_compat_request_table(struct compat_sg_req_info __user *o,
+ struct sg_req_info *rinfo)
{
- void __user *p = (void __user *)arg;
+ int i;
+ for (i = 0; i < SG_MAX_QUEUE; i++) {
+ if (copy_to_user(o + i, rinfo + i, offsetof(sg_req_info_t, usr_ptr)) ||
+ put_user((uintptr_t)rinfo[i].usr_ptr, &o[i].usr_ptr) ||
+ put_user(rinfo[i].duration, &o[i].duration) ||
+ put_user(rinfo[i].unused, &o[i].unused))
+ return -EFAULT;
+ }
+ return 0;
+}
+#endif
+
+static long
+sg_ioctl_common(struct file *filp, Sg_device *sdp, Sg_fd *sfp,
+ unsigned int cmd_in, void __user *p)
+{
int __user *ip = p;
int result, val, read_only;
- Sg_device *sdp;
- Sg_fd *sfp;
Sg_request *srp;
unsigned long iflags;
- if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
- return -ENXIO;
-
SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
"sg_ioctl: cmd=0x%x\n", (int) cmd_in));
read_only = (O_RDWR != (filp->f_flags & O_ACCMODE));
@@ -921,8 +933,6 @@
return -ENODEV;
if (!scsi_block_when_processing_errors(sdp->device))
return -ENXIO;
- if (!access_ok(p, SZ_SG_IO_HDR))
- return -EFAULT;
result = sg_new_write(sfp, filp, p, SZ_SG_IO_HDR,
1, read_only, 1, &srp);
if (result < 0)
@@ -967,26 +977,21 @@
case SG_GET_LOW_DMA:
return put_user((int) sdp->device->host->unchecked_isa_dma, ip);
case SG_GET_SCSI_ID:
- if (!access_ok(p, sizeof (sg_scsi_id_t)))
- return -EFAULT;
- else {
- sg_scsi_id_t __user *sg_idp = p;
+ {
+ sg_scsi_id_t v;
if (atomic_read(&sdp->detaching))
return -ENODEV;
- __put_user((int) sdp->device->host->host_no,
- &sg_idp->host_no);
- __put_user((int) sdp->device->channel,
- &sg_idp->channel);
- __put_user((int) sdp->device->id, &sg_idp->scsi_id);
- __put_user((int) sdp->device->lun, &sg_idp->lun);
- __put_user((int) sdp->device->type, &sg_idp->scsi_type);
- __put_user((short) sdp->device->host->cmd_per_lun,
- &sg_idp->h_cmd_per_lun);
- __put_user((short) sdp->device->queue_depth,
- &sg_idp->d_queue_depth);
- __put_user(0, &sg_idp->unused[0]);
- __put_user(0, &sg_idp->unused[1]);
+ memset(&v, 0, sizeof(v));
+ v.host_no = sdp->device->host->host_no;
+ v.channel = sdp->device->channel;
+ v.scsi_id = sdp->device->id;
+ v.lun = sdp->device->lun;
+ v.scsi_type = sdp->device->type;
+ v.h_cmd_per_lun = sdp->device->host->cmd_per_lun;
+ v.d_queue_depth = sdp->device->queue_depth;
+ if (copy_to_user(p, &v, sizeof(sg_scsi_id_t)))
+ return -EFAULT;
return 0;
}
case SG_SET_FORCE_PACK_ID:
@@ -996,20 +1001,16 @@
sfp->force_packid = val ? 1 : 0;
return 0;
case SG_GET_PACK_ID:
- if (!access_ok(ip, sizeof (int)))
- return -EFAULT;
read_lock_irqsave(&sfp->rq_list_lock, iflags);
list_for_each_entry(srp, &sfp->rq_list, entry) {
if ((1 == srp->done) && (!srp->sg_io_owned)) {
read_unlock_irqrestore(&sfp->rq_list_lock,
iflags);
- __put_user(srp->header.pack_id, ip);
- return 0;
+ return put_user(srp->header.pack_id, ip);
}
}
read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
- __put_user(-1, ip);
- return 0;
+ return put_user(-1, ip);
case SG_GET_NUM_WAITING:
read_lock_irqsave(&sfp->rq_list_lock, iflags);
val = 0;
@@ -1077,9 +1078,7 @@
val = (sdp->device ? 1 : 0);
return put_user(val, ip);
case SG_GET_REQUEST_TABLE:
- if (!access_ok(p, SZ_SG_REQ_INFO * SG_MAX_QUEUE))
- return -EFAULT;
- else {
+ {
sg_req_info_t *rinfo;
rinfo = kcalloc(SG_MAX_QUEUE, SZ_SG_REQ_INFO,
@@ -1089,8 +1088,13 @@
read_lock_irqsave(&sfp->rq_list_lock, iflags);
sg_fill_request_table(sfp, rinfo);
read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
- result = __copy_to_user(p, rinfo,
- SZ_SG_REQ_INFO * SG_MAX_QUEUE);
+ #ifdef CONFIG_COMPAT
+ if (in_compat_syscall())
+ result = put_compat_request_table(p, rinfo);
+ else
+ #endif
+ result = copy_to_user(p, rinfo,
+ SZ_SG_REQ_INFO * SG_MAX_QUEUE);
result = result ? -EFAULT : 0;
kfree(rinfo);
return result;
@@ -1141,29 +1145,44 @@
cmd_in, filp->f_flags & O_NDELAY);
if (result)
return result;
+
+ return -ENOIOCTLCMD;
+}
+
+static long
+sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
+{
+ void __user *p = (void __user *)arg;
+ Sg_device *sdp;
+ Sg_fd *sfp;
+ int ret;
+
+ if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
+ return -ENXIO;
+
+ ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p);
+ if (ret != -ENOIOCTLCMD)
+ return ret;
+
return scsi_ioctl(sdp->device, cmd_in, p);
}
#ifdef CONFIG_COMPAT
static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
{
+ void __user *p = compat_ptr(arg);
Sg_device *sdp;
Sg_fd *sfp;
- struct scsi_device *sdev;
+ int ret;
if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
return -ENXIO;
- sdev = sdp->device;
- if (sdev->host->hostt->compat_ioctl) {
- int ret;
-
- ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
-
+ ret = sg_ioctl_common(filp, sdp, sfp, cmd_in, p);
+ if (ret != -ENOIOCTLCMD)
return ret;
- }
-
- return -ENOIOCTLCMD;
+
+ return scsi_compat_ioctl(sdp->device, cmd_in, p);
}
#endif
@@ -1988,12 +2007,12 @@
num = 1 << (PAGE_SHIFT + schp->page_order);
for (k = 0; k < schp->k_use_sg && schp->pages[k]; k++) {
if (num > num_read_xfer) {
- if (__copy_to_user(outp, page_address(schp->pages[k]),
+ if (copy_to_user(outp, page_address(schp->pages[k]),
num_read_xfer))
return -EFAULT;
break;
} else {
- if (__copy_to_user(outp, page_address(schp->pages[k]),
+ if (copy_to_user(outp, page_address(schp->pages[k]),
num))
return -EFAULT;
num_read_xfer -= num;
@@ -2300,25 +2319,23 @@
static int sg_proc_single_open_adio(struct inode *inode, struct file *file);
static ssize_t sg_proc_write_adio(struct file *filp, const char __user *buffer,
size_t count, loff_t *off);
-static const struct file_operations adio_fops = {
- .owner = THIS_MODULE,
- .open = sg_proc_single_open_adio,
- .read = seq_read,
- .llseek = seq_lseek,
- .write = sg_proc_write_adio,
- .release = single_release,
+static const struct proc_ops adio_proc_ops = {
+ .proc_open = sg_proc_single_open_adio,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_write = sg_proc_write_adio,
+ .proc_release = single_release,
};
static int sg_proc_single_open_dressz(struct inode *inode, struct file *file);
static ssize_t sg_proc_write_dressz(struct file *filp,
const char __user *buffer, size_t count, loff_t *off);
-static const struct file_operations dressz_fops = {
- .owner = THIS_MODULE,
- .open = sg_proc_single_open_dressz,
- .read = seq_read,
- .llseek = seq_lseek,
- .write = sg_proc_write_dressz,
- .release = single_release,
+static const struct proc_ops dressz_proc_ops = {
+ .proc_open = sg_proc_single_open_dressz,
+ .proc_read = seq_read,
+ .proc_lseek = seq_lseek,
+ .proc_write = sg_proc_write_dressz,
+ .proc_release = single_release,
};
static int sg_proc_seq_show_version(struct seq_file *s, void *v);
@@ -2359,9 +2376,9 @@
if (!p)
return 1;
- proc_create("allow_dio", S_IRUGO | S_IWUSR, p, &adio_fops);
+ proc_create("allow_dio", S_IRUGO | S_IWUSR, p, &adio_proc_ops);
proc_create_seq("debug", S_IRUGO, p, &debug_seq_ops);
- proc_create("def_reserved_size", S_IRUGO | S_IWUSR, p, &dressz_fops);
+ proc_create("def_reserved_size", S_IRUGO | S_IWUSR, p, &dressz_proc_ops);
proc_create_single("device_hdr", S_IRUGO, p, sg_proc_seq_show_devhdr);
proc_create_seq("devices", S_IRUGO, p, &dev_seq_ops);
proc_create_seq("device_strs", S_IRUGO, p, &devstrs_seq_ops);
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
index 713bce9..cf1030c 100644
--- a/drivers/scsi/sgiwd93.c
+++ b/drivers/scsi/sgiwd93.c
@@ -95,7 +95,7 @@
*/
hcp->desc.pbuf = 0;
hcp->desc.cntinfo = HPCDMA_EOX;
- dma_cache_sync(hd->dev, hd->cpu,
+ dma_sync_single_for_device(hd->dev, hd->dma,
(unsigned long)(hcp + 1) - (unsigned long)hd->cpu,
DMA_TO_DEVICE);
}
@@ -187,7 +187,7 @@
hcp++;
dma += sizeof(struct hpc_chunk);
start += sizeof(struct hpc_chunk);
- };
+ }
hcp--;
hcp->desc.pnext = hdata->dma;
}
@@ -234,8 +234,8 @@
hdata = host_to_hostdata(host);
hdata->dev = &pdev->dev;
- hdata->cpu = dma_alloc_attrs(&pdev->dev, HPC_DMA_SIZE, &hdata->dma,
- GFP_KERNEL, DMA_ATTR_NON_CONSISTENT);
+ hdata->cpu = dma_alloc_noncoherent(&pdev->dev, HPC_DMA_SIZE,
+ &hdata->dma, DMA_TO_DEVICE, GFP_KERNEL);
if (!hdata->cpu) {
printk(KERN_WARNING "sgiwd93: Could not allocate memory for "
"host %d buffer.\n", unit);
@@ -274,8 +274,8 @@
out_irq:
free_irq(irq, host);
out_free:
- dma_free_attrs(&pdev->dev, HPC_DMA_SIZE, hdata->cpu, hdata->dma,
- DMA_ATTR_NON_CONSISTENT);
+ dma_free_noncoherent(&pdev->dev, HPC_DMA_SIZE, hdata->cpu, hdata->dma,
+ DMA_TO_DEVICE);
out_put:
scsi_host_put(host);
out:
@@ -291,8 +291,8 @@
scsi_remove_host(host);
free_irq(pd->irq, host);
- dma_free_attrs(&pdev->dev, HPC_DMA_SIZE, hdata->cpu, hdata->dma,
- DMA_ATTR_NON_CONSISTENT);
+ dma_free_noncoherent(&pdev->dev, HPC_DMA_SIZE, hdata->cpu, hdata->dma,
+ DMA_TO_DEVICE);
scsi_host_put(host);
return 0;
}
diff --git a/drivers/scsi/smartpqi/Kconfig b/drivers/scsi/smartpqi/Kconfig
index bc65068..cb9e4e9 100644
--- a/drivers/scsi/smartpqi/Kconfig
+++ b/drivers/scsi/smartpqi/Kconfig
@@ -1,11 +1,11 @@
#
# Kernel configuration file for the SMARTPQI
#
-# Copyright (c) 2019 Microchip Technology Inc. and its subsidiaries
+# Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
# Copyright (c) 2017-2018 Microsemi Corporation
# Copyright (c) 2016 Microsemi Corporation
# Copyright (c) 2016 PMC-Sierra, Inc.
-# (mailto:esc.storagedev@microsemi.com)
+# (mailto:storagedev@microchip.com)
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -42,7 +42,7 @@
depends on PCI && SCSI && !S390
select SCSI_SAS_ATTRS
select RAID_ATTRS
- ---help---
+ help
This driver supports Microsemi PQI controllers.
<http://www.microsemi.com>
@@ -53,4 +53,4 @@
Note: the aacraid driver will not manage a smartpqi
controller. You need to enable smartpqi for smartpqi
controllers. For more information, please see
- Documentation/scsi/smartpqi.txt
+ Documentation/scsi/smartpqi.rst
diff --git a/drivers/scsi/smartpqi/smartpqi.h b/drivers/scsi/smartpqi/smartpqi.h
index dd2175e..3e54590 100644
--- a/drivers/scsi/smartpqi/smartpqi.h
+++ b/drivers/scsi/smartpqi/smartpqi.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* driver for Microsemi PQI-based storage controllers
- * Copyright (c) 2019 Microchip Technology Inc. and its subsidiaries
+ * Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
@@ -276,7 +276,9 @@
u8 reserved4 : 2;
u8 additional_cdb_bytes_usage : 3;
u8 reserved5 : 3;
- u8 cdb[32];
+ u8 cdb[16];
+ u8 reserved6[12];
+ __le32 timeout;
struct pqi_sg_descriptor
sg_descriptors[PQI_MAX_EMBEDDED_SG_DESCRIPTORS];
};
@@ -385,7 +387,8 @@
struct pqi_iu_header header;
__le16 request_id;
__le16 nexus_id;
- u8 reserved[4];
+ u8 reserved[2];
+ __le16 timeout;
u8 lun_number[8];
__le16 protocol_specific;
__le16 outbound_queue_id_to_manage;
@@ -445,7 +448,7 @@
struct pqi_ofa_memory {
__le64 signature; /* "OFA_QRM" */
- __le16 version; /* version of this struct(1 = 1st version) */
+ __le16 version; /* version of this struct (1 = 1st version) */
u8 reserved[62];
__le32 bytes_allocated; /* total allocated memory in bytes */
__le16 num_memory_descriptors;
@@ -761,6 +764,8 @@
#define PQI_FIRMWARE_FEATURE_OFA 0
#define PQI_FIRMWARE_FEATURE_SMP 1
#define PQI_FIRMWARE_FEATURE_SOFT_RESET_HANDSHAKE 11
+#define PQI_FIRMWARE_FEATURE_RAID_IU_TIMEOUT 13
+#define PQI_FIRMWARE_FEATURE_TMF_IU_TIMEOUT 14
struct pqi_config_table_debug {
struct pqi_config_table_section_header header;
@@ -826,10 +831,17 @@
struct report_lun_header {
__be32 list_length;
- u8 extended_response;
+ u8 flags;
u8 reserved[3];
};
+/* for flags field of struct report_lun_header */
+#define CISS_REPORT_LOG_FLAG_UNIQUE_LUN_ID (1 << 0)
+#define CISS_REPORT_LOG_FLAG_QUEUE_DEPTH (1 << 5)
+#define CISS_REPORT_LOG_FLAG_DRIVE_TYPE_MIX (1 << 6)
+
+#define CISS_REPORT_PHYS_FLAG_OTHER (1 << 1)
+
struct report_log_lun_extended_entry {
u8 lunid[8];
u8 volume_id[16];
@@ -851,7 +863,7 @@
};
/* for device_flags field of struct report_phys_lun_extended_entry */
-#define REPORT_PHYS_LUN_DEV_FLAG_AIO_ENABLED 0x8
+#define CISS_REPORT_PHYS_DEV_FLAG_AIO_ENABLED 0x8
struct report_phys_lun_extended {
struct report_lun_header header;
@@ -864,7 +876,7 @@
u8 reserved[2];
};
-/* constants for flags field of RAID map */
+/* for flags field of RAID map */
#define RAID_MAP_ENCRYPTION_ENABLED 0x1
struct raid_map {
@@ -915,6 +927,7 @@
u8 new_device : 1;
u8 keep_device : 1;
u8 volume_offline : 1;
+ u8 rescan : 1;
bool aio_enabled; /* only valid for physical disks */
bool in_reset;
bool in_remove;
@@ -950,16 +963,13 @@
struct list_head delete_list_entry;
atomic_t scsi_cmds_outstanding;
+ atomic_t raid_bypass_cnt;
};
/* VPD inquiry pages */
-#define SCSI_VPD_SUPPORTED_PAGES 0x0 /* standard page */
-#define SCSI_VPD_DEVICE_ID 0x83 /* standard page */
#define CISS_VPD_LV_DEVICE_GEOMETRY 0xc1 /* vendor-specific page */
#define CISS_VPD_LV_BYPASS_STATUS 0xc2 /* vendor-specific page */
#define CISS_VPD_LV_STATUS 0xc3 /* vendor-specific page */
-#define SCSI_VPD_HEADER_SZ 4
-#define SCSI_VPD_DEVICE_ID_IDX 8 /* Index of page id in page */
#define VPD_PAGE (1 << 8)
@@ -1137,6 +1147,8 @@
u8 pqi_mode_enabled : 1;
u8 pqi_reset_quiesce_supported : 1;
u8 soft_reset_handshake_supported : 1;
+ u8 raid_iu_timeout_supported: 1;
+ u8 tmf_iu_timeout_supported: 1;
struct list_head scsi_device_list;
spinlock_t scsi_device_list_lock;
@@ -1170,9 +1182,9 @@
spinlock_t raid_bypass_retry_list_lock;
struct work_struct raid_bypass_retry_work;
- struct pqi_ofa_memory *pqi_ofa_mem_virt_addr;
- dma_addr_t pqi_ofa_mem_dma_handle;
- void **pqi_ofa_chunk_virt_addr;
+ struct pqi_ofa_memory *pqi_ofa_mem_virt_addr;
+ dma_addr_t pqi_ofa_mem_dma_handle;
+ void **pqi_ofa_chunk_virt_addr;
atomic_t sync_cmds_outstanding;
};
@@ -1192,10 +1204,6 @@
#define CISS_REPORT_PHYS 0xc3 /* Report Physical LUNs */
#define CISS_GET_RAID_MAP 0xc8
-/* constants for CISS_REPORT_LOG/CISS_REPORT_PHYS commands */
-#define CISS_REPORT_LOG_EXTENDED 0x1
-#define CISS_REPORT_PHYS_EXTENDED 0x2
-
/* BMIC commands */
#define BMIC_IDENTIFY_CONTROLLER 0x11
#define BMIC_IDENTIFY_PHYSICAL_DEVICE 0x15
@@ -1209,7 +1217,7 @@
#define BMIC_SET_DIAG_OPTIONS 0xf4
#define BMIC_SENSE_DIAG_OPTIONS 0xf5
-#define CSMI_CC_SAS_SMP_PASSTHRU 0X17
+#define CSMI_CC_SAS_SMP_PASSTHRU 0x17
#define SA_FLUSH_CACHE 0x1
@@ -1245,10 +1253,13 @@
u8 ctrl_serial_number[16];
};
-#define SA_EXPANDER_SMP_DEVICE 0x05
-#define SA_CONTROLLER_DEVICE 0x07
-/*SCSI Invalid Device Type for SAS devices*/
-#define PQI_SAS_SCSI_INVALID_DEVTYPE 0xff
+/* constants for device_type field */
+#define SA_DEVICE_TYPE_SATA 0x1
+#define SA_DEVICE_TYPE_SAS 0x2
+#define SA_DEVICE_TYPE_EXPANDER_SMP 0x5
+#define SA_DEVICE_TYPE_SES 0x6
+#define SA_DEVICE_TYPE_CONTROLLER 0x7
+#define SA_DEVICE_TYPE_NVME 0x9
struct bmic_identify_physical_device {
u8 scsi_bus; /* SCSI Bus number on controller */
@@ -1274,7 +1285,7 @@
__le32 rpm; /* drive rotational speed in RPM */
u8 device_type; /* type of drive */
u8 sata_version; /* only valid when device_type = */
- /* BMIC_DEVICE_TYPE_SATA */
+ /* SA_DEVICE_TYPE_SATA */
__le64 big_total_block_count;
__le64 ris_starting_lba;
__le32 ris_size;
@@ -1397,18 +1408,6 @@
#pragma pack()
-static inline struct pqi_ctrl_info *shost_to_hba(struct Scsi_Host *shost)
-{
- void *hostdata = shost_priv(shost);
-
- return *((struct pqi_ctrl_info **)hostdata);
-}
-
-static inline bool pqi_ctrl_offline(struct pqi_ctrl_info *ctrl_info)
-{
- return !ctrl_info->controller_online;
-}
-
static inline void pqi_ctrl_busy(struct pqi_ctrl_info *ctrl_info)
{
atomic_inc(&ctrl_info->num_busy_threads);
@@ -1419,14 +1418,11 @@
atomic_dec(&ctrl_info->num_busy_threads);
}
-static inline bool pqi_ctrl_blocked(struct pqi_ctrl_info *ctrl_info)
+static inline struct pqi_ctrl_info *shost_to_hba(struct Scsi_Host *shost)
{
- return ctrl_info->block_requests;
-}
+ void *hostdata = shost_priv(shost);
-static inline bool pqi_device_reset_blocked(struct pqi_ctrl_info *ctrl_info)
-{
- return ctrl_info->block_device_reset;
+ return *((struct pqi_ctrl_info **)hostdata);
}
void pqi_sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
index 80ff000..de73ade 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* driver for Microsemi PQI-based storage controllers
- * Copyright (c) 2019 Microchip Technology Inc. and its subsidiaries
+ * Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
@@ -33,11 +33,11 @@
#define BUILD_TIMESTAMP
#endif
-#define DRIVER_VERSION "1.2.8-026"
+#define DRIVER_VERSION "1.2.16-010"
#define DRIVER_MAJOR 1
#define DRIVER_MINOR 2
-#define DRIVER_RELEASE 8
-#define DRIVER_REVISION 26
+#define DRIVER_RELEASE 16
+#define DRIVER_REVISION 10
#define DRIVER_NAME "Microsemi PQI Driver (v" \
DRIVER_VERSION BUILD_TIMESTAMP ")"
@@ -211,6 +211,11 @@
return scsi3addr[2] != 0;
}
+static inline bool pqi_ctrl_offline(struct pqi_ctrl_info *ctrl_info)
+{
+ return !ctrl_info->controller_online;
+}
+
static inline void pqi_check_ctrl_health(struct pqi_ctrl_info *ctrl_info)
{
if (ctrl_info->controller_online)
@@ -235,6 +240,21 @@
sis_write_driver_scratch(ctrl_info, mode);
}
+static inline void pqi_ctrl_block_device_reset(struct pqi_ctrl_info *ctrl_info)
+{
+ ctrl_info->block_device_reset = true;
+}
+
+static inline bool pqi_device_reset_blocked(struct pqi_ctrl_info *ctrl_info)
+{
+ return ctrl_info->block_device_reset;
+}
+
+static inline bool pqi_ctrl_blocked(struct pqi_ctrl_info *ctrl_info)
+{
+ return ctrl_info->block_requests;
+}
+
static inline void pqi_ctrl_block_requests(struct pqi_ctrl_info *ctrl_info)
{
ctrl_info->block_requests = true;
@@ -249,11 +269,6 @@
scsi_unblock_requests(ctrl_info->scsi_host);
}
-static inline void pqi_ctrl_block_device_reset(struct pqi_ctrl_info *ctrl_info)
-{
- ctrl_info->block_device_reset = true;
-}
-
static unsigned long pqi_wait_if_ctrl_blocked(struct pqi_ctrl_info *ctrl_info,
unsigned long timeout_msecs)
{
@@ -397,7 +412,7 @@
}
static inline void pqi_clear_soft_reset_status(struct pqi_ctrl_info *ctrl_info,
- u8 clear)
+ u8 clear)
{
u8 status;
@@ -482,9 +497,9 @@
request->data_direction = SOP_READ_FLAG;
cdb[0] = cmd;
if (cmd == CISS_REPORT_PHYS)
- cdb[1] = CISS_REPORT_PHYS_EXTENDED;
+ cdb[1] = CISS_REPORT_PHYS_FLAG_OTHER;
else
- cdb[1] = CISS_REPORT_LOG_EXTENDED;
+ cdb[1] = CISS_REPORT_LOG_FLAG_UNIQUE_LUN_ID;
put_unaligned_be32(cdb_length, &cdb[6]);
break;
case CISS_GET_RAID_MAP:
@@ -501,7 +516,7 @@
break;
case BMIC_SENSE_DIAG_OPTIONS:
cdb_length = 0;
- /* fall through */
+ fallthrough;
case BMIC_IDENTIFY_CONTROLLER:
case BMIC_IDENTIFY_PHYSICAL_DEVICE:
case BMIC_SENSE_SUBSYSTEM_INFORMATION:
@@ -512,7 +527,7 @@
break;
case BMIC_SET_DIAG_OPTIONS:
cdb_length = 0;
- /* fall through */
+ fallthrough;
case BMIC_WRITE_HOST_WELLNESS:
request->data_direction = SOP_WRITE_FLAG;
cdb[0] = BMIC_WRITE;
@@ -586,13 +601,12 @@
}
static int pqi_send_scsi_raid_request(struct pqi_ctrl_info *ctrl_info, u8 cmd,
- u8 *scsi3addr, void *buffer, size_t buffer_length, u16 vpd_page,
- struct pqi_raid_error_info *error_info,
- unsigned long timeout_msecs)
+ u8 *scsi3addr, void *buffer, size_t buffer_length, u16 vpd_page,
+ struct pqi_raid_error_info *error_info, unsigned long timeout_msecs)
{
int rc;
- enum dma_data_direction dir;
struct pqi_raid_path_request request;
+ enum dma_data_direction dir;
rc = pqi_build_raid_path_request(ctrl_info, &request,
cmd, scsi3addr, buffer,
@@ -600,44 +614,44 @@
if (rc)
return rc;
- rc = pqi_submit_raid_request_synchronous(ctrl_info, &request.header,
- 0, error_info, timeout_msecs);
+ rc = pqi_submit_raid_request_synchronous(ctrl_info, &request.header, 0,
+ error_info, timeout_msecs);
pqi_pci_unmap(ctrl_info->pci_dev, request.sg_descriptors, 1, dir);
+
return rc;
}
-/* Helper functions for pqi_send_scsi_raid_request */
+/* helper functions for pqi_send_scsi_raid_request */
static inline int pqi_send_ctrl_raid_request(struct pqi_ctrl_info *ctrl_info,
- u8 cmd, void *buffer, size_t buffer_length)
+ u8 cmd, void *buffer, size_t buffer_length)
{
return pqi_send_scsi_raid_request(ctrl_info, cmd, RAID_CTLR_LUNID,
- buffer, buffer_length, 0, NULL, NO_TIMEOUT);
+ buffer, buffer_length, 0, NULL, NO_TIMEOUT);
}
static inline int pqi_send_ctrl_raid_with_error(struct pqi_ctrl_info *ctrl_info,
- u8 cmd, void *buffer, size_t buffer_length,
- struct pqi_raid_error_info *error_info)
+ u8 cmd, void *buffer, size_t buffer_length,
+ struct pqi_raid_error_info *error_info)
{
return pqi_send_scsi_raid_request(ctrl_info, cmd, RAID_CTLR_LUNID,
- buffer, buffer_length, 0, error_info, NO_TIMEOUT);
+ buffer, buffer_length, 0, error_info, NO_TIMEOUT);
}
-
static inline int pqi_identify_controller(struct pqi_ctrl_info *ctrl_info,
- struct bmic_identify_controller *buffer)
+ struct bmic_identify_controller *buffer)
{
return pqi_send_ctrl_raid_request(ctrl_info, BMIC_IDENTIFY_CONTROLLER,
- buffer, sizeof(*buffer));
+ buffer, sizeof(*buffer));
}
static inline int pqi_sense_subsystem_info(struct pqi_ctrl_info *ctrl_info,
- struct bmic_sense_subsystem_info *sense_info)
+ struct bmic_sense_subsystem_info *sense_info)
{
return pqi_send_ctrl_raid_request(ctrl_info,
- BMIC_SENSE_SUBSYSTEM_INFORMATION,
- sense_info, sizeof(*sense_info));
+ BMIC_SENSE_SUBSYSTEM_INFORMATION, sense_info,
+ sizeof(*sense_info));
}
static inline int pqi_scsi_inquiry(struct pqi_ctrl_info *ctrl_info,
@@ -649,8 +663,7 @@
static int pqi_identify_physical_device(struct pqi_ctrl_info *ctrl_info,
struct pqi_scsi_dev *device,
- struct bmic_identify_physical_device *buffer,
- size_t buffer_length)
+ struct bmic_identify_physical_device *buffer, size_t buffer_length)
{
int rc;
enum dma_data_direction dir;
@@ -671,6 +684,7 @@
0, NULL, NO_TIMEOUT);
pqi_pci_unmap(ctrl_info->pci_dev, request.sg_descriptors, 1, dir);
+
return rc;
}
@@ -709,7 +723,7 @@
buffer, buffer_length, error_info);
}
-#define PQI_FETCH_PTRAID_DATA (1UL<<31)
+#define PQI_FETCH_PTRAID_DATA (1 << 31)
static int pqi_set_diag_rescan(struct pqi_ctrl_info *ctrl_info)
{
@@ -721,14 +735,15 @@
return -ENOMEM;
rc = pqi_send_ctrl_raid_request(ctrl_info, BMIC_SENSE_DIAG_OPTIONS,
- diag, sizeof(*diag));
+ diag, sizeof(*diag));
if (rc)
goto out;
diag->options |= cpu_to_le32(PQI_FETCH_PTRAID_DATA);
- rc = pqi_send_ctrl_raid_request(ctrl_info, BMIC_SET_DIAG_OPTIONS,
- diag, sizeof(*diag));
+ rc = pqi_send_ctrl_raid_request(ctrl_info, BMIC_SET_DIAG_OPTIONS, diag,
+ sizeof(*diag));
+
out:
kfree(diag);
@@ -739,7 +754,7 @@
void *buffer, size_t buffer_length)
{
return pqi_send_ctrl_raid_request(ctrl_info, BMIC_WRITE_HOST_WELLNESS,
- buffer, buffer_length);
+ buffer, buffer_length);
}
#pragma pack(1)
@@ -892,7 +907,7 @@
void *buffer, size_t buffer_length)
{
return pqi_send_ctrl_raid_request(ctrl_info, cmd, buffer,
- buffer_length);
+ buffer_length);
}
static int pqi_report_phys_logical_luns(struct pqi_ctrl_info *ctrl_info, u8 cmd,
@@ -1227,9 +1242,9 @@
if (rc)
goto out;
-#define RAID_BYPASS_STATUS 4
-#define RAID_BYPASS_CONFIGURED 0x1
-#define RAID_BYPASS_ENABLED 0x2
+#define RAID_BYPASS_STATUS 4
+#define RAID_BYPASS_CONFIGURED 0x1
+#define RAID_BYPASS_ENABLED 0x2
bypass_status = buffer[RAID_BYPASS_STATUS];
device->raid_bypass_configured =
@@ -1285,33 +1300,59 @@
device->volume_offline = volume_offline;
}
-#define PQI_INQUIRY_PAGE0_RETRIES 3
+static int pqi_get_physical_device_info(struct pqi_ctrl_info *ctrl_info,
+ struct pqi_scsi_dev *device,
+ struct bmic_identify_physical_device *id_phys)
+{
+ int rc;
-static int pqi_get_device_info(struct pqi_ctrl_info *ctrl_info,
+ memset(id_phys, 0, sizeof(*id_phys));
+
+ rc = pqi_identify_physical_device(ctrl_info, device,
+ id_phys, sizeof(*id_phys));
+ if (rc) {
+ device->queue_depth = PQI_PHYSICAL_DISK_DEFAULT_MAX_QUEUE_DEPTH;
+ return rc;
+ }
+
+ scsi_sanitize_inquiry_string(&id_phys->model[0], 8);
+ scsi_sanitize_inquiry_string(&id_phys->model[8], 16);
+
+ memcpy(device->vendor, &id_phys->model[0], sizeof(device->vendor));
+ memcpy(device->model, &id_phys->model[8], sizeof(device->model));
+
+ device->box_index = id_phys->box_index;
+ device->phys_box_on_bus = id_phys->phys_box_on_bus;
+ device->phy_connected_dev_type = id_phys->phy_connected_dev_type[0];
+ device->queue_depth =
+ get_unaligned_le16(&id_phys->current_queue_depth_limit);
+ device->active_path_index = id_phys->active_path_number;
+ device->path_map = id_phys->redundant_path_present_map;
+ memcpy(&device->box,
+ &id_phys->alternate_paths_phys_box_on_port,
+ sizeof(device->box));
+ memcpy(&device->phys_connector,
+ &id_phys->alternate_paths_phys_connector,
+ sizeof(device->phys_connector));
+ device->bay = id_phys->phys_bay_in_box;
+
+ return 0;
+}
+
+static int pqi_get_logical_device_info(struct pqi_ctrl_info *ctrl_info,
struct pqi_scsi_dev *device)
{
int rc;
u8 *buffer;
- unsigned int retries;
-
- if (device->is_expander_smp_device)
- return 0;
buffer = kmalloc(64, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
/* Send an inquiry to the device to see what it is. */
- for (retries = 0;;) {
- rc = pqi_scsi_inquiry(ctrl_info, device->scsi3addr, 0,
- buffer, 64);
- if (rc == 0)
- break;
- if (pqi_is_logical_device(device) ||
- rc != PQI_CMD_STATUS_ABORTED ||
- ++retries > PQI_INQUIRY_PAGE0_RETRIES)
- goto out;
- }
+ rc = pqi_scsi_inquiry(ctrl_info, device->scsi3addr, 0, buffer, 64);
+ if (rc)
+ goto out;
scsi_sanitize_inquiry_string(&buffer[8], 8);
scsi_sanitize_inquiry_string(&buffer[16], 16);
@@ -1320,7 +1361,7 @@
memcpy(device->vendor, &buffer[8], sizeof(device->vendor));
memcpy(device->model, &buffer[16], sizeof(device->model));
- if (pqi_is_logical_device(device) && device->devtype == TYPE_DISK) {
+ if (device->devtype == TYPE_DISK) {
if (device->is_external_raid_device) {
device->raid_level = SA_RAID_UNKNOWN;
device->volume_status = CISS_LV_OK;
@@ -1338,35 +1379,21 @@
return rc;
}
-static void pqi_get_physical_disk_info(struct pqi_ctrl_info *ctrl_info,
+static int pqi_get_device_info(struct pqi_ctrl_info *ctrl_info,
struct pqi_scsi_dev *device,
struct bmic_identify_physical_device *id_phys)
{
int rc;
- memset(id_phys, 0, sizeof(*id_phys));
+ if (device->is_expander_smp_device)
+ return 0;
- rc = pqi_identify_physical_device(ctrl_info, device,
- id_phys, sizeof(*id_phys));
- if (rc) {
- device->queue_depth = PQI_PHYSICAL_DISK_DEFAULT_MAX_QUEUE_DEPTH;
- return;
- }
- device->box_index = id_phys->box_index;
- device->phys_box_on_bus = id_phys->phys_box_on_bus;
- device->phy_connected_dev_type = id_phys->phy_connected_dev_type[0];
- device->queue_depth =
- get_unaligned_le16(&id_phys->current_queue_depth_limit);
- device->device_type = id_phys->device_type;
- device->active_path_index = id_phys->active_path_number;
- device->path_map = id_phys->redundant_path_present_map;
- memcpy(&device->box,
- &id_phys->alternate_paths_phys_box_on_port,
- sizeof(device->box));
- memcpy(&device->phys_connector,
- &id_phys->alternate_paths_phys_connector,
- sizeof(device->phys_connector));
- device->bay = id_phys->phys_bay_in_box;
+ if (pqi_is_logical_device(device))
+ rc = pqi_get_logical_device_info(ctrl_info, device);
+ else
+ rc = pqi_get_physical_device_info(ctrl_info, device, id_phys);
+
+ return rc;
}
static void pqi_show_volume_status(struct pqi_ctrl_info *ctrl_info,
@@ -1505,11 +1532,10 @@
pqi_device_remove_start(device);
- rc = pqi_device_wait_for_pending_io(ctrl_info, device,
- PQI_PENDING_IO_TIMEOUT_SECS);
+ rc = pqi_device_wait_for_pending_io(ctrl_info, device, PQI_PENDING_IO_TIMEOUT_SECS);
if (rc)
dev_err(&ctrl_info->pci_dev->dev,
- "scsi %d:%d:%d:%d removing device with %d outstanding commands\n",
+ "scsi %d:%d:%d:%d removing device with %d outstanding command(s)\n",
ctrl_info->scsi_host->host_no, device->bus,
device->target, device->lun,
atomic_read(&device->scsi_cmds_outstanding));
@@ -1527,10 +1553,8 @@
{
struct pqi_scsi_dev *device;
- list_for_each_entry(device, &ctrl_info->scsi_device_list,
- scsi_device_list_entry)
- if (device->bus == bus && device->target == target &&
- device->lun == lun)
+ list_for_each_entry(device, &ctrl_info->scsi_device_list, scsi_device_list_entry)
+ if (device->bus == bus && device->target == target && device->lun == lun)
return device;
return NULL;
@@ -1556,15 +1580,12 @@
};
static enum pqi_find_result pqi_scsi_find_entry(struct pqi_ctrl_info *ctrl_info,
- struct pqi_scsi_dev *device_to_find,
- struct pqi_scsi_dev **matching_device)
+ struct pqi_scsi_dev *device_to_find, struct pqi_scsi_dev **matching_device)
{
struct pqi_scsi_dev *device;
- list_for_each_entry(device, &ctrl_info->scsi_device_list,
- scsi_device_list_entry) {
- if (pqi_scsi3addr_equal(device_to_find->scsi3addr,
- device->scsi3addr)) {
+ list_for_each_entry(device, &ctrl_info->scsi_device_list, scsi_device_list_entry) {
+ if (pqi_scsi3addr_equal(device_to_find->scsi3addr, device->scsi3addr)) {
*matching_device = device;
if (pqi_device_equal(device_to_find, device)) {
if (device_to_find->volume_offline)
@@ -1598,28 +1619,28 @@
"%d:%d:", ctrl_info->scsi_host->host_no, device->bus);
if (device->target_lun_valid)
- count += snprintf(buffer + count,
+ count += scnprintf(buffer + count,
PQI_DEV_INFO_BUFFER_LENGTH - count,
"%d:%d",
device->target,
device->lun);
else
- count += snprintf(buffer + count,
+ count += scnprintf(buffer + count,
PQI_DEV_INFO_BUFFER_LENGTH - count,
"-:-");
if (pqi_is_logical_device(device))
- count += snprintf(buffer + count,
+ count += scnprintf(buffer + count,
PQI_DEV_INFO_BUFFER_LENGTH - count,
" %08x%08x",
*((u32 *)&device->scsi3addr),
*((u32 *)&device->scsi3addr[4]));
else
- count += snprintf(buffer + count,
+ count += scnprintf(buffer + count,
PQI_DEV_INFO_BUFFER_LENGTH - count,
" %016llx", device->sas_address);
- count += snprintf(buffer + count, PQI_DEV_INFO_BUFFER_LENGTH - count,
+ count += scnprintf(buffer + count, PQI_DEV_INFO_BUFFER_LENGTH - count,
" %s %.8s %.16s ",
pqi_device_type(device),
device->vendor,
@@ -1627,19 +1648,19 @@
if (pqi_is_logical_device(device)) {
if (device->devtype == TYPE_DISK)
- count += snprintf(buffer + count,
+ count += scnprintf(buffer + count,
PQI_DEV_INFO_BUFFER_LENGTH - count,
"SSDSmartPathCap%c En%c %-12s",
device->raid_bypass_configured ? '+' : '-',
device->raid_bypass_enabled ? '+' : '-',
pqi_raid_level_to_string(device->raid_level));
} else {
- count += snprintf(buffer + count,
+ count += scnprintf(buffer + count,
PQI_DEV_INFO_BUFFER_LENGTH - count,
"AIO%c", device->aio_enabled ? '+' : '-');
if (device->devtype == TYPE_DISK ||
device->devtype == TYPE_ZBC)
- count += snprintf(buffer + count,
+ count += scnprintf(buffer + count,
PQI_DEV_INFO_BUFFER_LENGTH - count,
" qd=%-6d", device->queue_depth);
}
@@ -1661,6 +1682,11 @@
existing_device->target_lun_valid = true;
}
+ if ((existing_device->volume_status == CISS_LV_QUEUED_FOR_EXPANSION ||
+ existing_device->volume_status == CISS_LV_UNDERGOING_EXPANSION) &&
+ new_device->volume_status == CISS_LV_OK)
+ existing_device->rescan = true;
+
/* By definition, the scsi3addr and wwid fields are already the same. */
existing_device->is_physical_device = new_device->is_physical_device;
@@ -1759,15 +1785,14 @@
spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);
/* Assume that all devices in the existing list have gone away. */
- list_for_each_entry(device, &ctrl_info->scsi_device_list,
- scsi_device_list_entry)
+ list_for_each_entry(device, &ctrl_info->scsi_device_list, scsi_device_list_entry)
device->device_gone = true;
for (i = 0; i < num_new_devices; i++) {
device = new_device_list[i];
find_result = pqi_scsi_find_entry(ctrl_info, device,
- &matching_device);
+ &matching_device);
switch (find_result) {
case DEVICE_SAME:
@@ -1800,7 +1825,7 @@
list_for_each_entry_safe(device, next, &ctrl_info->scsi_device_list,
scsi_device_list_entry) {
if (device->device_gone) {
- list_del(&device->scsi_device_list_entry);
+ list_del_init(&device->scsi_device_list_entry);
list_add_tail(&device->delete_list_entry, &delete_list);
}
}
@@ -1825,18 +1850,19 @@
pqi_ctrl_ofa_done(ctrl_info);
/* Remove all devices that have gone away. */
- list_for_each_entry_safe(device, next, &delete_list,
- delete_list_entry) {
+ list_for_each_entry_safe(device, next, &delete_list, delete_list_entry) {
if (device->volume_offline) {
pqi_dev_info(ctrl_info, "offline", device);
pqi_show_volume_status(ctrl_info, device);
- } else {
- pqi_dev_info(ctrl_info, "removed", device);
}
- if (pqi_is_device_added(device))
- pqi_remove_device(ctrl_info, device);
list_del(&device->delete_list_entry);
- pqi_free_device(device);
+ if (pqi_is_device_added(device)) {
+ pqi_remove_device(ctrl_info, device);
+ } else {
+ if (!device->volume_offline)
+ pqi_dev_info(ctrl_info, "removed", device);
+ pqi_free_device(device);
+ }
}
/*
@@ -1845,20 +1871,27 @@
*/
list_for_each_entry(device, &ctrl_info->scsi_device_list,
scsi_device_list_entry) {
- if (device->sdev && device->queue_depth !=
- device->advertised_queue_depth) {
- device->advertised_queue_depth = device->queue_depth;
- scsi_change_queue_depth(device->sdev,
- device->advertised_queue_depth);
+ if (device->sdev) {
+ if (device->queue_depth !=
+ device->advertised_queue_depth) {
+ device->advertised_queue_depth = device->queue_depth;
+ scsi_change_queue_depth(device->sdev,
+ device->advertised_queue_depth);
+ }
+ if (device->rescan) {
+ scsi_rescan_device(&device->sdev->sdev_gendev);
+ device->rescan = false;
+ }
}
}
/* Expose any new devices. */
list_for_each_entry_safe(device, next, &add_list, add_list_entry) {
if (!pqi_is_device_added(device)) {
- pqi_dev_info(ctrl_info, "added", device);
rc = pqi_add_device(ctrl_info, device);
- if (rc) {
+ if (rc == 0) {
+ pqi_dev_info(ctrl_info, "added", device);
+ } else {
dev_warn(&ctrl_info->pci_dev->dev,
"scsi %d:%d:%d:%d addition failed, device not added\n",
ctrl_info->scsi_host->host_no,
@@ -1870,36 +1903,19 @@
}
}
-static bool pqi_is_supported_device(struct pqi_scsi_dev *device)
+static inline bool pqi_is_supported_device(struct pqi_scsi_dev *device)
{
- bool is_supported;
+ /*
+ * Only support the HBA controller itself as a RAID
+ * controller. If it's a RAID controller other than
+ * the HBA itself (an external RAID controller, for
+ * example), we don't support it.
+ */
+ if (device->device_type == SA_DEVICE_TYPE_CONTROLLER &&
+ !pqi_is_hba_lunid(device->scsi3addr))
+ return false;
- if (device->is_expander_smp_device)
- return true;
-
- is_supported = false;
-
- switch (device->devtype) {
- case TYPE_DISK:
- case TYPE_ZBC:
- case TYPE_TAPE:
- case TYPE_MEDIUM_CHANGER:
- case TYPE_ENCLOSURE:
- is_supported = true;
- break;
- case TYPE_RAID:
- /*
- * Only support the HBA controller itself as a RAID
- * controller. If it's a RAID controller other than
- * the HBA itself (an external RAID controller, for
- * example), we don't support it.
- */
- if (pqi_is_hba_lunid(device->scsi3addr))
- is_supported = true;
- break;
- }
-
- return is_supported;
+ return true;
}
static inline bool pqi_skip_device(u8 *scsi3addr)
@@ -1918,16 +1934,10 @@
static inline bool pqi_is_device_with_sas_address(struct pqi_scsi_dev *device)
{
- if (!device->is_physical_device)
- return false;
-
- if (device->is_expander_smp_device)
- return true;
-
- switch (device->devtype) {
- case TYPE_DISK:
- case TYPE_ZBC:
- case TYPE_ENCLOSURE:
+ switch (device->device_type) {
+ case SA_DEVICE_TYPE_SAS:
+ case SA_DEVICE_TYPE_EXPANDER_SMP:
+ case SA_DEVICE_TYPE_SES:
return true;
}
@@ -1996,9 +2006,8 @@
rc = -ENOMEM;
goto out;
}
- if (pqi_hide_vsep) {
- int i;
+ if (pqi_hide_vsep) {
for (i = num_physicals - 1; i >= 0; i--) {
phys_lun_ext_entry =
&physdev_list->lun_entries[i];
@@ -2070,16 +2079,19 @@
memcpy(device->scsi3addr, scsi3addr, sizeof(device->scsi3addr));
device->is_physical_device = is_physical_device;
if (is_physical_device) {
- if (phys_lun_ext_entry->device_type ==
- SA_EXPANDER_SMP_DEVICE)
+ device->device_type = phys_lun_ext_entry->device_type;
+ if (device->device_type == SA_DEVICE_TYPE_EXPANDER_SMP)
device->is_expander_smp_device = true;
} else {
device->is_external_raid_device =
pqi_is_external_raid_addr(scsi3addr);
}
+ if (!pqi_is_supported_device(device))
+ continue;
+
/* Gather information about the device. */
- rc = pqi_get_device_info(ctrl_info, device);
+ rc = pqi_get_device_info(ctrl_info, device, id_phys);
if (rc == -ENOMEM) {
dev_warn(&ctrl_info->pci_dev->dev, "%s\n",
out_of_memory_msg);
@@ -2100,24 +2112,17 @@
continue;
}
- if (!pqi_is_supported_device(device))
- continue;
-
pqi_assign_bus_target_lun(device);
if (device->is_physical_device) {
device->wwid = phys_lun_ext_entry->wwid;
if ((phys_lun_ext_entry->device_flags &
- REPORT_PHYS_LUN_DEV_FLAG_AIO_ENABLED) &&
+ CISS_REPORT_PHYS_DEV_FLAG_AIO_ENABLED) &&
phys_lun_ext_entry->aio_handle) {
device->aio_enabled = true;
- device->aio_handle =
- phys_lun_ext_entry->aio_handle;
+ device->aio_handle =
+ phys_lun_ext_entry->aio_handle;
}
-
- pqi_get_physical_disk_info(ctrl_info,
- device, id_phys);
-
} else {
memcpy(device->volume_id, log_lun_ext_entry->volume_id,
sizeof(device->volume_id));
@@ -2148,31 +2153,6 @@
return rc;
}
-static void pqi_remove_all_scsi_devices(struct pqi_ctrl_info *ctrl_info)
-{
- unsigned long flags;
- struct pqi_scsi_dev *device;
-
- while (1) {
- spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);
-
- device = list_first_entry_or_null(&ctrl_info->scsi_device_list,
- struct pqi_scsi_dev, scsi_device_list_entry);
- if (device)
- list_del(&device->scsi_device_list_entry);
-
- spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock,
- flags);
-
- if (!device)
- break;
-
- if (pqi_is_device_added(device))
- pqi_remove_device(ctrl_info, device);
- pqi_free_device(device);
- }
-}
-
static int pqi_scan_scsi_devices(struct pqi_ctrl_info *ctrl_info)
{
int rc = 0;
@@ -2312,7 +2292,7 @@
switch (scmd->cmnd[0]) {
case WRITE_6:
is_write = true;
- /* fall through */
+ fallthrough;
case READ_6:
first_block = (u64)(((scmd->cmnd[1] & 0x1f) << 16) |
(scmd->cmnd[2] << 8) | scmd->cmnd[3]);
@@ -2322,21 +2302,21 @@
break;
case WRITE_10:
is_write = true;
- /* fall through */
+ fallthrough;
case READ_10:
first_block = (u64)get_unaligned_be32(&scmd->cmnd[2]);
block_cnt = (u32)get_unaligned_be16(&scmd->cmnd[7]);
break;
case WRITE_12:
is_write = true;
- /* fall through */
+ fallthrough;
case READ_12:
first_block = (u64)get_unaligned_be32(&scmd->cmnd[2]);
block_cnt = get_unaligned_be32(&scmd->cmnd[6]);
break;
case WRITE_16:
is_write = true;
- /* fall through */
+ fallthrough;
case READ_16:
first_block = get_unaligned_be64(&scmd->cmnd[2]);
block_cnt = get_unaligned_be32(&scmd->cmnd[10]);
@@ -2958,7 +2938,7 @@
case PQI_RESPONSE_IU_AIO_PATH_IO_SUCCESS:
if (io_request->scmd)
io_request->scmd->result = 0;
- /* fall through */
+ fallthrough;
case PQI_RESPONSE_IU_GENERAL_MANAGEMENT:
break;
case PQI_RESPONSE_IU_VENDOR_GENERAL:
@@ -3117,18 +3097,17 @@
}
static void pqi_process_soft_reset(struct pqi_ctrl_info *ctrl_info,
- enum pqi_soft_reset_status reset_status)
+ enum pqi_soft_reset_status reset_status)
{
int rc;
switch (reset_status) {
case RESET_INITIATE_DRIVER:
- /* fall through */
case RESET_TIMEDOUT:
dev_info(&ctrl_info->pci_dev->dev,
"resetting controller %u\n", ctrl_info->ctrl_id);
sis_soft_reset(ctrl_info);
- /* fall through */
+ fallthrough;
case RESET_INITIATE_FIRMWARE:
rc = pqi_ofa_ctrl_restart(ctrl_info);
pqi_ofa_free_host_buffer(ctrl_info);
@@ -3161,8 +3140,8 @@
if (event_id == PQI_EVENT_OFA_QUIESCE) {
dev_info(&ctrl_info->pci_dev->dev,
- "Received Online Firmware Activation quiesce event for controller %u\n",
- ctrl_info->ctrl_id);
+ "Received Online Firmware Activation quiesce event for controller %u\n",
+ ctrl_info->ctrl_id);
pqi_ofa_ctrl_quiesce(ctrl_info);
pqi_acknowledge_event(ctrl_info, event);
if (ctrl_info->soft_reset_handshake_supported) {
@@ -3182,8 +3161,8 @@
pqi_ofa_free_host_buffer(ctrl_info);
pqi_acknowledge_event(ctrl_info, event);
dev_info(&ctrl_info->pci_dev->dev,
- "Online Firmware Activation(%u) cancel reason : %u\n",
- ctrl_info->ctrl_id, event->ofa_cancel_reason);
+ "Online Firmware Activation(%u) cancel reason : %u\n",
+ ctrl_info->ctrl_id, event->ofa_cancel_reason);
}
mutex_unlock(&ctrl_info->ofa_mutex);
@@ -3367,7 +3346,7 @@
#define PQI_LEGACY_INTX_MASK 0x1
static inline void pqi_configure_legacy_intx(struct pqi_ctrl_info *ctrl_info,
- bool enable_intx)
+ bool enable_intx)
{
u32 intx_mask;
struct pqi_device_registers __iomem *pqi_registers;
@@ -3814,7 +3793,7 @@
&pqi_registers->admin_oq_pi_addr);
reg = PQI_ADMIN_IQ_NUM_ELEMENTS |
- (PQI_ADMIN_OQ_NUM_ELEMENTS) << 8 |
+ (PQI_ADMIN_OQ_NUM_ELEMENTS << 8) |
(admin_queues->int_msg_num << 16);
writel(reg, &pqi_registers->admin_iq_num_elements);
writel(PQI_CREATE_ADMIN_QUEUE_PAIR,
@@ -4021,8 +4000,8 @@
complete(waiting);
}
-static int pqi_process_raid_io_error_synchronous(struct pqi_raid_error_info
- *error_info)
+static int pqi_process_raid_io_error_synchronous(
+ struct pqi_raid_error_info *error_info)
{
int rc = -EIO;
@@ -4641,11 +4620,11 @@
static inline int pqi_alloc_error_buffer(struct pqi_ctrl_info *ctrl_info)
{
- ctrl_info->error_buffer = dma_alloc_coherent(&ctrl_info->pci_dev->dev,
- ctrl_info->error_buffer_length,
- &ctrl_info->error_buffer_dma_handle,
- GFP_KERNEL);
+ ctrl_info->error_buffer = dma_alloc_coherent(&ctrl_info->pci_dev->dev,
+ ctrl_info->error_buffer_length,
+ &ctrl_info->error_buffer_dma_handle,
+ GFP_KERNEL);
if (!ctrl_info->error_buffer)
return -ENOMEM;
@@ -5395,22 +5374,21 @@
if (pqi_is_logical_device(device)) {
raid_bypassed = false;
if (device->raid_bypass_enabled &&
- !blk_rq_is_passthrough(scmd->request)) {
+ !blk_rq_is_passthrough(scmd->request)) {
rc = pqi_raid_bypass_submit_scsi_cmd(ctrl_info, device,
scmd, queue_group);
- if (rc == 0 || rc == SCSI_MLQUEUE_HOST_BUSY)
+ if (rc == 0 || rc == SCSI_MLQUEUE_HOST_BUSY) {
raid_bypassed = true;
+ atomic_inc(&device->raid_bypass_cnt);
+ }
}
if (!raid_bypassed)
- rc = pqi_raid_submit_scsi_cmd(ctrl_info, device, scmd,
- queue_group);
+ rc = pqi_raid_submit_scsi_cmd(ctrl_info, device, scmd, queue_group);
} else {
if (device->aio_enabled)
- rc = pqi_aio_submit_scsi_cmd(ctrl_info, device, scmd,
- queue_group);
+ rc = pqi_aio_submit_scsi_cmd(ctrl_info, device, scmd, queue_group);
else
- rc = pqi_raid_submit_scsi_cmd(ctrl_info, device, scmd,
- queue_group);
+ rc = pqi_raid_submit_scsi_cmd(ctrl_info, device, scmd, queue_group);
}
out:
@@ -5650,7 +5628,8 @@
complete(waiting);
}
-#define PQI_LUN_RESET_TIMEOUT_SECS 10
+#define PQI_LUN_RESET_TIMEOUT_SECS 30
+#define PQI_LUN_RESET_POLL_COMPLETION_SECS 10
static int pqi_wait_for_lun_reset_completion(struct pqi_ctrl_info *ctrl_info,
struct pqi_scsi_dev *device, struct completion *wait)
@@ -5659,7 +5638,7 @@
while (1) {
if (wait_for_completion_io_timeout(wait,
- PQI_LUN_RESET_TIMEOUT_SECS * PQI_HZ)) {
+ PQI_LUN_RESET_POLL_COMPLETION_SECS * PQI_HZ)) {
rc = 0;
break;
}
@@ -5696,6 +5675,9 @@
memcpy(request->lun_number, device->scsi3addr,
sizeof(request->lun_number));
request->task_management_function = SOP_TASK_MANAGEMENT_LUN_RESET;
+ if (ctrl_info->tmf_iu_timeout_supported)
+ put_unaligned_le16(PQI_LUN_RESET_TIMEOUT_SECS,
+ &request->timeout);
pqi_start_io(ctrl_info,
&ctrl_info->queue_groups[PQI_DEFAULT_QUEUE_GROUP], RAID_PATH,
@@ -5725,7 +5707,7 @@
for (retries = 0;;) {
rc = pqi_lun_reset(ctrl_info, device);
- if (rc != -EAGAIN || ++retries > PQI_LUN_RESET_RETRIES)
+ if (rc == 0 || ++retries > PQI_LUN_RESET_RETRIES)
break;
msleep(PQI_LUN_RESET_RETRY_INTERVAL_MSECS);
}
@@ -5853,8 +5835,42 @@
ctrl_info->pci_dev, 0);
}
-static int pqi_getpciinfo_ioctl(struct pqi_ctrl_info *ctrl_info,
- void __user *arg)
+static int pqi_slave_configure(struct scsi_device *sdev)
+{
+ struct pqi_scsi_dev *device;
+
+ device = sdev->hostdata;
+ device->devtype = sdev->type;
+
+ return 0;
+}
+
+static void pqi_slave_destroy(struct scsi_device *sdev)
+{
+ unsigned long flags;
+ struct pqi_scsi_dev *device;
+ struct pqi_ctrl_info *ctrl_info;
+
+ ctrl_info = shost_to_hba(sdev->host);
+
+ spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);
+
+ device = sdev->hostdata;
+ if (device) {
+ sdev->hostdata = NULL;
+ if (!list_empty(&device->scsi_device_list_entry))
+ list_del(&device->scsi_device_list_entry);
+ }
+
+ spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
+
+ if (device) {
+ pqi_dev_info(ctrl_info, "removed", device);
+ pqi_free_device(device);
+ }
+}
+
+static int pqi_getpciinfo_ioctl(struct pqi_ctrl_info *ctrl_info, void __user *arg)
{
struct pci_dev *pci_dev;
u32 subsystem_vendor;
@@ -5871,8 +5887,7 @@
pciinfo.dev_fn = pci_dev->devfn;
subsystem_vendor = pci_dev->subsystem_vendor;
subsystem_device = pci_dev->subsystem_device;
- pciinfo.board_id = ((subsystem_device << 16) & 0xffff0000) |
- subsystem_vendor;
+ pciinfo.board_id = ((subsystem_device << 16) & 0xffff0000) | subsystem_vendor;
if (copy_to_user(arg, &pciinfo, sizeof(pciinfo)))
return -EFAULT;
@@ -6058,6 +6073,9 @@
put_unaligned_le16(iu_length, &request.header.iu_length);
+ if (ctrl_info->raid_iu_timeout_supported)
+ put_unaligned_le32(iocommand.Request.Timeout, &request.timeout);
+
rc = pqi_submit_raid_request_synchronous(ctrl_info, &request.header,
PQI_SYNC_FLAGS_INTERRUPTABLE, &pqi_error_info, NO_TIMEOUT);
@@ -6111,8 +6129,7 @@
ctrl_info = shost_to_hba(sdev->host);
- if (pqi_ctrl_in_ofa(ctrl_info) ||
- pqi_ctrl_in_shutdown(ctrl_info))
+ if (pqi_ctrl_in_ofa(ctrl_info) || pqi_ctrl_in_shutdown(ctrl_info))
return -EBUSY;
switch (cmd) {
@@ -6153,14 +6170,8 @@
static ssize_t pqi_driver_version_show(struct device *dev,
struct device_attribute *attr, char *buffer)
{
- struct Scsi_Host *shost;
- struct pqi_ctrl_info *ctrl_info;
-
- shost = class_to_shost(dev);
- ctrl_info = shost_to_hba(shost);
-
- return snprintf(buffer, PAGE_SIZE,
- "%s\n", DRIVER_VERSION BUILD_TIMESTAMP);
+ return snprintf(buffer, PAGE_SIZE, "%s\n",
+ DRIVER_VERSION BUILD_TIMESTAMP);
}
static ssize_t pqi_serial_number_show(struct device *dev,
@@ -6217,14 +6228,14 @@
for (i = 0; i < ARRAY_SIZE(pqi_lockup_actions); i++) {
if (pqi_lockup_actions[i].action == pqi_lockup_action)
- count += snprintf(buffer + count, PAGE_SIZE - count,
+ count += scnprintf(buffer + count, PAGE_SIZE - count,
"[%s] ", pqi_lockup_actions[i].name);
else
- count += snprintf(buffer + count, PAGE_SIZE - count,
+ count += scnprintf(buffer + count, PAGE_SIZE - count,
"%s ", pqi_lockup_actions[i].name);
}
- count += snprintf(buffer + count, PAGE_SIZE - count, "\n");
+ count += scnprintf(buffer + count, PAGE_SIZE - count, "\n");
return count;
}
@@ -6285,8 +6296,7 @@
device = sdev->hostdata;
if (!device) {
- spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock,
- flags);
+ spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
return -ENODEV;
}
@@ -6323,10 +6333,10 @@
device = sdev->hostdata;
if (!device) {
- spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock,
- flags);
+ spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
return -ENODEV;
}
+
memcpy(lunid, device->scsi3addr, sizeof(lunid));
spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
@@ -6334,7 +6344,8 @@
return snprintf(buffer, PAGE_SIZE, "0x%8phN\n", lunid);
}
-#define MAX_PATHS 8
+#define MAX_PATHS 8
+
static ssize_t pqi_path_info_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -6346,9 +6357,9 @@
int output_len = 0;
u8 box;
u8 bay;
- u8 path_map_index = 0;
+ u8 path_map_index;
char *active;
- unsigned char phys_connector[2];
+ u8 phys_connector[2];
sdev = to_scsi_device(dev);
ctrl_info = shost_to_hba(sdev->host);
@@ -6357,14 +6368,13 @@
device = sdev->hostdata;
if (!device) {
- spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock,
- flags);
+ spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
return -ENODEV;
}
bay = device->bay;
for (i = 0; i < MAX_PATHS; i++) {
- path_map_index = 1<<i;
+ path_map_index = 1 << i;
if (i == device->active_path_index)
active = "Active";
else if (device->path_map & path_map_index)
@@ -6415,10 +6425,10 @@
}
spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
+
return output_len;
}
-
static ssize_t pqi_sas_address_show(struct device *dev,
struct device_attribute *attr, char *buffer)
{
@@ -6434,11 +6444,11 @@
spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);
device = sdev->hostdata;
- if (pqi_is_logical_device(device)) {
- spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock,
- flags);
+ if (!device || !pqi_is_device_with_sas_address(device)) {
+ spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
return -ENODEV;
}
+
sas_address = device->sas_address;
spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
@@ -6460,6 +6470,11 @@
spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);
device = sdev->hostdata;
+ if (!device) {
+ spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
+ return -ENODEV;
+ }
+
buffer[0] = device->raid_bypass_enabled ? '1' : '0';
buffer[1] = '\n';
buffer[2] = '\0';
@@ -6484,6 +6499,10 @@
spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);
device = sdev->hostdata;
+ if (!device) {
+ spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
+ return -ENODEV;
+ }
if (pqi_is_logical_device(device))
raid_level = pqi_raid_level_to_string(device->raid_level);
@@ -6495,13 +6514,40 @@
return snprintf(buffer, PAGE_SIZE, "%s\n", raid_level);
}
+static ssize_t pqi_raid_bypass_cnt_show(struct device *dev,
+ struct device_attribute *attr, char *buffer)
+{
+ struct pqi_ctrl_info *ctrl_info;
+ struct scsi_device *sdev;
+ struct pqi_scsi_dev *device;
+ unsigned long flags;
+ int raid_bypass_cnt;
+
+ sdev = to_scsi_device(dev);
+ ctrl_info = shost_to_hba(sdev->host);
+
+ spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);
+
+ device = sdev->hostdata;
+ if (!device) {
+ spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
+ return -ENODEV;
+ }
+
+ raid_bypass_cnt = atomic_read(&device->raid_bypass_cnt);
+
+ spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
+
+ return snprintf(buffer, PAGE_SIZE, "0x%x\n", raid_bypass_cnt);
+}
+
static DEVICE_ATTR(lunid, 0444, pqi_lunid_show, NULL);
static DEVICE_ATTR(unique_id, 0444, pqi_unique_id_show, NULL);
static DEVICE_ATTR(path_info, 0444, pqi_path_info_show, NULL);
static DEVICE_ATTR(sas_address, 0444, pqi_sas_address_show, NULL);
-static DEVICE_ATTR(ssd_smart_path_enabled, 0444,
- pqi_ssd_smart_path_enabled_show, NULL);
+static DEVICE_ATTR(ssd_smart_path_enabled, 0444, pqi_ssd_smart_path_enabled_show, NULL);
static DEVICE_ATTR(raid_level, 0444, pqi_raid_level_show, NULL);
+static DEVICE_ATTR(raid_bypass_cnt, 0444, pqi_raid_bypass_cnt_show, NULL);
static struct device_attribute *pqi_sdev_attrs[] = {
&dev_attr_lunid,
@@ -6510,6 +6556,7 @@
&dev_attr_sas_address,
&dev_attr_ssd_smart_path_enabled,
&dev_attr_raid_level,
+ &dev_attr_raid_bypass_cnt,
NULL
};
@@ -6524,6 +6571,8 @@
.eh_device_reset_handler = pqi_eh_device_reset_handler,
.ioctl = pqi_ioctl,
.slave_alloc = pqi_slave_alloc,
+ .slave_configure = pqi_slave_configure,
+ .slave_destroy = pqi_slave_destroy,
.map_queues = pqi_map_queues,
.sdev_attrs = pqi_sdev_attrs,
.shost_attrs = pqi_shost_attrs,
@@ -6557,6 +6606,7 @@
shost->irq = pci_irq_vector(ctrl_info->pci_dev, 0);
shost->unique_id = shost->irq;
shost->nr_hw_queues = ctrl_info->num_queue_groups;
+ shost->host_tagset = 1;
shost->hostdata[0] = (unsigned long)ctrl_info;
rc = scsi_add_host(shost, &ctrl_info->pci_dev->dev);
@@ -6843,6 +6893,27 @@
firmware_feature->feature_name);
}
+static void pqi_ctrl_update_feature_flags(struct pqi_ctrl_info *ctrl_info,
+ struct pqi_firmware_feature *firmware_feature)
+{
+ switch (firmware_feature->feature_bit) {
+ case PQI_FIRMWARE_FEATURE_SOFT_RESET_HANDSHAKE:
+ ctrl_info->soft_reset_handshake_supported =
+ firmware_feature->enabled;
+ break;
+ case PQI_FIRMWARE_FEATURE_RAID_IU_TIMEOUT:
+ ctrl_info->raid_iu_timeout_supported =
+ firmware_feature->enabled;
+ break;
+ case PQI_FIRMWARE_FEATURE_TMF_IU_TIMEOUT:
+ ctrl_info->tmf_iu_timeout_supported =
+ firmware_feature->enabled;
+ break;
+ }
+
+ pqi_firmware_feature_status(ctrl_info, firmware_feature);
+}
+
static inline void pqi_firmware_feature_update(struct pqi_ctrl_info *ctrl_info,
struct pqi_firmware_feature *firmware_feature)
{
@@ -6866,7 +6937,17 @@
{
.feature_name = "New Soft Reset Handshake",
.feature_bit = PQI_FIRMWARE_FEATURE_SOFT_RESET_HANDSHAKE,
- .feature_status = pqi_firmware_feature_status,
+ .feature_status = pqi_ctrl_update_feature_flags,
+ },
+ {
+ .feature_name = "RAID IU Timeout",
+ .feature_bit = PQI_FIRMWARE_FEATURE_RAID_IU_TIMEOUT,
+ .feature_status = pqi_ctrl_update_feature_flags,
+ },
+ {
+ .feature_name = "TMF IU Timeout",
+ .feature_bit = PQI_FIRMWARE_FEATURE_TMF_IU_TIMEOUT,
+ .feature_status = pqi_ctrl_update_feature_flags,
},
};
@@ -6920,7 +7001,6 @@
return;
}
- ctrl_info->soft_reset_handshake_supported = false;
for (i = 0; i < ARRAY_SIZE(pqi_firmware_features); i++) {
if (!pqi_firmware_features[i].supported)
continue;
@@ -6928,10 +7008,6 @@
firmware_features_iomem_addr,
pqi_firmware_features[i].feature_bit)) {
pqi_firmware_features[i].enabled = true;
- if (pqi_firmware_features[i].feature_bit ==
- PQI_FIRMWARE_FEATURE_SOFT_RESET_HANDSHAKE)
- ctrl_info->soft_reset_handshake_supported =
- true;
}
pqi_firmware_feature_update(ctrl_info,
&pqi_firmware_features[i]);
@@ -7392,7 +7468,7 @@
rc = pqi_get_ctrl_product_details(ctrl_info);
if (rc) {
dev_err(&ctrl_info->pci_dev->dev,
- "error obtaining product detail\n");
+ "error obtaining product details\n");
return rc;
}
@@ -7420,8 +7496,12 @@
static inline int pqi_set_pcie_completion_timeout(struct pci_dev *pci_dev,
u16 timeout)
{
- return pcie_capability_clear_and_set_word(pci_dev, PCI_EXP_DEVCTL2,
+ int rc;
+
+ rc = pcie_capability_clear_and_set_word(pci_dev, PCI_EXP_DEVCTL2,
PCI_EXP_DEVCTL2_COMP_TIMEOUT, timeout);
+
+ return pcibios_err_to_errno(rc);
}
static int pqi_pci_init(struct pqi_ctrl_info *ctrl_info)
@@ -7454,7 +7534,7 @@
goto disable_device;
}
- ctrl_info->iomem_base = ioremap_nocache(pci_resource_start(
+ ctrl_info->iomem_base = ioremap(pci_resource_start(
ctrl_info->pci_dev, 0),
sizeof(struct pqi_ctrl_registers));
if (!ctrl_info->iomem_base) {
@@ -7584,7 +7664,6 @@
{
pqi_cancel_rescan_worker(ctrl_info);
pqi_cancel_update_time_worker(ctrl_info);
- pqi_remove_all_scsi_devices(ctrl_info);
pqi_unregister_scsi(ctrl_info);
if (ctrl_info->pqi_mode_enabled)
pqi_revert_to_sis_mode(ctrl_info);
@@ -7728,6 +7807,8 @@
dev_err(dev, "Failed to allocate host buffer of size = %u",
bytes_requested);
}
+
+ return;
}
static void pqi_ofa_free_host_buffer(struct pqi_ctrl_info *ctrl_info)
@@ -8028,7 +8109,6 @@
pqi_crash_if_pending_command(ctrl_info);
pqi_reset(ctrl_info);
-
}
static void pqi_process_lockup_action_param(void)
@@ -8313,6 +8393,10 @@
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
+ PCI_VENDOR_ID_ADAPTEC2, 0x080a)
+ },
+ {
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
PCI_VENDOR_ID_ADAPTEC2, 0x0900)
},
{
@@ -8650,8 +8734,7 @@
pr_info(DRIVER_NAME "\n");
- pqi_sas_transport_template =
- sas_attach_transport(&pqi_sas_transport_functions);
+ pqi_sas_transport_template = sas_attach_transport(&pqi_sas_transport_functions);
if (!pqi_sas_transport_template)
return -ENODEV;
@@ -8841,11 +8924,11 @@
BUILD_BUG_ON(offsetof(struct pqi_general_admin_request,
data.delete_operational_queue.queue_id) != 12);
BUILD_BUG_ON(sizeof(struct pqi_general_admin_request) != 64);
- BUILD_BUG_ON(FIELD_SIZEOF(struct pqi_general_admin_request,
+ BUILD_BUG_ON(sizeof_field(struct pqi_general_admin_request,
data.create_operational_iq) != 64 - 11);
- BUILD_BUG_ON(FIELD_SIZEOF(struct pqi_general_admin_request,
+ BUILD_BUG_ON(sizeof_field(struct pqi_general_admin_request,
data.create_operational_oq) != 64 - 11);
- BUILD_BUG_ON(FIELD_SIZEOF(struct pqi_general_admin_request,
+ BUILD_BUG_ON(sizeof_field(struct pqi_general_admin_request,
data.delete_operational_queue) != 64 - 11);
BUILD_BUG_ON(offsetof(struct pqi_general_admin_response,
@@ -8893,6 +8976,8 @@
BUILD_BUG_ON(offsetof(struct pqi_raid_path_request,
cdb) != 32);
BUILD_BUG_ON(offsetof(struct pqi_raid_path_request,
+ timeout) != 60);
+ BUILD_BUG_ON(offsetof(struct pqi_raid_path_request,
sg_descriptors) != 64);
BUILD_BUG_ON(sizeof(struct pqi_raid_path_request) !=
PQI_OPERATIONAL_IQ_ELEMENT_LENGTH);
@@ -9047,6 +9132,8 @@
BUILD_BUG_ON(offsetof(struct pqi_task_management_request,
nexus_id) != 10);
BUILD_BUG_ON(offsetof(struct pqi_task_management_request,
+ timeout) != 14);
+ BUILD_BUG_ON(offsetof(struct pqi_task_management_request,
lun_number) != 16);
BUILD_BUG_ON(offsetof(struct pqi_task_management_request,
protocol_specific) != 24);
diff --git a/drivers/scsi/smartpqi/smartpqi_sas_transport.c b/drivers/scsi/smartpqi/smartpqi_sas_transport.c
index b7e28b9..999870e 100644
--- a/drivers/scsi/smartpqi/smartpqi_sas_transport.c
+++ b/drivers/scsi/smartpqi/smartpqi_sas_transport.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* driver for Microsemi PQI-based storage controllers
- * Copyright (c) 2019 Microchip Technology Inc. and its subsidiaries
+ * Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
@@ -312,7 +312,6 @@
static int pqi_sas_get_enclosure_identifier(struct sas_rphy *rphy,
u64 *identifier)
{
-
int rc;
unsigned long flags;
struct Scsi_Host *shost;
@@ -361,7 +360,7 @@
}
}
- if (found_device->phy_connected_dev_type != SA_CONTROLLER_DEVICE) {
+ if (found_device->phy_connected_dev_type != SA_DEVICE_TYPE_CONTROLLER) {
rc = -EINVAL;
goto out;
}
@@ -382,12 +381,10 @@
spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
return rc;
-
}
static int pqi_sas_get_bay_identifier(struct sas_rphy *rphy)
{
-
int rc;
unsigned long flags;
struct pqi_ctrl_info *ctrl_info;
@@ -482,7 +479,6 @@
req_size -= SMP_CRC_FIELD_LENGTH;
put_unaligned_le32(req_size, ¶meters->request_length);
-
put_unaligned_le32(resp_size, ¶meters->response_length);
sg_copy_to_buffer(job->request_payload.sg_list,
@@ -512,12 +508,12 @@
struct sas_rphy *rphy)
{
int rc;
- struct pqi_ctrl_info *ctrl_info = shost_to_hba(shost);
+ struct pqi_ctrl_info *ctrl_info;
struct bmic_csmi_smp_passthru_buffer *smp_buf;
struct pqi_raid_error_info error_info;
unsigned int reslen = 0;
- pqi_ctrl_busy(ctrl_info);
+ ctrl_info = shost_to_hba(shost);
if (job->reply_payload.payload_len == 0) {
rc = -ENOMEM;
@@ -539,16 +535,6 @@
goto out;
}
- if (pqi_ctrl_offline(ctrl_info)) {
- rc = -ENXIO;
- goto out;
- }
-
- if (pqi_ctrl_blocked(ctrl_info)) {
- rc = -EBUSY;
- goto out;
- }
-
smp_buf = pqi_build_csmi_smp_passthru_buffer(rphy, job);
if (!smp_buf) {
rc = -ENOMEM;
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.c b/drivers/scsi/smartpqi/smartpqi_sis.c
index f0d6e88..26ea6b9 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.c
+++ b/drivers/scsi/smartpqi/smartpqi_sis.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* driver for Microsemi PQI-based storage controllers
- * Copyright (c) 2019 Microchip Technology Inc. and its subsidiaries
+ * Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
diff --git a/drivers/scsi/smartpqi/smartpqi_sis.h b/drivers/scsi/smartpqi/smartpqi_sis.h
index 86b0e48..878d34c 100644
--- a/drivers/scsi/smartpqi/smartpqi_sis.h
+++ b/drivers/scsi/smartpqi/smartpqi_sis.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* driver for Microsemi PQI-based storage controllers
- * Copyright (c) 2019 Microchip Technology Inc. and its subsidiaries
+ * Copyright (c) 2019-2020 Microchip Technology Inc. and its subsidiaries
* Copyright (c) 2016-2018 Microsemi Corporation
* Copyright (c) 2016 PMC-Sierra, Inc.
*
diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c
index 0521575..97c6f81 100644
--- a/drivers/scsi/sni_53c710.c
+++ b/drivers/scsi/sni_53c710.c
@@ -28,7 +28,6 @@
#include <linux/platform_device.h>
#include <asm/page.h>
-#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/delay.h>
@@ -72,7 +71,7 @@
hostdata->dev = &dev->dev;
dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
- hostdata->base = ioremap_nocache(base, 0x100);
+ hostdata->base = ioremap(base, 0x100);
hostdata->differential = 0;
hostdata->clock = SNIRM710_CLOCK;
@@ -128,16 +127,4 @@
.name = "snirm_53c710",
},
};
-
-static int __init snirm710_init(void)
-{
- return platform_driver_register(&snirm710_driver);
-}
-
-static void __exit snirm710_exit(void)
-{
- platform_driver_unregister(&snirm710_driver);
-}
-
-module_init(snirm710_init);
-module_exit(snirm710_exit);
+module_platform_driver(snirm710_driver);
diff --git a/drivers/scsi/snic/snic.h b/drivers/scsi/snic/snic.h
index de0ab5f..f4c6662 100644
--- a/drivers/scsi/snic/snic.h
+++ b/drivers/scsi/snic/snic.h
@@ -399,7 +399,7 @@
void snic_handle_link(struct work_struct *);
int snic_queue_exch_ver_req(struct snic *);
-int snic_io_exch_ver_cmpl_handler(struct snic *, struct snic_fw_req *);
+void snic_io_exch_ver_cmpl_handler(struct snic *, struct snic_fw_req *);
int snic_queue_wq_desc(struct snic *, void *os_buf, u16 len);
diff --git a/drivers/scsi/snic/snic_ctl.c b/drivers/scsi/snic/snic_ctl.c
index 449b03f..4cd8611 100644
--- a/drivers/scsi/snic/snic_ctl.c
+++ b/drivers/scsi/snic/snic_ctl.c
@@ -151,7 +151,7 @@
/*
* snic_io_exch_ver_cmpl_handler
*/
-int
+void
snic_io_exch_ver_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq)
{
struct snic_req_info *rqi = NULL;
@@ -160,7 +160,6 @@
u32 cmnd_id, hid, max_sgs;
ulong ctx = 0;
unsigned long flags;
- int ret = 0;
SNIC_HOST_INFO(snic->shost, "Exch Ver Compl Received.\n");
snic_io_hdr_dec(&fwreq->hdr, &typ, &hdr_stat, &cmnd_id, &hid, &ctx);
@@ -224,8 +223,6 @@
snic_release_untagged_req(snic, rqi);
SNIC_HOST_INFO(snic->shost, "Exch_cmpl Done, hdr_stat %d.\n", hdr_stat);
-
- return ret;
} /* end of snic_io_exch_ver_cmpl_handler */
/*
diff --git a/drivers/scsi/snic/snic_debugfs.c b/drivers/scsi/snic/snic_debugfs.c
index 2b34936..4471c4c 100644
--- a/drivers/scsi/snic/snic_debugfs.c
+++ b/drivers/scsi/snic/snic_debugfs.c
@@ -439,26 +439,14 @@
return 0;
}
-static const struct seq_operations snic_trc_seq_ops = {
+static const struct seq_operations snic_trc_sops = {
.start = snic_trc_seq_start,
.next = snic_trc_seq_next,
.stop = snic_trc_seq_stop,
.show = snic_trc_seq_show,
};
-static int
-snic_trc_open(struct inode *inode, struct file *filp)
-{
- return seq_open(filp, &snic_trc_seq_ops);
-}
-
-static const struct file_operations snic_trc_fops = {
- .owner = THIS_MODULE,
- .open = snic_trc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
+DEFINE_SEQ_ATTRIBUTE(snic_trc);
/*
* snic_trc_debugfs_init : creates trace/tracing_enable files for trace
diff --git a/drivers/scsi/snic/snic_scsi.c b/drivers/scsi/snic/snic_scsi.c
index b3650c9..6dd0ff1 100644
--- a/drivers/scsi/snic/snic_scsi.c
+++ b/drivers/scsi/snic/snic_scsi.c
@@ -1387,19 +1387,15 @@
}
ret = snic_queue_itmf_req(snic, tmreq, sc, tmf, req_id);
- if (ret)
- goto tmreq_err;
-
- ret = 0;
tmreq_err:
if (ret) {
SNIC_HOST_ERR(snic->shost,
- "issu_tmreq: Queing ITMF(%d) Req, sc %p rqi %p req_id %d tag %x fails err = %d\n",
+ "issu_tmreq: Queueing ITMF(%d) Req, sc %p rqi %p req_id %d tag %x fails err = %d\n",
tmf, sc, rqi, req_id, tag, ret);
} else {
SNIC_SCSI_DBG(snic->shost,
- "issu_tmreq: Queuing ITMF(%d) Req, sc %p, rqi %p, req_id %d tag %x - Success.\n",
+ "issu_tmreq: Queueing ITMF(%d) Req, sc %p, rqi %p, req_id %d tag %x - Success.\n",
tmf, sc, rqi, req_id, tag);
}
diff --git a/drivers/scsi/snic/vnic_cq.c b/drivers/scsi/snic/vnic_cq.c
index 4c8e64e..3455dd7 100644
--- a/drivers/scsi/snic/vnic_cq.c
+++ b/drivers/scsi/snic/vnic_cq.c
@@ -31,8 +31,6 @@
int svnic_cq_alloc(struct vnic_dev *vdev, struct vnic_cq *cq,
unsigned int index, unsigned int desc_count, unsigned int desc_size)
{
- int err;
-
cq->index = index;
cq->vdev = vdev;
@@ -43,11 +41,7 @@
return -EINVAL;
}
- err = svnic_dev_alloc_desc_ring(vdev, &cq->ring, desc_count, desc_size);
- if (err)
- return err;
-
- return 0;
+ return svnic_dev_alloc_desc_ring(vdev, &cq->ring, desc_count, desc_size);
}
void svnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable,
diff --git a/drivers/scsi/snic/vnic_devcmd.h b/drivers/scsi/snic/vnic_devcmd.h
index d81b4f0..0e0fa38 100644
--- a/drivers/scsi/snic/vnic_devcmd.h
+++ b/drivers/scsi/snic/vnic_devcmd.h
@@ -208,7 +208,7 @@
struct vnic_devcmd_provinfo {
u8 oui[3];
u8 type;
- u8 data[0];
+ u8 data[];
};
/*
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 279dea6..4644184 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -38,6 +38,7 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/bio.h>
+#include <linux/compat.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/cdrom.h>
@@ -50,6 +51,8 @@
#include <linux/pm_runtime.h>
#include <linux/uaccess.h>
+#include <asm/unaligned.h>
+
#include <scsi/scsi.h>
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_device.h>
@@ -78,7 +81,6 @@
CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \
CDC_MRW|CDC_MRW_W|CDC_RAM)
-static DEFINE_MUTEX(sr_mutex);
static int sr_probe(struct device *);
static int sr_remove(struct device *);
static blk_status_t sr_init_command(struct scsi_cmnd *SCpnt);
@@ -346,10 +348,8 @@
case ILLEGAL_REQUEST:
if (!(SCpnt->sense_buffer[0] & 0x90))
break;
- error_sector = (SCpnt->sense_buffer[3] << 24) |
- (SCpnt->sense_buffer[4] << 16) |
- (SCpnt->sense_buffer[5] << 8) |
- SCpnt->sense_buffer[6];
+ error_sector =
+ get_unaligned_be32(&SCpnt->sense_buffer[3]);
if (SCpnt->request->bio != NULL)
block_sectors =
bio_sectors(SCpnt->request->bio);
@@ -394,15 +394,11 @@
struct request *rq = SCpnt->request;
blk_status_t ret;
- ret = scsi_init_io(SCpnt);
+ ret = scsi_alloc_sgtables(SCpnt);
if (ret != BLK_STS_OK)
- goto out;
+ return ret;
cd = scsi_cd(rq->rq_disk);
- /* from here on until we're complete, any goto out
- * is used for a killable error condition */
- ret = BLK_STS_IOERR;
-
SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt,
"Doing sr request, block = %d\n", block));
@@ -497,13 +493,9 @@
SCpnt->sdb.length = this_count * s_size;
}
- SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
- SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
- SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff;
- SCpnt->cmnd[5] = (unsigned char) block & 0xff;
+ put_unaligned_be32(block, &SCpnt->cmnd[2]);
SCpnt->cmnd[6] = SCpnt->cmnd[9] = 0;
- SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff;
- SCpnt->cmnd[8] = (unsigned char) this_count & 0xff;
+ put_unaligned_be16(this_count, &SCpnt->cmnd[7]);
/*
* We shouldn't disconnect in the middle of a sector, so with a dumb
@@ -513,14 +505,26 @@
SCpnt->transfersize = cd->device->sector_size;
SCpnt->underflow = this_count << 9;
SCpnt->allowed = MAX_RETRIES;
+ SCpnt->cmd_len = 10;
/*
- * This indicates that the command is ready from our end to be
- * queued.
+ * This indicates that the command is ready from our end to be queued.
*/
- ret = BLK_STS_OK;
+ return BLK_STS_OK;
out:
- return ret;
+ scsi_free_sgtables(SCpnt);
+ return BLK_STS_IOERR;
+}
+
+static void sr_revalidate_disk(struct scsi_cd *cd)
+{
+ struct scsi_sense_hdr sshdr;
+
+ /* if the unit is not ready, nothing more to do */
+ if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr))
+ return;
+ sr_cd_check(&cd->cdi);
+ get_sectorsize(cd);
}
static int sr_block_open(struct block_device *bdev, fmode_t mode)
@@ -535,11 +539,12 @@
sdev = cd->device;
scsi_autopm_get_device(sdev);
- check_disk_change(bdev);
+ if (bdev_check_media_change(bdev))
+ sr_revalidate_disk(cd);
- mutex_lock(&sr_mutex);
+ mutex_lock(&cd->lock);
ret = cdrom_open(&cd->cdi, bdev, mode);
- mutex_unlock(&sr_mutex);
+ mutex_unlock(&cd->lock);
scsi_autopm_put_device(sdev);
if (ret)
@@ -552,10 +557,12 @@
static void sr_block_release(struct gendisk *disk, fmode_t mode)
{
struct scsi_cd *cd = scsi_cd(disk);
- mutex_lock(&sr_mutex);
+
+ mutex_lock(&cd->lock);
cdrom_release(&cd->cdi, mode);
+ mutex_unlock(&cd->lock);
+
scsi_cd_put(cd);
- mutex_unlock(&sr_mutex);
}
static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
@@ -566,7 +573,7 @@
void __user *argp = (void __user *)arg;
int ret;
- mutex_lock(&sr_mutex);
+ mutex_lock(&cd->lock);
ret = scsi_ioctl_block_when_processing_errors(sdev, cmd,
(mode & FMODE_NDELAY) != 0);
@@ -596,10 +603,55 @@
scsi_autopm_put_device(sdev);
out:
- mutex_unlock(&sr_mutex);
+ mutex_unlock(&cd->lock);
return ret;
}
+#ifdef CONFIG_COMPAT
+static int sr_block_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
+ unsigned long arg)
+{
+ struct scsi_cd *cd = scsi_cd(bdev->bd_disk);
+ struct scsi_device *sdev = cd->device;
+ void __user *argp = compat_ptr(arg);
+ int ret;
+
+ mutex_lock(&cd->lock);
+
+ ret = scsi_ioctl_block_when_processing_errors(sdev, cmd,
+ (mode & FMODE_NDELAY) != 0);
+ if (ret)
+ goto out;
+
+ scsi_autopm_get_device(sdev);
+
+ /*
+ * Send SCSI addressing ioctls directly to mid level, send other
+ * ioctls to cdrom/block level.
+ */
+ switch (cmd) {
+ case SCSI_IOCTL_GET_IDLUN:
+ case SCSI_IOCTL_GET_BUS_NUMBER:
+ ret = scsi_compat_ioctl(sdev, cmd, argp);
+ goto put;
+ }
+
+ ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, (unsigned long)argp);
+ if (ret != -ENOSYS)
+ goto put;
+
+ ret = scsi_compat_ioctl(sdev, cmd, argp);
+
+put:
+ scsi_autopm_put_device(sdev);
+
+out:
+ mutex_unlock(&cd->lock);
+ return ret;
+
+}
+#endif
+
static unsigned int sr_block_check_events(struct gendisk *disk,
unsigned int clearing)
{
@@ -617,38 +669,16 @@
return ret;
}
-static int sr_block_revalidate_disk(struct gendisk *disk)
-{
- struct scsi_sense_hdr sshdr;
- struct scsi_cd *cd;
-
- cd = scsi_cd_get(disk);
- if (!cd)
- return -ENXIO;
-
- /* if the unit is not ready, nothing more to do */
- if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr))
- goto out;
-
- sr_cd_check(&cd->cdi);
- get_sectorsize(cd);
-out:
- scsi_cd_put(cd);
- return 0;
-}
-
static const struct block_device_operations sr_bdops =
{
.owner = THIS_MODULE,
.open = sr_block_open,
.release = sr_block_release,
.ioctl = sr_block_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = sr_block_compat_ioctl,
+#endif
.check_events = sr_block_check_events,
- .revalidate_disk = sr_block_revalidate_disk,
- /*
- * No compat_ioctl for now because sr_block_ioctl never
- * seems to pass arbitrary ioctls down to host drivers.
- */
};
static int sr_open(struct cdrom_device_info *cdi, int purpose)
@@ -702,6 +732,7 @@
disk = alloc_disk(1);
if (!disk)
goto fail_free;
+ mutex_init(&cd->lock);
spin_lock(&sr_index_lock);
minor = find_first_zero_bit(sr_index_bits, SR_DISKS);
@@ -749,9 +780,8 @@
set_capacity(disk, cd->capacity);
disk->private_data = &cd->driver;
disk->queue = sdev->request_queue;
- cd->cdi.disk = disk;
- if (register_cdrom(&cd->cdi))
+ if (register_cdrom(disk, &cd->cdi))
goto fail_minor;
/*
@@ -762,6 +792,7 @@
dev_set_drvdata(dev, cd);
disk->flags |= GENHD_FL_REMOVABLE;
+ sr_revalidate_disk(cd);
device_add_disk(&sdev->sdev_gendev, disk, NULL);
sdev_printk(KERN_DEBUG, sdev,
@@ -776,6 +807,7 @@
spin_unlock(&sr_index_lock);
fail_put:
put_disk(disk);
+ mutex_destroy(&cd->lock);
fail_free:
kfree(cd);
fail:
@@ -813,8 +845,7 @@
} else {
long last_written;
- cd->capacity = 1 + ((buffer[0] << 24) | (buffer[1] << 16) |
- (buffer[2] << 8) | buffer[3]);
+ cd->capacity = 1 + get_unaligned_be32(&buffer[0]);
/*
* READ_CAPACITY doesn't return the correct size on
* certain UDF media. If last_written is larger, use
@@ -825,8 +856,7 @@
if (!cdrom_get_last_written(&cd->cdi, &last_written))
cd->capacity = max_t(long, cd->capacity, last_written);
- sector_size = (buffer[4] << 24) |
- (buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
+ sector_size = get_unaligned_be32(&buffer[4]);
switch (sector_size) {
/*
* HP 4020i CD-Recorder reports 2340 byte sectors
@@ -838,10 +868,10 @@
case 2340:
case 2352:
sector_size = 2048;
- /* fall through */
+ fallthrough;
case 2048:
cd->capacity *= 4;
- /* fall through */
+ fallthrough;
case 512:
break;
default:
@@ -887,7 +917,7 @@
/* allocate transfer buffer */
- buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+ buffer = kmalloc(512, GFP_KERNEL);
if (!buffer) {
sr_printk(KERN_ERR, cd, "out of memory.\n");
return;
@@ -900,7 +930,7 @@
rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, ms_len,
SR_TIMEOUT, 3, &data, NULL);
- if (!scsi_status_is_good(rc) || data.length > ms_len ||
+ if (rc < 0 || data.length > ms_len ||
data.header_length + data.block_descriptor_length > data.length) {
/* failed, drive doesn't have capabilities mode page */
cd->cdi.speed = 1;
@@ -914,13 +944,13 @@
}
n = data.header_length + data.block_descriptor_length;
- cd->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176;
+ cd->cdi.speed = get_unaligned_be16(&buffer[n + 8]) / 176;
cd->readcd_known = 1;
cd->readcd_cdda = buffer[n + 5] & 0x01;
/* print some capability bits */
sr_printk(KERN_INFO, cd,
"scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n",
- ((buffer[n + 14] << 8) + buffer[n + 15]) / 176,
+ get_unaligned_be16(&buffer[n + 14]) / 176,
cd->cdi.speed,
buffer[n + 3] & 0x01 ? "writer " : "", /* CD Writer */
buffer[n + 3] & 0x20 ? "dvd-ram " : "",
@@ -1016,6 +1046,8 @@
put_disk(disk);
+ mutex_destroy(&cd->lock);
+
kfree(cd);
}
diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h
index a2bb7b8..339c624 100644
--- a/drivers/scsi/sr.h
+++ b/drivers/scsi/sr.h
@@ -20,6 +20,7 @@
#include <linux/genhd.h>
#include <linux/kref.h>
+#include <linux/mutex.h>
#define MAX_RETRIES 3
#define SR_TIMEOUT (30 * HZ)
@@ -51,6 +52,7 @@
bool ignore_get_event:1; /* GET_EVENT is unreliable, use TUR */
struct cdrom_device_info cdi;
+ struct mutex lock;
/* We hold gendisk and scsi_device references on probe and use
* the refs on this kref to decide when to release them */
struct kref kref;
diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
index b9db2ec..a616353 100644
--- a/drivers/scsi/sr_vendor.c
+++ b/drivers/scsi/sr_vendor.c
@@ -61,6 +61,7 @@
#define VENDOR_NEC 2
#define VENDOR_TOSHIBA 3
#define VENDOR_WRITER 4 /* pre-scsi3 writers */
+#define VENDOR_CYGNAL_85ED 5 /* CD-on-a-chip */
#define VENDOR_TIMEOUT 30*HZ
@@ -96,6 +97,23 @@
} else if (!strncmp(vendor, "TOSHIBA", 7)) {
cd->vendor = VENDOR_TOSHIBA;
+ } else if (!strncmp(vendor, "Beurer", 6) &&
+ !strncmp(model, "Gluco Memory", 12)) {
+ /* The Beurer GL50 evo uses a Cygnal-manufactured CD-on-a-chip
+ that only accepts a subset of SCSI commands. Most of the
+ not-implemented commands are fine to fail, but a few,
+ particularly around the MMC or Audio commands, will put the
+ device into an unrecoverable state, so they need to be
+ avoided at all costs.
+ */
+ cd->vendor = VENDOR_CYGNAL_85ED;
+ cd->cdi.mask |= (
+ CDC_MULTI_SESSION |
+ CDC_CLOSE_TRAY | CDC_OPEN_TRAY |
+ CDC_LOCK |
+ CDC_GENERIC_PACKET |
+ CDC_PLAY_AUDIO
+ );
}
}
@@ -113,7 +131,7 @@
if (cd->vendor == VENDOR_TOSHIBA)
density = (blocklength > 2048) ? 0x81 : 0x83;
- buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+ buffer = kmalloc(512, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
@@ -161,7 +179,7 @@
if (cd->cdi.mask & CDC_MULTI_SESSION)
return 0;
- buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+ buffer = kmalloc(512, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 2121e44..19bc8c9 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
SCSI Tape Driver for Linux version 1.1 and newer. See the accompanying
- file Documentation/scsi/st.txt for more information.
+ file Documentation/scsi/st.rst for more information.
History:
Rewritten from Dwayne Forsyth's SCSI tape driver by Kai Makisara.
@@ -22,6 +22,7 @@
#include <linux/module.h>
+#include <linux/compat.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/sched/signal.h>
@@ -44,6 +45,7 @@
#include <linux/uaccess.h>
#include <asm/dma.h>
+#include <asm/unaligned.h>
#include <scsi/scsi.h>
#include <scsi/scsi_dbg.h>
@@ -337,14 +339,14 @@
switch (sense[0] & 0x7f) {
case 0x71:
s->deferred = 1;
- /* fall through */
+ fallthrough;
case 0x70:
s->fixed_format = 1;
s->flags = sense[2] & 0xe0;
break;
case 0x73:
s->deferred = 1;
- /* fall through */
+ fallthrough;
case 0x72:
s->fixed_format = 0;
ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
@@ -1455,7 +1457,6 @@
accessing this tape. */
static int st_release(struct inode *inode, struct file *filp)
{
- int result = 0;
struct scsi_tape *STp = filp->private_data;
if (STp->door_locked == ST_LOCKED_AUTO)
@@ -1468,9 +1469,9 @@
scsi_autopm_put_device(STp->device);
scsi_tape_put(STp);
- return result;
+ return 0;
}
-
+
/* The checks common to both reading and writing */
static ssize_t rw_checks(struct scsi_tape *STp, struct file *filp, size_t count)
{
@@ -2679,8 +2680,7 @@
if (!debugging)
return;
- sc = cmd[2] & 0x80 ? 0xff000000 : 0;
- sc |= (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
+ sc = sign_extend32(get_unaligned_be24(&cmd[2]), 23);
if (direction)
sc = -sc;
st_printk(ST_DEB_MSG, STp, "Spacing tape %s over %d %s.\n",
@@ -2723,7 +2723,7 @@
switch (cmd_in) {
case MTFSFM:
chg_eof = 0; /* Changed from the FSF after this */
- /* fall through */
+ fallthrough;
case MTFSF:
cmd[0] = SPACE;
cmd[1] = 0x01; /* Space FileMarks */
@@ -2738,7 +2738,7 @@
break;
case MTBSFM:
chg_eof = 0; /* Changed from the FSF after this */
- /* fall through */
+ fallthrough;
case MTBSF:
cmd[0] = SPACE;
cmd[1] = 0x01; /* Space FileMarks */
@@ -3500,7 +3500,7 @@
/* The ioctl command */
-static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
+static long st_ioctl_common(struct file *file, unsigned int cmd_in, void __user *p)
{
int i, cmd_nr, cmd_type, bt;
int retval = 0;
@@ -3508,7 +3508,6 @@
struct scsi_tape *STp = file->private_data;
struct st_modedef *STm;
struct st_partstat *STps;
- void __user *p = (void __user *)arg;
if (mutex_lock_interruptible(&STp->lock))
return -ERESTARTSYS;
@@ -3800,14 +3799,11 @@
if (STp->cleaning_req)
mt_status.mt_gstat |= GMT_CLN(0xffffffff);
- i = copy_to_user(p, &mt_status, sizeof(struct mtget));
- if (i) {
- retval = (-EFAULT);
+ retval = put_user_mtget(p, &mt_status);
+ if (retval)
goto out;
- }
STp->recover_reg = 0; /* Clear after read */
- retval = 0;
goto out;
} /* End of MTIOCGET */
if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
@@ -3821,16 +3817,24 @@
goto out;
}
mt_pos.mt_blkno = blk;
- i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
- if (i)
- retval = (-EFAULT);
+ retval = put_user_mtpos(p, &mt_pos);
goto out;
}
mutex_unlock(&STp->lock);
switch (cmd_in) {
+ case SCSI_IOCTL_STOP_UNIT:
+ /* unload */
+ retval = scsi_ioctl(STp->device, cmd_in, p);
+ if (!retval) {
+ STp->rew_at_close = 0;
+ STp->ready = ST_NO_TAPE;
+ }
+ return retval;
+
case SCSI_IOCTL_GET_IDLUN:
case SCSI_IOCTL_GET_BUS_NUMBER:
break;
+
default:
if ((cmd_in == SG_IO ||
cmd_in == SCSI_IOCTL_SEND_COMMAND ||
@@ -3844,30 +3848,46 @@
return i;
break;
}
- retval = scsi_ioctl(STp->device, cmd_in, p);
- if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) { /* unload */
- STp->rew_at_close = 0;
- STp->ready = ST_NO_TAPE;
- }
- return retval;
+ return -ENOTTY;
out:
mutex_unlock(&STp->lock);
return retval;
}
-#ifdef CONFIG_COMPAT
-static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
{
+ void __user *p = (void __user *)arg;
struct scsi_tape *STp = file->private_data;
- struct scsi_device *sdev = STp->device;
- int ret = -ENOIOCTLCMD;
- if (sdev->host->hostt->compat_ioctl) {
+ int ret;
- ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
+ ret = st_ioctl_common(file, cmd_in, p);
+ if (ret != -ENOTTY)
+ return ret;
+ return scsi_ioctl(STp->device, cmd_in, p);
+}
+
+#ifdef CONFIG_COMPAT
+static long st_compat_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
+{
+ void __user *p = compat_ptr(arg);
+ struct scsi_tape *STp = file->private_data;
+ int ret;
+
+ /* argument conversion is handled using put_user_mtpos/put_user_mtget */
+ switch (cmd_in) {
+ case MTIOCPOS32:
+ return st_ioctl_common(file, MTIOCPOS, p);
+ case MTIOCGET32:
+ return st_ioctl_common(file, MTIOCGET, p);
}
- return ret;
+
+ ret = st_ioctl_common(file, cmd_in, p);
+ if (ret != -ENOTTY)
+ return ret;
+
+ return scsi_compat_ioctl(STp->device, cmd_in, p);
}
#endif
@@ -4901,7 +4921,7 @@
unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
unsigned long start = uaddr >> PAGE_SHIFT;
const int nr_pages = end - start;
- int res, i, j;
+ int res, i;
struct page **pages;
struct rq_map_data *mdata = &STbp->map_data;
@@ -4923,7 +4943,7 @@
/* Try to fault in all of the necessary pages */
/* rw==READ means read from drive, write into memory area */
- res = get_user_pages_fast(uaddr, nr_pages, rw == READ ? FOLL_WRITE : 0,
+ res = pin_user_pages_fast(uaddr, nr_pages, rw == READ ? FOLL_WRITE : 0,
pages);
/* Errors and no page mapped should return here */
@@ -4943,8 +4963,7 @@
return nr_pages;
out_unmap:
if (res > 0) {
- for (j=0; j < res; j++)
- put_page(pages[j]);
+ unpin_user_pages(pages, res);
res = 0;
}
kfree(pages);
@@ -4956,18 +4975,9 @@
static int sgl_unmap_user_pages(struct st_buffer *STbp,
const unsigned int nr_pages, int dirtied)
{
- int i;
+ /* FIXME: cache flush missing for rw==READ */
+ unpin_user_pages_dirty_lock(STbp->mapped_pages, nr_pages, dirtied);
- for (i=0; i < nr_pages; i++) {
- struct page *page = STbp->mapped_pages[i];
-
- if (dirtied)
- SetPageDirty(page);
- /* FIXME: cache flush missing for rw==READ
- * FIXME: call the correct reference counting function
- */
- put_page(page);
- }
kfree(STbp->mapped_pages);
STbp->mapped_pages = NULL;
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 33287b6..d4f10c0 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -236,7 +236,7 @@
u8 data_dir;
u8 payload_sz; /* payload size in 4-byte, not used */
u8 cdb[STEX_CDB_LENGTH];
- u32 variable[0];
+ u32 variable[];
};
struct status_msg {
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 5087ed6..0ee0b80 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -462,6 +462,11 @@
* Mask of CPUs bound to subchannels.
*/
struct cpumask alloced_cpus;
+ /*
+ * Serializes modifications of stor_chns[] from storvsc_do_io()
+ * and storvsc_change_target_cpu().
+ */
+ spinlock_t lock;
/* Used for vsc/vsp channel reset process */
struct storvsc_cmd_request init_request;
struct storvsc_cmd_request reset_request;
@@ -621,6 +626,64 @@
}
+static void storvsc_change_target_cpu(struct vmbus_channel *channel, u32 old,
+ u32 new)
+{
+ struct storvsc_device *stor_device;
+ struct vmbus_channel *cur_chn;
+ bool old_is_alloced = false;
+ struct hv_device *device;
+ unsigned long flags;
+ int cpu;
+
+ device = channel->primary_channel ?
+ channel->primary_channel->device_obj
+ : channel->device_obj;
+ stor_device = get_out_stor_device(device);
+ if (!stor_device)
+ return;
+
+ /* See storvsc_do_io() -> get_og_chn(). */
+ spin_lock_irqsave(&stor_device->lock, flags);
+
+ /*
+ * Determines if the storvsc device has other channels assigned to
+ * the "old" CPU to update the alloced_cpus mask and the stor_chns
+ * array.
+ */
+ if (device->channel != channel && device->channel->target_cpu == old) {
+ cur_chn = device->channel;
+ old_is_alloced = true;
+ goto old_is_alloced;
+ }
+ list_for_each_entry(cur_chn, &device->channel->sc_list, sc_list) {
+ if (cur_chn == channel)
+ continue;
+ if (cur_chn->target_cpu == old) {
+ old_is_alloced = true;
+ goto old_is_alloced;
+ }
+ }
+
+old_is_alloced:
+ if (old_is_alloced)
+ WRITE_ONCE(stor_device->stor_chns[old], cur_chn);
+ else
+ cpumask_clear_cpu(old, &stor_device->alloced_cpus);
+
+ /* "Flush" the stor_chns array. */
+ for_each_possible_cpu(cpu) {
+ if (stor_device->stor_chns[cpu] && !cpumask_test_cpu(
+ cpu, &stor_device->alloced_cpus))
+ WRITE_ONCE(stor_device->stor_chns[cpu], NULL);
+ }
+
+ WRITE_ONCE(stor_device->stor_chns[new], channel);
+ cpumask_set_cpu(new, &stor_device->alloced_cpus);
+
+ spin_unlock_irqrestore(&stor_device->lock, flags);
+}
+
static void handle_sc_creation(struct vmbus_channel *new_sc)
{
struct hv_device *device = new_sc->primary_channel->device_obj;
@@ -648,6 +711,8 @@
return;
}
+ new_sc->change_target_cpu_callback = storvsc_change_target_cpu;
+
/* Add the sub-channel to the array of available channels. */
stor_device->stor_chns[new_sc->target_cpu] = new_sc;
cpumask_set_cpu(new_sc->target_cpu, &stor_device->alloced_cpus);
@@ -876,6 +941,8 @@
if (stor_device->stor_chns == NULL)
return -ENOMEM;
+ device->channel->change_target_cpu_callback = storvsc_change_target_cpu;
+
stor_device->stor_chns[device->channel->target_cpu] = device->channel;
cpumask_set_cpu(device->channel->target_cpu,
&stor_device->alloced_cpus);
@@ -927,17 +994,40 @@
struct storvsc_scan_work *wrk;
void (*process_err_fn)(struct work_struct *work);
struct hv_host_device *host_dev = shost_priv(host);
- bool do_work = false;
- switch (SRB_STATUS(vm_srb->srb_status)) {
- case SRB_STATUS_ERROR:
+ /*
+ * In some situations, Hyper-V sets multiple bits in the
+ * srb_status, such as ABORTED and ERROR. So process them
+ * individually, with the most specific bits first.
+ */
+
+ if (vm_srb->srb_status & SRB_STATUS_INVALID_LUN) {
+ set_host_byte(scmnd, DID_NO_CONNECT);
+ process_err_fn = storvsc_remove_lun;
+ goto do_work;
+ }
+
+ if (vm_srb->srb_status & SRB_STATUS_ABORTED) {
+ if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID &&
+ /* Capacity data has changed */
+ (asc == 0x2a) && (ascq == 0x9)) {
+ process_err_fn = storvsc_device_scan;
+ /*
+ * Retry the I/O that triggered this.
+ */
+ set_host_byte(scmnd, DID_REQUEUE);
+ goto do_work;
+ }
+ }
+
+ if (vm_srb->srb_status & SRB_STATUS_ERROR) {
/*
* Let upper layer deal with error when
* sense message is present.
*/
-
if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID)
- break;
+ return;
+
/*
* If there is an error; offline the device since all
* error recovery strategies would have already been
@@ -950,37 +1040,19 @@
set_host_byte(scmnd, DID_PASSTHROUGH);
break;
/*
- * On Some Windows hosts TEST_UNIT_READY command can return
- * SRB_STATUS_ERROR, let the upper level code deal with it
- * based on the sense information.
+ * On some Hyper-V hosts TEST_UNIT_READY command can
+ * return SRB_STATUS_ERROR. Let the upper level code
+ * deal with it based on the sense information.
*/
case TEST_UNIT_READY:
break;
default:
set_host_byte(scmnd, DID_ERROR);
}
- break;
- case SRB_STATUS_INVALID_LUN:
- set_host_byte(scmnd, DID_NO_CONNECT);
- do_work = true;
- process_err_fn = storvsc_remove_lun;
- break;
- case SRB_STATUS_ABORTED:
- if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID &&
- (asc == 0x2a) && (ascq == 0x9)) {
- do_work = true;
- process_err_fn = storvsc_device_scan;
- /*
- * Retry the I/O that trigerred this.
- */
- set_host_byte(scmnd, DID_REQUEUE);
- }
- break;
}
+ return;
- if (!do_work)
- return;
-
+do_work:
/*
* We need to schedule work to process this error; schedule it.
*/
@@ -1038,6 +1110,10 @@
data_transfer_length = 0;
}
+ /* Validate data_transfer_length (from Hyper-V) */
+ if (data_transfer_length > cmd_request->payload->range.len)
+ data_transfer_length = cmd_request->payload->range.len;
+
scsi_set_resid(scmnd,
cmd_request->payload->range.len - data_transfer_length);
@@ -1078,6 +1154,11 @@
/* Copy over the status...etc */
stor_pkt->vm_srb.scsi_status = vstor_packet->vm_srb.scsi_status;
stor_pkt->vm_srb.srb_status = vstor_packet->vm_srb.srb_status;
+
+ /* Validate sense_info_length (from Hyper-V) */
+ if (vstor_packet->vm_srb.sense_info_length > sense_buffer_size)
+ vstor_packet->vm_srb.sense_info_length = sense_buffer_size;
+
stor_pkt->vm_srb.sense_info_length =
vstor_packet->vm_srb.sense_info_length;
@@ -1248,8 +1329,10 @@
const struct cpumask *node_mask;
int num_channels, tgt_cpu;
- if (stor_device->num_sc == 0)
+ if (stor_device->num_sc == 0) {
+ stor_device->stor_chns[q_num] = stor_device->device->channel;
return stor_device->device->channel;
+ }
/*
* Our channel array is sparsley populated and we
@@ -1258,7 +1341,6 @@
* The strategy is simple:
* I. Ensure NUMA locality
* II. Distribute evenly (best effort)
- * III. Mapping is persistent.
*/
node_mask = cpumask_of_node(cpu_to_node(q_num));
@@ -1268,8 +1350,10 @@
if (cpumask_test_cpu(tgt_cpu, node_mask))
num_channels++;
}
- if (num_channels == 0)
+ if (num_channels == 0) {
+ stor_device->stor_chns[q_num] = stor_device->device->channel;
return stor_device->device->channel;
+ }
hash_qnum = q_num;
while (hash_qnum >= num_channels)
@@ -1295,6 +1379,7 @@
struct storvsc_device *stor_device;
struct vstor_packet *vstor_packet;
struct vmbus_channel *outgoing_channel, *channel;
+ unsigned long flags;
int ret = 0;
const struct cpumask *node_mask;
int tgt_cpu;
@@ -1308,10 +1393,11 @@
request->device = device;
/*
- * Select an an appropriate channel to send the request out.
+ * Select an appropriate channel to send the request out.
*/
- if (stor_device->stor_chns[q_num] != NULL) {
- outgoing_channel = stor_device->stor_chns[q_num];
+ /* See storvsc_change_target_cpu(). */
+ outgoing_channel = READ_ONCE(stor_device->stor_chns[q_num]);
+ if (outgoing_channel != NULL) {
if (outgoing_channel->target_cpu == q_num) {
/*
* Ideally, we want to pick a different channel if
@@ -1324,7 +1410,10 @@
continue;
if (tgt_cpu == q_num)
continue;
- channel = stor_device->stor_chns[tgt_cpu];
+ channel = READ_ONCE(
+ stor_device->stor_chns[tgt_cpu]);
+ if (channel == NULL)
+ continue;
if (hv_get_avail_to_write_percent(
&channel->outbound)
> ring_avail_percent_lowater) {
@@ -1350,7 +1439,10 @@
for_each_cpu(tgt_cpu, &stor_device->alloced_cpus) {
if (cpumask_test_cpu(tgt_cpu, node_mask))
continue;
- channel = stor_device->stor_chns[tgt_cpu];
+ channel = READ_ONCE(
+ stor_device->stor_chns[tgt_cpu]);
+ if (channel == NULL)
+ continue;
if (hv_get_avail_to_write_percent(
&channel->outbound)
> ring_avail_percent_lowater) {
@@ -1360,7 +1452,14 @@
}
}
} else {
+ spin_lock_irqsave(&stor_device->lock, flags);
+ outgoing_channel = stor_device->stor_chns[q_num];
+ if (outgoing_channel != NULL) {
+ spin_unlock_irqrestore(&stor_device->lock, flags);
+ goto found_channel;
+ }
outgoing_channel = get_og_chn(stor_device, q_num);
+ spin_unlock_irqrestore(&stor_device->lock, flags);
}
found_channel:
@@ -1485,6 +1584,7 @@
request = &stor_device->reset_request;
vstor_packet = &request->vstor_packet;
+ memset(vstor_packet, 0, sizeof(struct vstor_packet));
init_completion(&request->wait_event);
@@ -1588,6 +1688,7 @@
/* Setup the cmd request */
cmd_request->cmd = scmnd;
+ memset(&cmd_request->vstor_packet, 0, sizeof(struct vstor_packet));
vm_srb = &cmd_request->vstor_packet.vm_srb;
vm_srb->win8_extension.time_out_value = 60;
@@ -1643,23 +1744,65 @@
payload_sz = sizeof(cmd_request->mpb);
if (sg_count) {
- if (sg_count > MAX_PAGE_BUFFER_COUNT) {
+ unsigned int hvpgoff = 0;
+ unsigned long offset_in_hvpg = sgl->offset & ~HV_HYP_PAGE_MASK;
+ unsigned int hvpg_count = HVPFN_UP(offset_in_hvpg + length);
+ u64 hvpfn;
- payload_sz = (sg_count * sizeof(u64) +
+ if (hvpg_count > MAX_PAGE_BUFFER_COUNT) {
+
+ payload_sz = (hvpg_count * sizeof(u64) +
sizeof(struct vmbus_packet_mpb_array));
payload = kzalloc(payload_sz, GFP_ATOMIC);
if (!payload)
return SCSI_MLQUEUE_DEVICE_BUSY;
}
+ /*
+ * sgl is a list of PAGEs, and payload->range.pfn_array
+ * expects the page number in the unit of HV_HYP_PAGE_SIZE (the
+ * page size that Hyper-V uses, so here we need to divide PAGEs
+ * into HV_HYP_PAGE in case that PAGE_SIZE > HV_HYP_PAGE_SIZE.
+ * Besides, payload->range.offset should be the offset in one
+ * HV_HYP_PAGE.
+ */
payload->range.len = length;
- payload->range.offset = sgl[0].offset;
+ payload->range.offset = offset_in_hvpg;
+ hvpgoff = sgl->offset >> HV_HYP_PAGE_SHIFT;
cur_sgl = sgl;
- for (i = 0; i < sg_count; i++) {
- payload->range.pfn_array[i] =
- page_to_pfn(sg_page((cur_sgl)));
- cur_sgl = sg_next(cur_sgl);
+ for (i = 0; i < hvpg_count; i++) {
+ /*
+ * 'i' is the index of hv pages in the payload and
+ * 'hvpgoff' is the offset (in hv pages) of the first
+ * hv page in the the first page. The relationship
+ * between the sum of 'i' and 'hvpgoff' and the offset
+ * (in hv pages) in a payload page ('hvpgoff_in_page')
+ * is as follow:
+ *
+ * |------------------ PAGE -------------------|
+ * | NR_HV_HYP_PAGES_IN_PAGE hvpgs in total |
+ * |hvpg|hvpg| ... |hvpg|... |hvpg|
+ * ^ ^ ^ ^
+ * +-hvpgoff-+ +-hvpgoff_in_page-+
+ * ^ |
+ * +--------------------- i ---------------------------+
+ */
+ unsigned int hvpgoff_in_page =
+ (i + hvpgoff) % NR_HV_HYP_PAGES_IN_PAGE;
+
+ /*
+ * Two cases that we need to fetch a page:
+ * 1) i == 0, the first step or
+ * 2) hvpgoff_in_page == 0, when we reach the boundary
+ * of a page.
+ */
+ if (hvpgoff_in_page == 0 || i == 0) {
+ hvpfn = page_to_hvpfn(sg_page(cur_sgl));
+ cur_sgl = sg_next(cur_sgl);
+ }
+
+ payload->range.pfn_array[i] = hvpfn + hvpgoff_in_page;
}
}
@@ -1727,6 +1870,13 @@
MODULE_DEVICE_TABLE(vmbus, id_table);
+static const struct { guid_t guid; } fc_guid = { HV_SYNTHFC_GUID };
+
+static bool hv_dev_is_fc(struct hv_device *hv_dev)
+{
+ return guid_equal(&fc_guid.guid, &hv_dev->dev_type);
+}
+
static int storvsc_probe(struct hv_device *device,
const struct hv_vmbus_device_id *dev_id)
{
@@ -1794,6 +1944,7 @@
init_waitqueue_head(&stor_device->waiting_to_drain);
stor_device->device = device;
stor_device->host = host;
+ spin_lock_init(&stor_device->lock);
hv_set_drvdata(device, stor_device);
stor_device->port_number = host->host_no;
@@ -1848,8 +1999,10 @@
alloc_ordered_workqueue("storvsc_error_wq_%d",
WQ_MEM_RECLAIM,
host->host_no);
- if (!host_dev->handle_error_wq)
+ if (!host_dev->handle_error_wq) {
+ ret = -ENOMEM;
goto err_out2;
+ }
INIT_WORK(&host_dev->host_scan_work, storvsc_host_scan);
/* Register the HBA and start the scsi bus scan */
ret = scsi_add_host(host, &device->device);
@@ -1936,11 +2089,42 @@
return 0;
}
+static int storvsc_suspend(struct hv_device *hv_dev)
+{
+ struct storvsc_device *stor_device = hv_get_drvdata(hv_dev);
+ struct Scsi_Host *host = stor_device->host;
+ struct hv_host_device *host_dev = shost_priv(host);
+
+ storvsc_wait_to_drain(stor_device);
+
+ drain_workqueue(host_dev->handle_error_wq);
+
+ vmbus_close(hv_dev->channel);
+
+ kfree(stor_device->stor_chns);
+ stor_device->stor_chns = NULL;
+
+ cpumask_clear(&stor_device->alloced_cpus);
+
+ return 0;
+}
+
+static int storvsc_resume(struct hv_device *hv_dev)
+{
+ int ret;
+
+ ret = storvsc_connect_to_vsp(hv_dev, storvsc_ringbuffer_size,
+ hv_dev_is_fc(hv_dev));
+ return ret;
+}
+
static struct hv_driver storvsc_drv = {
.name = KBUILD_MODNAME,
.id_table = id_table,
.probe = storvsc_probe,
.remove = storvsc_remove,
+ .suspend = storvsc_suspend,
+ .resume = storvsc_resume,
.driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c
index 701b842..2e3fbc2 100644
--- a/drivers/scsi/sun3_scsi.c
+++ b/drivers/scsi/sun3_scsi.c
@@ -397,12 +397,12 @@
case CSR_LEFT_3:
*vaddr = (dregs->bpack_lo & 0xff00) >> 8;
vaddr--;
- /* Fall through */
+ fallthrough;
case CSR_LEFT_2:
*vaddr = (dregs->bpack_hi & 0x00ff);
vaddr--;
- /* Fall through */
+ fallthrough;
case CSR_LEFT_1:
*vaddr = (dregs->bpack_hi & 0xff00) >> 8;
diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
index f8b1e57..d3489ac 100644
--- a/drivers/scsi/sun3x_esp.c
+++ b/drivers/scsi/sun3x_esp.c
@@ -190,7 +190,7 @@
if (!res || !res->start)
goto fail_unlink;
- esp->regs = ioremap_nocache(res->start, 0x20);
+ esp->regs = ioremap(res->start, 0x20);
if (!esp->regs)
goto fail_unmap_regs;
@@ -198,7 +198,7 @@
if (!res || !res->start)
goto fail_unmap_regs;
- esp->dma_regs = ioremap_nocache(res->start, 0x10);
+ esp->dma_regs = ioremap(res->start, 0x10);
esp->command_block = dma_alloc_coherent(esp->dev, 16,
&esp->command_block_dma,
@@ -272,22 +272,10 @@
.name = "sun3x_esp",
},
};
-
-static int __init sun3x_esp_init(void)
-{
- return platform_driver_register(&esp_sun3x_driver);
-}
-
-static void __exit sun3x_esp_exit(void)
-{
- platform_driver_unregister(&esp_sun3x_driver);
-}
+module_platform_driver(esp_sun3x_driver);
MODULE_DESCRIPTION("Sun3x ESP SCSI driver");
MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-
-module_init(sun3x_esp_init);
-module_exit(sun3x_esp_exit);
MODULE_ALIAS("platform:sun3x_esp");
diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c
index 964130d..5dc38d3 100644
--- a/drivers/scsi/sun_esp.c
+++ b/drivers/scsi/sun_esp.c
@@ -606,21 +606,9 @@
.probe = esp_sbus_probe,
.remove = esp_sbus_remove,
};
-
-static int __init sunesp_init(void)
-{
- return platform_driver_register(&esp_sbus_driver);
-}
-
-static void __exit sunesp_exit(void)
-{
- platform_driver_unregister(&esp_sbus_driver);
-}
+module_platform_driver(esp_sbus_driver);
MODULE_DESCRIPTION("Sun ESP SCSI driver");
MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-
-module_init(sunesp_init);
-module_exit(sunesp_exit);
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c
index 6d7651a..c536d2a 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw.c
+++ b/drivers/scsi/sym53c8xx_2/sym_fw.c
@@ -369,7 +369,7 @@
sym_name(np), (int) (cur-start));
++cur;
continue;
- };
+ }
/*
* We use the bogus value 0xf00ff00f ;-)
@@ -477,7 +477,7 @@
default:
relocs = 0;
break;
- };
+ }
/*
* Scriptify:) the opcode.
@@ -523,7 +523,7 @@
new = old;
break;
}
- /* fall through */
+ fallthrough;
default:
new = 0;
panic("sym_fw_bind_script: "
@@ -533,5 +533,5 @@
*cur++ = cpu_to_scr(new);
}
- };
+ }
}
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 2ca018c..d9a045f 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -156,12 +156,8 @@
static int sym_xerr_cam_status(int cam_status, int x_status)
{
if (x_status) {
- if (x_status & XE_PARITY_ERR)
+ if (x_status & XE_PARITY_ERR)
cam_status = DID_PARITY;
- else if (x_status &(XE_EXTRA_DATA|XE_SODL_UNRUN|XE_SWIDE_OVRUN))
- cam_status = DID_ERROR;
- else if (x_status & XE_BAD_PHASE)
- cam_status = DID_ERROR;
else
cam_status = DID_ERROR;
}
@@ -1743,7 +1739,7 @@
* @state: current state of the PCI slot
*/
static pci_ers_result_t sym2_io_error_detected(struct pci_dev *pdev,
- enum pci_channel_state state)
+ pci_channel_state_t state)
{
/* If slot is permanently frozen, turn everything off */
if (state == pci_channel_io_perm_failure) {
@@ -1774,6 +1770,7 @@
/**
* sym2_reset_workarounds - hardware-specific work-arounds
+ * @pdev: pointer to PCI device
*
* This routine is similar to sym_set_workarounds(), except
* that, at this point, we already know that the device was
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index a428cae..a9fe092 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -3059,7 +3059,7 @@
sym_print_addr(cp->cmd, "%s\n",
s_status == S_BUSY ? "BUSY" : "QUEUE FULL\n");
}
- /* fall through */
+ fallthrough;
default: /* S_INT, S_INT_COND_MET, S_CONFLICT */
sym_complete_error (np, cp);
break;
@@ -4620,7 +4620,7 @@
* Negotiation failed.
* Target does not want answer message.
*/
- /* fall through */
+ fallthrough;
case SIR_NEGO_PROTO:
sym_nego_default(np, tp, cp);
goto out;
@@ -5352,8 +5352,10 @@
{
struct scsi_device *sdev;
struct scsi_cmnd *cmd;
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
struct sym_tcb *tp;
struct sym_lcb *lp;
+#endif
int resid;
int i;
@@ -5370,11 +5372,13 @@
cp->host_status, cp->ssss_status, cp->host_flags);
}
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
/*
* Get target and lun pointers.
*/
tp = &np->target[cp->target];
lp = sym_lp(tp, sdev->lun);
+#endif
/*
* Check for extended errors.
@@ -5481,8 +5485,10 @@
*/
void sym_complete_ok (struct sym_hcb *np, struct sym_ccb *cp)
{
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
struct sym_tcb *tp;
struct sym_lcb *lp;
+#endif
struct scsi_cmnd *cmd;
int resid;
@@ -5498,11 +5504,13 @@
*/
cmd = cp->cmd;
+#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
/*
* Get target and lun pointers.
*/
tp = &np->target[cp->target];
lp = sym_lp(tp, cp->lun);
+#endif
/*
* If all data have been transferred, given than no
@@ -5648,7 +5656,7 @@
/*
* Allocate the array of lists of CCBs hashed by DSA.
*/
- np->ccbh = kcalloc(CCB_HASH_SIZE, sizeof(struct sym_ccb **), GFP_KERNEL);
+ np->ccbh = kcalloc(CCB_HASH_SIZE, sizeof(*np->ccbh), GFP_KERNEL);
if (!np->ccbh)
goto attach_failed;
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c
index 9dc17f1..e13d535 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.c
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c
@@ -227,7 +227,7 @@
/*
* 24C16 EEPROM reading.
*
- * GPOI0 - data in/data out
+ * GPIO0 - data in/data out
* GPIO1 - clock
* Symbios NVRAM wiring now also used by Tekram.
*/
@@ -524,7 +524,7 @@
/*
* 93C46 EEPROM reading.
*
- * GPOI0 - data in
+ * GPIO0 - data in
* GPIO1 - data out
* GPIO2 - clock
* GPIO4 - chip select
@@ -695,7 +695,7 @@
data, len);
if (!x)
break;
- /* fall through */
+ fallthrough;
default:
x = sym_read_T93C46_nvram(np, nvram);
break;
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 0b845ab..c339517 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -38,7 +38,7 @@
select PM_DEVFREQ
select DEVFREQ_GOV_SIMPLE_ONDEMAND
select NLS
- ---help---
+ help
This selects the support for UFS devices in Linux, say Y and make
sure that you know the name of your UFS host adapter (the card
inside your computer that "speaks" the UFS protocol, also
@@ -46,14 +46,14 @@
The module will be called ufshcd.
To compile this driver as a module, choose M here and read
- <file:Documentation/scsi/ufs.txt>.
+ <file:Documentation/scsi/ufs.rst>.
However, do not compile this as a module if your root file system
(the one containing the directory /) is located on a UFS device.
config SCSI_UFSHCD_PCI
tristate "PCI bus based UFS Controller support"
depends on SCSI_UFSHCD && PCI
- ---help---
+ help
This selects the PCI UFS Host Controller Interface. Select this if
you have UFS Host Controller with PCI Interface.
@@ -64,7 +64,7 @@
config SCSI_UFS_DWC_TC_PCI
tristate "DesignWare pci support using a G210 Test Chip"
depends on SCSI_UFSHCD_PCI
- ---help---
+ help
Synopsys Test Chip is a PHY for prototyping purposes.
If unsure, say N.
@@ -72,7 +72,8 @@
config SCSI_UFSHCD_PLATFORM
tristate "Platform bus based UFS Controller support"
depends on SCSI_UFSHCD
- ---help---
+ depends on HAS_IOMEM
+ help
This selects the UFS host controller support. Select this if
you have an UFS controller on Platform bus.
@@ -91,7 +92,7 @@
config SCSI_UFS_DWC_TC_PLATFORM
tristate "DesignWare platform support using a G210 Test Chip"
depends on SCSI_UFSHCD_PLATFORM
- ---help---
+ help
Synopsys Test Chip is a PHY for prototyping purposes.
If unsure, say N.
@@ -99,6 +100,7 @@
config SCSI_UFS_QCOM
tristate "QCOM specific hooks to UFS controller platform driver"
depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM
+ select QCOM_SCM
select RESET_CONTROLLER
help
This selects the QCOM specific additions to UFSHCD platform driver.
@@ -126,12 +128,22 @@
config SCSI_UFS_HISI
tristate "Hisilicon specific hooks to UFS controller platform driver"
depends on (ARCH_HISI || COMPILE_TEST) && SCSI_UFSHCD_PLATFORM
- ---help---
+ help
This selects the Hisilicon specific additions to UFSHCD platform driver.
Select this if you have UFS controller on Hisilicon chipset.
If unsure, say N.
+config SCSI_UFS_TI_J721E
+ tristate "TI glue layer for Cadence UFS Controller"
+ depends on OF && HAS_IOMEM && (ARCH_K3 || COMPILE_TEST)
+ help
+ This selects driver for TI glue layer for Cadence UFS Host
+ Controller IP.
+
+ Selects this if you have TI platform with UFS controller.
+ If unsure, say N.
+
config SCSI_UFS_BSG
bool "Universal Flash Storage BSG device node"
depends on SCSI_UFSHCD
@@ -150,3 +162,23 @@
Select this if you need a bsg device node for your UFS controller.
If unsure, say N.
+
+config SCSI_UFS_EXYNOS
+ tristate "EXYNOS specific hooks to UFS controller platform driver"
+ depends on SCSI_UFSHCD_PLATFORM && (ARCH_EXYNOS || COMPILE_TEST)
+ help
+ This selects the EXYNOS specific additions to UFSHCD platform driver.
+ UFS host on EXYNOS includes HCI and UNIPRO layer, and associates with
+ UFS-PHY driver.
+
+ Select this if you have UFS host controller on EXYNOS chipset.
+ If unsure, say N.
+
+config SCSI_UFS_CRYPTO
+ bool "UFS Crypto Engine Support"
+ depends on SCSI_UFSHCD && BLK_INLINE_ENCRYPTION
+ help
+ Enable Crypto Engine Support in UFS.
+ Enabling this makes it possible for the kernel to use the crypto
+ capabilities of the UFS device (if present) to perform crypto
+ operations on data being transferred to/from the device.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 2a90979..4679af1 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -3,11 +3,16 @@
obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o
obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o
obj-$(CONFIG_SCSI_UFS_CDNS_PLATFORM) += cdns-pltfrm.o
-obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
+obj-$(CONFIG_SCSI_UFS_QCOM) += ufs_qcom.o
+ufs_qcom-y += ufs-qcom.o
+ufs_qcom-$(CONFIG_SCSI_UFS_CRYPTO) += ufs-qcom-ice.o
+obj-$(CONFIG_SCSI_UFS_EXYNOS) += ufs-exynos.o
obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o
ufshcd-core-y += ufshcd.o ufs-sysfs.o
ufshcd-core-$(CONFIG_SCSI_UFS_BSG) += ufs_bsg.o
+ufshcd-core-$(CONFIG_SCSI_UFS_CRYPTO) += ufshcd-crypto.o
obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o
obj-$(CONFIG_SCSI_UFS_MEDIATEK) += ufs-mediatek.o
+obj-$(CONFIG_SCSI_UFS_TI_J721E) += ti-j721e-ufs.o
diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c
index 6feeb0f..da065a2 100644
--- a/drivers/scsi/ufs/cdns-pltfrm.c
+++ b/drivers/scsi/ufs/cdns-pltfrm.c
@@ -19,6 +19,85 @@
#define CDNS_UFS_REG_HCLKDIV 0xFC
#define CDNS_UFS_REG_PHY_XCFGD1 0x113C
+#define CDNS_UFS_MAX_L4_ATTRS 12
+
+struct cdns_ufs_host {
+ /**
+ * cdns_ufs_dme_attr_val - for storing L4 attributes
+ */
+ u32 cdns_ufs_dme_attr_val[CDNS_UFS_MAX_L4_ATTRS];
+};
+
+/**
+ * cdns_ufs_get_l4_attr - get L4 attributes on local side
+ * @hba: per adapter instance
+ *
+ */
+static void cdns_ufs_get_l4_attr(struct ufs_hba *hba)
+{
+ struct cdns_ufs_host *host = ufshcd_get_variant(hba);
+
+ ufshcd_dme_get(hba, UIC_ARG_MIB(T_PEERDEVICEID),
+ &host->cdns_ufs_dme_attr_val[0]);
+ ufshcd_dme_get(hba, UIC_ARG_MIB(T_PEERCPORTID),
+ &host->cdns_ufs_dme_attr_val[1]);
+ ufshcd_dme_get(hba, UIC_ARG_MIB(T_TRAFFICCLASS),
+ &host->cdns_ufs_dme_attr_val[2]);
+ ufshcd_dme_get(hba, UIC_ARG_MIB(T_PROTOCOLID),
+ &host->cdns_ufs_dme_attr_val[3]);
+ ufshcd_dme_get(hba, UIC_ARG_MIB(T_CPORTFLAGS),
+ &host->cdns_ufs_dme_attr_val[4]);
+ ufshcd_dme_get(hba, UIC_ARG_MIB(T_TXTOKENVALUE),
+ &host->cdns_ufs_dme_attr_val[5]);
+ ufshcd_dme_get(hba, UIC_ARG_MIB(T_RXTOKENVALUE),
+ &host->cdns_ufs_dme_attr_val[6]);
+ ufshcd_dme_get(hba, UIC_ARG_MIB(T_LOCALBUFFERSPACE),
+ &host->cdns_ufs_dme_attr_val[7]);
+ ufshcd_dme_get(hba, UIC_ARG_MIB(T_PEERBUFFERSPACE),
+ &host->cdns_ufs_dme_attr_val[8]);
+ ufshcd_dme_get(hba, UIC_ARG_MIB(T_CREDITSTOSEND),
+ &host->cdns_ufs_dme_attr_val[9]);
+ ufshcd_dme_get(hba, UIC_ARG_MIB(T_CPORTMODE),
+ &host->cdns_ufs_dme_attr_val[10]);
+ ufshcd_dme_get(hba, UIC_ARG_MIB(T_CONNECTIONSTATE),
+ &host->cdns_ufs_dme_attr_val[11]);
+}
+
+/**
+ * cdns_ufs_set_l4_attr - set L4 attributes on local side
+ * @hba: per adapter instance
+ *
+ */
+static void cdns_ufs_set_l4_attr(struct ufs_hba *hba)
+{
+ struct cdns_ufs_host *host = ufshcd_get_variant(hba);
+
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE), 0);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERDEVICEID),
+ host->cdns_ufs_dme_attr_val[0]);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERCPORTID),
+ host->cdns_ufs_dme_attr_val[1]);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_TRAFFICCLASS),
+ host->cdns_ufs_dme_attr_val[2]);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_PROTOCOLID),
+ host->cdns_ufs_dme_attr_val[3]);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_CPORTFLAGS),
+ host->cdns_ufs_dme_attr_val[4]);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_TXTOKENVALUE),
+ host->cdns_ufs_dme_attr_val[5]);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_RXTOKENVALUE),
+ host->cdns_ufs_dme_attr_val[6]);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_LOCALBUFFERSPACE),
+ host->cdns_ufs_dme_attr_val[7]);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERBUFFERSPACE),
+ host->cdns_ufs_dme_attr_val[8]);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_CREDITSTOSEND),
+ host->cdns_ufs_dme_attr_val[9]);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_CPORTMODE),
+ host->cdns_ufs_dme_attr_val[10]);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE),
+ host->cdns_ufs_dme_attr_val[11]);
+}
/**
* Sets HCLKDIV register value based on the core_clk
@@ -78,6 +157,22 @@
}
/**
+ * Called around hibern8 enter/exit.
+ * @hba: host controller instance
+ * @cmd: UIC Command
+ * @status: notify stage (pre, post change)
+ *
+ */
+static void cdns_ufs_hibern8_notify(struct ufs_hba *hba, enum uic_cmd_dme cmd,
+ enum ufs_notify_change_status status)
+{
+ if (status == PRE_CHANGE && cmd == UIC_CMD_DME_HIBER_ENTER)
+ cdns_ufs_get_l4_attr(hba);
+ if (status == POST_CHANGE && cmd == UIC_CMD_DME_HIBER_EXIT)
+ cdns_ufs_set_l4_attr(hba);
+}
+
+/**
* Called before and after Link startup is carried out.
* @hba: host controller instance
* @status: notify stage (pre, post change)
@@ -97,7 +192,7 @@
* and device TX LCC are disabled once link startup is
* completed.
*/
- ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0);
+ ufshcd_disable_host_tx_lcc(hba);
/*
* Disabling Autohibern8 feature in cadence UFS
@@ -117,6 +212,14 @@
static int cdns_ufs_init(struct ufs_hba *hba)
{
int status = 0;
+ struct cdns_ufs_host *host;
+ struct device *dev = hba->dev;
+
+ host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
+
+ if (!host)
+ return -ENOMEM;
+ ufshcd_set_variant(hba, host);
if (hba->vops && hba->vops->phy_initialization)
status = hba->vops->phy_initialization(hba);
@@ -144,8 +247,10 @@
static const struct ufs_hba_variant_ops cdns_ufs_pltfm_hba_vops = {
.name = "cdns-ufs-pltfm",
+ .init = cdns_ufs_init,
.hce_enable_notify = cdns_ufs_hce_enable_notify,
.link_startup_notify = cdns_ufs_link_startup_notify,
+ .hibern8_notify = cdns_ufs_hibern8_notify,
};
static const struct ufs_hba_variant_ops cdns_ufs_m31_16nm_pltfm_hba_vops = {
@@ -154,6 +259,7 @@
.hce_enable_notify = cdns_ufs_hce_enable_notify,
.link_startup_notify = cdns_ufs_link_startup_notify,
.phy_initialization = cdns_ufs_m31_16nm_phy_initialization,
+ .hibern8_notify = cdns_ufs_hibern8_notify,
};
static const struct of_device_id cdns_ufs_of_match[] = {
@@ -219,6 +325,7 @@
static struct platform_driver cdns_ufs_pltfrm_driver = {
.probe = cdns_ufs_pltfrm_probe,
.remove = cdns_ufs_pltfrm_remove,
+ .shutdown = ufshcd_pltfrm_shutdown,
.driver = {
.name = "cdns-ufshcd",
.pm = &cdns_ufs_dev_pm_ops,
diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c b/drivers/scsi/ufs/tc-dwc-g210-pci.c
index 67a6a61..4e47148 100644
--- a/drivers/scsi/ufs/tc-dwc-g210-pci.c
+++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c
@@ -135,7 +135,6 @@
return err;
}
- pci_set_drvdata(pdev, hba);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_allow(&pdev->dev);
diff --git a/drivers/scsi/ufs/ti-j721e-ufs.c b/drivers/scsi/ufs/ti-j721e-ufs.c
new file mode 100644
index 0000000..eafe0db
--- /dev/null
+++ b/drivers/scsi/ufs/ti-j721e-ufs.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+//
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#define TI_UFS_SS_CTRL 0x4
+#define TI_UFS_SS_RST_N_PCS BIT(0)
+#define TI_UFS_SS_CLK_26MHZ BIT(4)
+
+static int ti_j721e_ufs_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ unsigned long clk_rate;
+ void __iomem *regbase;
+ struct clk *clk;
+ u32 reg = 0;
+ int ret;
+
+ regbase = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(regbase))
+ return PTR_ERR(regbase);
+
+ pm_runtime_enable(dev);
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(dev);
+ goto disable_pm;
+ }
+
+ /* Select MPHY refclk frequency */
+ clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ dev_err(dev, "Cannot claim MPHY clock.\n");
+ goto clk_err;
+ }
+ clk_rate = clk_get_rate(clk);
+ if (clk_rate == 26000000)
+ reg |= TI_UFS_SS_CLK_26MHZ;
+ devm_clk_put(dev, clk);
+
+ /* Take UFS slave device out of reset */
+ reg |= TI_UFS_SS_RST_N_PCS;
+ writel(reg, regbase + TI_UFS_SS_CTRL);
+
+ ret = of_platform_populate(pdev->dev.of_node, NULL, NULL,
+ dev);
+ if (ret) {
+ dev_err(dev, "failed to populate child nodes %d\n", ret);
+ goto clk_err;
+ }
+
+ return ret;
+
+clk_err:
+ pm_runtime_put_sync(dev);
+disable_pm:
+ pm_runtime_disable(dev);
+ return ret;
+}
+
+static int ti_j721e_ufs_remove(struct platform_device *pdev)
+{
+ of_platform_depopulate(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+static const struct of_device_id ti_j721e_ufs_of_match[] = {
+ {
+ .compatible = "ti,j721e-ufs",
+ },
+ { },
+};
+
+static struct platform_driver ti_j721e_ufs_driver = {
+ .probe = ti_j721e_ufs_probe,
+ .remove = ti_j721e_ufs_remove,
+ .driver = {
+ .name = "ti-j721e-ufs",
+ .of_match_table = ti_j721e_ufs_of_match,
+ },
+};
+module_platform_driver(ti_j721e_ufs_driver);
+
+MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>");
+MODULE_DESCRIPTION("TI UFS host controller glue driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c
new file mode 100644
index 0000000..0246ea9
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-exynos.c
@@ -0,0 +1,1301 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * UFS Host Controller driver for Exynos specific extensions
+ *
+ * Copyright (C) 2014-2015 Samsung Electronics Co., Ltd.
+ * Author: Seungwon Jeon <essuuj@gmail.com>
+ * Author: Alim Akhtar <alim.akhtar@samsung.com>
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+#include "ufshcd.h"
+#include "ufshcd-pltfrm.h"
+#include "ufshci.h"
+#include "unipro.h"
+
+#include "ufs-exynos.h"
+
+/*
+ * Exynos's Vendor specific registers for UFSHCI
+ */
+#define HCI_TXPRDT_ENTRY_SIZE 0x00
+#define PRDT_PREFECT_EN BIT(31)
+#define PRDT_SET_SIZE(x) ((x) & 0x1F)
+#define HCI_RXPRDT_ENTRY_SIZE 0x04
+#define HCI_1US_TO_CNT_VAL 0x0C
+#define CNT_VAL_1US_MASK 0x3FF
+#define HCI_UTRL_NEXUS_TYPE 0x40
+#define HCI_UTMRL_NEXUS_TYPE 0x44
+#define HCI_SW_RST 0x50
+#define UFS_LINK_SW_RST BIT(0)
+#define UFS_UNIPRO_SW_RST BIT(1)
+#define UFS_SW_RST_MASK (UFS_UNIPRO_SW_RST | UFS_LINK_SW_RST)
+#define HCI_DATA_REORDER 0x60
+#define HCI_UNIPRO_APB_CLK_CTRL 0x68
+#define UNIPRO_APB_CLK(v, x) (((v) & ~0xF) | ((x) & 0xF))
+#define HCI_AXIDMA_RWDATA_BURST_LEN 0x6C
+#define HCI_GPIO_OUT 0x70
+#define HCI_ERR_EN_PA_LAYER 0x78
+#define HCI_ERR_EN_DL_LAYER 0x7C
+#define HCI_ERR_EN_N_LAYER 0x80
+#define HCI_ERR_EN_T_LAYER 0x84
+#define HCI_ERR_EN_DME_LAYER 0x88
+#define HCI_CLKSTOP_CTRL 0xB0
+#define REFCLK_STOP BIT(2)
+#define UNIPRO_MCLK_STOP BIT(1)
+#define UNIPRO_PCLK_STOP BIT(0)
+#define CLK_STOP_MASK (REFCLK_STOP |\
+ UNIPRO_MCLK_STOP |\
+ UNIPRO_PCLK_STOP)
+#define HCI_MISC 0xB4
+#define REFCLK_CTRL_EN BIT(7)
+#define UNIPRO_PCLK_CTRL_EN BIT(6)
+#define UNIPRO_MCLK_CTRL_EN BIT(5)
+#define HCI_CORECLK_CTRL_EN BIT(4)
+#define CLK_CTRL_EN_MASK (REFCLK_CTRL_EN |\
+ UNIPRO_PCLK_CTRL_EN |\
+ UNIPRO_MCLK_CTRL_EN)
+/* Device fatal error */
+#define DFES_ERR_EN BIT(31)
+#define DFES_DEF_L2_ERRS (UIC_DATA_LINK_LAYER_ERROR_RX_BUF_OF |\
+ UIC_DATA_LINK_LAYER_ERROR_PA_INIT)
+#define DFES_DEF_L3_ERRS (UIC_NETWORK_UNSUPPORTED_HEADER_TYPE |\
+ UIC_NETWORK_BAD_DEVICEID_ENC |\
+ UIC_NETWORK_LHDR_TRAP_PACKET_DROPPING)
+#define DFES_DEF_L4_ERRS (UIC_TRANSPORT_UNSUPPORTED_HEADER_TYPE |\
+ UIC_TRANSPORT_UNKNOWN_CPORTID |\
+ UIC_TRANSPORT_NO_CONNECTION_RX |\
+ UIC_TRANSPORT_BAD_TC)
+
+enum {
+ UNIPRO_L1_5 = 0,/* PHY Adapter */
+ UNIPRO_L2, /* Data Link */
+ UNIPRO_L3, /* Network */
+ UNIPRO_L4, /* Transport */
+ UNIPRO_DME, /* DME */
+};
+
+/*
+ * UNIPRO registers
+ */
+#define UNIPRO_COMP_VERSION 0x000
+#define UNIPRO_DME_PWR_REQ 0x090
+#define UNIPRO_DME_PWR_REQ_POWERMODE 0x094
+#define UNIPRO_DME_PWR_REQ_LOCALL2TIMER0 0x098
+#define UNIPRO_DME_PWR_REQ_LOCALL2TIMER1 0x09C
+#define UNIPRO_DME_PWR_REQ_LOCALL2TIMER2 0x0A0
+#define UNIPRO_DME_PWR_REQ_REMOTEL2TIMER0 0x0A4
+#define UNIPRO_DME_PWR_REQ_REMOTEL2TIMER1 0x0A8
+#define UNIPRO_DME_PWR_REQ_REMOTEL2TIMER2 0x0AC
+
+/*
+ * UFS Protector registers
+ */
+#define UFSPRSECURITY 0x010
+#define NSSMU BIT(14)
+#define UFSPSBEGIN0 0x200
+#define UFSPSEND0 0x204
+#define UFSPSLUN0 0x208
+#define UFSPSCTRL0 0x20C
+
+#define CNTR_DIV_VAL 40
+
+static void exynos_ufs_auto_ctrl_hcc(struct exynos_ufs *ufs, bool en);
+static void exynos_ufs_ctrl_clkstop(struct exynos_ufs *ufs, bool en);
+
+static inline void exynos_ufs_enable_auto_ctrl_hcc(struct exynos_ufs *ufs)
+{
+ exynos_ufs_auto_ctrl_hcc(ufs, true);
+}
+
+static inline void exynos_ufs_disable_auto_ctrl_hcc(struct exynos_ufs *ufs)
+{
+ exynos_ufs_auto_ctrl_hcc(ufs, false);
+}
+
+static inline void exynos_ufs_disable_auto_ctrl_hcc_save(
+ struct exynos_ufs *ufs, u32 *val)
+{
+ *val = hci_readl(ufs, HCI_MISC);
+ exynos_ufs_auto_ctrl_hcc(ufs, false);
+}
+
+static inline void exynos_ufs_auto_ctrl_hcc_restore(
+ struct exynos_ufs *ufs, u32 *val)
+{
+ hci_writel(ufs, *val, HCI_MISC);
+}
+
+static inline void exynos_ufs_gate_clks(struct exynos_ufs *ufs)
+{
+ exynos_ufs_ctrl_clkstop(ufs, true);
+}
+
+static inline void exynos_ufs_ungate_clks(struct exynos_ufs *ufs)
+{
+ exynos_ufs_ctrl_clkstop(ufs, false);
+}
+
+static int exynos7_ufs_drv_init(struct device *dev, struct exynos_ufs *ufs)
+{
+ return 0;
+}
+
+static int exynos7_ufs_pre_link(struct exynos_ufs *ufs)
+{
+ struct ufs_hba *hba = ufs->hba;
+ u32 val = ufs->drv_data->uic_attr->pa_dbg_option_suite;
+ int i;
+
+ exynos_ufs_enable_ov_tm(hba);
+ for_each_ufs_tx_lane(ufs, i)
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x297, i), 0x17);
+ for_each_ufs_rx_lane(ufs, i) {
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x362, i), 0xff);
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x363, i), 0x00);
+ }
+ exynos_ufs_disable_ov_tm(hba);
+
+ for_each_ufs_tx_lane(ufs, i)
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(TX_HIBERN8_CONTROL, i), 0x0);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_TXPHY_CFGUPDT), 0x1);
+ udelay(1);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OPTION_SUITE), val | (1 << 12));
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_SKIP_RESET_PHY), 0x1);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_SKIP_LINE_RESET), 0x1);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_LINE_RESET_REQ), 0x1);
+ udelay(1600);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OPTION_SUITE), val);
+
+ return 0;
+}
+
+static int exynos7_ufs_post_link(struct exynos_ufs *ufs)
+{
+ struct ufs_hba *hba = ufs->hba;
+ int i;
+
+ exynos_ufs_enable_ov_tm(hba);
+ for_each_ufs_tx_lane(ufs, i) {
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x28b, i), 0x83);
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x29a, i), 0x07);
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x277, i),
+ TX_LINERESET_N(exynos_ufs_calc_time_cntr(ufs, 200000)));
+ }
+ exynos_ufs_disable_ov_tm(hba);
+
+ exynos_ufs_enable_dbg_mode(hba);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_SAVECONFIGTIME), 0xbb8);
+ exynos_ufs_disable_dbg_mode(hba);
+
+ return 0;
+}
+
+static int exynos7_ufs_pre_pwr_change(struct exynos_ufs *ufs,
+ struct ufs_pa_layer_attr *pwr)
+{
+ unipro_writel(ufs, 0x22, UNIPRO_DBG_FORCE_DME_CTRL_STATE);
+
+ return 0;
+}
+
+static int exynos7_ufs_post_pwr_change(struct exynos_ufs *ufs,
+ struct ufs_pa_layer_attr *pwr)
+{
+ struct ufs_hba *hba = ufs->hba;
+ int lanes = max_t(u32, pwr->lane_rx, pwr->lane_tx);
+
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_RXPHY_CFGUPDT), 0x1);
+
+ if (lanes == 1) {
+ exynos_ufs_enable_dbg_mode(hba);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), 0x1);
+ exynos_ufs_disable_dbg_mode(hba);
+ }
+
+ return 0;
+}
+
+/*
+ * exynos_ufs_auto_ctrl_hcc - HCI core clock control by h/w
+ * Control should be disabled in the below cases
+ * - Before host controller S/W reset
+ * - Access to UFS protector's register
+ */
+static void exynos_ufs_auto_ctrl_hcc(struct exynos_ufs *ufs, bool en)
+{
+ u32 misc = hci_readl(ufs, HCI_MISC);
+
+ if (en)
+ hci_writel(ufs, misc | HCI_CORECLK_CTRL_EN, HCI_MISC);
+ else
+ hci_writel(ufs, misc & ~HCI_CORECLK_CTRL_EN, HCI_MISC);
+}
+
+static void exynos_ufs_ctrl_clkstop(struct exynos_ufs *ufs, bool en)
+{
+ u32 ctrl = hci_readl(ufs, HCI_CLKSTOP_CTRL);
+ u32 misc = hci_readl(ufs, HCI_MISC);
+
+ if (en) {
+ hci_writel(ufs, misc | CLK_CTRL_EN_MASK, HCI_MISC);
+ hci_writel(ufs, ctrl | CLK_STOP_MASK, HCI_CLKSTOP_CTRL);
+ } else {
+ hci_writel(ufs, ctrl & ~CLK_STOP_MASK, HCI_CLKSTOP_CTRL);
+ hci_writel(ufs, misc & ~CLK_CTRL_EN_MASK, HCI_MISC);
+ }
+}
+
+static int exynos_ufs_get_clk_info(struct exynos_ufs *ufs)
+{
+ struct ufs_hba *hba = ufs->hba;
+ struct list_head *head = &hba->clk_list_head;
+ struct ufs_clk_info *clki;
+ unsigned long pclk_rate;
+ u32 f_min, f_max;
+ u8 div = 0;
+ int ret = 0;
+
+ if (list_empty(head))
+ goto out;
+
+ list_for_each_entry(clki, head, list) {
+ if (!IS_ERR(clki->clk)) {
+ if (!strcmp(clki->name, "core_clk"))
+ ufs->clk_hci_core = clki->clk;
+ else if (!strcmp(clki->name, "sclk_unipro_main"))
+ ufs->clk_unipro_main = clki->clk;
+ }
+ }
+
+ if (!ufs->clk_hci_core || !ufs->clk_unipro_main) {
+ dev_err(hba->dev, "failed to get clk info\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ufs->mclk_rate = clk_get_rate(ufs->clk_unipro_main);
+ pclk_rate = clk_get_rate(ufs->clk_hci_core);
+ f_min = ufs->pclk_avail_min;
+ f_max = ufs->pclk_avail_max;
+
+ if (ufs->opts & EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL) {
+ do {
+ pclk_rate /= (div + 1);
+
+ if (pclk_rate <= f_max)
+ break;
+ div++;
+ } while (pclk_rate >= f_min);
+ }
+
+ if (unlikely(pclk_rate < f_min || pclk_rate > f_max)) {
+ dev_err(hba->dev, "not available pclk range %lu\n", pclk_rate);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ufs->pclk_rate = pclk_rate;
+ ufs->pclk_div = div;
+
+out:
+ return ret;
+}
+
+static void exynos_ufs_set_unipro_pclk_div(struct exynos_ufs *ufs)
+{
+ if (ufs->opts & EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL) {
+ u32 val;
+
+ val = hci_readl(ufs, HCI_UNIPRO_APB_CLK_CTRL);
+ hci_writel(ufs, UNIPRO_APB_CLK(val, ufs->pclk_div),
+ HCI_UNIPRO_APB_CLK_CTRL);
+ }
+}
+
+static void exynos_ufs_set_pwm_clk_div(struct exynos_ufs *ufs)
+{
+ struct ufs_hba *hba = ufs->hba;
+ struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr;
+
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB(CMN_PWM_CLK_CTRL), attr->cmn_pwm_clk_ctrl);
+}
+
+static void exynos_ufs_calc_pwm_clk_div(struct exynos_ufs *ufs)
+{
+ struct ufs_hba *hba = ufs->hba;
+ struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr;
+ const unsigned int div = 30, mult = 20;
+ const unsigned long pwm_min = 3 * 1000 * 1000;
+ const unsigned long pwm_max = 9 * 1000 * 1000;
+ const int divs[] = {32, 16, 8, 4};
+ unsigned long clk = 0, _clk, clk_period;
+ int i = 0, clk_idx = -1;
+
+ clk_period = UNIPRO_PCLK_PERIOD(ufs);
+ for (i = 0; i < ARRAY_SIZE(divs); i++) {
+ _clk = NSEC_PER_SEC * mult / (clk_period * divs[i] * div);
+ if (_clk >= pwm_min && _clk <= pwm_max) {
+ if (_clk > clk) {
+ clk_idx = i;
+ clk = _clk;
+ }
+ }
+ }
+
+ if (clk_idx == -1) {
+ ufshcd_dme_get(hba, UIC_ARG_MIB(CMN_PWM_CLK_CTRL), &clk_idx);
+ dev_err(hba->dev,
+ "failed to decide pwm clock divider, will not change\n");
+ }
+
+ attr->cmn_pwm_clk_ctrl = clk_idx & PWM_CLK_CTRL_MASK;
+}
+
+long exynos_ufs_calc_time_cntr(struct exynos_ufs *ufs, long period)
+{
+ const int precise = 10;
+ long pclk_rate = ufs->pclk_rate;
+ long clk_period, fraction;
+
+ clk_period = UNIPRO_PCLK_PERIOD(ufs);
+ fraction = ((NSEC_PER_SEC % pclk_rate) * precise) / pclk_rate;
+
+ return (period * precise) / ((clk_period * precise) + fraction);
+}
+
+static void exynos_ufs_specify_phy_time_attr(struct exynos_ufs *ufs)
+{
+ struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr;
+ struct ufs_phy_time_cfg *t_cfg = &ufs->t_cfg;
+
+ t_cfg->tx_linereset_p =
+ exynos_ufs_calc_time_cntr(ufs, attr->tx_dif_p_nsec);
+ t_cfg->tx_linereset_n =
+ exynos_ufs_calc_time_cntr(ufs, attr->tx_dif_n_nsec);
+ t_cfg->tx_high_z_cnt =
+ exynos_ufs_calc_time_cntr(ufs, attr->tx_high_z_cnt_nsec);
+ t_cfg->tx_base_n_val =
+ exynos_ufs_calc_time_cntr(ufs, attr->tx_base_unit_nsec);
+ t_cfg->tx_gran_n_val =
+ exynos_ufs_calc_time_cntr(ufs, attr->tx_gran_unit_nsec);
+ t_cfg->tx_sleep_cnt =
+ exynos_ufs_calc_time_cntr(ufs, attr->tx_sleep_cnt);
+
+ t_cfg->rx_linereset =
+ exynos_ufs_calc_time_cntr(ufs, attr->rx_dif_p_nsec);
+ t_cfg->rx_hibern8_wait =
+ exynos_ufs_calc_time_cntr(ufs, attr->rx_hibern8_wait_nsec);
+ t_cfg->rx_base_n_val =
+ exynos_ufs_calc_time_cntr(ufs, attr->rx_base_unit_nsec);
+ t_cfg->rx_gran_n_val =
+ exynos_ufs_calc_time_cntr(ufs, attr->rx_gran_unit_nsec);
+ t_cfg->rx_sleep_cnt =
+ exynos_ufs_calc_time_cntr(ufs, attr->rx_sleep_cnt);
+ t_cfg->rx_stall_cnt =
+ exynos_ufs_calc_time_cntr(ufs, attr->rx_stall_cnt);
+}
+
+static void exynos_ufs_config_phy_time_attr(struct exynos_ufs *ufs)
+{
+ struct ufs_hba *hba = ufs->hba;
+ struct ufs_phy_time_cfg *t_cfg = &ufs->t_cfg;
+ int i;
+
+ exynos_ufs_set_pwm_clk_div(ufs);
+
+ exynos_ufs_enable_ov_tm(hba);
+
+ for_each_ufs_rx_lane(ufs, i) {
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_FILLER_ENABLE, i),
+ ufs->drv_data->uic_attr->rx_filler_enable);
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_LINERESET_VAL, i),
+ RX_LINERESET(t_cfg->rx_linereset));
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_BASE_NVAL_07_00, i),
+ RX_BASE_NVAL_L(t_cfg->rx_base_n_val));
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_BASE_NVAL_15_08, i),
+ RX_BASE_NVAL_H(t_cfg->rx_base_n_val));
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_GRAN_NVAL_07_00, i),
+ RX_GRAN_NVAL_L(t_cfg->rx_gran_n_val));
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_GRAN_NVAL_10_08, i),
+ RX_GRAN_NVAL_H(t_cfg->rx_gran_n_val));
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_OV_SLEEP_CNT_TIMER, i),
+ RX_OV_SLEEP_CNT(t_cfg->rx_sleep_cnt));
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(RX_OV_STALL_CNT_TIMER, i),
+ RX_OV_STALL_CNT(t_cfg->rx_stall_cnt));
+ }
+
+ for_each_ufs_tx_lane(ufs, i) {
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_LINERESET_P_VAL, i),
+ TX_LINERESET_P(t_cfg->tx_linereset_p));
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_HIGH_Z_CNT_07_00, i),
+ TX_HIGH_Z_CNT_L(t_cfg->tx_high_z_cnt));
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_HIGH_Z_CNT_11_08, i),
+ TX_HIGH_Z_CNT_H(t_cfg->tx_high_z_cnt));
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_BASE_NVAL_07_00, i),
+ TX_BASE_NVAL_L(t_cfg->tx_base_n_val));
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_BASE_NVAL_15_08, i),
+ TX_BASE_NVAL_H(t_cfg->tx_base_n_val));
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_GRAN_NVAL_07_00, i),
+ TX_GRAN_NVAL_L(t_cfg->tx_gran_n_val));
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_GRAN_NVAL_10_08, i),
+ TX_GRAN_NVAL_H(t_cfg->tx_gran_n_val));
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_OV_SLEEP_CNT_TIMER, i),
+ TX_OV_H8_ENTER_EN |
+ TX_OV_SLEEP_CNT(t_cfg->tx_sleep_cnt));
+ ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_MIN_ACTIVATETIME, i),
+ ufs->drv_data->uic_attr->tx_min_activatetime);
+ }
+
+ exynos_ufs_disable_ov_tm(hba);
+}
+
+static void exynos_ufs_config_phy_cap_attr(struct exynos_ufs *ufs)
+{
+ struct ufs_hba *hba = ufs->hba;
+ struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr;
+ int i;
+
+ exynos_ufs_enable_ov_tm(hba);
+
+ for_each_ufs_rx_lane(ufs, i) {
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(RX_HS_G1_SYNC_LENGTH_CAP, i),
+ attr->rx_hs_g1_sync_len_cap);
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(RX_HS_G2_SYNC_LENGTH_CAP, i),
+ attr->rx_hs_g2_sync_len_cap);
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(RX_HS_G3_SYNC_LENGTH_CAP, i),
+ attr->rx_hs_g3_sync_len_cap);
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(RX_HS_G1_PREP_LENGTH_CAP, i),
+ attr->rx_hs_g1_prep_sync_len_cap);
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(RX_HS_G2_PREP_LENGTH_CAP, i),
+ attr->rx_hs_g2_prep_sync_len_cap);
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(RX_HS_G3_PREP_LENGTH_CAP, i),
+ attr->rx_hs_g3_prep_sync_len_cap);
+ }
+
+ if (attr->rx_adv_fine_gran_sup_en == 0) {
+ for_each_ufs_rx_lane(ufs, i) {
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(RX_ADV_GRANULARITY_CAP, i), 0);
+
+ if (attr->rx_min_actv_time_cap)
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(RX_MIN_ACTIVATETIME_CAP,
+ i), attr->rx_min_actv_time_cap);
+
+ if (attr->rx_hibern8_time_cap)
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(RX_HIBERN8TIME_CAP, i),
+ attr->rx_hibern8_time_cap);
+ }
+ } else if (attr->rx_adv_fine_gran_sup_en == 1) {
+ for_each_ufs_rx_lane(ufs, i) {
+ if (attr->rx_adv_fine_gran_step)
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(RX_ADV_GRANULARITY_CAP,
+ i), RX_ADV_FINE_GRAN_STEP(
+ attr->rx_adv_fine_gran_step));
+
+ if (attr->rx_adv_min_actv_time_cap)
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(
+ RX_ADV_MIN_ACTIVATETIME_CAP, i),
+ attr->rx_adv_min_actv_time_cap);
+
+ if (attr->rx_adv_hibern8_time_cap)
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(RX_ADV_HIBERN8TIME_CAP,
+ i),
+ attr->rx_adv_hibern8_time_cap);
+ }
+ }
+
+ exynos_ufs_disable_ov_tm(hba);
+}
+
+static void exynos_ufs_establish_connt(struct exynos_ufs *ufs)
+{
+ struct ufs_hba *hba = ufs->hba;
+ enum {
+ DEV_ID = 0x00,
+ PEER_DEV_ID = 0x01,
+ PEER_CPORT_ID = 0x00,
+ TRAFFIC_CLASS = 0x00,
+ };
+
+ /* allow cport attributes to be set */
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE), CPORT_IDLE);
+
+ /* local unipro attributes */
+ ufshcd_dme_set(hba, UIC_ARG_MIB(N_DEVICEID), DEV_ID);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(N_DEVICEID_VALID), TRUE);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERDEVICEID), PEER_DEV_ID);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERCPORTID), PEER_CPORT_ID);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_CPORTFLAGS), CPORT_DEF_FLAGS);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_TRAFFICCLASS), TRAFFIC_CLASS);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(T_CONNECTIONSTATE), CPORT_CONNECTED);
+}
+
+static void exynos_ufs_config_smu(struct exynos_ufs *ufs)
+{
+ u32 reg, val;
+
+ exynos_ufs_disable_auto_ctrl_hcc_save(ufs, &val);
+
+ /* make encryption disabled by default */
+ reg = ufsp_readl(ufs, UFSPRSECURITY);
+ ufsp_writel(ufs, reg | NSSMU, UFSPRSECURITY);
+ ufsp_writel(ufs, 0x0, UFSPSBEGIN0);
+ ufsp_writel(ufs, 0xffffffff, UFSPSEND0);
+ ufsp_writel(ufs, 0xff, UFSPSLUN0);
+ ufsp_writel(ufs, 0xf1, UFSPSCTRL0);
+
+ exynos_ufs_auto_ctrl_hcc_restore(ufs, &val);
+}
+
+static void exynos_ufs_config_sync_pattern_mask(struct exynos_ufs *ufs,
+ struct ufs_pa_layer_attr *pwr)
+{
+ struct ufs_hba *hba = ufs->hba;
+ u8 g = max_t(u32, pwr->gear_rx, pwr->gear_tx);
+ u32 mask, sync_len;
+ enum {
+ SYNC_LEN_G1 = 80 * 1000, /* 80us */
+ SYNC_LEN_G2 = 40 * 1000, /* 44us */
+ SYNC_LEN_G3 = 20 * 1000, /* 20us */
+ };
+ int i;
+
+ if (g == 1)
+ sync_len = SYNC_LEN_G1;
+ else if (g == 2)
+ sync_len = SYNC_LEN_G2;
+ else if (g == 3)
+ sync_len = SYNC_LEN_G3;
+ else
+ return;
+
+ mask = exynos_ufs_calc_time_cntr(ufs, sync_len);
+ mask = (mask >> 8) & 0xff;
+
+ exynos_ufs_enable_ov_tm(hba);
+
+ for_each_ufs_rx_lane(ufs, i)
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(RX_SYNC_MASK_LENGTH, i), mask);
+
+ exynos_ufs_disable_ov_tm(hba);
+}
+
+static int exynos_ufs_pre_pwr_mode(struct ufs_hba *hba,
+ struct ufs_pa_layer_attr *dev_max_params,
+ struct ufs_pa_layer_attr *dev_req_params)
+{
+ struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+ struct phy *generic_phy = ufs->phy;
+ struct ufs_dev_params ufs_exynos_cap;
+ int ret;
+
+ if (!dev_req_params) {
+ pr_err("%s: incoming dev_req_params is NULL\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+
+ ufs_exynos_cap.tx_lanes = UFS_EXYNOS_LIMIT_NUM_LANES_TX;
+ ufs_exynos_cap.rx_lanes = UFS_EXYNOS_LIMIT_NUM_LANES_RX;
+ ufs_exynos_cap.hs_rx_gear = UFS_EXYNOS_LIMIT_HSGEAR_RX;
+ ufs_exynos_cap.hs_tx_gear = UFS_EXYNOS_LIMIT_HSGEAR_TX;
+ ufs_exynos_cap.pwm_rx_gear = UFS_EXYNOS_LIMIT_PWMGEAR_RX;
+ ufs_exynos_cap.pwm_tx_gear = UFS_EXYNOS_LIMIT_PWMGEAR_TX;
+ ufs_exynos_cap.rx_pwr_pwm = UFS_EXYNOS_LIMIT_RX_PWR_PWM;
+ ufs_exynos_cap.tx_pwr_pwm = UFS_EXYNOS_LIMIT_TX_PWR_PWM;
+ ufs_exynos_cap.rx_pwr_hs = UFS_EXYNOS_LIMIT_RX_PWR_HS;
+ ufs_exynos_cap.tx_pwr_hs = UFS_EXYNOS_LIMIT_TX_PWR_HS;
+ ufs_exynos_cap.hs_rate = UFS_EXYNOS_LIMIT_HS_RATE;
+ ufs_exynos_cap.desired_working_mode =
+ UFS_EXYNOS_LIMIT_DESIRED_MODE;
+
+ ret = ufshcd_get_pwr_dev_param(&ufs_exynos_cap,
+ dev_max_params, dev_req_params);
+ if (ret) {
+ pr_err("%s: failed to determine capabilities\n", __func__);
+ goto out;
+ }
+
+ if (ufs->drv_data->pre_pwr_change)
+ ufs->drv_data->pre_pwr_change(ufs, dev_req_params);
+
+ if (ufshcd_is_hs_mode(dev_req_params)) {
+ exynos_ufs_config_sync_pattern_mask(ufs, dev_req_params);
+
+ switch (dev_req_params->hs_rate) {
+ case PA_HS_MODE_A:
+ case PA_HS_MODE_B:
+ phy_calibrate(generic_phy);
+ break;
+ }
+ }
+
+ /* setting for three timeout values for traffic class #0 */
+ ufshcd_dme_set(hba, UIC_ARG_MIB(DL_FC0PROTTIMEOUTVAL), 8064);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(DL_TC0REPLAYTIMEOUTVAL), 28224);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(DL_AFC0REQTIMEOUTVAL), 20160);
+
+ return 0;
+out:
+ return ret;
+}
+
+#define PWR_MODE_STR_LEN 64
+static int exynos_ufs_post_pwr_mode(struct ufs_hba *hba,
+ struct ufs_pa_layer_attr *pwr_max,
+ struct ufs_pa_layer_attr *pwr_req)
+{
+ struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+ struct phy *generic_phy = ufs->phy;
+ int gear = max_t(u32, pwr_req->gear_rx, pwr_req->gear_tx);
+ int lanes = max_t(u32, pwr_req->lane_rx, pwr_req->lane_tx);
+ char pwr_str[PWR_MODE_STR_LEN] = "";
+
+ /* let default be PWM Gear 1, Lane 1 */
+ if (!gear)
+ gear = 1;
+
+ if (!lanes)
+ lanes = 1;
+
+ if (ufs->drv_data->post_pwr_change)
+ ufs->drv_data->post_pwr_change(ufs, pwr_req);
+
+ if ((ufshcd_is_hs_mode(pwr_req))) {
+ switch (pwr_req->hs_rate) {
+ case PA_HS_MODE_A:
+ case PA_HS_MODE_B:
+ phy_calibrate(generic_phy);
+ break;
+ }
+
+ snprintf(pwr_str, PWR_MODE_STR_LEN, "%s series_%s G_%d L_%d",
+ "FAST", pwr_req->hs_rate == PA_HS_MODE_A ? "A" : "B",
+ gear, lanes);
+ } else {
+ snprintf(pwr_str, PWR_MODE_STR_LEN, "%s G_%d L_%d",
+ "SLOW", gear, lanes);
+ }
+
+ dev_info(hba->dev, "Power mode changed to : %s\n", pwr_str);
+
+ return 0;
+}
+
+static void exynos_ufs_specify_nexus_t_xfer_req(struct ufs_hba *hba,
+ int tag, bool op)
+{
+ struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+ u32 type;
+
+ type = hci_readl(ufs, HCI_UTRL_NEXUS_TYPE);
+
+ if (op)
+ hci_writel(ufs, type | (1 << tag), HCI_UTRL_NEXUS_TYPE);
+ else
+ hci_writel(ufs, type & ~(1 << tag), HCI_UTRL_NEXUS_TYPE);
+}
+
+static void exynos_ufs_specify_nexus_t_tm_req(struct ufs_hba *hba,
+ int tag, u8 func)
+{
+ struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+ u32 type;
+
+ type = hci_readl(ufs, HCI_UTMRL_NEXUS_TYPE);
+
+ switch (func) {
+ case UFS_ABORT_TASK:
+ case UFS_QUERY_TASK:
+ hci_writel(ufs, type | (1 << tag), HCI_UTMRL_NEXUS_TYPE);
+ break;
+ case UFS_ABORT_TASK_SET:
+ case UFS_CLEAR_TASK_SET:
+ case UFS_LOGICAL_RESET:
+ case UFS_QUERY_TASK_SET:
+ hci_writel(ufs, type & ~(1 << tag), HCI_UTMRL_NEXUS_TYPE);
+ break;
+ }
+}
+
+static int exynos_ufs_phy_init(struct exynos_ufs *ufs)
+{
+ struct ufs_hba *hba = ufs->hba;
+ struct phy *generic_phy = ufs->phy;
+ int ret = 0;
+
+ if (ufs->avail_ln_rx == 0 || ufs->avail_ln_tx == 0) {
+ ufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILRXDATALANES),
+ &ufs->avail_ln_rx);
+ ufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILTXDATALANES),
+ &ufs->avail_ln_tx);
+ WARN(ufs->avail_ln_rx != ufs->avail_ln_tx,
+ "available data lane is not equal(rx:%d, tx:%d)\n",
+ ufs->avail_ln_rx, ufs->avail_ln_tx);
+ }
+
+ phy_set_bus_width(generic_phy, ufs->avail_ln_rx);
+ ret = phy_init(generic_phy);
+ if (ret) {
+ dev_err(hba->dev, "%s: phy init failed, ret = %d\n",
+ __func__, ret);
+ goto out_exit_phy;
+ }
+
+ return 0;
+
+out_exit_phy:
+ phy_exit(generic_phy);
+
+ return ret;
+}
+
+static void exynos_ufs_config_unipro(struct exynos_ufs *ufs)
+{
+ struct ufs_hba *hba = ufs->hba;
+
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_CLK_PERIOD),
+ DIV_ROUND_UP(NSEC_PER_SEC, ufs->mclk_rate));
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXTRAILINGCLOCKS),
+ ufs->drv_data->uic_attr->tx_trailingclks);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OPTION_SUITE),
+ ufs->drv_data->uic_attr->pa_dbg_option_suite);
+}
+
+static void exynos_ufs_config_intr(struct exynos_ufs *ufs, u32 errs, u8 index)
+{
+ switch (index) {
+ case UNIPRO_L1_5:
+ hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_PA_LAYER);
+ break;
+ case UNIPRO_L2:
+ hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_DL_LAYER);
+ break;
+ case UNIPRO_L3:
+ hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_N_LAYER);
+ break;
+ case UNIPRO_L4:
+ hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_T_LAYER);
+ break;
+ case UNIPRO_DME:
+ hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERR_EN_DME_LAYER);
+ break;
+ }
+}
+
+static int exynos_ufs_pre_link(struct ufs_hba *hba)
+{
+ struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+
+ /* hci */
+ exynos_ufs_config_intr(ufs, DFES_DEF_L2_ERRS, UNIPRO_L2);
+ exynos_ufs_config_intr(ufs, DFES_DEF_L3_ERRS, UNIPRO_L3);
+ exynos_ufs_config_intr(ufs, DFES_DEF_L4_ERRS, UNIPRO_L4);
+ exynos_ufs_set_unipro_pclk_div(ufs);
+
+ /* unipro */
+ exynos_ufs_config_unipro(ufs);
+
+ /* m-phy */
+ exynos_ufs_phy_init(ufs);
+ exynos_ufs_config_phy_time_attr(ufs);
+ exynos_ufs_config_phy_cap_attr(ufs);
+
+ if (ufs->drv_data->pre_link)
+ ufs->drv_data->pre_link(ufs);
+
+ return 0;
+}
+
+static void exynos_ufs_fit_aggr_timeout(struct exynos_ufs *ufs)
+{
+ u32 val;
+
+ val = exynos_ufs_calc_time_cntr(ufs, IATOVAL_NSEC / CNTR_DIV_VAL);
+ hci_writel(ufs, val & CNT_VAL_1US_MASK, HCI_1US_TO_CNT_VAL);
+}
+
+static int exynos_ufs_post_link(struct ufs_hba *hba)
+{
+ struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+ struct phy *generic_phy = ufs->phy;
+ struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr;
+
+ exynos_ufs_establish_connt(ufs);
+ exynos_ufs_fit_aggr_timeout(ufs);
+
+ hci_writel(ufs, 0xa, HCI_DATA_REORDER);
+ hci_writel(ufs, PRDT_SET_SIZE(12), HCI_TXPRDT_ENTRY_SIZE);
+ hci_writel(ufs, PRDT_SET_SIZE(12), HCI_RXPRDT_ENTRY_SIZE);
+ hci_writel(ufs, (1 << hba->nutrs) - 1, HCI_UTRL_NEXUS_TYPE);
+ hci_writel(ufs, (1 << hba->nutmrs) - 1, HCI_UTMRL_NEXUS_TYPE);
+ hci_writel(ufs, 0xf, HCI_AXIDMA_RWDATA_BURST_LEN);
+
+ if (ufs->opts & EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB)
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB(T_DBG_SKIP_INIT_HIBERN8_EXIT), TRUE);
+
+ if (attr->pa_granularity) {
+ exynos_ufs_enable_dbg_mode(hba);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_GRANULARITY),
+ attr->pa_granularity);
+ exynos_ufs_disable_dbg_mode(hba);
+
+ if (attr->pa_tactivate)
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE),
+ attr->pa_tactivate);
+ if (attr->pa_hibern8time &&
+ !(ufs->opts & EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER))
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HIBERN8TIME),
+ attr->pa_hibern8time);
+ }
+
+ if (ufs->opts & EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER) {
+ if (!attr->pa_granularity)
+ ufshcd_dme_get(hba, UIC_ARG_MIB(PA_GRANULARITY),
+ &attr->pa_granularity);
+ if (!attr->pa_hibern8time)
+ ufshcd_dme_get(hba, UIC_ARG_MIB(PA_HIBERN8TIME),
+ &attr->pa_hibern8time);
+ /*
+ * not wait for HIBERN8 time to exit hibernation
+ */
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HIBERN8TIME), 0);
+
+ if (attr->pa_granularity < 1 || attr->pa_granularity > 6) {
+ /* Valid range for granularity: 1 ~ 6 */
+ dev_warn(hba->dev,
+ "%s: pa_granularity %d is invalid, assuming backwards compatibility\n",
+ __func__,
+ attr->pa_granularity);
+ attr->pa_granularity = 6;
+ }
+ }
+
+ phy_calibrate(generic_phy);
+
+ if (ufs->drv_data->post_link)
+ ufs->drv_data->post_link(ufs);
+
+ return 0;
+}
+
+static int exynos_ufs_parse_dt(struct device *dev, struct exynos_ufs *ufs)
+{
+ struct device_node *np = dev->of_node;
+ struct exynos_ufs_drv_data *drv_data = &exynos_ufs_drvs;
+ struct exynos_ufs_uic_attr *attr;
+ int ret = 0;
+
+ while (drv_data->compatible) {
+ if (of_device_is_compatible(np, drv_data->compatible)) {
+ ufs->drv_data = drv_data;
+ break;
+ }
+ drv_data++;
+ }
+
+ if (ufs->drv_data && ufs->drv_data->uic_attr) {
+ attr = ufs->drv_data->uic_attr;
+ } else {
+ dev_err(dev, "failed to get uic attributes\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ufs->pclk_avail_min = PCLK_AVAIL_MIN;
+ ufs->pclk_avail_max = PCLK_AVAIL_MAX;
+
+ attr->rx_adv_fine_gran_sup_en = RX_ADV_FINE_GRAN_SUP_EN;
+ attr->rx_adv_fine_gran_step = RX_ADV_FINE_GRAN_STEP_VAL;
+ attr->rx_adv_min_actv_time_cap = RX_ADV_MIN_ACTV_TIME_CAP;
+ attr->pa_granularity = PA_GRANULARITY_VAL;
+ attr->pa_tactivate = PA_TACTIVATE_VAL;
+ attr->pa_hibern8time = PA_HIBERN8TIME_VAL;
+
+out:
+ return ret;
+}
+
+static int exynos_ufs_init(struct ufs_hba *hba)
+{
+ struct device *dev = hba->dev;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct exynos_ufs *ufs;
+ int ret;
+
+ ufs = devm_kzalloc(dev, sizeof(*ufs), GFP_KERNEL);
+ if (!ufs)
+ return -ENOMEM;
+
+ /* exynos-specific hci */
+ ufs->reg_hci = devm_platform_ioremap_resource_byname(pdev, "vs_hci");
+ if (IS_ERR(ufs->reg_hci)) {
+ dev_err(dev, "cannot ioremap for hci vendor register\n");
+ return PTR_ERR(ufs->reg_hci);
+ }
+
+ /* unipro */
+ ufs->reg_unipro = devm_platform_ioremap_resource_byname(pdev, "unipro");
+ if (IS_ERR(ufs->reg_unipro)) {
+ dev_err(dev, "cannot ioremap for unipro register\n");
+ return PTR_ERR(ufs->reg_unipro);
+ }
+
+ /* ufs protector */
+ ufs->reg_ufsp = devm_platform_ioremap_resource_byname(pdev, "ufsp");
+ if (IS_ERR(ufs->reg_ufsp)) {
+ dev_err(dev, "cannot ioremap for ufs protector register\n");
+ return PTR_ERR(ufs->reg_ufsp);
+ }
+
+ ret = exynos_ufs_parse_dt(dev, ufs);
+ if (ret) {
+ dev_err(dev, "failed to get dt info.\n");
+ goto out;
+ }
+
+ ufs->phy = devm_phy_get(dev, "ufs-phy");
+ if (IS_ERR(ufs->phy)) {
+ ret = PTR_ERR(ufs->phy);
+ dev_err(dev, "failed to get ufs-phy\n");
+ goto out;
+ }
+
+ ret = phy_power_on(ufs->phy);
+ if (ret)
+ goto phy_off;
+
+ ufs->hba = hba;
+ ufs->opts = ufs->drv_data->opts;
+ ufs->rx_sel_idx = PA_MAXDATALANES;
+ if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX)
+ ufs->rx_sel_idx = 0;
+ hba->priv = (void *)ufs;
+ hba->quirks = ufs->drv_data->quirks;
+ if (ufs->drv_data->drv_init) {
+ ret = ufs->drv_data->drv_init(dev, ufs);
+ if (ret) {
+ dev_err(dev, "failed to init drv-data\n");
+ goto out;
+ }
+ }
+
+ ret = exynos_ufs_get_clk_info(ufs);
+ if (ret)
+ goto out;
+ exynos_ufs_specify_phy_time_attr(ufs);
+ exynos_ufs_config_smu(ufs);
+ return 0;
+
+phy_off:
+ phy_power_off(ufs->phy);
+out:
+ hba->priv = NULL;
+ return ret;
+}
+
+static int exynos_ufs_host_reset(struct ufs_hba *hba)
+{
+ struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+ unsigned long timeout = jiffies + msecs_to_jiffies(1);
+ u32 val;
+ int ret = 0;
+
+ exynos_ufs_disable_auto_ctrl_hcc_save(ufs, &val);
+
+ hci_writel(ufs, UFS_SW_RST_MASK, HCI_SW_RST);
+
+ do {
+ if (!(hci_readl(ufs, HCI_SW_RST) & UFS_SW_RST_MASK))
+ goto out;
+ } while (time_before(jiffies, timeout));
+
+ dev_err(hba->dev, "timeout host sw-reset\n");
+ ret = -ETIMEDOUT;
+
+out:
+ exynos_ufs_auto_ctrl_hcc_restore(ufs, &val);
+ return ret;
+}
+
+static void exynos_ufs_dev_hw_reset(struct ufs_hba *hba)
+{
+ struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+
+ hci_writel(ufs, 0 << 0, HCI_GPIO_OUT);
+ udelay(5);
+ hci_writel(ufs, 1 << 0, HCI_GPIO_OUT);
+}
+
+static void exynos_ufs_pre_hibern8(struct ufs_hba *hba, u8 enter)
+{
+ struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+ struct exynos_ufs_uic_attr *attr = ufs->drv_data->uic_attr;
+
+ if (!enter) {
+ if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL)
+ exynos_ufs_disable_auto_ctrl_hcc(ufs);
+ exynos_ufs_ungate_clks(ufs);
+
+ if (ufs->opts & EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER) {
+ const unsigned int granularity_tbl[] = {
+ 1, 4, 8, 16, 32, 100
+ };
+ int h8_time = attr->pa_hibern8time *
+ granularity_tbl[attr->pa_granularity - 1];
+ unsigned long us;
+ s64 delta;
+
+ do {
+ delta = h8_time - ktime_us_delta(ktime_get(),
+ ufs->entry_hibern8_t);
+ if (delta <= 0)
+ break;
+
+ us = min_t(s64, delta, USEC_PER_MSEC);
+ if (us >= 10)
+ usleep_range(us, us + 10);
+ } while (1);
+ }
+ }
+}
+
+static void exynos_ufs_post_hibern8(struct ufs_hba *hba, u8 enter)
+{
+ struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+
+ if (!enter) {
+ u32 cur_mode = 0;
+ u32 pwrmode;
+
+ if (ufshcd_is_hs_mode(&ufs->dev_req_params))
+ pwrmode = FAST_MODE;
+ else
+ pwrmode = SLOW_MODE;
+
+ ufshcd_dme_get(hba, UIC_ARG_MIB(PA_PWRMODE), &cur_mode);
+ if (cur_mode != (pwrmode << 4 | pwrmode)) {
+ dev_warn(hba->dev, "%s: power mode change\n", __func__);
+ hba->pwr_info.pwr_rx = (cur_mode >> 4) & 0xf;
+ hba->pwr_info.pwr_tx = cur_mode & 0xf;
+ ufshcd_config_pwr_mode(hba, &hba->max_pwr_info.info);
+ }
+
+ if (!(ufs->opts & EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB))
+ exynos_ufs_establish_connt(ufs);
+ } else {
+ ufs->entry_hibern8_t = ktime_get();
+ exynos_ufs_gate_clks(ufs);
+ if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL)
+ exynos_ufs_enable_auto_ctrl_hcc(ufs);
+ }
+}
+
+static int exynos_ufs_hce_enable_notify(struct ufs_hba *hba,
+ enum ufs_notify_change_status status)
+{
+ struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+ int ret = 0;
+
+ switch (status) {
+ case PRE_CHANGE:
+ ret = exynos_ufs_host_reset(hba);
+ if (ret)
+ return ret;
+ exynos_ufs_dev_hw_reset(hba);
+ break;
+ case POST_CHANGE:
+ exynos_ufs_calc_pwm_clk_div(ufs);
+ if (!(ufs->opts & EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL))
+ exynos_ufs_enable_auto_ctrl_hcc(ufs);
+ break;
+ }
+
+ return ret;
+}
+
+static int exynos_ufs_link_startup_notify(struct ufs_hba *hba,
+ enum ufs_notify_change_status status)
+{
+ int ret = 0;
+
+ switch (status) {
+ case PRE_CHANGE:
+ ret = exynos_ufs_pre_link(hba);
+ break;
+ case POST_CHANGE:
+ ret = exynos_ufs_post_link(hba);
+ break;
+ }
+
+ return ret;
+}
+
+static int exynos_ufs_pwr_change_notify(struct ufs_hba *hba,
+ enum ufs_notify_change_status status,
+ struct ufs_pa_layer_attr *dev_max_params,
+ struct ufs_pa_layer_attr *dev_req_params)
+{
+ int ret = 0;
+
+ switch (status) {
+ case PRE_CHANGE:
+ ret = exynos_ufs_pre_pwr_mode(hba, dev_max_params,
+ dev_req_params);
+ break;
+ case POST_CHANGE:
+ ret = exynos_ufs_post_pwr_mode(hba, NULL, dev_req_params);
+ break;
+ }
+
+ return ret;
+}
+
+static void exynos_ufs_hibern8_notify(struct ufs_hba *hba,
+ enum uic_cmd_dme enter,
+ enum ufs_notify_change_status notify)
+{
+ switch ((u8)notify) {
+ case PRE_CHANGE:
+ exynos_ufs_pre_hibern8(hba, enter);
+ break;
+ case POST_CHANGE:
+ exynos_ufs_post_hibern8(hba, enter);
+ break;
+ }
+}
+
+static int exynos_ufs_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
+{
+ struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+
+ if (!ufshcd_is_link_active(hba))
+ phy_power_off(ufs->phy);
+
+ return 0;
+}
+
+static int exynos_ufs_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
+{
+ struct exynos_ufs *ufs = ufshcd_get_variant(hba);
+
+ if (!ufshcd_is_link_active(hba))
+ phy_power_on(ufs->phy);
+
+ exynos_ufs_config_smu(ufs);
+
+ return 0;
+}
+
+static struct ufs_hba_variant_ops ufs_hba_exynos_ops = {
+ .name = "exynos_ufs",
+ .init = exynos_ufs_init,
+ .hce_enable_notify = exynos_ufs_hce_enable_notify,
+ .link_startup_notify = exynos_ufs_link_startup_notify,
+ .pwr_change_notify = exynos_ufs_pwr_change_notify,
+ .setup_xfer_req = exynos_ufs_specify_nexus_t_xfer_req,
+ .setup_task_mgmt = exynos_ufs_specify_nexus_t_tm_req,
+ .hibern8_notify = exynos_ufs_hibern8_notify,
+ .suspend = exynos_ufs_suspend,
+ .resume = exynos_ufs_resume,
+};
+
+static int exynos_ufs_probe(struct platform_device *pdev)
+{
+ int err;
+ struct device *dev = &pdev->dev;
+
+ err = ufshcd_pltfrm_init(pdev, &ufs_hba_exynos_ops);
+ if (err)
+ dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err);
+
+ return err;
+}
+
+static int exynos_ufs_remove(struct platform_device *pdev)
+{
+ struct ufs_hba *hba = platform_get_drvdata(pdev);
+
+ pm_runtime_get_sync(&(pdev)->dev);
+ ufshcd_remove(hba);
+ return 0;
+}
+
+struct exynos_ufs_drv_data exynos_ufs_drvs = {
+
+ .compatible = "samsung,exynos7-ufs",
+ .uic_attr = &exynos7_uic_attr,
+ .quirks = UFSHCD_QUIRK_PRDT_BYTE_GRAN |
+ UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR |
+ UFSHCI_QUIRK_BROKEN_HCE |
+ UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR |
+ UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR |
+ UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL |
+ UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING |
+ UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE,
+ .opts = EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL |
+ EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL |
+ EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX |
+ EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB |
+ EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER,
+ .drv_init = exynos7_ufs_drv_init,
+ .pre_link = exynos7_ufs_pre_link,
+ .post_link = exynos7_ufs_post_link,
+ .pre_pwr_change = exynos7_ufs_pre_pwr_change,
+ .post_pwr_change = exynos7_ufs_post_pwr_change,
+};
+
+static const struct of_device_id exynos_ufs_of_match[] = {
+ { .compatible = "samsung,exynos7-ufs",
+ .data = &exynos_ufs_drvs },
+ {},
+};
+
+static const struct dev_pm_ops exynos_ufs_pm_ops = {
+ .suspend = ufshcd_pltfrm_suspend,
+ .resume = ufshcd_pltfrm_resume,
+ .runtime_suspend = ufshcd_pltfrm_runtime_suspend,
+ .runtime_resume = ufshcd_pltfrm_runtime_resume,
+ .runtime_idle = ufshcd_pltfrm_runtime_idle,
+};
+
+static struct platform_driver exynos_ufs_pltform = {
+ .probe = exynos_ufs_probe,
+ .remove = exynos_ufs_remove,
+ .shutdown = ufshcd_pltfrm_shutdown,
+ .driver = {
+ .name = "exynos-ufshc",
+ .pm = &exynos_ufs_pm_ops,
+ .of_match_table = of_match_ptr(exynos_ufs_of_match),
+ },
+};
+module_platform_driver(exynos_ufs_pltform);
+
+MODULE_AUTHOR("Alim Akhtar <alim.akhtar@samsung.com>");
+MODULE_AUTHOR("Seungwon Jeon <essuuj@gmail.com>");
+MODULE_DESCRIPTION("Exynos UFS HCI Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/scsi/ufs/ufs-exynos.h b/drivers/scsi/ufs/ufs-exynos.h
new file mode 100644
index 0000000..541b577
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-exynos.h
@@ -0,0 +1,287 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * UFS Host Controller driver for Exynos specific extensions
+ *
+ * Copyright (C) 2014-2015 Samsung Electronics Co., Ltd.
+ *
+ */
+
+#ifndef _UFS_EXYNOS_H_
+#define _UFS_EXYNOS_H_
+
+/*
+ * UNIPRO registers
+ */
+#define UNIPRO_DBG_FORCE_DME_CTRL_STATE 0x150
+
+/*
+ * MIBs for PA debug registers
+ */
+#define PA_DBG_CLK_PERIOD 0x9514
+#define PA_DBG_TXPHY_CFGUPDT 0x9518
+#define PA_DBG_RXPHY_CFGUPDT 0x9519
+#define PA_DBG_MODE 0x9529
+#define PA_DBG_SKIP_RESET_PHY 0x9539
+#define PA_DBG_OV_TM 0x9540
+#define PA_DBG_SKIP_LINE_RESET 0x9541
+#define PA_DBG_LINE_RESET_REQ 0x9543
+#define PA_DBG_OPTION_SUITE 0x9564
+#define PA_DBG_OPTION_SUITE_DYN 0x9565
+
+/*
+ * MIBs for Transport Layer debug registers
+ */
+#define T_DBG_SKIP_INIT_HIBERN8_EXIT 0xc001
+
+/*
+ * Exynos MPHY attributes
+ */
+#define TX_LINERESET_N_VAL 0x0277
+#define TX_LINERESET_N(v) (((v) >> 10) & 0xFF)
+#define TX_LINERESET_P_VAL 0x027D
+#define TX_LINERESET_P(v) (((v) >> 12) & 0xFF)
+#define TX_OV_SLEEP_CNT_TIMER 0x028E
+#define TX_OV_H8_ENTER_EN (1 << 7)
+#define TX_OV_SLEEP_CNT(v) (((v) >> 5) & 0x7F)
+#define TX_HIGH_Z_CNT_11_08 0x028C
+#define TX_HIGH_Z_CNT_H(v) (((v) >> 8) & 0xF)
+#define TX_HIGH_Z_CNT_07_00 0x028D
+#define TX_HIGH_Z_CNT_L(v) ((v) & 0xFF)
+#define TX_BASE_NVAL_07_00 0x0293
+#define TX_BASE_NVAL_L(v) ((v) & 0xFF)
+#define TX_BASE_NVAL_15_08 0x0294
+#define TX_BASE_NVAL_H(v) (((v) >> 8) & 0xFF)
+#define TX_GRAN_NVAL_07_00 0x0295
+#define TX_GRAN_NVAL_L(v) ((v) & 0xFF)
+#define TX_GRAN_NVAL_10_08 0x0296
+#define TX_GRAN_NVAL_H(v) (((v) >> 8) & 0x3)
+
+#define RX_FILLER_ENABLE 0x0316
+#define RX_FILLER_EN (1 << 1)
+#define RX_LINERESET_VAL 0x0317
+#define RX_LINERESET(v) (((v) >> 12) & 0xFF)
+#define RX_LCC_IGNORE 0x0318
+#define RX_SYNC_MASK_LENGTH 0x0321
+#define RX_HIBERN8_WAIT_VAL_BIT_20_16 0x0331
+#define RX_HIBERN8_WAIT_VAL_BIT_15_08 0x0332
+#define RX_HIBERN8_WAIT_VAL_BIT_07_00 0x0333
+#define RX_OV_SLEEP_CNT_TIMER 0x0340
+#define RX_OV_SLEEP_CNT(v) (((v) >> 6) & 0x1F)
+#define RX_OV_STALL_CNT_TIMER 0x0341
+#define RX_OV_STALL_CNT(v) (((v) >> 4) & 0xFF)
+#define RX_BASE_NVAL_07_00 0x0355
+#define RX_BASE_NVAL_L(v) ((v) & 0xFF)
+#define RX_BASE_NVAL_15_08 0x0354
+#define RX_BASE_NVAL_H(v) (((v) >> 8) & 0xFF)
+#define RX_GRAN_NVAL_07_00 0x0353
+#define RX_GRAN_NVAL_L(v) ((v) & 0xFF)
+#define RX_GRAN_NVAL_10_08 0x0352
+#define RX_GRAN_NVAL_H(v) (((v) >> 8) & 0x3)
+
+#define CMN_PWM_CLK_CTRL 0x0402
+#define PWM_CLK_CTRL_MASK 0x3
+
+#define IATOVAL_NSEC 20000 /* unit: ns */
+#define UNIPRO_PCLK_PERIOD(ufs) (NSEC_PER_SEC / ufs->pclk_rate)
+
+struct exynos_ufs;
+
+/* vendor specific pre-defined parameters */
+#define SLOW 1
+#define FAST 2
+
+#define UFS_EXYNOS_LIMIT_NUM_LANES_RX 2
+#define UFS_EXYNOS_LIMIT_NUM_LANES_TX 2
+#define UFS_EXYNOS_LIMIT_HSGEAR_RX UFS_HS_G3
+#define UFS_EXYNOS_LIMIT_HSGEAR_TX UFS_HS_G3
+#define UFS_EXYNOS_LIMIT_PWMGEAR_RX UFS_PWM_G4
+#define UFS_EXYNOS_LIMIT_PWMGEAR_TX UFS_PWM_G4
+#define UFS_EXYNOS_LIMIT_RX_PWR_PWM SLOW_MODE
+#define UFS_EXYNOS_LIMIT_TX_PWR_PWM SLOW_MODE
+#define UFS_EXYNOS_LIMIT_RX_PWR_HS FAST_MODE
+#define UFS_EXYNOS_LIMIT_TX_PWR_HS FAST_MODE
+#define UFS_EXYNOS_LIMIT_HS_RATE PA_HS_MODE_B
+#define UFS_EXYNOS_LIMIT_DESIRED_MODE FAST
+
+#define RX_ADV_FINE_GRAN_SUP_EN 0x1
+#define RX_ADV_FINE_GRAN_STEP_VAL 0x3
+#define RX_ADV_MIN_ACTV_TIME_CAP 0x9
+
+#define PA_GRANULARITY_VAL 0x6
+#define PA_TACTIVATE_VAL 0x3
+#define PA_HIBERN8TIME_VAL 0x20
+
+#define PCLK_AVAIL_MIN 70000000
+#define PCLK_AVAIL_MAX 133000000
+
+struct exynos_ufs_uic_attr {
+ /* TX Attributes */
+ unsigned int tx_trailingclks;
+ unsigned int tx_dif_p_nsec;
+ unsigned int tx_dif_n_nsec;
+ unsigned int tx_high_z_cnt_nsec;
+ unsigned int tx_base_unit_nsec;
+ unsigned int tx_gran_unit_nsec;
+ unsigned int tx_sleep_cnt;
+ unsigned int tx_min_activatetime;
+ /* RX Attributes */
+ unsigned int rx_filler_enable;
+ unsigned int rx_dif_p_nsec;
+ unsigned int rx_hibern8_wait_nsec;
+ unsigned int rx_base_unit_nsec;
+ unsigned int rx_gran_unit_nsec;
+ unsigned int rx_sleep_cnt;
+ unsigned int rx_stall_cnt;
+ unsigned int rx_hs_g1_sync_len_cap;
+ unsigned int rx_hs_g2_sync_len_cap;
+ unsigned int rx_hs_g3_sync_len_cap;
+ unsigned int rx_hs_g1_prep_sync_len_cap;
+ unsigned int rx_hs_g2_prep_sync_len_cap;
+ unsigned int rx_hs_g3_prep_sync_len_cap;
+ /* Common Attributes */
+ unsigned int cmn_pwm_clk_ctrl;
+ /* Internal Attributes */
+ unsigned int pa_dbg_option_suite;
+ /* Changeable Attributes */
+ unsigned int rx_adv_fine_gran_sup_en;
+ unsigned int rx_adv_fine_gran_step;
+ unsigned int rx_min_actv_time_cap;
+ unsigned int rx_hibern8_time_cap;
+ unsigned int rx_adv_min_actv_time_cap;
+ unsigned int rx_adv_hibern8_time_cap;
+ unsigned int pa_granularity;
+ unsigned int pa_tactivate;
+ unsigned int pa_hibern8time;
+};
+
+struct exynos_ufs_drv_data {
+ char *compatible;
+ struct exynos_ufs_uic_attr *uic_attr;
+ unsigned int quirks;
+ unsigned int opts;
+ /* SoC's specific operations */
+ int (*drv_init)(struct device *dev, struct exynos_ufs *ufs);
+ int (*pre_link)(struct exynos_ufs *ufs);
+ int (*post_link)(struct exynos_ufs *ufs);
+ int (*pre_pwr_change)(struct exynos_ufs *ufs,
+ struct ufs_pa_layer_attr *pwr);
+ int (*post_pwr_change)(struct exynos_ufs *ufs,
+ struct ufs_pa_layer_attr *pwr);
+};
+
+struct ufs_phy_time_cfg {
+ u32 tx_linereset_p;
+ u32 tx_linereset_n;
+ u32 tx_high_z_cnt;
+ u32 tx_base_n_val;
+ u32 tx_gran_n_val;
+ u32 tx_sleep_cnt;
+ u32 rx_linereset;
+ u32 rx_hibern8_wait;
+ u32 rx_base_n_val;
+ u32 rx_gran_n_val;
+ u32 rx_sleep_cnt;
+ u32 rx_stall_cnt;
+};
+
+struct exynos_ufs {
+ struct ufs_hba *hba;
+ struct phy *phy;
+ void __iomem *reg_hci;
+ void __iomem *reg_unipro;
+ void __iomem *reg_ufsp;
+ struct clk *clk_hci_core;
+ struct clk *clk_unipro_main;
+ struct clk *clk_apb;
+ u32 pclk_rate;
+ u32 pclk_div;
+ u32 pclk_avail_min;
+ u32 pclk_avail_max;
+ unsigned long mclk_rate;
+ int avail_ln_rx;
+ int avail_ln_tx;
+ int rx_sel_idx;
+ struct ufs_pa_layer_attr dev_req_params;
+ struct ufs_phy_time_cfg t_cfg;
+ ktime_t entry_hibern8_t;
+ struct exynos_ufs_drv_data *drv_data;
+
+ u32 opts;
+#define EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL BIT(0)
+#define EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB BIT(1)
+#define EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL BIT(2)
+#define EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX BIT(3)
+#define EXYNOS_UFS_OPT_USE_SW_HIBERN8_TIMER BIT(4)
+};
+
+#define for_each_ufs_rx_lane(ufs, i) \
+ for (i = (ufs)->rx_sel_idx; \
+ i < (ufs)->rx_sel_idx + (ufs)->avail_ln_rx; i++)
+#define for_each_ufs_tx_lane(ufs, i) \
+ for (i = 0; i < (ufs)->avail_ln_tx; i++)
+
+#define EXYNOS_UFS_MMIO_FUNC(name) \
+static inline void name##_writel(struct exynos_ufs *ufs, u32 val, u32 reg)\
+{ \
+ writel(val, ufs->reg_##name + reg); \
+} \
+ \
+static inline u32 name##_readl(struct exynos_ufs *ufs, u32 reg) \
+{ \
+ return readl(ufs->reg_##name + reg); \
+}
+
+EXYNOS_UFS_MMIO_FUNC(hci);
+EXYNOS_UFS_MMIO_FUNC(unipro);
+EXYNOS_UFS_MMIO_FUNC(ufsp);
+#undef EXYNOS_UFS_MMIO_FUNC
+
+long exynos_ufs_calc_time_cntr(struct exynos_ufs *, long);
+
+static inline void exynos_ufs_enable_ov_tm(struct ufs_hba *hba)
+{
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OV_TM), TRUE);
+}
+
+static inline void exynos_ufs_disable_ov_tm(struct ufs_hba *hba)
+{
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OV_TM), FALSE);
+}
+
+static inline void exynos_ufs_enable_dbg_mode(struct ufs_hba *hba)
+{
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_MODE), TRUE);
+}
+
+static inline void exynos_ufs_disable_dbg_mode(struct ufs_hba *hba)
+{
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_MODE), FALSE);
+}
+
+struct exynos_ufs_drv_data exynos_ufs_drvs;
+
+struct exynos_ufs_uic_attr exynos7_uic_attr = {
+ .tx_trailingclks = 0x10,
+ .tx_dif_p_nsec = 3000000, /* unit: ns */
+ .tx_dif_n_nsec = 1000000, /* unit: ns */
+ .tx_high_z_cnt_nsec = 20000, /* unit: ns */
+ .tx_base_unit_nsec = 100000, /* unit: ns */
+ .tx_gran_unit_nsec = 4000, /* unit: ns */
+ .tx_sleep_cnt = 1000, /* unit: ns */
+ .tx_min_activatetime = 0xa,
+ .rx_filler_enable = 0x2,
+ .rx_dif_p_nsec = 1000000, /* unit: ns */
+ .rx_hibern8_wait_nsec = 4000000, /* unit: ns */
+ .rx_base_unit_nsec = 100000, /* unit: ns */
+ .rx_gran_unit_nsec = 4000, /* unit: ns */
+ .rx_sleep_cnt = 1280, /* unit: ns */
+ .rx_stall_cnt = 320, /* unit: ns */
+ .rx_hs_g1_sync_len_cap = SYNC_LEN_COARSE(0xf),
+ .rx_hs_g2_sync_len_cap = SYNC_LEN_COARSE(0xf),
+ .rx_hs_g3_sync_len_cap = SYNC_LEN_COARSE(0xf),
+ .rx_hs_g1_prep_sync_len_cap = PREP_LEN(0xf),
+ .rx_hs_g2_prep_sync_len_cap = PREP_LEN(0xf),
+ .rx_hs_g3_prep_sync_len_cap = PREP_LEN(0xf),
+ .pa_dbg_option_suite = 0x30103,
+};
+#endif /* _UFS_EXYNOS_H_ */
diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c
index 9903ce9..55b7161 100644
--- a/drivers/scsi/ufs/ufs-hisi.c
+++ b/drivers/scsi/ufs/ufs-hisi.c
@@ -235,7 +235,7 @@
ufshcd_writel(hba, reg, REG_AUTO_HIBERNATE_IDLE_TIMER);
/* Unipro PA_Local_TX_LCC_Enable */
- ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x155E, 0x0), 0x0);
+ ufshcd_disable_host_tx_lcc(hba);
/* close Unipro VS_Mk2ExtnSupport */
ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xD0AB, 0x0), 0x0);
ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(0xD0AB, 0x0), &value);
@@ -452,10 +452,7 @@
/* get resource of ufs sys ctrl */
host->ufs_sys_ctrl = devm_platform_ioremap_resource(pdev, 1);
- if (IS_ERR(host->ufs_sys_ctrl))
- return PTR_ERR(host->ufs_sys_ctrl);
-
- return 0;
+ return PTR_ERR_OR_ZERO(host->ufs_sys_ctrl);
}
static void ufs_hisi_set_pm_lvl(struct ufs_hba *hba)
diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c
index d4a8be5..aace133 100644
--- a/drivers/scsi/ufs/ufs-mediatek.c
+++ b/drivers/scsi/ufs/ufs-mediatek.c
@@ -6,17 +6,67 @@
* Peter Wang <peter.wang@mediatek.com>
*/
+#include <linux/arm-smccc.h>
+#include <linux/bitfield.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/soc/mediatek/mtk_sip_svc.h>
#include "ufshcd.h"
+#include "ufshcd-crypto.h"
#include "ufshcd-pltfrm.h"
#include "ufs_quirks.h"
#include "unipro.h"
#include "ufs-mediatek.h"
+#define ufs_mtk_smc(cmd, val, res) \
+ arm_smccc_smc(MTK_SIP_UFS_CONTROL, \
+ cmd, val, 0, 0, 0, 0, 0, &(res))
+
+#define ufs_mtk_crypto_ctrl(res, enable) \
+ ufs_mtk_smc(UFS_MTK_SIP_CRYPTO_CTRL, enable, res)
+
+#define ufs_mtk_ref_clk_notify(on, res) \
+ ufs_mtk_smc(UFS_MTK_SIP_REF_CLK_NOTIFICATION, on, res)
+
+#define ufs_mtk_device_reset_ctrl(high, res) \
+ ufs_mtk_smc(UFS_MTK_SIP_DEVICE_RESET, high, res)
+
+static struct ufs_dev_fix ufs_mtk_dev_fixups[] = {
+ UFS_FIX(UFS_VENDOR_MICRON, UFS_ANY_MODEL,
+ UFS_DEVICE_QUIRK_DELAY_AFTER_LPM),
+ UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ21AFAMZDAR",
+ UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES),
+ END_FIX
+};
+
+static const struct ufs_mtk_host_cfg ufs_mtk_mt8192_cfg = {
+ .caps = UFS_MTK_CAP_BOOST_CRYPT_ENGINE,
+};
+
+static const struct of_device_id ufs_mtk_of_match[] = {
+ {
+ .compatible = "mediatek,mt8183-ufshci",
+ },
+ {
+ .compatible = "mediatek,mt8192-ufshci",
+ .data = &ufs_mtk_mt8192_cfg
+ },
+ {},
+};
+
+static bool ufs_mtk_is_boost_crypt_enabled(struct ufs_hba *hba)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+
+ return (host->caps & UFS_MTK_CAP_BOOST_CRYPT_ENGINE);
+}
+
static void ufs_mtk_cfg_unipro_cg(struct ufs_hba *hba, bool enable)
{
u32 tmp;
@@ -53,6 +103,77 @@
}
}
+static void ufs_mtk_crypto_enable(struct ufs_hba *hba)
+{
+ struct arm_smccc_res res;
+
+ ufs_mtk_crypto_ctrl(res, 1);
+ if (res.a0) {
+ dev_info(hba->dev, "%s: crypto enable failed, err: %lu\n",
+ __func__, res.a0);
+ hba->caps &= ~UFSHCD_CAP_CRYPTO;
+ }
+}
+
+static void ufs_mtk_host_reset(struct ufs_hba *hba)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+
+ reset_control_assert(host->hci_reset);
+ reset_control_assert(host->crypto_reset);
+ reset_control_assert(host->unipro_reset);
+
+ usleep_range(100, 110);
+
+ reset_control_deassert(host->unipro_reset);
+ reset_control_deassert(host->crypto_reset);
+ reset_control_deassert(host->hci_reset);
+}
+
+static void ufs_mtk_init_reset_control(struct ufs_hba *hba,
+ struct reset_control **rc,
+ char *str)
+{
+ *rc = devm_reset_control_get(hba->dev, str);
+ if (IS_ERR(*rc)) {
+ dev_info(hba->dev, "Failed to get reset control %s: %ld\n",
+ str, PTR_ERR(*rc));
+ *rc = NULL;
+ }
+}
+
+static void ufs_mtk_init_reset(struct ufs_hba *hba)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+
+ ufs_mtk_init_reset_control(hba, &host->hci_reset,
+ "hci_rst");
+ ufs_mtk_init_reset_control(hba, &host->unipro_reset,
+ "unipro_rst");
+ ufs_mtk_init_reset_control(hba, &host->crypto_reset,
+ "crypto_rst");
+}
+
+static int ufs_mtk_hce_enable_notify(struct ufs_hba *hba,
+ enum ufs_notify_change_status status)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+
+ if (status == PRE_CHANGE) {
+ if (host->unipro_lpm) {
+ hba->vps->hba_enable_delay_us = 0;
+ } else {
+ hba->vps->hba_enable_delay_us = 600;
+ ufs_mtk_host_reset(hba);
+ }
+
+ if (hba->caps & UFSHCD_CAP_CRYPTO)
+ ufs_mtk_crypto_enable(hba);
+ }
+
+ return 0;
+}
+
static int ufs_mtk_bind_mphy(struct ufs_hba *hba)
{
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
@@ -73,15 +194,267 @@
__func__, err);
} else if (IS_ERR(host->mphy)) {
err = PTR_ERR(host->mphy);
- dev_info(dev, "%s: PHY get failed %d\n", __func__, err);
+ if (err != -ENODEV) {
+ dev_info(dev, "%s: PHY get failed %d\n", __func__,
+ err);
+ }
}
if (err)
host->mphy = NULL;
+ /*
+ * Allow unbound mphy because not every platform needs specific
+ * mphy control.
+ */
+ if (err == -ENODEV)
+ err = 0;
return err;
}
+static int ufs_mtk_setup_ref_clk(struct ufs_hba *hba, bool on)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+ struct arm_smccc_res res;
+ ktime_t timeout, time_checked;
+ u32 value;
+
+ if (host->ref_clk_enabled == on)
+ return 0;
+
+ if (on) {
+ ufs_mtk_ref_clk_notify(on, res);
+ ufshcd_delay_us(host->ref_clk_ungating_wait_us, 10);
+ ufshcd_writel(hba, REFCLK_REQUEST, REG_UFS_REFCLK_CTRL);
+ } else {
+ ufshcd_writel(hba, REFCLK_RELEASE, REG_UFS_REFCLK_CTRL);
+ }
+
+ /* Wait for ack */
+ timeout = ktime_add_us(ktime_get(), REFCLK_REQ_TIMEOUT_US);
+ do {
+ time_checked = ktime_get();
+ value = ufshcd_readl(hba, REG_UFS_REFCLK_CTRL);
+
+ /* Wait until ack bit equals to req bit */
+ if (((value & REFCLK_ACK) >> 1) == (value & REFCLK_REQUEST))
+ goto out;
+
+ usleep_range(100, 200);
+ } while (ktime_before(time_checked, timeout));
+
+ dev_err(hba->dev, "missing ack of refclk req, reg: 0x%x\n", value);
+
+ ufs_mtk_ref_clk_notify(host->ref_clk_enabled, res);
+
+ return -ETIMEDOUT;
+
+out:
+ host->ref_clk_enabled = on;
+ if (!on) {
+ ufshcd_delay_us(host->ref_clk_gating_wait_us, 10);
+ ufs_mtk_ref_clk_notify(on, res);
+ }
+
+ return 0;
+}
+
+static void ufs_mtk_setup_ref_clk_wait_us(struct ufs_hba *hba,
+ u16 gating_us, u16 ungating_us)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+
+ if (hba->dev_info.clk_gating_wait_us) {
+ host->ref_clk_gating_wait_us =
+ hba->dev_info.clk_gating_wait_us;
+ } else {
+ host->ref_clk_gating_wait_us = gating_us;
+ }
+
+ host->ref_clk_ungating_wait_us = ungating_us;
+}
+
+static int ufs_mtk_wait_link_state(struct ufs_hba *hba, u32 state,
+ unsigned long max_wait_ms)
+{
+ ktime_t timeout, time_checked;
+ u32 val;
+
+ timeout = ktime_add_ms(ktime_get(), max_wait_ms);
+ do {
+ time_checked = ktime_get();
+ ufshcd_writel(hba, 0x20, REG_UFS_DEBUG_SEL);
+ val = ufshcd_readl(hba, REG_UFS_PROBE);
+ val = val >> 28;
+
+ if (val == state)
+ return 0;
+
+ /* Sleep for max. 200us */
+ usleep_range(100, 200);
+ } while (ktime_before(time_checked, timeout));
+
+ if (val == state)
+ return 0;
+
+ return -ETIMEDOUT;
+}
+
+static void ufs_mtk_mphy_power_on(struct ufs_hba *hba, bool on)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+ struct phy *mphy = host->mphy;
+
+ if (!mphy)
+ return;
+
+ if (on && !host->mphy_powered_on)
+ phy_power_on(mphy);
+ else if (!on && host->mphy_powered_on)
+ phy_power_off(mphy);
+ else
+ return;
+ host->mphy_powered_on = on;
+}
+
+static int ufs_mtk_get_host_clk(struct device *dev, const char *name,
+ struct clk **clk_out)
+{
+ struct clk *clk;
+ int err = 0;
+
+ clk = devm_clk_get(dev, name);
+ if (IS_ERR(clk))
+ err = PTR_ERR(clk);
+ else
+ *clk_out = clk;
+
+ return err;
+}
+
+static void ufs_mtk_boost_crypt(struct ufs_hba *hba, bool boost)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+ struct ufs_mtk_crypt_cfg *cfg;
+ struct regulator *reg;
+ int volt, ret;
+
+ if (!ufs_mtk_is_boost_crypt_enabled(hba))
+ return;
+
+ cfg = host->crypt;
+ volt = cfg->vcore_volt;
+ reg = cfg->reg_vcore;
+
+ ret = clk_prepare_enable(cfg->clk_crypt_mux);
+ if (ret) {
+ dev_info(hba->dev, "clk_prepare_enable(): %d\n",
+ ret);
+ return;
+ }
+
+ if (boost) {
+ ret = regulator_set_voltage(reg, volt, INT_MAX);
+ if (ret) {
+ dev_info(hba->dev,
+ "failed to set vcore to %d\n", volt);
+ goto out;
+ }
+
+ ret = clk_set_parent(cfg->clk_crypt_mux,
+ cfg->clk_crypt_perf);
+ if (ret) {
+ dev_info(hba->dev,
+ "failed to set clk_crypt_perf\n");
+ regulator_set_voltage(reg, 0, INT_MAX);
+ goto out;
+ }
+ } else {
+ ret = clk_set_parent(cfg->clk_crypt_mux,
+ cfg->clk_crypt_lp);
+ if (ret) {
+ dev_info(hba->dev,
+ "failed to set clk_crypt_lp\n");
+ goto out;
+ }
+
+ ret = regulator_set_voltage(reg, 0, INT_MAX);
+ if (ret) {
+ dev_info(hba->dev,
+ "failed to set vcore to MIN\n");
+ }
+ }
+out:
+ clk_disable_unprepare(cfg->clk_crypt_mux);
+}
+
+static int ufs_mtk_init_host_clk(struct ufs_hba *hba, const char *name,
+ struct clk **clk)
+{
+ int ret;
+
+ ret = ufs_mtk_get_host_clk(hba->dev, name, clk);
+ if (ret) {
+ dev_info(hba->dev, "%s: failed to get %s: %d", __func__,
+ name, ret);
+ }
+
+ return ret;
+}
+
+static void ufs_mtk_init_host_caps(struct ufs_hba *hba)
+{
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+ struct ufs_mtk_crypt_cfg *cfg;
+ struct device *dev = hba->dev;
+ struct regulator *reg;
+ u32 volt;
+
+ host->caps = host->cfg->caps;
+
+ if (!ufs_mtk_is_boost_crypt_enabled(hba))
+ return;
+
+ host->crypt = devm_kzalloc(dev, sizeof(*(host->crypt)),
+ GFP_KERNEL);
+ if (!host->crypt)
+ goto disable_caps;
+
+ reg = devm_regulator_get_optional(dev, "dvfsrc-vcore");
+ if (IS_ERR(reg)) {
+ dev_info(dev, "failed to get dvfsrc-vcore: %ld",
+ PTR_ERR(reg));
+ goto disable_caps;
+ }
+
+ if (of_property_read_u32(dev->of_node, "boost-crypt-vcore-min",
+ &volt)) {
+ dev_info(dev, "failed to get boost-crypt-vcore-min");
+ goto disable_caps;
+ }
+
+ cfg = host->crypt;
+ if (ufs_mtk_init_host_clk(hba, "crypt_mux",
+ &cfg->clk_crypt_mux))
+ goto disable_caps;
+
+ if (ufs_mtk_init_host_clk(hba, "crypt_lp",
+ &cfg->clk_crypt_lp))
+ goto disable_caps;
+
+ if (ufs_mtk_init_host_clk(hba, "crypt_perf",
+ &cfg->clk_crypt_perf))
+ goto disable_caps;
+
+ cfg->reg_vcore = reg;
+ cfg->vcore_volt = volt;
+ dev_info(dev, "caps: boost-crypt");
+ return;
+
+disable_caps:
+ host->caps &= ~UFS_MTK_CAP_BOOST_CRYPT_ENGINE;
+}
+
/**
* ufs_mtk_setup_clocks - enables/disable clocks
* @hba: host controller instance
@@ -94,7 +467,8 @@
enum ufs_notify_change_status status)
{
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
- int ret = -EINVAL;
+ int ret = 0;
+ bool clk_pwr_off = false;
/*
* In case ufs_mtk_init() is not yet done, simply ignore.
@@ -104,15 +478,33 @@
if (!host)
return 0;
- switch (status) {
- case PRE_CHANGE:
- if (!on)
- ret = phy_power_off(host->mphy);
- break;
- case POST_CHANGE:
- if (on)
- ret = phy_power_on(host->mphy);
- break;
+ if (!on && status == PRE_CHANGE) {
+ if (ufshcd_is_link_off(hba)) {
+ clk_pwr_off = true;
+ } else if (ufshcd_is_link_hibern8(hba) ||
+ (!ufshcd_can_hibern8_during_gating(hba) &&
+ ufshcd_is_auto_hibern8_enabled(hba))) {
+ /*
+ * Gate ref-clk and poweroff mphy if link state is in
+ * OFF or Hibern8 by either Auto-Hibern8 or
+ * ufshcd_link_state_transition().
+ */
+ ret = ufs_mtk_wait_link_state(hba,
+ VS_LINK_HIBERN8,
+ 15);
+ if (!ret)
+ clk_pwr_off = true;
+ }
+
+ if (clk_pwr_off) {
+ ufs_mtk_boost_crypt(hba, on);
+ ufs_mtk_setup_ref_clk(hba, on);
+ ufs_mtk_mphy_power_on(hba, on);
+ }
+ } else if (on && status == POST_CHANGE) {
+ ufs_mtk_mphy_power_on(hba, on);
+ ufs_mtk_setup_ref_clk(hba, on);
+ ufs_mtk_boost_crypt(hba, on);
}
return ret;
@@ -130,8 +522,9 @@
*/
static int ufs_mtk_init(struct ufs_hba *hba)
{
- struct ufs_mtk_host *host;
+ const struct of_device_id *id;
struct device *dev = hba->dev;
+ struct ufs_mtk_host *host;
int err = 0;
host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
@@ -144,10 +537,38 @@
host->hba = hba;
ufshcd_set_variant(hba, host);
+ /* Get host capability and platform data */
+ id = of_match_device(ufs_mtk_of_match, dev);
+ if (!id) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (id->data) {
+ host->cfg = (struct ufs_mtk_host_cfg *)id->data;
+ ufs_mtk_init_host_caps(hba);
+ }
+
err = ufs_mtk_bind_mphy(hba);
if (err)
goto out_variant_clear;
+ ufs_mtk_init_reset(hba);
+
+ /* Enable runtime autosuspend */
+ hba->caps |= UFSHCD_CAP_RPM_AUTOSUSPEND;
+
+ /* Enable clock-gating */
+ hba->caps |= UFSHCD_CAP_CLK_GATING;
+
+ /* Enable inline encryption */
+ hba->caps |= UFSHCD_CAP_CRYPTO;
+
+ /* Enable WriteBooster */
+ hba->caps |= UFSHCD_CAP_WB_EN;
+ hba->quirks |= UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL;
+ hba->vps->wb_flush_threshold = UFS_WB_BUF_REMAIN_PERCENT(80);
+
/*
* ufshcd_vops_init() is invoked after
* ufshcd_setup_clock(true) in ufshcd_hba_init() thus
@@ -219,11 +640,44 @@
return ret;
}
+static int ufs_mtk_unipro_set_pm(struct ufs_hba *hba, bool lpm)
+{
+ int ret;
+ struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+
+ ret = ufshcd_dme_set(hba,
+ UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0),
+ lpm);
+ if (!ret || !lpm) {
+ /*
+ * Forcibly set as non-LPM mode if UIC commands is failed
+ * to use default hba_enable_delay_us value for re-enabling
+ * the host.
+ */
+ host->unipro_lpm = lpm;
+ }
+
+ return ret;
+}
+
static int ufs_mtk_pre_link(struct ufs_hba *hba)
{
int ret;
u32 tmp;
+ ret = ufs_mtk_unipro_set_pm(hba, false);
+ if (ret)
+ return ret;
+
+ /*
+ * Setting PA_Local_TX_LCC_Enable to 0 before link startup
+ * to make sure that both host and device TX LCC are disabled
+ * once link startup is completed.
+ */
+ ret = ufshcd_disable_host_tx_lcc(hba);
+ if (ret)
+ return ret;
+
/* disable deep stall */
ret = ufshcd_dme_get(hba, UIC_ARG_MIB(VS_SAVEPOWERCONTROL), &tmp);
if (ret)
@@ -236,14 +690,37 @@
return ret;
}
+static void ufs_mtk_setup_clk_gating(struct ufs_hba *hba)
+{
+ unsigned long flags;
+ u32 ah_ms;
+
+ if (ufshcd_is_clkgating_allowed(hba)) {
+ if (ufshcd_is_auto_hibern8_supported(hba) && hba->ahit)
+ ah_ms = FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK,
+ hba->ahit);
+ else
+ ah_ms = 10;
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ hba->clk_gating.delay_ms = ah_ms + 5;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+ }
+}
+
static int ufs_mtk_post_link(struct ufs_hba *hba)
{
- /* disable device LCC */
- ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0);
-
/* enable unipro clock gating feature */
ufs_mtk_cfg_unipro_cg(hba, true);
+ /* configure auto-hibern8 timer to 10ms */
+ if (ufshcd_is_auto_hibern8_supported(hba)) {
+ ufshcd_auto_hibern8_update(hba,
+ FIELD_PREP(UFSHCI_AHIBERN8_TIMER_MASK, 10) |
+ FIELD_PREP(UFSHCI_AHIBERN8_SCALE_MASK, 3));
+ }
+
+ ufs_mtk_setup_clk_gating(hba);
+
return 0;
}
@@ -267,50 +744,191 @@
return ret;
}
+static int ufs_mtk_device_reset(struct ufs_hba *hba)
+{
+ struct arm_smccc_res res;
+
+ ufs_mtk_device_reset_ctrl(0, res);
+
+ /*
+ * The reset signal is active low. UFS devices shall detect
+ * more than or equal to 1us of positive or negative RST_n
+ * pulse width.
+ *
+ * To be on safe side, keep the reset low for at least 10us.
+ */
+ usleep_range(10, 15);
+
+ ufs_mtk_device_reset_ctrl(1, res);
+
+ /* Some devices may need time to respond to rst_n */
+ usleep_range(10000, 15000);
+
+ dev_info(hba->dev, "device reset done\n");
+
+ return 0;
+}
+
+static int ufs_mtk_link_set_hpm(struct ufs_hba *hba)
+{
+ int err;
+
+ err = ufshcd_hba_enable(hba);
+ if (err)
+ return err;
+
+ err = ufs_mtk_unipro_set_pm(hba, false);
+ if (err)
+ return err;
+
+ err = ufshcd_uic_hibern8_exit(hba);
+ if (!err)
+ ufshcd_set_link_active(hba);
+ else
+ return err;
+
+ err = ufshcd_make_hba_operational(hba);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int ufs_mtk_link_set_lpm(struct ufs_hba *hba)
+{
+ int err;
+
+ err = ufs_mtk_unipro_set_pm(hba, true);
+ if (err) {
+ /* Resume UniPro state for following error recovery */
+ ufs_mtk_unipro_set_pm(hba, false);
+ return err;
+ }
+
+ return 0;
+}
+
+static void ufs_mtk_vreg_set_lpm(struct ufs_hba *hba, bool lpm)
+{
+ if (!hba->vreg_info.vccq2 || !hba->vreg_info.vcc)
+ return;
+
+ if (lpm && !hba->vreg_info.vcc->enabled)
+ regulator_set_mode(hba->vreg_info.vccq2->reg,
+ REGULATOR_MODE_IDLE);
+ else if (!lpm)
+ regulator_set_mode(hba->vreg_info.vccq2->reg,
+ REGULATOR_MODE_NORMAL);
+}
+
static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
{
- struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+ int err;
+ struct arm_smccc_res res;
- if (ufshcd_is_link_hibern8(hba))
- phy_power_off(host->mphy);
+ if (ufshcd_is_link_hibern8(hba)) {
+ err = ufs_mtk_link_set_lpm(hba);
+ if (err) {
+ /*
+ * Set link as off state enforcedly to trigger
+ * ufshcd_host_reset_and_restore() in ufshcd_suspend()
+ * for completed host reset.
+ */
+ ufshcd_set_link_off(hba);
+ return -EAGAIN;
+ }
+ /*
+ * Make sure no error will be returned to prevent
+ * ufshcd_suspend() re-enabling regulators while vreg is still
+ * in low-power mode.
+ */
+ ufs_mtk_vreg_set_lpm(hba, true);
+ }
+
+ if (ufshcd_is_link_off(hba))
+ ufs_mtk_device_reset_ctrl(0, res);
return 0;
}
static int ufs_mtk_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
{
- struct ufs_mtk_host *host = ufshcd_get_variant(hba);
+ int err;
- if (ufshcd_is_link_hibern8(hba))
- phy_power_on(host->mphy);
+ if (ufshcd_is_link_hibern8(hba)) {
+ ufs_mtk_vreg_set_lpm(hba, false);
+ err = ufs_mtk_link_set_hpm(hba);
+ if (err) {
+ err = ufshcd_link_recovery(hba);
+ return err;
+ }
+ }
return 0;
}
-static int ufs_mtk_apply_dev_quirks(struct ufs_hba *hba,
- struct ufs_dev_desc *card)
+static void ufs_mtk_dbg_register_dump(struct ufs_hba *hba)
{
- if (card->wmanufacturerid == UFS_VENDOR_SAMSUNG)
+ ufshcd_dump_regs(hba, REG_UFS_REFCLK_CTRL, 0x4, "Ref-Clk Ctrl ");
+
+ ufshcd_dump_regs(hba, REG_UFS_EXTREG, 0x4, "Ext Reg ");
+
+ ufshcd_dump_regs(hba, REG_UFS_MPHYCTRL,
+ REG_UFS_REJECT_MON - REG_UFS_MPHYCTRL + 4,
+ "MPHY Ctrl ");
+
+ /* Direct debugging information to REG_MTK_PROBE */
+ ufshcd_writel(hba, 0x20, REG_UFS_DEBUG_SEL);
+ ufshcd_dump_regs(hba, REG_UFS_PROBE, 0x4, "Debug Probe ");
+}
+
+static int ufs_mtk_apply_dev_quirks(struct ufs_hba *hba)
+{
+ struct ufs_dev_info *dev_info = &hba->dev_info;
+ u16 mid = dev_info->wmanufacturerid;
+
+ if (mid == UFS_VENDOR_SAMSUNG)
ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 6);
+ /*
+ * Decide waiting time before gating reference clock and
+ * after ungating reference clock according to vendors'
+ * requirements.
+ */
+ if (mid == UFS_VENDOR_SAMSUNG)
+ ufs_mtk_setup_ref_clk_wait_us(hba, 1, 1);
+ else if (mid == UFS_VENDOR_SKHYNIX)
+ ufs_mtk_setup_ref_clk_wait_us(hba, 30, 30);
+ else if (mid == UFS_VENDOR_TOSHIBA)
+ ufs_mtk_setup_ref_clk_wait_us(hba, 100, 32);
+
return 0;
}
-/**
+static void ufs_mtk_fixup_dev_quirks(struct ufs_hba *hba)
+{
+ ufshcd_fixup_dev_quirks(hba, ufs_mtk_dev_fixups);
+}
+
+/*
* struct ufs_hba_mtk_vops - UFS MTK specific variant operations
*
* The variant operations configure the necessary controller and PHY
* handshake during initialization.
*/
-static struct ufs_hba_variant_ops ufs_hba_mtk_vops = {
+static const struct ufs_hba_variant_ops ufs_hba_mtk_vops = {
.name = "mediatek.ufshci",
.init = ufs_mtk_init,
.setup_clocks = ufs_mtk_setup_clocks,
+ .hce_enable_notify = ufs_mtk_hce_enable_notify,
.link_startup_notify = ufs_mtk_link_startup_notify,
.pwr_change_notify = ufs_mtk_pwr_change_notify,
.apply_dev_quirks = ufs_mtk_apply_dev_quirks,
+ .fixup_dev_quirks = ufs_mtk_fixup_dev_quirks,
.suspend = ufs_mtk_suspend,
.resume = ufs_mtk_resume,
+ .dbg_register_dump = ufs_mtk_dbg_register_dump,
+ .device_reset = ufs_mtk_device_reset,
};
/**
@@ -347,11 +965,6 @@
return 0;
}
-static const struct of_device_id ufs_mtk_of_match[] = {
- { .compatible = "mediatek,mt8183-ufshci"},
- {},
-};
-
static const struct dev_pm_ops ufs_mtk_pm_ops = {
.suspend = ufshcd_pltfrm_suspend,
.resume = ufshcd_pltfrm_resume,
diff --git a/drivers/scsi/ufs/ufs-mediatek.h b/drivers/scsi/ufs/ufs-mediatek.h
index 19f8c42..2b6a131 100644
--- a/drivers/scsi/ufs/ufs-mediatek.h
+++ b/drivers/scsi/ufs/ufs-mediatek.h
@@ -6,11 +6,35 @@
#ifndef _UFS_MEDIATEK_H
#define _UFS_MEDIATEK_H
+#include <linux/bitops.h>
+#include <linux/soc/mediatek/mtk_sip_svc.h>
+
+/*
+ * Vendor specific UFSHCI Registers
+ */
+#define REG_UFS_REFCLK_CTRL 0x144
+#define REG_UFS_EXTREG 0x2100
+#define REG_UFS_MPHYCTRL 0x2200
+#define REG_UFS_REJECT_MON 0x22AC
+#define REG_UFS_DEBUG_SEL 0x22C0
+#define REG_UFS_PROBE 0x22C8
+
+/*
+ * Ref-clk control
+ *
+ * Values for register REG_UFS_REFCLK_CTRL
+ */
+#define REFCLK_RELEASE 0x0
+#define REFCLK_REQUEST BIT(0)
+#define REFCLK_ACK BIT(1)
+
+#define REFCLK_REQ_TIMEOUT_US 3000
+
/*
* Vendor specific pre-defined parameters
*/
-#define UFS_MTK_LIMIT_NUM_LANES_RX 1
-#define UFS_MTK_LIMIT_NUM_LANES_TX 1
+#define UFS_MTK_LIMIT_NUM_LANES_RX 2
+#define UFS_MTK_LIMIT_NUM_LANES_TX 2
#define UFS_MTK_LIMIT_HSGEAR_RX UFS_HS_G3
#define UFS_MTK_LIMIT_HSGEAR_TX UFS_HS_G3
#define UFS_MTK_LIMIT_PWMGEAR_RX UFS_PWM_G4
@@ -30,6 +54,26 @@
#define VS_UNIPROPOWERDOWNCONTROL 0xD0A8
/*
+ * Vendor specific link state
+ */
+enum {
+ VS_LINK_DISABLED = 0,
+ VS_LINK_DOWN = 1,
+ VS_LINK_UP = 2,
+ VS_LINK_HIBERN8 = 3,
+ VS_LINK_LOST = 4,
+ VS_LINK_CFG = 5,
+};
+
+/*
+ * SiP commands
+ */
+#define MTK_SIP_UFS_CONTROL MTK_SIP_SMC_CMD(0x276)
+#define UFS_MTK_SIP_DEVICE_RESET BIT(1)
+#define UFS_MTK_SIP_CRYPTO_CTRL BIT(2)
+#define UFS_MTK_SIP_REF_CLK_NOTIFICATION BIT(3)
+
+/*
* VS_DEBUGCLOCKENABLE
*/
enum {
@@ -45,9 +89,39 @@
TX_CLK_GATE_EN = 3,
};
+/*
+ * Host capability
+ */
+enum ufs_mtk_host_caps {
+ UFS_MTK_CAP_BOOST_CRYPT_ENGINE = 1 << 0,
+};
+
+struct ufs_mtk_crypt_cfg {
+ struct regulator *reg_vcore;
+ struct clk *clk_crypt_perf;
+ struct clk *clk_crypt_mux;
+ struct clk *clk_crypt_lp;
+ int vcore_volt;
+};
+
+struct ufs_mtk_host_cfg {
+ enum ufs_mtk_host_caps caps;
+};
+
struct ufs_mtk_host {
struct ufs_hba *hba;
struct phy *mphy;
+ struct ufs_mtk_host_cfg *cfg;
+ struct ufs_mtk_crypt_cfg *crypt;
+ enum ufs_mtk_host_caps caps;
+ struct reset_control *hci_reset;
+ struct reset_control *unipro_reset;
+ struct reset_control *crypto_reset;
+ bool mphy_powered_on;
+ bool unipro_lpm;
+ bool ref_clk_enabled;
+ u16 ref_clk_ungating_wait_us;
+ u16 ref_clk_gating_wait_us;
};
#endif /* !_UFS_MEDIATEK_H */
diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c
new file mode 100644
index 0000000..bbb0ad7
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-qcom-ice.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Qualcomm ICE (Inline Crypto Engine) support.
+ *
+ * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
+ * Copyright 2019 Google LLC
+ */
+
+#include <linux/platform_device.h>
+#include <linux/qcom_scm.h>
+
+#include "ufshcd-crypto.h"
+#include "ufs-qcom.h"
+
+#define AES_256_XTS_KEY_SIZE 64
+
+/* QCOM ICE registers */
+
+#define QCOM_ICE_REG_CONTROL 0x0000
+#define QCOM_ICE_REG_RESET 0x0004
+#define QCOM_ICE_REG_VERSION 0x0008
+#define QCOM_ICE_REG_FUSE_SETTING 0x0010
+#define QCOM_ICE_REG_PARAMETERS_1 0x0014
+#define QCOM_ICE_REG_PARAMETERS_2 0x0018
+#define QCOM_ICE_REG_PARAMETERS_3 0x001C
+#define QCOM_ICE_REG_PARAMETERS_4 0x0020
+#define QCOM_ICE_REG_PARAMETERS_5 0x0024
+
+/* QCOM ICE v3.X only */
+#define QCOM_ICE_GENERAL_ERR_STTS 0x0040
+#define QCOM_ICE_INVALID_CCFG_ERR_STTS 0x0030
+#define QCOM_ICE_GENERAL_ERR_MASK 0x0044
+
+/* QCOM ICE v2.X only */
+#define QCOM_ICE_REG_NON_SEC_IRQ_STTS 0x0040
+#define QCOM_ICE_REG_NON_SEC_IRQ_MASK 0x0044
+
+#define QCOM_ICE_REG_NON_SEC_IRQ_CLR 0x0048
+#define QCOM_ICE_REG_STREAM1_ERROR_SYNDROME1 0x0050
+#define QCOM_ICE_REG_STREAM1_ERROR_SYNDROME2 0x0054
+#define QCOM_ICE_REG_STREAM2_ERROR_SYNDROME1 0x0058
+#define QCOM_ICE_REG_STREAM2_ERROR_SYNDROME2 0x005C
+#define QCOM_ICE_REG_STREAM1_BIST_ERROR_VEC 0x0060
+#define QCOM_ICE_REG_STREAM2_BIST_ERROR_VEC 0x0064
+#define QCOM_ICE_REG_STREAM1_BIST_FINISH_VEC 0x0068
+#define QCOM_ICE_REG_STREAM2_BIST_FINISH_VEC 0x006C
+#define QCOM_ICE_REG_BIST_STATUS 0x0070
+#define QCOM_ICE_REG_BYPASS_STATUS 0x0074
+#define QCOM_ICE_REG_ADVANCED_CONTROL 0x1000
+#define QCOM_ICE_REG_ENDIAN_SWAP 0x1004
+#define QCOM_ICE_REG_TEST_BUS_CONTROL 0x1010
+#define QCOM_ICE_REG_TEST_BUS_REG 0x1014
+
+/* BIST ("built-in self-test"?) status flags */
+#define QCOM_ICE_BIST_STATUS_MASK 0xF0000000
+
+#define QCOM_ICE_FUSE_SETTING_MASK 0x1
+#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK 0x2
+#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK 0x4
+
+#define qcom_ice_writel(host, val, reg) \
+ writel((val), (host)->ice_mmio + (reg))
+#define qcom_ice_readl(host, reg) \
+ readl((host)->ice_mmio + (reg))
+
+static bool qcom_ice_supported(struct ufs_qcom_host *host)
+{
+ struct device *dev = host->hba->dev;
+ u32 regval = qcom_ice_readl(host, QCOM_ICE_REG_VERSION);
+ int major = regval >> 24;
+ int minor = (regval >> 16) & 0xFF;
+ int step = regval & 0xFFFF;
+
+ /* For now this driver only supports ICE version 3. */
+ if (major != 3) {
+ dev_warn(dev, "Unsupported ICE version: v%d.%d.%d\n",
+ major, minor, step);
+ return false;
+ }
+
+ dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n",
+ major, minor, step);
+
+ /* If fuses are blown, ICE might not work in the standard way. */
+ regval = qcom_ice_readl(host, QCOM_ICE_REG_FUSE_SETTING);
+ if (regval & (QCOM_ICE_FUSE_SETTING_MASK |
+ QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK |
+ QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK)) {
+ dev_warn(dev, "Fuses are blown; ICE is unusable!\n");
+ return false;
+ }
+ return true;
+}
+
+int ufs_qcom_ice_init(struct ufs_qcom_host *host)
+{
+ struct ufs_hba *hba = host->hba;
+ struct device *dev = hba->dev;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *res;
+ int err;
+
+ if (!(ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES) &
+ MASK_CRYPTO_SUPPORT))
+ return 0;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice");
+ if (!res) {
+ dev_warn(dev, "ICE registers not found\n");
+ goto disable;
+ }
+
+ if (!qcom_scm_ice_available()) {
+ dev_warn(dev, "ICE SCM interface not found\n");
+ goto disable;
+ }
+
+ host->ice_mmio = devm_ioremap_resource(dev, res);
+ if (IS_ERR(host->ice_mmio)) {
+ err = PTR_ERR(host->ice_mmio);
+ dev_err(dev, "Failed to map ICE registers; err=%d\n", err);
+ return err;
+ }
+
+ if (!qcom_ice_supported(host))
+ goto disable;
+
+ return 0;
+
+disable:
+ dev_warn(dev, "Disabling inline encryption support\n");
+ hba->caps &= ~UFSHCD_CAP_CRYPTO;
+ return 0;
+}
+
+static void qcom_ice_low_power_mode_enable(struct ufs_qcom_host *host)
+{
+ u32 regval;
+
+ regval = qcom_ice_readl(host, QCOM_ICE_REG_ADVANCED_CONTROL);
+ /*
+ * Enable low power mode sequence
+ * [0]-0, [1]-0, [2]-0, [3]-E, [4]-0, [5]-0, [6]-0, [7]-0
+ */
+ regval |= 0x7000;
+ qcom_ice_writel(host, regval, QCOM_ICE_REG_ADVANCED_CONTROL);
+}
+
+static void qcom_ice_optimization_enable(struct ufs_qcom_host *host)
+{
+ u32 regval;
+
+ /* ICE Optimizations Enable Sequence */
+ regval = qcom_ice_readl(host, QCOM_ICE_REG_ADVANCED_CONTROL);
+ regval |= 0xD807100;
+ /* ICE HPG requires delay before writing */
+ udelay(5);
+ qcom_ice_writel(host, regval, QCOM_ICE_REG_ADVANCED_CONTROL);
+ udelay(5);
+}
+
+int ufs_qcom_ice_enable(struct ufs_qcom_host *host)
+{
+ if (!(host->hba->caps & UFSHCD_CAP_CRYPTO))
+ return 0;
+ qcom_ice_low_power_mode_enable(host);
+ qcom_ice_optimization_enable(host);
+ return ufs_qcom_ice_resume(host);
+}
+
+/* Poll until all BIST bits are reset */
+static int qcom_ice_wait_bist_status(struct ufs_qcom_host *host)
+{
+ int count;
+ u32 reg;
+
+ for (count = 0; count < 100; count++) {
+ reg = qcom_ice_readl(host, QCOM_ICE_REG_BIST_STATUS);
+ if (!(reg & QCOM_ICE_BIST_STATUS_MASK))
+ break;
+ udelay(50);
+ }
+ if (reg)
+ return -ETIMEDOUT;
+ return 0;
+}
+
+int ufs_qcom_ice_resume(struct ufs_qcom_host *host)
+{
+ int err;
+
+ if (!(host->hba->caps & UFSHCD_CAP_CRYPTO))
+ return 0;
+
+ err = qcom_ice_wait_bist_status(host);
+ if (err) {
+ dev_err(host->hba->dev, "BIST status error (%d)\n", err);
+ return err;
+ }
+ return 0;
+}
+
+/*
+ * Program a key into a QC ICE keyslot, or evict a keyslot. QC ICE requires
+ * vendor-specific SCM calls for this; it doesn't support the standard way.
+ */
+int ufs_qcom_ice_program_key(struct ufs_hba *hba,
+ const union ufs_crypto_cfg_entry *cfg, int slot)
+{
+ union ufs_crypto_cap_entry cap;
+ union {
+ u8 bytes[AES_256_XTS_KEY_SIZE];
+ u32 words[AES_256_XTS_KEY_SIZE / sizeof(u32)];
+ } key;
+ int i;
+ int err;
+
+ if (!(cfg->config_enable & UFS_CRYPTO_CONFIGURATION_ENABLE))
+ return qcom_scm_ice_invalidate_key(slot);
+
+ /* Only AES-256-XTS has been tested so far. */
+ cap = hba->crypto_cap_array[cfg->crypto_cap_idx];
+ if (cap.algorithm_id != UFS_CRYPTO_ALG_AES_XTS ||
+ cap.key_size != UFS_CRYPTO_KEY_SIZE_256) {
+ dev_err_ratelimited(hba->dev,
+ "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n",
+ cap.algorithm_id, cap.key_size);
+ return -EINVAL;
+ }
+
+ memcpy(key.bytes, cfg->crypto_key, AES_256_XTS_KEY_SIZE);
+
+ /*
+ * The SCM call byte-swaps the 32-bit words of the key. So we have to
+ * do the same, in order for the final key be correct.
+ */
+ for (i = 0; i < ARRAY_SIZE(key.words); i++)
+ __cpu_to_be32s(&key.words[i]);
+
+ err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE,
+ QCOM_SCM_ICE_CIPHER_AES_256_XTS,
+ cfg->data_unit_size);
+ memzero_explicit(&key, sizeof(key));
+ return err;
+}
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 4f066e3..20182e3 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -10,6 +10,7 @@
#include <linux/phy/phy.h>
#include <linux/gpio/consumer.h>
#include <linux/reset-controller.h>
+#include <linux/devfreq.h>
#include "ufshcd.h"
#include "ufshcd-pltfrm.h"
@@ -38,7 +39,6 @@
static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS];
-static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host);
static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba,
u32 clk_cycles);
@@ -246,6 +246,54 @@
mb();
}
+/*
+ * ufs_qcom_host_reset - reset host controller and PHY
+ */
+static int ufs_qcom_host_reset(struct ufs_hba *hba)
+{
+ int ret = 0;
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ bool reenable_intr = false;
+
+ if (!host->core_reset) {
+ dev_warn(hba->dev, "%s: reset control not set\n", __func__);
+ goto out;
+ }
+
+ reenable_intr = hba->is_irq_enabled;
+ disable_irq(hba->irq);
+ hba->is_irq_enabled = false;
+
+ ret = reset_control_assert(host->core_reset);
+ if (ret) {
+ dev_err(hba->dev, "%s: core_reset assert failed, err = %d\n",
+ __func__, ret);
+ goto out;
+ }
+
+ /*
+ * The hardware requirement for delay between assert/deassert
+ * is at least 3-4 sleep clock (32.7KHz) cycles, which comes to
+ * ~125us (4/32768). To be on the safe side add 200us delay.
+ */
+ usleep_range(200, 210);
+
+ ret = reset_control_deassert(host->core_reset);
+ if (ret)
+ dev_err(hba->dev, "%s: core_reset deassert failed, err = %d\n",
+ __func__, ret);
+
+ usleep_range(1000, 1100);
+
+ if (reenable_intr) {
+ enable_irq(hba->irq);
+ hba->is_irq_enabled = true;
+ }
+
+out:
+ return ret;
+}
+
static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
@@ -254,6 +302,12 @@
bool is_rate_B = (UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B)
? true : false;
+ /* Reset UFS Host Controller and PHY */
+ ret = ufs_qcom_host_reset(hba);
+ if (ret)
+ dev_warn(hba->dev, "%s: host reset returned %d\n",
+ __func__, ret);
+
if (is_rate_B)
phy_set_mode(phy, PHY_MODE_UFS_HS_B);
@@ -321,7 +375,7 @@
/* check if UFS PHY moved from DISABLED to HIBERN8 */
err = ufs_qcom_check_hibern8(hba);
ufs_qcom_enable_hw_clk_gating(hba);
-
+ ufs_qcom_ice_enable(host);
break;
default:
dev_err(hba->dev, "%s: invalid status %d\n", __func__, status);
@@ -331,7 +385,7 @@
return err;
}
-/**
+/*
* Returns zero for success and non-zero in case of a failure
*/
static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear,
@@ -510,9 +564,7 @@
* completed.
*/
if (ufshcd_get_local_unipro_ver(hba) != UFS_UNIPRO_VER_1_41)
- err = ufshcd_dme_set(hba,
- UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE),
- 0);
+ err = ufshcd_disable_host_tx_lcc(hba);
break;
case POST_CHANGE:
@@ -530,7 +582,6 @@
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
struct phy *phy = host->generic_phy;
- int ret = 0;
if (ufs_qcom_is_link_off(hba)) {
/*
@@ -545,7 +596,7 @@
ufs_qcom_disable_lane_clks(host);
}
- return ret;
+ return 0;
}
static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
@@ -572,193 +623,14 @@
return err;
}
+ err = ufs_qcom_ice_resume(host);
+ if (err)
+ return err;
+
hba->is_sys_suspended = false;
return 0;
}
-#ifdef CONFIG_MSM_BUS_SCALING
-static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
- const char *speed_mode)
-{
- struct device *dev = host->hba->dev;
- struct device_node *np = dev->of_node;
- int err;
- const char *key = "qcom,bus-vector-names";
-
- if (!speed_mode) {
- err = -EINVAL;
- goto out;
- }
-
- if (host->bus_vote.is_max_bw_needed && !!strcmp(speed_mode, "MIN"))
- err = of_property_match_string(np, key, "MAX");
- else
- err = of_property_match_string(np, key, speed_mode);
-
-out:
- if (err < 0)
- dev_err(dev, "%s: Invalid %s mode %d\n",
- __func__, speed_mode, err);
- return err;
-}
-
-static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result)
-{
- int gear = max_t(u32, p->gear_rx, p->gear_tx);
- int lanes = max_t(u32, p->lane_rx, p->lane_tx);
- int pwr;
-
- /* default to PWM Gear 1, Lane 1 if power mode is not initialized */
- if (!gear)
- gear = 1;
-
- if (!lanes)
- lanes = 1;
-
- if (!p->pwr_rx && !p->pwr_tx) {
- pwr = SLOWAUTO_MODE;
- snprintf(result, BUS_VECTOR_NAME_LEN, "MIN");
- } else if (p->pwr_rx == FAST_MODE || p->pwr_rx == FASTAUTO_MODE ||
- p->pwr_tx == FAST_MODE || p->pwr_tx == FASTAUTO_MODE) {
- pwr = FAST_MODE;
- snprintf(result, BUS_VECTOR_NAME_LEN, "%s_R%s_G%d_L%d", "HS",
- p->hs_rate == PA_HS_MODE_B ? "B" : "A", gear, lanes);
- } else {
- pwr = SLOW_MODE;
- snprintf(result, BUS_VECTOR_NAME_LEN, "%s_G%d_L%d",
- "PWM", gear, lanes);
- }
-}
-
-static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote)
-{
- int err = 0;
-
- if (vote != host->bus_vote.curr_vote) {
- err = msm_bus_scale_client_update_request(
- host->bus_vote.client_handle, vote);
- if (err) {
- dev_err(host->hba->dev,
- "%s: msm_bus_scale_client_update_request() failed: bus_client_handle=0x%x, vote=%d, err=%d\n",
- __func__, host->bus_vote.client_handle,
- vote, err);
- goto out;
- }
-
- host->bus_vote.curr_vote = vote;
- }
-out:
- return err;
-}
-
-static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host)
-{
- int vote;
- int err = 0;
- char mode[BUS_VECTOR_NAME_LEN];
-
- ufs_qcom_get_speed_mode(&host->dev_req_params, mode);
-
- vote = ufs_qcom_get_bus_vote(host, mode);
- if (vote >= 0)
- err = ufs_qcom_set_bus_vote(host, vote);
- else
- err = vote;
-
- if (err)
- dev_err(host->hba->dev, "%s: failed %d\n", __func__, err);
- else
- host->bus_vote.saved_vote = vote;
- return err;
-}
-
-static ssize_t
-show_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct ufs_hba *hba = dev_get_drvdata(dev);
- struct ufs_qcom_host *host = ufshcd_get_variant(hba);
-
- return snprintf(buf, PAGE_SIZE, "%u\n",
- host->bus_vote.is_max_bw_needed);
-}
-
-static ssize_t
-store_ufs_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct ufs_hba *hba = dev_get_drvdata(dev);
- struct ufs_qcom_host *host = ufshcd_get_variant(hba);
- uint32_t value;
-
- if (!kstrtou32(buf, 0, &value)) {
- host->bus_vote.is_max_bw_needed = !!value;
- ufs_qcom_update_bus_bw_vote(host);
- }
-
- return count;
-}
-
-static int ufs_qcom_bus_register(struct ufs_qcom_host *host)
-{
- int err;
- struct msm_bus_scale_pdata *bus_pdata;
- struct device *dev = host->hba->dev;
- struct platform_device *pdev = to_platform_device(dev);
- struct device_node *np = dev->of_node;
-
- bus_pdata = msm_bus_cl_get_pdata(pdev);
- if (!bus_pdata) {
- dev_err(dev, "%s: failed to get bus vectors\n", __func__);
- err = -ENODATA;
- goto out;
- }
-
- err = of_property_count_strings(np, "qcom,bus-vector-names");
- if (err < 0 || err != bus_pdata->num_usecases) {
- dev_err(dev, "%s: qcom,bus-vector-names not specified correctly %d\n",
- __func__, err);
- goto out;
- }
-
- host->bus_vote.client_handle = msm_bus_scale_register_client(bus_pdata);
- if (!host->bus_vote.client_handle) {
- dev_err(dev, "%s: msm_bus_scale_register_client failed\n",
- __func__);
- err = -EFAULT;
- goto out;
- }
-
- /* cache the vote index for minimum and maximum bandwidth */
- host->bus_vote.min_bw_vote = ufs_qcom_get_bus_vote(host, "MIN");
- host->bus_vote.max_bw_vote = ufs_qcom_get_bus_vote(host, "MAX");
-
- host->bus_vote.max_bus_bw.show = show_ufs_to_mem_max_bus_bw;
- host->bus_vote.max_bus_bw.store = store_ufs_to_mem_max_bus_bw;
- sysfs_attr_init(&host->bus_vote.max_bus_bw.attr);
- host->bus_vote.max_bus_bw.attr.name = "max_bus_bw";
- host->bus_vote.max_bus_bw.attr.mode = S_IRUGO | S_IWUSR;
- err = device_create_file(dev, &host->bus_vote.max_bus_bw);
-out:
- return err;
-}
-#else /* CONFIG_MSM_BUS_SCALING */
-static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host)
-{
- return 0;
-}
-
-static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote)
-{
- return 0;
-}
-
-static int ufs_qcom_bus_register(struct ufs_qcom_host *host)
-{
- return 0;
-}
-#endif /* CONFIG_MSM_BUS_SCALING */
-
static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable)
{
if (host->dev_ref_clk_ctrl_mmio &&
@@ -773,11 +645,27 @@
/*
* If we are here to disable this clock it might be immediately
* after entering into hibern8 in which case we need to make
- * sure that device ref_clk is active at least 1us after the
+ * sure that device ref_clk is active for specific time after
* hibern8 enter.
*/
- if (!enable)
- udelay(1);
+ if (!enable) {
+ unsigned long gating_wait;
+
+ gating_wait = host->hba->dev_info.clk_gating_wait_us;
+ if (!gating_wait) {
+ udelay(1);
+ } else {
+ /*
+ * bRefClkGatingWaitTime defines the minimum
+ * time for which the reference clock is
+ * required by device during transition from
+ * HS-MODE to LS-MODE or HIBERN8 state. Give it
+ * more delay to be on the safe side.
+ */
+ gating_wait += 10;
+ usleep_range(gating_wait, gating_wait + 10);
+ }
+ }
writel_relaxed(temp, host->dev_ref_clk_ctrl_mmio);
@@ -854,6 +742,20 @@
if (!ufshcd_is_hs_mode(&hba->pwr_info) &&
ufshcd_is_hs_mode(dev_req_params))
ufs_qcom_dev_ref_clk_ctrl(host, true);
+
+ if (host->hw_ver.major >= 0x4) {
+ if (dev_req_params->gear_tx == UFS_HS_G4) {
+ /* INITIAL ADAPT */
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB(PA_TXHSADAPTTYPE),
+ PA_INITIAL_ADAPT);
+ } else {
+ /* NO ADAPT */
+ ufshcd_dme_set(hba,
+ UIC_ARG_MIB(PA_TXHSADAPTTYPE),
+ PA_NO_ADAPT);
+ }
+ }
break;
case POST_CHANGE:
if (ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx,
@@ -872,7 +774,6 @@
/* cache the power mode parameters to use internally */
memcpy(&host->dev_req_params,
dev_req_params, sizeof(*dev_req_params));
- ufs_qcom_update_bus_bw_vote(host);
/* disable the device ref clock if entered PWM mode */
if (ufshcd_is_hs_mode(&hba->pwr_info) &&
@@ -905,14 +806,16 @@
return err;
}
-static int ufs_qcom_apply_dev_quirks(struct ufs_hba *hba,
- struct ufs_dev_desc *card)
+static int ufs_qcom_apply_dev_quirks(struct ufs_hba *hba)
{
int err = 0;
if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME)
err = ufs_qcom_quirk_host_pa_saveconfigtime(hba);
+ if (hba->dev_info.wmanufacturerid == UFS_VENDOR_WDC)
+ hba->dev_quirks |= UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE;
+
return err;
}
@@ -968,6 +871,8 @@
hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_HIBERN8_WITH_CLK_GATING;
hba->caps |= UFSHCD_CAP_CLK_SCALING;
hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND;
+ hba->caps |= UFSHCD_CAP_WB_EN;
+ hba->caps |= UFSHCD_CAP_CRYPTO;
if (host->hw_ver.major >= 0x2) {
host->caps = UFS_QCOM_CAP_QUNIPRO |
@@ -987,8 +892,7 @@
enum ufs_notify_change_status status)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
- int err;
- int vote = 0;
+ int err = 0;
/*
* In case ufs_qcom_init() is not yet done, simply ignore.
@@ -998,28 +902,24 @@
if (!host)
return 0;
- if (on && (status == POST_CHANGE)) {
- /* enable the device ref clock for HS mode*/
- if (ufshcd_is_hs_mode(&hba->pwr_info))
- ufs_qcom_dev_ref_clk_ctrl(host, true);
- vote = host->bus_vote.saved_vote;
- if (vote == host->bus_vote.min_bw_vote)
- ufs_qcom_update_bus_bw_vote(host);
-
- } else if (!on && (status == PRE_CHANGE)) {
- if (!ufs_qcom_is_link_active(hba)) {
- /* disable device ref_clk */
- ufs_qcom_dev_ref_clk_ctrl(host, false);
+ switch (status) {
+ case PRE_CHANGE:
+ if (!on) {
+ if (!ufs_qcom_is_link_active(hba)) {
+ /* disable device ref_clk */
+ ufs_qcom_dev_ref_clk_ctrl(host, false);
+ }
}
-
- vote = host->bus_vote.min_bw_vote;
+ break;
+ case POST_CHANGE:
+ if (on) {
+ /* enable the device ref clock for HS mode*/
+ if (ufshcd_is_hs_mode(&hba->pwr_info))
+ ufs_qcom_dev_ref_clk_ctrl(host, true);
+ }
+ break;
}
- err = ufs_qcom_set_bus_vote(host, vote);
- if (err)
- dev_err(hba->dev, "%s: set bus vote failed %d\n",
- __func__, err);
-
return err;
}
@@ -1102,6 +1002,15 @@
host->hba = hba;
ufshcd_set_variant(hba, host);
+ /* Setup the reset control of HCI */
+ host->core_reset = devm_reset_control_get(hba->dev, "rst");
+ if (IS_ERR(host->core_reset)) {
+ err = PTR_ERR(host->core_reset);
+ dev_warn(dev, "Failed to get reset control %d\n", err);
+ host->core_reset = NULL;
+ err = 0;
+ }
+
/* Fire up the reset controller. Failure here is non-fatal. */
host->rcdev.of_node = dev->of_node;
host->rcdev.ops = &ufs_qcom_reset_ops;
@@ -1148,10 +1057,6 @@
goto out_variant_clear;
}
- err = ufs_qcom_bus_register(host);
- if (err)
- goto out_variant_clear;
-
ufs_qcom_get_controller_revision(hba, &host->hw_ver.major,
&host->hw_ver.minor, &host->hw_ver.step);
@@ -1164,7 +1069,8 @@
host->dev_ref_clk_en_mask = BIT(26);
} else {
/* "dev_ref_clk_ctrl_mem" is optional resource */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "dev_ref_clk_ctrl_mem");
if (res) {
host->dev_ref_clk_ctrl_mmio =
devm_ioremap_resource(dev, res);
@@ -1186,6 +1092,10 @@
ufs_qcom_set_caps(hba);
ufs_qcom_advertise_quirks(hba);
+ err = ufs_qcom_ice_init(host);
+ if (err)
+ goto out_variant_clear;
+
ufs_qcom_setup_clocks(hba, true, POST_CHANGE);
if (hba->dev->id < MAX_UFS_QCOM_HOSTS)
@@ -1324,7 +1234,6 @@
dev_req_params->pwr_rx,
dev_req_params->hs_rate,
false);
- ufs_qcom_update_bus_bw_vote(host);
}
out:
@@ -1508,44 +1417,12 @@
return 0;
}
-static void ufs_qcom_testbus_read(struct ufs_hba *hba)
-{
- ufshcd_dump_regs(hba, UFS_TEST_BUS, 4, "UFS_TEST_BUS ");
-}
-
-static void ufs_qcom_print_unipro_testbus(struct ufs_hba *hba)
-{
- struct ufs_qcom_host *host = ufshcd_get_variant(hba);
- u32 *testbus = NULL;
- int i, nminor = 256, testbus_len = nminor * sizeof(u32);
-
- testbus = kmalloc(testbus_len, GFP_KERNEL);
- if (!testbus)
- return;
-
- host->testbus.select_major = TSTBUS_UNIPRO;
- for (i = 0; i < nminor; i++) {
- host->testbus.select_minor = i;
- ufs_qcom_testbus_config(host);
- testbus[i] = ufshcd_readl(hba, UFS_TEST_BUS);
- }
- print_hex_dump(KERN_ERR, "UNIPRO_TEST_BUS ", DUMP_PREFIX_OFFSET,
- 16, 4, testbus, testbus_len, false);
- kfree(testbus);
-}
-
static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
{
ufshcd_dump_regs(hba, REG_UFS_SYS1CLK_1US, 16 * 4,
"HCI Vendor Specific Registers ");
- /* sleep a bit intermittently as we are dumping too much data */
ufs_qcom_print_hw_debug_reg_all(hba, NULL, ufs_qcom_dump_regs_wrapper);
- udelay(1000);
- ufs_qcom_testbus_read(hba);
- udelay(1000);
- ufs_qcom_print_unipro_testbus(hba);
- udelay(1000);
}
/**
@@ -1554,13 +1431,13 @@
*
* Toggles the (optional) reset line to reset the attached device.
*/
-static void ufs_qcom_device_reset(struct ufs_hba *hba)
+static int ufs_qcom_device_reset(struct ufs_hba *hba)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
/* reset gpio is optional */
if (!host->device_reset)
- return;
+ return -EOPNOTSUPP;
/*
* The UFS device shall detect reset pulses of 1us, sleep for 10us to
@@ -1571,9 +1448,34 @@
gpiod_set_value_cansleep(host->device_reset, 0);
usleep_range(10, 15);
+
+ return 0;
}
-/**
+#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
+static void ufs_qcom_config_scaling_param(struct ufs_hba *hba,
+ struct devfreq_dev_profile *p,
+ void *data)
+{
+ static struct devfreq_simple_ondemand_data *d;
+
+ if (!data)
+ return;
+
+ d = (struct devfreq_simple_ondemand_data *)data;
+ p->polling_ms = 60;
+ d->upthreshold = 70;
+ d->downdifferential = 5;
+}
+#else
+static void ufs_qcom_config_scaling_param(struct ufs_hba *hba,
+ struct devfreq_dev_profile *p,
+ void *data)
+{
+}
+#endif
+
+/*
* struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
*
* The variant operations configure the necessary controller and PHY
@@ -1594,6 +1496,8 @@
.resume = ufs_qcom_resume,
.dbg_register_dump = ufs_qcom_dump_dbg_regs,
.device_reset = ufs_qcom_device_reset,
+ .config_scaling_param = ufs_qcom_config_scaling_param,
+ .program_key = ufs_qcom_ice_program_key,
};
/**
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h
index d401f17..3f49227 100644
--- a/drivers/scsi/ufs/ufs-qcom.h
+++ b/drivers/scsi/ufs/ufs-qcom.h
@@ -6,6 +6,7 @@
#define UFS_QCOM_H_
#include <linux/reset-controller.h>
+#include <linux/reset.h>
#define MAX_UFS_QCOM_HOSTS 1
#define MAX_U32 (~(u32)0)
@@ -173,16 +174,6 @@
mb();
}
-struct ufs_qcom_bus_vote {
- uint32_t client_handle;
- uint32_t curr_vote;
- int min_bw_vote;
- int max_bw_vote;
- int saved_vote;
- bool is_max_bw_needed;
- struct device_attribute max_bus_bw;
-};
-
/* Host controller hardware version: major.minor.step */
struct ufs_hw_version {
u16 step;
@@ -215,7 +206,6 @@
struct phy *generic_phy;
struct ufs_hba *hba;
- struct ufs_qcom_bus_vote bus_vote;
struct ufs_pa_layer_attr dev_req_params;
struct clk *rx_l0_sync_clk;
struct clk *tx_l0_sync_clk;
@@ -226,6 +216,9 @@
void __iomem *dev_ref_clk_ctrl_mmio;
bool is_dev_ref_clk_enabled;
struct ufs_hw_version hw_ver;
+#ifdef CONFIG_SCSI_UFS_CRYPTO
+ void __iomem *ice_mmio;
+#endif
u32 dev_ref_clk_en_mask;
@@ -233,6 +226,8 @@
u32 dbg_print_en;
struct ufs_qcom_testbus testbus;
+ /* Reset control of HCI */
+ struct reset_control *core_reset;
struct reset_controller_dev rcdev;
struct gpio_desc *device_reset;
@@ -261,4 +256,28 @@
return false;
}
+/* ufs-qcom-ice.c */
+
+#ifdef CONFIG_SCSI_UFS_CRYPTO
+int ufs_qcom_ice_init(struct ufs_qcom_host *host);
+int ufs_qcom_ice_enable(struct ufs_qcom_host *host);
+int ufs_qcom_ice_resume(struct ufs_qcom_host *host);
+int ufs_qcom_ice_program_key(struct ufs_hba *hba,
+ const union ufs_crypto_cfg_entry *cfg, int slot);
+#else
+static inline int ufs_qcom_ice_init(struct ufs_qcom_host *host)
+{
+ return 0;
+}
+static inline int ufs_qcom_ice_enable(struct ufs_qcom_host *host)
+{
+ return 0;
+}
+static inline int ufs_qcom_ice_resume(struct ufs_qcom_host *host)
+{
+ return 0;
+}
+#define ufs_qcom_ice_program_key NULL
+#endif /* !CONFIG_SCSI_UFS_CRYPTO */
+
#endif /* UFS_QCOM_H_ */
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index ad2abc9..34b424a 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -16,6 +16,7 @@
case UIC_LINK_OFF_STATE: return "OFF";
case UIC_LINK_ACTIVE_STATE: return "ACTIVE";
case UIC_LINK_HIBERN8_STATE: return "HIBERN8";
+ case UIC_LINK_BROKEN_STATE: return "BROKEN";
default: return "UNKNOWN";
}
}
@@ -118,26 +119,6 @@
ufs_pm_lvl_states[hba->spm_lvl].link_state));
}
-static void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit)
-{
- unsigned long flags;
-
- if (!ufshcd_is_auto_hibern8_supported(hba))
- return;
-
- spin_lock_irqsave(hba->host->host_lock, flags);
- if (hba->ahit != ahit)
- hba->ahit = ahit;
- spin_unlock_irqrestore(hba->host->host_lock, flags);
- if (!pm_runtime_suspended(hba->dev)) {
- pm_runtime_get_sync(hba->dev);
- ufshcd_hold(hba, false);
- ufshcd_auto_hibern8_enable(hba);
- ufshcd_release(hba);
- pm_runtime_put(hba->dev);
- }
-}
-
/* Convert Auto-Hibernate Idle Timer register value to microseconds */
static int ufshcd_ahit_to_us(u32 ahit)
{
@@ -165,12 +146,19 @@
static ssize_t auto_hibern8_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ u32 ahit;
struct ufs_hba *hba = dev_get_drvdata(dev);
if (!ufshcd_is_auto_hibern8_supported(hba))
return -EOPNOTSUPP;
- return snprintf(buf, PAGE_SIZE, "%d\n", ufshcd_ahit_to_us(hba->ahit));
+ pm_runtime_get_sync(hba->dev);
+ ufshcd_hold(hba, false);
+ ahit = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER);
+ ufshcd_release(hba);
+ pm_runtime_put_sync(hba->dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", ufshcd_ahit_to_us(ahit));
}
static ssize_t auto_hibern8_store(struct device *dev,
@@ -230,8 +218,10 @@
if (param_size > 8)
return -EINVAL;
+ pm_runtime_get_sync(hba->dev);
ret = ufshcd_read_desc_param(hba, desc_id, desc_index,
param_offset, desc_buf, param_size);
+ pm_runtime_put_sync(hba->dev);
if (ret)
return -EINVAL;
switch (param_size) {
@@ -294,6 +284,10 @@
UFS_DEVICE_DESC_PARAM(number_of_secure_wpa, _NUM_SEC_WPA, 1);
UFS_DEVICE_DESC_PARAM(psa_max_data_size, _PSA_MAX_DATA, 4);
UFS_DEVICE_DESC_PARAM(psa_state_timeout, _PSA_TMT, 1);
+UFS_DEVICE_DESC_PARAM(ext_feature_sup, _EXT_UFS_FEATURE_SUP, 4);
+UFS_DEVICE_DESC_PARAM(wb_presv_us_en, _WB_PRESRV_USRSPC_EN, 1);
+UFS_DEVICE_DESC_PARAM(wb_type, _WB_TYPE, 1);
+UFS_DEVICE_DESC_PARAM(wb_shared_alloc_units, _WB_SHARED_ALLOC_UNITS, 4);
static struct attribute *ufs_sysfs_device_descriptor[] = {
&dev_attr_device_type.attr,
@@ -322,6 +316,10 @@
&dev_attr_number_of_secure_wpa.attr,
&dev_attr_psa_max_data_size.attr,
&dev_attr_psa_state_timeout.attr,
+ &dev_attr_ext_feature_sup.attr,
+ &dev_attr_wb_presv_us_en.attr,
+ &dev_attr_wb_type.attr,
+ &dev_attr_wb_shared_alloc_units.attr,
NULL,
};
@@ -391,6 +389,12 @@
_ENM4_MAX_NUM_UNITS, 4);
UFS_GEOMETRY_DESC_PARAM(enh4_memory_capacity_adjustment_factor,
_ENM4_CAP_ADJ_FCTR, 2);
+UFS_GEOMETRY_DESC_PARAM(wb_max_alloc_units, _WB_MAX_ALLOC_UNITS, 4);
+UFS_GEOMETRY_DESC_PARAM(wb_max_wb_luns, _WB_MAX_WB_LUNS, 1);
+UFS_GEOMETRY_DESC_PARAM(wb_buff_cap_adj, _WB_BUFF_CAP_ADJ, 1);
+UFS_GEOMETRY_DESC_PARAM(wb_sup_red_type, _WB_SUP_RED_TYPE, 1);
+UFS_GEOMETRY_DESC_PARAM(wb_sup_wb_type, _WB_SUP_WB_TYPE, 1);
+
static struct attribute *ufs_sysfs_geometry_descriptor[] = {
&dev_attr_raw_device_capacity.attr,
@@ -422,6 +426,11 @@
&dev_attr_enh3_memory_capacity_adjustment_factor.attr,
&dev_attr_enh4_memory_max_alloc_units.attr,
&dev_attr_enh4_memory_capacity_adjustment_factor.attr,
+ &dev_attr_wb_max_alloc_units.attr,
+ &dev_attr_wb_max_wb_luns.attr,
+ &dev_attr_wb_buff_cap_adj.attr,
+ &dev_attr_wb_sup_red_type.attr,
+ &dev_attr_wb_sup_wb_type.attr,
NULL,
};
@@ -578,6 +587,7 @@
desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_ATOMIC); \
if (!desc_buf) \
return -ENOMEM; \
+ pm_runtime_get_sync(hba->dev); \
ret = ufshcd_query_descriptor_retry(hba, \
UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_DEVICE, \
0, 0, desc_buf, &desc_len); \
@@ -594,6 +604,7 @@
goto out; \
ret = snprintf(buf, PAGE_SIZE, "%s\n", desc_buf); \
out: \
+ pm_runtime_put_sync(hba->dev); \
kfree(desc_buf); \
return ret; \
} \
@@ -619,16 +630,29 @@
.attrs = ufs_sysfs_string_descriptors,
};
+static inline bool ufshcd_is_wb_flags(enum flag_idn idn)
+{
+ return ((idn >= QUERY_FLAG_IDN_WB_EN) &&
+ (idn <= QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8));
+}
+
#define UFS_FLAG(_name, _uname) \
static ssize_t _name##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
bool flag; \
+ u8 index = 0; \
+ int ret; \
struct ufs_hba *hba = dev_get_drvdata(dev); \
- if (ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG, \
- QUERY_FLAG_IDN##_uname, &flag)) \
+ if (ufshcd_is_wb_flags(QUERY_FLAG_IDN##_uname)) \
+ index = ufshcd_wb_get_query_index(hba); \
+ pm_runtime_get_sync(hba->dev); \
+ ret = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG, \
+ QUERY_FLAG_IDN##_uname, index, &flag); \
+ pm_runtime_put_sync(hba->dev); \
+ if (ret) \
return -EINVAL; \
- return sprintf(buf, "%s\n", flag ? "true" : "false"); \
+ return sprintf(buf, "%s\n", flag ? "true" : "false"); \
} \
static DEVICE_ATTR_RO(_name)
@@ -640,6 +664,9 @@
UFS_FLAG(phy_resource_removal, _FPHYRESOURCEREMOVAL);
UFS_FLAG(busy_rtc, _BUSY_RTC);
UFS_FLAG(disable_fw_update, _PERMANENTLY_DISABLE_FW_UPDATE);
+UFS_FLAG(wb_enable, _WB_EN);
+UFS_FLAG(wb_flush_en, _WB_BUFF_FLUSH_EN);
+UFS_FLAG(wb_flush_during_h8, _WB_BUFF_FLUSH_DURING_HIBERN8);
static struct attribute *ufs_sysfs_device_flags[] = {
&dev_attr_device_init.attr,
@@ -650,6 +677,9 @@
&dev_attr_phy_resource_removal.attr,
&dev_attr_busy_rtc.attr,
&dev_attr_disable_fw_update.attr,
+ &dev_attr_wb_enable.attr,
+ &dev_attr_wb_flush_en.attr,
+ &dev_attr_wb_flush_during_h8.attr,
NULL,
};
@@ -658,14 +688,27 @@
.attrs = ufs_sysfs_device_flags,
};
+static inline bool ufshcd_is_wb_attrs(enum attr_idn idn)
+{
+ return ((idn >= QUERY_ATTR_IDN_WB_FLUSH_STATUS) &&
+ (idn <= QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE));
+}
+
#define UFS_ATTRIBUTE(_name, _uname) \
static ssize_t _name##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct ufs_hba *hba = dev_get_drvdata(dev); \
u32 value; \
- if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, \
- QUERY_ATTR_IDN##_uname, 0, 0, &value)) \
+ int ret; \
+ u8 index = 0; \
+ if (ufshcd_is_wb_attrs(QUERY_ATTR_IDN##_uname)) \
+ index = ufshcd_wb_get_query_index(hba); \
+ pm_runtime_get_sync(hba->dev); \
+ ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, \
+ QUERY_ATTR_IDN##_uname, index, 0, &value); \
+ pm_runtime_put_sync(hba->dev); \
+ if (ret) \
return -EINVAL; \
return sprintf(buf, "0x%08X\n", value); \
} \
@@ -687,6 +730,11 @@
UFS_ATTRIBUTE(ffu_status, _FFU_STATUS);
UFS_ATTRIBUTE(psa_state, _PSA_STATE);
UFS_ATTRIBUTE(psa_data_size, _PSA_DATA_SIZE);
+UFS_ATTRIBUTE(wb_flush_status, _WB_FLUSH_STATUS);
+UFS_ATTRIBUTE(wb_avail_buf, _AVAIL_WB_BUFF_SIZE);
+UFS_ATTRIBUTE(wb_life_time_est, _WB_BUFF_LIFE_TIME_EST);
+UFS_ATTRIBUTE(wb_cur_buf, _CURR_WB_BUFF_SIZE);
+
static struct attribute *ufs_sysfs_attributes[] = {
&dev_attr_boot_lun_enabled.attr,
@@ -705,6 +753,10 @@
&dev_attr_ffu_status.attr,
&dev_attr_psa_state.attr,
&dev_attr_psa_data_size.attr,
+ &dev_attr_wb_flush_status.attr,
+ &dev_attr_wb_avail_buf.attr,
+ &dev_attr_wb_life_time_est.attr,
+ &dev_attr_wb_cur_buf.attr,
NULL,
};
@@ -733,7 +785,8 @@
struct scsi_device *sdev = to_scsi_device(dev); \
struct ufs_hba *hba = shost_priv(sdev->host); \
u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun); \
- if (!ufs_is_valid_unit_desc_lun(lun)) \
+ if (!ufs_is_valid_unit_desc_lun(&hba->dev_info, lun, \
+ _duname##_DESC_PARAM##_puname)) \
return -EINVAL; \
return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_##_duname, \
lun, _duname##_DESC_PARAM##_puname, buf, _size); \
@@ -756,6 +809,8 @@
UFS_UNIT_DESC_PARAM(physical_memory_resourse_count, _PHY_MEM_RSRC_CNT, 8);
UFS_UNIT_DESC_PARAM(context_capabilities, _CTX_CAPABILITIES, 2);
UFS_UNIT_DESC_PARAM(large_unit_granularity, _LARGE_UNIT_SIZE_M1, 1);
+UFS_UNIT_DESC_PARAM(wb_buf_alloc_units, _WB_BUF_ALLOC_UNITS, 4);
+
static struct attribute *ufs_sysfs_unit_descriptor[] = {
&dev_attr_boot_lun_id.attr,
@@ -771,6 +826,7 @@
&dev_attr_physical_memory_resourse_count.attr,
&dev_attr_context_capabilities.attr,
&dev_attr_large_unit_granularity.attr,
+ &dev_attr_wb_buf_alloc_units.attr,
NULL,
};
@@ -786,9 +842,13 @@
struct scsi_device *sdev = to_scsi_device(dev);
struct ufs_hba *hba = shost_priv(sdev->host);
u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun);
+ int ret;
- if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
- QUERY_ATTR_IDN_DYN_CAP_NEEDED, lun, 0, &value))
+ pm_runtime_get_sync(hba->dev);
+ ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
+ QUERY_ATTR_IDN_DYN_CAP_NEEDED, lun, 0, &value);
+ pm_runtime_put_sync(hba->dev);
+ if (ret)
return -EINVAL;
return sprintf(buf, "0x%08X\n", value);
}
diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h
index e5621e5..0f4e750 100644
--- a/drivers/scsi/ufs/ufs-sysfs.h
+++ b/drivers/scsi/ufs/ufs-sysfs.h
@@ -1,5 +1,5 @@
-/* SPDX-License-Identifier: GPL-2.0
- * Copyright (C) 2018 Western Digital Corporation
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2018 Western Digital Corporation
*/
#ifndef __UFS_SYSFS_H__
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 3327981..07ca390 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -1,36 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Universal Flash Storage Host controller driver
- *
- * This code is based on drivers/scsi/ufs/ufs.h
* Copyright (C) 2011-2013 Samsung India Software Operations
*
* Authors:
* Santosh Yaraganavi <santosh.sy@samsung.com>
* Vinayak Holikatti <h.vinayak@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * See the COPYING file in the top-level directory or visit
- * <http://www.gnu.org/licenses/gpl-2.0.html>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * This program is provided "AS IS" and "WITH ALL FAULTS" and
- * without warranty of any kind. You are solely responsible for
- * determining the appropriateness of using and distributing
- * the program and assume all risks associated with your exercise
- * of rights with respect to the program, including but not limited
- * to infringement of third party rights, the risks and costs of
- * program errors, damage to or loss of data, programs or equipment,
- * and unavailability or interruption of operations. Under no
- * circumstances will the contributor of this Program be liable for
- * any damages of any kind arising from your use or distribution of
- * this program.
*/
#ifndef _UFS_H
@@ -63,7 +38,10 @@
#define UFS_UPIU_MAX_UNIT_NUM_ID 0x7F
#define UFS_MAX_LUNS (SCSI_W_LUN_BASE + UFS_UPIU_MAX_UNIT_NUM_ID)
#define UFS_UPIU_WLUN_ID (1 << 7)
-#define UFS_UPIU_MAX_GENERAL_LUN 8
+#define UFS_RPMB_UNIT 0xC4
+
+/* WriteBooster buffer is available only for the logical unit from 0 to 7 */
+#define UFS_UPIU_MAX_WB_LUN_ID 8
/* Well known logical unit id in LUN field of UPIU */
enum {
@@ -141,6 +119,9 @@
QUERY_FLAG_IDN_BUSY_RTC = 0x09,
QUERY_FLAG_IDN_RESERVED3 = 0x0A,
QUERY_FLAG_IDN_PERMANENTLY_DISABLE_FW_UPDATE = 0x0B,
+ QUERY_FLAG_IDN_WB_EN = 0x0E,
+ QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN = 0x0F,
+ QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8 = 0x10,
};
/* Attribute idn for Query requests */
@@ -168,6 +149,11 @@
QUERY_ATTR_IDN_FFU_STATUS = 0x14,
QUERY_ATTR_IDN_PSA_STATE = 0x15,
QUERY_ATTR_IDN_PSA_DATA_SIZE = 0x16,
+ QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME = 0x17,
+ QUERY_ATTR_IDN_WB_FLUSH_STATUS = 0x1C,
+ QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE = 0x1D,
+ QUERY_ATTR_IDN_WB_BUFF_LIFE_TIME_EST = 0x1E,
+ QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE = 0x1F,
};
/* Descriptor idn for Query requests */
@@ -190,16 +176,6 @@
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
};
-enum ufs_desc_def_size {
- QUERY_DESC_DEVICE_DEF_SIZE = 0x40,
- QUERY_DESC_CONFIGURATION_DEF_SIZE = 0x90,
- QUERY_DESC_UNIT_DEF_SIZE = 0x23,
- QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06,
- QUERY_DESC_GEOMETRY_DEF_SIZE = 0x48,
- QUERY_DESC_POWER_DEF_SIZE = 0x62,
- QUERY_DESC_HEALTH_DEF_SIZE = 0x25,
-};
-
/* Unit descriptor parameters offsets in bytes*/
enum unit_desc_param {
UNIT_DESC_PARAM_LEN = 0x0,
@@ -219,6 +195,7 @@
UNIT_DESC_PARAM_PHY_MEM_RSRC_CNT = 0x18,
UNIT_DESC_PARAM_CTX_CAPABILITIES = 0x20,
UNIT_DESC_PARAM_LARGE_UNIT_SIZE_M1 = 0x22,
+ UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS = 0x29,
};
/* Device descriptor parameters offsets in bytes*/
@@ -258,6 +235,10 @@
DEVICE_DESC_PARAM_PSA_MAX_DATA = 0x25,
DEVICE_DESC_PARAM_PSA_TMT = 0x29,
DEVICE_DESC_PARAM_PRDCT_REV = 0x2A,
+ DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP = 0x4F,
+ DEVICE_DESC_PARAM_WB_PRESRV_USRSPC_EN = 0x53,
+ DEVICE_DESC_PARAM_WB_TYPE = 0x54,
+ DEVICE_DESC_PARAM_WB_SHARED_ALLOC_UNITS = 0x55,
};
/* Interconnect descriptor parameters offsets in bytes*/
@@ -302,6 +283,11 @@
GEOMETRY_DESC_PARAM_ENM4_MAX_NUM_UNITS = 0x3E,
GEOMETRY_DESC_PARAM_ENM4_CAP_ADJ_FCTR = 0x42,
GEOMETRY_DESC_PARAM_OPT_LOG_BLK_SIZE = 0x44,
+ GEOMETRY_DESC_PARAM_WB_MAX_ALLOC_UNITS = 0x4F,
+ GEOMETRY_DESC_PARAM_WB_MAX_WB_LUNS = 0x53,
+ GEOMETRY_DESC_PARAM_WB_BUFF_CAP_ADJ = 0x54,
+ GEOMETRY_DESC_PARAM_WB_SUP_RED_TYPE = 0x55,
+ GEOMETRY_DESC_PARAM_WB_SUP_WB_TYPE = 0x56,
};
/* Health descriptor parameters offsets in bytes*/
@@ -313,6 +299,12 @@
HEALTH_DESC_PARAM_LIFE_TIME_EST_B = 0x4,
};
+/* WriteBooster buffer mode */
+enum {
+ WB_BUF_MODE_LU_DEDICATED = 0x0,
+ WB_BUF_MODE_SHARED = 0x1,
+};
+
/*
* Logical Unit Write Protect
* 00h: LU not write protected
@@ -333,6 +325,11 @@
UFSHCD_AMP = 3,
};
+/* Possible values for dExtendedUFSFeaturesSupport */
+enum {
+ UFS_DEV_WRITE_BOOSTER_SUP = BIT(8),
+};
+
#define POWER_DESC_MAX_SIZE 0x62
#define POWER_DESC_MAX_ACTV_ICC_LVLS 16
@@ -447,6 +444,8 @@
UFS_POWERDOWN_PWR_MODE = 3,
};
+#define UFS_WB_BUF_REMAIN_PERCENT(val) ((val) / 10)
+
/**
* struct utp_cmd_rsp - Response UPIU structure
* @residual_transfer_count: Residual transfer count DW-3
@@ -499,9 +498,9 @@
#define UFS_VREG_VCC_MAX_UV 3600000 /* uV */
#define UFS_VREG_VCC_1P8_MIN_UV 1700000 /* uV */
#define UFS_VREG_VCC_1P8_MAX_UV 1950000 /* uV */
-#define UFS_VREG_VCCQ_MIN_UV 1100000 /* uV */
-#define UFS_VREG_VCCQ_MAX_UV 1300000 /* uV */
-#define UFS_VREG_VCCQ2_MIN_UV 1650000 /* uV */
+#define UFS_VREG_VCCQ_MIN_UV 1140000 /* uV */
+#define UFS_VREG_VCCQ_MAX_UV 1260000 /* uV */
+#define UFS_VREG_VCCQ2_MIN_UV 1700000 /* uV */
#define UFS_VREG_VCCQ2_MAX_UV 1950000 /* uV */
/*
@@ -530,28 +529,38 @@
bool f_power_on_wp_en;
/* Keeps information if any of the LU is power on write protected */
bool is_lu_power_on_wp;
-};
-
-#define MAX_MODEL_LEN 16
-/**
- * ufs_dev_desc - ufs device details from the device descriptor
- *
- * @wmanufacturerid: card details
- * @model: card model
- */
-struct ufs_dev_desc {
+ /* Maximum number of general LU supported by the UFS device */
+ u8 max_lu_supported;
+ u8 wb_dedicated_lu;
u16 wmanufacturerid;
+ /*UFS device Product Name */
u8 *model;
+ u16 wspecversion;
+ u32 clk_gating_wait_us;
+ u32 d_ext_ufs_feature_sup;
+ u8 b_wb_buffer_type;
+ u32 d_wb_alloc_units;
+ bool b_rpm_dev_flush_capable;
+ u8 b_presrv_uspc_en;
};
/**
* ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @dev_info: pointer of instance of struct ufs_dev_info
* @lun: LU number to check
* @return: true if the lun has a matching unit descriptor, false otherwise
*/
-static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+static inline bool ufs_is_valid_unit_desc_lun(struct ufs_dev_info *dev_info,
+ u8 lun, u8 param_offset)
{
- return lun == UFS_UPIU_RPMB_WLUN || (lun < UFS_UPIU_MAX_GENERAL_LUN);
+ if (!dev_info || !dev_info->max_lu_supported) {
+ pr_err("Max General LU supported by UFS isn't initialized\n");
+ return false;
+ }
+ /* WB is available only for the logical unit from 0 to 7 */
+ if (param_offset == UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS)
+ return lun < UFS_UPIU_MAX_WB_LUN_ID;
+ return lun == UFS_UPIU_RPMB_WLUN || (lun < dev_info->max_lu_supported);
}
#endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index bad366e..5b2bc1a 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -11,13 +11,12 @@
{
int desc_size = be16_to_cpu(qr->length);
int desc_id = qr->idn;
- int ret;
if (desc_size <= 0)
return -EINVAL;
- ret = ufshcd_map_desc_id_to_length(hba, desc_id, desc_len);
- if (ret || !*desc_len)
+ ufshcd_map_desc_id_to_length(hba, desc_id, desc_len);
+ if (!*desc_len)
return -EINVAL;
*desc_len = min_t(int, *desc_len, desc_size);
@@ -111,7 +110,7 @@
goto out;
}
- /* fall through */
+ fallthrough;
case UPIU_TRANSACTION_NOP_OUT:
case UPIU_TRANSACTION_TASK_REQ:
ret = ufshcd_exec_raw_upiu_cmd(hba, &bsg_request->upiu_req,
@@ -164,6 +163,7 @@
/**
* ufs_bsg_remove - detach and remove the added ufs-bsg node
+ * @hba: per adapter object
*
* Should be called when unloading the driver.
*/
diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h
index 0398591..07f559a 100644
--- a/drivers/scsi/ufs/ufs_quirks.h
+++ b/drivers/scsi/ufs/ufs_quirks.h
@@ -13,9 +13,10 @@
#define UFS_ANY_MODEL "ANY_MODEL"
#define UFS_VENDOR_MICRON 0x12C
-#define UFS_VENDOR_TOSHIBA 0x198
#define UFS_VENDOR_SAMSUNG 0x1CE
#define UFS_VENDOR_SKHYNIX 0x1AD
+#define UFS_VENDOR_TOSHIBA 0x198
+#define UFS_VENDOR_WDC 0x145
/**
* ufs_dev_fix - ufs device quirk info
@@ -23,16 +24,17 @@
* @quirk: device quirk
*/
struct ufs_dev_fix {
- struct ufs_dev_desc card;
+ u16 wmanufacturerid;
+ u8 *model;
unsigned int quirk;
};
-#define END_FIX { { 0 }, 0 }
+#define END_FIX { }
/* add specific device quirk */
#define UFS_FIX(_vendor, _model, _quirk) { \
- .card.wmanufacturerid = (_vendor),\
- .card.model = (_model), \
+ .wmanufacturerid = (_vendor),\
+ .model = (_model), \
.quirk = (_quirk), \
}
@@ -100,4 +102,18 @@
*/
#define UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME (1 << 9)
+/*
+ * Some pre-3.1 UFS devices can support extended features by upgrading
+ * the firmware. Enable this quirk to make UFS core driver probe and enable
+ * supported features on such devices.
+ */
+#define UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES (1 << 10)
+
+/*
+ * Some UFS devices require delay after VCC power rail is turned-off.
+ * Enable this quirk to introduce 5ms delays after VCC power-off during
+ * suspend flow.
+ */
+#define UFS_DEVICE_QUIRK_DELAY_AFTER_LPM (1 << 11)
+
#endif /* UFS_QUIRKS_H_ */
diff --git a/drivers/scsi/ufs/ufshcd-crypto.c b/drivers/scsi/ufs/ufshcd-crypto.c
new file mode 100644
index 0000000..07310b1
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd-crypto.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include "ufshcd.h"
+#include "ufshcd-crypto.h"
+
+/* Blk-crypto modes supported by UFS crypto */
+static const struct ufs_crypto_alg_entry {
+ enum ufs_crypto_alg ufs_alg;
+ enum ufs_crypto_key_size ufs_key_size;
+} ufs_crypto_algs[BLK_ENCRYPTION_MODE_MAX] = {
+ [BLK_ENCRYPTION_MODE_AES_256_XTS] = {
+ .ufs_alg = UFS_CRYPTO_ALG_AES_XTS,
+ .ufs_key_size = UFS_CRYPTO_KEY_SIZE_256,
+ },
+};
+
+static int ufshcd_program_key(struct ufs_hba *hba,
+ const union ufs_crypto_cfg_entry *cfg, int slot)
+{
+ int i;
+ u32 slot_offset = hba->crypto_cfg_register + slot * sizeof(*cfg);
+ int err = 0;
+
+ ufshcd_hold(hba, false);
+
+ if (hba->vops && hba->vops->program_key) {
+ err = hba->vops->program_key(hba, cfg, slot);
+ goto out;
+ }
+
+ /* Ensure that CFGE is cleared before programming the key */
+ ufshcd_writel(hba, 0, slot_offset + 16 * sizeof(cfg->reg_val[0]));
+ for (i = 0; i < 16; i++) {
+ ufshcd_writel(hba, le32_to_cpu(cfg->reg_val[i]),
+ slot_offset + i * sizeof(cfg->reg_val[0]));
+ }
+ /* Write dword 17 */
+ ufshcd_writel(hba, le32_to_cpu(cfg->reg_val[17]),
+ slot_offset + 17 * sizeof(cfg->reg_val[0]));
+ /* Dword 16 must be written last */
+ ufshcd_writel(hba, le32_to_cpu(cfg->reg_val[16]),
+ slot_offset + 16 * sizeof(cfg->reg_val[0]));
+out:
+ ufshcd_release(hba);
+ return err;
+}
+
+static int ufshcd_crypto_keyslot_program(struct blk_keyslot_manager *ksm,
+ const struct blk_crypto_key *key,
+ unsigned int slot)
+{
+ struct ufs_hba *hba = container_of(ksm, struct ufs_hba, ksm);
+ const union ufs_crypto_cap_entry *ccap_array = hba->crypto_cap_array;
+ const struct ufs_crypto_alg_entry *alg =
+ &ufs_crypto_algs[key->crypto_cfg.crypto_mode];
+ u8 data_unit_mask = key->crypto_cfg.data_unit_size / 512;
+ int i;
+ int cap_idx = -1;
+ union ufs_crypto_cfg_entry cfg = {};
+ int err;
+
+ BUILD_BUG_ON(UFS_CRYPTO_KEY_SIZE_INVALID != 0);
+ for (i = 0; i < hba->crypto_capabilities.num_crypto_cap; i++) {
+ if (ccap_array[i].algorithm_id == alg->ufs_alg &&
+ ccap_array[i].key_size == alg->ufs_key_size &&
+ (ccap_array[i].sdus_mask & data_unit_mask)) {
+ cap_idx = i;
+ break;
+ }
+ }
+
+ if (WARN_ON(cap_idx < 0))
+ return -EOPNOTSUPP;
+
+ cfg.data_unit_size = data_unit_mask;
+ cfg.crypto_cap_idx = cap_idx;
+ cfg.config_enable = UFS_CRYPTO_CONFIGURATION_ENABLE;
+
+ if (ccap_array[cap_idx].algorithm_id == UFS_CRYPTO_ALG_AES_XTS) {
+ /* In XTS mode, the blk_crypto_key's size is already doubled */
+ memcpy(cfg.crypto_key, key->raw, key->size/2);
+ memcpy(cfg.crypto_key + UFS_CRYPTO_KEY_MAX_SIZE/2,
+ key->raw + key->size/2, key->size/2);
+ } else {
+ memcpy(cfg.crypto_key, key->raw, key->size);
+ }
+
+ err = ufshcd_program_key(hba, &cfg, slot);
+
+ memzero_explicit(&cfg, sizeof(cfg));
+ return err;
+}
+
+static int ufshcd_clear_keyslot(struct ufs_hba *hba, int slot)
+{
+ /*
+ * Clear the crypto cfg on the device. Clearing CFGE
+ * might not be sufficient, so just clear the entire cfg.
+ */
+ union ufs_crypto_cfg_entry cfg = {};
+
+ return ufshcd_program_key(hba, &cfg, slot);
+}
+
+static int ufshcd_crypto_keyslot_evict(struct blk_keyslot_manager *ksm,
+ const struct blk_crypto_key *key,
+ unsigned int slot)
+{
+ struct ufs_hba *hba = container_of(ksm, struct ufs_hba, ksm);
+
+ return ufshcd_clear_keyslot(hba, slot);
+}
+
+bool ufshcd_crypto_enable(struct ufs_hba *hba)
+{
+ if (!(hba->caps & UFSHCD_CAP_CRYPTO))
+ return false;
+
+ /* Reset might clear all keys, so reprogram all the keys. */
+ blk_ksm_reprogram_all_keys(&hba->ksm);
+ return true;
+}
+
+static const struct blk_ksm_ll_ops ufshcd_ksm_ops = {
+ .keyslot_program = ufshcd_crypto_keyslot_program,
+ .keyslot_evict = ufshcd_crypto_keyslot_evict,
+};
+
+static enum blk_crypto_mode_num
+ufshcd_find_blk_crypto_mode(union ufs_crypto_cap_entry cap)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ufs_crypto_algs); i++) {
+ BUILD_BUG_ON(UFS_CRYPTO_KEY_SIZE_INVALID != 0);
+ if (ufs_crypto_algs[i].ufs_alg == cap.algorithm_id &&
+ ufs_crypto_algs[i].ufs_key_size == cap.key_size) {
+ return i;
+ }
+ }
+ return BLK_ENCRYPTION_MODE_INVALID;
+}
+
+/**
+ * ufshcd_hba_init_crypto_capabilities - Read crypto capabilities, init crypto
+ * fields in hba
+ * @hba: Per adapter instance
+ *
+ * Return: 0 if crypto was initialized or is not supported, else a -errno value.
+ */
+int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba)
+{
+ int cap_idx;
+ int err = 0;
+ enum blk_crypto_mode_num blk_mode_num;
+
+ /*
+ * Don't use crypto if either the hardware doesn't advertise the
+ * standard crypto capability bit *or* if the vendor specific driver
+ * hasn't advertised that crypto is supported.
+ */
+ if (!(hba->capabilities & MASK_CRYPTO_SUPPORT) ||
+ !(hba->caps & UFSHCD_CAP_CRYPTO))
+ goto out;
+
+ hba->crypto_capabilities.reg_val =
+ cpu_to_le32(ufshcd_readl(hba, REG_UFS_CCAP));
+ hba->crypto_cfg_register =
+ (u32)hba->crypto_capabilities.config_array_ptr * 0x100;
+ hba->crypto_cap_array =
+ devm_kcalloc(hba->dev, hba->crypto_capabilities.num_crypto_cap,
+ sizeof(hba->crypto_cap_array[0]), GFP_KERNEL);
+ if (!hba->crypto_cap_array) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /* The actual number of configurations supported is (CFGC+1) */
+ err = blk_ksm_init(&hba->ksm,
+ hba->crypto_capabilities.config_count + 1);
+ if (err)
+ goto out_free_caps;
+
+ hba->ksm.ksm_ll_ops = ufshcd_ksm_ops;
+ /* UFS only supports 8 bytes for any DUN */
+ hba->ksm.max_dun_bytes_supported = 8;
+ hba->ksm.dev = hba->dev;
+
+ /*
+ * Cache all the UFS crypto capabilities and advertise the supported
+ * crypto modes and data unit sizes to the block layer.
+ */
+ for (cap_idx = 0; cap_idx < hba->crypto_capabilities.num_crypto_cap;
+ cap_idx++) {
+ hba->crypto_cap_array[cap_idx].reg_val =
+ cpu_to_le32(ufshcd_readl(hba,
+ REG_UFS_CRYPTOCAP +
+ cap_idx * sizeof(__le32)));
+ blk_mode_num = ufshcd_find_blk_crypto_mode(
+ hba->crypto_cap_array[cap_idx]);
+ if (blk_mode_num != BLK_ENCRYPTION_MODE_INVALID)
+ hba->ksm.crypto_modes_supported[blk_mode_num] |=
+ hba->crypto_cap_array[cap_idx].sdus_mask * 512;
+ }
+
+ return 0;
+
+out_free_caps:
+ devm_kfree(hba->dev, hba->crypto_cap_array);
+out:
+ /* Indicate that init failed by clearing UFSHCD_CAP_CRYPTO */
+ hba->caps &= ~UFSHCD_CAP_CRYPTO;
+ return err;
+}
+
+/**
+ * ufshcd_init_crypto - Initialize crypto hardware
+ * @hba: Per adapter instance
+ */
+void ufshcd_init_crypto(struct ufs_hba *hba)
+{
+ int slot;
+
+ if (!(hba->caps & UFSHCD_CAP_CRYPTO))
+ return;
+
+ /* Clear all keyslots - the number of keyslots is (CFGC + 1) */
+ for (slot = 0; slot < hba->crypto_capabilities.config_count + 1; slot++)
+ ufshcd_clear_keyslot(hba, slot);
+}
+
+void ufshcd_crypto_setup_rq_keyslot_manager(struct ufs_hba *hba,
+ struct request_queue *q)
+{
+ if (hba->caps & UFSHCD_CAP_CRYPTO)
+ blk_ksm_register(&hba->ksm, q);
+}
+
+void ufshcd_crypto_destroy_keyslot_manager(struct ufs_hba *hba)
+{
+ blk_ksm_destroy(&hba->ksm);
+}
diff --git a/drivers/scsi/ufs/ufshcd-crypto.h b/drivers/scsi/ufs/ufshcd-crypto.h
new file mode 100644
index 0000000..d53851b
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd-crypto.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#ifndef _UFSHCD_CRYPTO_H
+#define _UFSHCD_CRYPTO_H
+
+#ifdef CONFIG_SCSI_UFS_CRYPTO
+#include "ufshcd.h"
+#include "ufshci.h"
+
+static inline void ufshcd_prepare_lrbp_crypto(struct request *rq,
+ struct ufshcd_lrb *lrbp)
+{
+ if (!rq || !rq->crypt_keyslot) {
+ lrbp->crypto_key_slot = -1;
+ return;
+ }
+
+ lrbp->crypto_key_slot = blk_ksm_get_slot_idx(rq->crypt_keyslot);
+ lrbp->data_unit_num = rq->crypt_ctx->bc_dun[0];
+}
+
+static inline void
+ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp, u32 *dword_0,
+ u32 *dword_1, u32 *dword_3)
+{
+ if (lrbp->crypto_key_slot >= 0) {
+ *dword_0 |= UTP_REQ_DESC_CRYPTO_ENABLE_CMD;
+ *dword_0 |= lrbp->crypto_key_slot;
+ *dword_1 = lower_32_bits(lrbp->data_unit_num);
+ *dword_3 = upper_32_bits(lrbp->data_unit_num);
+ }
+}
+
+bool ufshcd_crypto_enable(struct ufs_hba *hba);
+
+int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba);
+
+void ufshcd_init_crypto(struct ufs_hba *hba);
+
+void ufshcd_crypto_setup_rq_keyslot_manager(struct ufs_hba *hba,
+ struct request_queue *q);
+
+void ufshcd_crypto_destroy_keyslot_manager(struct ufs_hba *hba);
+
+#else /* CONFIG_SCSI_UFS_CRYPTO */
+
+static inline void ufshcd_prepare_lrbp_crypto(struct request *rq,
+ struct ufshcd_lrb *lrbp) { }
+
+static inline void
+ufshcd_prepare_req_desc_hdr_crypto(struct ufshcd_lrb *lrbp, u32 *dword_0,
+ u32 *dword_1, u32 *dword_3) { }
+
+static inline bool ufshcd_crypto_enable(struct ufs_hba *hba)
+{
+ return false;
+}
+
+static inline int ufshcd_hba_init_crypto_capabilities(struct ufs_hba *hba)
+{
+ return 0;
+}
+
+static inline void ufshcd_init_crypto(struct ufs_hba *hba) { }
+
+static inline void ufshcd_crypto_setup_rq_keyslot_manager(struct ufs_hba *hba,
+ struct request_queue *q) { }
+
+static inline void ufshcd_crypto_destroy_keyslot_manager(struct ufs_hba *hba)
+{ }
+
+#endif /* CONFIG_SCSI_UFS_CRYPTO */
+
+#endif /* _UFSHCD_CRYPTO_H */
diff --git a/drivers/scsi/ufs/ufshcd-dwc.c b/drivers/scsi/ufs/ufshcd-dwc.c
index fb9e2ff..6a901da 100644
--- a/drivers/scsi/ufs/ufshcd-dwc.c
+++ b/drivers/scsi/ufs/ufshcd-dwc.c
@@ -80,7 +80,7 @@
*/
static int ufshcd_dwc_connection_setup(struct ufs_hba *hba)
{
- const struct ufshcd_dme_attr_val setup_attrs[] = {
+ static const struct ufshcd_dme_attr_val setup_attrs[] = {
{ UIC_ARG_MIB(T_CONNECTIONSTATE), 0, DME_LOCAL },
{ UIC_ARG_MIB(N_DEVICEID), 0, DME_LOCAL },
{ UIC_ARG_MIB(N_DEVICEID_VALID), 0, DME_LOCAL },
diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
index e4ba244..4bf8ec8 100644
--- a/drivers/scsi/ufs/ufshcd-pci.c
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Universal Flash Storage Host controller PCI glue driver
*
@@ -7,35 +8,19 @@
* Authors:
* Santosh Yaraganavi <santosh.sy@samsung.com>
* Vinayak Holikatti <h.vinayak@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * See the COPYING file in the top-level directory or visit
- * <http://www.gnu.org/licenses/gpl-2.0.html>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * This program is provided "AS IS" and "WITH ALL FAULTS" and
- * without warranty of any kind. You are solely responsible for
- * determining the appropriateness of using and distributing
- * the program and assume all risks associated with your exercise
- * of rights with respect to the program, including but not limited
- * to infringement of third party rights, the risks and costs of
- * program errors, damage to or loss of data, programs or equipment,
- * and unavailability or interruption of operations. Under no
- * circumstances will the contributor of this Program be liable for
- * any damages of any kind arising from your use or distribution of
- * this program.
*/
#include "ufshcd.h"
#include <linux/pci.h>
#include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
+#include <linux/debugfs.h>
+
+struct intel_host {
+ u32 active_ltr;
+ u32 idle_ltr;
+ struct dentry *debugfs_root;
+};
static int ufs_intel_disable_lcc(struct ufs_hba *hba)
{
@@ -44,7 +29,7 @@
ufshcd_dme_get(hba, attr, &lcc_enable);
if (lcc_enable)
- ufshcd_dme_set(hba, attr, 0);
+ ufshcd_disable_host_tx_lcc(hba);
return 0;
}
@@ -67,9 +52,174 @@
return err;
}
+#define INTEL_ACTIVELTR 0x804
+#define INTEL_IDLELTR 0x808
+
+#define INTEL_LTR_REQ BIT(15)
+#define INTEL_LTR_SCALE_MASK GENMASK(11, 10)
+#define INTEL_LTR_SCALE_1US (2 << 10)
+#define INTEL_LTR_SCALE_32US (3 << 10)
+#define INTEL_LTR_VALUE_MASK GENMASK(9, 0)
+
+static void intel_cache_ltr(struct ufs_hba *hba)
+{
+ struct intel_host *host = ufshcd_get_variant(hba);
+
+ host->active_ltr = readl(hba->mmio_base + INTEL_ACTIVELTR);
+ host->idle_ltr = readl(hba->mmio_base + INTEL_IDLELTR);
+}
+
+static void intel_ltr_set(struct device *dev, s32 val)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+ struct intel_host *host = ufshcd_get_variant(hba);
+ u32 ltr;
+
+ pm_runtime_get_sync(dev);
+
+ /*
+ * Program latency tolerance (LTR) accordingly what has been asked
+ * by the PM QoS layer or disable it in case we were passed
+ * negative value or PM_QOS_LATENCY_ANY.
+ */
+ ltr = readl(hba->mmio_base + INTEL_ACTIVELTR);
+
+ if (val == PM_QOS_LATENCY_ANY || val < 0) {
+ ltr &= ~INTEL_LTR_REQ;
+ } else {
+ ltr |= INTEL_LTR_REQ;
+ ltr &= ~INTEL_LTR_SCALE_MASK;
+ ltr &= ~INTEL_LTR_VALUE_MASK;
+
+ if (val > INTEL_LTR_VALUE_MASK) {
+ val >>= 5;
+ if (val > INTEL_LTR_VALUE_MASK)
+ val = INTEL_LTR_VALUE_MASK;
+ ltr |= INTEL_LTR_SCALE_32US | val;
+ } else {
+ ltr |= INTEL_LTR_SCALE_1US | val;
+ }
+ }
+
+ if (ltr == host->active_ltr)
+ goto out;
+
+ writel(ltr, hba->mmio_base + INTEL_ACTIVELTR);
+ writel(ltr, hba->mmio_base + INTEL_IDLELTR);
+
+ /* Cache the values into intel_host structure */
+ intel_cache_ltr(hba);
+out:
+ pm_runtime_put(dev);
+}
+
+static void intel_ltr_expose(struct device *dev)
+{
+ dev->power.set_latency_tolerance = intel_ltr_set;
+ dev_pm_qos_expose_latency_tolerance(dev);
+}
+
+static void intel_ltr_hide(struct device *dev)
+{
+ dev_pm_qos_hide_latency_tolerance(dev);
+ dev->power.set_latency_tolerance = NULL;
+}
+
+static void intel_add_debugfs(struct ufs_hba *hba)
+{
+ struct dentry *dir = debugfs_create_dir(dev_name(hba->dev), NULL);
+ struct intel_host *host = ufshcd_get_variant(hba);
+
+ intel_cache_ltr(hba);
+
+ host->debugfs_root = dir;
+ debugfs_create_x32("active_ltr", 0444, dir, &host->active_ltr);
+ debugfs_create_x32("idle_ltr", 0444, dir, &host->idle_ltr);
+}
+
+static void intel_remove_debugfs(struct ufs_hba *hba)
+{
+ struct intel_host *host = ufshcd_get_variant(hba);
+
+ debugfs_remove_recursive(host->debugfs_root);
+}
+
+static int ufs_intel_common_init(struct ufs_hba *hba)
+{
+ struct intel_host *host;
+
+ hba->caps |= UFSHCD_CAP_RPM_AUTOSUSPEND;
+
+ host = devm_kzalloc(hba->dev, sizeof(*host), GFP_KERNEL);
+ if (!host)
+ return -ENOMEM;
+ ufshcd_set_variant(hba, host);
+ intel_ltr_expose(hba->dev);
+ intel_add_debugfs(hba);
+ return 0;
+}
+
+static void ufs_intel_common_exit(struct ufs_hba *hba)
+{
+ intel_remove_debugfs(hba);
+ intel_ltr_hide(hba->dev);
+}
+
+static int ufs_intel_resume(struct ufs_hba *hba, enum ufs_pm_op op)
+{
+ /*
+ * To support S4 (suspend-to-disk) with spm_lvl other than 5, the base
+ * address registers must be restored because the restore kernel can
+ * have used different addresses.
+ */
+ ufshcd_writel(hba, lower_32_bits(hba->utrdl_dma_addr),
+ REG_UTP_TRANSFER_REQ_LIST_BASE_L);
+ ufshcd_writel(hba, upper_32_bits(hba->utrdl_dma_addr),
+ REG_UTP_TRANSFER_REQ_LIST_BASE_H);
+ ufshcd_writel(hba, lower_32_bits(hba->utmrdl_dma_addr),
+ REG_UTP_TASK_REQ_LIST_BASE_L);
+ ufshcd_writel(hba, upper_32_bits(hba->utmrdl_dma_addr),
+ REG_UTP_TASK_REQ_LIST_BASE_H);
+
+ if (ufshcd_is_link_hibern8(hba)) {
+ int ret = ufshcd_uic_hibern8_exit(hba);
+
+ if (!ret) {
+ ufshcd_set_link_active(hba);
+ } else {
+ dev_err(hba->dev, "%s: hibern8 exit failed %d\n",
+ __func__, ret);
+ /*
+ * Force reset and restore. Any other actions can lead
+ * to an unrecoverable state.
+ */
+ ufshcd_set_link_off(hba);
+ }
+ }
+
+ return 0;
+}
+
+static int ufs_intel_ehl_init(struct ufs_hba *hba)
+{
+ hba->quirks |= UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8;
+ return ufs_intel_common_init(hba);
+}
+
static struct ufs_hba_variant_ops ufs_intel_cnl_hba_vops = {
.name = "intel-pci",
+ .init = ufs_intel_common_init,
+ .exit = ufs_intel_common_exit,
.link_startup_notify = ufs_intel_link_startup_notify,
+ .resume = ufs_intel_resume,
+};
+
+static struct ufs_hba_variant_ops ufs_intel_ehl_hba_vops = {
+ .name = "intel-pci",
+ .init = ufs_intel_ehl_init,
+ .exit = ufs_intel_common_exit,
+ .link_startup_notify = ufs_intel_link_startup_notify,
+ .resume = ufs_intel_resume,
};
#ifdef CONFIG_PM_SLEEP
@@ -206,7 +356,6 @@
return err;
}
- pci_set_drvdata(pdev, hba);
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_allow(&pdev->dev);
@@ -230,8 +379,8 @@
static const struct pci_device_id ufshcd_pci_tbl[] = {
{ PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VDEVICE(INTEL, 0x9DFA), (kernel_ulong_t)&ufs_intel_cnl_hba_vops },
- { PCI_VDEVICE(INTEL, 0x4B41), (kernel_ulong_t)&ufs_intel_cnl_hba_vops },
- { PCI_VDEVICE(INTEL, 0x4B43), (kernel_ulong_t)&ufs_intel_cnl_hba_vops },
+ { PCI_VDEVICE(INTEL, 0x4B41), (kernel_ulong_t)&ufs_intel_ehl_hba_vops },
+ { PCI_VDEVICE(INTEL, 0x4B43), (kernel_ulong_t)&ufs_intel_ehl_hba_vops },
{ } /* terminate list */
};
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 8d40dc9..0f2430f 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -1,36 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Universal Flash Storage Host controller Platform bus based glue driver
- *
- * This code is based on drivers/scsi/ufs/ufshcd-pltfrm.c
* Copyright (C) 2011-2013 Samsung India Software Operations
*
* Authors:
* Santosh Yaraganavi <santosh.sy@samsung.com>
* Vinayak Holikatti <h.vinayak@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * See the COPYING file in the top-level directory or visit
- * <http://www.gnu.org/licenses/gpl-2.0.html>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * This program is provided "AS IS" and "WITH ALL FAULTS" and
- * without warranty of any kind. You are solely responsible for
- * determining the appropriateness of using and distributing
- * the program and assume all risks associated with your exercise
- * of rights with respect to the program, including but not limited
- * to infringement of third party rights, the risks and costs of
- * program errors, damage to or loss of data, programs or equipment,
- * and unavailability or interruption of operations. Under no
- * circumstances will the contributor of this Program be liable for
- * any damages of any kind arising from your use or distribution of
- * this program.
*/
#include <linux/platform_device.h>
@@ -116,7 +91,14 @@
clki->min_freq = clkfreq[i];
clki->max_freq = clkfreq[i+1];
- clki->name = kstrdup(name, GFP_KERNEL);
+ clki->name = devm_kstrdup(dev, name, GFP_KERNEL);
+ if (!clki->name) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (!strcmp(name, "ref_clk"))
+ clki->keep_link_active = true;
dev_dbg(dev, "%s: min %u max %u name %s\n", "freq-table-hz",
clki->min_freq, clki->max_freq, clki->name);
list_add_tail(&clki->list, &hba->clk_list_head);
@@ -150,7 +132,9 @@
if (!vreg)
return -ENOMEM;
- vreg->name = kstrdup(name, GFP_KERNEL);
+ vreg->name = devm_kstrdup(dev, name, GFP_KERNEL);
+ if (!vreg->name)
+ return -ENOMEM;
snprintf(prop_name, MAX_PROP_SIZE, "%s-max-microamp", name);
if (of_property_read_u32(np, prop_name, &vreg->max_uA)) {
@@ -402,8 +386,7 @@
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(dev, "IRQ resource not available\n");
- err = -ENODEV;
+ err = irq;
goto out;
}
@@ -436,8 +419,6 @@
goto dealloc_host;
}
- platform_set_drvdata(pdev, hba);
-
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 0429ba5..bf30277 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1,40 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Universal Flash Storage Host controller driver Core
- *
- * This code is based on drivers/scsi/ufs/ufshcd.c
* Copyright (C) 2011-2013 Samsung India Software Operations
* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* Authors:
* Santosh Yaraganavi <santosh.sy@samsung.com>
* Vinayak Holikatti <h.vinayak@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * See the COPYING file in the top-level directory or visit
- * <http://www.gnu.org/licenses/gpl-2.0.html>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * This program is provided "AS IS" and "WITH ALL FAULTS" and
- * without warranty of any kind. You are solely responsible for
- * determining the appropriateness of using and distributing
- * the program and assume all risks associated with your exercise
- * of rights with respect to the program, including but not limited
- * to infringement of third party rights, the risks and costs of
- * program errors, damage to or loss of data, programs or equipment,
- * and unavailability or interruption of operations. Under no
- * circumstances will the contributor of this Program be liable for
- * any damages of any kind arising from your use or distribution of
- * this program.
- *
- * The Linux Foundation chooses to take subject only to the GPLv2
- * license terms, and distributes only under these terms.
*/
#include <linux/async.h>
@@ -42,11 +14,16 @@
#include <linux/nls.h>
#include <linux/of.h>
#include <linux/bitfield.h>
+#include <linux/blk-pm.h>
+#include <linux/blkdev.h>
#include "ufshcd.h"
#include "ufs_quirks.h"
#include "unipro.h"
#include "ufs-sysfs.h"
#include "ufs_bsg.h"
+#include "ufshcd-crypto.h"
+#include <asm/unaligned.h>
+#include <linux/blkdev.h>
#define CREATE_TRACE_POINTS
#include <trace/events/ufs.h>
@@ -59,8 +36,8 @@
/* NOP OUT retries waiting for NOP IN response */
#define NOP_OUT_RETRIES 10
-/* Timeout after 30 msecs if NOP OUT hangs without response */
-#define NOP_OUT_TIMEOUT 30 /* msecs */
+/* Timeout after 50 msecs if NOP OUT hangs without response */
+#define NOP_OUT_TIMEOUT 50 /* msecs */
/* Query request retries */
#define QUERY_REQ_RETRIES 3
@@ -88,6 +65,18 @@
/* Interrupt aggregation default timeout, unit: 40us */
#define INT_AGGR_DEF_TO 0x02
+/* default delay of autosuspend: 2000 ms */
+#define RPM_AUTOSUSPEND_DELAY_MS 2000
+
+/* Default delay of RPM device flush delayed work */
+#define RPM_DEV_FLUSH_RECHECK_WORK_DELAY_MS 5000
+
+/* Default value of wait time before gating device ref clock */
+#define UFSHCD_REF_CLK_GATING_WAIT_US 0xFF /* microsecs */
+
+/* Polling time to wait for fDeviceInit */
+#define FDEVICEINIT_COMPL_TIMEOUT 1500 /* millisecs */
+
#define ufshcd_toggle_vreg(_dev, _vreg, _on) \
({ \
int _ret; \
@@ -114,7 +103,7 @@
if (offset % 4 != 0 || len % 4 != 0) /* keep readl happy */
return -EINVAL;
- regs = kzalloc(len, GFP_KERNEL);
+ regs = kzalloc(len, GFP_ATOMIC);
if (!regs)
return -ENOMEM;
@@ -140,7 +129,8 @@
UFSHCD_STATE_RESET,
UFSHCD_STATE_ERROR,
UFSHCD_STATE_OPERATIONAL,
- UFSHCD_STATE_EH_SCHEDULED,
+ UFSHCD_STATE_EH_SCHEDULED_FATAL,
+ UFSHCD_STATE_EH_SCHEDULED_NON_FATAL,
};
/* UFSHCD error handling flags */
@@ -156,6 +146,7 @@
UFSHCD_UIC_NL_ERROR = (1 << 3), /* Network layer error */
UFSHCD_UIC_TL_ERROR = (1 << 4), /* Transport Layer error */
UFSHCD_UIC_DME_ERROR = (1 << 5), /* DME error */
+ UFSHCD_UIC_PA_GENERIC_ERROR = (1 << 6), /* Generic PA error */
};
#define ufshcd_set_eh_in_progress(h) \
@@ -165,19 +156,6 @@
#define ufshcd_clear_eh_in_progress(h) \
((h)->eh_flags &= ~UFSHCD_EH_IN_PROGRESS)
-#define ufshcd_set_ufs_dev_active(h) \
- ((h)->curr_dev_pwr_mode = UFS_ACTIVE_PWR_MODE)
-#define ufshcd_set_ufs_dev_sleep(h) \
- ((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE)
-#define ufshcd_set_ufs_dev_poweroff(h) \
- ((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE)
-#define ufshcd_is_ufs_dev_active(h) \
- ((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE)
-#define ufshcd_is_ufs_dev_sleep(h) \
- ((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE)
-#define ufshcd_is_ufs_dev_poweroff(h) \
- ((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE)
-
struct ufs_pm_lvl_states ufs_pm_lvl_states[] = {
{UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE},
{UFS_ACTIVE_PWR_MODE, UIC_LINK_HIBERN8_STATE},
@@ -220,22 +198,19 @@
UFS_FIX(UFS_VENDOR_MICRON, UFS_ANY_MODEL,
UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
- UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
- UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
+ UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM |
+ UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE |
UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS),
- UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
- UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE),
+ UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL,
+ UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME),
+ UFS_FIX(UFS_VENDOR_SKHYNIX, "hB8aL1" /*H28U62301AMR*/,
+ UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME),
UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL,
UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG",
UFS_DEVICE_QUIRK_PA_TACTIVATE),
UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9D8KBADG",
UFS_DEVICE_QUIRK_PA_TACTIVATE),
- UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL,
- UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME),
- UFS_FIX(UFS_VENDOR_SKHYNIX, "hB8aL1" /*H28U62301AMR*/,
- UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME),
-
END_FIX
};
@@ -245,11 +220,8 @@
static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd);
static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag);
static void ufshcd_hba_exit(struct ufs_hba *hba);
-static int ufshcd_probe_hba(struct ufs_hba *hba);
-static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
- bool skip_ref_clk);
+static int ufshcd_probe_hba(struct ufs_hba *hba, bool async);
static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on);
-static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba);
static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba);
static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba);
static int ufshcd_host_reset_and_restore(struct ufs_hba *hba);
@@ -260,35 +232,59 @@
static irqreturn_t ufshcd_intr(int irq, void *__hba);
static int ufshcd_change_power_mode(struct ufs_hba *hba,
struct ufs_pa_layer_attr *pwr_mode);
+static void ufshcd_schedule_eh_work(struct ufs_hba *hba);
+static int ufshcd_setup_hba_vreg(struct ufs_hba *hba, bool on);
+static int ufshcd_setup_vreg(struct ufs_hba *hba, bool on);
+static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
+ struct ufs_vreg *vreg);
+static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag);
+static int ufshcd_wb_buf_flush_enable(struct ufs_hba *hba);
+static int ufshcd_wb_buf_flush_disable(struct ufs_hba *hba);
+static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable);
+static int ufshcd_wb_toggle_flush_during_h8(struct ufs_hba *hba, bool set);
+static inline void ufshcd_wb_toggle_flush(struct ufs_hba *hba, bool enable);
+
static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
{
return tag >= 0 && tag < hba->nutrs;
}
-static inline int ufshcd_enable_irq(struct ufs_hba *hba)
+static inline void ufshcd_enable_irq(struct ufs_hba *hba)
{
- int ret = 0;
-
if (!hba->is_irq_enabled) {
- ret = request_irq(hba->irq, ufshcd_intr, IRQF_SHARED, UFSHCD,
- hba);
- if (ret)
- dev_err(hba->dev, "%s: request_irq failed, ret=%d\n",
- __func__, ret);
+ enable_irq(hba->irq);
hba->is_irq_enabled = true;
}
-
- return ret;
}
static inline void ufshcd_disable_irq(struct ufs_hba *hba)
{
if (hba->is_irq_enabled) {
- free_irq(hba->irq, hba);
+ disable_irq(hba->irq);
hba->is_irq_enabled = false;
}
}
+static inline void ufshcd_wb_config(struct ufs_hba *hba)
+{
+ int ret;
+
+ if (!ufshcd_is_wb_allowed(hba))
+ return;
+
+ ret = ufshcd_wb_ctrl(hba, true);
+ if (ret)
+ dev_err(hba->dev, "%s: Enable WB failed: %d\n", __func__, ret);
+ else
+ dev_info(hba->dev, "%s: Write Booster Configured\n", __func__);
+ ret = ufshcd_wb_toggle_flush_during_h8(hba, true);
+ if (ret)
+ dev_err(hba->dev, "%s: En WB flush during H8: failed: %d\n",
+ __func__, ret);
+ if (!(hba->quirks & UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL))
+ ufshcd_wb_toggle_flush(hba, true);
+}
+
static void ufshcd_scsi_unblock_requests(struct ufs_hba *hba)
{
if (atomic_dec_and_test(&hba->scsi_block_reqs_cnt))
@@ -320,13 +316,32 @@
static void ufshcd_add_tm_upiu_trace(struct ufs_hba *hba, unsigned int tag,
const char *str)
{
- int off = (int)tag - hba->nutrs;
- struct utp_task_req_desc *descp = &hba->utmrdl_base_addr[off];
+ struct utp_task_req_desc *descp = &hba->utmrdl_base_addr[tag];
trace_ufshcd_upiu(dev_name(hba->dev), str, &descp->req_header,
&descp->input_param1);
}
+static void ufshcd_add_uic_command_trace(struct ufs_hba *hba,
+ struct uic_command *ucmd,
+ const char *str)
+{
+ u32 cmd;
+
+ if (!trace_ufshcd_uic_command_enabled())
+ return;
+
+ if (!strcmp(str, "send"))
+ cmd = ucmd->command;
+ else
+ cmd = ufshcd_readl(hba, REG_UIC_COMMAND);
+
+ trace_ufshcd_uic_command(dev_name(hba->dev), str, cmd,
+ ufshcd_readl(hba, REG_UIC_COMMAND_ARG_1),
+ ufshcd_readl(hba, REG_UIC_COMMAND_ARG_2),
+ ufshcd_readl(hba, REG_UIC_COMMAND_ARG_3));
+}
+
static void ufshcd_add_command_trace(struct ufs_hba *hba,
unsigned int tag, const char *str)
{
@@ -392,7 +407,7 @@
for (i = 0; i < UFS_ERR_REG_HIST_LENGTH; i++) {
int p = (i + err_hist->pos) % UFS_ERR_REG_HIST_LENGTH;
- if (err_hist->reg[p] == 0)
+ if (err_hist->tstamp[p] == 0)
continue;
dev_err(hba->dev, "%s[%d] = 0x%x at %lld us\n", err_name, p,
err_hist->reg[p], ktime_to_us(err_hist->tstamp[p]));
@@ -400,21 +415,12 @@
}
if (!found)
- dev_err(hba->dev, "No record of %s errors\n", err_name);
+ dev_err(hba->dev, "No record of %s\n", err_name);
}
static void ufshcd_print_host_regs(struct ufs_hba *hba)
{
ufshcd_dump_regs(hba, 0, UFSHCI_REG_SPACE_SIZE, "host_regs: ");
- dev_err(hba->dev, "hba->ufs_version = 0x%x, hba->capabilities = 0x%x\n",
- hba->ufs_version, hba->capabilities);
- dev_err(hba->dev,
- "hba->outstanding_reqs = 0x%x, hba->outstanding_tasks = 0x%x\n",
- (u32)hba->outstanding_reqs, (u32)hba->outstanding_tasks);
- dev_err(hba->dev,
- "last_hibern8_exit_tstamp at %lld us, hibern8_exit_cnt = %d\n",
- ktime_to_us(hba->ufs_stats.last_hibern8_exit_tstamp),
- hba->ufs_stats.hibern8_exit_cnt);
ufshcd_print_err_hist(hba, &hba->ufs_stats.pa_err, "pa_err");
ufshcd_print_err_hist(hba, &hba->ufs_stats.dl_err, "dl_err");
@@ -433,10 +439,7 @@
ufshcd_print_err_hist(hba, &hba->ufs_stats.host_reset, "host_reset");
ufshcd_print_err_hist(hba, &hba->ufs_stats.task_abort, "task_abort");
- ufshcd_print_clk_freqs(hba);
-
- if (hba->vops && hba->vops->dbg_register_dump)
- hba->vops->dbg_register_dump(hba);
+ ufshcd_vops_dbg_register_dump(hba);
}
static
@@ -470,6 +473,9 @@
prdt_length = le16_to_cpu(
lrbp->utr_descriptor_ptr->prd_table_length);
+ if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN)
+ prdt_length /= sizeof(struct ufshcd_sg_entry);
+
dev_err(hba->dev,
"UPIU[%d] - PRDT - %d entries phys@0x%llx\n",
tag, prdt_length,
@@ -495,6 +501,8 @@
static void ufshcd_print_host_state(struct ufs_hba *hba)
{
+ struct scsi_device *sdev_ufs = hba->sdev_ufs_device;
+
dev_err(hba->dev, "UFS Host state=%d\n", hba->ufshcd_state);
dev_err(hba->dev, "outstanding reqs=0x%lx tasks=0x%lx\n",
hba->outstanding_reqs, hba->outstanding_tasks);
@@ -507,12 +515,24 @@
dev_err(hba->dev, "Auto BKOPS=%d, Host self-block=%d\n",
hba->auto_bkops_enabled, hba->host->host_self_blocked);
dev_err(hba->dev, "Clk gate=%d\n", hba->clk_gating.state);
+ dev_err(hba->dev,
+ "last_hibern8_exit_tstamp at %lld us, hibern8_exit_cnt=%d\n",
+ ktime_to_us(hba->ufs_stats.last_hibern8_exit_tstamp),
+ hba->ufs_stats.hibern8_exit_cnt);
+ dev_err(hba->dev, "last intr at %lld us, last intr status=0x%x\n",
+ ktime_to_us(hba->ufs_stats.last_intr_ts),
+ hba->ufs_stats.last_intr_status);
dev_err(hba->dev, "error handling flags=0x%x, req. abort count=%d\n",
hba->eh_flags, hba->req_abort_count);
- dev_err(hba->dev, "Host capabilities=0x%x, caps=0x%x\n",
- hba->capabilities, hba->caps);
+ dev_err(hba->dev, "hba->ufs_version=0x%x, Host capabilities=0x%x, caps=0x%x\n",
+ hba->ufs_version, hba->capabilities, hba->caps);
dev_err(hba->dev, "quirks=0x%x, dev. quirks=0x%x\n", hba->quirks,
hba->dev_quirks);
+ if (sdev_ufs)
+ dev_err(hba->dev, "UFS dev info: %.8s %.16s rev %.4s\n",
+ sdev_ufs->vendor, sdev_ufs->model, sdev_ufs->rev);
+
+ ufshcd_print_clk_freqs(hba);
}
/**
@@ -541,21 +561,33 @@
hba->pwr_info.hs_rate);
}
-/*
+void ufshcd_delay_us(unsigned long us, unsigned long tolerance)
+{
+ if (!us)
+ return;
+
+ if (us < 10)
+ udelay(us);
+ else
+ usleep_range(us, us + tolerance);
+}
+EXPORT_SYMBOL_GPL(ufshcd_delay_us);
+
+/**
* ufshcd_wait_for_register - wait for register value to change
- * @hba - per-adapter interface
- * @reg - mmio register offset
- * @mask - mask to apply to read register value
- * @val - wait condition
- * @interval_us - polling interval in microsecs
- * @timeout_ms - timeout in millisecs
- * @can_sleep - perform sleep or just spin
+ * @hba: per-adapter interface
+ * @reg: mmio register offset
+ * @mask: mask to apply to the read register value
+ * @val: value to wait for
+ * @interval_us: polling interval in microseconds
+ * @timeout_ms: timeout in milliseconds
*
- * Returns -ETIMEDOUT on error, zero on success
+ * Return:
+ * -ETIMEDOUT on error, zero on success.
*/
int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
u32 val, unsigned long interval_us,
- unsigned long timeout_ms, bool can_sleep)
+ unsigned long timeout_ms)
{
int err = 0;
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
@@ -564,10 +596,7 @@
val = val & mask;
while ((ufshcd_readl(hba, reg) & mask) != val) {
- if (can_sleep)
- usleep_range(interval_us, interval_us + 50);
- else
- udelay(interval_us);
+ usleep_range(interval_us, interval_us + 50);
if (time_after(jiffies, timeout)) {
if ((ufshcd_readl(hba, reg) & mask) != val)
err = -ETIMEDOUT;
@@ -825,7 +854,12 @@
*/
static inline void ufshcd_hba_start(struct ufs_hba *hba)
{
- ufshcd_writel(hba, CONTROLLER_ENABLE, REG_CONTROLLER_ENABLE);
+ u32 val = CONTROLLER_ENABLE;
+
+ if (ufshcd_crypto_enable(hba))
+ val |= CRYPTO_GENERAL_ENABLE;
+
+ ufshcd_writel(hba, val, REG_CONTROLLER_ENABLE);
}
/**
@@ -868,28 +902,29 @@
return false;
}
-static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up)
+/**
+ * ufshcd_set_clk_freq - set UFS controller clock frequencies
+ * @hba: per adapter instance
+ * @scale_up: If True, set max possible frequency othewise set low frequency
+ *
+ * Returns 0 if successful
+ * Returns < 0 for any other errors
+ */
+static int ufshcd_set_clk_freq(struct ufs_hba *hba, bool scale_up)
{
int ret = 0;
struct ufs_clk_info *clki;
struct list_head *head = &hba->clk_list_head;
- ktime_t start = ktime_get();
- bool clk_state_changed = false;
if (list_empty(head))
goto out;
- ret = ufshcd_vops_clk_scale_notify(hba, scale_up, PRE_CHANGE);
- if (ret)
- return ret;
-
list_for_each_entry(clki, head, list) {
if (!IS_ERR_OR_NULL(clki->clk)) {
if (scale_up && clki->max_freq) {
if (clki->curr_freq == clki->max_freq)
continue;
- clk_state_changed = true;
ret = clk_set_rate(clki->clk, clki->max_freq);
if (ret) {
dev_err(hba->dev, "%s: %s clk set rate(%dHz) failed, %d\n",
@@ -908,7 +943,6 @@
if (clki->curr_freq == clki->min_freq)
continue;
- clk_state_changed = true;
ret = clk_set_rate(clki->clk, clki->min_freq);
if (ret) {
dev_err(hba->dev, "%s: %s clk set rate(%dHz) failed, %d\n",
@@ -927,11 +961,37 @@
clki->name, clk_get_rate(clki->clk));
}
+out:
+ return ret;
+}
+
+/**
+ * ufshcd_scale_clks - scale up or scale down UFS controller clocks
+ * @hba: per adapter instance
+ * @scale_up: True if scaling up and false if scaling down
+ *
+ * Returns 0 if successful
+ * Returns < 0 for any other errors
+ */
+static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up)
+{
+ int ret = 0;
+ ktime_t start = ktime_get();
+
+ ret = ufshcd_vops_clk_scale_notify(hba, scale_up, PRE_CHANGE);
+ if (ret)
+ goto out;
+
+ ret = ufshcd_set_clk_freq(hba, scale_up);
+ if (ret)
+ goto out;
+
ret = ufshcd_vops_clk_scale_notify(hba, scale_up, POST_CHANGE);
+ if (ret)
+ ufshcd_set_clk_freq(hba, !scale_up);
out:
- if (clk_state_changed)
- trace_ufshcd_profile_clk_scaling(dev_name(hba->dev),
+ trace_ufshcd_profile_clk_scaling(dev_name(hba->dev),
(scale_up ? "up" : "down"),
ktime_to_us(ktime_sub(ktime_get(), start)), ret);
return ret;
@@ -1065,8 +1125,7 @@
}
/* check if the power mode needs to be changed or not? */
- ret = ufshcd_change_power_mode(hba, &new_pwr_info);
-
+ ret = ufshcd_config_pwr_mode(hba, &new_pwr_info);
if (ret)
dev_err(hba->dev, "%s: failed err %d, old gear: (tx %d rx %d), new gear: (tx %d rx %d)",
__func__, ret,
@@ -1119,20 +1178,20 @@
ret = ufshcd_clock_scaling_prepare(hba);
if (ret)
- return ret;
+ goto out;
/* scale down the gear before scaling down clocks */
if (!scale_up) {
ret = ufshcd_scale_gear(hba, false);
if (ret)
- goto out;
+ goto out_unprepare;
}
ret = ufshcd_scale_clks(hba, scale_up);
if (ret) {
if (!scale_up)
ufshcd_scale_gear(hba, true);
- goto out;
+ goto out_unprepare;
}
/* scale up the gear after scaling up clocks */
@@ -1140,14 +1199,18 @@
ret = ufshcd_scale_gear(hba, true);
if (ret) {
ufshcd_scale_clks(hba, false);
- goto out;
+ goto out_unprepare;
}
}
- ret = ufshcd_vops_clk_scale_notify(hba, scale_up, POST_CHANGE);
+ /* Enable Write Booster if we have scaled up else disable it */
+ up_write(&hba->clk_scaling_lock);
+ ufshcd_wb_ctrl(hba, scale_up);
+ down_write(&hba->clk_scaling_lock);
-out:
+out_unprepare:
ufshcd_clock_scaling_unprepare(hba);
+out:
ufshcd_release(hba);
return ret;
}
@@ -1200,6 +1263,9 @@
if (!ufshcd_is_clkscaling_supported(hba))
return -EINVAL;
+ clki = list_first_entry(&hba->clk_list_head, struct ufs_clk_info, list);
+ /* Override with the closest supported frequency */
+ *freq = (unsigned long) clk_round_rate(clki->clk, *freq);
spin_lock_irqsave(hba->host->host_lock, irq_flags);
if (ufshcd_eh_in_progress(hba)) {
spin_unlock_irqrestore(hba->host->host_lock, irq_flags);
@@ -1214,8 +1280,11 @@
goto out;
}
- clki = list_first_entry(&hba->clk_list_head, struct ufs_clk_info, list);
+ /* Decide based on the rounded-off frequency and update */
scale_up = (*freq == clki->max_freq) ? true : false;
+ if (!scale_up)
+ *freq = clki->min_freq;
+ /* Update the frequency */
if (!ufshcd_is_devfreq_scaling_required(hba, scale_up)) {
spin_unlock_irqrestore(hba->host->host_lock, irq_flags);
ret = 0;
@@ -1270,6 +1339,9 @@
struct ufs_hba *hba = dev_get_drvdata(dev);
struct ufs_clk_scaling *scaling = &hba->clk_scaling;
unsigned long flags;
+ struct list_head *clk_list = &hba->clk_list_head;
+ struct ufs_clk_info *clki;
+ ktime_t curr_t;
if (!ufshcd_is_clkscaling_supported(hba))
return -EINVAL;
@@ -1277,22 +1349,29 @@
memset(stat, 0, sizeof(*stat));
spin_lock_irqsave(hba->host->host_lock, flags);
+ curr_t = ktime_get();
if (!scaling->window_start_t)
goto start_window;
+ clki = list_first_entry(clk_list, struct ufs_clk_info, list);
+ /*
+ * If current frequency is 0, then the ondemand governor considers
+ * there's no initial frequency set. And it always requests to set
+ * to max. frequency.
+ */
+ stat->current_frequency = clki->curr_freq;
if (scaling->is_busy_started)
- scaling->tot_busy_t += ktime_to_us(ktime_sub(ktime_get(),
- scaling->busy_start_t));
+ scaling->tot_busy_t += ktime_us_delta(curr_t,
+ scaling->busy_start_t);
- stat->total_time = jiffies_to_usecs((long)jiffies -
- (long)scaling->window_start_t);
+ stat->total_time = ktime_us_delta(curr_t, scaling->window_start_t);
stat->busy_time = scaling->tot_busy_t;
start_window:
- scaling->window_start_t = jiffies;
+ scaling->window_start_t = curr_t;
scaling->tot_busy_t = 0;
if (hba->outstanding_reqs) {
- scaling->busy_start_t = ktime_get();
+ scaling->busy_start_t = curr_t;
scaling->is_busy_started = true;
} else {
scaling->busy_start_t = 0;
@@ -1302,12 +1381,6 @@
return 0;
}
-static struct devfreq_dev_profile ufs_devfreq_profile = {
- .polling_ms = 100,
- .target = ufshcd_devfreq_target,
- .get_dev_status = ufshcd_devfreq_get_dev_status,
-};
-
static int ufshcd_devfreq_init(struct ufs_hba *hba)
{
struct list_head *clk_list = &hba->clk_list_head;
@@ -1323,10 +1396,12 @@
dev_pm_opp_add(hba->dev, clki->min_freq, 0);
dev_pm_opp_add(hba->dev, clki->max_freq, 0);
+ ufshcd_vops_config_scaling_param(hba, &hba->vps->devfreq_profile,
+ &hba->vps->ondemand_data);
devfreq = devfreq_add_device(hba->dev,
- &ufs_devfreq_profile,
+ &hba->vps->devfreq_profile,
DEVFREQ_GOV_SIMPLE_ONDEMAND,
- NULL);
+ &hba->vps->ondemand_data);
if (IS_ERR(devfreq)) {
ret = PTR_ERR(devfreq);
dev_err(hba->dev, "Unable to register with devfreq %d\n", ret);
@@ -1480,6 +1555,8 @@
spin_unlock_irqrestore(hba->host->host_lock, flags);
ufshcd_setup_clocks(hba, true);
+ ufshcd_enable_irq(hba);
+
/* Exit from hibern8 */
if (ufshcd_can_hibern8_during_gating(hba)) {
/* Prevent gating in this path */
@@ -1515,11 +1592,6 @@
spin_lock_irqsave(hba->host->host_lock, flags);
hba->clk_gating.active_reqs++;
- if (ufshcd_eh_in_progress(hba)) {
- spin_unlock_irqrestore(hba->host->host_lock, flags);
- return 0;
- }
-
start:
switch (hba->clk_gating.state) {
case CLKS_ON:
@@ -1558,7 +1630,7 @@
* currently running. Hence, fall through to cancel gating
* work and to enable clocks.
*/
- /* fallthrough */
+ fallthrough;
case CLKS_OFF:
hba->clk_gating.state = REQ_CLKS_ON;
trace_ufshcd_clk_gating(dev_name(hba->dev),
@@ -1570,7 +1642,7 @@
* fall through to check if we should wait for this
* work to be done or not.
*/
- /* fallthrough */
+ fallthrough;
case REQ_CLKS_ON:
if (async) {
rc = -EAGAIN;
@@ -1599,6 +1671,7 @@
struct ufs_hba *hba = container_of(work, struct ufs_hba,
clk_gating.gate_work.work);
unsigned long flags;
+ int ret;
spin_lock_irqsave(hba->host->host_lock, flags);
/*
@@ -1608,7 +1681,7 @@
* state to CLKS_ON.
*/
if (hba->clk_gating.is_suspended ||
- (hba->clk_gating.state == REQ_CLKS_ON)) {
+ (hba->clk_gating.state != REQ_CLKS_OFF)) {
hba->clk_gating.state = CLKS_ON;
trace_ufshcd_clk_gating(dev_name(hba->dev),
hba->clk_gating.state);
@@ -1625,8 +1698,11 @@
/* put the link into hibern8 mode before turning off clocks */
if (ufshcd_can_hibern8_during_gating(hba)) {
- if (ufshcd_uic_hibern8_enter(hba)) {
+ ret = ufshcd_uic_hibern8_enter(hba);
+ if (ret) {
hba->clk_gating.state = CLKS_ON;
+ dev_err(hba->dev, "%s: hibern8 enter failed %d\n",
+ __func__, ret);
trace_ufshcd_clk_gating(dev_name(hba->dev),
hba->clk_gating.state);
goto out;
@@ -1634,11 +1710,9 @@
ufshcd_set_link_hibern8(hba);
}
- if (!ufshcd_is_link_active(hba))
- ufshcd_setup_clocks(hba, false);
- else
- /* If link is active, device ref_clk can't be switched off */
- __ufshcd_setup_clocks(hba, false, true);
+ ufshcd_disable_irq(hba);
+
+ ufshcd_setup_clocks(hba, false);
/*
* In case you are here to cancel this work the gating state
@@ -1669,11 +1743,11 @@
hba->clk_gating.active_reqs--;
- if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended
- || hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL
- || ufshcd_any_tag_in_use(hba) || hba->outstanding_tasks
- || hba->active_uic_cmd || hba->uic_async_done
- || ufshcd_eh_in_progress(hba))
+ if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended ||
+ hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL ||
+ hba->outstanding_tasks ||
+ hba->active_uic_cmd || hba->uic_async_done ||
+ hba->clk_gating.state == CLKS_OFF)
return;
hba->clk_gating.state = REQ_CLKS_OFF;
@@ -1786,6 +1860,8 @@
if (!ufshcd_is_clkgating_allowed(hba))
return;
+ hba->clk_gating.state = CLKS_ON;
+
hba->clk_gating.delay_ms = 150;
INIT_DELAYED_WORK(&hba->clk_gating.gate_work, ufshcd_gate_work);
INIT_WORK(&hba->clk_gating.ungate_work, ufshcd_ungate_work);
@@ -1829,6 +1905,7 @@
static void ufshcd_clk_scaling_start_busy(struct ufs_hba *hba)
{
bool queue_resume_work = false;
+ ktime_t curr_t = ktime_get();
if (!ufshcd_is_clkscaling_supported(hba))
return;
@@ -1844,13 +1921,13 @@
&hba->clk_scaling.resume_work);
if (!hba->clk_scaling.window_start_t) {
- hba->clk_scaling.window_start_t = jiffies;
+ hba->clk_scaling.window_start_t = curr_t;
hba->clk_scaling.tot_busy_t = 0;
hba->clk_scaling.is_busy_started = false;
}
if (!hba->clk_scaling.is_busy_started) {
- hba->clk_scaling.busy_start_t = ktime_get();
+ hba->clk_scaling.busy_start_t = curr_t;
hba->clk_scaling.is_busy_started = true;
}
}
@@ -1877,8 +1954,11 @@
static inline
void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
{
- hba->lrb[task_tag].issue_time_stamp = ktime_get();
- hba->lrb[task_tag].compl_time_stamp = ktime_set(0, 0);
+ struct ufshcd_lrb *lrbp = &hba->lrb[task_tag];
+
+ lrbp->issue_time_stamp = ktime_get();
+ lrbp->compl_time_stamp = ktime_set(0, 0);
+ ufshcd_vops_setup_xfer_req(hba, task_tag, (lrbp->cmd ? true : false));
ufshcd_add_command_trace(hba, task_tag, "send");
ufshcd_clk_scaling_start_busy(hba);
__set_bit(task_tag, &hba->outstanding_reqs);
@@ -1936,8 +2016,8 @@
memcpy(hba->dev_cmd.query.descriptor, descp, resp_len);
} else {
dev_warn(hba->dev,
- "%s: Response size is bigger than buffer",
- __func__);
+ "%s: rsp size %d is bigger than buffer size %d",
+ __func__, resp_len, buf_len);
return -EINVAL;
}
}
@@ -1948,15 +2028,26 @@
/**
* ufshcd_hba_capabilities - Read controller capabilities
* @hba: per adapter instance
+ *
+ * Return: 0 on success, negative on error.
*/
-static inline void ufshcd_hba_capabilities(struct ufs_hba *hba)
+static inline int ufshcd_hba_capabilities(struct ufs_hba *hba)
{
+ int err;
+
hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES);
/* nutrs and nutmrs are 0 based values */
hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1;
hba->nutmrs =
((hba->capabilities & MASK_TASK_MANAGEMENT_REQUEST_SLOTS) >> 16) + 1;
+
+ /* Read crypto capabilities */
+ err = ufshcd_hba_init_crypto_capabilities(hba);
+ if (err)
+ dev_err(hba->dev, "crypto setup failed\n");
+
+ return err;
}
/**
@@ -2004,6 +2095,8 @@
ufshcd_writel(hba, uic_cmd->argument2, REG_UIC_COMMAND_ARG_2);
ufshcd_writel(hba, uic_cmd->argument3, REG_UIC_COMMAND_ARG_3);
+ ufshcd_add_uic_command_trace(hba, uic_cmd, "send");
+
/* Write UIC Cmd */
ufshcd_writel(hba, uic_cmd->command & COMMAND_OPCODE_MASK,
REG_UIC_COMMAND);
@@ -2024,10 +2117,20 @@
unsigned long flags;
if (wait_for_completion_timeout(&uic_cmd->done,
- msecs_to_jiffies(UIC_CMD_TIMEOUT)))
+ msecs_to_jiffies(UIC_CMD_TIMEOUT))) {
ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
- else
+ } else {
ret = -ETIMEDOUT;
+ dev_err(hba->dev,
+ "uic cmd 0x%x with arg3 0x%x completion timeout\n",
+ uic_cmd->command, uic_cmd->argument3);
+
+ if (!uic_cmd->cmd_active) {
+ dev_err(hba->dev, "%s: UIC cmd has been completed, return the result\n",
+ __func__);
+ ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT;
+ }
+ }
spin_lock_irqsave(hba->host->host_lock, flags);
hba->active_uic_cmd = NULL;
@@ -2059,6 +2162,7 @@
if (completion)
init_completion(&uic_cmd->done);
+ uic_cmd->cmd_active = 1;
ufshcd_dispatch_uic_cmd(hba, uic_cmd);
return 0;
@@ -2113,9 +2217,10 @@
return sg_segments;
if (sg_segments) {
+
if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN)
lrbp->utr_descriptor_ptr->prd_table_length =
- cpu_to_le16((u16)(sg_segments *
+ cpu_to_le16((sg_segments *
sizeof(struct ufshcd_sg_entry)));
else
lrbp->utr_descriptor_ptr->prd_table_length =
@@ -2189,11 +2294,13 @@
* @cmd_dir: requests data direction
*/
static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp,
- u32 *upiu_flags, enum dma_data_direction cmd_dir)
+ u8 *upiu_flags, enum dma_data_direction cmd_dir)
{
struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr;
u32 data_direction;
u32 dword_0;
+ u32 dword_1 = 0;
+ u32 dword_3 = 0;
if (cmd_dir == DMA_FROM_DEVICE) {
data_direction = UTP_DEVICE_TO_HOST;
@@ -2211,10 +2318,12 @@
if (lrbp->intr_cmd)
dword_0 |= UTP_REQ_DESC_INT_CMD;
+ /* Prepare crypto related dwords */
+ ufshcd_prepare_req_desc_hdr_crypto(lrbp, &dword_0, &dword_1, &dword_3);
+
/* Transfer request descriptor header fields */
req_desc->header.dword_0 = cpu_to_le32(dword_0);
- /* dword_1 is reserved, hence it is set to 0 */
- req_desc->header.dword_1 = 0;
+ req_desc->header.dword_1 = cpu_to_le32(dword_1);
/*
* assigning invalid value for command status. Controller
* updates OCS on command completion, with the command
@@ -2222,8 +2331,7 @@
*/
req_desc->header.dword_2 =
cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
- /* dword_3 is reserved, hence it is set to 0 */
- req_desc->header.dword_3 = 0;
+ req_desc->header.dword_3 = cpu_to_le32(dword_3);
req_desc->prd_table_length = 0;
}
@@ -2235,8 +2343,9 @@
* @upiu_flags: flags
*/
static
-void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u32 upiu_flags)
+void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u8 upiu_flags)
{
+ struct scsi_cmnd *cmd = lrbp->cmd;
struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
unsigned short cdb_len;
@@ -2250,12 +2359,11 @@
/* Total EHS length and Data segment length will be zero */
ucd_req_ptr->header.dword_2 = 0;
- ucd_req_ptr->sc.exp_data_transfer_len =
- cpu_to_be32(lrbp->cmd->sdb.length);
+ ucd_req_ptr->sc.exp_data_transfer_len = cpu_to_be32(cmd->sdb.length);
- cdb_len = min_t(unsigned short, lrbp->cmd->cmd_len, UFS_CDB_SIZE);
+ cdb_len = min_t(unsigned short, cmd->cmd_len, UFS_CDB_SIZE);
memset(ucd_req_ptr->sc.cdb, 0, UFS_CDB_SIZE);
- memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd, cdb_len);
+ memcpy(ucd_req_ptr->sc.cdb, cmd->cmnd, cdb_len);
memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
}
@@ -2268,7 +2376,7 @@
* @upiu_flags: flags
*/
static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba,
- struct ufshcd_lrb *lrbp, u32 upiu_flags)
+ struct ufshcd_lrb *lrbp, u8 upiu_flags)
{
struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
struct ufs_query *query = &hba->dev_cmd.query;
@@ -2317,14 +2425,15 @@
}
/**
- * ufshcd_comp_devman_upiu - UFS Protocol Information Unit(UPIU)
+ * ufshcd_compose_devman_upiu - UFS Protocol Information Unit(UPIU)
* for Device Management Purposes
* @hba: per adapter instance
* @lrbp: pointer to local reference block
*/
-static int ufshcd_comp_devman_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
+static int ufshcd_compose_devman_upiu(struct ufs_hba *hba,
+ struct ufshcd_lrb *lrbp)
{
- u32 upiu_flags;
+ u8 upiu_flags;
int ret = 0;
if ((hba->ufs_version == UFSHCI_VERSION_10) ||
@@ -2352,7 +2461,7 @@
*/
static int ufshcd_comp_scsi_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
{
- u32 upiu_flags;
+ u8 upiu_flags;
int ret = 0;
if ((hba->ufs_version == UFSHCI_VERSION_10) ||
@@ -2383,6 +2492,27 @@
return (upiu_wlun_id & ~UFS_UPIU_WLUN_ID) | SCSI_W_LUN_BASE;
}
+static void ufshcd_init_lrb(struct ufs_hba *hba, struct ufshcd_lrb *lrb, int i)
+{
+ struct utp_transfer_cmd_desc *cmd_descp = hba->ucdl_base_addr;
+ struct utp_transfer_req_desc *utrdlp = hba->utrdl_base_addr;
+ dma_addr_t cmd_desc_element_addr = hba->ucdl_dma_addr +
+ i * sizeof(struct utp_transfer_cmd_desc);
+ u16 response_offset = offsetof(struct utp_transfer_cmd_desc,
+ response_upiu);
+ u16 prdt_offset = offsetof(struct utp_transfer_cmd_desc, prd_table);
+
+ lrb->utr_descriptor_ptr = utrdlp + i;
+ lrb->utrd_dma_addr = hba->utrdl_dma_addr +
+ i * sizeof(struct utp_transfer_req_desc);
+ lrb->ucd_req_ptr = (struct utp_upiu_req *)(cmd_descp + i);
+ lrb->ucd_req_dma_addr = cmd_desc_element_addr;
+ lrb->ucd_rsp_ptr = (struct utp_upiu_rsp *)cmd_descp[i].response_upiu;
+ lrb->ucd_rsp_dma_addr = cmd_desc_element_addr + response_offset;
+ lrb->ucd_prdt_ptr = (struct ufshcd_sg_entry *)cmd_descp[i].prd_table;
+ lrb->ucd_prdt_dma_addr = cmd_desc_element_addr + prdt_offset;
+}
+
/**
* ufshcd_queuecommand - main entry point for SCSI requests
* @host: SCSI host pointer
@@ -2411,34 +2541,6 @@
if (!down_read_trylock(&hba->clk_scaling_lock))
return SCSI_MLQUEUE_HOST_BUSY;
- spin_lock_irqsave(hba->host->host_lock, flags);
- switch (hba->ufshcd_state) {
- case UFSHCD_STATE_OPERATIONAL:
- break;
- case UFSHCD_STATE_EH_SCHEDULED:
- case UFSHCD_STATE_RESET:
- err = SCSI_MLQUEUE_HOST_BUSY;
- goto out_unlock;
- case UFSHCD_STATE_ERROR:
- set_host_byte(cmd, DID_ERROR);
- cmd->scsi_done(cmd);
- goto out_unlock;
- default:
- dev_WARN_ONCE(hba->dev, 1, "%s: invalid state %d\n",
- __func__, hba->ufshcd_state);
- set_host_byte(cmd, DID_BAD_TARGET);
- cmd->scsi_done(cmd);
- goto out_unlock;
- }
-
- /* if error handling is in progress, don't issue commands */
- if (ufshcd_eh_in_progress(hba)) {
- set_host_byte(cmd, DID_ERROR);
- cmd->scsi_done(cmd);
- goto out_unlock;
- }
- spin_unlock_irqrestore(hba->host->host_lock, flags);
-
hba->req_abort_count = 0;
err = ufshcd_hold(hba, true);
@@ -2446,7 +2548,8 @@
err = SCSI_MLQUEUE_HOST_BUSY;
goto out;
}
- WARN_ON(hba->clk_gating.state != CLKS_ON);
+ WARN_ON(ufshcd_is_clkgating_allowed(hba) &&
+ (hba->clk_gating.state != CLKS_ON));
lrbp = &hba->lrb[tag];
@@ -2457,25 +2560,67 @@
lrbp->task_tag = tag;
lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun);
lrbp->intr_cmd = !ufshcd_is_intr_aggr_allowed(hba) ? true : false;
+
+ ufshcd_prepare_lrbp_crypto(cmd->request, lrbp);
+
lrbp->req_abort_skip = false;
ufshcd_comp_scsi_upiu(hba, lrbp);
err = ufshcd_map_sg(hba, lrbp);
if (err) {
- ufshcd_release(hba);
lrbp->cmd = NULL;
+ ufshcd_release(hba);
goto out;
}
/* Make sure descriptors are ready before ringing the doorbell */
wmb();
- /* issue command to the controller */
spin_lock_irqsave(hba->host->host_lock, flags);
- ufshcd_vops_setup_xfer_req(hba, tag, (lrbp->cmd ? true : false));
+ switch (hba->ufshcd_state) {
+ case UFSHCD_STATE_OPERATIONAL:
+ case UFSHCD_STATE_EH_SCHEDULED_NON_FATAL:
+ break;
+ case UFSHCD_STATE_EH_SCHEDULED_FATAL:
+ /*
+ * pm_runtime_get_sync() is used at error handling preparation
+ * stage. If a scsi cmd, e.g. the SSU cmd, is sent from hba's
+ * PM ops, it can never be finished if we let SCSI layer keep
+ * retrying it, which gets err handler stuck forever. Neither
+ * can we let the scsi cmd pass through, because UFS is in bad
+ * state, the scsi cmd may eventually time out, which will get
+ * err handler blocked for too long. So, just fail the scsi cmd
+ * sent from PM ops, err handler can recover PM error anyways.
+ */
+ if (hba->pm_op_in_progress) {
+ hba->force_reset = true;
+ set_host_byte(cmd, DID_BAD_TARGET);
+ goto out_compl_cmd;
+ }
+ fallthrough;
+ case UFSHCD_STATE_RESET:
+ err = SCSI_MLQUEUE_HOST_BUSY;
+ goto out_compl_cmd;
+ case UFSHCD_STATE_ERROR:
+ set_host_byte(cmd, DID_ERROR);
+ goto out_compl_cmd;
+ default:
+ dev_WARN_ONCE(hba->dev, 1, "%s: invalid state %d\n",
+ __func__, hba->ufshcd_state);
+ set_host_byte(cmd, DID_BAD_TARGET);
+ goto out_compl_cmd;
+ }
ufshcd_send_command(hba, tag);
-out_unlock:
spin_unlock_irqrestore(hba->host->host_lock, flags);
+ goto out;
+
+out_compl_cmd:
+ scsi_dma_unmap(lrbp->cmd);
+ lrbp->cmd = NULL;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+ ufshcd_release(hba);
+ if (!err)
+ cmd->scsi_done(cmd);
out:
up_read(&hba->clk_scaling_lock);
return err;
@@ -2490,9 +2635,10 @@
lrbp->task_tag = tag;
lrbp->lun = 0; /* device management cmd is not specific to any LUN */
lrbp->intr_cmd = true; /* No interrupt aggregation */
+ ufshcd_prepare_lrbp_crypto(NULL, lrbp);
hba->dev_cmd.type = cmd_type;
- return ufshcd_comp_devman_upiu(hba, lrbp);
+ return ufshcd_compose_devman_upiu(hba, lrbp);
}
static int
@@ -2513,7 +2659,7 @@
*/
err = ufshcd_wait_for_register(hba,
REG_UTP_TRANSFER_REQ_DOOR_BELL,
- mask, ~mask, 1000, 1000, true);
+ mask, ~mask, 1000, 1000);
return err;
}
@@ -2662,7 +2808,6 @@
/* Make sure descriptors are ready before ringing the doorbell */
wmb();
spin_lock_irqsave(hba->host->host_lock, flags);
- ufshcd_vops_setup_xfer_req(hba, tag, (lrbp->cmd ? true : false));
ufshcd_send_command(hba, tag);
spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -2703,13 +2848,13 @@
}
static int ufshcd_query_flag_retry(struct ufs_hba *hba,
- enum query_opcode opcode, enum flag_idn idn, bool *flag_res)
+ enum query_opcode opcode, enum flag_idn idn, u8 index, bool *flag_res)
{
int ret;
int retries;
for (retries = 0; retries < QUERY_REQ_RETRIES; retries++) {
- ret = ufshcd_query_flag(hba, opcode, idn, flag_res);
+ ret = ufshcd_query_flag(hba, opcode, idn, index, flag_res);
if (ret)
dev_dbg(hba->dev,
"%s: failed with error %d, retries %d\n",
@@ -2730,16 +2875,17 @@
* @hba: per-adapter instance
* @opcode: flag query to perform
* @idn: flag idn to access
+ * @index: flag index to access
* @flag_res: the flag value after the query request completes
*
* Returns 0 for success, non-zero in case of failure
*/
int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
- enum flag_idn idn, bool *flag_res)
+ enum flag_idn idn, u8 index, bool *flag_res)
{
struct ufs_query_req *request = NULL;
struct ufs_query_res *response = NULL;
- int err, index = 0, selector = 0;
+ int err, selector = 0;
int timeout = QUERY_REQ_TIMEOUT;
BUG_ON(!hba);
@@ -2876,7 +3022,7 @@
int ret = 0;
u32 retries;
- for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
+ for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
ret = ufshcd_query_attr(hba, opcode, idn, index,
selector, attr_val);
if (ret)
@@ -2991,94 +3137,36 @@
}
/**
- * ufshcd_read_desc_length - read the specified descriptor length from header
- * @hba: Pointer to adapter instance
- * @desc_id: descriptor idn value
- * @desc_index: descriptor index
- * @desc_length: pointer to variable to read the length of descriptor
- *
- * Return 0 in case of success, non-zero otherwise
- */
-static int ufshcd_read_desc_length(struct ufs_hba *hba,
- enum desc_idn desc_id,
- int desc_index,
- int *desc_length)
-{
- int ret;
- u8 header[QUERY_DESC_HDR_SIZE];
- int header_len = QUERY_DESC_HDR_SIZE;
-
- if (desc_id >= QUERY_DESC_IDN_MAX)
- return -EINVAL;
-
- ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC,
- desc_id, desc_index, 0, header,
- &header_len);
-
- if (ret) {
- dev_err(hba->dev, "%s: Failed to get descriptor header id %d",
- __func__, desc_id);
- return ret;
- } else if (desc_id != header[QUERY_DESC_DESC_TYPE_OFFSET]) {
- dev_warn(hba->dev, "%s: descriptor header id %d and desc_id %d mismatch",
- __func__, header[QUERY_DESC_DESC_TYPE_OFFSET],
- desc_id);
- ret = -EINVAL;
- }
-
- *desc_length = header[QUERY_DESC_LENGTH_OFFSET];
- return ret;
-
-}
-
-/**
* ufshcd_map_desc_id_to_length - map descriptor IDN to its length
* @hba: Pointer to adapter instance
* @desc_id: descriptor idn value
* @desc_len: mapped desc length (out)
- *
- * Return 0 in case of success, non-zero otherwise
*/
-int ufshcd_map_desc_id_to_length(struct ufs_hba *hba,
- enum desc_idn desc_id, int *desc_len)
+void ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id,
+ int *desc_len)
{
- switch (desc_id) {
- case QUERY_DESC_IDN_DEVICE:
- *desc_len = hba->desc_size.dev_desc;
- break;
- case QUERY_DESC_IDN_POWER:
- *desc_len = hba->desc_size.pwr_desc;
- break;
- case QUERY_DESC_IDN_GEOMETRY:
- *desc_len = hba->desc_size.geom_desc;
- break;
- case QUERY_DESC_IDN_CONFIGURATION:
- *desc_len = hba->desc_size.conf_desc;
- break;
- case QUERY_DESC_IDN_UNIT:
- *desc_len = hba->desc_size.unit_desc;
- break;
- case QUERY_DESC_IDN_INTERCONNECT:
- *desc_len = hba->desc_size.interc_desc;
- break;
- case QUERY_DESC_IDN_STRING:
- *desc_len = QUERY_DESC_MAX_SIZE;
- break;
- case QUERY_DESC_IDN_HEALTH:
- *desc_len = hba->desc_size.hlth_desc;
- break;
- case QUERY_DESC_IDN_RFU_0:
- case QUERY_DESC_IDN_RFU_1:
+ if (desc_id >= QUERY_DESC_IDN_MAX || desc_id == QUERY_DESC_IDN_RFU_0 ||
+ desc_id == QUERY_DESC_IDN_RFU_1)
*desc_len = 0;
- break;
- default:
- *desc_len = 0;
- return -EINVAL;
- }
- return 0;
+ else
+ *desc_len = hba->desc_size[desc_id];
}
EXPORT_SYMBOL(ufshcd_map_desc_id_to_length);
+static void ufshcd_update_desc_length(struct ufs_hba *hba,
+ enum desc_idn desc_id, int desc_index,
+ unsigned char desc_len)
+{
+ if (hba->desc_size[desc_id] == QUERY_DESC_MAX_SIZE &&
+ desc_id != QUERY_DESC_IDN_STRING && desc_index != UFS_RPMB_UNIT)
+ /* For UFS 3.1, the normal unit descriptor is 10 bytes larger
+ * than the RPMB unit, however, both descriptors share the same
+ * desc_idn, to cover both unit descriptors with one length, we
+ * choose the normal unit descriptor length by desc_index.
+ */
+ hba->desc_size[desc_id] = desc_len;
+}
+
/**
* ufshcd_read_desc_param - read the specified descriptor parameter
* @hba: Pointer to adapter instance
@@ -3106,21 +3194,22 @@
if (desc_id >= QUERY_DESC_IDN_MAX || !param_size)
return -EINVAL;
- /* Get the max length of descriptor from structure filled up at probe
- * time.
- */
- ret = ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len);
+ /* Get the length of descriptor */
+ ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len);
+ if (!buff_len) {
+ dev_err(hba->dev, "%s: Failed to get desc length\n", __func__);
+ return -EINVAL;
+ }
- /* Sanity checks */
- if (ret || !buff_len) {
- dev_err(hba->dev, "%s: Failed to get full descriptor length",
- __func__);
- return ret;
+ if (param_offset >= buff_len) {
+ dev_err(hba->dev, "%s: Invalid offset 0x%x in descriptor IDN 0x%x, length 0x%x\n",
+ __func__, param_offset, desc_id, buff_len);
+ return -EINVAL;
}
/* Check whether we need temp memory */
if (param_offset != 0 || param_size < buff_len) {
- desc_buf = kmalloc(buff_len, GFP_KERNEL);
+ desc_buf = kzalloc(buff_len, GFP_KERNEL);
if (!desc_buf)
return -ENOMEM;
} else {
@@ -3134,52 +3223,37 @@
desc_buf, &buff_len);
if (ret) {
- dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d",
+ dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d\n",
__func__, desc_id, desc_index, param_offset, ret);
goto out;
}
/* Sanity check */
if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id) {
- dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header",
+ dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header\n",
__func__, desc_buf[QUERY_DESC_DESC_TYPE_OFFSET]);
ret = -EINVAL;
goto out;
}
- /* Check wherher we will not copy more data, than available */
- if (is_kmalloc && param_size > buff_len)
- param_size = buff_len;
+ /* Update descriptor length */
+ buff_len = desc_buf[QUERY_DESC_LENGTH_OFFSET];
+ ufshcd_update_desc_length(hba, desc_id, desc_index, buff_len);
- if (is_kmalloc)
- memcpy(param_read_buf, &desc_buf[param_offset], param_size);
+ if (is_kmalloc) {
+ /* Make sure we don't copy more data than available */
+ if (param_offset >= buff_len)
+ ret = -EINVAL;
+ else
+ memcpy(param_read_buf, &desc_buf[param_offset],
+ min_t(u32, param_size, buff_len - param_offset));
+ }
out:
if (is_kmalloc)
kfree(desc_buf);
return ret;
}
-static inline int ufshcd_read_desc(struct ufs_hba *hba,
- enum desc_idn desc_id,
- int desc_index,
- void *buf,
- u32 size)
-{
- return ufshcd_read_desc_param(hba, desc_id, desc_index, 0, buf, size);
-}
-
-static inline int ufshcd_read_power_desc(struct ufs_hba *hba,
- u8 *buf,
- u32 size)
-{
- return ufshcd_read_desc(hba, QUERY_DESC_IDN_POWER, 0, buf, size);
-}
-
-static int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size)
-{
- return ufshcd_read_desc(hba, QUERY_DESC_IDN_DEVICE, 0, buf, size);
-}
-
/**
* struct uc_string_id - unicode string
*
@@ -3190,7 +3264,7 @@
struct uc_string_id {
u8 len;
u8 type;
- wchar_t uc[0];
+ wchar_t uc[];
} __packed;
/* replace non-printable or non-ASCII characters with spaces */
@@ -3227,9 +3301,8 @@
if (!uc_str)
return -ENOMEM;
- ret = ufshcd_read_desc(hba, QUERY_DESC_IDN_STRING,
- desc_index, uc_str,
- QUERY_DESC_MAX_SIZE);
+ ret = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_STRING, desc_index, 0,
+ (u8 *)uc_str, QUERY_DESC_MAX_SIZE);
if (ret < 0) {
dev_err(hba->dev, "Reading String Desc failed after %d retries. err = %d\n",
QUERY_REQ_RETRIES, ret);
@@ -3303,13 +3376,38 @@
* Unit descriptors are only available for general purpose LUs (LUN id
* from 0 to 7) and RPMB Well known LU.
*/
- if (!ufs_is_valid_unit_desc_lun(lun))
+ if (!ufs_is_valid_unit_desc_lun(&hba->dev_info, lun, param_offset))
return -EOPNOTSUPP;
return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun,
param_offset, param_read_buf, param_size);
}
+static int ufshcd_get_ref_clk_gating_wait(struct ufs_hba *hba)
+{
+ int err = 0;
+ u32 gating_wait = UFSHCD_REF_CLK_GATING_WAIT_US;
+
+ if (hba->dev_info.wspecversion >= 0x300) {
+ err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
+ QUERY_ATTR_IDN_REF_CLK_GATING_WAIT_TIME, 0, 0,
+ &gating_wait);
+ if (err)
+ dev_err(hba->dev, "Failed reading bRefClkGatingWait. err = %d, use default %uus\n",
+ err, gating_wait);
+
+ if (gating_wait == 0) {
+ gating_wait = UFSHCD_REF_CLK_GATING_WAIT_US;
+ dev_err(hba->dev, "Undefined ref clk gating wait time, use default %uus\n",
+ gating_wait);
+ }
+
+ hba->dev_info.clk_gating_wait_us = gating_wait;
+ }
+
+ return err;
+}
+
/**
* ufshcd_memory_alloc - allocate memory for host memory space data structures
* @hba: per adapter instance
@@ -3407,7 +3505,6 @@
*/
static void ufshcd_host_memory_configure(struct ufs_hba *hba)
{
- struct utp_transfer_cmd_desc *cmd_descp;
struct utp_transfer_req_desc *utrdlp;
dma_addr_t cmd_desc_dma_addr;
dma_addr_t cmd_desc_element_addr;
@@ -3417,7 +3514,6 @@
int i;
utrdlp = hba->utrdl_base_addr;
- cmd_descp = hba->ucdl_base_addr;
response_offset =
offsetof(struct utp_transfer_cmd_desc, response_upiu);
@@ -3446,27 +3542,14 @@
cpu_to_le16(ALIGNED_UPIU_SIZE);
} else {
utrdlp[i].response_upiu_offset =
- cpu_to_le16((response_offset >> 2));
+ cpu_to_le16(response_offset >> 2);
utrdlp[i].prd_table_offset =
- cpu_to_le16((prdt_offset >> 2));
+ cpu_to_le16(prdt_offset >> 2);
utrdlp[i].response_upiu_length =
cpu_to_le16(ALIGNED_UPIU_SIZE >> 2);
}
- hba->lrb[i].utr_descriptor_ptr = (utrdlp + i);
- hba->lrb[i].utrd_dma_addr = hba->utrdl_dma_addr +
- (i * sizeof(struct utp_transfer_req_desc));
- hba->lrb[i].ucd_req_ptr =
- (struct utp_upiu_req *)(cmd_descp + i);
- hba->lrb[i].ucd_req_dma_addr = cmd_desc_element_addr;
- hba->lrb[i].ucd_rsp_ptr =
- (struct utp_upiu_rsp *)cmd_descp[i].response_upiu;
- hba->lrb[i].ucd_rsp_dma_addr = cmd_desc_element_addr +
- response_offset;
- hba->lrb[i].ucd_prdt_ptr =
- (struct ufshcd_sg_entry *)cmd_descp[i].prd_table;
- hba->lrb[i].ucd_prdt_dma_addr = cmd_desc_element_addr +
- prdt_offset;
+ ufshcd_init_lrb(hba, &hba->lrb[i], i);
}
}
@@ -3499,7 +3582,7 @@
* @hba: per adapter instance
*
* DME_RESET command is issued in order to reset UniPro stack.
- * This function now deal with cold reset.
+ * This function now deals with cold reset.
*
* Returns 0 on success, non-zero value on failure
*/
@@ -3720,6 +3803,10 @@
ufshcd_add_delay_before_dme_cmd(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
+ if (ufshcd_is_link_broken(hba)) {
+ ret = -ENOLINK;
+ goto out_unlock;
+ }
hba->uic_async_done = &uic_async_done;
if (ufshcd_readl(hba, REG_INTERRUPT_ENABLE) & UIC_COMMAND_COMPL) {
ufshcd_disable_intr(hba, UIC_COMMAND_COMPL);
@@ -3744,10 +3831,18 @@
dev_err(hba->dev,
"pwr ctrl cmd 0x%x with mode 0x%x completion timeout\n",
cmd->command, cmd->argument3);
+
+ if (!cmd->cmd_active) {
+ dev_err(hba->dev, "%s: Power Mode Change operation has been completed, go check UPMCRS\n",
+ __func__);
+ goto check_upmcrs;
+ }
+
ret = -ETIMEDOUT;
goto out;
}
+check_upmcrs:
status = ufshcd_get_upmcrs(hba);
if (status != PWR_LOCAL) {
dev_err(hba->dev,
@@ -3767,6 +3862,11 @@
hba->uic_async_done = NULL;
if (reenable_intr)
ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
+ if (ret) {
+ ufshcd_set_link_broken(hba);
+ ufshcd_schedule_eh_work(hba);
+ }
+out_unlock:
spin_unlock_irqrestore(hba->host->host_lock, flags);
mutex_unlock(&hba->uic_cmd_mutex);
@@ -3807,7 +3907,7 @@
return ret;
}
-static int ufshcd_link_recovery(struct ufs_hba *hba)
+int ufshcd_link_recovery(struct ufs_hba *hba)
{
int ret;
unsigned long flags;
@@ -3817,6 +3917,9 @@
ufshcd_set_eh_in_progress(hba);
spin_unlock_irqrestore(hba->host->host_lock, flags);
+ /* Reset the attached device */
+ ufshcd_vops_device_reset(hba);
+
ret = ufshcd_host_reset_and_restore(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
@@ -3831,8 +3934,9 @@
return ret;
}
+EXPORT_SYMBOL_GPL(ufshcd_link_recovery);
-static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
+static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
{
int ret;
struct uic_command uic_cmd = {0};
@@ -3845,46 +3949,17 @@
trace_ufshcd_profile_hibern8(dev_name(hba->dev), "enter",
ktime_to_us(ktime_sub(ktime_get(), start)), ret);
- if (ret) {
- int err;
-
+ if (ret)
dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d\n",
__func__, ret);
-
- /*
- * If link recovery fails then return error code returned from
- * ufshcd_link_recovery().
- * If link recovery succeeds then return -EAGAIN to attempt
- * hibern8 enter retry again.
- */
- err = ufshcd_link_recovery(hba);
- if (err) {
- dev_err(hba->dev, "%s: link recovery failed", __func__);
- ret = err;
- } else {
- ret = -EAGAIN;
- }
- } else
+ else
ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_ENTER,
POST_CHANGE);
return ret;
}
-static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
-{
- int ret = 0, retries;
-
- for (retries = UIC_HIBERN8_ENTER_RETRIES; retries > 0; retries--) {
- ret = __ufshcd_uic_hibern8_enter(hba);
- if (!ret)
- goto out;
- }
-out:
- return ret;
-}
-
-static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
+int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
{
struct uic_command uic_cmd = {0};
int ret;
@@ -3900,7 +3975,6 @@
if (ret) {
dev_err(hba->dev, "%s: hibern8 exit failed. ret = %d\n",
__func__, ret);
- ret = ufshcd_link_recovery(hba);
} else {
ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_EXIT,
POST_CHANGE);
@@ -3910,12 +3984,38 @@
return ret;
}
+EXPORT_SYMBOL_GPL(ufshcd_uic_hibern8_exit);
+
+void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit)
+{
+ unsigned long flags;
+ bool update = false;
+
+ if (!ufshcd_is_auto_hibern8_supported(hba))
+ return;
+
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ if (hba->ahit != ahit) {
+ hba->ahit = ahit;
+ update = true;
+ }
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+ if (update && !pm_runtime_suspended(hba->dev)) {
+ pm_runtime_get_sync(hba->dev);
+ ufshcd_hold(hba, false);
+ ufshcd_auto_hibern8_enable(hba);
+ ufshcd_release(hba);
+ pm_runtime_put(hba->dev);
+ }
+}
+EXPORT_SYMBOL_GPL(ufshcd_auto_hibern8_update);
void ufshcd_auto_hibern8_enable(struct ufs_hba *hba)
{
unsigned long flags;
- if (!ufshcd_is_auto_hibern8_supported(hba) || !hba->ahit)
+ if (!ufshcd_is_auto_hibern8_supported(hba))
return;
spin_lock_irqsave(hba->host->host_lock, flags);
@@ -4008,7 +4108,8 @@
int ret;
/* if already configured to the requested pwr_mode */
- if (pwr_mode->gear_rx == hba->pwr_info.gear_rx &&
+ if (!hba->force_pmc &&
+ pwr_mode->gear_rx == hba->pwr_info.gear_rx &&
pwr_mode->gear_tx == hba->pwr_info.gear_tx &&
pwr_mode->lane_rx == hba->pwr_info.lane_rx &&
pwr_mode->lane_tx == hba->pwr_info.lane_tx &&
@@ -4050,6 +4151,28 @@
ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HSSERIES),
pwr_mode->hs_rate);
+ if (!(hba->quirks & UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING)) {
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA0),
+ DL_FC0ProtectionTimeOutVal_Default);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA1),
+ DL_TC0ReplayTimeOutVal_Default);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA2),
+ DL_AFC0ReqTimeOutVal_Default);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA3),
+ DL_FC1ProtectionTimeOutVal_Default);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA4),
+ DL_TC1ReplayTimeOutVal_Default);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA5),
+ DL_AFC1ReqTimeOutVal_Default);
+
+ ufshcd_dme_set(hba, UIC_ARG_MIB(DME_LocalFC0ProtectionTimeOutVal),
+ DL_FC0ProtectionTimeOutVal_Default);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(DME_LocalTC0ReplayTimeOutVal),
+ DL_TC0ReplayTimeOutVal_Default);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(DME_LocalAFC0ReqTimeOutVal),
+ DL_AFC0ReqTimeOutVal_Default);
+ }
+
ret = ufshcd_uic_change_pwr_mode(hba, pwr_mode->pwr_rx << 4
| pwr_mode->pwr_tx);
@@ -4085,8 +4208,6 @@
memcpy(&final_params, desired_pwr_mode, sizeof(final_params));
ret = ufshcd_change_power_mode(hba, &final_params);
- if (!ret)
- ufshcd_print_pwr_info(hba);
return ret;
}
@@ -4100,12 +4221,12 @@
*/
static int ufshcd_complete_dev_init(struct ufs_hba *hba)
{
- int i;
int err;
- bool flag_res = 1;
+ bool flag_res = true;
+ ktime_t timeout;
err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
- QUERY_FLAG_IDN_FDEVICEINIT, NULL);
+ QUERY_FLAG_IDN_FDEVICEINIT, 0, NULL);
if (err) {
dev_err(hba->dev,
"%s setting fDeviceInit flag failed with error %d\n",
@@ -4113,20 +4234,26 @@
goto out;
}
- /* poll for max. 1000 iterations for fDeviceInit flag to clear */
- for (i = 0; i < 1000 && !err && flag_res; i++)
- err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
- QUERY_FLAG_IDN_FDEVICEINIT, &flag_res);
+ /* Poll fDeviceInit flag to be cleared */
+ timeout = ktime_add_ms(ktime_get(), FDEVICEINIT_COMPL_TIMEOUT);
+ do {
+ err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,
+ QUERY_FLAG_IDN_FDEVICEINIT, 0, &flag_res);
+ if (!flag_res)
+ break;
+ usleep_range(5000, 10000);
+ } while (ktime_before(ktime_get(), timeout));
- if (err)
+ if (err) {
dev_err(hba->dev,
- "%s reading fDeviceInit flag failed with error %d\n",
- __func__, err);
- else if (flag_res)
+ "%s reading fDeviceInit flag failed with error %d\n",
+ __func__, err);
+ } else if (flag_res) {
dev_err(hba->dev,
- "%s fDeviceInit was not cleared by the device\n",
- __func__);
-
+ "%s fDeviceInit was not cleared by the device\n",
+ __func__);
+ err = -EBUSY;
+ }
out:
return err;
}
@@ -4143,7 +4270,7 @@
*
* Returns 0 on success, non-zero value on failure
*/
-static int ufshcd_make_hba_operational(struct ufs_hba *hba)
+int ufshcd_make_hba_operational(struct ufs_hba *hba)
{
int err = 0;
u32 reg;
@@ -4183,26 +4310,32 @@
dev_err(hba->dev,
"Host controller not ready to process requests");
err = -EIO;
- goto out;
}
-out:
return err;
}
+EXPORT_SYMBOL_GPL(ufshcd_make_hba_operational);
/**
* ufshcd_hba_stop - Send controller to reset state
* @hba: per adapter instance
- * @can_sleep: perform sleep or just spin
*/
-static inline void ufshcd_hba_stop(struct ufs_hba *hba, bool can_sleep)
+static inline void ufshcd_hba_stop(struct ufs_hba *hba)
{
+ unsigned long flags;
int err;
+ /*
+ * Obtain the host lock to prevent that the controller is disabled
+ * while the UFS interrupt handler is active on another CPU.
+ */
+ spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_writel(hba, CONTROLLER_DISABLE, REG_CONTROLLER_ENABLE);
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+
err = ufshcd_wait_for_register(hba, REG_CONTROLLER_ENABLE,
CONTROLLER_ENABLE, CONTROLLER_DISABLE,
- 10, 1, can_sleep);
+ 10, 1);
if (err)
dev_err(hba->dev, "%s: Controller disable failed\n", __func__);
}
@@ -4223,7 +4356,7 @@
if (!ufshcd_is_hba_active(hba))
/* change controller state to "reset state" */
- ufshcd_hba_stop(hba, true);
+ ufshcd_hba_stop(hba);
/* UniPro link is disabled at this point */
ufshcd_set_link_off(hba);
@@ -4243,10 +4376,10 @@
* instruction might be read back.
* This delay can be changed based on the controller.
*/
- usleep_range(1000, 1100);
+ ufshcd_delay_us(hba->vps->hba_enable_delay_us, 100);
/* wait for the host controller to complete initialization */
- retry = 10;
+ retry = 50;
while (ufshcd_is_hba_active(hba)) {
if (retry) {
retry--;
@@ -4255,7 +4388,7 @@
"Controller enable failed\n");
return -EIO;
}
- usleep_range(5000, 5100);
+ usleep_range(1000, 1100);
}
/* enable UIC related interrupts */
@@ -4266,7 +4399,7 @@
return 0;
}
-static int ufshcd_hba_enable(struct ufs_hba *hba)
+int ufshcd_hba_enable(struct ufs_hba *hba)
{
int ret;
@@ -4291,9 +4424,11 @@
return ret;
}
+EXPORT_SYMBOL_GPL(ufshcd_hba_enable);
+
static int ufshcd_disable_tx_lcc(struct ufs_hba *hba, bool peer)
{
- int tx_lanes, i, err = 0;
+ int tx_lanes = 0, i, err = 0;
if (!peer)
ufshcd_dme_get(hba, UIC_ARG_MIB(PA_CONNECTEDTXDATALANES),
@@ -4327,13 +4462,14 @@
return ufshcd_disable_tx_lcc(hba, true);
}
-static void ufshcd_update_reg_hist(struct ufs_err_reg_hist *reg_hist,
- u32 reg)
+void ufshcd_update_reg_hist(struct ufs_err_reg_hist *reg_hist,
+ u32 reg)
{
reg_hist->reg[reg_hist->pos] = reg;
reg_hist->tstamp[reg_hist->pos] = ktime_get();
reg_hist->pos = (reg_hist->pos + 1) % UFS_ERR_REG_HIST_LENGTH;
}
+EXPORT_SYMBOL_GPL(ufshcd_update_reg_hist);
/**
* ufshcd_link_startup - Initialize unipro link startup
@@ -4409,6 +4545,8 @@
if (ret)
goto out;
+ /* Clear UECPA once due to LINERESET has happened during LINK_STARTUP */
+ ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
ret = ufshcd_make_hba_operational(hba);
out:
if (ret) {
@@ -4516,7 +4654,7 @@
* protected so skip reading bLUWriteProtect parameter for
* it. For other W-LUs, UNIT DESCRIPTOR is not available.
*/
- else if (lun >= UFS_UPIU_MAX_GENERAL_LUN)
+ else if (lun >= hba->dev_info.max_lu_supported)
ret = -ENOTSUPP;
else
ret = ufshcd_read_unit_desc_param(hba,
@@ -4563,6 +4701,9 @@
/* Mode sense(6) is not supported by UFS, so use Mode sense(10) */
sdev->use_10_for_ms = 1;
+ /* DBD field should be set to 1 in mode sense(10) */
+ sdev->set_dbd_for_ms = 1;
+
/* allow SCSI layer to restart the device in case of errors */
sdev->allow_restart = 1;
@@ -4601,9 +4742,18 @@
*/
static int ufshcd_slave_configure(struct scsi_device *sdev)
{
+ struct ufs_hba *hba = shost_priv(sdev->host);
struct request_queue *q = sdev->request_queue;
blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1);
+ if (hba->quirks & UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE)
+ blk_queue_update_dma_alignment(q, PAGE_SIZE - 1);
+
+ if (ufshcd_is_rpm_autosuspend_allowed(hba))
+ sdev->rpm_autosuspend = 1;
+
+ ufshcd_crypto_setup_rq_keyslot_manager(hba, q);
+
return 0;
}
@@ -4641,7 +4791,7 @@
switch (scsi_status) {
case SAM_STAT_CHECK_CONDITION:
ufshcd_copy_sense_data(lrbp);
- /* fallthrough */
+ fallthrough;
case SAM_STAT_GOOD:
result |= DID_OK << 16 |
COMMAND_COMPLETE << 8 |
@@ -4678,6 +4828,12 @@
/* overall command status of utrd */
ocs = ufshcd_get_tr_ocs(lrbp);
+ if (hba->quirks & UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR) {
+ if (be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_1) &
+ MASK_RSP_UPIU_RESULT)
+ ocs = OCS_SUCCESS;
+ }
+
switch (ocs) {
case OCS_SUCCESS:
result = ufshcd_get_req_rsp(lrbp->ucd_rsp_ptr);
@@ -4710,8 +4866,15 @@
* UFS device needs urgent BKOPs.
*/
if (!hba->pm_op_in_progress &&
- ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
- schedule_work(&hba->eeh_work);
+ ufshcd_is_exception_event(lrbp->ucd_rsp_ptr) &&
+ schedule_work(&hba->eeh_work)) {
+ /*
+ * Prevent suspend once eeh_work is scheduled
+ * to avoid deadlock between ufshcd_suspend
+ * and exception event handler.
+ */
+ pm_runtime_get_noresume(hba->dev);
+ }
break;
case UPIU_TRANSACTION_REJECT_UPIU:
/* TODO: handle Reject UPIU Response */
@@ -4739,6 +4902,9 @@
case OCS_MISMATCH_RESP_UPIU_SIZE:
case OCS_PEER_COMM_FAILURE:
case OCS_FATAL_ERROR:
+ case OCS_DEVICE_FATAL_ERROR:
+ case OCS_INVALID_CRYPTO_CONFIG:
+ case OCS_GENERAL_CRYPTO_ERROR:
default:
result |= DID_ERROR << 16;
dev_err(hba->dev,
@@ -4749,7 +4915,8 @@
break;
} /* end of switch */
- if ((host_byte(result) != DID_OK) && !hba->silence_err_logs)
+ if ((host_byte(result) != DID_OK) &&
+ (host_byte(result) != DID_REQUEUE) && !hba->silence_err_logs)
ufshcd_print_trs(hba, 1 << lrbp->task_tag, true);
return result;
}
@@ -4772,14 +4939,21 @@
ufshcd_get_uic_cmd_result(hba);
hba->active_uic_cmd->argument3 =
ufshcd_get_dme_attr_val(hba);
+ if (!hba->uic_async_done)
+ hba->active_uic_cmd->cmd_active = 0;
complete(&hba->active_uic_cmd->done);
retval = IRQ_HANDLED;
}
if ((intr_status & UFSHCD_UIC_PWR_MASK) && hba->uic_async_done) {
+ hba->active_uic_cmd->cmd_active = 0;
complete(hba->uic_async_done);
retval = IRQ_HANDLED;
}
+
+ if (retval == IRQ_HANDLED)
+ ufshcd_add_uic_command_trace(hba, hba->active_uic_cmd,
+ "complete");
return retval;
}
@@ -4798,6 +4972,7 @@
for_each_set_bit(index, &completed_reqs, hba->nutrs) {
lrbp = &hba->lrb[index];
+ lrbp->compl_time_stamp = ktime_get();
cmd = lrbp->cmd;
if (cmd) {
ufshcd_add_command_trace(hba, index, "complete");
@@ -4819,8 +4994,6 @@
}
if (ufshcd_is_clkscaling_supported(hba))
hba->clk_scaling.active_reqs--;
-
- lrbp->compl_time_stamp = ktime_get();
}
/* clear corresponding bits of completed commands */
@@ -4939,7 +5112,7 @@
goto out;
err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
- QUERY_FLAG_IDN_BKOPS_EN, NULL);
+ QUERY_FLAG_IDN_BKOPS_EN, 0, NULL);
if (err) {
dev_err(hba->dev, "%s: failed to enable bkops %d\n",
__func__, err);
@@ -4989,7 +5162,7 @@
}
err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG,
- QUERY_FLAG_IDN_BKOPS_EN, NULL);
+ QUERY_FLAG_IDN_BKOPS_EN, 0, NULL);
if (err) {
dev_err(hba->dev, "%s: failed to disable bkops %d\n",
__func__, err);
@@ -5024,6 +5197,7 @@
hba->ee_ctrl_mask &= ~MASK_EE_URGENT_BKOPS;
ufshcd_disable_auto_bkops(hba);
}
+ hba->urgent_bkops_lvl = BKOPS_STATUS_PERF_IMPACT;
hba->is_urgent_bkops_lvl_checked = false;
}
@@ -5133,6 +5307,190 @@
__func__, err);
}
+static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable)
+{
+ int ret;
+ u8 index;
+ enum query_opcode opcode;
+
+ if (!ufshcd_is_wb_allowed(hba))
+ return 0;
+
+ if (!(enable ^ hba->wb_enabled))
+ return 0;
+ if (enable)
+ opcode = UPIU_QUERY_OPCODE_SET_FLAG;
+ else
+ opcode = UPIU_QUERY_OPCODE_CLEAR_FLAG;
+
+ index = ufshcd_wb_get_query_index(hba);
+ ret = ufshcd_query_flag_retry(hba, opcode,
+ QUERY_FLAG_IDN_WB_EN, index, NULL);
+ if (ret) {
+ dev_err(hba->dev, "%s write booster %s failed %d\n",
+ __func__, enable ? "enable" : "disable", ret);
+ return ret;
+ }
+
+ hba->wb_enabled = enable;
+ dev_dbg(hba->dev, "%s write booster %s %d\n",
+ __func__, enable ? "enable" : "disable", ret);
+
+ return ret;
+}
+
+static int ufshcd_wb_toggle_flush_during_h8(struct ufs_hba *hba, bool set)
+{
+ int val;
+ u8 index;
+
+ if (set)
+ val = UPIU_QUERY_OPCODE_SET_FLAG;
+ else
+ val = UPIU_QUERY_OPCODE_CLEAR_FLAG;
+
+ index = ufshcd_wb_get_query_index(hba);
+ return ufshcd_query_flag_retry(hba, val,
+ QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8,
+ index, NULL);
+}
+
+static inline void ufshcd_wb_toggle_flush(struct ufs_hba *hba, bool enable)
+{
+ if (enable)
+ ufshcd_wb_buf_flush_enable(hba);
+ else
+ ufshcd_wb_buf_flush_disable(hba);
+
+}
+
+static int ufshcd_wb_buf_flush_enable(struct ufs_hba *hba)
+{
+ int ret;
+ u8 index;
+
+ if (!ufshcd_is_wb_allowed(hba) || hba->wb_buf_flush_enabled)
+ return 0;
+
+ index = ufshcd_wb_get_query_index(hba);
+ ret = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
+ QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN,
+ index, NULL);
+ if (ret)
+ dev_err(hba->dev, "%s WB - buf flush enable failed %d\n",
+ __func__, ret);
+ else
+ hba->wb_buf_flush_enabled = true;
+
+ dev_dbg(hba->dev, "WB - Flush enabled: %d\n", ret);
+ return ret;
+}
+
+static int ufshcd_wb_buf_flush_disable(struct ufs_hba *hba)
+{
+ int ret;
+ u8 index;
+
+ if (!ufshcd_is_wb_allowed(hba) || !hba->wb_buf_flush_enabled)
+ return 0;
+
+ index = ufshcd_wb_get_query_index(hba);
+ ret = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG,
+ QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN,
+ index, NULL);
+ if (ret) {
+ dev_warn(hba->dev, "%s: WB - buf flush disable failed %d\n",
+ __func__, ret);
+ } else {
+ hba->wb_buf_flush_enabled = false;
+ dev_dbg(hba->dev, "WB - Flush disabled: %d\n", ret);
+ }
+
+ return ret;
+}
+
+static bool ufshcd_wb_presrv_usrspc_keep_vcc_on(struct ufs_hba *hba,
+ u32 avail_buf)
+{
+ u32 cur_buf;
+ int ret;
+ u8 index;
+
+ index = ufshcd_wb_get_query_index(hba);
+ ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
+ QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE,
+ index, 0, &cur_buf);
+ if (ret) {
+ dev_err(hba->dev, "%s dCurWriteBoosterBufferSize read failed %d\n",
+ __func__, ret);
+ return false;
+ }
+
+ if (!cur_buf) {
+ dev_info(hba->dev, "dCurWBBuf: %d WB disabled until free-space is available\n",
+ cur_buf);
+ return false;
+ }
+ /* Let it continue to flush when available buffer exceeds threshold */
+ if (avail_buf < hba->vps->wb_flush_threshold)
+ return true;
+
+ return false;
+}
+
+static bool ufshcd_wb_need_flush(struct ufs_hba *hba)
+{
+ int ret;
+ u32 avail_buf;
+ u8 index;
+
+ if (!ufshcd_is_wb_allowed(hba))
+ return false;
+ /*
+ * The ufs device needs the vcc to be ON to flush.
+ * With user-space reduction enabled, it's enough to enable flush
+ * by checking only the available buffer. The threshold
+ * defined here is > 90% full.
+ * With user-space preserved enabled, the current-buffer
+ * should be checked too because the wb buffer size can reduce
+ * when disk tends to be full. This info is provided by current
+ * buffer (dCurrentWriteBoosterBufferSize). There's no point in
+ * keeping vcc on when current buffer is empty.
+ */
+ index = ufshcd_wb_get_query_index(hba);
+ ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
+ QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE,
+ index, 0, &avail_buf);
+ if (ret) {
+ dev_warn(hba->dev, "%s dAvailableWriteBoosterBufferSize read failed %d\n",
+ __func__, ret);
+ return false;
+ }
+
+ if (!hba->dev_info.b_presrv_uspc_en) {
+ if (avail_buf <= UFS_WB_BUF_REMAIN_PERCENT(10))
+ return true;
+ return false;
+ }
+
+ return ufshcd_wb_presrv_usrspc_keep_vcc_on(hba, avail_buf);
+}
+
+static void ufshcd_rpm_dev_flush_recheck_work(struct work_struct *work)
+{
+ struct ufs_hba *hba = container_of(to_delayed_work(work),
+ struct ufs_hba,
+ rpm_dev_flush_recheck_work);
+ /*
+ * To prevent unnecessary VCC power drain after device finishes
+ * WriteBooster buffer flush or Auto BKOPs, force runtime resume
+ * after a certain delay to recheck the threshold by next runtime
+ * suspend.
+ */
+ pm_runtime_get_sync(hba->dev);
+ pm_runtime_put_sync(hba->dev);
+}
+
/**
* ufshcd_exception_event_handler - handle exceptions raised by device
* @work: pointer to work data
@@ -5148,7 +5506,7 @@
hba = container_of(work, struct ufs_hba, eeh_work);
pm_runtime_get_sync(hba->dev);
- scsi_block_requests(hba->host);
+ ufshcd_scsi_block_requests(hba);
err = ufshcd_get_ee_status(hba, &status);
if (err) {
dev_err(hba->dev, "%s: failed to get exception status %d\n",
@@ -5162,8 +5520,15 @@
ufshcd_bkops_exception_event_handler(hba);
out:
- scsi_unblock_requests(hba->host);
- pm_runtime_put_sync(hba->dev);
+ ufshcd_scsi_unblock_requests(hba);
+ /*
+ * pm_runtime_get_noresume is called while scheduling
+ * eeh_work to avoid suspend racing with exception work.
+ * Hence decrement usage counter using pm_runtime_put_noidle
+ * to allow suspend on completion of exception event handler.
+ */
+ pm_runtime_put_noidle(hba->dev);
+ pm_runtime_put(hba->dev);
return;
}
@@ -5237,16 +5602,129 @@
hba->saved_err &= ~UIC_ERROR;
/* clear NAC error */
hba->saved_uic_err &= ~UFSHCD_UIC_DL_NAC_RECEIVED_ERROR;
- if (!hba->saved_uic_err) {
+ if (!hba->saved_uic_err)
err_handling = false;
- goto out;
- }
}
out:
spin_unlock_irqrestore(hba->host->host_lock, flags);
return err_handling;
}
+/* host lock must be held before calling this func */
+static inline bool ufshcd_is_saved_err_fatal(struct ufs_hba *hba)
+{
+ return (hba->saved_uic_err & UFSHCD_UIC_DL_PA_INIT_ERROR) ||
+ (hba->saved_err & (INT_FATAL_ERRORS | UFSHCD_UIC_HIBERN8_MASK));
+}
+
+/* host lock must be held before calling this func */
+static inline void ufshcd_schedule_eh_work(struct ufs_hba *hba)
+{
+ /* handle fatal errors only when link is not in error state */
+ if (hba->ufshcd_state != UFSHCD_STATE_ERROR) {
+ if (hba->force_reset || ufshcd_is_link_broken(hba) ||
+ ufshcd_is_saved_err_fatal(hba))
+ hba->ufshcd_state = UFSHCD_STATE_EH_SCHEDULED_FATAL;
+ else
+ hba->ufshcd_state = UFSHCD_STATE_EH_SCHEDULED_NON_FATAL;
+ queue_work(hba->eh_wq, &hba->eh_work);
+ }
+}
+
+static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
+{
+ pm_runtime_get_sync(hba->dev);
+ if (pm_runtime_suspended(hba->dev)) {
+ /*
+ * Don't assume anything of pm_runtime_get_sync(), if
+ * resume fails, irq and clocks can be OFF, and powers
+ * can be OFF or in LPM.
+ */
+ ufshcd_setup_hba_vreg(hba, true);
+ ufshcd_enable_irq(hba);
+ ufshcd_setup_vreg(hba, true);
+ ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq);
+ ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq2);
+ ufshcd_hold(hba, false);
+ if (!ufshcd_is_clkgating_allowed(hba))
+ ufshcd_setup_clocks(hba, true);
+ ufshcd_release(hba);
+ ufshcd_vops_resume(hba, UFS_RUNTIME_PM);
+ } else {
+ ufshcd_hold(hba, false);
+ if (hba->clk_scaling.is_allowed) {
+ cancel_work_sync(&hba->clk_scaling.suspend_work);
+ cancel_work_sync(&hba->clk_scaling.resume_work);
+ ufshcd_suspend_clkscaling(hba);
+ }
+ }
+}
+
+static void ufshcd_err_handling_unprepare(struct ufs_hba *hba)
+{
+ ufshcd_release(hba);
+ if (hba->clk_scaling.is_allowed)
+ ufshcd_resume_clkscaling(hba);
+ pm_runtime_put(hba->dev);
+}
+
+static inline bool ufshcd_err_handling_should_stop(struct ufs_hba *hba)
+{
+ return (hba->ufshcd_state == UFSHCD_STATE_ERROR ||
+ (!(hba->saved_err || hba->saved_uic_err || hba->force_reset ||
+ ufshcd_is_link_broken(hba))));
+}
+
+#ifdef CONFIG_PM
+static void ufshcd_recover_pm_error(struct ufs_hba *hba)
+{
+ struct Scsi_Host *shost = hba->host;
+ struct scsi_device *sdev;
+ struct request_queue *q;
+ int ret;
+
+ /*
+ * Set RPM status of hba device to RPM_ACTIVE,
+ * this also clears its runtime error.
+ */
+ ret = pm_runtime_set_active(hba->dev);
+ /*
+ * If hba device had runtime error, we also need to resume those
+ * scsi devices under hba in case any of them has failed to be
+ * resumed due to hba runtime resume failure. This is to unblock
+ * blk_queue_enter in case there are bios waiting inside it.
+ */
+ if (!ret) {
+ shost_for_each_device(sdev, shost) {
+ q = sdev->request_queue;
+ if (q->dev && (q->rpm_status == RPM_SUSPENDED ||
+ q->rpm_status == RPM_SUSPENDING))
+ pm_request_resume(q->dev);
+ }
+ }
+}
+#else
+static inline void ufshcd_recover_pm_error(struct ufs_hba *hba)
+{
+}
+#endif
+
+static bool ufshcd_is_pwr_mode_restore_needed(struct ufs_hba *hba)
+{
+ struct ufs_pa_layer_attr *pwr_info = &hba->pwr_info;
+ u32 mode;
+
+ ufshcd_dme_get(hba, UIC_ARG_MIB(PA_PWRMODE), &mode);
+
+ if (pwr_info->pwr_rx != ((mode >> PWRMODE_RX_OFFSET) & PWRMODE_MASK))
+ return true;
+
+ if (pwr_info->pwr_tx != (mode & PWRMODE_MASK))
+ return true;
+
+ return false;
+}
+
/**
* ufshcd_err_handler - handle UFS errors that require s/w attention
* @work: pointer to work structure
@@ -5255,23 +5733,36 @@
{
struct ufs_hba *hba;
unsigned long flags;
- u32 err_xfer = 0;
- u32 err_tm = 0;
- int err = 0;
+ bool err_xfer = false;
+ bool err_tm = false;
+ int err = 0, pmc_err;
int tag;
- bool needs_reset = false;
+ bool needs_reset = false, needs_restore = false;
hba = container_of(work, struct ufs_hba, eh_work);
- pm_runtime_get_sync(hba->dev);
- ufshcd_hold(hba, false);
-
spin_lock_irqsave(hba->host->host_lock, flags);
- if (hba->ufshcd_state == UFSHCD_STATE_RESET)
- goto out;
-
- hba->ufshcd_state = UFSHCD_STATE_RESET;
+ if (ufshcd_err_handling_should_stop(hba)) {
+ if (hba->ufshcd_state != UFSHCD_STATE_ERROR)
+ hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+ return;
+ }
ufshcd_set_eh_in_progress(hba);
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+ ufshcd_err_handling_prepare(hba);
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ ufshcd_scsi_block_requests(hba);
+ /*
+ * A full reset and restore might have happened after preparation
+ * is finished, double check whether we should stop.
+ */
+ if (ufshcd_err_handling_should_stop(hba)) {
+ if (hba->ufshcd_state != UFSHCD_STATE_ERROR)
+ hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
+ goto out;
+ }
+ hba->ufshcd_state = UFSHCD_STATE_RESET;
/* Complete requests that have door-bell cleared by h/w */
ufshcd_complete_requests(hba);
@@ -5283,30 +5774,61 @@
/* release the lock as ufshcd_quirk_dl_nac_errors() may sleep */
ret = ufshcd_quirk_dl_nac_errors(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
- if (!ret)
+ if (!ret && !hba->force_reset && ufshcd_is_link_active(hba))
goto skip_err_handling;
}
- if ((hba->saved_err & INT_FATAL_ERRORS) ||
- (hba->saved_err & UFSHCD_UIC_HIBERN8_MASK) ||
+
+ if (hba->force_reset || ufshcd_is_link_broken(hba) ||
+ ufshcd_is_saved_err_fatal(hba) ||
((hba->saved_err & UIC_ERROR) &&
- (hba->saved_uic_err & (UFSHCD_UIC_DL_PA_INIT_ERROR |
- UFSHCD_UIC_DL_NAC_RECEIVED_ERROR |
- UFSHCD_UIC_DL_TCx_REPLAY_ERROR))))
+ (hba->saved_uic_err & (UFSHCD_UIC_DL_NAC_RECEIVED_ERROR |
+ UFSHCD_UIC_DL_TCx_REPLAY_ERROR))))
needs_reset = true;
+ if ((hba->saved_err & (INT_FATAL_ERRORS | UFSHCD_UIC_HIBERN8_MASK)) ||
+ (hba->saved_uic_err &&
+ (hba->saved_uic_err != UFSHCD_UIC_PA_GENERIC_ERROR))) {
+ bool pr_prdt = !!(hba->saved_err & SYSTEM_BUS_FATAL_ERROR);
+
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+ ufshcd_print_host_state(hba);
+ ufshcd_print_pwr_info(hba);
+ ufshcd_print_host_regs(hba);
+ ufshcd_print_tmrs(hba, hba->outstanding_tasks);
+ ufshcd_print_trs(hba, hba->outstanding_reqs, pr_prdt);
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ }
+
/*
* if host reset is required then skip clearing the pending
* transfers forcefully because they will get cleared during
* host reset and restore
*/
if (needs_reset)
- goto skip_pending_xfer_clear;
+ goto do_reset;
+ /*
+ * If LINERESET was caught, UFS might have been put to PWM mode,
+ * check if power mode restore is needed.
+ */
+ if (hba->saved_uic_err & UFSHCD_UIC_PA_GENERIC_ERROR) {
+ hba->saved_uic_err &= ~UFSHCD_UIC_PA_GENERIC_ERROR;
+ if (!hba->saved_uic_err)
+ hba->saved_err &= ~UIC_ERROR;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+ if (ufshcd_is_pwr_mode_restore_needed(hba))
+ needs_restore = true;
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ if (!hba->saved_err && !needs_restore)
+ goto skip_err_handling;
+ }
+
+ hba->silence_err_logs = true;
/* release lock as clear command might sleep */
spin_unlock_irqrestore(hba->host->host_lock, flags);
/* Clear pending transfer requests */
for_each_set_bit(tag, &hba->outstanding_reqs, hba->nutrs) {
- if (ufshcd_clear_cmd(hba, tag)) {
+ if (ufshcd_try_to_abort_task(hba, tag)) {
err_xfer = true;
goto lock_skip_pending_xfer_clear;
}
@@ -5325,11 +5847,38 @@
/* Complete the requests that are cleared by s/w */
ufshcd_complete_requests(hba);
+ hba->silence_err_logs = false;
- if (err_xfer || err_tm)
+ if (err_xfer || err_tm) {
needs_reset = true;
+ goto do_reset;
+ }
-skip_pending_xfer_clear:
+ /*
+ * After all reqs and tasks are cleared from doorbell,
+ * now it is safe to retore power mode.
+ */
+ if (needs_restore) {
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+ /*
+ * Hold the scaling lock just in case dev cmds
+ * are sent via bsg and/or sysfs.
+ */
+ down_write(&hba->clk_scaling_lock);
+ hba->force_pmc = true;
+ pmc_err = ufshcd_config_pwr_mode(hba, &(hba->pwr_info));
+ if (pmc_err) {
+ needs_reset = true;
+ dev_err(hba->dev, "%s: Failed to restore power mode, err = %d\n",
+ __func__, pmc_err);
+ }
+ hba->force_pmc = false;
+ ufshcd_print_pwr_info(hba);
+ up_write(&hba->clk_scaling_lock);
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ }
+
+do_reset:
/* Fatal errors need reset */
if (needs_reset) {
unsigned long max_doorbells = (1UL << hba->nutrs) - 1;
@@ -5345,38 +5894,31 @@
__ufshcd_transfer_req_compl(hba,
(1UL << (hba->nutrs - 1)));
+ hba->force_reset = false;
spin_unlock_irqrestore(hba->host->host_lock, flags);
err = ufshcd_reset_and_restore(hba);
+ if (err)
+ dev_err(hba->dev, "%s: reset and restore failed with err %d\n",
+ __func__, err);
+ else
+ ufshcd_recover_pm_error(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
- if (err) {
- dev_err(hba->dev, "%s: reset and restore failed\n",
- __func__);
- hba->ufshcd_state = UFSHCD_STATE_ERROR;
- }
- /*
- * Inform scsi mid-layer that we did reset and allow to handle
- * Unit Attention properly.
- */
- scsi_report_bus_reset(hba->host, 0);
- hba->saved_err = 0;
- hba->saved_uic_err = 0;
}
skip_err_handling:
if (!needs_reset) {
- hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
+ if (hba->ufshcd_state == UFSHCD_STATE_RESET)
+ hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
if (hba->saved_err || hba->saved_uic_err)
dev_err_ratelimited(hba->dev, "%s: exit: saved_err 0x%x saved_uic_err 0x%x",
__func__, hba->saved_err, hba->saved_uic_err);
}
- ufshcd_clear_eh_in_progress(hba);
-
out:
+ ufshcd_clear_eh_in_progress(hba);
spin_unlock_irqrestore(hba->host->host_lock, flags);
ufshcd_scsi_unblock_requests(hba);
- ufshcd_release(hba);
- pm_runtime_put_sync(hba->dev);
+ ufshcd_err_handling_unprepare(hba);
}
/**
@@ -5392,17 +5934,33 @@
u32 reg;
irqreturn_t retval = IRQ_NONE;
- /* PHY layer lane error */
+ /* PHY layer error */
reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
- /* Ignore LINERESET indication, as this is not an error */
if ((reg & UIC_PHY_ADAPTER_LAYER_ERROR) &&
- (reg & UIC_PHY_ADAPTER_LAYER_LANE_ERR_MASK)) {
+ (reg & UIC_PHY_ADAPTER_LAYER_ERROR_CODE_MASK)) {
+ ufshcd_update_reg_hist(&hba->ufs_stats.pa_err, reg);
/*
* To know whether this error is fatal or not, DB timeout
* must be checked but this error is handled separately.
*/
- dev_dbg(hba->dev, "%s: UIC Lane error reported\n", __func__);
- ufshcd_update_reg_hist(&hba->ufs_stats.pa_err, reg);
+ if (reg & UIC_PHY_ADAPTER_LAYER_LANE_ERR_MASK)
+ dev_dbg(hba->dev, "%s: UIC Lane error reported\n",
+ __func__);
+
+ /* Got a LINERESET indication. */
+ if (reg & UIC_PHY_ADAPTER_LAYER_GENERIC_ERROR) {
+ struct uic_command *cmd = NULL;
+
+ hba->uic_error |= UFSHCD_UIC_PA_GENERIC_ERROR;
+ if (hba->uic_async_done && hba->active_uic_cmd)
+ cmd = hba->active_uic_cmd;
+ /*
+ * Ignore the LINERESET during power mode change
+ * operation via DME_SET command.
+ */
+ if (cmd && (cmd->command == UIC_CMD_DME_SET))
+ hba->uic_error &= ~UFSHCD_UIC_PA_GENERIC_ERROR;
+ }
retval |= IRQ_HANDLED;
}
@@ -5506,6 +6064,7 @@
hba->errors, ufshcd_get_upmcrs(hba));
ufshcd_update_reg_hist(&hba->ufs_stats.auto_hibern8_err,
hba->errors);
+ ufshcd_set_link_broken(hba);
queue_eh_work = true;
}
@@ -5517,30 +6076,18 @@
hba->saved_err |= hba->errors;
hba->saved_uic_err |= hba->uic_error;
- /* handle fatal errors only when link is functional */
- if (hba->ufshcd_state == UFSHCD_STATE_OPERATIONAL) {
- /* block commands from scsi mid-layer */
- ufshcd_scsi_block_requests(hba);
-
- hba->ufshcd_state = UFSHCD_STATE_EH_SCHEDULED;
-
- /* dump controller state before resetting */
- if (hba->saved_err & (INT_FATAL_ERRORS | UIC_ERROR)) {
- bool pr_prdt = !!(hba->saved_err &
- SYSTEM_BUS_FATAL_ERROR);
-
- dev_err(hba->dev, "%s: saved_err 0x%x saved_uic_err 0x%x\n",
+ /* dump controller state before resetting */
+ if ((hba->saved_err & (INT_FATAL_ERRORS)) ||
+ (hba->saved_uic_err &&
+ (hba->saved_uic_err != UFSHCD_UIC_PA_GENERIC_ERROR))) {
+ dev_err(hba->dev, "%s: saved_err 0x%x saved_uic_err 0x%x\n",
__func__, hba->saved_err,
hba->saved_uic_err);
-
- ufshcd_print_host_regs(hba);
- ufshcd_print_pwr_info(hba);
- ufshcd_print_tmrs(hba, hba->outstanding_tasks);
- ufshcd_print_trs(hba, hba->outstanding_reqs,
- pr_prdt);
- }
- schedule_work(&hba->eh_work);
+ ufshcd_dump_regs(hba, 0, UFSHCI_REG_SPACE_SIZE,
+ "host_regs: ");
+ ufshcd_print_pwr_info(hba);
}
+ ufshcd_schedule_eh_work(hba);
retval |= IRQ_HANDLED;
}
/*
@@ -5552,27 +6099,6 @@
return retval;
}
-struct ctm_info {
- struct ufs_hba *hba;
- unsigned long pending;
- unsigned int ncpl;
-};
-
-static bool ufshcd_compl_tm(struct request *req, void *priv, bool reserved)
-{
- struct ctm_info *const ci = priv;
- struct completion *c;
-
- WARN_ON_ONCE(reserved);
- if (test_bit(req->tag, &ci->pending))
- return true;
- ci->ncpl++;
- c = req->end_io_data;
- if (c)
- complete(c);
- return true;
-}
-
/**
* ufshcd_tmc_handler - handle task management function completion
* @hba: per adapter instance
@@ -5583,14 +6109,22 @@
*/
static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba)
{
- struct request_queue *q = hba->tmf_queue;
- struct ctm_info ci = {
- .hba = hba,
- .pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL),
- };
+ unsigned long pending, issued;
+ irqreturn_t ret = IRQ_NONE;
+ int tag;
- blk_mq_tagset_busy_iter(q->tag_set, ufshcd_compl_tm, &ci);
- return ci.ncpl ? IRQ_HANDLED : IRQ_NONE;
+ pending = ufshcd_readl(hba, REG_UTP_TASK_REQ_DOOR_BELL);
+
+ issued = hba->outstanding_tasks & ~pending;
+ for_each_set_bit(tag, &issued, hba->nutmrs) {
+ struct request *req = hba->tmf_rqs[tag];
+ struct completion *c = req->end_io_data;
+
+ complete(c);
+ ret = IRQ_HANDLED;
+ }
+
+ return ret;
}
/**
@@ -5644,6 +6178,8 @@
spin_lock(hba->host->host_lock);
intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
+ hba->ufs_stats.last_intr_status = intr_status;
+ hba->ufs_stats.last_intr_ts = ktime_get();
/*
* There could be max of hba->nutrs reqs in flight and in worst case
@@ -5662,9 +6198,13 @@
intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
}
- if (retval == IRQ_NONE) {
- dev_err(hba->dev, "%s: Unhandled interrupt 0x%08x\n",
- __func__, intr_status);
+ if (enabled_intr_status && retval == IRQ_NONE &&
+ !ufshcd_eh_in_progress(hba)) {
+ dev_err(hba->dev, "%s: Unhandled interrupt 0x%08x (0x%08x, 0x%08x)\n",
+ __func__,
+ intr_status,
+ hba->ufs_stats.last_intr_status,
+ enabled_intr_status);
ufshcd_dump_regs(hba, 0, UFSHCI_REG_SPACE_SIZE, "host_regs: ");
}
@@ -5688,7 +6228,7 @@
/* poll for max. 1 sec to clear door bell register by h/w */
err = ufshcd_wait_for_register(hba,
REG_UTP_TASK_REQ_DOOR_BELL,
- mask, 0, 1000, 1000, true);
+ mask, 0, 1000, 1000);
out:
return err;
}
@@ -5706,14 +6246,17 @@
/*
* blk_get_request() is used here only to get a free tag.
*/
- req = blk_get_request(q, REQ_OP_DRV_OUT, BLK_MQ_REQ_RESERVED);
+ req = blk_get_request(q, REQ_OP_DRV_OUT, 0);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
+
req->end_io_data = &wait;
ufshcd_hold(hba, false);
spin_lock_irqsave(host->host_lock, flags);
- blk_mq_start_request(req);
task_tag = req->tag;
+ hba->tmf_rqs[req->tag] = req;
treq->req_header.dword_0 |= cpu_to_be32(task_tag);
memcpy(hba->utmrdl_base_addr + task_tag, treq, sizeof(*treq));
@@ -5737,11 +6280,6 @@
err = wait_for_completion_io_timeout(&wait,
msecs_to_jiffies(TM_CMD_TIMEOUT));
if (!err) {
- /*
- * Make sure that ufshcd_compl_tm() does not trigger a
- * use-after-free.
- */
- req->end_io_data = NULL;
ufshcd_add_tm_upiu_trace(hba, task_tag, "tm_complete_err");
dev_err(hba->dev, "%s: task management cmd 0x%.2x timed-out\n",
__func__, tm_function);
@@ -5757,6 +6295,7 @@
}
spin_lock_irqsave(hba->host->host_lock, flags);
+ hba->tmf_rqs[req->tag] = NULL;
__clear_bit(task_tag, &hba->outstanding_tasks);
spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -5817,9 +6356,9 @@
* @hba: per-adapter instance
* @req_upiu: upiu request
* @rsp_upiu: upiu reply
- * @msgcode: message code, one of UPIU Transaction Codes Initiator to Target
* @desc_buff: pointer to descriptor buffer, NULL if NA
* @buff_len: descriptor size, 0 if NA
+ * @cmd_type: specifies the type (NOP, Query...)
* @desc_op: descriptor operation
*
* Those type of requests uses UTP Transfer Request Descriptor - utrd.
@@ -5833,7 +6372,7 @@
struct utp_upiu_req *req_upiu,
struct utp_upiu_req *rsp_upiu,
u8 *desc_buff, int *buff_len,
- int cmd_type,
+ enum dev_cmd_type cmd_type,
enum query_opcode desc_op)
{
struct request_queue *q = hba->cmd_queue;
@@ -5843,7 +6382,7 @@
int tag;
struct completion wait;
unsigned long flags;
- u32 upiu_flags;
+ u8 upiu_flags;
down_read(&hba->clk_scaling_lock);
@@ -5865,6 +6404,7 @@
lrbp->task_tag = tag;
lrbp->lun = 0;
lrbp->intr_cmd = true;
+ ufshcd_prepare_lrbp_crypto(NULL, lrbp);
hba->dev_cmd.type = cmd_type;
switch (hba->ufs_version) {
@@ -5921,7 +6461,9 @@
memcpy(desc_buff, descp, resp_len);
*buff_len = resp_len;
} else {
- dev_warn(hba->dev, "rsp size is bigger than buffer");
+ dev_warn(hba->dev,
+ "%s: rsp size %d is bigger than buffer size %d",
+ __func__, resp_len, *buff_len);
*buff_len = 0;
err = -EINVAL;
}
@@ -5956,7 +6498,7 @@
enum query_opcode desc_op)
{
int err;
- int cmd_type = DEV_CMD_TYPE_QUERY;
+ enum dev_cmd_type cmd_type = DEV_CMD_TYPE_QUERY;
struct utp_task_req_desc treq = { { 0 }, };
int ocs_value;
u8 tm_f = be32_to_cpu(req_upiu->header.dword_1) >> 16 & MASK_TM_FUNC;
@@ -5964,7 +6506,7 @@
switch (msgcode) {
case UPIU_TRANSACTION_NOP_OUT:
cmd_type = DEV_CMD_TYPE_NOP;
- /* fall through */
+ fallthrough;
case UPIU_TRANSACTION_QUERY_REQ:
ufshcd_hold(hba, false);
mutex_lock(&hba->dev_cmd.lock);
@@ -6067,7 +6609,7 @@
}
/**
- * ufshcd_abort - abort a specific command
+ * ufshcd_try_to_abort_task - abort a specific task
* @cmd: SCSI command pointer
*
* Abort the pending command in device by sending UFS_ABORT_TASK task management
@@ -6076,6 +6618,80 @@
* issued. To avoid that, first issue UFS_QUERY_TASK to check if the command is
* really issued and then try to abort it.
*
+ * Returns zero on success, non-zero on failure
+ */
+static int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag)
+{
+ struct ufshcd_lrb *lrbp = &hba->lrb[tag];
+ int err = 0;
+ int poll_cnt;
+ u8 resp = 0xF;
+ u32 reg;
+
+ for (poll_cnt = 100; poll_cnt; poll_cnt--) {
+ err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
+ UFS_QUERY_TASK, &resp);
+ if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED) {
+ /* cmd pending in the device */
+ dev_err(hba->dev, "%s: cmd pending in the device. tag = %d\n",
+ __func__, tag);
+ break;
+ } else if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
+ /*
+ * cmd not pending in the device, check if it is
+ * in transition.
+ */
+ dev_err(hba->dev, "%s: cmd at tag %d not pending in the device.\n",
+ __func__, tag);
+ reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+ if (reg & (1 << tag)) {
+ /* sleep for max. 200us to stabilize */
+ usleep_range(100, 200);
+ continue;
+ }
+ /* command completed already */
+ dev_err(hba->dev, "%s: cmd at tag %d successfully cleared from DB.\n",
+ __func__, tag);
+ goto out;
+ } else {
+ dev_err(hba->dev,
+ "%s: no response from device. tag = %d, err %d\n",
+ __func__, tag, err);
+ if (!err)
+ err = resp; /* service response error */
+ goto out;
+ }
+ }
+
+ if (!poll_cnt) {
+ err = -EBUSY;
+ goto out;
+ }
+
+ err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
+ UFS_ABORT_TASK, &resp);
+ if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
+ if (!err) {
+ err = resp; /* service response error */
+ dev_err(hba->dev, "%s: issued. tag = %d, err %d\n",
+ __func__, tag, err);
+ }
+ goto out;
+ }
+
+ err = ufshcd_clear_cmd(hba, tag);
+ if (err)
+ dev_err(hba->dev, "%s: Failed clearing cmd at tag %d, err %d\n",
+ __func__, tag, err);
+
+out:
+ return err;
+}
+
+/**
+ * ufshcd_abort - scsi host template eh_abort_handler callback
+ * @cmd: SCSI command pointer
+ *
* Returns SUCCESS/FAILED
*/
static int ufshcd_abort(struct scsi_cmnd *cmd)
@@ -6085,8 +6701,6 @@
unsigned long flags;
unsigned int tag;
int err = 0;
- int poll_cnt;
- u8 resp = 0xF;
struct ufshcd_lrb *lrbp;
u32 reg;
@@ -6121,14 +6735,8 @@
goto out;
}
- if (!(reg & (1 << tag))) {
- dev_err(hba->dev,
- "%s: cmd was completed, but without a notifying intr, tag = %d",
- __func__, tag);
- }
-
/* Print Transfer Request of aborted task */
- dev_err(hba->dev, "%s: Device abort task at tag %d\n", __func__, tag);
+ dev_info(hba->dev, "%s: Device abort task at tag %d\n", __func__, tag);
/*
* Print detailed info about aborted request.
@@ -6149,80 +6757,25 @@
}
hba->req_abort_count++;
+ if (!(reg & (1 << tag))) {
+ dev_err(hba->dev,
+ "%s: cmd was completed, but without a notifying intr, tag = %d",
+ __func__, tag);
+ goto cleanup;
+ }
+
/* Skip task abort in case previous aborts failed and report failure */
- if (lrbp->req_abort_skip) {
+ if (lrbp->req_abort_skip)
err = -EIO;
- goto out;
- }
+ else
+ err = ufshcd_try_to_abort_task(hba, tag);
- for (poll_cnt = 100; poll_cnt; poll_cnt--) {
- err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
- UFS_QUERY_TASK, &resp);
- if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED) {
- /* cmd pending in the device */
- dev_err(hba->dev, "%s: cmd pending in the device. tag = %d\n",
- __func__, tag);
- break;
- } else if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
- /*
- * cmd not pending in the device, check if it is
- * in transition.
- */
- dev_err(hba->dev, "%s: cmd at tag %d not pending in the device.\n",
- __func__, tag);
- reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
- if (reg & (1 << tag)) {
- /* sleep for max. 200us to stabilize */
- usleep_range(100, 200);
- continue;
- }
- /* command completed already */
- dev_err(hba->dev, "%s: cmd at tag %d successfully cleared from DB.\n",
- __func__, tag);
- goto cleanup;
- } else {
- dev_err(hba->dev,
- "%s: no response from device. tag = %d, err %d\n",
- __func__, tag, err);
- if (!err)
- err = resp; /* service response error */
- goto out;
- }
- }
-
- if (!poll_cnt) {
- err = -EBUSY;
- goto out;
- }
-
- err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
- UFS_ABORT_TASK, &resp);
- if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
- if (!err) {
- err = resp; /* service response error */
- dev_err(hba->dev, "%s: issued. tag = %d, err %d\n",
- __func__, tag, err);
- }
- goto out;
- }
-
- err = ufshcd_clear_cmd(hba, tag);
- if (err) {
- dev_err(hba->dev, "%s: Failed clearing cmd at tag %d, err %d\n",
- __func__, tag, err);
- goto out;
- }
-
-cleanup:
- scsi_dma_unmap(cmd);
-
- spin_lock_irqsave(host->host_lock, flags);
- ufshcd_outstanding_req_clear(hba, tag);
- hba->lrb[tag].cmd = NULL;
- spin_unlock_irqrestore(host->host_lock, flags);
-
-out:
if (!err) {
+cleanup:
+ spin_lock_irqsave(host->host_lock, flags);
+ __ufshcd_transfer_req_compl(hba, (1UL << tag));
+ spin_unlock_irqrestore(host->host_lock, flags);
+out:
err = SUCCESS;
} else {
dev_err(hba->dev, "%s: failed with err %d\n", __func__, err);
@@ -6257,25 +6810,24 @@
* Stop the host controller and complete the requests
* cleared by h/w
*/
+ ufshcd_hba_stop(hba);
+
spin_lock_irqsave(hba->host->host_lock, flags);
- ufshcd_hba_stop(hba, false);
hba->silence_err_logs = true;
ufshcd_complete_requests(hba);
hba->silence_err_logs = false;
spin_unlock_irqrestore(hba->host->host_lock, flags);
/* scale up clocks to max frequency before full reinitialization */
- ufshcd_scale_clks(hba, true);
+ ufshcd_set_clk_freq(hba, true);
err = ufshcd_hba_enable(hba);
if (err)
goto out;
/* Establish the link again and restore the device */
- err = ufshcd_probe_hba(hba);
+ err = ufshcd_probe_hba(hba, false);
- if (!err && (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL))
- err = -EIO;
out:
if (err)
dev_err(hba->dev, "%s: Host init failed %d\n", __func__, err);
@@ -6294,9 +6846,23 @@
*/
static int ufshcd_reset_and_restore(struct ufs_hba *hba)
{
+ u32 saved_err;
+ u32 saved_uic_err;
int err = 0;
+ unsigned long flags;
int retries = MAX_HOST_RESET_RETRIES;
+ /*
+ * This is a fresh start, cache and clear saved error first,
+ * in case new error generated during reset and restore.
+ */
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ saved_err = hba->saved_err;
+ saved_uic_err = hba->saved_uic_err;
+ hba->saved_err = 0;
+ hba->saved_uic_err = 0;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+
do {
/* Reset the attached device */
ufshcd_vops_device_reset(hba);
@@ -6304,6 +6870,18 @@
err = ufshcd_host_reset_and_restore(hba);
} while (err && --retries);
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ /*
+ * Inform scsi mid-layer that we did reset and allow to handle
+ * Unit Attention properly.
+ */
+ scsi_report_bus_reset(hba->host, 0);
+ if (err) {
+ hba->saved_err |= saved_err;
+ hba->saved_uic_err |= saved_uic_err;
+ }
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+
return err;
}
@@ -6315,48 +6893,25 @@
*/
static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd)
{
- int err;
+ int err = SUCCESS;
unsigned long flags;
struct ufs_hba *hba;
hba = shost_priv(cmd->device->host);
- ufshcd_hold(hba, false);
- /*
- * Check if there is any race with fatal error handling.
- * If so, wait for it to complete. Even though fatal error
- * handling does reset and restore in some cases, don't assume
- * anything out of it. We are just avoiding race here.
- */
- do {
- spin_lock_irqsave(hba->host->host_lock, flags);
- if (!(work_pending(&hba->eh_work) ||
- hba->ufshcd_state == UFSHCD_STATE_RESET ||
- hba->ufshcd_state == UFSHCD_STATE_EH_SCHEDULED))
- break;
- spin_unlock_irqrestore(hba->host->host_lock, flags);
- dev_dbg(hba->dev, "%s: reset in progress\n", __func__);
- flush_work(&hba->eh_work);
- } while (1);
-
- hba->ufshcd_state = UFSHCD_STATE_RESET;
- ufshcd_set_eh_in_progress(hba);
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ hba->force_reset = true;
+ ufshcd_schedule_eh_work(hba);
+ dev_err(hba->dev, "%s: reset in progress - 1\n", __func__);
spin_unlock_irqrestore(hba->host->host_lock, flags);
- err = ufshcd_reset_and_restore(hba);
+ flush_work(&hba->eh_work);
spin_lock_irqsave(hba->host->host_lock, flags);
- if (!err) {
- err = SUCCESS;
- hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
- } else {
+ if (hba->ufshcd_state == UFSHCD_STATE_ERROR)
err = FAILED;
- hba->ufshcd_state = UFSHCD_STATE_ERROR;
- }
- ufshcd_clear_eh_in_progress(hba);
spin_unlock_irqrestore(hba->host->host_lock, flags);
- ufshcd_release(hba);
return err;
}
@@ -6448,17 +7003,19 @@
return icc_level;
}
-static void ufshcd_init_icc_levels(struct ufs_hba *hba)
+static void ufshcd_set_active_icc_lvl(struct ufs_hba *hba)
{
int ret;
- int buff_len = hba->desc_size.pwr_desc;
+ int buff_len = hba->desc_size[QUERY_DESC_IDN_POWER];
u8 *desc_buf;
+ u32 icc_level;
desc_buf = kmalloc(buff_len, GFP_KERNEL);
if (!desc_buf)
return;
- ret = ufshcd_read_power_desc(hba, desc_buf, buff_len);
+ ret = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_POWER, 0, 0,
+ desc_buf, buff_len);
if (ret) {
dev_err(hba->dev,
"%s: Failed reading power descriptor.len = %d ret = %d",
@@ -6466,25 +7023,32 @@
goto out;
}
- hba->init_prefetch_data.icc_level =
- ufshcd_find_max_sup_active_icc_level(hba,
- desc_buf, buff_len);
- dev_dbg(hba->dev, "%s: setting icc_level 0x%x",
- __func__, hba->init_prefetch_data.icc_level);
+ icc_level = ufshcd_find_max_sup_active_icc_level(hba, desc_buf,
+ buff_len);
+ dev_dbg(hba->dev, "%s: setting icc_level 0x%x", __func__, icc_level);
ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
- QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0,
- &hba->init_prefetch_data.icc_level);
+ QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0, &icc_level);
if (ret)
dev_err(hba->dev,
"%s: Failed configuring bActiveICCLevel = %d ret = %d",
- __func__, hba->init_prefetch_data.icc_level , ret);
+ __func__, icc_level, ret);
out:
kfree(desc_buf);
}
+static inline void ufshcd_blk_pm_runtime_init(struct scsi_device *sdev)
+{
+ scsi_autopm_get_device(sdev);
+ blk_pm_runtime_init(sdev->request_queue, &sdev->sdev_gendev);
+ if (sdev->rpm_autosuspend)
+ pm_runtime_set_autosuspend_delay(&sdev->sdev_gendev,
+ RPM_AUTOSUSPEND_DELAY_MS);
+ scsi_autopm_put_device(sdev);
+}
+
/**
* ufshcd_scsi_add_wlus - Adds required W-LUs
* @hba: per-adapter instance
@@ -6514,7 +7078,6 @@
static int ufshcd_scsi_add_wlus(struct ufs_hba *hba)
{
int ret = 0;
- struct scsi_device *sdev_rpmb;
struct scsi_device *sdev_boot;
hba->sdev_ufs_device = __scsi_add_device(hba->host, 0, 0,
@@ -6524,22 +7087,26 @@
hba->sdev_ufs_device = NULL;
goto out;
}
+ ufshcd_blk_pm_runtime_init(hba->sdev_ufs_device);
scsi_device_put(hba->sdev_ufs_device);
- sdev_rpmb = __scsi_add_device(hba->host, 0, 0,
+ hba->sdev_rpmb = __scsi_add_device(hba->host, 0, 0,
ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN), NULL);
- if (IS_ERR(sdev_rpmb)) {
- ret = PTR_ERR(sdev_rpmb);
+ if (IS_ERR(hba->sdev_rpmb)) {
+ ret = PTR_ERR(hba->sdev_rpmb);
goto remove_sdev_ufs_device;
}
- scsi_device_put(sdev_rpmb);
+ ufshcd_blk_pm_runtime_init(hba->sdev_rpmb);
+ scsi_device_put(hba->sdev_rpmb);
sdev_boot = __scsi_add_device(hba->host, 0, 0,
ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL);
- if (IS_ERR(sdev_boot))
+ if (IS_ERR(sdev_boot)) {
dev_err(hba->dev, "%s: BOOT WLUN not found\n", __func__);
- else
+ } else {
+ ufshcd_blk_pm_runtime_init(sdev_boot);
scsi_device_put(sdev_boot);
+ }
goto out;
remove_sdev_ufs_device:
@@ -6548,26 +7115,119 @@
return ret;
}
-static int ufs_get_device_desc(struct ufs_hba *hba,
- struct ufs_dev_desc *dev_desc)
+static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf)
+{
+ struct ufs_dev_info *dev_info = &hba->dev_info;
+ u8 lun;
+ u32 d_lu_wb_buf_alloc;
+
+ if (!ufshcd_is_wb_allowed(hba))
+ return;
+ /*
+ * Probe WB only for UFS-2.2 and UFS-3.1 (and later) devices or
+ * UFS devices with quirk UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES
+ * enabled
+ */
+ if (!(dev_info->wspecversion >= 0x310 ||
+ dev_info->wspecversion == 0x220 ||
+ (hba->dev_quirks & UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES)))
+ goto wb_disabled;
+
+ if (hba->desc_size[QUERY_DESC_IDN_DEVICE] <
+ DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP + 4)
+ goto wb_disabled;
+
+ dev_info->d_ext_ufs_feature_sup =
+ get_unaligned_be32(desc_buf +
+ DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP);
+
+ if (!(dev_info->d_ext_ufs_feature_sup & UFS_DEV_WRITE_BOOSTER_SUP))
+ goto wb_disabled;
+
+ /*
+ * WB may be supported but not configured while provisioning.
+ * The spec says, in dedicated wb buffer mode,
+ * a max of 1 lun would have wb buffer configured.
+ * Now only shared buffer mode is supported.
+ */
+ dev_info->b_wb_buffer_type =
+ desc_buf[DEVICE_DESC_PARAM_WB_TYPE];
+
+ dev_info->b_presrv_uspc_en =
+ desc_buf[DEVICE_DESC_PARAM_WB_PRESRV_USRSPC_EN];
+
+ if (dev_info->b_wb_buffer_type == WB_BUF_MODE_SHARED) {
+ dev_info->d_wb_alloc_units =
+ get_unaligned_be32(desc_buf +
+ DEVICE_DESC_PARAM_WB_SHARED_ALLOC_UNITS);
+ if (!dev_info->d_wb_alloc_units)
+ goto wb_disabled;
+ } else {
+ for (lun = 0; lun < UFS_UPIU_MAX_WB_LUN_ID; lun++) {
+ d_lu_wb_buf_alloc = 0;
+ ufshcd_read_unit_desc_param(hba,
+ lun,
+ UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS,
+ (u8 *)&d_lu_wb_buf_alloc,
+ sizeof(d_lu_wb_buf_alloc));
+ if (d_lu_wb_buf_alloc) {
+ dev_info->wb_dedicated_lu = lun;
+ break;
+ }
+ }
+
+ if (!d_lu_wb_buf_alloc)
+ goto wb_disabled;
+ }
+ return;
+
+wb_disabled:
+ hba->caps &= ~UFSHCD_CAP_WB_EN;
+}
+
+void ufshcd_fixup_dev_quirks(struct ufs_hba *hba, struct ufs_dev_fix *fixups)
+{
+ struct ufs_dev_fix *f;
+ struct ufs_dev_info *dev_info = &hba->dev_info;
+
+ if (!fixups)
+ return;
+
+ for (f = fixups; f->quirk; f++) {
+ if ((f->wmanufacturerid == dev_info->wmanufacturerid ||
+ f->wmanufacturerid == UFS_ANY_VENDOR) &&
+ ((dev_info->model &&
+ STR_PRFX_EQUAL(f->model, dev_info->model)) ||
+ !strcmp(f->model, UFS_ANY_MODEL)))
+ hba->dev_quirks |= f->quirk;
+ }
+}
+EXPORT_SYMBOL_GPL(ufshcd_fixup_dev_quirks);
+
+static void ufs_fixup_device_setup(struct ufs_hba *hba)
+{
+ /* fix by general quirk table */
+ ufshcd_fixup_dev_quirks(hba, ufs_fixups);
+
+ /* allow vendors to fix quirks */
+ ufshcd_vops_fixup_dev_quirks(hba);
+}
+
+static int ufs_get_device_desc(struct ufs_hba *hba)
{
int err;
- size_t buff_len;
u8 model_index;
u8 *desc_buf;
+ struct ufs_dev_info *dev_info = &hba->dev_info;
- if (!dev_desc)
- return -EINVAL;
-
- buff_len = max_t(size_t, hba->desc_size.dev_desc,
- QUERY_DESC_MAX_SIZE + 1);
- desc_buf = kmalloc(buff_len, GFP_KERNEL);
+ desc_buf = kmalloc(QUERY_DESC_MAX_SIZE, GFP_KERNEL);
if (!desc_buf) {
err = -ENOMEM;
goto out;
}
- err = ufshcd_read_device_desc(hba, desc_buf, hba->desc_size.dev_desc);
+ err = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_DEVICE, 0, 0, desc_buf,
+ hba->desc_size[QUERY_DESC_IDN_DEVICE]);
if (err) {
dev_err(hba->dev, "%s: Failed reading Device Desc. err = %d\n",
__func__, err);
@@ -6578,18 +7238,27 @@
* getting vendor (manufacturerID) and Bank Index in big endian
* format
*/
- dev_desc->wmanufacturerid = desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8 |
+ dev_info->wmanufacturerid = desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8 |
desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1];
+ /* getting Specification Version in big endian format */
+ dev_info->wspecversion = desc_buf[DEVICE_DESC_PARAM_SPEC_VER] << 8 |
+ desc_buf[DEVICE_DESC_PARAM_SPEC_VER + 1];
+
model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME];
+
err = ufshcd_read_string_desc(hba, model_index,
- &dev_desc->model, SD_ASCII_STD);
+ &dev_info->model, SD_ASCII_STD);
if (err < 0) {
dev_err(hba->dev, "%s: Failed reading Product Name. err = %d\n",
__func__, err);
goto out;
}
+ ufs_fixup_device_setup(hba);
+
+ ufshcd_wb_probe(hba, desc_buf);
+
/*
* ufshcd_read_string_desc returns size of the string
* reset the error value
@@ -6601,25 +7270,12 @@
return err;
}
-static void ufs_put_device_desc(struct ufs_dev_desc *dev_desc)
+static void ufs_put_device_desc(struct ufs_hba *hba)
{
- kfree(dev_desc->model);
- dev_desc->model = NULL;
-}
+ struct ufs_dev_info *dev_info = &hba->dev_info;
-static void ufs_fixup_device_setup(struct ufs_hba *hba,
- struct ufs_dev_desc *dev_desc)
-{
- struct ufs_dev_fix *f;
-
- for (f = ufs_fixups; f->quirk; f++) {
- if ((f->card.wmanufacturerid == dev_desc->wmanufacturerid ||
- f->card.wmanufacturerid == UFS_ANY_VENDOR) &&
- ((dev_desc->model &&
- STR_PRFX_EQUAL(f->card.model, dev_desc->model)) ||
- !strcmp(f->card.model, UFS_ANY_MODEL)))
- hba->dev_quirks |= f->quirk;
- }
+ kfree(dev_info->model);
+ dev_info->model = NULL;
}
/**
@@ -6769,22 +7425,21 @@
return ret;
}
-static void ufshcd_tune_unipro_params(struct ufs_hba *hba,
- struct ufs_dev_desc *card)
+static void ufshcd_tune_unipro_params(struct ufs_hba *hba)
{
if (ufshcd_is_unipro_pa_params_tuning_req(hba)) {
ufshcd_tune_pa_tactivate(hba);
ufshcd_tune_pa_hibern8time(hba);
}
+ ufshcd_vops_apply_dev_quirks(hba);
+
if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_TACTIVATE)
/* set 1ms timeout for PA_TACTIVATE */
ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TACTIVATE), 10);
if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE)
ufshcd_quirk_tune_host_pa_tactivate(hba);
-
- ufshcd_vops_apply_dev_quirks(hba, card);
}
static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba)
@@ -6794,44 +7449,35 @@
hba->req_abort_count = 0;
}
-static void ufshcd_init_desc_sizes(struct ufs_hba *hba)
+static int ufshcd_device_geo_params_init(struct ufs_hba *hba)
{
int err;
+ size_t buff_len;
+ u8 *desc_buf;
- err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_DEVICE, 0,
- &hba->desc_size.dev_desc);
- if (err)
- hba->desc_size.dev_desc = QUERY_DESC_DEVICE_DEF_SIZE;
+ buff_len = hba->desc_size[QUERY_DESC_IDN_GEOMETRY];
+ desc_buf = kmalloc(buff_len, GFP_KERNEL);
+ if (!desc_buf) {
+ err = -ENOMEM;
+ goto out;
+ }
- err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_POWER, 0,
- &hba->desc_size.pwr_desc);
- if (err)
- hba->desc_size.pwr_desc = QUERY_DESC_POWER_DEF_SIZE;
+ err = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_GEOMETRY, 0, 0,
+ desc_buf, buff_len);
+ if (err) {
+ dev_err(hba->dev, "%s: Failed reading Geometry Desc. err = %d\n",
+ __func__, err);
+ goto out;
+ }
- err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_INTERCONNECT, 0,
- &hba->desc_size.interc_desc);
- if (err)
- hba->desc_size.interc_desc = QUERY_DESC_INTERCONNECT_DEF_SIZE;
+ if (desc_buf[GEOMETRY_DESC_PARAM_MAX_NUM_LUN] == 1)
+ hba->dev_info.max_lu_supported = 32;
+ else if (desc_buf[GEOMETRY_DESC_PARAM_MAX_NUM_LUN] == 0)
+ hba->dev_info.max_lu_supported = 8;
- err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_CONFIGURATION, 0,
- &hba->desc_size.conf_desc);
- if (err)
- hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE;
-
- err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_UNIT, 0,
- &hba->desc_size.unit_desc);
- if (err)
- hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE;
-
- err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_GEOMETRY, 0,
- &hba->desc_size.geom_desc);
- if (err)
- hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE;
-
- err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_HEALTH, 0,
- &hba->desc_size.hlth_desc);
- if (err)
- hba->desc_size.hlth_desc = QUERY_DESC_HEALTH_DEF_SIZE;
+out:
+ kfree(desc_buf);
+ return err;
}
static struct ufs_ref_clk ufs_ref_clk_freqs[] = {
@@ -6902,64 +7548,188 @@
return err;
}
+static int ufshcd_device_params_init(struct ufs_hba *hba)
+{
+ bool flag;
+ int ret, i;
+
+ /* Init device descriptor sizes */
+ for (i = 0; i < QUERY_DESC_IDN_MAX; i++)
+ hba->desc_size[i] = QUERY_DESC_MAX_SIZE;
+
+ /* Init UFS geometry descriptor related parameters */
+ ret = ufshcd_device_geo_params_init(hba);
+ if (ret)
+ goto out;
+
+ /* Check and apply UFS device quirks */
+ ret = ufs_get_device_desc(hba);
+ if (ret) {
+ dev_err(hba->dev, "%s: Failed getting device info. err = %d\n",
+ __func__, ret);
+ goto out;
+ }
+
+ ufshcd_get_ref_clk_gating_wait(hba);
+
+ if (!ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
+ QUERY_FLAG_IDN_PWR_ON_WPE, 0, &flag))
+ hba->dev_info.f_power_on_wp_en = flag;
+
+ /* Probe maximum power mode co-supported by both UFS host and device */
+ if (ufshcd_get_max_pwr_mode(hba))
+ dev_err(hba->dev,
+ "%s: Failed getting max supported power mode\n",
+ __func__);
+out:
+ return ret;
+}
+
+/**
+ * ufshcd_add_lus - probe and add UFS logical units
+ * @hba: per-adapter instance
+ */
+static int ufshcd_add_lus(struct ufs_hba *hba)
+{
+ int ret;
+
+ /* Add required well known logical units to scsi mid layer */
+ ret = ufshcd_scsi_add_wlus(hba);
+ if (ret)
+ goto out;
+
+ /* Initialize devfreq after UFS device is detected */
+ if (ufshcd_is_clkscaling_supported(hba)) {
+ memcpy(&hba->clk_scaling.saved_pwr_info.info,
+ &hba->pwr_info,
+ sizeof(struct ufs_pa_layer_attr));
+ hba->clk_scaling.saved_pwr_info.is_valid = true;
+ if (!hba->devfreq) {
+ ret = ufshcd_devfreq_init(hba);
+ if (ret)
+ goto out;
+ }
+
+ hba->clk_scaling.is_allowed = true;
+ }
+
+ ufs_bsg_probe(hba);
+ scsi_scan_host(hba->host);
+ pm_runtime_put_sync(hba->dev);
+
+out:
+ return ret;
+}
+
+static int
+ufshcd_send_request_sense(struct ufs_hba *hba, struct scsi_device *sdp);
+
+static int ufshcd_clear_ua_wlun(struct ufs_hba *hba, u8 wlun)
+{
+ struct scsi_device *sdp;
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ if (wlun == UFS_UPIU_UFS_DEVICE_WLUN)
+ sdp = hba->sdev_ufs_device;
+ else if (wlun == UFS_UPIU_RPMB_WLUN)
+ sdp = hba->sdev_rpmb;
+ else
+ BUG();
+ if (sdp) {
+ ret = scsi_device_get(sdp);
+ if (!ret && !scsi_device_online(sdp)) {
+ ret = -ENODEV;
+ scsi_device_put(sdp);
+ }
+ } else {
+ ret = -ENODEV;
+ }
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+ if (ret)
+ goto out_err;
+
+ ret = ufshcd_send_request_sense(hba, sdp);
+ scsi_device_put(sdp);
+out_err:
+ if (ret)
+ dev_err(hba->dev, "%s: UAC clear LU=%x ret = %d\n",
+ __func__, wlun, ret);
+ return ret;
+}
+
+static int ufshcd_clear_ua_wluns(struct ufs_hba *hba)
+{
+ int ret = 0;
+
+ if (!hba->wlun_dev_clr_ua)
+ goto out;
+
+ ret = ufshcd_clear_ua_wlun(hba, UFS_UPIU_UFS_DEVICE_WLUN);
+ if (!ret)
+ ret = ufshcd_clear_ua_wlun(hba, UFS_UPIU_RPMB_WLUN);
+ if (!ret)
+ hba->wlun_dev_clr_ua = false;
+out:
+ if (ret)
+ dev_err(hba->dev, "%s: Failed to clear UAC WLUNS ret = %d\n",
+ __func__, ret);
+ return ret;
+}
+
/**
* ufshcd_probe_hba - probe hba to detect device and initialize
* @hba: per-adapter instance
+ * @async: asynchronous execution or not
*
* Execute link-startup and verify device initialization
*/
-static int ufshcd_probe_hba(struct ufs_hba *hba)
+static int ufshcd_probe_hba(struct ufs_hba *hba, bool async)
{
- struct ufs_dev_desc card = {0};
int ret;
+ unsigned long flags;
ktime_t start = ktime_get();
ret = ufshcd_link_startup(hba);
if (ret)
goto out;
- /* set the default level for urgent bkops */
- hba->urgent_bkops_lvl = BKOPS_STATUS_PERF_IMPACT;
- hba->is_urgent_bkops_lvl_checked = false;
-
/* Debug counters initialization */
ufshcd_clear_dbg_ufs_stats(hba);
/* UniPro link is active now */
ufshcd_set_link_active(hba);
+ /* Verify device initialization by sending NOP OUT UPIU */
ret = ufshcd_verify_dev_init(hba);
if (ret)
goto out;
+ /* Initiate UFS initialization, and waiting until completion */
ret = ufshcd_complete_dev_init(hba);
if (ret)
goto out;
- /* Init check for device descriptor sizes */
- ufshcd_init_desc_sizes(hba);
-
- ret = ufs_get_device_desc(hba, &card);
- if (ret) {
- dev_err(hba->dev, "%s: Failed getting device info. err = %d\n",
- __func__, ret);
- goto out;
+ /*
+ * Initialize UFS device parameters used by driver, these
+ * parameters are associated with UFS descriptors.
+ */
+ if (async) {
+ ret = ufshcd_device_params_init(hba);
+ if (ret)
+ goto out;
}
- ufs_fixup_device_setup(hba, &card);
- ufshcd_tune_unipro_params(hba, &card);
- ufs_put_device_desc(&card);
+ ufshcd_tune_unipro_params(hba);
/* UFS device is also active now */
ufshcd_set_ufs_dev_active(hba);
ufshcd_force_reset_auto_bkops(hba);
hba->wlun_dev_clr_ua = true;
- if (ufshcd_get_max_pwr_mode(hba)) {
- dev_err(hba->dev,
- "%s: Failed getting max supported power mode\n",
- __func__);
- } else {
+ /* Gear up to HS gear if supported */
+ if (hba->max_pwr_info.is_valid) {
/*
* Set the right value to bRefClkFreq before attempting to
* switch to HS gears.
@@ -6972,68 +7742,28 @@
__func__, ret);
goto out;
}
+ ufshcd_print_pwr_info(hba);
}
- /* set the state as operational after switching to desired gear */
- hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
+ /*
+ * bActiveICCLevel is volatile for UFS device (as per latest v2.1 spec)
+ * and for removable UFS card as well, hence always set the parameter.
+ * Note: Error handler may issue the device reset hence resetting
+ * bActiveICCLevel as well so it is always safe to set this here.
+ */
+ ufshcd_set_active_icc_lvl(hba);
+ ufshcd_wb_config(hba);
/* Enable Auto-Hibernate if configured */
ufshcd_auto_hibern8_enable(hba);
- /*
- * If we are in error handling context or in power management callbacks
- * context, no need to scan the host
- */
- if (!ufshcd_eh_in_progress(hba) && !hba->pm_op_in_progress) {
- bool flag;
-
- /* clear any previous UFS device information */
- memset(&hba->dev_info, 0, sizeof(hba->dev_info));
- if (!ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
- QUERY_FLAG_IDN_PWR_ON_WPE, &flag))
- hba->dev_info.f_power_on_wp_en = flag;
-
- if (!hba->is_init_prefetch)
- ufshcd_init_icc_levels(hba);
-
- /* Add required well known logical units to scsi mid layer */
- ret = ufshcd_scsi_add_wlus(hba);
- if (ret)
- goto out;
-
- /* Initialize devfreq after UFS device is detected */
- if (ufshcd_is_clkscaling_supported(hba)) {
- memcpy(&hba->clk_scaling.saved_pwr_info.info,
- &hba->pwr_info,
- sizeof(struct ufs_pa_layer_attr));
- hba->clk_scaling.saved_pwr_info.is_valid = true;
- if (!hba->devfreq) {
- ret = ufshcd_devfreq_init(hba);
- if (ret)
- goto out;
- }
- hba->clk_scaling.is_allowed = true;
- }
-
- ufs_bsg_probe(hba);
-
- scsi_scan_host(hba->host);
- pm_runtime_put_sync(hba->dev);
- }
-
- if (!hba->is_init_prefetch)
- hba->is_init_prefetch = true;
-
out:
- /*
- * If we failed to initialize the device or the device is not
- * present, turn off the power/clocks etc.
- */
- if (ret && !ufshcd_eh_in_progress(hba) && !hba->pm_op_in_progress) {
- pm_runtime_put_sync(hba->dev);
- ufshcd_exit_clk_scaling(hba);
- ufshcd_hba_exit(hba);
- }
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ if (ret)
+ hba->ufshcd_state = UFSHCD_STATE_ERROR;
+ else if (hba->ufshcd_state == UFSHCD_STATE_RESET)
+ hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
trace_ufshcd_init(dev_name(hba->dev), ret,
ktime_to_us(ktime_sub(ktime_get(), start)),
@@ -7049,43 +7779,27 @@
static void ufshcd_async_scan(void *data, async_cookie_t cookie)
{
struct ufs_hba *hba = (struct ufs_hba *)data;
+ int ret;
- ufshcd_probe_hba(hba);
-}
+ /* Initialize hba, detect and initialize UFS device */
+ ret = ufshcd_probe_hba(hba, true);
+ if (ret)
+ goto out;
-static enum blk_eh_timer_return ufshcd_eh_timed_out(struct scsi_cmnd *scmd)
-{
- unsigned long flags;
- struct Scsi_Host *host;
- struct ufs_hba *hba;
- int index;
- bool found = false;
-
- if (!scmd || !scmd->device || !scmd->device->host)
- return BLK_EH_DONE;
-
- host = scmd->device->host;
- hba = shost_priv(host);
- if (!hba)
- return BLK_EH_DONE;
-
- spin_lock_irqsave(host->host_lock, flags);
-
- for_each_set_bit(index, &hba->outstanding_reqs, hba->nutrs) {
- if (hba->lrb[index].cmd == scmd) {
- found = true;
- break;
- }
- }
-
- spin_unlock_irqrestore(host->host_lock, flags);
-
+ /* Probe and add UFS logical units */
+ ret = ufshcd_add_lus(hba);
+out:
/*
- * Bypass SCSI error handling and reset the block layer timer if this
- * SCSI command was not actually dispatched to UFS driver, otherwise
- * let SCSI layer handle the error as usual.
+ * If we failed to initialize the device or the device is not
+ * present, turn off the power/clocks etc.
*/
- return found ? BLK_EH_DONE : BLK_EH_RESET_TIMER;
+ if (ret) {
+ pm_runtime_put_sync(hba->dev);
+ ufshcd_exit_clk_scaling(hba);
+ ufshcd_hba_exit(hba);
+ } else {
+ ufshcd_clear_ua_wluns(hba);
+ }
}
static const struct attribute_group *ufshcd_driver_groups[] = {
@@ -7094,6 +7808,16 @@
NULL,
};
+static struct ufs_hba_variant_params ufs_hba_vps = {
+ .hba_enable_delay_us = 1000,
+ .wb_flush_threshold = UFS_WB_BUF_REMAIN_PERCENT(40),
+ .devfreq_profile.polling_ms = 100,
+ .devfreq_profile.target = ufshcd_devfreq_target,
+ .devfreq_profile.get_dev_status = ufshcd_devfreq_get_dev_status,
+ .ondemand_data.upthreshold = 70,
+ .ondemand_data.downdifferential = 5,
+};
+
static struct scsi_host_template ufshcd_driver_template = {
.module = THIS_MODULE,
.name = UFSHCD,
@@ -7106,7 +7830,6 @@
.eh_abort_handler = ufshcd_abort,
.eh_device_reset_handler = ufshcd_eh_device_reset_handler,
.eh_host_reset_handler = ufshcd_eh_host_reset_handler,
- .eh_timed_out = ufshcd_eh_timed_out,
.this_id = -1,
.sg_tablesize = SG_ALL,
.cmd_per_lun = UFSHCD_CMD_PER_LUN,
@@ -7116,6 +7839,7 @@
.track_queue_depth = 1,
.sdev_groups = ufshcd_driver_groups,
.dma_boundary = PAGE_SIZE - 1,
+ .rpm_autosuspend_delay = RPM_AUTOSUSPEND_DELAY_MS,
};
static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg,
@@ -7173,21 +7897,19 @@
name = vreg->name;
if (regulator_count_voltages(reg) > 0) {
- if (vreg->min_uV && vreg->max_uV) {
- min_uV = on ? vreg->min_uV : 0;
- ret = regulator_set_voltage(reg, min_uV, vreg->max_uV);
- if (ret) {
- dev_err(dev,
- "%s: %s set voltage failed, err=%d\n",
- __func__, name, ret);
- goto out;
- }
- }
-
uA_load = on ? vreg->max_uA : 0;
ret = ufshcd_config_vreg_load(dev, vreg, uA_load);
if (ret)
goto out;
+
+ if (vreg->min_uV && vreg->max_uV) {
+ min_uV = on ? vreg->min_uV : 0;
+ ret = regulator_set_voltage(reg, min_uV, vreg->max_uV);
+ if (ret)
+ dev_err(dev,
+ "%s: %s set voltage failed, err=%d\n",
+ __func__, name, ret);
+ }
}
out:
return ret;
@@ -7249,8 +7971,6 @@
goto out;
ret = ufshcd_toggle_vreg(dev, info->vccq2, on);
- if (ret)
- goto out;
out:
if (ret) {
@@ -7296,10 +8016,8 @@
goto out;
ret = ufshcd_get_vreg(dev, info->vccq);
- if (ret)
- goto out;
-
- ret = ufshcd_get_vreg(dev, info->vccq2);
+ if (!ret)
+ ret = ufshcd_get_vreg(dev, info->vccq2);
out:
return ret;
}
@@ -7314,8 +8032,7 @@
return 0;
}
-static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
- bool skip_ref_clk)
+static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on)
{
int ret = 0;
struct ufs_clk_info *clki;
@@ -7327,20 +8044,18 @@
if (list_empty(head))
goto out;
- /*
- * vendor specific setup_clocks ops may depend on clocks managed by
- * this standard driver hence call the vendor specific setup_clocks
- * before disabling the clocks managed here.
- */
- if (!on) {
- ret = ufshcd_vops_setup_clocks(hba, on, PRE_CHANGE);
- if (ret)
- return ret;
- }
+ ret = ufshcd_vops_setup_clocks(hba, on, PRE_CHANGE);
+ if (ret)
+ return ret;
list_for_each_entry(clki, head, list) {
if (!IS_ERR_OR_NULL(clki->clk)) {
- if (skip_ref_clk && !strcmp(clki->name, "ref_clk"))
+ /*
+ * Don't disable clocks which are needed
+ * to keep the link active.
+ */
+ if (ufshcd_is_link_active(hba) &&
+ clki->keep_link_active)
continue;
clk_state_changed = on ^ clki->enabled;
@@ -7360,16 +8075,9 @@
}
}
- /*
- * vendor specific setup_clocks ops may depend on clocks managed by
- * this standard driver hence call the vendor specific setup_clocks
- * after enabling the clocks managed here.
- */
- if (on) {
- ret = ufshcd_vops_setup_clocks(hba, on, POST_CHANGE);
- if (ret)
- return ret;
- }
+ ret = ufshcd_vops_setup_clocks(hba, on, POST_CHANGE);
+ if (ret)
+ return ret;
out:
if (ret) {
@@ -7392,11 +8100,6 @@
return ret;
}
-static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on)
-{
- return __ufshcd_setup_clocks(hba, on, false);
-}
-
static int ufshcd_init_clocks(struct ufs_hba *hba)
{
int ret = 0;
@@ -7457,12 +8160,7 @@
err = ufshcd_vops_setup_regulators(hba, true);
if (err)
- goto out_exit;
-
- goto out;
-
-out_exit:
- ufshcd_vops_exit(hba);
+ ufshcd_vops_exit(hba);
out:
if (err)
dev_err(hba->dev, "%s: variant %s init failed err %d\n",
@@ -7544,6 +8242,7 @@
ufshcd_setup_clocks(hba, false);
ufshcd_setup_hba_vreg(hba, false);
hba->is_powered = false;
+ ufs_put_device_desc(hba);
}
}
@@ -7661,18 +8360,20 @@
if (req_link_state == UIC_LINK_HIBERN8_STATE) {
ret = ufshcd_uic_hibern8_enter(hba);
- if (!ret)
+ if (!ret) {
ufshcd_set_link_hibern8(hba);
- else
+ } else {
+ dev_err(hba->dev, "%s: hibern8 enter failed %d\n",
+ __func__, ret);
goto out;
+ }
}
/*
* If autobkops is enabled, link can't be turned off because
* turning off the link would also turn off the device.
*/
else if ((req_link_state == UIC_LINK_OFF_STATE) &&
- (!check_for_bkops || (check_for_bkops &&
- !hba->auto_bkops_enabled))) {
+ (!check_for_bkops || !hba->auto_bkops_enabled)) {
/*
* Let's make sure that link is in low power mode, we are doing
* this currently by putting the link in Hibern8. Otherway to
@@ -7681,13 +8382,16 @@
* unipro. But putting the link in hibern8 is much faster.
*/
ret = ufshcd_uic_hibern8_enter(hba);
- if (ret)
+ if (ret) {
+ dev_err(hba->dev, "%s: hibern8 enter failed %d\n",
+ __func__, ret);
goto out;
+ }
/*
* Change controller state to "reset state" which
* should also put the link in off/reset state
*/
- ufshcd_hba_stop(hba, true);
+ ufshcd_hba_stop(hba);
/*
* TODO: Check if we need any delay to make sure that
* controller is reset
@@ -7701,6 +8405,8 @@
static void ufshcd_vreg_set_lpm(struct ufs_hba *hba)
{
+ bool vcc_off = false;
+
/*
* It seems some UFS devices may keep drawing more than sleep current
* (atleast for 500us) from UFS rails (especially from VCCQ rail).
@@ -7722,17 +8428,29 @@
*
* Ignore the error returned by ufshcd_toggle_vreg() as device is anyway
* in low power state which would save some power.
+ *
+ * If Write Booster is enabled and the device needs to flush the WB
+ * buffer OR if bkops status is urgent for WB, keep Vcc on.
*/
if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) &&
!hba->dev_info.is_lu_power_on_wp) {
ufshcd_setup_vreg(hba, false);
+ vcc_off = true;
} else if (!ufshcd_is_ufs_dev_active(hba)) {
ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false);
- if (!ufshcd_is_link_active(hba)) {
+ vcc_off = true;
+ if (ufshcd_is_link_hibern8(hba) || ufshcd_is_link_off(hba)) {
ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq);
ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2);
}
}
+
+ /*
+ * Some UFS devices require delay after VCC power rail is turned-off.
+ */
+ if (vcc_off && hba->vreg_info.vcc &&
+ hba->dev_quirks & UFS_DEVICE_QUIRK_DELAY_AFTER_LPM)
+ usleep_range(5000, 5100);
}
static int ufshcd_vreg_set_hpm(struct ufs_hba *hba)
@@ -7743,7 +8461,7 @@
!hba->dev_info.is_lu_power_on_wp) {
ret = ufshcd_setup_vreg(hba, true);
} else if (!ufshcd_is_ufs_dev_active(hba)) {
- if (!ret && !ufshcd_is_link_active(hba)) {
+ if (!ufshcd_is_link_active(hba)) {
ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq);
if (ret)
goto vcc_disable;
@@ -7851,18 +8569,34 @@
/* make sure that auto bkops is disabled */
ufshcd_disable_auto_bkops(hba);
}
+ /*
+ * If device needs to do BKOP or WB buffer flush during
+ * Hibern8, keep device power mode as "active power mode"
+ * and VCC supply.
+ */
+ hba->dev_info.b_rpm_dev_flush_capable =
+ hba->auto_bkops_enabled ||
+ (((req_link_state == UIC_LINK_HIBERN8_STATE) ||
+ ((req_link_state == UIC_LINK_ACTIVE_STATE) &&
+ ufshcd_is_auto_hibern8_enabled(hba))) &&
+ ufshcd_wb_need_flush(hba));
}
- if ((req_dev_pwr_mode != hba->curr_dev_pwr_mode) &&
- ((ufshcd_is_runtime_pm(pm_op) && !hba->auto_bkops_enabled) ||
- !ufshcd_is_runtime_pm(pm_op))) {
- /* ensure that bkops is disabled */
- ufshcd_disable_auto_bkops(hba);
- ret = ufshcd_set_dev_pwr_mode(hba, req_dev_pwr_mode);
- if (ret)
- goto enable_gating;
+ if (req_dev_pwr_mode != hba->curr_dev_pwr_mode) {
+ if ((ufshcd_is_runtime_pm(pm_op) && !hba->auto_bkops_enabled) ||
+ !ufshcd_is_runtime_pm(pm_op)) {
+ /* ensure that bkops is disabled */
+ ufshcd_disable_auto_bkops(hba);
+ }
+
+ if (!hba->dev_info.b_rpm_dev_flush_capable) {
+ ret = ufshcd_set_dev_pwr_mode(hba, req_dev_pwr_mode);
+ if (ret)
+ goto enable_gating;
+ }
}
+ flush_work(&hba->eeh_work);
ret = ufshcd_link_state_transition(hba, req_link_state, 1);
if (ret)
goto set_dev_active;
@@ -7878,20 +8612,20 @@
ret = ufshcd_vops_suspend(hba, pm_op);
if (ret)
goto set_link_active;
-
- if (!ufshcd_is_link_active(hba))
- ufshcd_setup_clocks(hba, false);
- else
- /* If link is active, device ref_clk can't be switched off */
- __ufshcd_setup_clocks(hba, false, true);
-
- hba->clk_gating.state = CLKS_OFF;
- trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state);
/*
* Disable the host irq as host controller as there won't be any
* host controller transaction expected till resume.
*/
ufshcd_disable_irq(hba);
+
+ ufshcd_setup_clocks(hba, false);
+
+ if (ufshcd_is_clkgating_allowed(hba)) {
+ hba->clk_gating.state = CLKS_OFF;
+ trace_ufshcd_clk_gating(dev_name(hba->dev),
+ hba->clk_gating.state);
+ }
+
/* Put the host controller in low power mode if possible */
ufshcd_hba_vreg_set_lpm(hba);
goto out;
@@ -7911,9 +8645,16 @@
if (hba->clk_scaling.is_allowed)
ufshcd_resume_clkscaling(hba);
hba->clk_gating.is_suspended = false;
+ hba->dev_info.b_rpm_dev_flush_capable = false;
ufshcd_release(hba);
out:
+ if (hba->dev_info.b_rpm_dev_flush_capable) {
+ schedule_delayed_work(&hba->rpm_dev_flush_recheck_work,
+ msecs_to_jiffies(RPM_DEV_FLUSH_RECHECK_WORK_DELAY_MS));
+ }
+
hba->pm_op_in_progress = 0;
+
if (ret)
ufshcd_update_reg_hist(&hba->ufs_stats.suspend_err, (u32)ret);
return ret;
@@ -7944,9 +8685,7 @@
goto out;
/* enable the host irq as host controller would be active soon */
- ret = ufshcd_enable_irq(hba);
- if (ret)
- goto disable_irq_and_vops_clks;
+ ufshcd_enable_irq(hba);
ret = ufshcd_vreg_set_hpm(hba);
if (ret)
@@ -7963,14 +8702,21 @@
if (ufshcd_is_link_hibern8(hba)) {
ret = ufshcd_uic_hibern8_exit(hba);
- if (!ret)
+ if (!ret) {
ufshcd_set_link_active(hba);
- else
+ } else {
+ dev_err(hba->dev, "%s: hibern8 exit failed %d\n",
+ __func__, ret);
goto vendor_suspend;
+ }
} else if (ufshcd_is_link_off(hba)) {
- ret = ufshcd_host_reset_and_restore(hba);
/*
- * ufshcd_host_reset_and_restore() should have already
+ * A full initialization of the host and the device is
+ * required since the link was put to off during suspend.
+ */
+ ret = ufshcd_reset_and_restore(hba);
+ /*
+ * ufshcd_reset_and_restore() should have already
* set the link state as active
*/
if (ret || !ufshcd_is_link_active(hba))
@@ -8000,6 +8746,11 @@
/* Enable Auto-Hibernate if configured */
ufshcd_auto_hibern8_enable(hba);
+ if (hba->dev_info.b_rpm_dev_flush_capable) {
+ hba->dev_info.b_rpm_dev_flush_capable = false;
+ cancel_delayed_work(&hba->rpm_dev_flush_recheck_work);
+ }
+
/* Schedule clock gating in case of no access to UFS device yet */
ufshcd_release(hba);
@@ -8016,6 +8767,11 @@
if (hba->clk_scaling.is_allowed)
ufshcd_suspend_clkscaling(hba);
ufshcd_setup_clocks(hba, false);
+ if (ufshcd_is_clkgating_allowed(hba)) {
+ hba->clk_gating.state = CLKS_OFF;
+ trace_ufshcd_clk_gating(dev_name(hba->dev),
+ hba->clk_gating.state);
+ }
out:
hba->pm_op_in_progress = 0;
if (ret)
@@ -8039,10 +8795,14 @@
if (!hba || !hba->is_powered)
return 0;
+ cancel_delayed_work_sync(&hba->rpm_dev_flush_recheck_work);
+
if ((ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) ==
hba->curr_dev_pwr_mode) &&
(ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) ==
- hba->uic_link_state))
+ hba->uic_link_state) &&
+ pm_runtime_suspended(hba->dev) &&
+ !hba->dev_info.b_rpm_dev_flush_capable)
goto out;
if (pm_runtime_suspended(hba->dev)) {
@@ -8220,9 +8980,10 @@
blk_mq_free_tag_set(&hba->tmf_tag_set);
blk_cleanup_queue(hba->cmd_queue);
scsi_remove_host(hba->host);
+ destroy_workqueue(hba->eh_wq);
/* disable interrupts */
ufshcd_disable_intr(hba, hba->intr_mask);
- ufshcd_hba_stop(hba, true);
+ ufshcd_hba_stop(hba);
ufshcd_exit_clk_scaling(hba);
ufshcd_exit_clk_gating(hba);
@@ -8238,6 +8999,7 @@
*/
void ufshcd_dealloc_host(struct ufs_hba *hba)
{
+ ufshcd_crypto_destroy_keyslot_manager(hba);
scsi_host_put(hba->host);
}
EXPORT_SYMBOL_GPL(ufshcd_dealloc_host);
@@ -8321,6 +9083,14 @@
int err;
struct Scsi_Host *host = hba->host;
struct device *dev = hba->dev;
+ char eh_wq_name[sizeof("ufs_eh_wq_00")];
+
+ /*
+ * dev_set_drvdata() must be called before any callbacks are registered
+ * that use dev_get_drvdata() (frequency scaling, clock scaling, hwmon,
+ * sysfs).
+ */
+ dev_set_drvdata(dev, hba);
if (!mmio_base) {
dev_err(hba->dev,
@@ -8331,13 +9101,16 @@
hba->mmio_base = mmio_base;
hba->irq = irq;
+ hba->vps = &ufs_hba_vps;
err = ufshcd_hba_init(hba);
if (err)
goto out_error;
/* Read capabilities registers */
- ufshcd_hba_capabilities(hba);
+ err = ufshcd_hba_capabilities(hba);
+ if (err)
+ goto out_disable;
/* Get UFS version supported by the controller */
hba->ufs_version = ufshcd_get_ufs_version(hba);
@@ -8379,6 +9152,15 @@
hba->max_pwr_info.is_valid = false;
/* Initialize work queues */
+ snprintf(eh_wq_name, sizeof(eh_wq_name), "ufs_eh_wq_%d",
+ hba->host->host_no);
+ hba->eh_wq = create_singlethread_workqueue(eh_wq_name);
+ if (!hba->eh_wq) {
+ dev_err(hba->dev, "%s: failed to create eh workqueue\n",
+ __func__);
+ err = -ENOMEM;
+ goto out_disable;
+ }
INIT_WORK(&hba->eh_work, ufshcd_err_handler);
INIT_WORK(&hba->eeh_work, ufshcd_exception_event_handler);
@@ -8443,10 +9225,18 @@
err = PTR_ERR(hba->tmf_queue);
goto free_tmf_tag_set;
}
+ hba->tmf_rqs = devm_kcalloc(hba->dev, hba->nutmrs,
+ sizeof(*hba->tmf_rqs), GFP_KERNEL);
+ if (!hba->tmf_rqs) {
+ err = -ENOMEM;
+ goto free_tmf_queue;
+ }
/* Reset the attached device */
ufshcd_vops_device_reset(hba);
+ ufshcd_init_crypto(hba);
+
/* Host controller enable */
err = ufshcd_hba_enable(hba);
if (err) {
@@ -8468,6 +9258,9 @@
UFS_SLEEP_PWR_MODE,
UIC_LINK_HIBERN8_STATE);
+ INIT_DELAYED_WORK(&hba->rpm_dev_flush_recheck_work,
+ ufshcd_rpm_dev_flush_recheck_work);
+
/* Set the default auto-hiberate idle timer value to 150 ms */
if (ufshcd_is_auto_hibern8_supported(hba) && !hba->ahit) {
hba->ahit = FIELD_PREP(UFSHCI_AHIBERN8_TIMER_MASK, 150) |
@@ -8501,6 +9294,7 @@
exit_gating:
ufshcd_exit_clk_scaling(hba);
ufshcd_exit_clk_gating(hba);
+ destroy_workqueue(hba->eh_wq);
out_disable:
hba->is_irq_enabled = false;
ufshcd_hba_exit(hba);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 92ef6e6..35dd519 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -1,37 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Universal Flash Storage Host controller driver
- *
- * This code is based on drivers/scsi/ufs/ufshcd.h
* Copyright (C) 2011-2013 Samsung India Software Operations
* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* Authors:
* Santosh Yaraganavi <santosh.sy@samsung.com>
* Vinayak Holikatti <h.vinayak@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * See the COPYING file in the top-level directory or visit
- * <http://www.gnu.org/licenses/gpl-2.0.html>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * This program is provided "AS IS" and "WITH ALL FAULTS" and
- * without warranty of any kind. You are solely responsible for
- * determining the appropriateness of using and distributing
- * the program and assume all risks associated with your exercise
- * of rights with respect to the program, including but not limited
- * to infringement of third party rights, the risks and costs of
- * program errors, damage to or loss of data, programs or equipment,
- * and unavailability or interruption of operations. Under no
- * circumstances will the contributor of this Program be liable for
- * any damages of any kind arising from your use or distribution of
- * this program.
*/
#ifndef _UFSHCD_H
@@ -56,6 +31,8 @@
#include <linux/completion.h>
#include <linux/regulator/consumer.h>
#include <linux/bitfield.h>
+#include <linux/devfreq.h>
+#include <linux/keyslot-manager.h>
#include "unipro.h"
#include <asm/irq.h>
@@ -68,6 +45,7 @@
#include <scsi/scsi_eh.h>
#include "ufs.h"
+#include "ufs_quirks.h"
#include "ufshci.h"
#define UFSHCD "ufshcd"
@@ -87,7 +65,6 @@
* @argument2: UIC command argument 2
* @argument3: UIC command argument 3
* @cmd_active: Indicate if UIC command is outstanding
- * @result: UIC command result
* @done: UIC command completion
*/
struct uic_command {
@@ -96,7 +73,6 @@
u32 argument2;
u32 argument3;
int cmd_active;
- int result;
struct completion done;
};
@@ -116,6 +92,7 @@
UIC_LINK_OFF_STATE = 0, /* Link powered down or disabled */
UIC_LINK_ACTIVE_STATE = 1, /* Link is in Fast/Slow/Sleep state */
UIC_LINK_HIBERN8_STATE = 2, /* Link is in Hibernate state */
+ UIC_LINK_BROKEN_STATE = 3, /* Link is in broken state */
};
#define ufshcd_is_link_off(hba) ((hba)->uic_link_state == UIC_LINK_OFF_STATE)
@@ -123,11 +100,28 @@
UIC_LINK_ACTIVE_STATE)
#define ufshcd_is_link_hibern8(hba) ((hba)->uic_link_state == \
UIC_LINK_HIBERN8_STATE)
+#define ufshcd_is_link_broken(hba) ((hba)->uic_link_state == \
+ UIC_LINK_BROKEN_STATE)
#define ufshcd_set_link_off(hba) ((hba)->uic_link_state = UIC_LINK_OFF_STATE)
#define ufshcd_set_link_active(hba) ((hba)->uic_link_state = \
UIC_LINK_ACTIVE_STATE)
#define ufshcd_set_link_hibern8(hba) ((hba)->uic_link_state = \
UIC_LINK_HIBERN8_STATE)
+#define ufshcd_set_link_broken(hba) ((hba)->uic_link_state = \
+ UIC_LINK_BROKEN_STATE)
+
+#define ufshcd_set_ufs_dev_active(h) \
+ ((h)->curr_dev_pwr_mode = UFS_ACTIVE_PWR_MODE)
+#define ufshcd_set_ufs_dev_sleep(h) \
+ ((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE)
+#define ufshcd_set_ufs_dev_poweroff(h) \
+ ((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE)
+#define ufshcd_is_ufs_dev_active(h) \
+ ((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE)
+#define ufshcd_is_ufs_dev_sleep(h) \
+ ((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE)
+#define ufshcd_is_ufs_dev_poweroff(h) \
+ ((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE)
/*
* UFS Power management levels.
@@ -168,6 +162,8 @@
* @intr_cmd: Interrupt command (doesn't participate in interrupt aggregation)
* @issue_time_stamp: time stamp for debug purposes
* @compl_time_stamp: time stamp for statistics
+ * @crypto_key_slot: the key slot to use for inline crypto (-1 if none)
+ * @data_unit_num: the data unit number for the first block for inline crypto
* @req_abort_skip: skip request abort task flag
*/
struct ufshcd_lrb {
@@ -192,6 +188,10 @@
bool intr_cmd;
ktime_t issue_time_stamp;
ktime_t compl_time_stamp;
+#ifdef CONFIG_SCSI_UFS_CRYPTO
+ int crypto_key_slot;
+ u64 data_unit_num;
+#endif
bool req_abort_skip;
};
@@ -221,16 +221,6 @@
struct ufs_query query;
};
-struct ufs_desc_size {
- int dev_desc;
- int pwr_desc;
- int geom_desc;
- int interc_desc;
- int unit_desc;
- int conf_desc;
- int hlth_desc;
-};
-
/**
* struct ufs_clk_info - UFS clock related info
* @list: list headed by hba->clk_list_head
@@ -239,6 +229,8 @@
* @max_freq: maximum frequency supported by the clock
* @min_freq: min frequency that can be used for clock scaling
* @curr_freq: indicates the current frequency that it is set to
+ * @keep_link_active: indicates that the clk should not be disabled if
+ link is active
* @enabled: variable to check against multiple enable/disable
*/
struct ufs_clk_info {
@@ -248,6 +240,7 @@
u32 max_freq;
u32 min_freq;
u32 curr_freq;
+ bool keep_link_active;
bool enabled;
};
@@ -298,6 +291,7 @@
* @dbg_register_dump: used to dump controller debug information
* @phy_initialization: used to initialize phys
* @device_reset: called to issue a reset pulse on the UFS device
+ * @program_key: program or evict an inline encryption key
*/
struct ufs_hba_variant_ops {
const char *name;
@@ -321,12 +315,18 @@
void (*setup_task_mgmt)(struct ufs_hba *, int, u8);
void (*hibern8_notify)(struct ufs_hba *, enum uic_cmd_dme,
enum ufs_notify_change_status);
- int (*apply_dev_quirks)(struct ufs_hba *, struct ufs_dev_desc *);
+ int (*apply_dev_quirks)(struct ufs_hba *hba);
+ void (*fixup_dev_quirks)(struct ufs_hba *hba);
int (*suspend)(struct ufs_hba *, enum ufs_pm_op);
int (*resume)(struct ufs_hba *, enum ufs_pm_op);
void (*dbg_register_dump)(struct ufs_hba *hba);
int (*phy_initialization)(struct ufs_hba *);
- void (*device_reset)(struct ufs_hba *hba);
+ int (*device_reset)(struct ufs_hba *hba);
+ void (*config_scaling_param)(struct ufs_hba *hba,
+ struct devfreq_dev_profile *profile,
+ void *data);
+ int (*program_key)(struct ufs_hba *hba,
+ const union ufs_crypto_cfg_entry *cfg, int slot);
};
/* clock gating state */
@@ -392,7 +392,7 @@
struct ufs_clk_scaling {
int active_reqs;
unsigned long tot_busy_t;
- unsigned long window_start_t;
+ ktime_t window_start_t;
ktime_t busy_start_t;
struct device_attribute enable_attr;
struct ufs_saved_pwr_info saved_pwr_info;
@@ -404,15 +404,6 @@
bool is_suspended;
};
-/**
- * struct ufs_init_prefetch - contains data that is pre-fetched once during
- * initialization
- * @icc_level: icc level which was read during initialization
- */
-struct ufs_init_prefetch {
- u32 icc_level;
-};
-
#define UFS_ERR_REG_HIST_LENGTH 8
/**
* struct ufs_err_reg_hist - keeps history of errors
@@ -428,6 +419,8 @@
/**
* struct ufs_stats - keeps usage/err statistics
+ * @last_intr_status: record the last interrupt status.
+ * @last_intr_ts: record the last interrupt timestamp.
* @hibern8_exit_cnt: Counter to keep track of number of exits,
* reset this after link-startup.
* @last_hibern8_exit_tstamp: Set time after the hibern8 exit.
@@ -447,6 +440,9 @@
* @tsk_abort: tracks task abort events
*/
struct ufs_stats {
+ u32 last_intr_status;
+ ktime_t last_intr_ts;
+
u32 hibern8_exit_cnt;
ktime_t last_hibern8_exit_tstamp;
@@ -470,6 +466,156 @@
struct ufs_err_reg_hist task_abort;
};
+enum ufshcd_quirks {
+ /* Interrupt aggregation support is broken */
+ UFSHCD_QUIRK_BROKEN_INTR_AGGR = 1 << 0,
+
+ /*
+ * delay before each dme command is required as the unipro
+ * layer has shown instabilities
+ */
+ UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS = 1 << 1,
+
+ /*
+ * If UFS host controller is having issue in processing LCC (Line
+ * Control Command) coming from device then enable this quirk.
+ * When this quirk is enabled, host controller driver should disable
+ * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE
+ * attribute of device to 0).
+ */
+ UFSHCD_QUIRK_BROKEN_LCC = 1 << 2,
+
+ /*
+ * The attribute PA_RXHSUNTERMCAP specifies whether or not the
+ * inbound Link supports unterminated line in HS mode. Setting this
+ * attribute to 1 fixes moving to HS gear.
+ */
+ UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP = 1 << 3,
+
+ /*
+ * This quirk needs to be enabled if the host controller only allows
+ * accessing the peer dme attributes in AUTO mode (FAST AUTO or
+ * SLOW AUTO).
+ */
+ UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE = 1 << 4,
+
+ /*
+ * This quirk needs to be enabled if the host controller doesn't
+ * advertise the correct version in UFS_VER register. If this quirk
+ * is enabled, standard UFS host driver will call the vendor specific
+ * ops (get_ufs_hci_version) to get the correct version.
+ */
+ UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION = 1 << 5,
+
+ /*
+ * Clear handling for transfer/task request list is just opposite.
+ */
+ UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR = 1 << 6,
+
+ /*
+ * This quirk needs to be enabled if host controller doesn't allow
+ * that the interrupt aggregation timer and counter are reset by s/w.
+ */
+ UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR = 1 << 7,
+
+ /*
+ * This quirks needs to be enabled if host controller cannot be
+ * enabled via HCE register.
+ */
+ UFSHCI_QUIRK_BROKEN_HCE = 1 << 8,
+
+ /*
+ * This quirk needs to be enabled if the host controller regards
+ * resolution of the values of PRDTO and PRDTL in UTRD as byte.
+ */
+ UFSHCD_QUIRK_PRDT_BYTE_GRAN = 1 << 9,
+
+ /*
+ * This quirk needs to be enabled if the host controller reports
+ * OCS FATAL ERROR with device error through sense data
+ */
+ UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR = 1 << 10,
+
+ /*
+ * This quirk needs to be enabled if the host controller has
+ * auto-hibernate capability but it doesn't work.
+ */
+ UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8 = 1 << 11,
+
+ /*
+ * This quirk needs to disable manual flush for write booster
+ */
+ UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL = 1 << 12,
+
+ /*
+ * This quirk needs to disable unipro timeout values
+ * before power mode change
+ */
+ UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING = 1 << 13,
+
+ /*
+ * This quirk allows only sg entries aligned with page size.
+ */
+ UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE = 1 << 14,
+};
+
+enum ufshcd_caps {
+ /* Allow dynamic clk gating */
+ UFSHCD_CAP_CLK_GATING = 1 << 0,
+
+ /* Allow hiberb8 with clk gating */
+ UFSHCD_CAP_HIBERN8_WITH_CLK_GATING = 1 << 1,
+
+ /* Allow dynamic clk scaling */
+ UFSHCD_CAP_CLK_SCALING = 1 << 2,
+
+ /* Allow auto bkops to enabled during runtime suspend */
+ UFSHCD_CAP_AUTO_BKOPS_SUSPEND = 1 << 3,
+
+ /*
+ * This capability allows host controller driver to use the UFS HCI's
+ * interrupt aggregation capability.
+ * CAUTION: Enabling this might reduce overall UFS throughput.
+ */
+ UFSHCD_CAP_INTR_AGGR = 1 << 4,
+
+ /*
+ * This capability allows the device auto-bkops to be always enabled
+ * except during suspend (both runtime and suspend).
+ * Enabling this capability means that device will always be allowed
+ * to do background operation when it's active but it might degrade
+ * the performance of ongoing read/write operations.
+ */
+ UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND = 1 << 5,
+
+ /*
+ * This capability allows host controller driver to automatically
+ * enable runtime power management by itself instead of waiting
+ * for userspace to control the power management.
+ */
+ UFSHCD_CAP_RPM_AUTOSUSPEND = 1 << 6,
+
+ /*
+ * This capability allows the host controller driver to turn-on
+ * WriteBooster, if the underlying device supports it and is
+ * provisioned to be used. This would increase the write performance.
+ */
+ UFSHCD_CAP_WB_EN = 1 << 7,
+
+ /*
+ * This capability allows the host controller driver to use the
+ * inline crypto engine, if it is present
+ */
+ UFSHCD_CAP_CRYPTO = 1 << 8,
+};
+
+struct ufs_hba_variant_params {
+ struct devfreq_dev_profile devfreq_profile;
+ struct devfreq_simple_ondemand_data ondemand_data;
+ u16 hba_enable_delay_us;
+ u32 wb_flush_threshold;
+};
+
/**
* struct ufs_hba - per adapter private structure
* @mmio_base: UFSHCI base register address
@@ -502,14 +648,15 @@
* @intr_mask: Interrupt Mask Bits
* @ee_ctrl_mask: Exception event control mask
* @is_powered: flag to check if HBA is powered
- * @is_init_prefetch: flag to check if data was pre-fetched in initialization
- * @init_prefetch_data: data pre-fetched during initialization
+ * @eh_wq: Workqueue that eh_work works on
* @eh_work: Worker to handle UFS errors that require s/w attention
* @eeh_work: Worker to handle exception events
* @errors: HBA errors
* @uic_error: UFS interconnect layer error status
* @saved_err: sticky error mask
* @saved_uic_err: sticky UIC error mask
+ * @force_reset: flag to force eh_work perform a full reset
+ * @force_pmc: flag to force a power mode change
* @silence_err_logs: flag to silence error logs
* @dev_cmd: ufs device management command information
* @last_dme_cmd_tstamp: time stamp of the last completed DME command
@@ -523,6 +670,10 @@
* @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for
* device is known or not.
* @scsi_block_reqs_cnt: reference counting for scsi block requests
+ * @crypto_capabilities: Content of crypto capabilities register (0x100)
+ * @crypto_cap_array: Array of crypto capabilities
+ * @crypto_cfg_register: Start of the crypto cfg array
+ * @ksm: the keyslot manager tied to this hba
*/
struct ufs_hba {
void __iomem *mmio_base;
@@ -545,6 +696,7 @@
* "UFS device" W-LU.
*/
struct scsi_device *sdev_ufs_device;
+ struct scsi_device *sdev_rpmb;
enum ufs_dev_pwr_mode curr_dev_pwr_mode;
enum uic_link_state uic_link_state;
@@ -569,73 +721,12 @@
int nutmrs;
u32 ufs_version;
const struct ufs_hba_variant_ops *vops;
+ struct ufs_hba_variant_params *vps;
void *priv;
unsigned int irq;
bool is_irq_enabled;
enum ufs_ref_clk_freq dev_ref_clk_freq;
- /* Interrupt aggregation support is broken */
- #define UFSHCD_QUIRK_BROKEN_INTR_AGGR 0x1
-
- /*
- * delay before each dme command is required as the unipro
- * layer has shown instabilities
- */
- #define UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS 0x2
-
- /*
- * If UFS host controller is having issue in processing LCC (Line
- * Control Command) coming from device then enable this quirk.
- * When this quirk is enabled, host controller driver should disable
- * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE
- * attribute of device to 0).
- */
- #define UFSHCD_QUIRK_BROKEN_LCC 0x4
-
- /*
- * The attribute PA_RXHSUNTERMCAP specifies whether or not the
- * inbound Link supports unterminated line in HS mode. Setting this
- * attribute to 1 fixes moving to HS gear.
- */
- #define UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP 0x8
-
- /*
- * This quirk needs to be enabled if the host contoller only allows
- * accessing the peer dme attributes in AUTO mode (FAST AUTO or
- * SLOW AUTO).
- */
- #define UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE 0x10
-
- /*
- * This quirk needs to be enabled if the host contoller doesn't
- * advertise the correct version in UFS_VER register. If this quirk
- * is enabled, standard UFS host driver will call the vendor specific
- * ops (get_ufs_hci_version) to get the correct version.
- */
- #define UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION 0x20
-
- /*
- * This quirk needs to be enabled if the host contoller regards
- * resolution of the values of PRDTO and PRDTL in UTRD as byte.
- */
- #define UFSHCD_QUIRK_PRDT_BYTE_GRAN 0x80
-
- /*
- * Clear handling for transfer/task request list is just opposite.
- */
- #define UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR 0x100
-
- /*
- * This quirk needs to be enabled if host controller doesn't allow
- * that the interrupt aggregation timer and counter are reset by s/w.
- */
- #define UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR 0x200
-
- /*
- * This quirks needs to be enabled if host controller cannot be
- * enabled via HCE register.
- */
- #define UFSHCI_QUIRK_BROKEN_HCE 0x400
unsigned int quirks; /* Deviations from standard UFSHCI spec. */
/* Device deviations from standard UFS device spec. */
@@ -643,6 +734,7 @@
struct blk_mq_tag_set tmf_tag_set;
struct request_queue *tmf_queue;
+ struct request **tmf_rqs;
struct uic_command *active_uic_cmd;
struct mutex uic_cmd_mutex;
@@ -653,10 +745,9 @@
u32 intr_mask;
u16 ee_ctrl_mask;
bool is_powered;
- bool is_init_prefetch;
- struct ufs_init_prefetch init_prefetch_data;
/* Work Queues */
+ struct workqueue_struct *eh_wq;
struct work_struct eh_work;
struct work_struct eeh_work;
@@ -666,6 +757,8 @@
u32 saved_err;
u32 saved_uic_err;
struct ufs_stats ufs_stats;
+ bool force_reset;
+ bool force_pmc;
bool silence_err_logs;
/* Device management request data */
@@ -691,28 +784,6 @@
struct ufs_clk_gating clk_gating;
/* Control to enable/disable host capabilities */
u32 caps;
- /* Allow dynamic clk gating */
-#define UFSHCD_CAP_CLK_GATING (1 << 0)
- /* Allow hiberb8 with clk gating */
-#define UFSHCD_CAP_HIBERN8_WITH_CLK_GATING (1 << 1)
- /* Allow dynamic clk scaling */
-#define UFSHCD_CAP_CLK_SCALING (1 << 2)
- /* Allow auto bkops to enabled during runtime suspend */
-#define UFSHCD_CAP_AUTO_BKOPS_SUSPEND (1 << 3)
- /*
- * This capability allows host controller driver to use the UFS HCI's
- * interrupt aggregation capability.
- * CAUTION: Enabling this might reduce overall UFS throughput.
- */
-#define UFSHCD_CAP_INTR_AGGR (1 << 4)
- /*
- * This capability allows the device auto-bkops to be always enabled
- * except during suspend (both runtime and suspend).
- * Enabling this capability means that device will always be allowed
- * to do background operation when it's active but it might degrade
- * the performance of ongoing read/write operations.
- */
-#define UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND (1 << 5)
struct devfreq *devfreq;
struct ufs_clk_scaling clk_scaling;
@@ -722,11 +793,21 @@
bool is_urgent_bkops_lvl_checked;
struct rw_semaphore clk_scaling_lock;
- struct ufs_desc_size desc_size;
+ unsigned char desc_size[QUERY_DESC_IDN_MAX];
atomic_t scsi_block_reqs_cnt;
struct device bsg_dev;
struct request_queue *bsg_queue;
+ bool wb_buf_flush_enabled;
+ bool wb_enabled;
+ struct delayed_work rpm_dev_flush_recheck_work;
+
+#ifdef CONFIG_SCSI_UFS_CRYPTO
+ union ufs_crypto_capabilities crypto_capabilities;
+ union ufs_crypto_cap_entry *crypto_cap_array;
+ u32 crypto_cfg_register;
+ struct blk_keyslot_manager ksm;
+#endif
};
/* Returns true if clocks can be gated. Otherwise false */
@@ -746,6 +827,10 @@
{
return hba->caps & UFSHCD_CAP_AUTO_BKOPS_SUSPEND;
}
+static inline bool ufshcd_is_rpm_autosuspend_allowed(struct ufs_hba *hba)
+{
+ return hba->caps & UFSHCD_CAP_RPM_AUTOSUSPEND;
+}
static inline bool ufshcd_is_intr_aggr_allowed(struct ufs_hba *hba)
{
@@ -763,7 +848,8 @@
static inline bool ufshcd_is_auto_hibern8_supported(struct ufs_hba *hba)
{
- return (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT);
+ return (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT) &&
+ !(hba->quirks & UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8);
}
static inline bool ufshcd_is_auto_hibern8_enabled(struct ufs_hba *hba)
@@ -771,6 +857,11 @@
return FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, hba->ahit) ? true : false;
}
+static inline bool ufshcd_is_wb_allowed(struct ufs_hba *hba)
+{
+ return hba->caps & UFSHCD_CAP_WB_EN;
+}
+
#define ufshcd_writel(hba, val, reg) \
writel((val), (hba)->mmio_base + (reg))
#define ufshcd_readl(hba, reg) \
@@ -795,12 +886,19 @@
int ufshcd_alloc_host(struct device *, struct ufs_hba **);
void ufshcd_dealloc_host(struct ufs_hba *);
+int ufshcd_hba_enable(struct ufs_hba *hba);
int ufshcd_init(struct ufs_hba * , void __iomem * , unsigned int);
+int ufshcd_link_recovery(struct ufs_hba *hba);
+int ufshcd_make_hba_operational(struct ufs_hba *hba);
void ufshcd_remove(struct ufs_hba *);
+int ufshcd_uic_hibern8_exit(struct ufs_hba *hba);
+void ufshcd_delay_us(unsigned long us, unsigned long tolerance);
int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
u32 val, unsigned long interval_us,
- unsigned long timeout_ms, bool can_sleep);
+ unsigned long timeout_ms);
void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba, struct clk *refclk);
+void ufshcd_update_reg_hist(struct ufs_err_reg_hist *reg_hist,
+ u32 reg);
static inline void check_upiu_size(void)
{
@@ -834,6 +932,13 @@
return hba->caps & UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND;
}
+static inline u8 ufshcd_wb_get_query_index(struct ufs_hba *hba)
+{
+ if (hba->dev_info.b_wb_buffer_type == WB_BUF_MODE_LU_DEDICATED)
+ return hba->dev_info.wb_dedicated_lu;
+ return 0;
+}
+
extern int ufshcd_runtime_suspend(struct ufs_hba *hba);
extern int ufshcd_runtime_resume(struct ufs_hba *hba);
extern int ufshcd_runtime_idle(struct ufs_hba *hba);
@@ -901,6 +1006,11 @@
pwr_info->pwr_tx == FASTAUTO_MODE);
}
+static inline int ufshcd_disable_host_tx_lcc(struct ufs_hba *hba)
+{
+ return ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0);
+}
+
/* Expose Query-Request API */
int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
enum query_opcode opcode,
@@ -916,10 +1026,11 @@
int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
enum attr_idn idn, u8 index, u8 selector, u32 *attr_val);
int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
- enum flag_idn idn, bool *flag_res);
+ enum flag_idn idn, u8 index, bool *flag_res);
void ufshcd_auto_hibern8_enable(struct ufs_hba *hba);
-
+void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit);
+void ufshcd_fixup_dev_quirks(struct ufs_hba *hba, struct ufs_dev_fix *fixups);
#define SD_ASCII_STD true
#define SD_RAW false
int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index,
@@ -928,8 +1039,8 @@
int ufshcd_hold(struct ufs_hba *hba, bool async);
void ufshcd_release(struct ufs_hba *hba);
-int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id,
- int *desc_length);
+void ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id,
+ int *desc_length);
u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba);
@@ -1047,14 +1158,19 @@
return hba->vops->hibern8_notify(hba, cmd, status);
}
-static inline int ufshcd_vops_apply_dev_quirks(struct ufs_hba *hba,
- struct ufs_dev_desc *card)
+static inline int ufshcd_vops_apply_dev_quirks(struct ufs_hba *hba)
{
if (hba->vops && hba->vops->apply_dev_quirks)
- return hba->vops->apply_dev_quirks(hba, card);
+ return hba->vops->apply_dev_quirks(hba);
return 0;
}
+static inline void ufshcd_vops_fixup_dev_quirks(struct ufs_hba *hba)
+{
+ if (hba->vops && hba->vops->fixup_dev_quirks)
+ hba->vops->fixup_dev_quirks(hba);
+}
+
static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op)
{
if (hba->vops && hba->vops->suspend)
@@ -1079,8 +1195,27 @@
static inline void ufshcd_vops_device_reset(struct ufs_hba *hba)
{
- if (hba->vops && hba->vops->device_reset)
- hba->vops->device_reset(hba);
+ if (hba->vops && hba->vops->device_reset) {
+ int err = hba->vops->device_reset(hba);
+
+ if (!err) {
+ ufshcd_set_ufs_dev_active(hba);
+ if (ufshcd_is_wb_allowed(hba)) {
+ hba->wb_enabled = false;
+ hba->wb_buf_flush_enabled = false;
+ }
+ }
+ if (err != -EOPNOTSUPP)
+ ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, err);
+ }
+}
+
+static inline void ufshcd_vops_config_scaling_param(struct ufs_hba *hba,
+ struct devfreq_dev_profile
+ *profile, void *data)
+{
+ if (hba->vops && hba->vops->config_scaling_param)
+ hba->vops->config_scaling_param(hba, profile, data);
}
extern struct ufs_pm_lvl_states ufs_pm_lvl_states[];
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index c2961d3..1d99922 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -1,36 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Universal Flash Storage Host controller driver
- *
- * This code is based on drivers/scsi/ufs/ufshci.h
* Copyright (C) 2011-2013 Samsung India Software Operations
*
* Authors:
* Santosh Yaraganavi <santosh.sy@samsung.com>
* Vinayak Holikatti <h.vinayak@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * See the COPYING file in the top-level directory or visit
- * <http://www.gnu.org/licenses/gpl-2.0.html>
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * This program is provided "AS IS" and "WITH ALL FAULTS" and
- * without warranty of any kind. You are solely responsible for
- * determining the appropriateness of using and distributing
- * the program and assume all risks associated with your exercise
- * of rights with respect to the program, including but not limited
- * to infringement of third party rights, the risks and costs of
- * program errors, damage to or loss of data, programs or equipment,
- * and unavailability or interruption of operations. Under no
- * circumstances will the contributor of this Program be liable for
- * any damages of any kind arising from your use or distribution of
- * this program.
*/
#ifndef _UFSHCI_H
@@ -90,6 +65,7 @@
MASK_64_ADDRESSING_SUPPORT = 0x01000000,
MASK_OUT_OF_ORDER_DATA_DELIVERY_SUPPORT = 0x02000000,
MASK_UIC_DME_TEST_MODE_SUPPORT = 0x04000000,
+ MASK_CRYPTO_SUPPORT = 0x10000000,
};
#define UFS_MASK(mask, offset) ((mask) << (offset))
@@ -143,6 +119,7 @@
#define DEVICE_FATAL_ERROR 0x800
#define CONTROLLER_FATAL_ERROR 0x10000
#define SYSTEM_BUS_FATAL_ERROR 0x20000
+#define CRYPTO_ENGINE_FATAL_ERROR 0x40000
#define UFSHCD_UIC_HIBERN8_MASK (UIC_HIBERNATE_ENTER |\
UIC_HIBERNATE_EXIT)
@@ -155,11 +132,14 @@
#define UFSHCD_ERROR_MASK (UIC_ERROR |\
DEVICE_FATAL_ERROR |\
CONTROLLER_FATAL_ERROR |\
- SYSTEM_BUS_FATAL_ERROR)
+ SYSTEM_BUS_FATAL_ERROR |\
+ CRYPTO_ENGINE_FATAL_ERROR)
#define INT_FATAL_ERRORS (DEVICE_FATAL_ERROR |\
CONTROLLER_FATAL_ERROR |\
- SYSTEM_BUS_FATAL_ERROR)
+ SYSTEM_BUS_FATAL_ERROR |\
+ CRYPTO_ENGINE_FATAL_ERROR |\
+ UIC_LINK_LOST)
/* HCS - Host Controller Status 30h */
#define DEVICE_PRESENT 0x1
@@ -192,6 +172,7 @@
#define UIC_PHY_ADAPTER_LAYER_ERROR 0x80000000
#define UIC_PHY_ADAPTER_LAYER_ERROR_CODE_MASK 0x1F
#define UIC_PHY_ADAPTER_LAYER_LANE_ERR_MASK 0xF
+#define UIC_PHY_ADAPTER_LAYER_GENERIC_ERROR 0x10
/* UECDL - Host UIC Error Code Data Link Layer 3Ch */
#define UIC_DATA_LINK_LAYER_ERROR 0x80000000
@@ -318,6 +299,61 @@
INTERRUPT_MASK_ALL_VER_21 = 0x71FFF,
};
+/* CCAP - Crypto Capability 100h */
+union ufs_crypto_capabilities {
+ __le32 reg_val;
+ struct {
+ u8 num_crypto_cap;
+ u8 config_count;
+ u8 reserved;
+ u8 config_array_ptr;
+ };
+};
+
+enum ufs_crypto_key_size {
+ UFS_CRYPTO_KEY_SIZE_INVALID = 0x0,
+ UFS_CRYPTO_KEY_SIZE_128 = 0x1,
+ UFS_CRYPTO_KEY_SIZE_192 = 0x2,
+ UFS_CRYPTO_KEY_SIZE_256 = 0x3,
+ UFS_CRYPTO_KEY_SIZE_512 = 0x4,
+};
+
+enum ufs_crypto_alg {
+ UFS_CRYPTO_ALG_AES_XTS = 0x0,
+ UFS_CRYPTO_ALG_BITLOCKER_AES_CBC = 0x1,
+ UFS_CRYPTO_ALG_AES_ECB = 0x2,
+ UFS_CRYPTO_ALG_ESSIV_AES_CBC = 0x3,
+};
+
+/* x-CRYPTOCAP - Crypto Capability X */
+union ufs_crypto_cap_entry {
+ __le32 reg_val;
+ struct {
+ u8 algorithm_id;
+ u8 sdus_mask; /* Supported data unit size mask */
+ u8 key_size;
+ u8 reserved;
+ };
+};
+
+#define UFS_CRYPTO_CONFIGURATION_ENABLE (1 << 7)
+#define UFS_CRYPTO_KEY_MAX_SIZE 64
+/* x-CRYPTOCFG - Crypto Configuration X */
+union ufs_crypto_cfg_entry {
+ __le32 reg_val[32];
+ struct {
+ u8 crypto_key[UFS_CRYPTO_KEY_MAX_SIZE];
+ u8 data_unit_size;
+ u8 crypto_cap_idx;
+ u8 reserved_1;
+ u8 config_enable;
+ u8 reserved_multi_host;
+ u8 reserved_2;
+ u8 vsb[2];
+ u8 reserved_3[56];
+ };
+};
+
/*
* Request Descriptor Definitions
*/
@@ -339,6 +375,7 @@
UTP_NATIVE_UFS_COMMAND = 0x10000000,
UTP_DEVICE_MANAGEMENT_FUNCTION = 0x20000000,
UTP_REQ_DESC_INT_CMD = 0x01000000,
+ UTP_REQ_DESC_CRYPTO_ENABLE_CMD = 0x00800000,
};
/* UTP Transfer Request Data Direction (DD) */
@@ -358,6 +395,9 @@
OCS_PEER_COMM_FAILURE = 0x5,
OCS_ABORTED = 0x6,
OCS_FATAL_ERROR = 0x7,
+ OCS_DEVICE_FATAL_ERROR = 0x8,
+ OCS_INVALID_CRYPTO_CONFIG = 0x9,
+ OCS_GENERAL_CRYPTO_ERROR = 0xA,
OCS_INVALID_COMMAND_STATUS = 0x0F,
MASK_OCS = 0x0F,
};
diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h
index f539f87..f6b52ce 100644
--- a/drivers/scsi/ufs/unipro.h
+++ b/drivers/scsi/ufs/unipro.h
@@ -64,8 +64,25 @@
#define CFGRXOVR4 0x00E9
#define RXSQCTRL 0x00B5
#define CFGRXOVR6 0x00BF
+#define RX_HS_G1_SYNC_LENGTH_CAP 0x008B
+#define RX_HS_G1_PREP_LENGTH_CAP 0x008C
+#define RX_HS_G2_SYNC_LENGTH_CAP 0x0094
+#define RX_HS_G3_SYNC_LENGTH_CAP 0x0095
+#define RX_HS_G2_PREP_LENGTH_CAP 0x0096
+#define RX_HS_G3_PREP_LENGTH_CAP 0x0097
+#define RX_ADV_GRANULARITY_CAP 0x0098
+#define RX_MIN_ACTIVATETIME_CAP 0x008F
+#define RX_HIBERN8TIME_CAP 0x0092
+#define RX_ADV_HIBERN8TIME_CAP 0x0099
+#define RX_ADV_MIN_ACTIVATETIME_CAP 0x009A
+
#define is_mphy_tx_attr(attr) (attr < RX_MODE)
+#define RX_ADV_FINE_GRAN_STEP(x) ((((x) & 0x3) << 1) | 0x1)
+#define SYNC_LEN_FINE(x) ((x) & 0x3F)
+#define SYNC_LEN_COARSE(x) ((1 << 6) | ((x) & 0x3F))
+#define PREP_LEN(x) ((x) & 0xF)
+
#define RX_MIN_ACTIVATETIME_UNIT_US 100
#define HIBERN8TIME_UNIT_US 100
@@ -124,6 +141,7 @@
#define PA_PACPREQEOBTIMEOUT 0x1591
#define PA_HIBERN8TIME 0x15A7
#define PA_LOCALVERINFO 0x15A9
+#define PA_GRANULARITY 0x15AA
#define PA_TACTIVATE 0x15A8
#define PA_PACPFRAMECOUNT 0x15C0
#define PA_PACPERRORCOUNT 0x15C1
@@ -146,6 +164,12 @@
#define PA_SLEEPNOCONFIGTIME 0x15A2
#define PA_STALLNOCONFIGTIME 0x15A3
#define PA_SAVECONFIGTIME 0x15A4
+#define PA_TXHSADAPTTYPE 0x15D4
+
+/* Adpat type for PA_TXHSADAPTTYPE attribute */
+#define PA_REFRESH_ADAPT 0x00
+#define PA_INITIAL_ADAPT 0x01
+#define PA_NO_ADAPT 0x03
#define PA_TACTIVATE_TIME_UNIT_US 10
#define PA_HIBERN8_TIME_UNIT_US 100
@@ -161,6 +185,17 @@
/* PHY Adapter Protocol Constants */
#define PA_MAXDATALANES 4
+#define DL_FC0ProtectionTimeOutVal_Default 8191
+#define DL_TC0ReplayTimeOutVal_Default 65535
+#define DL_AFC0ReqTimeOutVal_Default 32767
+#define DL_FC1ProtectionTimeOutVal_Default 8191
+#define DL_TC1ReplayTimeOutVal_Default 65535
+#define DL_AFC1ReqTimeOutVal_Default 32767
+
+#define DME_LocalFC0ProtectionTimeOutVal 0xD041
+#define DME_LocalTC0ReplayTimeOutVal 0xD042
+#define DME_LocalAFC0ReqTimeOutVal 0xD043
+
/* PA power modes */
enum {
FAST_MODE = 1,
@@ -170,6 +205,9 @@
UNCHANGED = 7,
};
+#define PWRMODE_MASK 0xF
+#define PWRMODE_RX_OFFSET 4
+
/* PA TX/RX Frequency Series */
enum {
PA_HS_MODE_A = 1,
@@ -192,6 +230,7 @@
UFS_HS_G1, /* HS Gear 1 (default for reset) */
UFS_HS_G2, /* HS Gear 2 */
UFS_HS_G3, /* HS Gear 3 */
+ UFS_HS_G4, /* HS Gear 4 */
};
enum ufs_unipro_ver {
@@ -273,4 +312,19 @@
TRUE,
};
+/* CPort setting */
+#define E2EFC_ON (1 << 0)
+#define E2EFC_OFF (0 << 0)
+#define CSD_N_ON (0 << 1)
+#define CSD_N_OFF (1 << 1)
+#define CSV_N_ON (0 << 2)
+#define CSV_N_OFF (1 << 2)
+#define CPORT_DEF_FLAGS (CSV_N_OFF | CSD_N_OFF | E2EFC_OFF)
+
+/* CPort connection state */
+enum {
+ CPORT_IDLE = 0,
+ CPORT_CONNECTED,
+};
+
#endif /* _UNIPRO_H_ */
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index bfec84a..6dac58a 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -100,7 +100,7 @@
scsi_set_resid(sc, resid);
}
-/**
+/*
* virtscsi_complete_cmd - finish a scsi_cmd and invoke scsi_done
*
* Called with vq_lock held.
@@ -148,7 +148,7 @@
default:
scmd_printk(KERN_WARNING, sc, "Unknown response %d",
resp->response);
- /* fall through */
+ fallthrough;
case VIRTIO_SCSI_S_FAILURE:
set_host_byte(sc, DID_ERROR);
break;
@@ -284,7 +284,12 @@
switch (virtio32_to_cpu(vscsi->vdev, event->reason)) {
case VIRTIO_SCSI_EVT_RESET_RESCAN:
- scsi_add_device(shost, 0, target, lun);
+ if (lun == 0) {
+ scsi_scan_target(&shost->shost_gendev, 0, target,
+ SCAN_WILD_CARD, SCSI_SCAN_INITIAL);
+ } else {
+ scsi_add_device(shost, 0, target, lun);
+ }
break;
case VIRTIO_SCSI_EVT_RESET_REMOVED:
sdev = scsi_device_lookup(shost, 0, target, lun);
@@ -297,7 +302,7 @@
}
break;
default:
- pr_info("Unsupport virtio scsi event reason %x\n", event->reason);
+ pr_info("Unsupported virtio scsi event reason %x\n", event->reason);
}
}
@@ -350,6 +355,14 @@
if (result == 0 && inq_result[0] >> 5) {
/* PQ indicates the LUN is not attached */
scsi_remove_device(sdev);
+ } else if (host_byte(result) == DID_BAD_TARGET) {
+ /*
+ * If all LUNs of a virtio-scsi device are unplugged
+ * it will respond with BAD TARGET on any INQUIRY
+ * command.
+ * Remove the device in this case as well.
+ */
+ scsi_remove_device(sdev);
}
}
@@ -381,7 +394,7 @@
virtscsi_handle_param_change(vscsi, event);
break;
default:
- pr_err("Unsupport virtio scsi event %x\n", event->event);
+ pr_err("Unsupported virtio scsi event %x\n", event->event);
}
virtscsi_kick_event(vscsi, event_node);
}
@@ -742,19 +755,18 @@
.dma_boundary = UINT_MAX,
.map_queues = virtscsi_map_queues,
.track_queue_depth = 1,
- .force_blk_mq = 1,
};
#define virtscsi_config_get(vdev, fld) \
({ \
- typeof(((struct virtio_scsi_config *)0)->fld) __val; \
+ __virtio_native_type(struct virtio_scsi_config, fld) __val; \
virtio_cread(vdev, struct virtio_scsi_config, fld, &__val); \
__val; \
})
#define virtscsi_config_set(vdev, fld, val) \
do { \
- typeof(((struct virtio_scsi_config *)0)->fld) __val = (val); \
+ __virtio_native_type(struct virtio_scsi_config, fld) __val = (val); \
virtio_cwrite(vdev, struct virtio_scsi_config, fld, &__val); \
} while(0)
@@ -1003,14 +1015,10 @@
return 0;
error:
- if (virtscsi_cmd_pool) {
- mempool_destroy(virtscsi_cmd_pool);
- virtscsi_cmd_pool = NULL;
- }
- if (virtscsi_cmd_cache) {
- kmem_cache_destroy(virtscsi_cmd_cache);
- virtscsi_cmd_cache = NULL;
- }
+ mempool_destroy(virtscsi_cmd_pool);
+ virtscsi_cmd_pool = NULL;
+ kmem_cache_destroy(virtscsi_cmd_cache);
+ virtscsi_cmd_cache = NULL;
return ret;
}
diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c
index 0ac342b..7d51ff4 100644
--- a/drivers/scsi/vmw_pvscsi.c
+++ b/drivers/scsi/vmw_pvscsi.c
@@ -365,7 +365,7 @@
int segs = scsi_dma_map(cmd);
if (segs == -ENOMEM) {
- scmd_printk(KERN_ERR, cmd,
+ scmd_printk(KERN_DEBUG, cmd,
"vmw_pvscsi: Failed to map cmd sglist for DMA.\n");
return -ENOMEM;
} else if (segs > 1) {
@@ -392,7 +392,7 @@
ctx->dataPA = dma_map_single(&adapter->dev->dev, sg, bufflen,
cmd->sc_data_direction);
if (dma_mapping_error(&adapter->dev->dev, ctx->dataPA)) {
- scmd_printk(KERN_ERR, cmd,
+ scmd_printk(KERN_DEBUG, cmd,
"vmw_pvscsi: Failed to map direct data buffer for DMA.\n");
return -ENOMEM;
}
@@ -402,6 +402,17 @@
return 0;
}
+/*
+ * The device incorrectly doesn't clear the first byte of the sense
+ * buffer in some cases. We have to do it ourselves.
+ * Otherwise we run into trouble when SWIOTLB is forced.
+ */
+static void pvscsi_patch_sense(struct scsi_cmnd *cmd)
+{
+ if (cmd->sense_buffer)
+ cmd->sense_buffer[0] = 0;
+}
+
static void pvscsi_unmap_buffers(const struct pvscsi_adapter *adapter,
struct pvscsi_ctx *ctx)
{
@@ -544,6 +555,8 @@
cmd = ctx->cmd;
abort_cmp = ctx->abort_cmp;
pvscsi_unmap_buffers(adapter, ctx);
+ if (sdstat != SAM_STAT_CHECK_CONDITION)
+ pvscsi_patch_sense(cmd);
pvscsi_release_context(adapter, ctx);
if (abort_cmp) {
/*
@@ -578,9 +591,12 @@
* Commands like INQUIRY may transfer less data than
* requested by the initiator via bufflen. Set residual
* count to make upper layer aware of the actual amount
- * of data returned.
+ * of data returned. There are cases when controller
+ * returns zero dataLen with non zero data - do not set
+ * residual count in that case.
*/
- scsi_set_resid(cmd, scsi_bufflen(cmd) - e->dataLen);
+ if (e->dataLen && (e->dataLen < scsi_bufflen(cmd)))
+ scsi_set_resid(cmd, scsi_bufflen(cmd) - e->dataLen);
cmd->result = (DID_OK << 16);
break;
@@ -600,7 +616,7 @@
case BTSTAT_TAGREJECT:
case BTSTAT_BADMSG:
cmd->result = (DRIVER_INVALID << 24);
- /* fall through */
+ fallthrough;
case BTSTAT_HAHARDWARE:
case BTSTAT_INVPHASE:
@@ -718,7 +734,7 @@
cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE,
DMA_FROM_DEVICE);
if (dma_mapping_error(&adapter->dev->dev, ctx->sensePA)) {
- scmd_printk(KERN_ERR, cmd,
+ scmd_printk(KERN_DEBUG, cmd,
"vmw_pvscsi: Failed to map sense buffer for DMA.\n");
ctx->sensePA = 0;
return -ENOMEM;
@@ -879,6 +895,7 @@
scmd_printk(KERN_ERR, cmd,
"Forced reset on cmd %p\n", cmd);
pvscsi_unmap_buffers(adapter, ctx);
+ pvscsi_patch_sense(cmd);
pvscsi_release_context(adapter, ctx);
cmd->result = (DID_RESET << 16);
cmd->scsi_done(cmd);
@@ -900,7 +917,7 @@
use_msg = adapter->use_msg;
if (use_msg) {
- adapter->use_msg = 0;
+ adapter->use_msg = false;
spin_unlock_irqrestore(&adapter->hw_lock, flags);
/*
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index f81046f..87dafbc 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -1854,7 +1854,7 @@
case 1: --x;
break;
case 2: ++x;
- /* fall through */
+ fallthrough;
case 3: ++x;
}
return x;
diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c
index f0068e9..a25c938 100644
--- a/drivers/scsi/xen-scsifront.c
+++ b/drivers/scsi/xen-scsifront.c
@@ -233,12 +233,11 @@
return;
for (i = 0; i < shadow->nr_grants; i++) {
- if (unlikely(gnttab_query_foreign_access(shadow->gref[i]))) {
+ if (unlikely(!gnttab_try_end_foreign_access(shadow->gref[i]))) {
shost_printk(KERN_ALERT, info->host, KBUILD_MODNAME
"grant still in use by backend\n");
BUG();
}
- gnttab_end_foreign_access(shadow->gref[i], 0, 0UL);
}
kfree(shadow->sg);
@@ -1111,7 +1110,7 @@
case XenbusStateClosed:
if (dev->state == XenbusStateClosed)
break;
- /* fall through - Missed the backend's Closing state */
+ fallthrough; /* Missed the backend's Closing state */
case XenbusStateClosing:
scsifront_disconnect(info);
break;
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index 77bce20..7eac76c 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -89,7 +89,7 @@
struct gsc_irq gsc_irq;
u32 zalon_vers;
int error = -ENODEV;
- void __iomem *zalon = ioremap_nocache(dev->hpa.start, 4096);
+ void __iomem *zalon = ioremap(dev->hpa.start, 4096);
void __iomem *io_port = zalon + GSC_SCSI_ZALON_OFFSET;
static int unit = 0;
struct Scsi_Host *host;
diff --git a/drivers/scsi/zorro_esp.c b/drivers/scsi/zorro_esp.c
index a23a8e5..928c8ad 100644
--- a/drivers/scsi/zorro_esp.c
+++ b/drivers/scsi/zorro_esp.c
@@ -34,9 +34,9 @@
#include <linux/delay.h>
#include <linux/zorro.h>
#include <linux/slab.h>
+#include <linux/pgtable.h>
#include <asm/page.h>
-#include <asm/pgtable.h>
#include <asm/cacheflush.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
@@ -801,8 +801,7 @@
/* additional setup required for Fastlane */
if (zep->zorro3 && ent->driver_data == ZORRO_BLZ1230II) {
/* map full address space up to ESP base for DMA */
- zep->board_base = ioremap_nocache(board,
- FASTLANE_ESP_ADDR-1);
+ zep->board_base = ioremap(board, FASTLANE_ESP_ADDR - 1);
if (!zep->board_base) {
pr_err("Cannot allocate board address space\n");
err = -ENOMEM;
@@ -816,7 +815,7 @@
esp->ops = zdd->esp_ops;
if (ioaddr > 0xffffff)
- esp->regs = ioremap_nocache(ioaddr, 0x20);
+ esp->regs = ioremap(ioaddr, 0x20);
else
/* ZorroII address space remapped nocache by early startup */
esp->regs = ZTWO_VADDR(ioaddr);
@@ -842,8 +841,8 @@
* Only Fastlane Z3 for now - add switch for correct struct
* dma_registers size if adding any more
*/
- esp->dma_regs = ioremap_nocache(dmaaddr,
- sizeof(struct fastlane_dma_registers));
+ esp->dma_regs = ioremap(dmaaddr,
+ sizeof(struct fastlane_dma_registers));
} else
/* ZorroII address space remapped nocache by early startup */
esp->dma_regs = ZTWO_VADDR(dmaaddr);