SCSI misc on 20160727
This update includes the usual round of driver updates (fcoe, lpfc, ufs, qla2xxx, hisi_sas). The most important other change is removing the flag to allow non-blk_mq on a per host basis (it's unused); there is still a global module parameter for all of SCSI just in case. The rest are an assortment of minor fixes and typo updates. Signed-off-by: James Bottomley <jejb@linux.vnet.ibm.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJXmKE4AAoJEAVr7HOZEZN4Ph0P/0WbMd2+KF0PMcSmejEfZnYF v63+bldM5745VyDoMmicz8pd5HmoxXNQKLRKO6Wk5r95cZ1BHsWKzXzULP22BlIm 67ca12s7vUI0jaDR3RkVYtzW2MDU3sLH4dgt/12zr1aKd7Y+N+nk+FPwpiatJMzK FQoSmGgy5m3g93oI4g0ou3zyJQ+eorh/wY6b554xrnh5p+Sgam2Gy9T5WOnCriKg o2Luxh93hIqabvN8cjWkmtLNYYRAdNRexqrUJ+h/3id5xSsqMDllwkJk457MnRn+ sKHKCCuorz0N5V/knBw1d9gtcv+lTNC4n3k8Bi4BA7Az0wB0tkP6TIQtY1EJpLno UCAghj9k8OgIMav7/vjH8zAEqAbSDQWIb/C8r2j4gQkknNL7POXEo2Epxdcm1uwy KTRQVBjhKSq9euyKMLD5EzWo4fUdaSFS5wffOxH3oUxfuQsMyO4MfgZ37fi1WWX3 d/KGWBjjSIV1oWd74exdXkZhXcI08WLMDtm6BBBBK9lB/BaGLvwyEvvKSQmgf84p 7t+0TgZ592RCQhgaGJMh9/k9Y2XSqXYS3/J4Yab2kmvqXdQgwMiOx5hYbrJtAIIF RaaIvIICsIDplLTUhn56ngzmPQsh9mKcc2Uf4cMEjy/Y0Bdr+PiN/BzSoj63pkPR QWh8B+JSPJBwjlpsqtL5 =vRgI -----END PGP SIGNATURE----- Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi Pull SCSI updates from James Bottomley: "This update includes the usual round of driver updates (fcoe, lpfc, ufs, qla2xxx, hisi_sas). The most important other change is removing the flag to allow non-blk_mq on a per host basis (it's unused); there is still a global module parameter for all of SCSI just in case. The rest are an assortment of minor fixes and typo updates" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (101 commits) scsi:libsas: fix oops caused by assigning a freed task to ->lldd_task fnic: pci_dma_mapping_error() doesn't return an error code scsi: lpfc: avoid harmless comparison warning fcoe: implement FIP VLAN responder fcoe: Rename 'fip_frame' to 'fip_vn2vn_notify_frame' lpfc: call lpfc_sli_validate_fcp_iocb() with the hbalock held scsi: ufs: remove unnecessary goto label hpsa: change hpsa_passthru_ioctl timeout hpsa: correct skipping masked peripherals qla2xxx: Update driver version to 8.07.00.38-k qla2xxx: Fix BBCR offset qla2xxx: Fix duplicate message id. qla2xxx: Disable the adapter and skip error recovery in case of register disconnect. qla2xxx: Separate ISP type bits out from device type. qla2xxx: Correction to function qla26xx_dport_diagnostics(). qla2xxx: Add support to handle Loop Init error Asynchronus event. qla2xxx: Let DPORT be enabled purely by nvram. qla2xxx: Add bsg interface to support statistics counter reset. qla2xxx: Add bsg interface to support D_Port Diagnostics. qla2xxx: Check for device state before unloading the driver. ...
This commit is contained in:
Коммит
6a492b0f23
|
@ -0,0 +1,26 @@
|
|||
* Universal Flash Storage (UFS) DesignWare Host Controller
|
||||
|
||||
DWC_UFS nodes are defined to describe on-chip UFS host controllers and MPHY.
|
||||
Each UFS controller instance should have its own node.
|
||||
|
||||
Required properties:
|
||||
- compatible : compatible list must contain the PHY type & version:
|
||||
"snps,g210-tc-6.00-20bit"
|
||||
"snps,g210-tc-6.00-40bit"
|
||||
complemented with the Controller IP version:
|
||||
"snps,dwc-ufshcd-1.40a"
|
||||
complemented with the JEDEC version:
|
||||
"jedec,ufs-1.1"
|
||||
"jedec,ufs-2.0"
|
||||
|
||||
- reg : <registers mapping>
|
||||
- interrupts : <interrupt mapping for UFS host controller IRQ>
|
||||
|
||||
Example for a setup using a 1.40a DWC Controller with a 6.00 G210 40-bit TC:
|
||||
dwc-ufs@d0000000 {
|
||||
compatible = "snps,g210-tc-6.00-40bit",
|
||||
"snps,dwc-ufshcd-1.40a",
|
||||
"jedec,ufs-2.0";
|
||||
reg = < 0xd0000000 0x10000 >;
|
||||
interrupts = < 24 >;
|
||||
};
|
|
@ -4,8 +4,8 @@ UFSHC nodes are defined to describe on-chip UFS host controllers.
|
|||
Each UFS controller instance should have its own node.
|
||||
|
||||
Required properties:
|
||||
- compatible : must contain "jedec,ufs-1.1", may also list one or more
|
||||
of the following:
|
||||
- compatible : must contain "jedec,ufs-1.1" or "jedec,ufs-2.0", may
|
||||
also list one or more of the following:
|
||||
"qcom,msm8994-ufshc"
|
||||
"qcom,msm8996-ufshc"
|
||||
"qcom,ufshc"
|
||||
|
|
16
MAINTAINERS
16
MAINTAINERS
|
@ -213,7 +213,7 @@ S: Maintained
|
|||
F: drivers/media/dvb-frontends/a8293*
|
||||
|
||||
AACRAID SCSI RAID DRIVER
|
||||
M: Adaptec OEM Raid Solutions <aacraid@adaptec.com>
|
||||
M: Adaptec OEM Raid Solutions <aacraid@microsemi.com>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
W: http://www.adaptec.com/
|
||||
S: Supported
|
||||
|
@ -4699,7 +4699,7 @@ S: Maintained
|
|||
F: drivers/staging/fbtft/
|
||||
|
||||
FCOE SUBSYSTEM (libfc, libfcoe, fcoe)
|
||||
M: Vasu Dev <vasu.dev@intel.com>
|
||||
M: Johannes Thumshirn <jth@kernel.org>
|
||||
L: fcoe-devel@open-fcoe.org
|
||||
W: www.Open-FCoE.org
|
||||
S: Supported
|
||||
|
@ -10260,6 +10260,7 @@ M: "Martin K. Petersen" <martin.petersen@oracle.com>
|
|||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/scsi/
|
||||
F: drivers/scsi/
|
||||
F: include/scsi/
|
||||
|
||||
|
@ -11894,6 +11895,12 @@ S: Supported
|
|||
F: Documentation/scsi/ufs.txt
|
||||
F: drivers/scsi/ufs/
|
||||
|
||||
UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER DWC HOOKS
|
||||
M: Joao Pinto <Joao.Pinto@synopsys.com>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/scsi/ufs/*dwc*
|
||||
|
||||
UNSORTED BLOCK IMAGES (UBI)
|
||||
M: Artem Bityutskiy <dedekind1@gmail.com>
|
||||
M: Richard Weinberger <richard@nod.at>
|
||||
|
@ -11919,8 +11926,7 @@ S: Maintained
|
|||
F: drivers/net/wireless/ath/ar5523/
|
||||
|
||||
USB ATTACHED SCSI
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
M: Gerd Hoffmann <kraxel@redhat.com>
|
||||
M: Oliver Neukum <oneukum@suse.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Maintained
|
||||
|
@ -12419,7 +12425,7 @@ S: Maintained
|
|||
F: drivers/net/vmxnet3/
|
||||
|
||||
VMware PVSCSI driver
|
||||
M: Arvind Kumar <arvindkumar@vmware.com>
|
||||
M: Jim Gill <jgill@vmware.com>
|
||||
M: VMware PV-Drivers <pv-drivers@vmware.com>
|
||||
L: linux-scsi@vger.kernel.org
|
||||
S: Maintained
|
||||
|
|
|
@ -1120,9 +1120,9 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
|
|||
"reselection is tag %d, slot %p(%d)\n",
|
||||
hostdata->msgin[2], slot, slot->tag);
|
||||
} else {
|
||||
struct scsi_cmnd *SCp;
|
||||
struct NCR_700_Device_Parameters *p = SDp->hostdata;
|
||||
struct scsi_cmnd *SCp = p->current_cmnd;
|
||||
|
||||
SCp = SDp->current_cmnd;
|
||||
if(unlikely(SCp == NULL)) {
|
||||
sdev_printk(KERN_ERR, SDp,
|
||||
"no saved request for untagged cmd\n");
|
||||
|
@ -1825,9 +1825,11 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)
|
|||
CDEBUG(KERN_DEBUG, SCp, "sending out tag %d, slot %p\n",
|
||||
slot->tag, slot);
|
||||
} else {
|
||||
struct NCR_700_Device_Parameters *p = SCp->device->hostdata;
|
||||
|
||||
slot->tag = SCSI_NO_TAG;
|
||||
/* save current command for reselection */
|
||||
SCp->device->current_cmnd = SCp;
|
||||
p->current_cmnd = SCp;
|
||||
}
|
||||
/* sanity check: some of the commands generated by the mid-layer
|
||||
* have an eccentric idea of their sc_data_direction */
|
||||
|
@ -1892,7 +1894,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)
|
|||
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);
|
||||
DEBUG((" SETTING %08lx to %x\n",
|
||||
DEBUG((" SETTING %p to %x\n",
|
||||
(&slot->pSG[i].ins),
|
||||
slot->SG[i].ins));
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@ struct NCR_700_Device_Parameters {
|
|||
* cmnd[1], this could be in static storage */
|
||||
unsigned char cmnd[MAX_COMMAND_SIZE];
|
||||
__u8 depth;
|
||||
struct scsi_cmnd *current_cmnd; /* currently active command */
|
||||
};
|
||||
|
||||
|
||||
|
@ -423,23 +424,25 @@ struct NCR_700_Host_Parameters {
|
|||
#define script_patch_32(dev, 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]]) + value; \
|
||||
__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); \
|
||||
DEBUG((" script, patching %s at %d to 0x%lx\n", \
|
||||
#symbol, A_##symbol##_used[i], (value))); \
|
||||
DEBUG((" script, patching %s at %d to %pad\n", \
|
||||
#symbol, A_##symbol##_used[i], &da)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define script_patch_32_abs(dev, 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(value); \
|
||||
(script)[A_##symbol##_used[i]] = bS_to_host(da); \
|
||||
dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \
|
||||
DEBUG((" script, patching %s at %d to 0x%lx\n", \
|
||||
#symbol, A_##symbol##_used[i], (value))); \
|
||||
DEBUG((" script, patching %s at %d to %pad\n", \
|
||||
#symbol, A_##symbol##_used[i], &da)); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
|
|
@ -1433,7 +1433,7 @@ config SCSI_U14_34F_MAX_TAGS
|
|||
|
||||
config SCSI_ULTRASTOR
|
||||
tristate "UltraStor SCSI support"
|
||||
depends on X86 && ISA && SCSI
|
||||
depends on X86 && ISA && SCSI && ISA_DMA_API
|
||||
---help---
|
||||
This is support for the UltraStor 14F, 24F and 34F SCSI-2 host
|
||||
adapter family. This driver is explained in section 3.12 of the
|
||||
|
|
|
@ -635,15 +635,14 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
|
|||
}
|
||||
} else {
|
||||
struct user_sgmap* usg;
|
||||
usg = kmalloc(actual_fibsize - sizeof(struct aac_srb)
|
||||
+ sizeof(struct sgmap), GFP_KERNEL);
|
||||
usg = kmemdup(upsg,
|
||||
actual_fibsize - sizeof(struct aac_srb)
|
||||
+ sizeof(struct sgmap), GFP_KERNEL);
|
||||
if (!usg) {
|
||||
dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n"));
|
||||
rcode = -ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb)
|
||||
+ sizeof(struct sgmap));
|
||||
actual_fibsize = actual_fibsize64;
|
||||
|
||||
for (i = 0; i < usg->count; i++) {
|
||||
|
|
|
@ -57,7 +57,7 @@ static struct scsi_host_template bnx2fc_shost_template;
|
|||
static struct fc_function_template bnx2fc_transport_function;
|
||||
static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ;
|
||||
static struct fc_function_template bnx2fc_vport_xport_function;
|
||||
static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode);
|
||||
static int bnx2fc_create(struct net_device *netdev, enum fip_mode fip_mode);
|
||||
static void __bnx2fc_destroy(struct bnx2fc_interface *interface);
|
||||
static int bnx2fc_destroy(struct net_device *net_device);
|
||||
static int bnx2fc_enable(struct net_device *netdev);
|
||||
|
@ -486,7 +486,7 @@ static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||
|
||||
__skb_queue_tail(&bg->fcoe_rx_list, skb);
|
||||
if (bg->fcoe_rx_list.qlen == 1)
|
||||
wake_up_process(bg->thread);
|
||||
wake_up_process(bg->kthread);
|
||||
|
||||
spin_unlock(&bg->fcoe_rx_list.lock);
|
||||
|
||||
|
@ -2260,7 +2260,7 @@ enum bnx2fc_create_link_state {
|
|||
* Returns: 0 for success
|
||||
*/
|
||||
static int _bnx2fc_create(struct net_device *netdev,
|
||||
enum fip_state fip_mode,
|
||||
enum fip_mode fip_mode,
|
||||
enum bnx2fc_create_link_state link_state)
|
||||
{
|
||||
struct fcoe_ctlr_device *cdev;
|
||||
|
@ -2412,7 +2412,7 @@ mod_err:
|
|||
*
|
||||
* Returns: 0 for success
|
||||
*/
|
||||
static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
|
||||
static int bnx2fc_create(struct net_device *netdev, enum fip_mode fip_mode)
|
||||
{
|
||||
return _bnx2fc_create(netdev, fip_mode, BNX2FC_CREATE_LINK_UP);
|
||||
}
|
||||
|
@ -2715,7 +2715,7 @@ static int __init bnx2fc_mod_init(void)
|
|||
}
|
||||
wake_up_process(l2_thread);
|
||||
spin_lock_bh(&bg->fcoe_rx_list.lock);
|
||||
bg->thread = l2_thread;
|
||||
bg->kthread = l2_thread;
|
||||
spin_unlock_bh(&bg->fcoe_rx_list.lock);
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
|
@ -2788,8 +2788,8 @@ static void __exit bnx2fc_mod_exit(void)
|
|||
/* Destroy global thread */
|
||||
bg = &bnx2fc_global;
|
||||
spin_lock_bh(&bg->fcoe_rx_list.lock);
|
||||
l2_thread = bg->thread;
|
||||
bg->thread = NULL;
|
||||
l2_thread = bg->kthread;
|
||||
bg->kthread = NULL;
|
||||
while ((skb = __skb_dequeue(&bg->fcoe_rx_list)) != NULL)
|
||||
kfree_skb(skb);
|
||||
|
||||
|
|
|
@ -1758,7 +1758,7 @@ static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
|
|||
if ((fcp_rsp_len == 4) || (fcp_rsp_len == 8)) {
|
||||
/* Only for task management function */
|
||||
io_req->fcp_rsp_code = rq_data[3];
|
||||
printk(KERN_ERR PFX "fcp_rsp_code = %d\n",
|
||||
BNX2FC_IO_DBG(io_req, "fcp_rsp_code = %d\n",
|
||||
io_req->fcp_rsp_code);
|
||||
}
|
||||
|
||||
|
|
|
@ -2417,7 +2417,7 @@ static void bnx2i_process_conn_destroy_cmpl(struct bnx2i_hba *hba,
|
|||
ep = bnx2i_find_ep_in_destroy_list(hba, conn_destroy->iscsi_conn_id);
|
||||
if (!ep) {
|
||||
printk(KERN_ALERT "bnx2i_conn_destroy_cmpl: no pending "
|
||||
"offload request, unexpected complection\n");
|
||||
"offload request, unexpected completion\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -764,6 +764,67 @@ static void term_afu(struct cxlflash_cfg *cfg)
|
|||
pr_debug("%s: returning\n", __func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* notify_shutdown() - notifies device of pending shutdown
|
||||
* @cfg: Internal structure associated with the host.
|
||||
* @wait: Whether to wait for shutdown processing to complete.
|
||||
*
|
||||
* This function will notify the AFU that the adapter is being shutdown
|
||||
* and will wait for shutdown processing to complete if wait is true.
|
||||
* This notification should flush pending I/Os to the device and halt
|
||||
* further I/Os until the next AFU reset is issued and device restarted.
|
||||
*/
|
||||
static void notify_shutdown(struct cxlflash_cfg *cfg, bool wait)
|
||||
{
|
||||
struct afu *afu = cfg->afu;
|
||||
struct device *dev = &cfg->dev->dev;
|
||||
struct sisl_global_map __iomem *global = &afu->afu_map->global;
|
||||
struct dev_dependent_vals *ddv;
|
||||
u64 reg, status;
|
||||
int i, retry_cnt = 0;
|
||||
|
||||
ddv = (struct dev_dependent_vals *)cfg->dev_id->driver_data;
|
||||
if (!(ddv->flags & CXLFLASH_NOTIFY_SHUTDOWN))
|
||||
return;
|
||||
|
||||
/* Notify AFU */
|
||||
for (i = 0; i < NUM_FC_PORTS; i++) {
|
||||
reg = readq_be(&global->fc_regs[i][FC_CONFIG2 / 8]);
|
||||
reg |= SISL_FC_SHUTDOWN_NORMAL;
|
||||
writeq_be(reg, &global->fc_regs[i][FC_CONFIG2 / 8]);
|
||||
}
|
||||
|
||||
if (!wait)
|
||||
return;
|
||||
|
||||
/* Wait up to 1.5 seconds for shutdown processing to complete */
|
||||
for (i = 0; i < NUM_FC_PORTS; i++) {
|
||||
retry_cnt = 0;
|
||||
while (true) {
|
||||
status = readq_be(&global->fc_regs[i][FC_STATUS / 8]);
|
||||
if (status & SISL_STATUS_SHUTDOWN_COMPLETE)
|
||||
break;
|
||||
if (++retry_cnt >= MC_RETRY_CNT) {
|
||||
dev_dbg(dev, "%s: port %d shutdown processing "
|
||||
"not yet completed\n", __func__, i);
|
||||
break;
|
||||
}
|
||||
msleep(100 * retry_cnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cxlflash_shutdown() - shutdown handler
|
||||
* @pdev: PCI device associated with the host.
|
||||
*/
|
||||
static void cxlflash_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
struct cxlflash_cfg *cfg = pci_get_drvdata(pdev);
|
||||
|
||||
notify_shutdown(cfg, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* cxlflash_remove() - PCI entry point to tear down host
|
||||
* @pdev: PCI device associated with the host.
|
||||
|
@ -785,6 +846,9 @@ static void cxlflash_remove(struct pci_dev *pdev)
|
|||
cfg->tmf_slock);
|
||||
spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
|
||||
|
||||
/* Notify AFU and wait for shutdown processing to complete */
|
||||
notify_shutdown(cfg, true);
|
||||
|
||||
cfg->state = STATE_FAILTERM;
|
||||
cxlflash_stop_term_user_contexts(cfg);
|
||||
|
||||
|
@ -1915,6 +1979,19 @@ static int afu_reset(struct cxlflash_cfg *cfg)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* drain_ioctls() - wait until all currently executing ioctls have completed
|
||||
* @cfg: Internal structure associated with the host.
|
||||
*
|
||||
* Obtain write access to read/write semaphore that wraps ioctl
|
||||
* handling to 'drain' ioctls currently executing.
|
||||
*/
|
||||
static void drain_ioctls(struct cxlflash_cfg *cfg)
|
||||
{
|
||||
down_write(&cfg->ioctl_rwsem);
|
||||
up_write(&cfg->ioctl_rwsem);
|
||||
}
|
||||
|
||||
/**
|
||||
* cxlflash_eh_device_reset_handler() - reset a single LUN
|
||||
* @scp: SCSI command to send.
|
||||
|
@ -1986,6 +2063,7 @@ static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp)
|
|||
switch (cfg->state) {
|
||||
case STATE_NORMAL:
|
||||
cfg->state = STATE_RESET;
|
||||
drain_ioctls(cfg);
|
||||
cxlflash_mark_contexts_error(cfg);
|
||||
rcr = afu_reset(cfg);
|
||||
if (rcr) {
|
||||
|
@ -2319,8 +2397,10 @@ static struct scsi_host_template driver_template = {
|
|||
/*
|
||||
* Device dependent values
|
||||
*/
|
||||
static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS };
|
||||
static struct dev_dependent_vals dev_flash_gt_vals = { CXLFLASH_MAX_SECTORS };
|
||||
static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS,
|
||||
0ULL };
|
||||
static struct dev_dependent_vals dev_flash_gt_vals = { CXLFLASH_MAX_SECTORS,
|
||||
CXLFLASH_NOTIFY_SHUTDOWN };
|
||||
|
||||
/*
|
||||
* PCI device binding table
|
||||
|
@ -2503,19 +2583,6 @@ out_remove:
|
|||
goto out;
|
||||
}
|
||||
|
||||
/**
|
||||
* drain_ioctls() - wait until all currently executing ioctls have completed
|
||||
* @cfg: Internal structure associated with the host.
|
||||
*
|
||||
* Obtain write access to read/write semaphore that wraps ioctl
|
||||
* handling to 'drain' ioctls currently executing.
|
||||
*/
|
||||
static void drain_ioctls(struct cxlflash_cfg *cfg)
|
||||
{
|
||||
down_write(&cfg->ioctl_rwsem);
|
||||
up_write(&cfg->ioctl_rwsem);
|
||||
}
|
||||
|
||||
/**
|
||||
* cxlflash_pci_error_detected() - called when a PCI error is detected
|
||||
* @pdev: PCI device struct.
|
||||
|
@ -2610,6 +2677,7 @@ static struct pci_driver cxlflash_driver = {
|
|||
.id_table = cxlflash_pci_table,
|
||||
.probe = cxlflash_probe,
|
||||
.remove = cxlflash_remove,
|
||||
.shutdown = cxlflash_shutdown,
|
||||
.err_handler = &cxlflash_err_handler,
|
||||
};
|
||||
|
||||
|
|
|
@ -88,6 +88,8 @@ enum undo_level {
|
|||
|
||||
struct dev_dependent_vals {
|
||||
u64 max_sectors;
|
||||
u64 flags;
|
||||
#define CXLFLASH_NOTIFY_SHUTDOWN 0x0000000000000001ULL
|
||||
};
|
||||
|
||||
struct asyc_intr_info {
|
||||
|
|
|
@ -311,6 +311,12 @@ struct sisl_global_regs {
|
|||
#define SISL_FC_INTERNAL_MASK ~(SISL_FC_INTERNAL_UNMASK)
|
||||
#define SISL_FC_INTERNAL_SHIFT 32
|
||||
|
||||
#define SISL_FC_SHUTDOWN_NORMAL 0x0000000000000010ULL
|
||||
#define SISL_FC_SHUTDOWN_ABRUPT 0x0000000000000020ULL
|
||||
|
||||
#define SISL_STATUS_SHUTDOWN_ACTIVE 0x0000000000000010ULL
|
||||
#define SISL_STATUS_SHUTDOWN_COMPLETE 0x0000000000000020ULL
|
||||
|
||||
#define SISL_ASTATUS_UNMASK 0xFFFFULL /* 1 means unmasked */
|
||||
#define SISL_ASTATUS_MASK ~(SISL_ASTATUS_UNMASK) /* 1 means masked */
|
||||
|
||||
|
|
|
@ -67,9 +67,6 @@ static DEFINE_MUTEX(fcoe_config_mutex);
|
|||
|
||||
static struct workqueue_struct *fcoe_wq;
|
||||
|
||||
/* fcoe_percpu_clean completion. Waiter protected by fcoe_create_mutex */
|
||||
static DECLARE_COMPLETION(fcoe_flush_completion);
|
||||
|
||||
/* fcoe host list */
|
||||
/* must only by accessed under the RTNL mutex */
|
||||
static LIST_HEAD(fcoe_hostlist);
|
||||
|
@ -80,7 +77,6 @@ static int fcoe_reset(struct Scsi_Host *);
|
|||
static int fcoe_xmit(struct fc_lport *, struct fc_frame *);
|
||||
static int fcoe_rcv(struct sk_buff *, struct net_device *,
|
||||
struct packet_type *, struct net_device *);
|
||||
static int fcoe_percpu_receive_thread(void *);
|
||||
static void fcoe_percpu_clean(struct fc_lport *);
|
||||
static int fcoe_link_ok(struct fc_lport *);
|
||||
|
||||
|
@ -107,12 +103,11 @@ static int fcoe_ddp_setup(struct fc_lport *, u16, struct scatterlist *,
|
|||
static int fcoe_ddp_done(struct fc_lport *, u16);
|
||||
static int fcoe_ddp_target(struct fc_lport *, u16, struct scatterlist *,
|
||||
unsigned int);
|
||||
static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *);
|
||||
static int fcoe_dcb_app_notification(struct notifier_block *notifier,
|
||||
ulong event, void *ptr);
|
||||
|
||||
static bool fcoe_match(struct net_device *netdev);
|
||||
static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode);
|
||||
static int fcoe_create(struct net_device *netdev, enum fip_mode fip_mode);
|
||||
static int fcoe_destroy(struct net_device *netdev);
|
||||
static int fcoe_enable(struct net_device *netdev);
|
||||
static int fcoe_disable(struct net_device *netdev);
|
||||
|
@ -120,7 +115,7 @@ static int fcoe_disable(struct net_device *netdev);
|
|||
/* fcoe_syfs control interface handlers */
|
||||
static int fcoe_ctlr_alloc(struct net_device *netdev);
|
||||
static int fcoe_ctlr_enabled(struct fcoe_ctlr_device *cdev);
|
||||
|
||||
static void fcoe_ctlr_mode(struct fcoe_ctlr_device *ctlr_dev);
|
||||
|
||||
static struct fc_seq *fcoe_elsct_send(struct fc_lport *,
|
||||
u32 did, struct fc_frame *,
|
||||
|
@ -136,11 +131,6 @@ static struct notifier_block fcoe_notifier = {
|
|||
.notifier_call = fcoe_device_notification,
|
||||
};
|
||||
|
||||
/* notification function for CPU hotplug events */
|
||||
static struct notifier_block fcoe_cpu_notifier = {
|
||||
.notifier_call = fcoe_cpu_callback,
|
||||
};
|
||||
|
||||
/* notification function for DCB events */
|
||||
static struct notifier_block dcb_notifier = {
|
||||
.notifier_call = fcoe_dcb_app_notification,
|
||||
|
@ -156,8 +146,9 @@ static void fcoe_set_vport_symbolic_name(struct fc_vport *);
|
|||
static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *);
|
||||
static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *);
|
||||
|
||||
|
||||
static struct fcoe_sysfs_function_template fcoe_sysfs_templ = {
|
||||
.set_fcoe_ctlr_mode = fcoe_ctlr_set_fip_mode,
|
||||
.set_fcoe_ctlr_mode = fcoe_ctlr_mode,
|
||||
.set_fcoe_ctlr_enabled = fcoe_ctlr_enabled,
|
||||
.get_fcoe_ctlr_link_fail = fcoe_ctlr_get_lesb,
|
||||
.get_fcoe_ctlr_vlink_fail = fcoe_ctlr_get_lesb,
|
||||
|
@ -682,6 +673,12 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
|
|||
fcoe = port->priv;
|
||||
ctlr = fcoe_to_ctlr(fcoe);
|
||||
|
||||
/* Figure out the VLAN ID, if any */
|
||||
if (netdev->priv_flags & IFF_802_1Q_VLAN)
|
||||
lport->vlan = vlan_dev_vlan_id(netdev);
|
||||
else
|
||||
lport->vlan = 0;
|
||||
|
||||
/*
|
||||
* Determine max frame size based on underlying device and optional
|
||||
* user-configured limit. If the MFS is too low, fcoe_link_ok()
|
||||
|
@ -780,9 +777,6 @@ static void fcoe_fdmi_info(struct fc_lport *lport, struct net_device *netdev)
|
|||
fcoe = port->priv;
|
||||
realdev = fcoe->realdev;
|
||||
|
||||
if (!realdev)
|
||||
return;
|
||||
|
||||
/* No FDMI state m/c for NPIV ports */
|
||||
if (lport->vport)
|
||||
return;
|
||||
|
@ -1245,152 +1239,21 @@ static int __exit fcoe_if_exit(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_percpu_thread_create() - Create a receive thread for an online CPU
|
||||
* @cpu: The CPU index of the CPU to create a receive thread for
|
||||
*/
|
||||
static void fcoe_percpu_thread_create(unsigned int cpu)
|
||||
static void fcoe_thread_cleanup_local(unsigned int cpu)
|
||||
{
|
||||
struct fcoe_percpu_s *p;
|
||||
struct task_struct *thread;
|
||||
|
||||
p = &per_cpu(fcoe_percpu, cpu);
|
||||
|
||||
thread = kthread_create_on_node(fcoe_percpu_receive_thread,
|
||||
(void *)p, cpu_to_node(cpu),
|
||||
"fcoethread/%d", cpu);
|
||||
|
||||
if (likely(!IS_ERR(thread))) {
|
||||
kthread_bind(thread, cpu);
|
||||
wake_up_process(thread);
|
||||
|
||||
spin_lock_bh(&p->fcoe_rx_list.lock);
|
||||
p->thread = thread;
|
||||
spin_unlock_bh(&p->fcoe_rx_list.lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_percpu_thread_destroy() - Remove the receive thread of a CPU
|
||||
* @cpu: The CPU index of the CPU whose receive thread is to be destroyed
|
||||
*
|
||||
* Destroys a per-CPU Rx thread. Any pending skbs are moved to the
|
||||
* current CPU's Rx thread. If the thread being destroyed is bound to
|
||||
* the CPU processing this context the skbs will be freed.
|
||||
*/
|
||||
static void fcoe_percpu_thread_destroy(unsigned int cpu)
|
||||
{
|
||||
struct fcoe_percpu_s *p;
|
||||
struct task_struct *thread;
|
||||
struct page *crc_eof;
|
||||
struct sk_buff *skb;
|
||||
#ifdef CONFIG_SMP
|
||||
struct fcoe_percpu_s *p0;
|
||||
unsigned targ_cpu = get_cpu();
|
||||
#endif /* CONFIG_SMP */
|
||||
struct fcoe_percpu_s *p;
|
||||
|
||||
FCOE_DBG("Destroying receive thread for CPU %d\n", cpu);
|
||||
|
||||
/* Prevent any new skbs from being queued for this CPU. */
|
||||
p = &per_cpu(fcoe_percpu, cpu);
|
||||
p = per_cpu_ptr(&fcoe_percpu, cpu);
|
||||
spin_lock_bh(&p->fcoe_rx_list.lock);
|
||||
thread = p->thread;
|
||||
p->thread = NULL;
|
||||
crc_eof = p->crc_eof_page;
|
||||
p->crc_eof_page = NULL;
|
||||
p->crc_eof_offset = 0;
|
||||
spin_unlock_bh(&p->fcoe_rx_list.lock);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* Don't bother moving the skb's if this context is running
|
||||
* on the same CPU that is having its thread destroyed. This
|
||||
* can easily happen when the module is removed.
|
||||
*/
|
||||
if (cpu != targ_cpu) {
|
||||
p0 = &per_cpu(fcoe_percpu, targ_cpu);
|
||||
spin_lock_bh(&p0->fcoe_rx_list.lock);
|
||||
if (p0->thread) {
|
||||
FCOE_DBG("Moving frames from CPU %d to CPU %d\n",
|
||||
cpu, targ_cpu);
|
||||
|
||||
while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
|
||||
__skb_queue_tail(&p0->fcoe_rx_list, skb);
|
||||
spin_unlock_bh(&p0->fcoe_rx_list.lock);
|
||||
} else {
|
||||
/*
|
||||
* The targeted CPU is not initialized and cannot accept
|
||||
* new skbs. Unlock the targeted CPU and drop the skbs
|
||||
* on the CPU that is going offline.
|
||||
*/
|
||||
while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
|
||||
kfree_skb(skb);
|
||||
spin_unlock_bh(&p0->fcoe_rx_list.lock);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* This scenario occurs when the module is being removed
|
||||
* and all threads are being destroyed. skbs will continue
|
||||
* to be shifted from the CPU thread that is being removed
|
||||
* to the CPU thread associated with the CPU that is processing
|
||||
* the module removal. Once there is only one CPU Rx thread it
|
||||
* will reach this case and we will drop all skbs and later
|
||||
* stop the thread.
|
||||
*/
|
||||
spin_lock_bh(&p->fcoe_rx_list.lock);
|
||||
while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
|
||||
kfree_skb(skb);
|
||||
spin_unlock_bh(&p->fcoe_rx_list.lock);
|
||||
}
|
||||
put_cpu();
|
||||
#else
|
||||
/*
|
||||
* This a non-SMP scenario where the singular Rx thread is
|
||||
* being removed. Free all skbs and stop the thread.
|
||||
*/
|
||||
spin_lock_bh(&p->fcoe_rx_list.lock);
|
||||
while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
|
||||
kfree_skb(skb);
|
||||
spin_unlock_bh(&p->fcoe_rx_list.lock);
|
||||
#endif
|
||||
|
||||
if (thread)
|
||||
kthread_stop(thread);
|
||||
|
||||
if (crc_eof)
|
||||
put_page(crc_eof);
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_cpu_callback() - Handler for CPU hotplug events
|
||||
* @nfb: The callback data block
|
||||
* @action: The event triggering the callback
|
||||
* @hcpu: The index of the CPU that the event is for
|
||||
*
|
||||
* This creates or destroys per-CPU data for fcoe
|
||||
*
|
||||
* Returns NOTIFY_OK always.
|
||||
*/
|
||||
static int fcoe_cpu_callback(struct notifier_block *nfb,
|
||||
unsigned long action, void *hcpu)
|
||||
{
|
||||
unsigned cpu = (unsigned long)hcpu;
|
||||
|
||||
switch (action) {
|
||||
case CPU_ONLINE:
|
||||
case CPU_ONLINE_FROZEN:
|
||||
FCOE_DBG("CPU %x online: Create Rx thread\n", cpu);
|
||||
fcoe_percpu_thread_create(cpu);
|
||||
break;
|
||||
case CPU_DEAD:
|
||||
case CPU_DEAD_FROZEN:
|
||||
FCOE_DBG("CPU %x offline: Remove Rx thread\n", cpu);
|
||||
fcoe_percpu_thread_destroy(cpu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
flush_work(&p->work);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1509,26 +1372,6 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
|
|||
|
||||
fps = &per_cpu(fcoe_percpu, cpu);
|
||||
spin_lock(&fps->fcoe_rx_list.lock);
|
||||
if (unlikely(!fps->thread)) {
|
||||
/*
|
||||
* The targeted CPU is not ready, let's target
|
||||
* the first CPU now. For non-SMP systems this
|
||||
* will check the same CPU twice.
|
||||
*/
|
||||
FCOE_NETDEV_DBG(netdev, "CPU is online, but no receive thread "
|
||||
"ready for incoming skb- using first online "
|
||||
"CPU.\n");
|
||||
|
||||
spin_unlock(&fps->fcoe_rx_list.lock);
|
||||
cpu = cpumask_first(cpu_online_mask);
|
||||
fps = &per_cpu(fcoe_percpu, cpu);
|
||||
spin_lock(&fps->fcoe_rx_list.lock);
|
||||
if (!fps->thread) {
|
||||
spin_unlock(&fps->fcoe_rx_list.lock);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We now have a valid CPU that we're targeting for
|
||||
* this skb. We also have this receive thread locked,
|
||||
|
@ -1543,8 +1386,7 @@ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev,
|
|||
* in softirq context.
|
||||
*/
|
||||
__skb_queue_tail(&fps->fcoe_rx_list, skb);
|
||||
if (fps->thread->state == TASK_INTERRUPTIBLE)
|
||||
wake_up_process(fps->thread);
|
||||
schedule_work_on(cpu, &fps->work);
|
||||
spin_unlock(&fps->fcoe_rx_list.lock);
|
||||
|
||||
return NET_RX_SUCCESS;
|
||||
|
@ -1712,15 +1554,6 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_percpu_flush_done() - Indicate per-CPU queue flush completion
|
||||
* @skb: The completed skb (argument required by destructor)
|
||||
*/
|
||||
static void fcoe_percpu_flush_done(struct sk_buff *skb)
|
||||
{
|
||||
complete(&fcoe_flush_completion);
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_filter_frames() - filter out bad fcoe frames, i.e. bad CRC
|
||||
* @lport: The local port the frame was received on
|
||||
|
@ -1792,8 +1625,7 @@ static void fcoe_recv_frame(struct sk_buff *skb)
|
|||
fr = fcoe_dev_from_skb(skb);
|
||||
lport = fr->fr_dev;
|
||||
if (unlikely(!lport)) {
|
||||
if (skb->destructor != fcoe_percpu_flush_done)
|
||||
FCOE_NETDEV_DBG(skb->dev, "NULL lport in skb\n");
|
||||
FCOE_NETDEV_DBG(skb->dev, "NULL lport in skb\n");
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
@ -1857,40 +1689,28 @@ drop:
|
|||
}
|
||||
|
||||
/**
|
||||
* fcoe_percpu_receive_thread() - The per-CPU packet receive thread
|
||||
* @arg: The per-CPU context
|
||||
* fcoe_receive_work() - The per-CPU worker
|
||||
* @work: The work struct
|
||||
*
|
||||
* Return: 0 for success
|
||||
*/
|
||||
static int fcoe_percpu_receive_thread(void *arg)
|
||||
static void fcoe_receive_work(struct work_struct *work)
|
||||
{
|
||||
struct fcoe_percpu_s *p = arg;
|
||||
struct fcoe_percpu_s *p;
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff_head tmp;
|
||||
|
||||
p = container_of(work, struct fcoe_percpu_s, work);
|
||||
skb_queue_head_init(&tmp);
|
||||
|
||||
set_user_nice(current, MIN_NICE);
|
||||
spin_lock_bh(&p->fcoe_rx_list.lock);
|
||||
skb_queue_splice_init(&p->fcoe_rx_list, &tmp);
|
||||
spin_unlock_bh(&p->fcoe_rx_list.lock);
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
if (!skb_queue_len(&tmp))
|
||||
return;
|
||||
|
||||
spin_lock_bh(&p->fcoe_rx_list.lock);
|
||||
skb_queue_splice_init(&p->fcoe_rx_list, &tmp);
|
||||
|
||||
if (!skb_queue_len(&tmp)) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
spin_unlock_bh(&p->fcoe_rx_list.lock);
|
||||
schedule();
|
||||
continue;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&p->fcoe_rx_list.lock);
|
||||
|
||||
while ((skb = __skb_dequeue(&tmp)) != NULL)
|
||||
fcoe_recv_frame(skb);
|
||||
|
||||
}
|
||||
return 0;
|
||||
while ((skb = __skb_dequeue(&tmp)))
|
||||
fcoe_recv_frame(skb);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2162,6 +1982,32 @@ static int fcoe_ctlr_enabled(struct fcoe_ctlr_device *cdev)
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_ctlr_mode() - Switch FIP mode
|
||||
* @cdev: 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
|
||||
* frames.
|
||||
*/
|
||||
static void fcoe_ctlr_mode(struct fcoe_ctlr_device *ctlr_dev)
|
||||
{
|
||||
struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
|
||||
struct fcoe_interface *fcoe = fcoe_ctlr_priv(ctlr);
|
||||
|
||||
if (ctlr_dev->mode == FIP_CONN_TYPE_VN2VN &&
|
||||
ctlr->mode != FIP_MODE_VN2VN) {
|
||||
dev_mc_del(fcoe->netdev, FIP_ALL_ENODE_MACS);
|
||||
dev_mc_add(fcoe->netdev, FIP_ALL_VN2VN_MACS);
|
||||
dev_mc_add(fcoe->netdev, FIP_ALL_P2P_MACS);
|
||||
} else if (ctlr->mode != FIP_MODE_FABRIC) {
|
||||
dev_mc_del(fcoe->netdev, FIP_ALL_VN2VN_MACS);
|
||||
dev_mc_del(fcoe->netdev, FIP_ALL_P2P_MACS);
|
||||
dev_mc_add(fcoe->netdev, FIP_ALL_ENODE_MACS);
|
||||
}
|
||||
fcoe_ctlr_set_fip_mode(ctlr_dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_destroy() - Destroy a FCoE interface
|
||||
* @netdev : The net_device object the Ethernet interface to create on
|
||||
|
@ -2317,7 +2163,7 @@ enum fcoe_create_link_state {
|
|||
* consolidation of code can be done when that interface is
|
||||
* removed.
|
||||
*/
|
||||
static int _fcoe_create(struct net_device *netdev, enum fip_state fip_mode,
|
||||
static int _fcoe_create(struct net_device *netdev, enum fip_mode fip_mode,
|
||||
enum fcoe_create_link_state link_state)
|
||||
{
|
||||
int rc = 0;
|
||||
|
@ -2406,7 +2252,7 @@ out:
|
|||
*
|
||||
* Returns: 0 for success
|
||||
*/
|
||||
static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
|
||||
static int fcoe_create(struct net_device *netdev, enum fip_mode fip_mode)
|
||||
{
|
||||
return _fcoe_create(netdev, fip_mode, FCOE_CREATE_LINK_UP);
|
||||
}
|
||||
|
@ -2450,36 +2296,19 @@ static int fcoe_link_ok(struct fc_lport *lport)
|
|||
*
|
||||
* Must be called with fcoe_create_mutex held to single-thread completion.
|
||||
*
|
||||
* This flushes the pending skbs by adding a new skb to each queue and
|
||||
* waiting until they are all freed. This assures us that not only are
|
||||
* there no packets that will be handled by the lport, but also that any
|
||||
* threads already handling packet have returned.
|
||||
* This flushes the pending skbs by flush the work item for each CPU. The work
|
||||
* item on each possible CPU is flushed because we may have used the per-CPU
|
||||
* struct of an offline CPU.
|
||||
*/
|
||||
static void fcoe_percpu_clean(struct fc_lport *lport)
|
||||
{
|
||||
struct fcoe_percpu_s *pp;
|
||||
struct sk_buff *skb;
|
||||
unsigned int cpu;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
pp = &per_cpu(fcoe_percpu, cpu);
|
||||
|
||||
if (!pp->thread || !cpu_online(cpu))
|
||||
continue;
|
||||
|
||||
skb = dev_alloc_skb(0);
|
||||
if (!skb)
|
||||
continue;
|
||||
|
||||
skb->destructor = fcoe_percpu_flush_done;
|
||||
|
||||
spin_lock_bh(&pp->fcoe_rx_list.lock);
|
||||
__skb_queue_tail(&pp->fcoe_rx_list, skb);
|
||||
if (pp->fcoe_rx_list.qlen == 1)
|
||||
wake_up_process(pp->thread);
|
||||
spin_unlock_bh(&pp->fcoe_rx_list.lock);
|
||||
|
||||
wait_for_completion(&fcoe_flush_completion);
|
||||
flush_work(&pp->work);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2625,22 +2454,11 @@ static int __init fcoe_init(void)
|
|||
mutex_lock(&fcoe_config_mutex);
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
p = &per_cpu(fcoe_percpu, cpu);
|
||||
p = per_cpu_ptr(&fcoe_percpu, cpu);
|
||||
INIT_WORK(&p->work, fcoe_receive_work);
|
||||
skb_queue_head_init(&p->fcoe_rx_list);
|
||||
}
|
||||
|
||||
cpu_notifier_register_begin();
|
||||
|
||||
for_each_online_cpu(cpu)
|
||||
fcoe_percpu_thread_create(cpu);
|
||||
|
||||
/* Initialize per CPU interrupt thread */
|
||||
rc = __register_hotcpu_notifier(&fcoe_cpu_notifier);
|
||||
if (rc)
|
||||
goto out_free;
|
||||
|
||||
cpu_notifier_register_done();
|
||||
|
||||
/* Setup link change notification */
|
||||
fcoe_dev_setup();
|
||||
|
||||
|
@ -2652,12 +2470,6 @@ static int __init fcoe_init(void)
|
|||
return 0;
|
||||
|
||||
out_free:
|
||||
for_each_online_cpu(cpu) {
|
||||
fcoe_percpu_thread_destroy(cpu);
|
||||
}
|
||||
|
||||
cpu_notifier_register_done();
|
||||
|
||||
mutex_unlock(&fcoe_config_mutex);
|
||||
destroy_workqueue(fcoe_wq);
|
||||
return rc;
|
||||
|
@ -2690,14 +2502,8 @@ static void __exit fcoe_exit(void)
|
|||
}
|
||||
rtnl_unlock();
|
||||
|
||||
cpu_notifier_register_begin();
|
||||
|
||||
for_each_online_cpu(cpu)
|
||||
fcoe_percpu_thread_destroy(cpu);
|
||||
|
||||
__unregister_hotcpu_notifier(&fcoe_cpu_notifier);
|
||||
|
||||
cpu_notifier_register_done();
|
||||
for_each_possible_cpu(cpu)
|
||||
fcoe_thread_cleanup_local(cpu);
|
||||
|
||||
mutex_unlock(&fcoe_config_mutex);
|
||||
|
||||
|
|
|
@ -59,6 +59,8 @@ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *);
|
|||
static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *);
|
||||
static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *, u32, u8 *);
|
||||
|
||||
static int fcoe_ctlr_vlan_recv(struct fcoe_ctlr *, struct sk_buff *);
|
||||
|
||||
static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS;
|
||||
static u8 fcoe_all_enode[ETH_ALEN] = FIP_ALL_ENODE_MACS;
|
||||
static u8 fcoe_all_vn2vn[ETH_ALEN] = FIP_ALL_VN2VN_MACS;
|
||||
|
@ -149,6 +151,7 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode)
|
|||
{
|
||||
fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT);
|
||||
fip->mode = mode;
|
||||
fip->fip_resp = false;
|
||||
INIT_LIST_HEAD(&fip->fcfs);
|
||||
mutex_init(&fip->ctlr_mutex);
|
||||
spin_lock_init(&fip->ctlr_lock);
|
||||
|
@ -991,7 +994,7 @@ static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip,
|
|||
LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
|
||||
"in FIP adv\n", desc->fip_dtype);
|
||||
/* standard says ignore unknown descriptors >= 128 */
|
||||
if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
|
||||
if (desc->fip_dtype < FIP_DT_NON_CRITICAL)
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
@ -1232,7 +1235,7 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
|
|||
LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
|
||||
"in FIP adv\n", desc->fip_dtype);
|
||||
/* standard says ignore unknown descriptors >= 128 */
|
||||
if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
|
||||
if (desc->fip_dtype < FIP_DT_NON_CRITICAL)
|
||||
goto drop;
|
||||
if (desc_cnt <= 2) {
|
||||
LIBFCOE_FIP_DBG(fip, "FIP descriptors "
|
||||
|
@ -1410,7 +1413,7 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
|
|||
break;
|
||||
default:
|
||||
/* standard says ignore unknown descriptors >= 128 */
|
||||
if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
|
||||
if (desc->fip_dtype < FIP_DT_NON_CRITICAL)
|
||||
goto err;
|
||||
break;
|
||||
}
|
||||
|
@ -1513,6 +1516,7 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb)
|
|||
struct fip_header *fiph;
|
||||
struct ethhdr *eh;
|
||||
enum fip_state state;
|
||||
bool fip_vlan_resp = false;
|
||||
u16 op;
|
||||
u8 sub;
|
||||
|
||||
|
@ -1546,11 +1550,17 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb)
|
|||
state = FIP_ST_ENABLED;
|
||||
LIBFCOE_FIP_DBG(fip, "Using FIP mode\n");
|
||||
}
|
||||
fip_vlan_resp = fip->fip_resp;
|
||||
mutex_unlock(&fip->ctlr_mutex);
|
||||
|
||||
if (fip->mode == FIP_MODE_VN2VN && op == FIP_OP_VN2VN)
|
||||
return fcoe_ctlr_vn_recv(fip, skb);
|
||||
|
||||
if (fip_vlan_resp && op == FIP_OP_VLAN) {
|
||||
LIBFCOE_FIP_DBG(fip, "fip vlan discovery\n");
|
||||
return fcoe_ctlr_vlan_recv(fip, skb);
|
||||
}
|
||||
|
||||
if (state != FIP_ST_ENABLED && state != FIP_ST_VNMP_UP &&
|
||||
state != FIP_ST_VNMP_CLAIM)
|
||||
goto drop;
|
||||
|
@ -1989,7 +1999,7 @@ static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip,
|
|||
const u8 *dest, size_t min_len)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct fip_frame {
|
||||
struct fip_vn2vn_probe_frame {
|
||||
struct ethhdr eth;
|
||||
struct fip_header fip;
|
||||
struct fip_mac_desc mac;
|
||||
|
@ -2016,7 +2026,7 @@ static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip,
|
|||
if (!skb)
|
||||
return;
|
||||
|
||||
frame = (struct fip_frame *)skb->data;
|
||||
frame = (struct fip_vn2vn_probe_frame *)skb->data;
|
||||
memset(frame, 0, len);
|
||||
memcpy(frame->eth.h_dest, dest, ETH_ALEN);
|
||||
|
||||
|
@ -2338,7 +2348,7 @@ static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
|
|||
LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
|
||||
"in FIP probe\n", dtype);
|
||||
/* standard says ignore unknown descriptors >= 128 */
|
||||
if (dtype < FIP_DT_VENDOR_BASE)
|
||||
if (dtype < FIP_DT_NON_CRITICAL)
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
@ -2496,14 +2506,13 @@ static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *fip, u32 port_id, u8 *mac)
|
|||
struct fcoe_rport *frport;
|
||||
int ret = -1;
|
||||
|
||||
rcu_read_lock();
|
||||
rdata = lport->tt.rport_lookup(lport, port_id);
|
||||
if (rdata) {
|
||||
frport = fcoe_ctlr_rport(rdata);
|
||||
memcpy(mac, frport->enode_mac, ETH_ALEN);
|
||||
ret = 0;
|
||||
kref_put(&rdata->kref, lport->tt.rport_destroy);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2585,11 +2594,7 @@ static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip,
|
|||
fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
|
||||
return;
|
||||
}
|
||||
mutex_lock(&lport->disc.disc_mutex);
|
||||
rdata = lport->tt.rport_lookup(lport, new->ids.port_id);
|
||||
if (rdata)
|
||||
kref_get(&rdata->kref);
|
||||
mutex_unlock(&lport->disc.disc_mutex);
|
||||
if (rdata) {
|
||||
if (rdata->ids.node_name == new->ids.node_name &&
|
||||
rdata->ids.port_name == new->ids.port_name) {
|
||||
|
@ -2708,6 +2713,220 @@ drop:
|
|||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* Returns non-zero error number on error.
|
||||
* Does not consume the packet.
|
||||
*/
|
||||
static int fcoe_ctlr_vlan_parse(struct fcoe_ctlr *fip,
|
||||
struct sk_buff *skb,
|
||||
struct fc_rport_priv *rdata)
|
||||
{
|
||||
struct fip_header *fiph;
|
||||
struct fip_desc *desc = NULL;
|
||||
struct fip_mac_desc *macd = NULL;
|
||||
struct fip_wwn_desc *wwn = NULL;
|
||||
struct fcoe_rport *frport;
|
||||
size_t rlen;
|
||||
size_t dlen;
|
||||
u32 desc_mask = 0;
|
||||
u32 dtype;
|
||||
u8 sub;
|
||||
|
||||
memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
|
||||
frport = fcoe_ctlr_rport(rdata);
|
||||
|
||||
fiph = (struct fip_header *)skb->data;
|
||||
frport->flags = ntohs(fiph->fip_flags);
|
||||
|
||||
sub = fiph->fip_subcode;
|
||||
switch (sub) {
|
||||
case FIP_SC_VL_REQ:
|
||||
desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME);
|
||||
break;
|
||||
default:
|
||||
LIBFCOE_FIP_DBG(fip, "vn_parse unknown subcode %u\n", sub);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rlen = ntohs(fiph->fip_dl_len) * 4;
|
||||
if (rlen + sizeof(*fiph) > skb->len)
|
||||
return -EINVAL;
|
||||
|
||||
desc = (struct fip_desc *)(fiph + 1);
|
||||
while (rlen > 0) {
|
||||
dlen = desc->fip_dlen * FIP_BPW;
|
||||
if (dlen < sizeof(*desc) || dlen > rlen)
|
||||
return -EINVAL;
|
||||
|
||||
dtype = desc->fip_dtype;
|
||||
if (dtype < 32) {
|
||||
if (!(desc_mask & BIT(dtype))) {
|
||||
LIBFCOE_FIP_DBG(fip,
|
||||
"unexpected or duplicated desc "
|
||||
"desc type %u in "
|
||||
"FIP VN2VN subtype %u\n",
|
||||
dtype, sub);
|
||||
return -EINVAL;
|
||||
}
|
||||
desc_mask &= ~BIT(dtype);
|
||||
}
|
||||
|
||||
switch (dtype) {
|
||||
case FIP_DT_MAC:
|
||||
if (dlen != sizeof(struct fip_mac_desc))
|
||||
goto len_err;
|
||||
macd = (struct fip_mac_desc *)desc;
|
||||
if (!is_valid_ether_addr(macd->fd_mac)) {
|
||||
LIBFCOE_FIP_DBG(fip,
|
||||
"Invalid MAC addr %pM in FIP VN2VN\n",
|
||||
macd->fd_mac);
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(frport->enode_mac, macd->fd_mac, ETH_ALEN);
|
||||
break;
|
||||
case FIP_DT_NAME:
|
||||
if (dlen != sizeof(struct fip_wwn_desc))
|
||||
goto len_err;
|
||||
wwn = (struct fip_wwn_desc *)desc;
|
||||
rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
|
||||
break;
|
||||
default:
|
||||
LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
|
||||
"in FIP probe\n", dtype);
|
||||
/* standard says ignore unknown descriptors >= 128 */
|
||||
if (dtype < FIP_DT_NON_CRITICAL)
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
desc = (struct fip_desc *)((char *)desc + dlen);
|
||||
rlen -= dlen;
|
||||
}
|
||||
return 0;
|
||||
|
||||
len_err:
|
||||
LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
|
||||
dtype, dlen);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_ctlr_vlan_send() - Send a FIP VLAN Notification
|
||||
* @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,
|
||||
const u8 *dest)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct fip_vlan_notify_frame {
|
||||
struct ethhdr eth;
|
||||
struct fip_header fip;
|
||||
struct fip_mac_desc mac;
|
||||
struct fip_vlan_desc vlan;
|
||||
} __packed * frame;
|
||||
size_t len;
|
||||
size_t dlen;
|
||||
|
||||
len = sizeof(*frame);
|
||||
dlen = sizeof(frame->mac) + sizeof(frame->vlan);
|
||||
len = max(len, sizeof(struct ethhdr));
|
||||
|
||||
skb = dev_alloc_skb(len);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
LIBFCOE_FIP_DBG(fip, "fip %s vlan notification, vlan %d\n",
|
||||
fip->mode == FIP_MODE_VN2VN ? "vn2vn" : "fcf",
|
||||
fip->lp->vlan);
|
||||
|
||||
frame = (struct fip_vlan_notify_frame *)skb->data;
|
||||
memset(frame, 0, len);
|
||||
memcpy(frame->eth.h_dest, dest, ETH_ALEN);
|
||||
|
||||
memcpy(frame->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
|
||||
frame->eth.h_proto = htons(ETH_P_FIP);
|
||||
|
||||
frame->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
|
||||
frame->fip.fip_op = htons(FIP_OP_VLAN);
|
||||
frame->fip.fip_subcode = sub;
|
||||
frame->fip.fip_dl_len = htons(dlen / FIP_BPW);
|
||||
|
||||
frame->mac.fd_desc.fip_dtype = FIP_DT_MAC;
|
||||
frame->mac.fd_desc.fip_dlen = sizeof(frame->mac) / FIP_BPW;
|
||||
memcpy(frame->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
|
||||
|
||||
frame->vlan.fd_desc.fip_dtype = FIP_DT_VLAN;
|
||||
frame->vlan.fd_desc.fip_dlen = sizeof(frame->vlan) / FIP_BPW;
|
||||
put_unaligned_be16(fip->lp->vlan, &frame->vlan.fd_vlan);
|
||||
|
||||
skb_put(skb, len);
|
||||
skb->protocol = htons(ETH_P_FIP);
|
||||
skb->priority = fip->priority;
|
||||
skb_reset_mac_header(skb);
|
||||
skb_reset_network_header(skb);
|
||||
|
||||
fip->send(fip, skb);
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_ctlr_vlan_disk_reply() - send FIP VLAN Discovery Notification.
|
||||
* @fip: The FCoE controller
|
||||
*
|
||||
* Called with ctlr_mutex held.
|
||||
*/
|
||||
static void fcoe_ctlr_vlan_disc_reply(struct fcoe_ctlr *fip,
|
||||
struct fc_rport_priv *rdata)
|
||||
{
|
||||
struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
|
||||
enum fip_vlan_subcode sub = FIP_SC_VL_NOTE;
|
||||
|
||||
if (fip->mode == FIP_MODE_VN2VN)
|
||||
sub = FIP_SC_VL_VN2VN_NOTE;
|
||||
|
||||
fcoe_ctlr_vlan_send(fip, sub, frport->enode_mac);
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_ctlr_vlan_recv - vlan request receive handler for VN2VN mode.
|
||||
* @lport: The local port
|
||||
* @fp: The received frame
|
||||
*
|
||||
*/
|
||||
static int fcoe_ctlr_vlan_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
|
||||
{
|
||||
struct fip_header *fiph;
|
||||
enum fip_vlan_subcode sub;
|
||||
struct {
|
||||
struct fc_rport_priv rdata;
|
||||
struct fcoe_rport frport;
|
||||
} buf;
|
||||
int rc;
|
||||
|
||||
fiph = (struct fip_header *)skb->data;
|
||||
sub = fiph->fip_subcode;
|
||||
rc = fcoe_ctlr_vlan_parse(fip, skb, &buf.rdata);
|
||||
if (rc) {
|
||||
LIBFCOE_FIP_DBG(fip, "vlan_recv vlan_parse error %d\n", rc);
|
||||
goto drop;
|
||||
}
|
||||
mutex_lock(&fip->ctlr_mutex);
|
||||
if (sub == FIP_SC_VL_REQ)
|
||||
fcoe_ctlr_vlan_disc_reply(fip, &buf.rdata);
|
||||
mutex_unlock(&fip->ctlr_mutex);
|
||||
|
||||
drop:
|
||||
kfree(skb);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_ctlr_disc_recv - discovery receive handler for VN2VN mode.
|
||||
* @lport: The local port
|
||||
|
@ -2869,7 +3088,7 @@ unlock:
|
|||
* when nothing is happening.
|
||||
*/
|
||||
static void fcoe_ctlr_mode_set(struct fc_lport *lport, struct fcoe_ctlr *fip,
|
||||
enum fip_state fip_mode)
|
||||
enum fip_mode fip_mode)
|
||||
{
|
||||
void *priv;
|
||||
|
||||
|
|
|
@ -385,6 +385,44 @@ static FCOE_DEVICE_ATTR(ctlr, enabled, S_IRUGO | S_IWUSR,
|
|||
show_ctlr_enabled_state,
|
||||
store_ctlr_enabled);
|
||||
|
||||
static ssize_t store_ctlr_fip_resp(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
|
||||
struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr);
|
||||
|
||||
mutex_lock(&fip->ctlr_mutex);
|
||||
if ((buf[1] == '\0') || ((buf[1] == '\n') && (buf[2] == '\0'))) {
|
||||
if (buf[0] == '1') {
|
||||
fip->fip_resp = 1;
|
||||
mutex_unlock(&fip->ctlr_mutex);
|
||||
return count;
|
||||
}
|
||||
if (buf[0] == '0') {
|
||||
fip->fip_resp = 0;
|
||||
mutex_unlock(&fip->ctlr_mutex);
|
||||
return count;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&fip->ctlr_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t show_ctlr_fip_resp(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
|
||||
struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr);
|
||||
|
||||
return sprintf(buf, "%d\n", fip->fip_resp ? 1 : 0);
|
||||
}
|
||||
|
||||
static FCOE_DEVICE_ATTR(ctlr, fip_vlan_responder, S_IRUGO | S_IWUSR,
|
||||
show_ctlr_fip_resp,
|
||||
store_ctlr_fip_resp);
|
||||
|
||||
static ssize_t
|
||||
store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
|
@ -467,6 +505,7 @@ static struct attribute_group fcoe_ctlr_lesb_attr_group = {
|
|||
};
|
||||
|
||||
static struct attribute *fcoe_ctlr_attrs[] = {
|
||||
&device_attr_fcoe_ctlr_fip_vlan_responder.attr,
|
||||
&device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr,
|
||||
&device_attr_fcoe_ctlr_enabled.attr,
|
||||
&device_attr_fcoe_ctlr_mode.attr,
|
||||
|
|
|
@ -133,10 +133,10 @@ int fcoe_link_speed_update(struct fc_lport *lport)
|
|||
case SPEED_10000:
|
||||
lport->link_speed = FC_PORTSPEED_10GBIT;
|
||||
break;
|
||||
case 20000:
|
||||
case SPEED_20000:
|
||||
lport->link_speed = FC_PORTSPEED_20GBIT;
|
||||
break;
|
||||
case 40000:
|
||||
case SPEED_40000:
|
||||
lport->link_speed = FC_PORTSPEED_40GBIT;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -359,7 +359,7 @@ static void fnic_fcoe_send_vlan_req(struct fnic *fnic)
|
|||
|
||||
vlan->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
|
||||
vlan->fip.fip_op = htons(FIP_OP_VLAN);
|
||||
vlan->fip.fip_subcode = FIP_SC_VL_REQ;
|
||||
vlan->fip.fip_subcode = FIP_SC_VL_NOTE;
|
||||
vlan->fip.fip_dl_len = htons(sizeof(vlan->desc) / FIP_BPW);
|
||||
|
||||
vlan->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
|
||||
|
@ -551,7 +551,7 @@ static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb)
|
|||
goto drop;
|
||||
/* pass it on to fcoe */
|
||||
ret = 1;
|
||||
} else if (op == FIP_OP_VLAN && sub == FIP_SC_VL_REP) {
|
||||
} else if (op == FIP_OP_VLAN && sub == FIP_SC_VL_NOTE) {
|
||||
/* set the vlan as used */
|
||||
fnic_fcoe_process_vlan_resp(fnic, skb);
|
||||
ret = 0;
|
||||
|
@ -954,8 +954,8 @@ int fnic_alloc_rq_frame(struct vnic_rq *rq)
|
|||
skb_put(skb, len);
|
||||
pa = pci_map_single(fnic->pdev, skb->data, len, PCI_DMA_FROMDEVICE);
|
||||
|
||||
r = pci_dma_mapping_error(fnic->pdev, pa);
|
||||
if (r) {
|
||||
if (pci_dma_mapping_error(fnic->pdev, pa)) {
|
||||
r = -ENOMEM;
|
||||
printk(KERN_ERR "PCI mapping failed with error %d\n", r);
|
||||
goto free_skb;
|
||||
}
|
||||
|
@ -1093,8 +1093,8 @@ static int fnic_send_frame(struct fnic *fnic, struct fc_frame *fp)
|
|||
|
||||
pa = pci_map_single(fnic->pdev, eth_hdr, tot_len, PCI_DMA_TODEVICE);
|
||||
|
||||
ret = pci_dma_mapping_error(fnic->pdev, pa);
|
||||
if (ret) {
|
||||
if (pci_dma_mapping_error(fnic->pdev, pa)) {
|
||||
ret = -ENOMEM;
|
||||
printk(KERN_ERR "DMA map failed with error %d\n", ret);
|
||||
goto free_skb_on_err;
|
||||
}
|
||||
|
@ -1308,7 +1308,7 @@ void fnic_handle_fip_timer(struct fnic *fnic)
|
|||
}
|
||||
spin_unlock_irqrestore(&fnic->fnic_lock, flags);
|
||||
|
||||
if (fnic->ctlr.mode == FIP_ST_NON_FIP)
|
||||
if (fnic->ctlr.mode == FIP_MODE_NON_FIP)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&fnic->vlans_lock, flags);
|
||||
|
|
|
@ -26,14 +26,6 @@
|
|||
|
||||
#define FINC_MAX_FLOGI_REJECTS 8
|
||||
|
||||
/*
|
||||
* FIP_DT_VLAN descriptor.
|
||||
*/
|
||||
struct fip_vlan_desc {
|
||||
struct fip_desc fd_desc;
|
||||
__be16 fd_vlan;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct vlan {
|
||||
__be16 vid;
|
||||
__be16 type;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <scsi/sas_ata.h>
|
||||
#include <scsi/libsas.h>
|
||||
|
||||
#define DRV_VERSION "v1.4"
|
||||
#define DRV_VERSION "v1.5"
|
||||
|
||||
#define HISI_SAS_MAX_PHYS 9
|
||||
#define HISI_SAS_MAX_QUEUES 32
|
||||
|
|
|
@ -721,30 +721,41 @@ static int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
/* reset and disable clock*/
|
||||
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg,
|
||||
reset_val);
|
||||
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg + 4,
|
||||
reset_val);
|
||||
msleep(1);
|
||||
regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg, &val);
|
||||
if (reset_val != (val & reset_val)) {
|
||||
dev_err(dev, "SAS reset fail.\n");
|
||||
return -EIO;
|
||||
}
|
||||
if (ACPI_HANDLE(dev)) {
|
||||
acpi_status s;
|
||||
|
||||
/* De-reset and enable clock*/
|
||||
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg + 4,
|
||||
reset_val);
|
||||
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg,
|
||||
reset_val);
|
||||
msleep(1);
|
||||
regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg,
|
||||
&val);
|
||||
if (val & reset_val) {
|
||||
dev_err(dev, "SAS de-reset fail.\n");
|
||||
return -EIO;
|
||||
}
|
||||
s = acpi_evaluate_object(ACPI_HANDLE(dev), "_RST", NULL, NULL);
|
||||
if (ACPI_FAILURE(s)) {
|
||||
dev_err(dev, "Reset failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
} else if (hisi_hba->ctrl) {
|
||||
/* reset and disable clock*/
|
||||
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg,
|
||||
reset_val);
|
||||
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg + 4,
|
||||
reset_val);
|
||||
msleep(1);
|
||||
regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg, &val);
|
||||
if (reset_val != (val & reset_val)) {
|
||||
dev_err(dev, "SAS reset fail.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* De-reset and enable clock*/
|
||||
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg + 4,
|
||||
reset_val);
|
||||
regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg,
|
||||
reset_val);
|
||||
msleep(1);
|
||||
regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg,
|
||||
&val);
|
||||
if (val & reset_val) {
|
||||
dev_err(dev, "SAS de-reset fail.\n");
|
||||
return -EIO;
|
||||
}
|
||||
} else
|
||||
dev_warn(dev, "no reset method\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -752,13 +763,12 @@ static int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
|
|||
static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
|
||||
{
|
||||
struct device *dev = &hisi_hba->pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
int i;
|
||||
|
||||
/* Global registers init */
|
||||
|
||||
/* Deal with am-max-transmissions quirk */
|
||||
if (of_get_property(np, "hip06-sas-v2-quirk-amt", NULL)) {
|
||||
if (device_property_present(dev, "hip06-sas-v2-quirk-amt")) {
|
||||
hisi_sas_write32(hisi_hba, AM_CFG_MAX_TRANS, 0x2020);
|
||||
hisi_sas_write32(hisi_hba, AM_CFG_SINGLE_PORT_MAX_TRANS,
|
||||
0x2020);
|
||||
|
@ -1902,14 +1912,9 @@ static void phy_bcast_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
|
|||
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;
|
||||
unsigned long flags;
|
||||
|
||||
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 1);
|
||||
|
||||
spin_lock_irqsave(&hisi_hba->lock, flags);
|
||||
sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
|
||||
spin_unlock_irqrestore(&hisi_hba->lock, flags);
|
||||
|
||||
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);
|
||||
|
@ -2260,12 +2265,20 @@ static const struct of_device_id sas_v2_of_match[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, sas_v2_of_match);
|
||||
|
||||
static const struct acpi_device_id sas_v2_acpi_match[] = {
|
||||
{ "HISI0162", 0 },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(acpi, sas_v2_acpi_match);
|
||||
|
||||
static struct platform_driver hisi_sas_v2_driver = {
|
||||
.probe = hisi_sas_v2_probe,
|
||||
.remove = hisi_sas_v2_remove,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = sas_v2_of_match,
|
||||
.acpi_match_table = ACPI_PTR(sas_v2_acpi_match),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -486,8 +486,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
|
|||
else
|
||||
shost->dma_boundary = 0xffffffff;
|
||||
|
||||
shost->use_blk_mq = scsi_use_blk_mq && !shost->hostt->disable_blk_mq;
|
||||
|
||||
device_initialize(&shost->shost_gendev);
|
||||
dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
|
||||
shost->shost_gendev.bus = &scsi_bus_type;
|
||||
|
|
|
@ -4105,6 +4105,70 @@ static int hpsa_set_local_logical_count(struct ctlr_info *h,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static bool hpsa_is_disk_spare(struct ctlr_info *h, u8 *lunaddrbytes)
|
||||
{
|
||||
struct bmic_identify_physical_device *id_phys;
|
||||
bool is_spare = false;
|
||||
int rc;
|
||||
|
||||
id_phys = kzalloc(sizeof(*id_phys), GFP_KERNEL);
|
||||
if (!id_phys)
|
||||
return false;
|
||||
|
||||
rc = hpsa_bmic_id_physical_device(h,
|
||||
lunaddrbytes,
|
||||
GET_BMIC_DRIVE_NUMBER(lunaddrbytes),
|
||||
id_phys, sizeof(*id_phys));
|
||||
if (rc == 0)
|
||||
is_spare = (id_phys->more_flags >> 6) & 0x01;
|
||||
|
||||
kfree(id_phys);
|
||||
return is_spare;
|
||||
}
|
||||
|
||||
#define RPL_DEV_FLAG_NON_DISK 0x1
|
||||
#define RPL_DEV_FLAG_UNCONFIG_DISK_REPORTING_SUPPORTED 0x2
|
||||
#define RPL_DEV_FLAG_UNCONFIG_DISK 0x4
|
||||
|
||||
#define BMIC_DEVICE_TYPE_ENCLOSURE 6
|
||||
|
||||
static bool hpsa_skip_device(struct ctlr_info *h, u8 *lunaddrbytes,
|
||||
struct ext_report_lun_entry *rle)
|
||||
{
|
||||
u8 device_flags;
|
||||
u8 device_type;
|
||||
|
||||
if (!MASKED_DEVICE(lunaddrbytes))
|
||||
return false;
|
||||
|
||||
device_flags = rle->device_flags;
|
||||
device_type = rle->device_type;
|
||||
|
||||
if (device_flags & RPL_DEV_FLAG_NON_DISK) {
|
||||
if (device_type == BMIC_DEVICE_TYPE_ENCLOSURE)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(device_flags & RPL_DEV_FLAG_UNCONFIG_DISK_REPORTING_SUPPORTED))
|
||||
return false;
|
||||
|
||||
if (device_flags & RPL_DEV_FLAG_UNCONFIG_DISK)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Spares may be spun down, we do not want to
|
||||
* do an Inquiry to a RAID set spare drive as
|
||||
* that would have them spun up, that is a
|
||||
* performance hit because I/O to the RAID device
|
||||
* stops while the spin up occurs which can take
|
||||
* over 50 seconds.
|
||||
*/
|
||||
if (hpsa_is_disk_spare(h, lunaddrbytes))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void hpsa_update_scsi_devices(struct ctlr_info *h)
|
||||
{
|
||||
|
@ -4198,6 +4262,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
|
|||
u8 *lunaddrbytes, is_OBDR = 0;
|
||||
int rc = 0;
|
||||
int phys_dev_index = i - (raid_ctlr_position == 0);
|
||||
bool skip_device = false;
|
||||
|
||||
physical_device = i < nphysicals + (raid_ctlr_position == 0);
|
||||
|
||||
|
@ -4205,11 +4270,15 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
|
|||
lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position,
|
||||
i, nphysicals, nlogicals, physdev_list, logdev_list);
|
||||
|
||||
/* skip masked non-disk devices */
|
||||
if (MASKED_DEVICE(lunaddrbytes) && physical_device &&
|
||||
(physdev_list->LUN[phys_dev_index].device_type != 0x06) &&
|
||||
(physdev_list->LUN[phys_dev_index].device_flags & 0x01))
|
||||
continue;
|
||||
/*
|
||||
* Skip over some devices such as a spare.
|
||||
*/
|
||||
if (!tmpdevice->external && physical_device) {
|
||||
skip_device = hpsa_skip_device(h, lunaddrbytes,
|
||||
&physdev_list->LUN[phys_dev_index]);
|
||||
if (skip_device)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get device type, vendor, model, device id */
|
||||
rc = hpsa_update_device_info(h, lunaddrbytes, tmpdevice,
|
||||
|
@ -6455,7 +6524,7 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
|
|||
c->SG[0].Ext = cpu_to_le32(HPSA_SG_LAST); /* not chaining */
|
||||
}
|
||||
rc = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE,
|
||||
DEFAULT_TIMEOUT);
|
||||
NO_TIMEOUT);
|
||||
if (iocommand.buf_size > 0)
|
||||
hpsa_pci_unmap(h->pdev, c, 1, PCI_DMA_BIDIRECTIONAL);
|
||||
check_ioctl_unit_attention(h, c);
|
||||
|
@ -6588,7 +6657,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
|
|||
c->SG[--i].Ext = cpu_to_le32(HPSA_SG_LAST);
|
||||
}
|
||||
status = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE,
|
||||
DEFAULT_TIMEOUT);
|
||||
NO_TIMEOUT);
|
||||
if (sg_used)
|
||||
hpsa_pci_unmap(h->pdev, c, sg_used, PCI_DMA_BIDIRECTIONAL);
|
||||
check_ioctl_unit_attention(h, c);
|
||||
|
|
|
@ -4722,6 +4722,8 @@ static void ibmvfc_rport_add_thread(struct work_struct *work)
|
|||
tgt_dbg(tgt, "Setting rport roles\n");
|
||||
fc_remote_port_rolechg(rport, tgt->ids.roles);
|
||||
put_device(&rport->dev);
|
||||
} else {
|
||||
spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
||||
}
|
||||
|
||||
kref_put(&tgt->kref, ibmvfc_release_tgt);
|
||||
|
|
|
@ -98,7 +98,7 @@ static unsigned int ipr_transop_timeout = 0;
|
|||
static unsigned int ipr_debug = 0;
|
||||
static unsigned int ipr_max_devs = IPR_DEFAULT_SIS64_DEVS;
|
||||
static unsigned int ipr_dual_ioa_raid = 1;
|
||||
static unsigned int ipr_number_of_msix = 2;
|
||||
static unsigned int ipr_number_of_msix = 16;
|
||||
static unsigned int ipr_fast_reboot;
|
||||
static DEFINE_SPINLOCK(ipr_driver_lock);
|
||||
|
||||
|
@ -194,7 +194,8 @@ static const struct ipr_chip_t ipr_chip[] = {
|
|||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[1] },
|
||||
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, IPR_USE_LSI, IPR_SIS32, IPR_PCI_CFG, &ipr_chip_cfg[1] },
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROC_FPGA_E2, IPR_USE_MSI, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] },
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE, IPR_USE_MSI, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] }
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE, IPR_USE_MSI, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] },
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_RATTLESNAKE, IPR_USE_MSI, IPR_SIS64, IPR_MMIO, &ipr_chip_cfg[2] }
|
||||
};
|
||||
|
||||
static int ipr_max_bus_speeds[] = {
|
||||
|
@ -221,7 +222,7 @@ module_param_named(max_devs, ipr_max_devs, int, 0);
|
|||
MODULE_PARM_DESC(max_devs, "Specify the maximum number of physical devices. "
|
||||
"[Default=" __stringify(IPR_DEFAULT_SIS64_DEVS) "]");
|
||||
module_param_named(number_of_msix, ipr_number_of_msix, int, 0);
|
||||
MODULE_PARM_DESC(number_of_msix, "Specify the number of MSIX interrupts to use on capable adapters (1 - 16). (default:2)");
|
||||
MODULE_PARM_DESC(number_of_msix, "Specify the number of MSIX interrupts to use on capable adapters (1 - 16). (default:16)");
|
||||
module_param_named(fast_reboot, ipr_fast_reboot, int, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(fast_reboot, "Skip adapter shutdown during reboot. Set to 1 to enable. (default: 0)");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -10565,6 +10566,10 @@ static struct pci_device_id ipr_pci_table[] = {
|
|||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2CD2, 0, 0, 0 },
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CROCODILE,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2CCD, 0, 0, 0 },
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_RATTLESNAKE,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_580A, 0, 0, 0 },
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_RATTLESNAKE,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_580B, 0, 0, 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, ipr_pci_table);
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
|
||||
#define PCI_DEVICE_ID_IBM_CROC_FPGA_E2 0x033D
|
||||
#define PCI_DEVICE_ID_IBM_CROCODILE 0x034A
|
||||
#define PCI_DEVICE_ID_IBM_RATTLESNAKE 0x04DA
|
||||
|
||||
#define IPR_SUBS_DEV_ID_2780 0x0264
|
||||
#define IPR_SUBS_DEV_ID_5702 0x0266
|
||||
|
@ -111,6 +112,8 @@
|
|||
#define IPR_SUBS_DEV_ID_2CCA 0x04C7
|
||||
#define IPR_SUBS_DEV_ID_2CD2 0x04C8
|
||||
#define IPR_SUBS_DEV_ID_2CCD 0x04C9
|
||||
#define IPR_SUBS_DEV_ID_580A 0x04FC
|
||||
#define IPR_SUBS_DEV_ID_580B 0x04FB
|
||||
#define IPR_NAME "ipr"
|
||||
|
||||
/*
|
||||
|
|
|
@ -908,9 +908,17 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr *mp, u16 xid)
|
|||
{
|
||||
struct fc_exch_pool *pool;
|
||||
struct fc_exch *ep = NULL;
|
||||
u16 cpu = xid & fc_cpu_mask;
|
||||
|
||||
if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) {
|
||||
printk_ratelimited(KERN_ERR
|
||||
"libfc: lookup request for XID = %d, "
|
||||
"indicates invalid CPU %d\n", xid, cpu);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((xid >= mp->min_xid) && (xid <= mp->max_xid)) {
|
||||
pool = per_cpu_ptr(mp->pool, xid & fc_cpu_mask);
|
||||
pool = per_cpu_ptr(mp->pool, cpu);
|
||||
spin_lock_bh(&pool->lock);
|
||||
ep = fc_exch_ptr_get(pool, (xid - mp->min_xid) >> fc_cpu_order);
|
||||
if (ep) {
|
||||
|
|
|
@ -301,7 +301,6 @@ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
|
|||
{
|
||||
struct fc_host_statistics *fc_stats;
|
||||
struct fc_lport *lport = shost_priv(shost);
|
||||
struct timespec v0, v1;
|
||||
unsigned int cpu;
|
||||
u64 fcp_in_bytes = 0;
|
||||
u64 fcp_out_bytes = 0;
|
||||
|
@ -309,9 +308,7 @@ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
|
|||
fc_stats = &lport->host_stats;
|
||||
memset(fc_stats, 0, sizeof(struct fc_host_statistics));
|
||||
|
||||
jiffies_to_timespec(jiffies, &v0);
|
||||
jiffies_to_timespec(lport->boot_time, &v1);
|
||||
fc_stats->seconds_since_last_reset = (v0.tv_sec - v1.tv_sec);
|
||||
fc_stats->seconds_since_last_reset = (lport->boot_time - jiffies) / HZ;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
struct fc_stats *stats;
|
||||
|
@ -2090,7 +2087,7 @@ int fc_lport_bsg_request(struct fc_bsg_job *job)
|
|||
struct fc_rport *rport;
|
||||
struct fc_rport_priv *rdata;
|
||||
int rc = -EINVAL;
|
||||
u32 did;
|
||||
u32 did, tov;
|
||||
|
||||
job->reply->reply_payload_rcv_len = 0;
|
||||
if (rsp)
|
||||
|
@ -2121,15 +2118,20 @@ int fc_lport_bsg_request(struct fc_bsg_job *job)
|
|||
|
||||
case FC_BSG_HST_CT:
|
||||
did = ntoh24(job->request->rqst_data.h_ct.port_id);
|
||||
if (did == FC_FID_DIR_SERV)
|
||||
if (did == FC_FID_DIR_SERV) {
|
||||
rdata = lport->dns_rdata;
|
||||
else
|
||||
if (!rdata)
|
||||
break;
|
||||
tov = rdata->e_d_tov;
|
||||
} else {
|
||||
rdata = lport->tt.rport_lookup(lport, did);
|
||||
if (!rdata)
|
||||
break;
|
||||
tov = rdata->e_d_tov;
|
||||
kref_put(&rdata->kref, lport->tt.rport_destroy);
|
||||
}
|
||||
|
||||
if (!rdata)
|
||||
break;
|
||||
|
||||
rc = fc_lport_ct_request(job, lport, did, rdata->e_d_tov);
|
||||
rc = fc_lport_ct_request(job, lport, did, tov);
|
||||
break;
|
||||
|
||||
case FC_BSG_HST_ELS_NOLOGIN:
|
||||
|
|
|
@ -95,17 +95,23 @@ static const char *fc_rport_state_names[] = {
|
|||
* @lport: The local port to lookup the remote port on
|
||||
* @port_id: The remote port ID to look up
|
||||
*
|
||||
* The caller must hold either disc_mutex or rcu_read_lock().
|
||||
* The reference count of the fc_rport_priv structure is
|
||||
* increased by one.
|
||||
*/
|
||||
static struct fc_rport_priv *fc_rport_lookup(const struct fc_lport *lport,
|
||||
u32 port_id)
|
||||
{
|
||||
struct fc_rport_priv *rdata;
|
||||
struct fc_rport_priv *rdata = NULL, *tmp_rdata;
|
||||
|
||||
list_for_each_entry_rcu(rdata, &lport->disc.rports, peers)
|
||||
if (rdata->ids.port_id == port_id)
|
||||
return rdata;
|
||||
return NULL;
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(tmp_rdata, &lport->disc.rports, peers)
|
||||
if (tmp_rdata->ids.port_id == port_id &&
|
||||
kref_get_unless_zero(&tmp_rdata->kref)) {
|
||||
rdata = tmp_rdata;
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return rdata;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -340,7 +346,6 @@ static void fc_rport_work(struct work_struct *work)
|
|||
fc_remote_port_delete(rport);
|
||||
}
|
||||
|
||||
mutex_lock(&lport->disc.disc_mutex);
|
||||
mutex_lock(&rdata->rp_mutex);
|
||||
if (rdata->rp_state == RPORT_ST_DELETE) {
|
||||
if (port_id == FC_FID_DIR_SERV) {
|
||||
|
@ -370,7 +375,6 @@ static void fc_rport_work(struct work_struct *work)
|
|||
fc_rport_enter_ready(rdata);
|
||||
mutex_unlock(&rdata->rp_mutex);
|
||||
}
|
||||
mutex_unlock(&lport->disc.disc_mutex);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -702,7 +706,7 @@ out:
|
|||
err:
|
||||
mutex_unlock(&rdata->rp_mutex);
|
||||
put:
|
||||
kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
|
||||
kref_put(&rdata->kref, lport->tt.rport_destroy);
|
||||
return;
|
||||
bad:
|
||||
FC_RPORT_DBG(rdata, "Bad FLOGI response\n");
|
||||
|
@ -762,8 +766,6 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
|
|||
FC_RPORT_ID_DBG(lport, sid, "Received FLOGI request\n");
|
||||
|
||||
disc = &lport->disc;
|
||||
mutex_lock(&disc->disc_mutex);
|
||||
|
||||
if (!lport->point_to_multipoint) {
|
||||
rjt_data.reason = ELS_RJT_UNSUP;
|
||||
rjt_data.explan = ELS_EXPL_NONE;
|
||||
|
@ -808,7 +810,7 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
|
|||
mutex_unlock(&rdata->rp_mutex);
|
||||
rjt_data.reason = ELS_RJT_FIP;
|
||||
rjt_data.explan = ELS_EXPL_NOT_NEIGHBOR;
|
||||
goto reject;
|
||||
goto reject_put;
|
||||
case RPORT_ST_FLOGI:
|
||||
case RPORT_ST_PLOGI_WAIT:
|
||||
case RPORT_ST_PLOGI:
|
||||
|
@ -825,13 +827,13 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
|
|||
mutex_unlock(&rdata->rp_mutex);
|
||||
rjt_data.reason = ELS_RJT_BUSY;
|
||||
rjt_data.explan = ELS_EXPL_NONE;
|
||||
goto reject;
|
||||
goto reject_put;
|
||||
}
|
||||
if (fc_rport_login_complete(rdata, fp)) {
|
||||
mutex_unlock(&rdata->rp_mutex);
|
||||
rjt_data.reason = ELS_RJT_LOGIC;
|
||||
rjt_data.explan = ELS_EXPL_NONE;
|
||||
goto reject;
|
||||
goto reject_put;
|
||||
}
|
||||
|
||||
fp = fc_frame_alloc(lport, sizeof(*flp));
|
||||
|
@ -851,12 +853,13 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport,
|
|||
fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT);
|
||||
out:
|
||||
mutex_unlock(&rdata->rp_mutex);
|
||||
mutex_unlock(&disc->disc_mutex);
|
||||
kref_put(&rdata->kref, lport->tt.rport_destroy);
|
||||
fc_frame_free(rx_fp);
|
||||
return;
|
||||
|
||||
reject_put:
|
||||
kref_put(&rdata->kref, lport->tt.rport_destroy);
|
||||
reject:
|
||||
mutex_unlock(&disc->disc_mutex);
|
||||
lport->tt.seq_els_rsp_send(rx_fp, ELS_LS_RJT, &rjt_data);
|
||||
fc_frame_free(rx_fp);
|
||||
}
|
||||
|
@ -923,7 +926,7 @@ out:
|
|||
fc_frame_free(fp);
|
||||
err:
|
||||
mutex_unlock(&rdata->rp_mutex);
|
||||
kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
|
||||
kref_put(&rdata->kref, lport->tt.rport_destroy);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1477,14 +1480,11 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
|
|||
struct fc_rport_priv *rdata;
|
||||
struct fc_seq_els_data els_data;
|
||||
|
||||
mutex_lock(&lport->disc.disc_mutex);
|
||||
rdata = lport->tt.rport_lookup(lport, fc_frame_sid(fp));
|
||||
if (!rdata) {
|
||||
mutex_unlock(&lport->disc.disc_mutex);
|
||||
if (!rdata)
|
||||
goto reject;
|
||||
}
|
||||
|
||||
mutex_lock(&rdata->rp_mutex);
|
||||
mutex_unlock(&lport->disc.disc_mutex);
|
||||
|
||||
switch (rdata->rp_state) {
|
||||
case RPORT_ST_PRLI:
|
||||
|
@ -1494,6 +1494,7 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
|
|||
break;
|
||||
default:
|
||||
mutex_unlock(&rdata->rp_mutex);
|
||||
kref_put(&rdata->kref, lport->tt.rport_destroy);
|
||||
goto reject;
|
||||
}
|
||||
|
||||
|
@ -1524,6 +1525,7 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp)
|
|||
}
|
||||
|
||||
mutex_unlock(&rdata->rp_mutex);
|
||||
kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
|
||||
return;
|
||||
|
||||
reject:
|
||||
|
@ -1907,7 +1909,6 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp)
|
|||
|
||||
sid = fc_frame_sid(fp);
|
||||
|
||||
mutex_lock(&lport->disc.disc_mutex);
|
||||
rdata = lport->tt.rport_lookup(lport, sid);
|
||||
if (rdata) {
|
||||
mutex_lock(&rdata->rp_mutex);
|
||||
|
@ -1916,10 +1917,10 @@ static void fc_rport_recv_logo_req(struct fc_lport *lport, struct fc_frame *fp)
|
|||
|
||||
fc_rport_enter_delete(rdata, RPORT_EV_LOGO);
|
||||
mutex_unlock(&rdata->rp_mutex);
|
||||
kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy);
|
||||
} else
|
||||
FC_RPORT_ID_DBG(lport, sid,
|
||||
"Received LOGO from non-logged-in port\n");
|
||||
mutex_unlock(&lport->disc.disc_mutex);
|
||||
fc_frame_free(fp);
|
||||
}
|
||||
|
||||
|
|
|
@ -246,6 +246,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
|
|||
if (qc->scsicmd)
|
||||
ASSIGN_SAS_TASK(qc->scsicmd, NULL);
|
||||
sas_free_task(task);
|
||||
qc->lldd_task = NULL;
|
||||
ret = AC_ERR_SYSTEM;
|
||||
}
|
||||
|
||||
|
|
|
@ -647,6 +647,7 @@ struct lpfc_hba {
|
|||
#define HBA_RRQ_ACTIVE 0x4000 /* process the rrq active list */
|
||||
#define HBA_FCP_IOQ_FLUSH 0x8000 /* FCP 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 */
|
||||
uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/
|
||||
struct lpfc_dmabuf slim2p;
|
||||
|
||||
|
@ -694,7 +695,8 @@ struct lpfc_hba {
|
|||
uint8_t wwnn[8];
|
||||
uint8_t wwpn[8];
|
||||
uint32_t RandomData[7];
|
||||
uint32_t fcp_embed_io;
|
||||
uint8_t fcp_embed_io;
|
||||
uint8_t mds_diags_support;
|
||||
|
||||
/* HBA Config Parameters */
|
||||
uint32_t cfg_ack0;
|
||||
|
@ -741,6 +743,7 @@ struct lpfc_hba {
|
|||
#define OAS_FIND_ANY_VPORT 0x01
|
||||
#define OAS_FIND_ANY_TARGET 0x02
|
||||
#define OAS_LUN_VALID 0x04
|
||||
uint32_t cfg_oas_priority;
|
||||
uint32_t cfg_XLanePriority;
|
||||
uint32_t cfg_enable_bg;
|
||||
uint32_t cfg_hostmem_hgp;
|
||||
|
@ -751,6 +754,8 @@ struct lpfc_hba {
|
|||
uint32_t cfg_iocb_cnt;
|
||||
uint32_t cfg_suppress_link_up;
|
||||
uint32_t cfg_rrq_xri_bitmap_sz;
|
||||
uint32_t cfg_delay_discovery;
|
||||
uint32_t cfg_sli_mode;
|
||||
#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 */
|
||||
|
@ -759,6 +764,7 @@ struct lpfc_hba {
|
|||
#define LPFC_FDMI_NO_SUPPORT 0 /* FDMI not supported */
|
||||
#define LPFC_FDMI_SUPPORT 1 /* FDMI supported? */
|
||||
uint32_t cfg_enable_SmartSAN;
|
||||
uint32_t cfg_enable_mds_diags;
|
||||
lpfc_vpd_t vpd; /* vital product data */
|
||||
|
||||
struct pci_dev *pcidev;
|
||||
|
@ -779,9 +785,9 @@ struct lpfc_hba {
|
|||
|
||||
atomic_t fcp_qidx; /* next work queue to post work to */
|
||||
|
||||
unsigned long pci_bar0_map; /* Physical address for PCI BAR0 */
|
||||
unsigned long pci_bar1_map; /* Physical address for PCI BAR1 */
|
||||
unsigned long pci_bar2_map; /* Physical address for PCI BAR2 */
|
||||
phys_addr_t pci_bar0_map; /* Physical address for PCI BAR0 */
|
||||
phys_addr_t pci_bar1_map; /* Physical address for PCI BAR1 */
|
||||
phys_addr_t pci_bar2_map; /* Physical address for PCI BAR2 */
|
||||
void __iomem *slim_memmap_p; /* Kernel memory mapped address for
|
||||
PCI BAR0 */
|
||||
void __iomem *ctrl_regs_memmap_p;/* Kernel memory mapped address for
|
||||
|
@ -827,6 +833,7 @@ struct lpfc_hba {
|
|||
|
||||
struct timer_list fcp_poll_timer;
|
||||
struct timer_list eratt_poll;
|
||||
uint32_t eratt_poll_interval;
|
||||
|
||||
/*
|
||||
* stat counters
|
||||
|
@ -999,6 +1006,18 @@ struct lpfc_hba {
|
|||
spinlock_t devicelock; /* lock for luns list */
|
||||
mempool_t *device_data_mem_pool;
|
||||
struct list_head luns;
|
||||
#define LPFC_TRANSGRESSION_HIGH_TEMPERATURE 0x0080
|
||||
#define LPFC_TRANSGRESSION_LOW_TEMPERATURE 0x0040
|
||||
#define LPFC_TRANSGRESSION_HIGH_VOLTAGE 0x0020
|
||||
#define LPFC_TRANSGRESSION_LOW_VOLTAGE 0x0010
|
||||
#define LPFC_TRANSGRESSION_HIGH_TXBIAS 0x0008
|
||||
#define LPFC_TRANSGRESSION_LOW_TXBIAS 0x0004
|
||||
#define LPFC_TRANSGRESSION_HIGH_TXPOWER 0x0002
|
||||
#define LPFC_TRANSGRESSION_LOW_TXPOWER 0x0001
|
||||
#define LPFC_TRANSGRESSION_HIGH_RXPOWER 0x8000
|
||||
#define LPFC_TRANSGRESSION_LOW_RXPOWER 0x4000
|
||||
uint16_t sfp_alarm;
|
||||
uint16_t sfp_warning;
|
||||
};
|
||||
|
||||
static inline struct Scsi_Host *
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "lpfc_compat.h"
|
||||
#include "lpfc_crtn.h"
|
||||
#include "lpfc_vport.h"
|
||||
#include "lpfc_attr.h"
|
||||
|
||||
#define LPFC_DEF_DEVLOSS_TMO 30
|
||||
#define LPFC_MIN_DEVLOSS_TMO 1
|
||||
|
@ -1620,6 +1621,11 @@ lpfc_sriov_hw_max_virtfn_show(struct device *dev,
|
|||
return snprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn);
|
||||
}
|
||||
|
||||
static inline bool lpfc_rangecheck(uint val, uint min, uint max)
|
||||
{
|
||||
return val >= min && val <= max;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_param_show - Return a cfg attribute value in decimal
|
||||
*
|
||||
|
@ -1697,7 +1703,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
|
|||
static int \
|
||||
lpfc_##attr##_init(struct lpfc_hba *phba, uint val) \
|
||||
{ \
|
||||
if (val >= minval && val <= maxval) {\
|
||||
if (lpfc_rangecheck(val, minval, maxval)) {\
|
||||
phba->cfg_##attr = val;\
|
||||
return 0;\
|
||||
}\
|
||||
|
@ -1732,7 +1738,7 @@ lpfc_##attr##_init(struct lpfc_hba *phba, uint val) \
|
|||
static int \
|
||||
lpfc_##attr##_set(struct lpfc_hba *phba, uint val) \
|
||||
{ \
|
||||
if (val >= minval && val <= maxval) {\
|
||||
if (lpfc_rangecheck(val, minval, maxval)) {\
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, \
|
||||
"3052 lpfc_" #attr " changed from %d to %d\n", \
|
||||
phba->cfg_##attr, val); \
|
||||
|
@ -1856,7 +1862,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \
|
|||
static int \
|
||||
lpfc_##attr##_init(struct lpfc_vport *vport, uint val) \
|
||||
{ \
|
||||
if (val >= minval && val <= maxval) {\
|
||||
if (lpfc_rangecheck(val, minval, maxval)) {\
|
||||
vport->cfg_##attr = val;\
|
||||
return 0;\
|
||||
}\
|
||||
|
@ -1888,7 +1894,7 @@ lpfc_##attr##_init(struct lpfc_vport *vport, uint val) \
|
|||
static int \
|
||||
lpfc_##attr##_set(struct lpfc_vport *vport, uint val) \
|
||||
{ \
|
||||
if (val >= minval && val <= maxval) {\
|
||||
if (lpfc_rangecheck(val, minval, maxval)) {\
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, \
|
||||
"3053 lpfc_" #attr \
|
||||
" changed from %d (x%x) to %d (x%x)\n", \
|
||||
|
@ -1939,102 +1945,6 @@ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
|
|||
}
|
||||
|
||||
|
||||
#define LPFC_ATTR(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_param_init(name, defval, minval, maxval)
|
||||
|
||||
#define LPFC_ATTR_R(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_param_show(name)\
|
||||
lpfc_param_init(name, defval, minval, maxval)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
|
||||
|
||||
#define LPFC_ATTR_RW(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_param_show(name)\
|
||||
lpfc_param_init(name, defval, minval, maxval)\
|
||||
lpfc_param_set(name, defval, minval, maxval)\
|
||||
lpfc_param_store(name)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
|
||||
lpfc_##name##_show, lpfc_##name##_store)
|
||||
|
||||
#define LPFC_ATTR_HEX_R(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_param_hex_show(name)\
|
||||
lpfc_param_init(name, defval, minval, maxval)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
|
||||
|
||||
#define LPFC_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_param_hex_show(name)\
|
||||
lpfc_param_init(name, defval, minval, maxval)\
|
||||
lpfc_param_set(name, defval, minval, maxval)\
|
||||
lpfc_param_store(name)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
|
||||
lpfc_##name##_show, lpfc_##name##_store)
|
||||
|
||||
#define LPFC_VPORT_ATTR(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_vport_param_init(name, defval, minval, maxval)
|
||||
|
||||
#define LPFC_VPORT_ATTR_R(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_vport_param_show(name)\
|
||||
lpfc_vport_param_init(name, defval, minval, maxval)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
|
||||
|
||||
#define LPFC_VPORT_ULL_ATTR_R(name, defval, minval, maxval, desc) \
|
||||
static uint64_t lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, ullong, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_vport_param_show(name)\
|
||||
lpfc_vport_param_init(name, defval, minval, maxval)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
|
||||
|
||||
#define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_vport_param_show(name)\
|
||||
lpfc_vport_param_init(name, defval, minval, maxval)\
|
||||
lpfc_vport_param_set(name, defval, minval, maxval)\
|
||||
lpfc_vport_param_store(name)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
|
||||
lpfc_##name##_show, lpfc_##name##_store)
|
||||
|
||||
#define LPFC_VPORT_ATTR_HEX_R(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_vport_param_hex_show(name)\
|
||||
lpfc_vport_param_init(name, defval, minval, maxval)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
|
||||
|
||||
#define LPFC_VPORT_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_vport_param_hex_show(name)\
|
||||
lpfc_vport_param_init(name, defval, minval, maxval)\
|
||||
lpfc_vport_param_set(name, defval, minval, maxval)\
|
||||
lpfc_vport_param_store(name)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
|
||||
lpfc_##name##_show, lpfc_##name##_store)
|
||||
|
||||
static DEVICE_ATTR(bg_info, S_IRUGO, lpfc_bg_info_show, NULL);
|
||||
static DEVICE_ATTR(bg_guard_err, S_IRUGO, lpfc_bg_guard_err_show, NULL);
|
||||
static DEVICE_ATTR(bg_apptag_err, S_IRUGO, lpfc_bg_apptag_err_show, NULL);
|
||||
|
@ -2400,6 +2310,69 @@ lpfc_oas_tgt_store(struct device *dev, struct device_attribute *attr,
|
|||
static DEVICE_ATTR(lpfc_xlane_tgt, S_IRUGO | S_IWUSR,
|
||||
lpfc_oas_tgt_show, lpfc_oas_tgt_store);
|
||||
|
||||
/**
|
||||
* lpfc_oas_priority_show - Return wwpn of target whose luns maybe enabled for
|
||||
* Optimized Access Storage (OAS) operations.
|
||||
* @dev: class device that is converted into a Scsi_host.
|
||||
* @attr: device attribute, not used.
|
||||
* @buf: buffer for passing information.
|
||||
*
|
||||
* Returns:
|
||||
* value of count
|
||||
**/
|
||||
static ssize_t
|
||||
lpfc_oas_priority_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 snprintf(buf, PAGE_SIZE, "%d\n", phba->cfg_oas_priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_oas_priority_store - Store wwpn of target whose luns maybe enabled for
|
||||
* Optimized Access Storage (OAS) operations.
|
||||
* @dev: class device that is converted into a Scsi_host.
|
||||
* @attr: device attribute, not used.
|
||||
* @buf: buffer for passing information.
|
||||
* @count: Size of the data buffer.
|
||||
*
|
||||
* Returns:
|
||||
* -EINVAL count is invalid, invalid wwpn byte invalid
|
||||
* -EPERM oas is not supported by hba
|
||||
* value of count on success
|
||||
**/
|
||||
static ssize_t
|
||||
lpfc_oas_priority_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
|
||||
unsigned int cnt = count;
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
if (!phba->cfg_fof)
|
||||
return -EPERM;
|
||||
|
||||
/* count may include a LF at end of string */
|
||||
if (buf[cnt-1] == '\n')
|
||||
cnt--;
|
||||
|
||||
ret = kstrtoul(buf, 0, &val);
|
||||
if (ret || (val > 0x7f))
|
||||
return -EINVAL;
|
||||
|
||||
if (val)
|
||||
phba->cfg_oas_priority = (uint8_t)val;
|
||||
else
|
||||
phba->cfg_oas_priority = phba->cfg_XLanePriority;
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR(lpfc_xlane_priority, S_IRUGO | S_IWUSR,
|
||||
lpfc_oas_priority_show, lpfc_oas_priority_store);
|
||||
|
||||
/**
|
||||
* lpfc_oas_vpt_show - Return wwpn of vport whose targets maybe enabled
|
||||
* for Optimized Access Storage (OAS) operations.
|
||||
|
@ -2462,6 +2435,7 @@ lpfc_oas_vpt_store(struct device *dev, struct device_attribute *attr,
|
|||
else
|
||||
phba->cfg_oas_flags &= ~OAS_FIND_ANY_VPORT;
|
||||
phba->cfg_oas_flags &= ~OAS_LUN_VALID;
|
||||
phba->cfg_oas_priority = phba->cfg_XLanePriority;
|
||||
phba->sli4_hba.oas_next_lun = FIND_FIRST_OAS_LUN;
|
||||
return count;
|
||||
}
|
||||
|
@ -2524,7 +2498,6 @@ lpfc_oas_lun_state_store(struct device *dev, struct device_attribute *attr,
|
|||
return -EINVAL;
|
||||
|
||||
phba->cfg_oas_lun_state = val;
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
static DEVICE_ATTR(lpfc_xlane_lun_state, S_IRUGO | S_IWUSR,
|
||||
|
@ -2572,7 +2545,8 @@ static DEVICE_ATTR(lpfc_xlane_lun_status, S_IRUGO,
|
|||
*/
|
||||
static size_t
|
||||
lpfc_oas_lun_state_set(struct lpfc_hba *phba, uint8_t vpt_wwpn[],
|
||||
uint8_t tgt_wwpn[], uint64_t lun, uint32_t oas_state)
|
||||
uint8_t tgt_wwpn[], uint64_t lun,
|
||||
uint32_t oas_state, uint8_t pri)
|
||||
{
|
||||
|
||||
int rc = 0;
|
||||
|
@ -2582,7 +2556,8 @@ lpfc_oas_lun_state_set(struct lpfc_hba *phba, uint8_t vpt_wwpn[],
|
|||
|
||||
if (oas_state) {
|
||||
if (!lpfc_enable_oas_lun(phba, (struct lpfc_name *)vpt_wwpn,
|
||||
(struct lpfc_name *)tgt_wwpn, lun))
|
||||
(struct lpfc_name *)tgt_wwpn,
|
||||
lun, pri))
|
||||
rc = -ENOMEM;
|
||||
} else {
|
||||
lpfc_disable_oas_lun(phba, (struct lpfc_name *)vpt_wwpn,
|
||||
|
@ -2648,13 +2623,13 @@ lpfc_oas_lun_get_next(struct lpfc_hba *phba, uint8_t vpt_wwpn[],
|
|||
static ssize_t
|
||||
lpfc_oas_lun_state_change(struct lpfc_hba *phba, uint8_t vpt_wwpn[],
|
||||
uint8_t tgt_wwpn[], uint64_t lun,
|
||||
uint32_t oas_state)
|
||||
uint32_t oas_state, uint8_t pri)
|
||||
{
|
||||
|
||||
int rc;
|
||||
|
||||
rc = lpfc_oas_lun_state_set(phba, vpt_wwpn, tgt_wwpn, lun,
|
||||
oas_state);
|
||||
oas_state, pri);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -2744,16 +2719,16 @@ lpfc_oas_lun_store(struct device *dev, struct device_attribute *attr,
|
|||
return -EINVAL;
|
||||
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
|
||||
"3372 Try to set vport 0x%llx target 0x%llx lun:%lld "
|
||||
"with oas set to %d\n",
|
||||
"3372 Try to set vport 0x%llx target 0x%llx lun:0x%llx "
|
||||
"priority 0x%x with oas state %d\n",
|
||||
wwn_to_u64(phba->cfg_oas_vpt_wwpn),
|
||||
wwn_to_u64(phba->cfg_oas_tgt_wwpn), scsi_lun,
|
||||
phba->cfg_oas_lun_state);
|
||||
phba->cfg_oas_priority, phba->cfg_oas_lun_state);
|
||||
|
||||
rc = lpfc_oas_lun_state_change(phba, phba->cfg_oas_vpt_wwpn,
|
||||
phba->cfg_oas_tgt_wwpn, scsi_lun,
|
||||
phba->cfg_oas_lun_state);
|
||||
|
||||
phba->cfg_oas_tgt_wwpn, scsi_lun,
|
||||
phba->cfg_oas_lun_state,
|
||||
phba->cfg_oas_priority);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -2772,19 +2747,14 @@ MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:"
|
|||
static DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
|
||||
lpfc_poll_show, lpfc_poll_store);
|
||||
|
||||
int lpfc_sli_mode = 0;
|
||||
module_param(lpfc_sli_mode, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:"
|
||||
" 0 - auto (SLI-3 if supported),"
|
||||
" 2 - select SLI-2 even on SLI-3 capable HBAs,"
|
||||
" 3 - select SLI-3");
|
||||
LPFC_ATTR(sli_mode, 0, 0, 3,
|
||||
"SLI mode selector:"
|
||||
" 0 - auto (SLI-3 if supported),"
|
||||
" 2 - select SLI-2 even on SLI-3 capable HBAs,"
|
||||
" 3 - select SLI-3");
|
||||
|
||||
int lpfc_enable_npiv = 1;
|
||||
module_param(lpfc_enable_npiv, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(lpfc_enable_npiv, "Enable NPIV functionality");
|
||||
lpfc_param_show(enable_npiv);
|
||||
lpfc_param_init(enable_npiv, 1, 0, 1);
|
||||
static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL);
|
||||
LPFC_ATTR_R(enable_npiv, 1, 0, 1,
|
||||
"Enable NPIV functionality");
|
||||
|
||||
LPFC_ATTR_R(fcf_failover_policy, 1, 1, 2,
|
||||
"FCF Fast failover=1 Priority failover=2");
|
||||
|
@ -4754,11 +4724,8 @@ MODULE_PARM_DESC(lpfc_prot_guard, "host protection guard type");
|
|||
* accept and FCID/Fabric name/Fabric portname is changed.
|
||||
* Default value is 0.
|
||||
*/
|
||||
int lpfc_delay_discovery;
|
||||
module_param(lpfc_delay_discovery, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(lpfc_delay_discovery,
|
||||
"Delay NPort discovery when Clean Address bit is cleared. "
|
||||
"Allowed values: 0,1.");
|
||||
LPFC_ATTR(delay_discovery, 0, 0, 1,
|
||||
"Delay NPort discovery when Clean Address bit is cleared.");
|
||||
|
||||
/*
|
||||
* lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count
|
||||
|
@ -4780,6 +4747,14 @@ LPFC_ATTR_R(prot_sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT,
|
|||
LPFC_DEFAULT_SG_SEG_CNT, LPFC_MAX_SG_SEG_CNT,
|
||||
"Max Protection Scatter Gather Segment Count");
|
||||
|
||||
/*
|
||||
* lpfc_enable_mds_diags: Enable MDS Diagnostics
|
||||
* 0 = MDS Diagnostics disabled (default)
|
||||
* 1 = MDS Diagnostics enabled
|
||||
* Value range is [0,1]. Default value is 0.
|
||||
*/
|
||||
LPFC_ATTR_R(enable_mds_diags, 0, 0, 1, "Enable MDS Diagnostics");
|
||||
|
||||
struct device_attribute *lpfc_hba_attrs[] = {
|
||||
&dev_attr_bg_info,
|
||||
&dev_attr_bg_guard_err,
|
||||
|
@ -4857,6 +4832,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
|
|||
&dev_attr_lpfc_xlane_vpt,
|
||||
&dev_attr_lpfc_xlane_lun_state,
|
||||
&dev_attr_lpfc_xlane_lun_status,
|
||||
&dev_attr_lpfc_xlane_priority,
|
||||
&dev_attr_lpfc_sg_seg_cnt,
|
||||
&dev_attr_lpfc_max_scsicmpl_time,
|
||||
&dev_attr_lpfc_stat_data_ctrl,
|
||||
|
@ -4876,6 +4852,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
|
|||
&dev_attr_lpfc_sriov_hw_max_virtfn,
|
||||
&dev_attr_protocol,
|
||||
&dev_attr_lpfc_xlane_supported,
|
||||
&dev_attr_lpfc_enable_mds_diags,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -5849,6 +5826,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
|
|||
phba->cfg_oas_lun_state = 0;
|
||||
phba->cfg_oas_lun_status = 0;
|
||||
phba->cfg_oas_flags = 0;
|
||||
phba->cfg_oas_priority = 0;
|
||||
lpfc_enable_bg_init(phba, lpfc_enable_bg);
|
||||
if (phba->sli_rev == LPFC_SLI_REV4)
|
||||
phba->cfg_poll = 0;
|
||||
|
@ -5866,7 +5844,10 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
|
|||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.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_ATTR(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_param_init(name, defval, minval, maxval)
|
||||
|
||||
#define LPFC_ATTR_R(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_param_show(name)\
|
||||
lpfc_param_init(name, defval, minval, maxval)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO, lpfc_##name##_show, NULL)
|
||||
|
||||
#define LPFC_ATTR_RW(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_param_show(name)\
|
||||
lpfc_param_init(name, defval, minval, maxval)\
|
||||
lpfc_param_set(name, defval, minval, maxval)\
|
||||
lpfc_param_store(name)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
|
||||
lpfc_##name##_show, lpfc_##name##_store)
|
||||
|
||||
#define LPFC_ATTR_HEX_R(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_param_hex_show(name)\
|
||||
lpfc_param_init(name, defval, minval, maxval)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO, lpfc_##name##_show, NULL)
|
||||
|
||||
#define LPFC_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_param_hex_show(name)\
|
||||
lpfc_param_init(name, defval, minval, maxval)\
|
||||
lpfc_param_set(name, defval, minval, maxval)\
|
||||
lpfc_param_store(name)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
|
||||
lpfc_##name##_show, lpfc_##name##_store)
|
||||
|
||||
#define LPFC_VPORT_ATTR(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_vport_param_init(name, defval, minval, maxval)
|
||||
|
||||
#define LPFC_VPORT_ATTR_R(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_vport_param_show(name)\
|
||||
lpfc_vport_param_init(name, defval, minval, maxval)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO, lpfc_##name##_show, NULL)
|
||||
|
||||
#define LPFC_VPORT_ULL_ATTR_R(name, defval, minval, maxval, desc) \
|
||||
static uint64_t lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, ullong, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_vport_param_show(name)\
|
||||
lpfc_vport_param_init(name, defval, minval, maxval)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO, lpfc_##name##_show, NULL)
|
||||
|
||||
#define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_vport_param_show(name)\
|
||||
lpfc_vport_param_init(name, defval, minval, maxval)\
|
||||
lpfc_vport_param_set(name, defval, minval, maxval)\
|
||||
lpfc_vport_param_store(name)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
|
||||
lpfc_##name##_show, lpfc_##name##_store)
|
||||
|
||||
#define LPFC_VPORT_ATTR_HEX_R(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_vport_param_hex_show(name)\
|
||||
lpfc_vport_param_init(name, defval, minval, maxval)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO, lpfc_##name##_show, NULL)
|
||||
|
||||
#define LPFC_VPORT_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_vport_param_hex_show(name)\
|
||||
lpfc_vport_param_init(name, defval, minval, maxval)\
|
||||
lpfc_vport_param_set(name, defval, minval, maxval)\
|
||||
lpfc_vport_param_store(name)\
|
||||
static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
|
||||
lpfc_##name##_show, lpfc_##name##_store)
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2015 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
|
@ -359,9 +359,6 @@ extern struct scsi_host_template lpfc_template_s3;
|
|||
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;
|
||||
extern int lpfc_sli_mode;
|
||||
extern int lpfc_enable_npiv;
|
||||
extern int lpfc_delay_discovery;
|
||||
|
||||
int lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t);
|
||||
int lpfc_vport_symbolic_port_name(struct lpfc_vport *, char *, size_t);
|
||||
|
@ -492,7 +489,7 @@ struct lpfc_device_data *__lpfc_get_device_data(struct lpfc_hba *,
|
|||
struct lpfc_name *,
|
||||
struct lpfc_name *, uint64_t);
|
||||
bool lpfc_enable_oas_lun(struct lpfc_hba *, struct lpfc_name *,
|
||||
struct lpfc_name *, uint64_t);
|
||||
struct lpfc_name *, uint64_t, uint8_t);
|
||||
bool lpfc_disable_oas_lun(struct lpfc_hba *, struct lpfc_name *,
|
||||
struct lpfc_name *, uint64_t);
|
||||
bool lpfc_find_next_oas_lun(struct lpfc_hba *, struct lpfc_name *,
|
||||
|
|
|
@ -1510,6 +1510,10 @@ lpfc_fdmi_num_disc_check(struct lpfc_vport *vport)
|
|||
if (!lpfc_is_link_up(phba))
|
||||
return;
|
||||
|
||||
/* Must be connected to a Fabric */
|
||||
if (!(vport->fc_flag & FC_FABRIC))
|
||||
return;
|
||||
|
||||
if (!(vport->fdmi_port_mask & LPFC_FDMI_PORT_ATTR_num_disc))
|
||||
return;
|
||||
|
||||
|
|
|
@ -594,6 +594,7 @@ static uint8_t
|
|||
lpfc_check_clean_addr_bit(struct lpfc_vport *vport,
|
||||
struct serv_parm *sp)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
uint8_t fabric_param_changed = 0;
|
||||
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
|
||||
|
||||
|
@ -615,7 +616,7 @@ lpfc_check_clean_addr_bit(struct lpfc_vport *vport,
|
|||
* - lpfc_delay_discovery module parameter is set.
|
||||
*/
|
||||
if (fabric_param_changed && !sp->cmn.clean_address_bit &&
|
||||
(vport->fc_prevDID || lpfc_delay_discovery)) {
|
||||
(vport->fc_prevDID || phba->cfg_delay_discovery)) {
|
||||
spin_lock_irq(shost->host_lock);
|
||||
vport->fc_flag |= FC_DISC_DELAYED;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
|
@ -3299,6 +3300,12 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
FC_VPORT_FABRIC_REJ_WWN);
|
||||
}
|
||||
break;
|
||||
case LSRJT_VENDOR_UNIQUE:
|
||||
if ((stat.un.b.vendorUnique == 0x45) &&
|
||||
(cmd == ELS_CMD_FLOGI)) {
|
||||
goto out_retry;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -3344,6 +3351,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
if ((vport->load_flag & FC_UNLOADING) != 0)
|
||||
retry = 0;
|
||||
|
||||
out_retry:
|
||||
if (retry) {
|
||||
if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_FDISC)) {
|
||||
/* Stop retrying PLOGI and FDISC if in FCF discovery */
|
||||
|
@ -4609,7 +4617,7 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport)
|
|||
return sentplogi;
|
||||
}
|
||||
|
||||
void
|
||||
uint32_t
|
||||
lpfc_rdp_res_link_service(struct fc_rdp_link_service_desc *desc,
|
||||
uint32_t word0)
|
||||
{
|
||||
|
@ -4617,9 +4625,11 @@ lpfc_rdp_res_link_service(struct fc_rdp_link_service_desc *desc,
|
|||
desc->tag = cpu_to_be32(RDP_LINK_SERVICE_DESC_TAG);
|
||||
desc->payload.els_req = word0;
|
||||
desc->length = cpu_to_be32(sizeof(desc->payload));
|
||||
|
||||
return sizeof(struct fc_rdp_link_service_desc);
|
||||
}
|
||||
|
||||
void
|
||||
uint32_t
|
||||
lpfc_rdp_res_sfp_desc(struct fc_rdp_sfp_desc *desc,
|
||||
uint8_t *page_a0, uint8_t *page_a2)
|
||||
{
|
||||
|
@ -4680,9 +4690,11 @@ lpfc_rdp_res_sfp_desc(struct fc_rdp_sfp_desc *desc,
|
|||
|
||||
desc->sfp_info.flags = cpu_to_be16(flag);
|
||||
desc->length = cpu_to_be32(sizeof(desc->sfp_info));
|
||||
|
||||
return sizeof(struct fc_rdp_sfp_desc);
|
||||
}
|
||||
|
||||
void
|
||||
uint32_t
|
||||
lpfc_rdp_res_link_error(struct fc_rdp_link_error_status_desc *desc,
|
||||
READ_LNK_VAR *stat)
|
||||
{
|
||||
|
@ -4707,134 +4719,181 @@ lpfc_rdp_res_link_error(struct fc_rdp_link_error_status_desc *desc,
|
|||
desc->info.link_status.invalid_crc_cnt = cpu_to_be32(stat->crcCnt);
|
||||
|
||||
desc->length = cpu_to_be32(sizeof(desc->info));
|
||||
|
||||
return sizeof(struct fc_rdp_link_error_status_desc);
|
||||
}
|
||||
|
||||
void
|
||||
uint32_t
|
||||
lpfc_rdp_res_bbc_desc(struct fc_rdp_bbc_desc *desc, READ_LNK_VAR *stat,
|
||||
struct lpfc_vport *vport)
|
||||
{
|
||||
uint32_t bbCredit;
|
||||
|
||||
desc->tag = cpu_to_be32(RDP_BBC_DESC_TAG);
|
||||
|
||||
desc->bbc_info.port_bbc = cpu_to_be32(
|
||||
vport->fc_sparam.cmn.bbCreditMsb |
|
||||
vport->fc_sparam.cmn.bbCreditlsb << 8);
|
||||
if (vport->phba->fc_topology != LPFC_TOPOLOGY_LOOP)
|
||||
desc->bbc_info.attached_port_bbc = cpu_to_be32(
|
||||
vport->phba->fc_fabparam.cmn.bbCreditMsb |
|
||||
vport->phba->fc_fabparam.cmn.bbCreditlsb << 8);
|
||||
else
|
||||
bbCredit = vport->fc_sparam.cmn.bbCreditLsb |
|
||||
(vport->fc_sparam.cmn.bbCreditMsb << 8);
|
||||
desc->bbc_info.port_bbc = cpu_to_be32(bbCredit);
|
||||
if (vport->phba->fc_topology != LPFC_TOPOLOGY_LOOP) {
|
||||
bbCredit = vport->phba->fc_fabparam.cmn.bbCreditLsb |
|
||||
(vport->phba->fc_fabparam.cmn.bbCreditMsb << 8);
|
||||
desc->bbc_info.attached_port_bbc = cpu_to_be32(bbCredit);
|
||||
} else {
|
||||
desc->bbc_info.attached_port_bbc = 0;
|
||||
}
|
||||
|
||||
desc->bbc_info.rtt = 0;
|
||||
desc->length = cpu_to_be32(sizeof(desc->bbc_info));
|
||||
|
||||
return sizeof(struct fc_rdp_bbc_desc);
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_rdp_res_oed_temp_desc(struct fc_rdp_oed_sfp_desc *desc, uint8_t *page_a2)
|
||||
uint32_t
|
||||
lpfc_rdp_res_oed_temp_desc(struct lpfc_hba *phba,
|
||||
struct fc_rdp_oed_sfp_desc *desc, uint8_t *page_a2)
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t flags = 0;
|
||||
|
||||
desc->tag = cpu_to_be32(RDP_OED_DESC_TAG);
|
||||
|
||||
desc->oed_info.hi_alarm =
|
||||
cpu_to_be16(page_a2[SSF_TEMP_HIGH_ALARM]);
|
||||
desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_TEMP_LOW_ALARM]);
|
||||
desc->oed_info.hi_warning =
|
||||
cpu_to_be16(page_a2[SSF_TEMP_HIGH_WARNING]);
|
||||
desc->oed_info.lo_warning =
|
||||
cpu_to_be16(page_a2[SSF_TEMP_LOW_WARNING]);
|
||||
flags = 0xf; /* All four are valid */
|
||||
desc->oed_info.hi_alarm = page_a2[SSF_TEMP_HIGH_ALARM];
|
||||
desc->oed_info.lo_alarm = page_a2[SSF_TEMP_LOW_ALARM];
|
||||
desc->oed_info.hi_warning = page_a2[SSF_TEMP_HIGH_WARNING];
|
||||
desc->oed_info.lo_warning = page_a2[SSF_TEMP_LOW_WARNING];
|
||||
|
||||
if (phba->sfp_alarm & LPFC_TRANSGRESSION_HIGH_TEMPERATURE)
|
||||
flags |= RDP_OET_HIGH_ALARM;
|
||||
if (phba->sfp_alarm & LPFC_TRANSGRESSION_LOW_TEMPERATURE)
|
||||
flags |= RDP_OET_LOW_ALARM;
|
||||
if (phba->sfp_warning & LPFC_TRANSGRESSION_HIGH_TEMPERATURE)
|
||||
flags |= RDP_OET_HIGH_WARNING;
|
||||
if (phba->sfp_warning & LPFC_TRANSGRESSION_LOW_TEMPERATURE)
|
||||
flags |= RDP_OET_LOW_WARNING;
|
||||
|
||||
flags |= ((0xf & RDP_OED_TEMPERATURE) << RDP_OED_TYPE_SHIFT);
|
||||
desc->oed_info.function_flags = cpu_to_be32(flags);
|
||||
desc->length = cpu_to_be32(sizeof(desc->oed_info));
|
||||
return sizeof(struct fc_rdp_oed_sfp_desc);
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_rdp_res_oed_voltage_desc(struct fc_rdp_oed_sfp_desc *desc,
|
||||
uint32_t
|
||||
lpfc_rdp_res_oed_voltage_desc(struct lpfc_hba *phba,
|
||||
struct fc_rdp_oed_sfp_desc *desc,
|
||||
uint8_t *page_a2)
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t flags = 0;
|
||||
|
||||
desc->tag = cpu_to_be32(RDP_OED_DESC_TAG);
|
||||
|
||||
desc->oed_info.hi_alarm =
|
||||
cpu_to_be16(page_a2[SSF_VOLTAGE_HIGH_ALARM]);
|
||||
desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_VOLTAGE_LOW_ALARM]);
|
||||
desc->oed_info.hi_warning =
|
||||
cpu_to_be16(page_a2[SSF_VOLTAGE_HIGH_WARNING]);
|
||||
desc->oed_info.lo_warning =
|
||||
cpu_to_be16(page_a2[SSF_VOLTAGE_LOW_WARNING]);
|
||||
flags = 0xf; /* All four are valid */
|
||||
desc->oed_info.hi_alarm = page_a2[SSF_VOLTAGE_HIGH_ALARM];
|
||||
desc->oed_info.lo_alarm = page_a2[SSF_VOLTAGE_LOW_ALARM];
|
||||
desc->oed_info.hi_warning = page_a2[SSF_VOLTAGE_HIGH_WARNING];
|
||||
desc->oed_info.lo_warning = page_a2[SSF_VOLTAGE_LOW_WARNING];
|
||||
|
||||
if (phba->sfp_alarm & LPFC_TRANSGRESSION_HIGH_VOLTAGE)
|
||||
flags |= RDP_OET_HIGH_ALARM;
|
||||
if (phba->sfp_alarm & LPFC_TRANSGRESSION_LOW_VOLTAGE)
|
||||
flags |= RDP_OET_LOW_ALARM;
|
||||
if (phba->sfp_warning & LPFC_TRANSGRESSION_HIGH_VOLTAGE)
|
||||
flags |= RDP_OET_HIGH_WARNING;
|
||||
if (phba->sfp_warning & LPFC_TRANSGRESSION_LOW_VOLTAGE)
|
||||
flags |= RDP_OET_LOW_WARNING;
|
||||
|
||||
flags |= ((0xf & RDP_OED_VOLTAGE) << RDP_OED_TYPE_SHIFT);
|
||||
desc->oed_info.function_flags = cpu_to_be32(flags);
|
||||
desc->length = cpu_to_be32(sizeof(desc->oed_info));
|
||||
return sizeof(struct fc_rdp_oed_sfp_desc);
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_rdp_res_oed_txbias_desc(struct fc_rdp_oed_sfp_desc *desc,
|
||||
uint32_t
|
||||
lpfc_rdp_res_oed_txbias_desc(struct lpfc_hba *phba,
|
||||
struct fc_rdp_oed_sfp_desc *desc,
|
||||
uint8_t *page_a2)
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t flags = 0;
|
||||
|
||||
desc->tag = cpu_to_be32(RDP_OED_DESC_TAG);
|
||||
|
||||
desc->oed_info.hi_alarm =
|
||||
cpu_to_be16(page_a2[SSF_BIAS_HIGH_ALARM]);
|
||||
desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_BIAS_LOW_ALARM]);
|
||||
desc->oed_info.hi_warning =
|
||||
cpu_to_be16(page_a2[SSF_BIAS_HIGH_WARNING]);
|
||||
desc->oed_info.lo_warning =
|
||||
cpu_to_be16(page_a2[SSF_BIAS_LOW_WARNING]);
|
||||
flags = 0xf; /* All four are valid */
|
||||
desc->oed_info.hi_alarm = page_a2[SSF_BIAS_HIGH_ALARM];
|
||||
desc->oed_info.lo_alarm = page_a2[SSF_BIAS_LOW_ALARM];
|
||||
desc->oed_info.hi_warning = page_a2[SSF_BIAS_HIGH_WARNING];
|
||||
desc->oed_info.lo_warning = page_a2[SSF_BIAS_LOW_WARNING];
|
||||
|
||||
if (phba->sfp_alarm & LPFC_TRANSGRESSION_HIGH_TXBIAS)
|
||||
flags |= RDP_OET_HIGH_ALARM;
|
||||
if (phba->sfp_alarm & LPFC_TRANSGRESSION_LOW_TXBIAS)
|
||||
flags |= RDP_OET_LOW_ALARM;
|
||||
if (phba->sfp_warning & LPFC_TRANSGRESSION_HIGH_TXBIAS)
|
||||
flags |= RDP_OET_HIGH_WARNING;
|
||||
if (phba->sfp_warning & LPFC_TRANSGRESSION_LOW_TXBIAS)
|
||||
flags |= RDP_OET_LOW_WARNING;
|
||||
|
||||
flags |= ((0xf & RDP_OED_TXBIAS) << RDP_OED_TYPE_SHIFT);
|
||||
desc->oed_info.function_flags = cpu_to_be32(flags);
|
||||
desc->length = cpu_to_be32(sizeof(desc->oed_info));
|
||||
return sizeof(struct fc_rdp_oed_sfp_desc);
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_rdp_res_oed_txpower_desc(struct fc_rdp_oed_sfp_desc *desc,
|
||||
uint32_t
|
||||
lpfc_rdp_res_oed_txpower_desc(struct lpfc_hba *phba,
|
||||
struct fc_rdp_oed_sfp_desc *desc,
|
||||
uint8_t *page_a2)
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t flags = 0;
|
||||
|
||||
desc->tag = cpu_to_be32(RDP_OED_DESC_TAG);
|
||||
|
||||
desc->oed_info.hi_alarm =
|
||||
cpu_to_be16(page_a2[SSF_TXPOWER_HIGH_ALARM]);
|
||||
desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_TXPOWER_LOW_ALARM]);
|
||||
desc->oed_info.hi_warning =
|
||||
cpu_to_be16(page_a2[SSF_TXPOWER_HIGH_WARNING]);
|
||||
desc->oed_info.lo_warning =
|
||||
cpu_to_be16(page_a2[SSF_TXPOWER_LOW_WARNING]);
|
||||
flags = 0xf; /* All four are valid */
|
||||
desc->oed_info.hi_alarm = page_a2[SSF_TXPOWER_HIGH_ALARM];
|
||||
desc->oed_info.lo_alarm = page_a2[SSF_TXPOWER_LOW_ALARM];
|
||||
desc->oed_info.hi_warning = page_a2[SSF_TXPOWER_HIGH_WARNING];
|
||||
desc->oed_info.lo_warning = page_a2[SSF_TXPOWER_LOW_WARNING];
|
||||
|
||||
if (phba->sfp_alarm & LPFC_TRANSGRESSION_HIGH_TXPOWER)
|
||||
flags |= RDP_OET_HIGH_ALARM;
|
||||
if (phba->sfp_alarm & LPFC_TRANSGRESSION_LOW_TXPOWER)
|
||||
flags |= RDP_OET_LOW_ALARM;
|
||||
if (phba->sfp_warning & LPFC_TRANSGRESSION_HIGH_TXPOWER)
|
||||
flags |= RDP_OET_HIGH_WARNING;
|
||||
if (phba->sfp_warning & LPFC_TRANSGRESSION_LOW_TXPOWER)
|
||||
flags |= RDP_OET_LOW_WARNING;
|
||||
|
||||
flags |= ((0xf & RDP_OED_TXPOWER) << RDP_OED_TYPE_SHIFT);
|
||||
desc->oed_info.function_flags = cpu_to_be32(flags);
|
||||
desc->length = cpu_to_be32(sizeof(desc->oed_info));
|
||||
return sizeof(struct fc_rdp_oed_sfp_desc);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lpfc_rdp_res_oed_rxpower_desc(struct fc_rdp_oed_sfp_desc *desc,
|
||||
uint32_t
|
||||
lpfc_rdp_res_oed_rxpower_desc(struct lpfc_hba *phba,
|
||||
struct fc_rdp_oed_sfp_desc *desc,
|
||||
uint8_t *page_a2)
|
||||
{
|
||||
uint32_t flags;
|
||||
uint32_t flags = 0;
|
||||
|
||||
desc->tag = cpu_to_be32(RDP_OED_DESC_TAG);
|
||||
|
||||
desc->oed_info.hi_alarm =
|
||||
cpu_to_be16(page_a2[SSF_RXPOWER_HIGH_ALARM]);
|
||||
desc->oed_info.lo_alarm = cpu_to_be16(page_a2[SSF_RXPOWER_LOW_ALARM]);
|
||||
desc->oed_info.hi_warning =
|
||||
cpu_to_be16(page_a2[SSF_RXPOWER_HIGH_WARNING]);
|
||||
desc->oed_info.lo_warning =
|
||||
cpu_to_be16(page_a2[SSF_RXPOWER_LOW_WARNING]);
|
||||
flags = 0xf; /* All four are valid */
|
||||
desc->oed_info.hi_alarm = page_a2[SSF_RXPOWER_HIGH_ALARM];
|
||||
desc->oed_info.lo_alarm = page_a2[SSF_RXPOWER_LOW_ALARM];
|
||||
desc->oed_info.hi_warning = page_a2[SSF_RXPOWER_HIGH_WARNING];
|
||||
desc->oed_info.lo_warning = page_a2[SSF_RXPOWER_LOW_WARNING];
|
||||
|
||||
if (phba->sfp_alarm & LPFC_TRANSGRESSION_HIGH_RXPOWER)
|
||||
flags |= RDP_OET_HIGH_ALARM;
|
||||
if (phba->sfp_alarm & LPFC_TRANSGRESSION_LOW_RXPOWER)
|
||||
flags |= RDP_OET_LOW_ALARM;
|
||||
if (phba->sfp_warning & LPFC_TRANSGRESSION_HIGH_RXPOWER)
|
||||
flags |= RDP_OET_HIGH_WARNING;
|
||||
if (phba->sfp_warning & LPFC_TRANSGRESSION_LOW_RXPOWER)
|
||||
flags |= RDP_OET_LOW_WARNING;
|
||||
|
||||
flags |= ((0xf & RDP_OED_RXPOWER) << RDP_OED_TYPE_SHIFT);
|
||||
desc->oed_info.function_flags = cpu_to_be32(flags);
|
||||
desc->length = cpu_to_be32(sizeof(desc->oed_info));
|
||||
return sizeof(struct fc_rdp_oed_sfp_desc);
|
||||
}
|
||||
|
||||
void
|
||||
uint32_t
|
||||
lpfc_rdp_res_opd_desc(struct fc_rdp_opd_sfp_desc *desc,
|
||||
uint8_t *page_a0, struct lpfc_vport *vport)
|
||||
{
|
||||
|
@ -4845,9 +4904,10 @@ lpfc_rdp_res_opd_desc(struct fc_rdp_opd_sfp_desc *desc,
|
|||
memcpy(desc->opd_info.revision, &page_a0[SSF_VENDOR_REV], 2);
|
||||
memcpy(desc->opd_info.date, &page_a0[SSF_DATE_CODE], 8);
|
||||
desc->length = cpu_to_be32(sizeof(desc->opd_info));
|
||||
return sizeof(struct fc_rdp_opd_sfp_desc);
|
||||
}
|
||||
|
||||
int
|
||||
uint32_t
|
||||
lpfc_rdp_res_fec_desc(struct fc_fec_rdp_desc *desc, READ_LNK_VAR *stat)
|
||||
{
|
||||
if (bf_get(lpfc_read_link_stat_gec2, stat) == 0)
|
||||
|
@ -4864,7 +4924,7 @@ lpfc_rdp_res_fec_desc(struct fc_fec_rdp_desc *desc, READ_LNK_VAR *stat)
|
|||
return sizeof(struct fc_fec_rdp_desc);
|
||||
}
|
||||
|
||||
void
|
||||
uint32_t
|
||||
lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba)
|
||||
{
|
||||
uint16_t rdp_cap = 0;
|
||||
|
@ -4923,9 +4983,10 @@ lpfc_rdp_res_speed(struct fc_rdp_port_speed_desc *desc, struct lpfc_hba *phba)
|
|||
|
||||
desc->info.port_speed.capabilities = cpu_to_be16(rdp_cap);
|
||||
desc->length = cpu_to_be32(sizeof(desc->info));
|
||||
return sizeof(struct fc_rdp_port_speed_desc);
|
||||
}
|
||||
|
||||
void
|
||||
uint32_t
|
||||
lpfc_rdp_res_diag_port_names(struct fc_rdp_port_name_desc *desc,
|
||||
struct lpfc_hba *phba)
|
||||
{
|
||||
|
@ -4939,9 +5000,10 @@ lpfc_rdp_res_diag_port_names(struct fc_rdp_port_name_desc *desc,
|
|||
sizeof(desc->port_names.wwpn));
|
||||
|
||||
desc->length = cpu_to_be32(sizeof(desc->port_names));
|
||||
return sizeof(struct fc_rdp_port_name_desc);
|
||||
}
|
||||
|
||||
void
|
||||
uint32_t
|
||||
lpfc_rdp_res_attach_port_names(struct fc_rdp_port_name_desc *desc,
|
||||
struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
|
||||
{
|
||||
|
@ -4962,6 +5024,7 @@ lpfc_rdp_res_attach_port_names(struct fc_rdp_port_name_desc *desc,
|
|||
}
|
||||
|
||||
desc->length = cpu_to_be32(sizeof(desc->port_names));
|
||||
return sizeof(struct fc_rdp_port_name_desc);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -4976,8 +5039,9 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context,
|
|||
uint8_t *pcmd;
|
||||
struct ls_rjt *stat;
|
||||
struct fc_rdp_res_frame *rdp_res;
|
||||
uint32_t cmdsize;
|
||||
int rc, fec_size;
|
||||
uint32_t cmdsize, len;
|
||||
uint16_t *flag_ptr;
|
||||
int rc;
|
||||
|
||||
if (status != SUCCESS)
|
||||
goto error;
|
||||
|
@ -5008,39 +5072,61 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context,
|
|||
memset(pcmd, 0, sizeof(struct fc_rdp_res_frame));
|
||||
*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
|
||||
|
||||
/* For RDP payload */
|
||||
lpfc_rdp_res_link_service(&rdp_res->link_service_desc, ELS_CMD_RDP);
|
||||
/* Update Alarm and Warning */
|
||||
flag_ptr = (uint16_t *)(rdp_context->page_a2 + SSF_ALARM_FLAGS);
|
||||
phba->sfp_alarm |= *flag_ptr;
|
||||
flag_ptr = (uint16_t *)(rdp_context->page_a2 + SSF_WARNING_FLAGS);
|
||||
phba->sfp_warning |= *flag_ptr;
|
||||
|
||||
lpfc_rdp_res_sfp_desc(&rdp_res->sfp_desc,
|
||||
/* For RDP payload */
|
||||
len = 8;
|
||||
len += lpfc_rdp_res_link_service((struct fc_rdp_link_service_desc *)
|
||||
(len + pcmd), ELS_CMD_RDP);
|
||||
|
||||
len += lpfc_rdp_res_sfp_desc((struct fc_rdp_sfp_desc *)(len + pcmd),
|
||||
rdp_context->page_a0, rdp_context->page_a2);
|
||||
lpfc_rdp_res_speed(&rdp_res->portspeed_desc, phba);
|
||||
lpfc_rdp_res_link_error(&rdp_res->link_error_desc,
|
||||
len += lpfc_rdp_res_speed((struct fc_rdp_port_speed_desc *)(len + pcmd),
|
||||
phba);
|
||||
len += lpfc_rdp_res_link_error((struct fc_rdp_link_error_status_desc *)
|
||||
(len + pcmd), &rdp_context->link_stat);
|
||||
len += lpfc_rdp_res_diag_port_names((struct fc_rdp_port_name_desc *)
|
||||
(len + pcmd), phba);
|
||||
len += lpfc_rdp_res_attach_port_names((struct fc_rdp_port_name_desc *)
|
||||
(len + pcmd), vport, ndlp);
|
||||
len += lpfc_rdp_res_fec_desc((struct fc_fec_rdp_desc *)(len + pcmd),
|
||||
&rdp_context->link_stat);
|
||||
lpfc_rdp_res_diag_port_names(&rdp_res->diag_port_names_desc, phba);
|
||||
lpfc_rdp_res_attach_port_names(&rdp_res->attached_port_names_desc,
|
||||
vport, ndlp);
|
||||
lpfc_rdp_res_bbc_desc(&rdp_res->bbc_desc, &rdp_context->link_stat,
|
||||
vport);
|
||||
lpfc_rdp_res_oed_temp_desc(&rdp_res->oed_temp_desc,
|
||||
rdp_context->page_a2);
|
||||
lpfc_rdp_res_oed_voltage_desc(&rdp_res->oed_voltage_desc,
|
||||
rdp_context->page_a2);
|
||||
lpfc_rdp_res_oed_txbias_desc(&rdp_res->oed_txbias_desc,
|
||||
rdp_context->page_a2);
|
||||
lpfc_rdp_res_oed_txpower_desc(&rdp_res->oed_txpower_desc,
|
||||
rdp_context->page_a2);
|
||||
lpfc_rdp_res_oed_rxpower_desc(&rdp_res->oed_rxpower_desc,
|
||||
rdp_context->page_a2);
|
||||
lpfc_rdp_res_opd_desc(&rdp_res->opd_desc, rdp_context->page_a0, vport);
|
||||
fec_size = lpfc_rdp_res_fec_desc(&rdp_res->fec_desc,
|
||||
&rdp_context->link_stat);
|
||||
rdp_res->length = cpu_to_be32(fec_size + RDP_DESC_PAYLOAD_SIZE);
|
||||
/* Check if nport is logged, BZ190632 */
|
||||
if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED))
|
||||
goto lpfc_skip_descriptor;
|
||||
|
||||
len += lpfc_rdp_res_bbc_desc((struct fc_rdp_bbc_desc *)(len + pcmd),
|
||||
&rdp_context->link_stat, vport);
|
||||
len += lpfc_rdp_res_oed_temp_desc(phba,
|
||||
(struct fc_rdp_oed_sfp_desc *)(len + pcmd),
|
||||
rdp_context->page_a2);
|
||||
len += lpfc_rdp_res_oed_voltage_desc(phba,
|
||||
(struct fc_rdp_oed_sfp_desc *)(len + pcmd),
|
||||
rdp_context->page_a2);
|
||||
len += lpfc_rdp_res_oed_txbias_desc(phba,
|
||||
(struct fc_rdp_oed_sfp_desc *)(len + pcmd),
|
||||
rdp_context->page_a2);
|
||||
len += lpfc_rdp_res_oed_txpower_desc(phba,
|
||||
(struct fc_rdp_oed_sfp_desc *)(len + pcmd),
|
||||
rdp_context->page_a2);
|
||||
len += lpfc_rdp_res_oed_rxpower_desc(phba,
|
||||
(struct fc_rdp_oed_sfp_desc *)(len + pcmd),
|
||||
rdp_context->page_a2);
|
||||
len += lpfc_rdp_res_opd_desc((struct fc_rdp_opd_sfp_desc *)(len + pcmd),
|
||||
rdp_context->page_a0, vport);
|
||||
|
||||
lpfc_skip_descriptor:
|
||||
rdp_res->length = cpu_to_be32(len - 8);
|
||||
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
|
||||
|
||||
/* Now that we know the true size of the payload, update the BPL */
|
||||
bpl = (struct ulp_bde64 *)
|
||||
(((struct lpfc_dmabuf *)(elsiocb->context3))->virt);
|
||||
bpl->tus.f.bdeSize = (fec_size + RDP_DESC_PAYLOAD_SIZE + 8);
|
||||
bpl->tus.f.bdeSize = len;
|
||||
bpl->tus.f.bdeFlags = 0;
|
||||
bpl->tus.w = le32_to_cpu(bpl->tus.w);
|
||||
|
||||
|
@ -5165,6 +5251,12 @@ lpfc_els_rcv_rdp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
|
|||
be32_to_cpu(rdp_req->nport_id_desc.nport_id),
|
||||
be32_to_cpu(rdp_req->nport_id_desc.length));
|
||||
|
||||
if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED) &&
|
||||
!phba->cfg_enable_SmartSAN) {
|
||||
rjt_err = LSRJT_UNABLE_TPC;
|
||||
rjt_expl = LSEXP_PORT_LOGIN_REQ;
|
||||
goto error;
|
||||
}
|
||||
if (sizeof(struct fc_rdp_nport_desc) !=
|
||||
be32_to_cpu(rdp_req->rdp_des_length))
|
||||
goto rjt_logerr;
|
||||
|
|
|
@ -346,7 +346,7 @@ struct csp {
|
|||
uint8_t fcphHigh; /* FC Word 0, byte 0 */
|
||||
uint8_t fcphLow;
|
||||
uint8_t bbCreditMsb;
|
||||
uint8_t bbCreditlsb; /* FC Word 0, byte 3 */
|
||||
uint8_t bbCreditLsb; /* FC Word 0, byte 3 */
|
||||
|
||||
/*
|
||||
* Word 1 Bit 31 in common service parameter is overloaded.
|
||||
|
@ -1206,6 +1206,12 @@ struct fc_rdp_bbc_desc {
|
|||
struct fc_rdp_bbc_info bbc_info;
|
||||
};
|
||||
|
||||
/* Optical Element Type Transgression Flags */
|
||||
#define RDP_OET_LOW_WARNING 0x1
|
||||
#define RDP_OET_HIGH_WARNING 0x2
|
||||
#define RDP_OET_LOW_ALARM 0x4
|
||||
#define RDP_OET_HIGH_ALARM 0x8
|
||||
|
||||
#define RDP_OED_TEMPERATURE 0x1
|
||||
#define RDP_OED_VOLTAGE 0x2
|
||||
#define RDP_OED_TXBIAS 0x3
|
||||
|
@ -1233,8 +1239,8 @@ struct fc_rdp_opd_sfp_info {
|
|||
uint8_t vendor_name[16];
|
||||
uint8_t model_number[16];
|
||||
uint8_t serial_number[16];
|
||||
uint8_t reserved[2];
|
||||
uint8_t revision[2];
|
||||
uint8_t reserved[2];
|
||||
uint8_t date[8];
|
||||
};
|
||||
|
||||
|
@ -1261,27 +1267,17 @@ struct fc_rdp_res_frame {
|
|||
struct fc_rdp_link_error_status_desc link_error_desc; /* Word 13-21 */
|
||||
struct fc_rdp_port_name_desc diag_port_names_desc; /* Word 22-27 */
|
||||
struct fc_rdp_port_name_desc attached_port_names_desc;/* Word 28-33 */
|
||||
struct fc_rdp_bbc_desc bbc_desc; /* FC Word 34-38*/
|
||||
struct fc_rdp_oed_sfp_desc oed_temp_desc; /* FC Word 39-43*/
|
||||
struct fc_rdp_oed_sfp_desc oed_voltage_desc; /* FC word 44-48*/
|
||||
struct fc_rdp_oed_sfp_desc oed_txbias_desc; /* FC word 49-53*/
|
||||
struct fc_rdp_oed_sfp_desc oed_txpower_desc; /* FC word 54-58*/
|
||||
struct fc_rdp_oed_sfp_desc oed_rxpower_desc; /* FC word 59-63*/
|
||||
struct fc_rdp_opd_sfp_desc opd_desc; /* FC word 64-80*/
|
||||
struct fc_fec_rdp_desc fec_desc; /* FC word 81-84*/
|
||||
struct fc_fec_rdp_desc fec_desc; /* FC word 34-37*/
|
||||
struct fc_rdp_bbc_desc bbc_desc; /* FC Word 38-42*/
|
||||
struct fc_rdp_oed_sfp_desc oed_temp_desc; /* FC Word 43-47*/
|
||||
struct fc_rdp_oed_sfp_desc oed_voltage_desc; /* FC word 48-52*/
|
||||
struct fc_rdp_oed_sfp_desc oed_txbias_desc; /* FC word 53-57*/
|
||||
struct fc_rdp_oed_sfp_desc oed_txpower_desc; /* FC word 58-62*/
|
||||
struct fc_rdp_oed_sfp_desc oed_rxpower_desc; /* FC word 63-67*/
|
||||
struct fc_rdp_opd_sfp_desc opd_desc; /* FC word 68-84*/
|
||||
};
|
||||
|
||||
|
||||
#define RDP_DESC_PAYLOAD_SIZE (sizeof(struct fc_rdp_link_service_desc) \
|
||||
+ sizeof(struct fc_rdp_sfp_desc) \
|
||||
+ sizeof(struct fc_rdp_port_speed_desc) \
|
||||
+ sizeof(struct fc_rdp_link_error_status_desc) \
|
||||
+ (sizeof(struct fc_rdp_port_name_desc) * 2) \
|
||||
+ sizeof(struct fc_rdp_bbc_desc) \
|
||||
+ (sizeof(struct fc_rdp_oed_sfp_desc) * 5) \
|
||||
+ sizeof(struct fc_rdp_opd_sfp_desc))
|
||||
|
||||
|
||||
/******** FDMI ********/
|
||||
|
||||
/* lpfc_sli_ct_request defines the CT_IU preamble for FDMI commands */
|
||||
|
|
|
@ -544,6 +544,8 @@ struct lpfc_register {
|
|||
uint32_t word0;
|
||||
};
|
||||
|
||||
#define LPFC_PORT_SEM_UE_RECOVERABLE 0xE000
|
||||
#define LPFC_PORT_SEM_MASK 0xF000
|
||||
/* The following BAR0 Registers apply to SLI4 if_type 0 UCNAs. */
|
||||
#define LPFC_UERR_STATUS_HI 0x00A4
|
||||
#define LPFC_UERR_STATUS_LO 0x00A0
|
||||
|
@ -937,6 +939,7 @@ struct mbox_header {
|
|||
#define LPFC_MBOX_OPCODE_READ_OBJECT_LIST 0xAD
|
||||
#define LPFC_MBOX_OPCODE_DELETE_OBJECT 0xAE
|
||||
#define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS 0xB5
|
||||
#define LPFC_MBOX_OPCODE_SET_FEATURES 0xBF
|
||||
|
||||
/* FCoE Opcodes */
|
||||
#define LPFC_MBOX_OPCODE_FCOE_WQ_CREATE 0x01
|
||||
|
@ -2590,10 +2593,8 @@ struct lpfc_mbx_memory_dump_type3 {
|
|||
#define SFF_RXPOWER_B1 104
|
||||
#define SFF_RXPOWER_B0 105
|
||||
#define SSF_STATUS_CONTROL 110
|
||||
#define SSF_ALARM_FLAGS_B1 112
|
||||
#define SSF_ALARM_FLAGS_B0 113
|
||||
#define SSF_WARNING_FLAGS_B1 116
|
||||
#define SSF_WARNING_FLAGS_B0 117
|
||||
#define SSF_ALARM_FLAGS 112
|
||||
#define SSF_WARNING_FLAGS 116
|
||||
#define SSF_EXT_TATUS_CONTROL_B1 118
|
||||
#define SSF_EXT_TATUS_CONTROL_B0 119
|
||||
#define SSF_A2_VENDOR_SPECIFIC 120
|
||||
|
@ -2887,8 +2888,37 @@ struct lpfc_sli4_parameters {
|
|||
#define cfg_ext_embed_cb_SHIFT 0
|
||||
#define cfg_ext_embed_cb_MASK 0x00000001
|
||||
#define cfg_ext_embed_cb_WORD word19
|
||||
#define cfg_mds_diags_SHIFT 1
|
||||
#define cfg_mds_diags_MASK 0x00000001
|
||||
#define cfg_mds_diags_WORD word19
|
||||
};
|
||||
|
||||
#define LPFC_SET_UE_RECOVERY 0x10
|
||||
#define LPFC_SET_MDS_DIAGS 0x11
|
||||
struct lpfc_mbx_set_feature {
|
||||
struct mbox_header header;
|
||||
uint32_t feature;
|
||||
uint32_t param_len;
|
||||
uint32_t word6;
|
||||
#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_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
|
||||
uint32_t word7;
|
||||
#define lpfc_mbx_set_feature_UERP_SHIFT 0
|
||||
#define lpfc_mbx_set_feature_UERP_MASK 0x0000ffff
|
||||
#define lpfc_mbx_set_feature_UERP_WORD word7
|
||||
#define lpfc_mbx_set_feature_UESR_SHIFT 16
|
||||
#define lpfc_mbx_set_feature_UESR_MASK 0x0000ffff
|
||||
#define lpfc_mbx_set_feature_UESR_WORD word7
|
||||
};
|
||||
|
||||
|
||||
struct lpfc_mbx_get_sli4_parameters {
|
||||
struct mbox_header header;
|
||||
struct lpfc_sli4_parameters sli4_parameters;
|
||||
|
@ -3281,6 +3311,7 @@ struct lpfc_mqe {
|
|||
struct lpfc_mbx_get_prof_cfg get_prof_cfg;
|
||||
struct lpfc_mbx_wr_object wr_object;
|
||||
struct lpfc_mbx_get_port_name get_port_name;
|
||||
struct lpfc_mbx_set_feature set_feature;
|
||||
struct lpfc_mbx_memory_dump_type3 mem_dump_type3;
|
||||
struct lpfc_mbx_nop nop;
|
||||
} un;
|
||||
|
@ -3443,6 +3474,8 @@ struct lpfc_acqe_fc_la {
|
|||
#define LPFC_FC_LA_TYPE_LINK_UP 0x1
|
||||
#define LPFC_FC_LA_TYPE_LINK_DOWN 0x2
|
||||
#define LPFC_FC_LA_TYPE_NO_HARD_ALPA 0x3
|
||||
#define LPFC_FC_LA_TYPE_MDS_LINK_DOWN 0x4
|
||||
#define LPFC_FC_LA_TYPE_MDS_LOOPBACK 0x5
|
||||
#define lpfc_acqe_fc_la_port_type_SHIFT 6
|
||||
#define lpfc_acqe_fc_la_port_type_MASK 0x00000003
|
||||
#define lpfc_acqe_fc_la_port_type_WORD word0
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.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. *
|
||||
*******************************************************************/
|
||||
|
||||
#include <linux/pci.h>
|
||||
|
||||
const struct pci_device_id lpfc_id_table[] = {
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_FIREFLY,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_THOR,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PEGASUS,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_CENTAUR,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_DRAGONFLY,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SUPERFLY,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_RFLY,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PFLY,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_SCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_DCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_SCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_DCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BMID,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BSMB,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HORNET,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_SCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_DCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZMID,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZSMB,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_TFLY,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP101,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP10000S,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP11000S,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LPE11000S,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_MID,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SMB,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_DCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_S,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_VF,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_PF,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_S,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TIGERSHARK,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TOMCAT,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_FALCON,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BALIUS,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FC,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FC_VF,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE_VF,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G6_FC,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK_VF,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{ 0 }
|
||||
};
|
|
@ -52,6 +52,7 @@
|
|||
#include "lpfc_crtn.h"
|
||||
#include "lpfc_vport.h"
|
||||
#include "lpfc_version.h"
|
||||
#include "lpfc_ids.h"
|
||||
|
||||
char *_dump_buf_data;
|
||||
unsigned long _dump_buf_data_order;
|
||||
|
@ -568,7 +569,7 @@ lpfc_config_port_post(struct lpfc_hba *phba)
|
|||
phba->last_completion_time = jiffies;
|
||||
/* Set up error attention (ERATT) polling timer */
|
||||
mod_timer(&phba->eratt_poll,
|
||||
jiffies + msecs_to_jiffies(1000 * LPFC_ERATT_POLL_INTERVAL));
|
||||
jiffies + msecs_to_jiffies(1000 * phba->eratt_poll_interval));
|
||||
|
||||
if (phba->hba_flag & LINK_DISABLED) {
|
||||
lpfc_printf_log(phba,
|
||||
|
@ -1587,35 +1588,39 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action,
|
|||
int rc;
|
||||
uint32_t intr_mode;
|
||||
|
||||
/*
|
||||
* On error status condition, driver need to wait for port
|
||||
* ready before performing reset.
|
||||
*/
|
||||
rc = lpfc_sli4_pdev_status_reg_wait(phba);
|
||||
if (!rc) {
|
||||
/* need reset: attempt for port recovery */
|
||||
if (en_rn_msg)
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"2887 Reset Needed: Attempting Port "
|
||||
"Recovery...\n");
|
||||
lpfc_offline_prep(phba, mbx_action);
|
||||
lpfc_offline(phba);
|
||||
/* release interrupt for possible resource change */
|
||||
lpfc_sli4_disable_intr(phba);
|
||||
lpfc_sli_brdrestart(phba);
|
||||
/* 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,
|
||||
"3175 Failed to enable interrupt\n");
|
||||
return -EIO;
|
||||
} else {
|
||||
phba->intr_mode = intr_mode;
|
||||
}
|
||||
rc = lpfc_online(phba);
|
||||
if (rc == 0)
|
||||
lpfc_unblock_mgmt_io(phba);
|
||||
if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
|
||||
LPFC_SLI_INTF_IF_TYPE_2) {
|
||||
/*
|
||||
* On error status condition, driver need to wait for port
|
||||
* ready before performing reset.
|
||||
*/
|
||||
rc = lpfc_sli4_pdev_status_reg_wait(phba);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* need reset: attempt for port recovery */
|
||||
if (en_rn_msg)
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"2887 Reset Needed: Attempting Port "
|
||||
"Recovery...\n");
|
||||
lpfc_offline_prep(phba, mbx_action);
|
||||
lpfc_offline(phba);
|
||||
/* release interrupt for possible resource change */
|
||||
lpfc_sli4_disable_intr(phba);
|
||||
lpfc_sli_brdrestart(phba);
|
||||
/* 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,
|
||||
"3175 Failed to enable interrupt\n");
|
||||
return -EIO;
|
||||
}
|
||||
phba->intr_mode = intr_mode;
|
||||
rc = lpfc_online(phba);
|
||||
if (rc == 0)
|
||||
lpfc_unblock_mgmt_io(phba);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1636,10 +1641,11 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
|
|||
struct lpfc_register portstat_reg = {0};
|
||||
uint32_t reg_err1, reg_err2;
|
||||
uint32_t uerrlo_reg, uemasklo_reg;
|
||||
uint32_t pci_rd_rc1, pci_rd_rc2;
|
||||
uint32_t smphr_port_status = 0, pci_rd_rc1, pci_rd_rc2;
|
||||
bool en_rn_msg = true;
|
||||
struct temp_event temp_event_data;
|
||||
int rc;
|
||||
struct lpfc_register portsmphr_reg;
|
||||
int rc, i;
|
||||
|
||||
/* If the pci channel is offline, ignore possible errors, since
|
||||
* we cannot communicate with the pci card anyway.
|
||||
|
@ -1647,6 +1653,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
|
|||
if (pci_channel_offline(phba->pcidev))
|
||||
return;
|
||||
|
||||
memset(&portsmphr_reg, 0, sizeof(portsmphr_reg));
|
||||
if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
|
||||
switch (if_type) {
|
||||
case LPFC_SLI_INTF_IF_TYPE_0:
|
||||
|
@ -1659,6 +1666,55 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
|
|||
/* consider PCI bus read error as pci_channel_offline */
|
||||
if (pci_rd_rc1 == -EIO && pci_rd_rc2 == -EIO)
|
||||
return;
|
||||
if (!(phba->hba_flag & HBA_RECOVERABLE_UE)) {
|
||||
lpfc_sli4_offline_eratt(phba);
|
||||
return;
|
||||
}
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"7623 Checking UE recoverable");
|
||||
|
||||
for (i = 0; i < phba->sli4_hba.ue_to_sr / 1000; i++) {
|
||||
if (lpfc_readl(phba->sli4_hba.PSMPHRregaddr,
|
||||
&portsmphr_reg.word0))
|
||||
continue;
|
||||
|
||||
smphr_port_status = bf_get(lpfc_port_smphr_port_status,
|
||||
&portsmphr_reg);
|
||||
if ((smphr_port_status & LPFC_PORT_SEM_MASK) ==
|
||||
LPFC_PORT_SEM_UE_RECOVERABLE)
|
||||
break;
|
||||
/*Sleep for 1Sec, before checking SEMAPHORE */
|
||||
msleep(1000);
|
||||
}
|
||||
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"4827 smphr_port_status x%x : Waited %dSec",
|
||||
smphr_port_status, i);
|
||||
|
||||
/* Recoverable UE, reset the HBA device */
|
||||
if ((smphr_port_status & LPFC_PORT_SEM_MASK) ==
|
||||
LPFC_PORT_SEM_UE_RECOVERABLE) {
|
||||
for (i = 0; i < 20; i++) {
|
||||
msleep(1000);
|
||||
if (!lpfc_readl(phba->sli4_hba.PSMPHRregaddr,
|
||||
&portsmphr_reg.word0) &&
|
||||
(LPFC_POST_STAGE_PORT_READY ==
|
||||
bf_get(lpfc_port_smphr_port_status,
|
||||
&portsmphr_reg))) {
|
||||
rc = lpfc_sli4_port_sta_fn_reset(phba,
|
||||
LPFC_MBX_NO_WAIT, en_rn_msg);
|
||||
if (rc == 0)
|
||||
return;
|
||||
lpfc_printf_log(phba,
|
||||
KERN_ERR, LOG_INIT,
|
||||
"4215 Failed to recover UE");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"7624 Firmware not ready: Failing UE recovery,"
|
||||
" waited %dSec", i);
|
||||
lpfc_sli4_offline_eratt(phba);
|
||||
break;
|
||||
|
||||
|
@ -1681,6 +1737,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
|
|||
"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;
|
||||
temp_event_data.event_code = LPFC_CRIT_TEMP;
|
||||
temp_event_data.data = 0xFFFFFFFF;
|
||||
|
@ -3985,6 +4042,8 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
|
|||
{
|
||||
struct lpfc_dmabuf *mp;
|
||||
LPFC_MBOXQ_t *pmb;
|
||||
MAILBOX_t *mb;
|
||||
struct lpfc_mbx_read_top *la;
|
||||
int rc;
|
||||
|
||||
if (bf_get(lpfc_trailer_type, acqe_fc) !=
|
||||
|
@ -4055,6 +4114,24 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
|
|||
pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology;
|
||||
pmb->vport = phba->pport;
|
||||
|
||||
if (phba->sli4_hba.link_state.status != LPFC_FC_LA_TYPE_LINK_UP) {
|
||||
/* Parse and translate status field */
|
||||
mb = &pmb->u.mb;
|
||||
mb->mbxStatus = lpfc_sli4_parse_latt_fault(phba,
|
||||
(void *)acqe_fc);
|
||||
|
||||
/* Parse and translate link attention fields */
|
||||
la = (struct lpfc_mbx_read_top *)&pmb->u.mb.un.varReadTop;
|
||||
la->eventTag = acqe_fc->event_tag;
|
||||
bf_set(lpfc_mbx_read_top_att_type, la,
|
||||
LPFC_FC_LA_TYPE_LINK_DOWN);
|
||||
|
||||
/* Invoke the mailbox command callback function */
|
||||
lpfc_mbx_cmpl_read_topology(phba, pmb);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
|
||||
if (rc == MBX_NOT_FINISHED)
|
||||
goto out_free_dmabuf;
|
||||
|
@ -4107,6 +4184,7 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
|
|||
"3190 Over Temperature:%d Celsius- Port Name %c\n",
|
||||
acqe_sli->event_data1, port_name);
|
||||
|
||||
phba->sfp_warning |= LPFC_TRANSGRESSION_HIGH_TEMPERATURE;
|
||||
shost = lpfc_shost_from_vport(phba->pport);
|
||||
fc_host_post_vendor_event(shost, fc_get_event_number(),
|
||||
sizeof(temp_event_data),
|
||||
|
@ -4408,7 +4486,8 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
|
|||
* the corresponding FCF bit in the roundrobin bitmap.
|
||||
*/
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
if (phba->fcf.fcf_flag & FCF_DISCOVERY) {
|
||||
if ((phba->fcf.fcf_flag & FCF_DISCOVERY) &&
|
||||
(phba->fcf.current_rec.fcf_indx != acqe_fip->index)) {
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
/* Update FLOGI FCF failover eligible FCF bmask */
|
||||
lpfc_sli4_fcf_rr_index_clear(phba, acqe_fip->index);
|
||||
|
@ -5363,6 +5442,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
|||
goto out_free_bsmbx;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get sli4 parameters that override parameters from Port capabilities.
|
||||
* If this call fails, it isn't critical unless the SLI4 parameters come
|
||||
|
@ -6091,6 +6171,7 @@ lpfc_hba_alloc(struct pci_dev *pdev)
|
|||
kfree(phba);
|
||||
return NULL;
|
||||
}
|
||||
phba->eratt_poll_interval = LPFC_ERATT_POLL_INTERVAL;
|
||||
|
||||
spin_lock_init(&phba->ct_ev_lock);
|
||||
INIT_LIST_HEAD(&phba->ct_ev_waiters);
|
||||
|
@ -9527,6 +9608,14 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
|
|||
phba->fcp_embed_io = 1;
|
||||
else
|
||||
phba->fcp_embed_io = 0;
|
||||
|
||||
/*
|
||||
* Check if the SLI port supports MDS Diagnostics
|
||||
*/
|
||||
if (bf_get(cfg_mds_diags, mbx_sli4_parameters))
|
||||
phba->mds_diags_support = 1;
|
||||
else
|
||||
phba->mds_diags_support = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -11298,106 +11387,6 @@ lpfc_fof_queue_destroy(struct lpfc_hba *phba)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct pci_device_id lpfc_id_table[] = {
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_FIREFLY,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_THOR,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PEGASUS,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_CENTAUR,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_DRAGONFLY,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SUPERFLY,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_RFLY,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PFLY,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_SCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_DCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_SCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_DCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BMID,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BSMB,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HORNET,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_SCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_DCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZMID,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZSMB,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_TFLY,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP101,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP10000S,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP11000S,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LPE11000S,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_MID,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SMB,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_DCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_S,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_VF,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_PF,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_S,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TIGERSHARK,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TOMCAT,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_FALCON,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BALIUS,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FC,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FC_VF,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE_VF,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G6_FC,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK_VF,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, lpfc_id_table);
|
||||
|
||||
static const struct pci_error_handlers lpfc_err_handler = {
|
||||
|
@ -11452,21 +11441,17 @@ lpfc_init(void)
|
|||
printk(KERN_ERR "Could not register lpfcmgmt device, "
|
||||
"misc_register returned with status %d", error);
|
||||
|
||||
if (lpfc_enable_npiv) {
|
||||
lpfc_transport_functions.vport_create = lpfc_vport_create;
|
||||
lpfc_transport_functions.vport_delete = lpfc_vport_delete;
|
||||
}
|
||||
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;
|
||||
if (lpfc_enable_npiv) {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* Initialize in case vector mapping is needed */
|
||||
|
@ -11478,8 +11463,7 @@ lpfc_init(void)
|
|||
error = pci_register_driver(&lpfc_driver);
|
||||
if (error) {
|
||||
fc_release_transport(lpfc_transport_template);
|
||||
if (lpfc_enable_npiv)
|
||||
fc_release_transport(lpfc_vport_transport_template);
|
||||
fc_release_transport(lpfc_vport_transport_template);
|
||||
}
|
||||
|
||||
return error;
|
||||
|
@ -11498,8 +11482,7 @@ lpfc_exit(void)
|
|||
misc_deregister(&lpfc_mgmt_dev);
|
||||
pci_unregister_driver(&lpfc_driver);
|
||||
fc_release_transport(lpfc_transport_template);
|
||||
if (lpfc_enable_npiv)
|
||||
fc_release_transport(lpfc_vport_transport_template);
|
||||
fc_release_transport(lpfc_vport_transport_template);
|
||||
if (_dump_buf_data) {
|
||||
printk(KERN_ERR "9062 BLKGRD: freeing %lu pages for "
|
||||
"_dump_buf_data at 0x%p\n",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2015 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
|
||||
|
@ -3335,8 +3335,11 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
|
|||
* OAS, set the oas iocb related flags.
|
||||
*/
|
||||
if ((phba->cfg_fof) && ((struct lpfc_device_data *)
|
||||
scsi_cmnd->device->hostdata)->oas_enabled)
|
||||
scsi_cmnd->device->hostdata)->oas_enabled) {
|
||||
lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF);
|
||||
lpfc_cmd->cur_iocbq.priority = ((struct lpfc_device_data *)
|
||||
scsi_cmnd->device->hostdata)->priority;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -5607,6 +5610,7 @@ lpfc_create_device_data(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
|
|||
sizeof(struct lpfc_name));
|
||||
lun_info->device_id.lun = lun;
|
||||
lun_info->oas_enabled = false;
|
||||
lun_info->priority = phba->cfg_XLanePriority;
|
||||
lun_info->available = false;
|
||||
return lun_info;
|
||||
}
|
||||
|
@ -5798,7 +5802,7 @@ lpfc_find_next_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
|
|||
**/
|
||||
bool
|
||||
lpfc_enable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
|
||||
struct lpfc_name *target_wwpn, uint64_t lun)
|
||||
struct lpfc_name *target_wwpn, uint64_t lun, uint8_t pri)
|
||||
{
|
||||
|
||||
struct lpfc_device_data *lun_info;
|
||||
|
@ -5825,6 +5829,7 @@ lpfc_enable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
|
|||
false);
|
||||
if (lun_info) {
|
||||
lun_info->oas_enabled = true;
|
||||
lun_info->priority = pri;
|
||||
lun_info->available = false;
|
||||
list_add_tail(&lun_info->listentry, &phba->luns);
|
||||
spin_unlock_irqrestore(&phba->devicelock, flags);
|
||||
|
@ -5886,6 +5891,7 @@ lpfc_disable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
|
|||
struct scsi_host_template lpfc_template_s3 = {
|
||||
.module = THIS_MODULE,
|
||||
.name = LPFC_DRIVER_NAME,
|
||||
.proc_name = LPFC_DRIVER_NAME,
|
||||
.info = lpfc_info,
|
||||
.queuecommand = lpfc_queuecommand,
|
||||
.eh_abort_handler = lpfc_abort_handler,
|
||||
|
@ -5910,6 +5916,7 @@ struct scsi_host_template lpfc_template_s3 = {
|
|||
struct scsi_host_template lpfc_template = {
|
||||
.module = THIS_MODULE,
|
||||
.name = LPFC_DRIVER_NAME,
|
||||
.proc_name = LPFC_DRIVER_NAME,
|
||||
.info = lpfc_info,
|
||||
.queuecommand = lpfc_queuecommand,
|
||||
.eh_abort_handler = lpfc_abort_handler,
|
||||
|
@ -5935,6 +5942,7 @@ struct scsi_host_template lpfc_template = {
|
|||
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_abort_handler = lpfc_abort_handler,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2015 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
|
@ -51,6 +51,7 @@ struct lpfc_device_data {
|
|||
struct list_head listentry;
|
||||
struct lpfc_rport_data *rport_data;
|
||||
struct lpfc_device_id device_id;
|
||||
uint8_t priority;
|
||||
bool oas_enabled;
|
||||
bool available;
|
||||
};
|
||||
|
|
|
@ -2947,8 +2947,8 @@ void lpfc_poll_eratt(unsigned long ptr)
|
|||
else
|
||||
cnt = (sli_intr - phba->sli.slistat.sli_prev_intr);
|
||||
|
||||
/* 64-bit integer division not supporte on 32-bit x86 - use do_div */
|
||||
do_div(cnt, LPFC_ERATT_POLL_INTERVAL);
|
||||
/* 64-bit integer division not supported on 32-bit x86 - use do_div */
|
||||
do_div(cnt, phba->eratt_poll_interval);
|
||||
phba->sli.slistat.sli_ips = cnt;
|
||||
|
||||
phba->sli.slistat.sli_prev_intr = sli_intr;
|
||||
|
@ -2963,7 +2963,7 @@ void lpfc_poll_eratt(unsigned long ptr)
|
|||
/* Restart the timer for next eratt poll */
|
||||
mod_timer(&phba->eratt_poll,
|
||||
jiffies +
|
||||
msecs_to_jiffies(1000 * LPFC_ERATT_POLL_INTERVAL));
|
||||
msecs_to_jiffies(1000 * phba->eratt_poll_interval));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4665,13 +4665,13 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba)
|
|||
int mode = 3, i;
|
||||
int longs;
|
||||
|
||||
switch (lpfc_sli_mode) {
|
||||
switch (phba->cfg_sli_mode) {
|
||||
case 2:
|
||||
if (phba->cfg_enable_npiv) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
|
||||
"1824 NPIV enabled: Override lpfc_sli_mode "
|
||||
"1824 NPIV enabled: Override sli_mode "
|
||||
"parameter (%d) to auto (0).\n",
|
||||
lpfc_sli_mode);
|
||||
phba->cfg_sli_mode);
|
||||
break;
|
||||
}
|
||||
mode = 2;
|
||||
|
@ -4681,8 +4681,8 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba)
|
|||
break;
|
||||
default:
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
|
||||
"1819 Unrecognized lpfc_sli_mode "
|
||||
"parameter: %d.\n", lpfc_sli_mode);
|
||||
"1819 Unrecognized sli_mode parameter: %d.\n",
|
||||
phba->cfg_sli_mode);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -4690,12 +4690,14 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba)
|
|||
|
||||
rc = lpfc_sli_config_port(phba, mode);
|
||||
|
||||
if (rc && lpfc_sli_mode == 3)
|
||||
if (rc && phba->cfg_sli_mode == 3)
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
|
||||
"1820 Unable to select SLI-3. "
|
||||
"Not supported by adapter.\n");
|
||||
if (rc && mode != 2)
|
||||
rc = lpfc_sli_config_port(phba, 2);
|
||||
else if (rc && mode == 2)
|
||||
rc = lpfc_sli_config_port(phba, 3);
|
||||
if (rc)
|
||||
goto lpfc_sli_hba_setup_error;
|
||||
|
||||
|
@ -5690,6 +5692,38 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type)
|
|||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
|
||||
uint32_t feature)
|
||||
{
|
||||
uint32_t len;
|
||||
|
||||
len = sizeof(struct lpfc_mbx_set_feature) -
|
||||
sizeof(struct lpfc_sli4_cfg_mhdr);
|
||||
lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON,
|
||||
LPFC_MBOX_OPCODE_SET_FEATURES, len,
|
||||
LPFC_SLI4_MBX_EMBED);
|
||||
|
||||
switch (feature) {
|
||||
case LPFC_SET_UE_RECOVERY:
|
||||
bf_set(lpfc_mbx_set_feature_UER,
|
||||
&mbox->u.mqe.un.set_feature, 1);
|
||||
mbox->u.mqe.un.set_feature.feature = LPFC_SET_UE_RECOVERY;
|
||||
mbox->u.mqe.un.set_feature.param_len = 8;
|
||||
break;
|
||||
case LPFC_SET_MDS_DIAGS:
|
||||
bf_set(lpfc_mbx_set_feature_mds,
|
||||
&mbox->u.mqe.un.set_feature, 1);
|
||||
bf_set(lpfc_mbx_set_feature_mds_deep_loopbk,
|
||||
&mbox->u.mqe.un.set_feature, 0);
|
||||
mbox->u.mqe.un.set_feature.feature = LPFC_SET_MDS_DIAGS;
|
||||
mbox->u.mqe.un.set_feature.param_len = 8;
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_sli4_alloc_resource_identifiers - Allocate all SLI4 resource extents.
|
||||
* @phba: Pointer to HBA context object.
|
||||
|
@ -6414,6 +6448,30 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
|
|||
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);
|
||||
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
|
||||
if (rc == MBX_SUCCESS) {
|
||||
phba->hba_flag |= HBA_RECOVERABLE_UE;
|
||||
/* Set 1Sec interval to detect UE */
|
||||
phba->eratt_poll_interval = 1;
|
||||
phba->sli4_hba.ue_to_sr = bf_get(
|
||||
lpfc_mbx_set_feature_UESR,
|
||||
&mboxq->u.mqe.un.set_feature);
|
||||
phba->sli4_hba.ue_to_rp = bf_get(
|
||||
lpfc_mbx_set_feature_UERP,
|
||||
&mboxq->u.mqe.un.set_feature);
|
||||
}
|
||||
}
|
||||
|
||||
if (phba->cfg_enable_mds_diags && phba->mds_diags_support) {
|
||||
/* Enable MDS Diagnostics only if the SLI Port supports it */
|
||||
lpfc_set_features(phba, mboxq, LPFC_SET_MDS_DIAGS);
|
||||
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
|
||||
if (rc != MBX_SUCCESS)
|
||||
phba->mds_diags_support = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Discover the port's supported feature set and match it against the
|
||||
|
@ -6612,7 +6670,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
|
|||
|
||||
/* Start error attention (ERATT) polling timer */
|
||||
mod_timer(&phba->eratt_poll,
|
||||
jiffies + msecs_to_jiffies(1000 * LPFC_ERATT_POLL_INTERVAL));
|
||||
jiffies + msecs_to_jiffies(1000 * phba->eratt_poll_interval));
|
||||
|
||||
/* Enable PCIe device Advanced Error Reporting (AER) if configured */
|
||||
if (phba->cfg_aer_support == 1 && !(phba->hba_flag & HBA_AER_ENABLED)) {
|
||||
|
@ -8383,8 +8441,11 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
|
|||
bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 1);
|
||||
if (iocbq->iocb_flag & LPFC_IO_OAS) {
|
||||
bf_set(wqe_oas, &wqe->fcp_iwrite.wqe_com, 1);
|
||||
if (phba->cfg_XLanePriority) {
|
||||
bf_set(wqe_ccpe, &wqe->fcp_iwrite.wqe_com, 1);
|
||||
bf_set(wqe_ccpe, &wqe->fcp_iwrite.wqe_com, 1);
|
||||
if (iocbq->priority) {
|
||||
bf_set(wqe_ccp, &wqe->fcp_iwrite.wqe_com,
|
||||
(iocbq->priority << 1));
|
||||
} else {
|
||||
bf_set(wqe_ccp, &wqe->fcp_iwrite.wqe_com,
|
||||
(phba->cfg_XLanePriority << 1));
|
||||
}
|
||||
|
@ -8439,8 +8500,11 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
|
|||
bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1);
|
||||
if (iocbq->iocb_flag & LPFC_IO_OAS) {
|
||||
bf_set(wqe_oas, &wqe->fcp_iread.wqe_com, 1);
|
||||
if (phba->cfg_XLanePriority) {
|
||||
bf_set(wqe_ccpe, &wqe->fcp_iread.wqe_com, 1);
|
||||
bf_set(wqe_ccpe, &wqe->fcp_iread.wqe_com, 1);
|
||||
if (iocbq->priority) {
|
||||
bf_set(wqe_ccp, &wqe->fcp_iread.wqe_com,
|
||||
(iocbq->priority << 1));
|
||||
} else {
|
||||
bf_set(wqe_ccp, &wqe->fcp_iread.wqe_com,
|
||||
(phba->cfg_XLanePriority << 1));
|
||||
}
|
||||
|
@ -8494,8 +8558,11 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
|
|||
iocbq->iocb.ulpFCP2Rcvy);
|
||||
if (iocbq->iocb_flag & LPFC_IO_OAS) {
|
||||
bf_set(wqe_oas, &wqe->fcp_icmd.wqe_com, 1);
|
||||
if (phba->cfg_XLanePriority) {
|
||||
bf_set(wqe_ccpe, &wqe->fcp_icmd.wqe_com, 1);
|
||||
bf_set(wqe_ccpe, &wqe->fcp_icmd.wqe_com, 1);
|
||||
if (iocbq->priority) {
|
||||
bf_set(wqe_ccp, &wqe->fcp_icmd.wqe_com,
|
||||
(iocbq->priority << 1));
|
||||
} else {
|
||||
bf_set(wqe_ccp, &wqe->fcp_icmd.wqe_com,
|
||||
(phba->cfg_XLanePriority << 1));
|
||||
}
|
||||
|
@ -10136,6 +10203,7 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id,
|
|||
struct lpfc_iocbq *iocbq;
|
||||
int sum, i;
|
||||
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
for (i = 1, sum = 0; i <= phba->sli.last_iotag; i++) {
|
||||
iocbq = phba->sli.iocbq_lookup[i];
|
||||
|
||||
|
@ -10143,6 +10211,7 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id,
|
|||
ctx_cmd) == 0)
|
||||
sum++;
|
||||
}
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2015 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
|
@ -57,6 +57,7 @@ struct lpfc_iocbq {
|
|||
struct lpfc_cq_event cq_event;
|
||||
|
||||
IOCB_t iocb; /* IOCB cmd */
|
||||
uint8_t priority; /* OAS priority */
|
||||
uint8_t retry; /* retry counter for IOCB cmd - if needed */
|
||||
uint32_t iocb_flag;
|
||||
#define LPFC_IO_LIBDFC 1 /* libdfc iocb */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2009-2015 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2009-2016 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
|
@ -511,6 +511,8 @@ struct lpfc_sli4_hba {
|
|||
|
||||
uint32_t ue_mask_lo;
|
||||
uint32_t ue_mask_hi;
|
||||
uint32_t ue_to_sr;
|
||||
uint32_t ue_to_rp;
|
||||
struct lpfc_register sli_intf;
|
||||
struct lpfc_pc_sli4_params pc_sli4_params;
|
||||
struct msix_entry *msix_entries;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "11.1.0.0."
|
||||
#define LPFC_DRIVER_VERSION "11.2.0.0."
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
/* Used for SLI 2/3 */
|
||||
|
|
|
@ -4079,6 +4079,12 @@ megasas_get_pd_list(struct megasas_instance *instance)
|
|||
struct MR_PD_ADDRESS *pd_addr;
|
||||
dma_addr_t ci_h = 0;
|
||||
|
||||
if (instance->pd_list_not_supported) {
|
||||
dev_info(&instance->pdev->dev, "MR_DCMD_PD_LIST_QUERY "
|
||||
"not supported by firmware\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
cmd = megasas_get_cmd(instance);
|
||||
|
||||
if (!cmd) {
|
||||
|
|
|
@ -4903,13 +4903,22 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
|
|||
u16 ioc_status;
|
||||
u16 sz;
|
||||
u8 device_missing_delay;
|
||||
u8 num_phys;
|
||||
|
||||
mpt3sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys);
|
||||
if (!ioc->sas_hba.num_phys) {
|
||||
mpt3sas_config_get_number_hba_phys(ioc, &num_phys);
|
||||
if (!num_phys) {
|
||||
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
|
||||
ioc->name, __FILE__, __LINE__, __func__);
|
||||
return;
|
||||
}
|
||||
ioc->sas_hba.phy = kcalloc(num_phys,
|
||||
sizeof(struct _sas_phy), GFP_KERNEL);
|
||||
if (!ioc->sas_hba.phy) {
|
||||
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
|
||||
ioc->name, __FILE__, __LINE__, __func__);
|
||||
goto out;
|
||||
}
|
||||
ioc->sas_hba.num_phys = num_phys;
|
||||
|
||||
/* sas_iounit page 0 */
|
||||
sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
|
||||
|
@ -4969,13 +4978,6 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
|
|||
MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
|
||||
|
||||
ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev;
|
||||
ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys,
|
||||
sizeof(struct _sas_phy), GFP_KERNEL);
|
||||
if (!ioc->sas_hba.phy) {
|
||||
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
|
||||
ioc->name, __FILE__, __LINE__, __func__);
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
|
||||
if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
|
||||
i))) {
|
||||
|
@ -9033,8 +9035,11 @@ scsih_pci_mmio_enabled(struct pci_dev *pdev)
|
|||
|
||||
/* TODO - dump whatever for debugging purposes */
|
||||
|
||||
/* Request a slot reset. */
|
||||
return PCI_ERS_RESULT_NEED_RESET;
|
||||
/* This called only if scsih_pci_error_detected returns
|
||||
* PCI_ERS_RESULT_CAN_RECOVER. Read/write to the device still
|
||||
* works, no need to reset slot.
|
||||
*/
|
||||
return PCI_ERS_RESULT_RECOVERED;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -705,6 +705,11 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
|
|||
goto out_fail;
|
||||
}
|
||||
|
||||
if (!sas_node->parent_dev) {
|
||||
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
|
||||
ioc->name, __FILE__, __LINE__, __func__);
|
||||
goto out_fail;
|
||||
}
|
||||
port = sas_port_alloc_num(sas_node->parent_dev);
|
||||
if ((sas_port_add(port))) {
|
||||
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
|
||||
|
|
|
@ -1249,7 +1249,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev)
|
|||
|
||||
/* Chip documentation for the 8070 and 8072 SPCv */
|
||||
/* states that a 500ms minimum delay is required */
|
||||
/* before issuing commands. Otherwise, the firmare */
|
||||
/* before issuing commands. Otherwise, the firmware */
|
||||
/* will enter an unrecoverable state. */
|
||||
|
||||
if (pm8001_ha->chip_id == chip_8070 ||
|
||||
|
|
|
@ -146,92 +146,6 @@ static struct bin_attribute sysfs_fw_dump_attr = {
|
|||
.write = qla2x00_sysfs_write_fw_dump,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
qla2x00_sysfs_read_fw_dump_template(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
{
|
||||
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
||||
struct device, kobj)));
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
|
||||
if (!ha->fw_dump_template || !ha->fw_dump_template_len)
|
||||
return 0;
|
||||
|
||||
ql_dbg(ql_dbg_user, vha, 0x70e2,
|
||||
"chunk <- off=%llx count=%zx\n", off, count);
|
||||
return memory_read_from_buffer(buf, count, &off,
|
||||
ha->fw_dump_template, ha->fw_dump_template_len);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
qla2x00_sysfs_write_fw_dump_template(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
char *buf, loff_t off, size_t count)
|
||||
{
|
||||
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
|
||||
struct device, kobj)));
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
uint32_t size;
|
||||
|
||||
if (off == 0) {
|
||||
if (ha->fw_dump)
|
||||
vfree(ha->fw_dump);
|
||||
if (ha->fw_dump_template)
|
||||
vfree(ha->fw_dump_template);
|
||||
|
||||
ha->fw_dump = NULL;
|
||||
ha->fw_dump_len = 0;
|
||||
ha->fw_dump_template = NULL;
|
||||
ha->fw_dump_template_len = 0;
|
||||
|
||||
size = qla27xx_fwdt_template_size(buf);
|
||||
ql_dbg(ql_dbg_user, vha, 0x70d1,
|
||||
"-> allocating fwdt (%x bytes)...\n", size);
|
||||
ha->fw_dump_template = vmalloc(size);
|
||||
if (!ha->fw_dump_template) {
|
||||
ql_log(ql_log_warn, vha, 0x70d2,
|
||||
"Failed allocate fwdt (%x bytes).\n", size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
ha->fw_dump_template_len = size;
|
||||
}
|
||||
|
||||
if (off + count > ha->fw_dump_template_len) {
|
||||
count = ha->fw_dump_template_len - off;
|
||||
ql_dbg(ql_dbg_user, vha, 0x70d3,
|
||||
"chunk -> truncating to %zx bytes.\n", count);
|
||||
}
|
||||
|
||||
ql_dbg(ql_dbg_user, vha, 0x70d4,
|
||||
"chunk -> off=%llx count=%zx\n", off, count);
|
||||
memcpy(ha->fw_dump_template + off, buf, count);
|
||||
|
||||
if (off + count == ha->fw_dump_template_len) {
|
||||
size = qla27xx_fwdt_calculate_dump_size(vha);
|
||||
ql_dbg(ql_dbg_user, vha, 0x70d5,
|
||||
"-> allocating fwdump (%x bytes)...\n", size);
|
||||
ha->fw_dump = vmalloc(size);
|
||||
if (!ha->fw_dump) {
|
||||
ql_log(ql_log_warn, vha, 0x70d6,
|
||||
"Failed allocate fwdump (%x bytes).\n", size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
ha->fw_dump_len = size;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
static struct bin_attribute sysfs_fw_dump_template_attr = {
|
||||
.attr = {
|
||||
.name = "fw_dump_template",
|
||||
.mode = S_IRUSR | S_IWUSR,
|
||||
},
|
||||
.size = 0,
|
||||
.read = qla2x00_sysfs_read_fw_dump_template,
|
||||
.write = qla2x00_sysfs_write_fw_dump_template,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
qla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *bin_attr,
|
||||
|
@ -973,7 +887,6 @@ static struct sysfs_entry {
|
|||
int is4GBp_only;
|
||||
} bin_file_entries[] = {
|
||||
{ "fw_dump", &sysfs_fw_dump_attr, },
|
||||
{ "fw_dump_template", &sysfs_fw_dump_template_attr, 0x27 },
|
||||
{ "nvram", &sysfs_nvram_attr, },
|
||||
{ "optrom", &sysfs_optrom_attr, },
|
||||
{ "optrom_ctl", &sysfs_optrom_ctl_attr, },
|
||||
|
@ -1000,8 +913,6 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha)
|
|||
continue;
|
||||
if (iter->is4GBp_only == 3 && !(IS_CNA_CAPABLE(vha->hw)))
|
||||
continue;
|
||||
if (iter->is4GBp_only == 0x27 && !IS_QLA27XX(vha->hw))
|
||||
continue;
|
||||
|
||||
ret = sysfs_create_bin_file(&host->shost_gendev.kobj,
|
||||
iter->attr);
|
||||
|
@ -1858,6 +1769,9 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
|
|||
if (!fcport)
|
||||
return;
|
||||
|
||||
if (test_bit(UNLOADING, &fcport->vha->dpc_flags))
|
||||
return;
|
||||
|
||||
if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
|
||||
return;
|
||||
|
||||
|
@ -1900,10 +1814,9 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
|
|||
int rval;
|
||||
struct link_statistics *stats;
|
||||
dma_addr_t stats_dma;
|
||||
struct fc_host_statistics *pfc_host_stat;
|
||||
struct fc_host_statistics *p = &vha->fc_host_stat;
|
||||
|
||||
pfc_host_stat = &vha->fc_host_stat;
|
||||
memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics));
|
||||
memset(p, -1, sizeof(*p));
|
||||
|
||||
if (IS_QLAFX00(vha->hw))
|
||||
goto done;
|
||||
|
@ -1918,17 +1831,17 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
|
|||
goto done;
|
||||
|
||||
stats = dma_alloc_coherent(&ha->pdev->dev,
|
||||
sizeof(struct link_statistics), &stats_dma, GFP_KERNEL);
|
||||
if (stats == NULL) {
|
||||
sizeof(*stats), &stats_dma, GFP_KERNEL);
|
||||
if (!stats) {
|
||||
ql_log(ql_log_warn, vha, 0x707d,
|
||||
"Failed to allocate memory for stats.\n");
|
||||
goto done;
|
||||
}
|
||||
memset(stats, 0, DMA_POOL_SIZE);
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
|
||||
rval = QLA_FUNCTION_FAILED;
|
||||
if (IS_FWI2_CAPABLE(ha)) {
|
||||
rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma);
|
||||
rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma, 0);
|
||||
} else if (atomic_read(&base_vha->loop_state) == LOOP_READY &&
|
||||
!ha->dpc_active) {
|
||||
/* Must be in a 'READY' state for statistics retrieval. */
|
||||
|
@ -1939,47 +1852,68 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
|
|||
if (rval != QLA_SUCCESS)
|
||||
goto done_free;
|
||||
|
||||
pfc_host_stat->link_failure_count = stats->link_fail_cnt;
|
||||
pfc_host_stat->loss_of_sync_count = stats->loss_sync_cnt;
|
||||
pfc_host_stat->loss_of_signal_count = stats->loss_sig_cnt;
|
||||
pfc_host_stat->prim_seq_protocol_err_count = stats->prim_seq_err_cnt;
|
||||
pfc_host_stat->invalid_tx_word_count = stats->inval_xmit_word_cnt;
|
||||
pfc_host_stat->invalid_crc_count = stats->inval_crc_cnt;
|
||||
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)) {
|
||||
pfc_host_stat->lip_count = stats->lip_cnt;
|
||||
pfc_host_stat->tx_frames = stats->tx_frames;
|
||||
pfc_host_stat->rx_frames = stats->rx_frames;
|
||||
pfc_host_stat->dumped_frames = stats->discarded_frames;
|
||||
pfc_host_stat->nos_count = stats->nos_rcvd;
|
||||
pfc_host_stat->error_frames =
|
||||
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;
|
||||
pfc_host_stat->rx_words = vha->qla_stats.input_bytes;
|
||||
pfc_host_stat->tx_words = vha->qla_stats.output_bytes;
|
||||
p->rx_words = vha->qla_stats.input_bytes;
|
||||
p->tx_words = vha->qla_stats.output_bytes;
|
||||
}
|
||||
pfc_host_stat->fcp_control_requests = vha->qla_stats.control_requests;
|
||||
pfc_host_stat->fcp_input_requests = vha->qla_stats.input_requests;
|
||||
pfc_host_stat->fcp_output_requests = vha->qla_stats.output_requests;
|
||||
pfc_host_stat->fcp_input_megabytes = vha->qla_stats.input_bytes >> 20;
|
||||
pfc_host_stat->fcp_output_megabytes = vha->qla_stats.output_bytes >> 20;
|
||||
pfc_host_stat->seconds_since_last_reset =
|
||||
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->seconds_since_last_reset =
|
||||
get_jiffies_64() - vha->qla_stats.jiffies_at_last_reset;
|
||||
do_div(pfc_host_stat->seconds_since_last_reset, HZ);
|
||||
do_div(p->seconds_since_last_reset, HZ);
|
||||
|
||||
done_free:
|
||||
dma_free_coherent(&ha->pdev->dev, sizeof(struct link_statistics),
|
||||
stats, stats_dma);
|
||||
done:
|
||||
return pfc_host_stat;
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
qla2x00_reset_host_stats(struct Scsi_Host *shost)
|
||||
{
|
||||
scsi_qla_host_t *vha = shost_priv(shost);
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
|
||||
struct link_statistics *stats;
|
||||
dma_addr_t stats_dma;
|
||||
|
||||
memset(&vha->qla_stats, 0, sizeof(vha->qla_stats));
|
||||
memset(&vha->fc_host_stat, 0, sizeof(vha->fc_host_stat));
|
||||
|
||||
vha->qla_stats.jiffies_at_last_reset = get_jiffies_64();
|
||||
|
||||
if (IS_FWI2_CAPABLE(ha)) {
|
||||
stats = dma_alloc_coherent(&ha->pdev->dev,
|
||||
sizeof(*stats), &stats_dma, GFP_KERNEL);
|
||||
if (!stats) {
|
||||
ql_log(ql_log_warn, vha, 0x70d7,
|
||||
"Failed to allocate memory for stats.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* reset firmware statistics */
|
||||
qla24xx_get_isp_stats(base_vha, stats, stats_dma, BIT_0);
|
||||
|
||||
dma_free_coherent(&ha->pdev->dev, sizeof(*stats),
|
||||
stats, stats_dma);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -2246,53 +2246,94 @@ qla2x00_get_priv_stats(struct fc_bsg_job *bsg_job)
|
|||
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
|
||||
struct link_statistics *stats = NULL;
|
||||
dma_addr_t stats_dma;
|
||||
int rval = QLA_FUNCTION_FAILED;
|
||||
int rval;
|
||||
uint32_t *cmd = bsg_job->request->rqst_data.h_vendor.vendor_cmd;
|
||||
uint options = cmd[0] == QL_VND_GET_PRIV_STATS_EX ? cmd[1] : 0;
|
||||
|
||||
if (test_bit(UNLOADING, &vha->dpc_flags))
|
||||
goto done;
|
||||
return -ENODEV;
|
||||
|
||||
if (unlikely(pci_channel_offline(ha->pdev)))
|
||||
goto done;
|
||||
return -ENODEV;
|
||||
|
||||
if (qla2x00_reset_active(vha))
|
||||
goto done;
|
||||
return -EBUSY;
|
||||
|
||||
if (!IS_FWI2_CAPABLE(ha))
|
||||
goto done;
|
||||
return -EPERM;
|
||||
|
||||
stats = dma_alloc_coherent(&ha->pdev->dev,
|
||||
sizeof(struct link_statistics), &stats_dma, GFP_KERNEL);
|
||||
sizeof(*stats), &stats_dma, GFP_KERNEL);
|
||||
if (!stats) {
|
||||
ql_log(ql_log_warn, vha, 0x70e2,
|
||||
"Failed to allocate memory for stats.\n");
|
||||
goto done;
|
||||
"Failed to allocate memory for stats.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(stats, 0, sizeof(struct link_statistics));
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
|
||||
rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma);
|
||||
rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma, options);
|
||||
|
||||
if (rval != QLA_SUCCESS)
|
||||
goto done_free;
|
||||
if (rval == QLA_SUCCESS) {
|
||||
ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e3,
|
||||
(uint8_t *)stats, sizeof(*stats));
|
||||
sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
|
||||
bsg_job->reply_payload.sg_cnt, stats, sizeof(*stats));
|
||||
}
|
||||
|
||||
ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e3,
|
||||
(uint8_t *)stats, sizeof(struct link_statistics));
|
||||
bsg_job->reply->reply_payload_rcv_len = sizeof(*stats);
|
||||
bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
|
||||
rval ? EXT_STATUS_MAILBOX : EXT_STATUS_OK;
|
||||
|
||||
sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
|
||||
bsg_job->reply_payload.sg_cnt, stats, sizeof(struct link_statistics));
|
||||
bsg_job->reply->reply_payload_rcv_len = sizeof(struct link_statistics);
|
||||
|
||||
bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
|
||||
|
||||
bsg_job->reply_len = sizeof(struct fc_bsg_reply);
|
||||
bsg_job->reply_len = sizeof(*bsg_job->reply);
|
||||
bsg_job->reply->result = DID_OK << 16;
|
||||
bsg_job->job_done(bsg_job);
|
||||
|
||||
done_free:
|
||||
dma_free_coherent(&ha->pdev->dev, sizeof(struct link_statistics),
|
||||
dma_free_coherent(&ha->pdev->dev, sizeof(*stats),
|
||||
stats, stats_dma);
|
||||
done:
|
||||
return rval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qla2x00_do_dport_diagnostics(struct fc_bsg_job *bsg_job)
|
||||
{
|
||||
struct Scsi_Host *host = bsg_job->shost;
|
||||
scsi_qla_host_t *vha = shost_priv(host);
|
||||
int rval;
|
||||
struct qla_dport_diag *dd;
|
||||
|
||||
if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw))
|
||||
return -EPERM;
|
||||
|
||||
dd = kmalloc(sizeof(*dd), GFP_KERNEL);
|
||||
if (!dd) {
|
||||
ql_log(ql_log_warn, vha, 0x70db,
|
||||
"Failed to allocate memory for dport.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
sg_copy_to_buffer(bsg_job->request_payload.sg_list,
|
||||
bsg_job->request_payload.sg_cnt, dd, sizeof(*dd));
|
||||
|
||||
rval = qla26xx_dport_diagnostics(
|
||||
vha, dd->buf, sizeof(dd->buf), dd->options);
|
||||
if (rval == QLA_SUCCESS) {
|
||||
sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
|
||||
bsg_job->reply_payload.sg_cnt, dd, sizeof(*dd));
|
||||
}
|
||||
|
||||
bsg_job->reply->reply_payload_rcv_len = sizeof(*dd);
|
||||
bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] =
|
||||
rval ? EXT_STATUS_MAILBOX : EXT_STATUS_OK;
|
||||
|
||||
bsg_job->reply_len = sizeof(*bsg_job->reply);
|
||||
bsg_job->reply->result = DID_OK << 16;
|
||||
bsg_job->job_done(bsg_job);
|
||||
|
||||
kfree(dd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -2360,8 +2401,12 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
|
|||
return qla27xx_get_bbcr_data(bsg_job);
|
||||
|
||||
case QL_VND_GET_PRIV_STATS:
|
||||
case QL_VND_GET_PRIV_STATS_EX:
|
||||
return qla2x00_get_priv_stats(bsg_job);
|
||||
|
||||
case QL_VND_DPORT_DIAGNOSTICS:
|
||||
return qla2x00_do_dport_diagnostics(bsg_job);
|
||||
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#define QL_VND_SET_FLASH_UPDATE_CAPS 0x16
|
||||
#define QL_VND_GET_BBCR_DATA 0x17
|
||||
#define QL_VND_GET_PRIV_STATS 0x18
|
||||
#define QL_VND_DPORT_DIAGNOSTICS 0x19
|
||||
#define QL_VND_GET_PRIV_STATS_EX 0x1A
|
||||
|
||||
/* BSG Vendor specific subcode returns */
|
||||
#define EXT_STATUS_OK 0
|
||||
|
@ -266,4 +268,15 @@ struct qla_bbcr_data {
|
|||
uint16_t mbx1; /* Port state */
|
||||
uint8_t reserved[9];
|
||||
} __packed;
|
||||
|
||||
struct qla_dport_diag {
|
||||
uint16_t options;
|
||||
uint32_t buf[16];
|
||||
uint8_t unused[62];
|
||||
} __packed;
|
||||
|
||||
/* D_Port options */
|
||||
#define QLA_DPORT_RESULT 0x0
|
||||
#define QLA_DPORT_START 0x2
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,12 +11,11 @@
|
|||
* ----------------------------------------------------------------------
|
||||
* | Level | Last Value Used | Holes |
|
||||
* ----------------------------------------------------------------------
|
||||
* | Module Init and Probe | 0x018f | 0x0146 |
|
||||
* | Module Init and Probe | 0x0191 | 0x0146 |
|
||||
* | | | 0x015b-0x0160 |
|
||||
* | | | 0x016e-0x0170 |
|
||||
* | Mailbox commands | 0x1192 | |
|
||||
* | | | |
|
||||
* | Device Discovery | 0x2016 | 0x2020-0x2022, |
|
||||
* | | | 0x016e |
|
||||
* | Mailbox commands | 0x1199 | 0x1193 |
|
||||
* | Device Discovery | 0x2004 | 0x2016 |
|
||||
* | | | 0x2011-0x2012, |
|
||||
* | | | 0x2099-0x20a4 |
|
||||
* | Queue Command and IO tracing | 0x3074 | 0x300b |
|
||||
|
@ -26,11 +25,11 @@
|
|||
* | | | 0x3036,0x3038 |
|
||||
* | | | 0x303a |
|
||||
* | DPC Thread | 0x4023 | 0x4002,0x4013 |
|
||||
* | Async Events | 0x5089 | 0x502b-0x502f |
|
||||
* | | | 0x505e |
|
||||
* | Async Events | 0x5090 | 0x502b-0x502f |
|
||||
* | | | 0x5047 |
|
||||
* | | | 0x5084,0x5075 |
|
||||
* | | | 0x503d,0x5044 |
|
||||
* | | | 0x507b,0x505f |
|
||||
* | | | 0x505f |
|
||||
* | Timer Routines | 0x6012 | |
|
||||
* | User Space Interactions | 0x70e3 | 0x7018,0x702e |
|
||||
* | | | 0x7020,0x7024 |
|
||||
|
@ -39,9 +38,9 @@
|
|||
* | | | 0x70a5-0x70a6 |
|
||||
* | | | 0x70a8,0x70ab |
|
||||
* | | | 0x70ad-0x70ae |
|
||||
* | | | 0x70d0-0x70d6 |
|
||||
* | | | 0x70d7-0x70db |
|
||||
* | | | 0x70de-0x70df |
|
||||
* | Task Management | 0x803d | 0x8000,0x800b |
|
||||
* | Task Management | 0x8042 | 0x8000,0x800b |
|
||||
* | | | 0x8019 |
|
||||
* | | | 0x8025,0x8026 |
|
||||
* | | | 0x8031,0x8032 |
|
||||
|
@ -2697,29 +2696,24 @@ ql_dump_regs(uint32_t level, scsi_qla_host_t *vha, int32_t id)
|
|||
|
||||
void
|
||||
ql_dump_buffer(uint32_t level, scsi_qla_host_t *vha, int32_t id,
|
||||
uint8_t *b, uint32_t size)
|
||||
uint8_t *buf, uint size)
|
||||
{
|
||||
uint32_t cnt;
|
||||
uint8_t c;
|
||||
uint cnt;
|
||||
|
||||
if (!ql_mask_match(level))
|
||||
return;
|
||||
|
||||
ql_dbg(level, vha, id, " 0 1 2 3 4 5 6 7 8 "
|
||||
"9 Ah Bh Ch Dh Eh Fh\n");
|
||||
ql_dbg(level, vha, id, "----------------------------------"
|
||||
"----------------------------\n");
|
||||
|
||||
ql_dbg(level, vha, id, " ");
|
||||
for (cnt = 0; cnt < size;) {
|
||||
c = *b++;
|
||||
printk("%02x", (uint32_t) c);
|
||||
cnt++;
|
||||
if (!(cnt % 16))
|
||||
ql_dbg(level, vha, id,
|
||||
"%-+5d 0 1 2 3 4 5 6 7 8 9 A B C D E F\n", size);
|
||||
ql_dbg(level, vha, id,
|
||||
"----- -----------------------------------------------\n");
|
||||
for (cnt = 0; cnt < size; cnt++, buf++) {
|
||||
if (cnt % 16 == 0)
|
||||
ql_dbg(level, vha, id, "%04x:", cnt & ~0xFU);
|
||||
printk(" %02x", *buf);
|
||||
if (cnt % 16 == 15)
|
||||
printk("\n");
|
||||
else
|
||||
printk(" ");
|
||||
}
|
||||
if (cnt % 16)
|
||||
ql_dbg(level, vha, id, "\n");
|
||||
if (cnt % 16 != 0)
|
||||
printk("\n");
|
||||
}
|
||||
|
|
|
@ -829,6 +829,7 @@ struct mbx_cmd_32 {
|
|||
#define MBA_FW_RESTART_CMPLT 0x8060 /* Firmware restart complete */
|
||||
#define MBA_INIT_REQUIRED 0x8061 /* Initialization required */
|
||||
#define MBA_SHUTDOWN_REQUESTED 0x8062 /* Shutdown Requested */
|
||||
#define MBA_TEMPERATURE_ALERT 0x8070 /* Temperature Alert */
|
||||
#define MBA_DPORT_DIAGNOSTICS 0x8080 /* D-port Diagnostics */
|
||||
#define MBA_FW_INIT_FAILURE 0x8401 /* Firmware initialization failure */
|
||||
#define MBA_MIRROR_LUN_CHANGE 0x8402 /* Mirror LUN State Change
|
||||
|
@ -3028,6 +3029,7 @@ struct qla_hw_data {
|
|||
uint32_t mr_reset_hdlr_active:1;
|
||||
uint32_t mr_intr_valid:1;
|
||||
|
||||
uint32_t dport_enabled:1;
|
||||
uint32_t fawwpn_enabled:1;
|
||||
uint32_t exlogins_enabled:1;
|
||||
uint32_t exchoffld_enabled:1;
|
||||
|
@ -3128,7 +3130,7 @@ struct qla_hw_data {
|
|||
#define PCI_DEVICE_ID_QLOGIC_ISP2271 0x2271
|
||||
#define PCI_DEVICE_ID_QLOGIC_ISP2261 0x2261
|
||||
|
||||
uint32_t device_type;
|
||||
uint32_t isp_type;
|
||||
#define DT_ISP2100 BIT_0
|
||||
#define DT_ISP2200 BIT_1
|
||||
#define DT_ISP2300 BIT_2
|
||||
|
@ -3153,6 +3155,7 @@ struct qla_hw_data {
|
|||
#define DT_ISP2261 BIT_21
|
||||
#define DT_ISP_LAST (DT_ISP2261 << 1)
|
||||
|
||||
uint32_t device_type;
|
||||
#define DT_T10_PI BIT_25
|
||||
#define DT_IIDMA BIT_26
|
||||
#define DT_FWI2 BIT_27
|
||||
|
@ -3160,7 +3163,8 @@ struct qla_hw_data {
|
|||
#define DT_OEM_001 BIT_29
|
||||
#define DT_ISP2200A BIT_30
|
||||
#define DT_EXTENDED_IDS BIT_31
|
||||
#define DT_MASK(ha) ((ha)->device_type & (DT_ISP_LAST - 1))
|
||||
|
||||
#define DT_MASK(ha) ((ha)->isp_type & (DT_ISP_LAST - 1))
|
||||
#define IS_QLA2100(ha) (DT_MASK(ha) & DT_ISP2100)
|
||||
#define IS_QLA2200(ha) (DT_MASK(ha) & DT_ISP2200)
|
||||
#define IS_QLA2300(ha) (DT_MASK(ha) & DT_ISP2300)
|
||||
|
@ -3370,6 +3374,8 @@ struct qla_hw_data {
|
|||
|
||||
uint32_t fw_shared_ram_start;
|
||||
uint32_t fw_shared_ram_end;
|
||||
uint32_t fw_ddr_ram_start;
|
||||
uint32_t fw_ddr_ram_end;
|
||||
|
||||
uint16_t fw_options[16]; /* slots: 1,2,3,10,11 */
|
||||
uint8_t fw_seriallink_options[4];
|
||||
|
@ -3505,7 +3511,6 @@ struct qla_hw_data {
|
|||
int cur_vport_count;
|
||||
|
||||
struct qla_chip_state_84xx *cs84xx;
|
||||
struct qla_statistics qla_stats;
|
||||
struct isp_operations *isp_ops;
|
||||
struct workqueue_struct *wq;
|
||||
struct qlfc_fw fw_buf;
|
||||
|
@ -3656,6 +3661,7 @@ typedef struct scsi_qla_host {
|
|||
#define PFLG_DISCONNECTED 0 /* PCI device removed */
|
||||
#define PFLG_DRIVER_REMOVING 1 /* PCI driver .remove */
|
||||
#define PFLG_DRIVER_PROBING 2 /* PCI driver .probe */
|
||||
#define PCI_ERR 30
|
||||
|
||||
uint32_t device_flags;
|
||||
#define SWITCH_FOUND BIT_0
|
||||
|
|
|
@ -1288,7 +1288,7 @@ struct vp_rpt_id_entry_24xx {
|
|||
|
||||
uint8_t vp_idx_map[16];
|
||||
|
||||
uint8_t reserved_4[28];
|
||||
uint8_t reserved_4[24];
|
||||
uint16_t bbcr;
|
||||
uint8_t reserved_5[6];
|
||||
};
|
||||
|
|
|
@ -344,7 +344,7 @@ qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, struct link_statistics *,
|
|||
|
||||
extern int
|
||||
qla24xx_get_isp_stats(scsi_qla_host_t *, struct link_statistics *,
|
||||
dma_addr_t);
|
||||
dma_addr_t, uint);
|
||||
|
||||
extern int qla24xx_abort_command(srb_t *);
|
||||
extern int qla24xx_async_abort_command(srb_t *);
|
||||
|
@ -445,6 +445,9 @@ qla2x00_port_logout(scsi_qla_host_t *, struct fc_port *);
|
|||
extern int
|
||||
qla2x00_dump_mctp_data(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
|
||||
|
||||
extern int
|
||||
qla26xx_dport_diagnostics(scsi_qla_host_t *, void *, uint, uint);
|
||||
|
||||
/*
|
||||
* Global Function Prototypes in qla_isr.c source file.
|
||||
*/
|
||||
|
|
|
@ -624,6 +624,9 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
|
|||
struct qla_hw_data *ha = vha->hw;
|
||||
struct req_que *req = ha->req_q_map[0];
|
||||
|
||||
memset(&vha->qla_stats, 0, sizeof(vha->qla_stats));
|
||||
memset(&vha->fc_host_stat, 0, sizeof(vha->fc_host_stat));
|
||||
|
||||
/* Clear adapter flags. */
|
||||
vha->flags.online = 0;
|
||||
ha->flags.chip_reset_done = 0;
|
||||
|
@ -2053,6 +2056,14 @@ qla2x00_update_fw_options(scsi_qla_host_t *vha)
|
|||
if (IS_QLA6312(ha))
|
||||
ha->fw_options[2] |= BIT_13;
|
||||
|
||||
/* 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, 0x2100,
|
||||
"(%s): Setting FLOGI retry BIT in fw_options[2]: 0x%x\n",
|
||||
__func__, ha->fw_options[2]);
|
||||
}
|
||||
|
||||
/* Update firmware options. */
|
||||
qla2x00_set_fw_options(vha, ha->fw_options);
|
||||
}
|
||||
|
@ -2070,6 +2081,14 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
|
|||
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, 0x2101,
|
||||
"(%s): Setting FLOGI retry BIT in fw_options[2]: 0x%x\n",
|
||||
__func__, ha->fw_options[2]);
|
||||
}
|
||||
|
||||
/* Update Serial Link options. */
|
||||
if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)
|
||||
return;
|
||||
|
@ -2269,13 +2288,13 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
|
|||
mid_init_cb->options = cpu_to_le16(BIT_1);
|
||||
mid_init_cb->init_cb.execution_throttle =
|
||||
cpu_to_le16(ha->cur_fw_xcb_count);
|
||||
/* D-Port Status */
|
||||
if (IS_DPORT_CAPABLE(ha))
|
||||
mid_init_cb->init_cb.firmware_options_1 |=
|
||||
cpu_to_le16(BIT_7);
|
||||
/* Enable FA-WWPN */
|
||||
ha->flags.dport_enabled =
|
||||
(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) ? 1 : 0;
|
||||
(mid_init_cb->init_cb.firmware_options_1 & BIT_6) != 0;
|
||||
ql_dbg(ql_dbg_init, vha, 0x0141, "FA-WWPN Support: %s.\n",
|
||||
(ha->flags.fawwpn_enabled) ? "enabled" : "disabled");
|
||||
}
|
||||
|
@ -6513,6 +6532,14 @@ qla81xx_update_fw_options(scsi_qla_host_t *vha)
|
|||
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]);
|
||||
}
|
||||
|
||||
if (!ql2xetsenable)
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -710,16 +710,23 @@ skip_rio:
|
|||
|
||||
case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */
|
||||
ql_log(ql_log_warn, vha, 0x5007,
|
||||
"ISP Response Transfer Error.\n");
|
||||
"ISP Response Transfer Error (%x).\n", mb[1]);
|
||||
|
||||
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
||||
break;
|
||||
|
||||
case MBA_WAKEUP_THRES: /* Request Queue Wake-up */
|
||||
ql_dbg(ql_dbg_async, vha, 0x5008,
|
||||
"Asynchronous WAKEUP_THRES.\n");
|
||||
|
||||
"Asynchronous WAKEUP_THRES (%x).\n", mb[1]);
|
||||
break;
|
||||
|
||||
case MBA_LOOP_INIT_ERR:
|
||||
ql_log(ql_log_warn, vha, 0x5090,
|
||||
"LOOP INIT ERROR (%x).\n", mb[1]);
|
||||
ha->isp_ops->fw_dump(vha, 1);
|
||||
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
|
||||
break;
|
||||
|
||||
case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */
|
||||
ql_dbg(ql_dbg_async, vha, 0x5009,
|
||||
"LIP occurred (%x).\n", mb[1]);
|
||||
|
@ -1152,12 +1159,20 @@ global_port_update:
|
|||
|
||||
case MBA_DPORT_DIAGNOSTICS:
|
||||
ql_dbg(ql_dbg_async, vha, 0x5052,
|
||||
"D-Port Diagnostics: %04x %04x=%s\n", mb[0], mb[1],
|
||||
"D-Port Diagnostics: %04x result=%s\n",
|
||||
mb[0],
|
||||
mb[1] == 0 ? "start" :
|
||||
mb[1] == 1 ? "done (ok)" :
|
||||
mb[1] == 1 ? "done (pass)" :
|
||||
mb[1] == 2 ? "done (error)" : "other");
|
||||
break;
|
||||
|
||||
case MBA_TEMPERATURE_ALERT:
|
||||
ql_dbg(ql_dbg_async, vha, 0x505e,
|
||||
"TEMPERATURE ALERT: %04x %04x %04x\n", mb[1], mb[2], mb[3]);
|
||||
if (mb[1] == 0x12)
|
||||
schedule_work(&ha->board_disable);
|
||||
break;
|
||||
|
||||
default:
|
||||
ql_dbg(ql_dbg_async, vha, 0x5057,
|
||||
"Unknown AEN:%04x %04x %04x %04x\n",
|
||||
|
@ -3086,6 +3101,8 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
|
|||
/* Enable MSI-X vectors for the base queue */
|
||||
for (i = 0; i < 2; i++) {
|
||||
qentry = &ha->msix_entries[i];
|
||||
qentry->rsp = rsp;
|
||||
rsp->msix = qentry;
|
||||
if (IS_P3P_TYPE(ha))
|
||||
ret = request_irq(qentry->vector,
|
||||
qla82xx_msix_entries[i].handler,
|
||||
|
@ -3097,8 +3114,6 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
|
|||
if (ret)
|
||||
goto msix_register_fail;
|
||||
qentry->have_irq = 1;
|
||||
qentry->rsp = rsp;
|
||||
rsp->msix = qentry;
|
||||
|
||||
/* Register for CPU affinity notification. */
|
||||
irq_set_affinity_notifier(qentry->vector, &qentry->irq_notify);
|
||||
|
@ -3119,12 +3134,12 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
|
|||
*/
|
||||
if (QLA_TGT_MODE_ENABLED() && IS_ATIO_MSIX_CAPABLE(ha)) {
|
||||
qentry = &ha->msix_entries[ATIO_VECTOR];
|
||||
qentry->rsp = rsp;
|
||||
rsp->msix = qentry;
|
||||
ret = request_irq(qentry->vector,
|
||||
qla83xx_msix_entries[ATIO_VECTOR].handler,
|
||||
0, qla83xx_msix_entries[ATIO_VECTOR].name, rsp);
|
||||
qentry->have_irq = 1;
|
||||
qentry->rsp = rsp;
|
||||
rsp->msix = qentry;
|
||||
}
|
||||
|
||||
msix_register_fail:
|
||||
|
|
|
@ -64,6 +64,13 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
|
|||
return QLA_FUNCTION_TIMEOUT;
|
||||
}
|
||||
|
||||
/* if PCI error, then avoid mbx processing.*/
|
||||
if (test_bit(PCI_ERR, &base_vha->dpc_flags)) {
|
||||
ql_log(ql_log_warn, vha, 0x1191,
|
||||
"PCI error, exiting.\n");
|
||||
return QLA_FUNCTION_TIMEOUT;
|
||||
}
|
||||
|
||||
reg = ha->iobase;
|
||||
io_lock_on = base_vha->flags.init_done;
|
||||
|
||||
|
@ -266,6 +273,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
|
|||
|
||||
uint16_t mb0;
|
||||
uint32_t ictrl;
|
||||
uint16_t w;
|
||||
|
||||
if (IS_FWI2_CAPABLE(ha)) {
|
||||
mb0 = RD_REG_WORD(®->isp24.mailbox0);
|
||||
|
@ -279,15 +287,32 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
|
|||
"mb[0]=0x%x\n", command, ictrl, jiffies, mb0);
|
||||
ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019);
|
||||
|
||||
/*
|
||||
* Attempt to capture a firmware dump for further analysis
|
||||
* of the current firmware state. We do not need to do this
|
||||
* if we are intentionally generating a dump.
|
||||
*/
|
||||
if (mcp->mb[0] != MBC_GEN_SYSTEM_ERROR)
|
||||
ha->isp_ops->fw_dump(vha, 0);
|
||||
/* Capture FW dump only, if PCI device active */
|
||||
if (!pci_channel_offline(vha->hw->pdev)) {
|
||||
pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
|
||||
if (w == 0xffff || ictrl == 0xffffffff) {
|
||||
/* This is special case if there is unload
|
||||
* of driver happening and if PCI device go
|
||||
* into bad state due to PCI error condition
|
||||
* then only PCI ERR flag would be set.
|
||||
* we will do premature exit for above case.
|
||||
*/
|
||||
if (test_bit(UNLOADING, &base_vha->dpc_flags))
|
||||
set_bit(PCI_ERR, &base_vha->dpc_flags);
|
||||
ha->flags.mbox_busy = 0;
|
||||
rval = QLA_FUNCTION_TIMEOUT;
|
||||
goto premature_exit;
|
||||
}
|
||||
|
||||
rval = QLA_FUNCTION_TIMEOUT;
|
||||
/* Attempt to capture firmware dump for further
|
||||
* anallysis of the current formware state. we do not
|
||||
* need to do this if we are intentionally generating
|
||||
* a dump
|
||||
*/
|
||||
if (mcp->mb[0] != MBC_GEN_SYSTEM_ERROR)
|
||||
ha->isp_ops->fw_dump(vha, 0);
|
||||
rval = QLA_FUNCTION_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
ha->flags.mbox_busy = 0;
|
||||
|
@ -379,7 +404,7 @@ mbx_done:
|
|||
"**** Failed mbx[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x, cmd=%x ****.\n",
|
||||
mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], command);
|
||||
|
||||
ql_dbg(ql_dbg_disc, vha, 0x1115,
|
||||
ql_dbg(ql_dbg_mbx, vha, 0x1198,
|
||||
"host status: 0x%x, flags:0x%lx, intr ctrl reg:0x%x, intr status:0x%x\n",
|
||||
RD_REG_DWORD(®->isp24.host_status),
|
||||
ha->fw_dump_cap_flags,
|
||||
|
@ -388,7 +413,7 @@ mbx_done:
|
|||
|
||||
mbx_reg = ®->isp24.mailbox0;
|
||||
for (i = 0; i < 6; i++)
|
||||
ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x1116,
|
||||
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1199,
|
||||
"mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg++));
|
||||
} else {
|
||||
ql_dbg(ql_dbg_mbx, base_vha, 0x1021, "Done %s.\n", __func__);
|
||||
|
@ -782,8 +807,9 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha)
|
|||
if (IS_FWI2_CAPABLE(ha))
|
||||
mcp->in_mb |= MBX_17|MBX_16|MBX_15;
|
||||
if (IS_QLA27XX(ha))
|
||||
mcp->in_mb |= MBX_23 | MBX_22 | MBX_21 | MBX_20 | MBX_19 |
|
||||
MBX_18 | MBX_14 | MBX_13 | MBX_11 | MBX_10 | MBX_9 | MBX_8;
|
||||
mcp->in_mb |=
|
||||
MBX_25|MBX_24|MBX_23|MBX_22|MBX_21|MBX_20|MBX_19|MBX_18|
|
||||
MBX_14|MBX_13|MBX_11|MBX_10|MBX_9|MBX_8;
|
||||
|
||||
mcp->flags = 0;
|
||||
mcp->tov = MBX_TOV_SECONDS;
|
||||
|
@ -842,6 +868,8 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha)
|
|||
ha->pep_version[2] = mcp->mb[14] & 0xff;
|
||||
ha->fw_shared_ram_start = (mcp->mb[19] << 16) | mcp->mb[18];
|
||||
ha->fw_shared_ram_end = (mcp->mb[21] << 16) | mcp->mb[20];
|
||||
ha->fw_ddr_ram_start = (mcp->mb[23] << 16) | mcp->mb[22];
|
||||
ha->fw_ddr_ram_end = (mcp->mb[25] << 16) | mcp->mb[24];
|
||||
}
|
||||
|
||||
failed:
|
||||
|
@ -1844,7 +1872,7 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states)
|
|||
states[0] = mcp->mb[1];
|
||||
if (IS_FWI2_CAPABLE(vha->hw)) {
|
||||
states[1] = mcp->mb[2];
|
||||
states[2] = mcp->mb[3];
|
||||
states[2] = mcp->mb[3]; /* SFP info */
|
||||
states[3] = mcp->mb[4];
|
||||
states[4] = mcp->mb[5];
|
||||
states[5] = mcp->mb[6]; /* DPORT status */
|
||||
|
@ -2759,15 +2787,16 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
|
|||
int rval;
|
||||
mbx_cmd_t mc;
|
||||
mbx_cmd_t *mcp = &mc;
|
||||
uint32_t *iter, dwords;
|
||||
uint32_t *iter = (void *)stats;
|
||||
ushort dwords = offsetof(typeof(*stats), link_up_cnt)/sizeof(*iter);
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
|
||||
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1084,
|
||||
"Entered %s.\n", __func__);
|
||||
|
||||
mcp->mb[0] = MBC_GET_LINK_STATUS;
|
||||
mcp->mb[2] = MSW(stats_dma);
|
||||
mcp->mb[3] = LSW(stats_dma);
|
||||
mcp->mb[2] = MSW(LSD(stats_dma));
|
||||
mcp->mb[3] = LSW(LSD(stats_dma));
|
||||
mcp->mb[6] = MSW(MSD(stats_dma));
|
||||
mcp->mb[7] = LSW(MSD(stats_dma));
|
||||
mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
|
||||
|
@ -2796,12 +2825,9 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
|
|||
"Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
|
||||
rval = QLA_FUNCTION_FAILED;
|
||||
} else {
|
||||
/* Copy over data -- firmware data is LE. */
|
||||
/* Re-endianize - firmware data is le32. */
|
||||
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1086,
|
||||
"Done %s.\n", __func__);
|
||||
dwords = offsetof(struct link_statistics,
|
||||
link_up_cnt) / 4;
|
||||
iter = &stats->link_fail_cnt;
|
||||
for ( ; dwords--; iter++)
|
||||
le32_to_cpus(iter);
|
||||
}
|
||||
|
@ -2815,7 +2841,7 @@ qla2x00_get_link_status(scsi_qla_host_t *vha, uint16_t loop_id,
|
|||
|
||||
int
|
||||
qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
|
||||
dma_addr_t stats_dma)
|
||||
dma_addr_t stats_dma, uint options)
|
||||
{
|
||||
int rval;
|
||||
mbx_cmd_t mc;
|
||||
|
@ -2832,7 +2858,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
|
|||
mcp->mb[7] = LSW(MSD(stats_dma));
|
||||
mcp->mb[8] = sizeof(struct link_statistics) / 4;
|
||||
mcp->mb[9] = vha->vp_idx;
|
||||
mcp->mb[10] = 0;
|
||||
mcp->mb[10] = options;
|
||||
mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
|
||||
mcp->in_mb = MBX_2|MBX_1|MBX_0;
|
||||
mcp->tov = MBX_TOV_SECONDS;
|
||||
|
@ -2847,7 +2873,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats,
|
|||
} else {
|
||||
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x108a,
|
||||
"Done %s.\n", __func__);
|
||||
/* Copy over data -- firmware data is LE. */
|
||||
/* Re-endianize - firmware data is le32. */
|
||||
dwords = sizeof(struct link_statistics) / 4;
|
||||
iter = &stats->link_fail_cnt;
|
||||
for ( ; dwords--; iter++)
|
||||
|
@ -5722,3 +5748,54 @@ qla2x00_dump_mctp_data(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr,
|
|||
|
||||
return rval;
|
||||
}
|
||||
|
||||
int
|
||||
qla26xx_dport_diagnostics(scsi_qla_host_t *vha,
|
||||
void *dd_buf, uint size, uint options)
|
||||
{
|
||||
int rval;
|
||||
mbx_cmd_t mc;
|
||||
mbx_cmd_t *mcp = &mc;
|
||||
dma_addr_t dd_dma;
|
||||
|
||||
if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw))
|
||||
return QLA_FUNCTION_FAILED;
|
||||
|
||||
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1192,
|
||||
"Entered %s.\n", __func__);
|
||||
|
||||
dd_dma = dma_map_single(&vha->hw->pdev->dev,
|
||||
dd_buf, size, DMA_FROM_DEVICE);
|
||||
if (!dd_dma) {
|
||||
ql_log(ql_log_warn, vha, 0x1194, "Failed to map dma buffer.\n");
|
||||
return QLA_MEMORY_ALLOC_FAILED;
|
||||
}
|
||||
|
||||
memset(dd_buf, 0, size);
|
||||
|
||||
mcp->mb[0] = MBC_DPORT_DIAGNOSTICS;
|
||||
mcp->mb[1] = options;
|
||||
mcp->mb[2] = MSW(LSD(dd_dma));
|
||||
mcp->mb[3] = LSW(LSD(dd_dma));
|
||||
mcp->mb[6] = MSW(MSD(dd_dma));
|
||||
mcp->mb[7] = LSW(MSD(dd_dma));
|
||||
mcp->mb[8] = size;
|
||||
mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
|
||||
mcp->in_mb = MBX_3|MBX_2|MBX_1|MBX_0;
|
||||
mcp->buf_size = size;
|
||||
mcp->flags = MBX_DMA_IN;
|
||||
mcp->tov = MBX_TOV_SECONDS * 4;
|
||||
rval = qla2x00_mailbox_command(vha, mcp);
|
||||
|
||||
if (rval != QLA_SUCCESS) {
|
||||
ql_dbg(ql_dbg_mbx, vha, 0x1195, "Failed=%x.\n", rval);
|
||||
} else {
|
||||
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1196,
|
||||
"Done %s.\n", __func__);
|
||||
}
|
||||
|
||||
dma_unmap_single(&vha->hw->pdev->dev, dd_dma,
|
||||
size, DMA_FROM_DEVICE);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@ MODULE_PARM_DESC(ql2xallocfwdump,
|
|||
|
||||
int ql2xextended_error_logging;
|
||||
module_param(ql2xextended_error_logging, int, S_IRUGO|S_IWUSR);
|
||||
module_param_named(logging, ql2xextended_error_logging, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(ql2xextended_error_logging,
|
||||
"Option to enable extended error logging,\n"
|
||||
"\t\tDefault is 0 - no logging. 0x40000000 - Module Init & Probe.\n"
|
||||
|
@ -106,6 +107,7 @@ MODULE_PARM_DESC(ql2xshiftctondsd,
|
|||
|
||||
int ql2xfdmienable=1;
|
||||
module_param(ql2xfdmienable, int, S_IRUGO|S_IWUSR);
|
||||
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.");
|
||||
|
@ -157,6 +159,7 @@ MODULE_PARM_DESC(ql2xmultique_tag,
|
|||
|
||||
int ql2xfwloadbin;
|
||||
module_param(ql2xfwloadbin, int, S_IRUGO|S_IWUSR);
|
||||
module_param_named(fwload, ql2xfwloadbin, int, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(ql2xfwloadbin,
|
||||
"Option to specify location from which to load ISP firmware:.\n"
|
||||
" 2 -- load firmware via the request_firmware() (hotplug).\n"
|
||||
|
@ -894,12 +897,16 @@ static void
|
|||
qla2x00_wait_for_hba_ready(scsi_qla_host_t *vha)
|
||||
{
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
|
||||
|
||||
while (((qla2x00_reset_active(vha)) || ha->dpc_active ||
|
||||
ha->flags.mbox_busy) ||
|
||||
test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags) ||
|
||||
test_bit(FX00_TARGET_SCAN, &vha->dpc_flags))
|
||||
test_bit(FX00_TARGET_SCAN, &vha->dpc_flags)) {
|
||||
if (test_bit(UNLOADING, &base_vha->dpc_flags))
|
||||
break;
|
||||
msleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -936,6 +943,30 @@ sp_get(struct srb *sp)
|
|||
atomic_inc(&sp->ref_count);
|
||||
}
|
||||
|
||||
#define ISP_REG_DISCONNECT 0xffffffffU
|
||||
/**************************************************************************
|
||||
* qla2x00_isp_reg_stat
|
||||
*
|
||||
* Description:
|
||||
* Read the host status register of ISP before aborting the command.
|
||||
*
|
||||
* Input:
|
||||
* ha = pointer to host adapter structure.
|
||||
*
|
||||
*
|
||||
* Returns:
|
||||
* Either true or false.
|
||||
*
|
||||
* Note: Return true if there is register disconnect.
|
||||
**************************************************************************/
|
||||
static inline
|
||||
uint32_t qla2x00_isp_reg_stat(struct qla_hw_data *ha)
|
||||
{
|
||||
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
|
||||
|
||||
return ((RD_REG_DWORD(®->host_status)) == ISP_REG_DISCONNECT);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* qla2xxx_eh_abort
|
||||
*
|
||||
|
@ -963,6 +994,11 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
|||
int rval, wait = 0;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
|
||||
if (qla2x00_isp_reg_stat(ha)) {
|
||||
ql_log(ql_log_info, vha, 0x8042,
|
||||
"PCI/Register disconnect, exiting.\n");
|
||||
return FAILED;
|
||||
}
|
||||
if (!CMD_SP(cmd))
|
||||
return SUCCESS;
|
||||
|
||||
|
@ -1146,6 +1182,12 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
|
|||
scsi_qla_host_t *vha = shost_priv(cmd->device->host);
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
|
||||
if (qla2x00_isp_reg_stat(ha)) {
|
||||
ql_log(ql_log_info, vha, 0x803e,
|
||||
"PCI/Register disconnect, exiting.\n");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
return __qla2xxx_eh_generic_reset("DEVICE", WAIT_LUN, cmd,
|
||||
ha->isp_ops->lun_reset);
|
||||
}
|
||||
|
@ -1156,6 +1198,12 @@ qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
|
|||
scsi_qla_host_t *vha = shost_priv(cmd->device->host);
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
|
||||
if (qla2x00_isp_reg_stat(ha)) {
|
||||
ql_log(ql_log_info, vha, 0x803f,
|
||||
"PCI/Register disconnect, exiting.\n");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
return __qla2xxx_eh_generic_reset("TARGET", WAIT_TARGET, cmd,
|
||||
ha->isp_ops->target_reset);
|
||||
}
|
||||
|
@ -1183,6 +1231,13 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
|
|||
int ret = FAILED;
|
||||
unsigned int id;
|
||||
uint64_t lun;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
|
||||
if (qla2x00_isp_reg_stat(ha)) {
|
||||
ql_log(ql_log_info, vha, 0x8040,
|
||||
"PCI/Register disconnect, exiting.\n");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
id = cmd->device->id;
|
||||
lun = cmd->device->lun;
|
||||
|
@ -1252,6 +1307,13 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
|
|||
uint64_t lun;
|
||||
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
|
||||
|
||||
if (qla2x00_isp_reg_stat(ha)) {
|
||||
ql_log(ql_log_info, vha, 0x8041,
|
||||
"PCI/Register disconnect, exiting.\n");
|
||||
schedule_work(&ha->board_disable);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
id = cmd->device->id;
|
||||
lun = cmd->device->lun;
|
||||
|
||||
|
@ -2103,27 +2165,27 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
|
|||
ha->device_type = DT_EXTENDED_IDS;
|
||||
switch (ha->pdev->device) {
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP2100:
|
||||
ha->device_type |= DT_ISP2100;
|
||||
ha->isp_type |= DT_ISP2100;
|
||||
ha->device_type &= ~DT_EXTENDED_IDS;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2100;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP2200:
|
||||
ha->device_type |= DT_ISP2200;
|
||||
ha->isp_type |= DT_ISP2200;
|
||||
ha->device_type &= ~DT_EXTENDED_IDS;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2100;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP2300:
|
||||
ha->device_type |= DT_ISP2300;
|
||||
ha->isp_type |= DT_ISP2300;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2300;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP2312:
|
||||
ha->device_type |= DT_ISP2312;
|
||||
ha->isp_type |= DT_ISP2312;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2300;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP2322:
|
||||
ha->device_type |= DT_ISP2322;
|
||||
ha->isp_type |= DT_ISP2322;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
if (ha->pdev->subsystem_vendor == 0x1028 &&
|
||||
ha->pdev->subsystem_device == 0x0170)
|
||||
|
@ -2131,60 +2193,60 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
|
|||
ha->fw_srisc_address = RISC_START_ADDRESS_2300;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP6312:
|
||||
ha->device_type |= DT_ISP6312;
|
||||
ha->isp_type |= DT_ISP6312;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2300;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP6322:
|
||||
ha->device_type |= DT_ISP6322;
|
||||
ha->isp_type |= DT_ISP6322;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2300;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP2422:
|
||||
ha->device_type |= DT_ISP2422;
|
||||
ha->isp_type |= DT_ISP2422;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
ha->device_type |= DT_FWI2;
|
||||
ha->device_type |= DT_IIDMA;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP2432:
|
||||
ha->device_type |= DT_ISP2432;
|
||||
ha->isp_type |= DT_ISP2432;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
ha->device_type |= DT_FWI2;
|
||||
ha->device_type |= DT_IIDMA;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP8432:
|
||||
ha->device_type |= DT_ISP8432;
|
||||
ha->isp_type |= DT_ISP8432;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
ha->device_type |= DT_FWI2;
|
||||
ha->device_type |= DT_IIDMA;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP5422:
|
||||
ha->device_type |= DT_ISP5422;
|
||||
ha->isp_type |= DT_ISP5422;
|
||||
ha->device_type |= DT_FWI2;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP5432:
|
||||
ha->device_type |= DT_ISP5432;
|
||||
ha->isp_type |= DT_ISP5432;
|
||||
ha->device_type |= DT_FWI2;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP2532:
|
||||
ha->device_type |= DT_ISP2532;
|
||||
ha->isp_type |= DT_ISP2532;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
ha->device_type |= DT_FWI2;
|
||||
ha->device_type |= DT_IIDMA;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP8001:
|
||||
ha->device_type |= DT_ISP8001;
|
||||
ha->isp_type |= DT_ISP8001;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
ha->device_type |= DT_FWI2;
|
||||
ha->device_type |= DT_IIDMA;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP8021:
|
||||
ha->device_type |= DT_ISP8021;
|
||||
ha->isp_type |= DT_ISP8021;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
ha->device_type |= DT_FWI2;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
|
||||
|
@ -2192,7 +2254,7 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
|
|||
qla82xx_init_flags(ha);
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP8044:
|
||||
ha->device_type |= DT_ISP8044;
|
||||
ha->isp_type |= DT_ISP8044;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
ha->device_type |= DT_FWI2;
|
||||
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
|
||||
|
@ -2200,7 +2262,7 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
|
|||
qla82xx_init_flags(ha);
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP2031:
|
||||
ha->device_type |= DT_ISP2031;
|
||||
ha->isp_type |= DT_ISP2031;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
ha->device_type |= DT_FWI2;
|
||||
ha->device_type |= DT_IIDMA;
|
||||
|
@ -2208,7 +2270,7 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
|
|||
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP8031:
|
||||
ha->device_type |= DT_ISP8031;
|
||||
ha->isp_type |= DT_ISP8031;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
ha->device_type |= DT_FWI2;
|
||||
ha->device_type |= DT_IIDMA;
|
||||
|
@ -2216,10 +2278,10 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
|
|||
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISPF001:
|
||||
ha->device_type |= DT_ISPFX00;
|
||||
ha->isp_type |= DT_ISPFX00;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP2071:
|
||||
ha->device_type |= DT_ISP2071;
|
||||
ha->isp_type |= DT_ISP2071;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
ha->device_type |= DT_FWI2;
|
||||
ha->device_type |= DT_IIDMA;
|
||||
|
@ -2227,7 +2289,7 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
|
|||
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP2271:
|
||||
ha->device_type |= DT_ISP2271;
|
||||
ha->isp_type |= DT_ISP2271;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
ha->device_type |= DT_FWI2;
|
||||
ha->device_type |= DT_IIDMA;
|
||||
|
@ -2235,7 +2297,7 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
|
|||
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
|
||||
break;
|
||||
case PCI_DEVICE_ID_QLOGIC_ISP2261:
|
||||
ha->device_type |= DT_ISP2261;
|
||||
ha->isp_type |= DT_ISP2261;
|
||||
ha->device_type |= DT_ZIO_SUPPORTED;
|
||||
ha->device_type |= DT_FWI2;
|
||||
ha->device_type |= DT_IIDMA;
|
||||
|
@ -2901,6 +2963,10 @@ skip_dpc:
|
|||
qlt_add_target(ha, base_vha);
|
||||
|
||||
clear_bit(PFLG_DRIVER_PROBING, &base_vha->pci_flags);
|
||||
|
||||
if (test_bit(UNLOADING, &base_vha->dpc_flags))
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
|
||||
probe_init_failed:
|
||||
|
@ -3128,6 +3194,12 @@ qla2x00_remove_one(struct pci_dev *pdev)
|
|||
|
||||
qla2x00_wait_for_hba_ready(base_vha);
|
||||
|
||||
/* if UNLOAD flag is already set, then continue unload,
|
||||
* where it was set first.
|
||||
*/
|
||||
if (test_bit(UNLOADING, &base_vha->dpc_flags))
|
||||
return;
|
||||
|
||||
set_bit(UNLOADING, &base_vha->dpc_flags);
|
||||
|
||||
if (IS_QLAFX00(ha))
|
||||
|
@ -4907,6 +4979,12 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
|
|||
struct pci_dev *pdev = ha->pdev;
|
||||
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
|
||||
|
||||
/* if UNLOAD flag is already set, then continue unload,
|
||||
* where it was set first.
|
||||
*/
|
||||
if (test_bit(UNLOADING, &base_vha->dpc_flags))
|
||||
return;
|
||||
|
||||
ql_log(ql_log_warn, base_vha, 0x015b,
|
||||
"Disabling adapter.\n");
|
||||
|
||||
|
@ -5002,6 +5080,9 @@ qla2x00_do_dpc(void *data)
|
|||
"DPC handler waking up, dpc_flags=0x%lx.\n",
|
||||
base_vha->dpc_flags);
|
||||
|
||||
if (test_bit(UNLOADING, &base_vha->dpc_flags))
|
||||
break;
|
||||
|
||||
qla2x00_do_work(base_vha);
|
||||
|
||||
if (IS_P3P_TYPE(ha)) {
|
||||
|
|
|
@ -215,8 +215,8 @@ static inline void qlt_incr_num_pend_cmds(struct scsi_qla_host *vha)
|
|||
spin_lock_irqsave(&vha->hw->tgt.q_full_lock, flags);
|
||||
|
||||
vha->hw->tgt.num_pend_cmds++;
|
||||
if (vha->hw->tgt.num_pend_cmds > vha->hw->qla_stats.stat_max_pend_cmds)
|
||||
vha->hw->qla_stats.stat_max_pend_cmds =
|
||||
if (vha->hw->tgt.num_pend_cmds > vha->qla_stats.stat_max_pend_cmds)
|
||||
vha->qla_stats.stat_max_pend_cmds =
|
||||
vha->hw->tgt.num_pend_cmds;
|
||||
spin_unlock_irqrestore(&vha->hw->tgt.q_full_lock, flags);
|
||||
}
|
||||
|
@ -5231,8 +5231,8 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
|
|||
if ((vha->hw->tgt.num_qfull_cmds_alloc + 1) > MAX_QFULL_CMDS_ALLOC) {
|
||||
vha->hw->tgt.num_qfull_cmds_dropped++;
|
||||
if (vha->hw->tgt.num_qfull_cmds_dropped >
|
||||
vha->hw->qla_stats.stat_max_qfull_cmds_dropped)
|
||||
vha->hw->qla_stats.stat_max_qfull_cmds_dropped =
|
||||
vha->qla_stats.stat_max_qfull_cmds_dropped)
|
||||
vha->qla_stats.stat_max_qfull_cmds_dropped =
|
||||
vha->hw->tgt.num_qfull_cmds_dropped;
|
||||
|
||||
ql_dbg(ql_dbg_io, vha, 0x3068,
|
||||
|
@ -5263,8 +5263,8 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
|
|||
|
||||
vha->hw->tgt.num_qfull_cmds_dropped++;
|
||||
if (vha->hw->tgt.num_qfull_cmds_dropped >
|
||||
vha->hw->qla_stats.stat_max_qfull_cmds_dropped)
|
||||
vha->hw->qla_stats.stat_max_qfull_cmds_dropped =
|
||||
vha->qla_stats.stat_max_qfull_cmds_dropped)
|
||||
vha->qla_stats.stat_max_qfull_cmds_dropped =
|
||||
vha->hw->tgt.num_qfull_cmds_dropped;
|
||||
|
||||
qlt_chk_exch_leak_thresh_hold(vha);
|
||||
|
@ -5293,8 +5293,8 @@ qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
|
|||
|
||||
vha->hw->tgt.num_qfull_cmds_alloc++;
|
||||
if (vha->hw->tgt.num_qfull_cmds_alloc >
|
||||
vha->hw->qla_stats.stat_max_qfull_cmds_alloc)
|
||||
vha->hw->qla_stats.stat_max_qfull_cmds_alloc =
|
||||
vha->qla_stats.stat_max_qfull_cmds_alloc)
|
||||
vha->qla_stats.stat_max_qfull_cmds_alloc =
|
||||
vha->hw->tgt.num_qfull_cmds_alloc;
|
||||
}
|
||||
|
||||
|
|
|
@ -357,6 +357,13 @@ qla27xx_fwdt_entry_t262(struct scsi_qla_host *vha,
|
|||
ent->t262.start_addr = start;
|
||||
ent->t262.end_addr = end;
|
||||
}
|
||||
} else if (ent->t262.ram_area == T262_RAM_AREA_DDR_RAM) {
|
||||
start = vha->hw->fw_ddr_ram_start;
|
||||
end = vha->hw->fw_ddr_ram_end;
|
||||
if (buf) {
|
||||
ent->t262.start_addr = start;
|
||||
ent->t262.end_addr = end;
|
||||
}
|
||||
} else {
|
||||
ql_dbg(ql_dbg_misc, vha, 0xd022,
|
||||
"%s: unknown area %x\n", __func__, ent->t262.ram_area);
|
||||
|
@ -364,7 +371,7 @@ qla27xx_fwdt_entry_t262(struct scsi_qla_host *vha,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (end < start || end == 0) {
|
||||
if (end <= start || start == 0 || end == 0) {
|
||||
ql_dbg(ql_dbg_misc, vha, 0xd023,
|
||||
"%s: unusable range (start=%x end=%x)\n", __func__,
|
||||
ent->t262.end_addr, ent->t262.start_addr);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
/*
|
||||
* Driver version
|
||||
*/
|
||||
#define QLA2XXX_VERSION "8.07.00.33-k"
|
||||
#define QLA2XXX_VERSION "8.07.00.38-k"
|
||||
|
||||
#define QLA_DRIVER_MAJOR_VER 8
|
||||
#define QLA_DRIVER_MINOR_VER 7
|
||||
|
|
|
@ -1160,6 +1160,7 @@ bool scsi_use_blk_mq = true;
|
|||
bool scsi_use_blk_mq = false;
|
||||
#endif
|
||||
module_param_named(use_blk_mq, scsi_use_blk_mq, bool, S_IWUSR | S_IRUGO);
|
||||
EXPORT_SYMBOL_GPL(scsi_use_blk_mq);
|
||||
|
||||
static int __init init_scsi(void)
|
||||
{
|
||||
|
|
|
@ -890,7 +890,7 @@ static int make_ua(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */
|
||||
/* Build SCSI "data-in" buffer. Returns 0 if ok else (DID_ERROR << 16). */
|
||||
static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
|
||||
int arr_len)
|
||||
{
|
||||
|
@ -909,7 +909,35 @@ static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Returns number of bytes fetched into 'arr' or -1 if error. */
|
||||
/* Partial build of SCSI "data-in" buffer. Returns 0 if ok else
|
||||
* (DID_ERROR << 16). Can write to offset in data-in buffer. If multiple
|
||||
* calls, not required to write in ascending offset order. Assumes resid
|
||||
* set to scsi_bufflen() prior to any calls.
|
||||
*/
|
||||
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;
|
||||
struct scsi_data_buffer *sdb = scsi_in(scp);
|
||||
off_t skip = off_dst;
|
||||
|
||||
if (sdb->length <= off_dst)
|
||||
return 0;
|
||||
if (!(scsi_bidi_cmnd(scp) || scp->sc_data_direction == DMA_FROM_DEVICE))
|
||||
return DID_ERROR << 16;
|
||||
|
||||
act_len = sg_pcopy_from_buffer(sdb->table.sgl, sdb->table.nents,
|
||||
arr, arr_len, skip);
|
||||
pr_debug("%s: off_dst=%u, scsi_bufflen=%u, act_len=%u, resid=%d\n",
|
||||
__func__, off_dst, scsi_bufflen(scp), act_len, sdb->resid);
|
||||
n = (int)scsi_bufflen(scp) - ((int)off_dst + act_len);
|
||||
sdb->resid = min(sdb->resid, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fetches from SCSI "data-out" buffer. Returns number of bytes fetched into
|
||||
* 'arr' or -1 if error.
|
||||
*/
|
||||
static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr,
|
||||
int arr_len)
|
||||
{
|
||||
|
@ -3269,6 +3297,8 @@ static int resp_get_lba_status(struct scsi_cmnd *scp,
|
|||
return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
|
||||
}
|
||||
|
||||
#define RL_BUCKET_ELEMS 8
|
||||
|
||||
/* Even though each pseudo target has a REPORT LUNS "well known logical unit"
|
||||
* (W-LUN), the normal Linux scanning logic does not associate it with a
|
||||
* device (e.g. /dev/sg7). The following magic will make that association:
|
||||
|
@ -3285,12 +3315,14 @@ static int resp_report_luns(struct scsi_cmnd *scp,
|
|||
unsigned char select_report;
|
||||
u64 lun;
|
||||
struct scsi_lun *lun_p;
|
||||
u8 *arr;
|
||||
u8 arr[RL_BUCKET_ELEMS * sizeof(struct scsi_lun)];
|
||||
unsigned int lun_cnt; /* normal LUN count (max: 256) */
|
||||
unsigned int wlun_cnt; /* report luns W-LUN count */
|
||||
unsigned int tlun_cnt; /* total LUN count */
|
||||
unsigned int rlen; /* response length (in bytes) */
|
||||
int i, res;
|
||||
int k, j, n, res;
|
||||
unsigned int off_rsp = 0;
|
||||
const int sz_lun = sizeof(struct scsi_lun);
|
||||
|
||||
clear_luns_changed_on_target(devip);
|
||||
|
||||
|
@ -3329,33 +3361,40 @@ static int resp_report_luns(struct scsi_cmnd *scp,
|
|||
--lun_cnt;
|
||||
|
||||
tlun_cnt = lun_cnt + wlun_cnt;
|
||||
|
||||
rlen = (tlun_cnt * sizeof(struct scsi_lun)) + 8;
|
||||
arr = vmalloc(rlen);
|
||||
if (!arr) {
|
||||
mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
|
||||
INSUFF_RES_ASCQ);
|
||||
return check_condition_result;
|
||||
}
|
||||
memset(arr, 0, rlen);
|
||||
rlen = tlun_cnt * sz_lun; /* excluding 8 byte header */
|
||||
scsi_set_resid(scp, scsi_bufflen(scp));
|
||||
pr_debug("select_report %d luns = %d wluns = %d no_lun0 %d\n",
|
||||
select_report, lun_cnt, wlun_cnt, sdebug_no_lun_0);
|
||||
|
||||
/* luns start at byte 8 in response following the header */
|
||||
lun_p = (struct scsi_lun *)&arr[8];
|
||||
|
||||
/* LUNs use single level peripheral device addressing method */
|
||||
/* loops rely on sizeof response header same as sizeof lun (both 8) */
|
||||
lun = sdebug_no_lun_0 ? 1 : 0;
|
||||
for (i = 0; i < lun_cnt; i++)
|
||||
int_to_scsilun(lun++, lun_p++);
|
||||
|
||||
if (wlun_cnt)
|
||||
int_to_scsilun(SCSI_W_LUN_REPORT_LUNS, lun_p++);
|
||||
|
||||
put_unaligned_be32(rlen - 8, &arr[0]);
|
||||
|
||||
res = fill_from_dev_buffer(scp, arr, rlen);
|
||||
vfree(arr);
|
||||
for (k = 0, j = 0, res = 0; true; ++k, j = 0) {
|
||||
memset(arr, 0, sizeof(arr));
|
||||
lun_p = (struct scsi_lun *)&arr[0];
|
||||
if (k == 0) {
|
||||
put_unaligned_be32(rlen, &arr[0]);
|
||||
++lun_p;
|
||||
j = 1;
|
||||
}
|
||||
for ( ; j < RL_BUCKET_ELEMS; ++j, ++lun_p) {
|
||||
if ((k * RL_BUCKET_ELEMS) + j > lun_cnt)
|
||||
break;
|
||||
int_to_scsilun(lun++, lun_p);
|
||||
}
|
||||
if (j < RL_BUCKET_ELEMS)
|
||||
break;
|
||||
n = j * sz_lun;
|
||||
res = p_fill_from_dev_buffer(scp, arr, n, off_rsp);
|
||||
if (res)
|
||||
return res;
|
||||
off_rsp += n;
|
||||
}
|
||||
if (wlun_cnt) {
|
||||
int_to_scsilun(SCSI_W_LUN_REPORT_LUNS, lun_p);
|
||||
++j;
|
||||
}
|
||||
if (j > 0)
|
||||
res = p_fill_from_dev_buffer(scp, arr, j * sz_lun, off_rsp);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -113,11 +113,11 @@ snic_queue_report_tgt_req(struct snic *snic)
|
|||
|
||||
pa = pci_map_single(snic->pdev, buf, buf_len, PCI_DMA_FROMDEVICE);
|
||||
if (pci_dma_mapping_error(snic->pdev, pa)) {
|
||||
kfree(buf);
|
||||
snic_req_free(snic, rqi);
|
||||
SNIC_HOST_ERR(snic->shost,
|
||||
"Rpt-tgt rspbuf %p: PCI DMA Mapping Failed\n",
|
||||
buf);
|
||||
kfree(buf);
|
||||
snic_req_free(snic, rqi);
|
||||
ret = -EINVAL;
|
||||
|
||||
goto error;
|
||||
|
|
|
@ -92,7 +92,7 @@ enum snic_io_status {
|
|||
}; /* end of enum snic_io_status */
|
||||
|
||||
/*
|
||||
* snic_io_hdr : host <--> firmare
|
||||
* snic_io_hdr : host <--> firmware
|
||||
*
|
||||
* for any other message that will be queued to firmware should
|
||||
* have the following request header
|
||||
|
|
|
@ -966,6 +966,8 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request,
|
|||
if (scmnd->result) {
|
||||
if (scsi_normalize_sense(scmnd->sense_buffer,
|
||||
SCSI_SENSE_BUFFERSIZE, &sense_hdr) &&
|
||||
!(sense_hdr.sense_key == NOT_READY &&
|
||||
sense_hdr.asc == 0x03A) &&
|
||||
do_logging(STORVSC_LOGGING_ERROR))
|
||||
scsi_print_sense_hdr(scmnd->device, "storvsc",
|
||||
&sense_hdr);
|
||||
|
|
|
@ -61,6 +61,14 @@ config SCSI_UFSHCD_PCI
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config SCSI_UFS_DWC_TC_PCI
|
||||
tristate "DesignWare pci support using a G210 Test Chip"
|
||||
depends on SCSI_UFSHCD && PCI
|
||||
---help---
|
||||
Synopsys Test Chip is a PHY for prototyping purposes.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SCSI_UFSHCD_PLATFORM
|
||||
tristate "Platform bus based UFS Controller support"
|
||||
depends on SCSI_UFSHCD
|
||||
|
@ -72,6 +80,14 @@ config SCSI_UFSHCD_PLATFORM
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config SCSI_UFS_DWC_TC_PLATFORM
|
||||
tristate "DesignWare platform support using a G210 Test Chip"
|
||||
depends on SCSI_UFSHCD_PLATFORM
|
||||
---help---
|
||||
Synopsys Test Chip is a PHY for prototyping purposes.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SCSI_UFS_QCOM
|
||||
tristate "QCOM specific hooks to UFS controller platform driver"
|
||||
depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
# UFSHCD makefile
|
||||
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_QCOM) += ufs-qcom.o
|
||||
obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
|
||||
obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Synopsys G210 Test Chip driver
|
||||
*
|
||||
* Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
|
||||
*
|
||||
* Authors: Joao Pinto <jpinto@synopsys.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "ufshcd.h"
|
||||
#include "ufshcd-dwc.h"
|
||||
#include "tc-dwc-g210.h"
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
/* Test Chip type expected values */
|
||||
#define TC_G210_20BIT 20
|
||||
#define TC_G210_40BIT 40
|
||||
#define TC_G210_INV 0
|
||||
|
||||
static int tc_type = TC_G210_INV;
|
||||
module_param(tc_type, int, 0);
|
||||
MODULE_PARM_DESC(tc_type, "Test Chip Type (20 = 20-bit, 40 = 40-bit)");
|
||||
|
||||
static int tc_dwc_g210_pci_suspend(struct device *dev)
|
||||
{
|
||||
return ufshcd_system_suspend(dev_get_drvdata(dev));
|
||||
}
|
||||
|
||||
static int tc_dwc_g210_pci_resume(struct device *dev)
|
||||
{
|
||||
return ufshcd_system_resume(dev_get_drvdata(dev));
|
||||
}
|
||||
|
||||
static int tc_dwc_g210_pci_runtime_suspend(struct device *dev)
|
||||
{
|
||||
return ufshcd_runtime_suspend(dev_get_drvdata(dev));
|
||||
}
|
||||
|
||||
static int tc_dwc_g210_pci_runtime_resume(struct device *dev)
|
||||
{
|
||||
return ufshcd_runtime_resume(dev_get_drvdata(dev));
|
||||
}
|
||||
|
||||
static int tc_dwc_g210_pci_runtime_idle(struct device *dev)
|
||||
{
|
||||
return ufshcd_runtime_idle(dev_get_drvdata(dev));
|
||||
}
|
||||
|
||||
/**
|
||||
* struct ufs_hba_dwc_vops - UFS DWC specific variant operations
|
||||
*/
|
||||
static struct ufs_hba_variant_ops tc_dwc_g210_pci_hba_vops = {
|
||||
.name = "tc-dwc-g210-pci",
|
||||
.link_startup_notify = ufshcd_dwc_link_startup_notify,
|
||||
};
|
||||
|
||||
/**
|
||||
* tc_dwc_g210_pci_shutdown - main function to put the controller in reset state
|
||||
* @pdev: pointer to PCI device handle
|
||||
*/
|
||||
static void tc_dwc_g210_pci_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
ufshcd_shutdown((struct ufs_hba *)pci_get_drvdata(pdev));
|
||||
}
|
||||
|
||||
/**
|
||||
* tc_dwc_g210_pci_remove - de-allocate PCI/SCSI host and host memory space
|
||||
* data structure memory
|
||||
* @pdev - pointer to PCI handle
|
||||
*/
|
||||
static void tc_dwc_g210_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct ufs_hba *hba = pci_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_forbid(&pdev->dev);
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
ufshcd_remove(hba);
|
||||
}
|
||||
|
||||
/**
|
||||
* tc_dwc_g210_pci_probe - probe routine of the driver
|
||||
* @pdev: pointer to PCI device handle
|
||||
* @id: PCI device id
|
||||
*
|
||||
* Returns 0 on success, non-zero value on failure
|
||||
*/
|
||||
static int
|
||||
tc_dwc_g210_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
struct ufs_hba *hba;
|
||||
void __iomem *mmio_base;
|
||||
int err;
|
||||
|
||||
/* Check Test Chip type and set the specific setup routine */
|
||||
if (tc_type == TC_G210_20BIT) {
|
||||
tc_dwc_g210_pci_hba_vops.phy_initialization =
|
||||
tc_dwc_g210_config_20_bit;
|
||||
} else if (tc_type == TC_G210_40BIT) {
|
||||
tc_dwc_g210_pci_hba_vops.phy_initialization =
|
||||
tc_dwc_g210_config_40_bit;
|
||||
} else {
|
||||
dev_err(&pdev->dev, "test chip version not specified\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
err = pcim_enable_device(pdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "pcim_enable_device failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
err = pcim_iomap_regions(pdev, 1 << 0, UFSHCD);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "request and iomap failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
mmio_base = pcim_iomap_table(pdev)[0];
|
||||
|
||||
err = ufshcd_alloc_host(&pdev->dev, &hba);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Allocation failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&hba->clk_list_head);
|
||||
|
||||
hba->vops = &tc_dwc_g210_pci_hba_vops;
|
||||
|
||||
err = ufshcd_init(hba, mmio_base, pdev->irq);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Initialization failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
pci_set_drvdata(pdev, hba);
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_allow(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops tc_dwc_g210_pci_pm_ops = {
|
||||
.suspend = tc_dwc_g210_pci_suspend,
|
||||
.resume = tc_dwc_g210_pci_resume,
|
||||
.runtime_suspend = tc_dwc_g210_pci_runtime_suspend,
|
||||
.runtime_resume = tc_dwc_g210_pci_runtime_resume,
|
||||
.runtime_idle = tc_dwc_g210_pci_runtime_idle,
|
||||
};
|
||||
|
||||
static const struct pci_device_id tc_dwc_g210_pci_tbl[] = {
|
||||
{ PCI_VENDOR_ID_SYNOPSYS, 0xB101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
|
||||
{ PCI_VENDOR_ID_SYNOPSYS, 0xB102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
|
||||
{ } /* terminate list */
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, tc_dwc_g210_pci_tbl);
|
||||
|
||||
static struct pci_driver tc_dwc_g210_pci_driver = {
|
||||
.name = "tc-dwc-g210-pci",
|
||||
.id_table = tc_dwc_g210_pci_tbl,
|
||||
.probe = tc_dwc_g210_pci_probe,
|
||||
.remove = tc_dwc_g210_pci_remove,
|
||||
.shutdown = tc_dwc_g210_pci_shutdown,
|
||||
.driver = {
|
||||
.pm = &tc_dwc_g210_pci_pm_ops
|
||||
},
|
||||
};
|
||||
|
||||
module_pci_driver(tc_dwc_g210_pci_driver);
|
||||
|
||||
MODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>");
|
||||
MODULE_DESCRIPTION("Synopsys Test Chip G210 PCI glue driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Synopsys G210 Test Chip driver
|
||||
*
|
||||
* Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
|
||||
*
|
||||
* Authors: Joao Pinto <jpinto@synopsys.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "ufshcd-pltfrm.h"
|
||||
#include "ufshcd-dwc.h"
|
||||
#include "tc-dwc-g210.h"
|
||||
|
||||
/**
|
||||
* UFS DWC specific variant operations
|
||||
*/
|
||||
static struct ufs_hba_variant_ops tc_dwc_g210_20bit_pltfm_hba_vops = {
|
||||
.name = "tc-dwc-g210-pltfm",
|
||||
.link_startup_notify = ufshcd_dwc_link_startup_notify,
|
||||
.phy_initialization = tc_dwc_g210_config_20_bit,
|
||||
};
|
||||
|
||||
static struct ufs_hba_variant_ops tc_dwc_g210_40bit_pltfm_hba_vops = {
|
||||
.name = "tc-dwc-g210-pltfm",
|
||||
.link_startup_notify = ufshcd_dwc_link_startup_notify,
|
||||
.phy_initialization = tc_dwc_g210_config_40_bit,
|
||||
};
|
||||
|
||||
static const struct of_device_id tc_dwc_g210_pltfm_match[] = {
|
||||
{
|
||||
.compatible = "snps,g210-tc-6.00-20bit",
|
||||
.data = &tc_dwc_g210_20bit_pltfm_hba_vops,
|
||||
},
|
||||
{
|
||||
.compatible = "snps,g210-tc-6.00-40bit",
|
||||
.data = &tc_dwc_g210_40bit_pltfm_hba_vops,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tc_dwc_g210_pltfm_match);
|
||||
|
||||
/**
|
||||
* tc_dwc_g210_pltfm_probe()
|
||||
* @pdev: pointer to platform device structure
|
||||
*
|
||||
*/
|
||||
static int tc_dwc_g210_pltfm_probe(struct platform_device *pdev)
|
||||
{
|
||||
int err;
|
||||
const struct of_device_id *of_id;
|
||||
struct ufs_hba_variant_ops *vops;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
of_id = of_match_node(tc_dwc_g210_pltfm_match, dev->of_node);
|
||||
vops = (struct ufs_hba_variant_ops *)of_id->data;
|
||||
|
||||
/* Perform generic probe */
|
||||
err = ufshcd_pltfrm_init(pdev, vops);
|
||||
if (err)
|
||||
dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* tc_dwc_g210_pltfm_remove()
|
||||
* @pdev: pointer to platform device structure
|
||||
*
|
||||
*/
|
||||
static int tc_dwc_g210_pltfm_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ufs_hba *hba = platform_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_get_sync(&(pdev)->dev);
|
||||
ufshcd_remove(hba);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops tc_dwc_g210_pltfm_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 tc_dwc_g210_pltfm_driver = {
|
||||
.probe = tc_dwc_g210_pltfm_probe,
|
||||
.remove = tc_dwc_g210_pltfm_remove,
|
||||
.shutdown = ufshcd_pltfrm_shutdown,
|
||||
.driver = {
|
||||
.name = "tc-dwc-g210-pltfm",
|
||||
.pm = &tc_dwc_g210_pltfm_pm_ops,
|
||||
.of_match_table = of_match_ptr(tc_dwc_g210_pltfm_match),
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(tc_dwc_g210_pltfm_driver);
|
||||
|
||||
MODULE_ALIAS("platform:tc-dwc-g210-pltfm");
|
||||
MODULE_DESCRIPTION("Synopsys Test Chip G210 platform glue driver");
|
||||
MODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
* Synopsys G210 Test Chip driver
|
||||
*
|
||||
* Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
|
||||
*
|
||||
* Authors: Joao Pinto <jpinto@synopsys.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "ufshcd.h"
|
||||
#include "unipro.h"
|
||||
|
||||
#include "ufshcd-dwc.h"
|
||||
#include "ufshci-dwc.h"
|
||||
|
||||
/**
|
||||
* tc_dwc_g210_setup_40bit_rmmi()
|
||||
* This function configures Synopsys TC specific atributes (40-bit RMMI)
|
||||
* @hba: Pointer to drivers structure
|
||||
*
|
||||
* Returns 0 on success or non-zero value on failure
|
||||
*/
|
||||
static int tc_dwc_g210_setup_40bit_rmmi(struct ufs_hba *hba)
|
||||
{
|
||||
const struct ufshcd_dme_attr_val setup_attrs[] = {
|
||||
{ UIC_ARG_MIB(TX_GLOBALHIBERNATE), 0x00, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(REFCLKMODE), 0x01, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(CDIRECTCTRL6), 0x80, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(CBDIVFACTOR), 0x08, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(CBDCOCTRL5), 0x64, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(CBPRGTUNING), 0x09, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(RTOBSERVESELECT), 0x00, DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(TX_REFCLKFREQ, SELIND_LN0_TX), 0x01,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(TX_CFGCLKFREQVAL, SELIND_LN0_TX), 0x19,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGEXTRATTR, SELIND_LN0_TX), 0x14,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(DITHERCTRL2, SELIND_LN0_TX), 0xd6,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(RX_REFCLKFREQ, SELIND_LN0_RX), 0x01,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(RX_CFGCLKFREQVAL, SELIND_LN0_RX), 0x19,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGWIDEINLN, SELIND_LN0_RX), 4,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGRXCDR8, SELIND_LN0_RX), 0x80,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB(DIRECTCTRL10), 0x04, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(DIRECTCTRL19), 0x02, DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGRXCDR8, SELIND_LN0_RX), 0x80,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG4, SELIND_LN0_RX), 0x03,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGRXOVR8, SELIND_LN0_RX), 0x16,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(RXDIRECTCTRL2, SELIND_LN0_RX), 0x42,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG3, SELIND_LN0_RX), 0xa4,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(RXCALCTRL, SELIND_LN0_RX), 0x01,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG2, SELIND_LN0_RX), 0x01,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGRXOVR4, SELIND_LN0_RX), 0x28,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(RXSQCTRL, SELIND_LN0_RX), 0x1E,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGRXOVR6, SELIND_LN0_RX), 0x2f,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGRXOVR6, SELIND_LN0_RX), 0x2f,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB(CBPRGPLL2), 0x00, DME_LOCAL },
|
||||
};
|
||||
|
||||
return ufshcd_dwc_dme_set_attrs(hba, setup_attrs,
|
||||
ARRAY_SIZE(setup_attrs));
|
||||
}
|
||||
|
||||
/**
|
||||
* tc_dwc_g210_setup_20bit_rmmi_lane0()
|
||||
* This function configures Synopsys TC 20-bit RMMI Lane 0
|
||||
* @hba: Pointer to drivers structure
|
||||
*
|
||||
* Returns 0 on success or non-zero value on failure
|
||||
*/
|
||||
static int tc_dwc_g210_setup_20bit_rmmi_lane0(struct ufs_hba *hba)
|
||||
{
|
||||
const struct ufshcd_dme_attr_val setup_attrs[] = {
|
||||
{ UIC_ARG_MIB_SEL(TX_REFCLKFREQ, SELIND_LN0_TX), 0x01,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(TX_CFGCLKFREQVAL, SELIND_LN0_TX), 0x19,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(RX_CFGCLKFREQVAL, SELIND_LN0_RX), 0x19,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGEXTRATTR, SELIND_LN0_TX), 0x12,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(DITHERCTRL2, SELIND_LN0_TX), 0xd6,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(RX_REFCLKFREQ, SELIND_LN0_RX), 0x01,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGWIDEINLN, SELIND_LN0_RX), 2,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGRXCDR8, SELIND_LN0_RX), 0x80,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB(DIRECTCTRL10), 0x04, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(DIRECTCTRL19), 0x02, DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG4, SELIND_LN0_RX), 0x03,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGRXOVR8, SELIND_LN0_RX), 0x16,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(RXDIRECTCTRL2, SELIND_LN0_RX), 0x42,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG3, SELIND_LN0_RX), 0xa4,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(RXCALCTRL, SELIND_LN0_RX), 0x01,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG2, SELIND_LN0_RX), 0x01,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGRXOVR4, SELIND_LN0_RX), 0x28,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(RXSQCTRL, SELIND_LN0_RX), 0x1E,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGRXOVR6, SELIND_LN0_RX), 0x2f,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB(CBPRGPLL2), 0x00, DME_LOCAL },
|
||||
};
|
||||
|
||||
return ufshcd_dwc_dme_set_attrs(hba, setup_attrs,
|
||||
ARRAY_SIZE(setup_attrs));
|
||||
}
|
||||
|
||||
/**
|
||||
* tc_dwc_g210_setup_20bit_rmmi_lane1()
|
||||
* This function configures Synopsys TC 20-bit RMMI Lane 1
|
||||
* @hba: Pointer to drivers structure
|
||||
*
|
||||
* Returns 0 on success or non-zero value on failure
|
||||
*/
|
||||
static int tc_dwc_g210_setup_20bit_rmmi_lane1(struct ufs_hba *hba)
|
||||
{
|
||||
int connected_rx_lanes = 0;
|
||||
int connected_tx_lanes = 0;
|
||||
int ret = 0;
|
||||
|
||||
const struct ufshcd_dme_attr_val setup_tx_attrs[] = {
|
||||
{ UIC_ARG_MIB_SEL(TX_REFCLKFREQ, SELIND_LN1_TX), 0x0d,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(TX_CFGCLKFREQVAL, SELIND_LN1_TX), 0x19,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGEXTRATTR, SELIND_LN1_TX), 0x12,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(DITHERCTRL2, SELIND_LN0_TX), 0xd6,
|
||||
DME_LOCAL },
|
||||
};
|
||||
|
||||
const struct ufshcd_dme_attr_val setup_rx_attrs[] = {
|
||||
{ UIC_ARG_MIB_SEL(RX_REFCLKFREQ, SELIND_LN1_RX), 0x01,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(RX_CFGCLKFREQVAL, SELIND_LN1_RX), 0x19,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGWIDEINLN, SELIND_LN1_RX), 2,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGRXCDR8, SELIND_LN1_RX), 0x80,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG4, SELIND_LN1_RX), 0x03,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGRXOVR8, SELIND_LN1_RX), 0x16,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(RXDIRECTCTRL2, SELIND_LN1_RX), 0x42,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG3, SELIND_LN1_RX), 0xa4,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(RXCALCTRL, SELIND_LN1_RX), 0x01,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(ENARXDIRECTCFG2, SELIND_LN1_RX), 0x01,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGRXOVR4, SELIND_LN1_RX), 0x28,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(RXSQCTRL, SELIND_LN1_RX), 0x1E,
|
||||
DME_LOCAL },
|
||||
{ UIC_ARG_MIB_SEL(CFGRXOVR6, SELIND_LN1_RX), 0x2f,
|
||||
DME_LOCAL },
|
||||
};
|
||||
|
||||
/* Get the available lane count */
|
||||
ufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILRXDATALANES),
|
||||
&connected_rx_lanes);
|
||||
ufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILTXDATALANES),
|
||||
&connected_tx_lanes);
|
||||
|
||||
if (connected_tx_lanes == 2) {
|
||||
|
||||
ret = ufshcd_dwc_dme_set_attrs(hba, setup_tx_attrs,
|
||||
ARRAY_SIZE(setup_tx_attrs));
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (connected_rx_lanes == 2) {
|
||||
ret = ufshcd_dwc_dme_set_attrs(hba, setup_rx_attrs,
|
||||
ARRAY_SIZE(setup_rx_attrs));
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* tc_dwc_g210_setup_20bit_rmmi()
|
||||
* This function configures Synopsys TC specific atributes (20-bit RMMI)
|
||||
* @hba: Pointer to drivers structure
|
||||
*
|
||||
* Returns 0 on success or non-zero value on failure
|
||||
*/
|
||||
static int tc_dwc_g210_setup_20bit_rmmi(struct ufs_hba *hba)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
const struct ufshcd_dme_attr_val setup_attrs[] = {
|
||||
{ UIC_ARG_MIB(TX_GLOBALHIBERNATE), 0x00, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(REFCLKMODE), 0x01, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(CDIRECTCTRL6), 0xc0, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(CBDIVFACTOR), 0x44, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(CBDCOCTRL5), 0x64, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(CBPRGTUNING), 0x09, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(RTOBSERVESELECT), 0x00, DME_LOCAL },
|
||||
};
|
||||
|
||||
ret = ufshcd_dwc_dme_set_attrs(hba, setup_attrs,
|
||||
ARRAY_SIZE(setup_attrs));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* Lane 0 configuration*/
|
||||
ret = tc_dwc_g210_setup_20bit_rmmi_lane0(hba);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* Lane 1 configuration*/
|
||||
ret = tc_dwc_g210_setup_20bit_rmmi_lane1(hba);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* tc_dwc_g210_config_40_bit()
|
||||
* This function configures Local (host) Synopsys 40-bit TC specific attributes
|
||||
*
|
||||
* @hba: Pointer to drivers structure
|
||||
*
|
||||
* Returns 0 on success non-zero value on failure
|
||||
*/
|
||||
int tc_dwc_g210_config_40_bit(struct ufs_hba *hba)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
dev_info(hba->dev, "Configuring Test Chip 40-bit RMMI\n");
|
||||
ret = tc_dwc_g210_setup_40bit_rmmi(hba);
|
||||
if (ret) {
|
||||
dev_err(hba->dev, "Configuration failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* To write Shadow register bank to effective configuration block */
|
||||
ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_MPHYCFGUPDT), 0x01);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* To configure Debug OMC */
|
||||
ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_DEBUGOMC), 0x01);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(tc_dwc_g210_config_40_bit);
|
||||
|
||||
/**
|
||||
* tc_dwc_g210_config_20_bit()
|
||||
* This function configures Local (host) Synopsys 20-bit TC specific attributes
|
||||
*
|
||||
* @hba: Pointer to drivers structure
|
||||
*
|
||||
* Returns 0 on success non-zero value on failure
|
||||
*/
|
||||
int tc_dwc_g210_config_20_bit(struct ufs_hba *hba)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
dev_info(hba->dev, "Configuring Test Chip 20-bit RMMI\n");
|
||||
ret = tc_dwc_g210_setup_20bit_rmmi(hba);
|
||||
if (ret) {
|
||||
dev_err(hba->dev, "Configuration failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* To write Shadow register bank to effective configuration block */
|
||||
ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_MPHYCFGUPDT), 0x01);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* To configure Debug OMC */
|
||||
ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_DEBUGOMC), 0x01);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(tc_dwc_g210_config_20_bit);
|
||||
|
||||
MODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>");
|
||||
MODULE_DESCRIPTION("Synopsys G210 Test Chip driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Synopsys G210 Test Chip driver
|
||||
*
|
||||
* Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
|
||||
*
|
||||
* Authors: Joao Pinto <jpinto@synopsys.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _TC_DWC_G210_H
|
||||
#define _TC_DWC_G210_H
|
||||
|
||||
int tc_dwc_g210_config_40_bit(struct ufs_hba *hba);
|
||||
int tc_dwc_g210_config_20_bit(struct ufs_hba *hba);
|
||||
|
||||
#endif /* End of Header */
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* UFS Host driver for Synopsys Designware Core
|
||||
*
|
||||
* Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
|
||||
*
|
||||
* Authors: Joao Pinto <jpinto@synopsys.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "ufshcd.h"
|
||||
#include "unipro.h"
|
||||
|
||||
#include "ufshcd-dwc.h"
|
||||
#include "ufshci-dwc.h"
|
||||
|
||||
int ufshcd_dwc_dme_set_attrs(struct ufs_hba *hba,
|
||||
const struct ufshcd_dme_attr_val *v, int n)
|
||||
{
|
||||
int ret = 0;
|
||||
int attr_node = 0;
|
||||
|
||||
for (attr_node = 0; attr_node < n; attr_node++) {
|
||||
ret = ufshcd_dme_set_attr(hba, v[attr_node].attr_sel,
|
||||
ATTR_SET_NOR, v[attr_node].mib_val, v[attr_node].peer);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ufshcd_dwc_dme_set_attrs);
|
||||
|
||||
/**
|
||||
* ufshcd_dwc_program_clk_div()
|
||||
* This function programs the clk divider value. This value is needed to
|
||||
* provide 1 microsecond tick to unipro layer.
|
||||
* @hba: Private Structure pointer
|
||||
* @divider_val: clock divider value to be programmed
|
||||
*
|
||||
*/
|
||||
static void ufshcd_dwc_program_clk_div(struct ufs_hba *hba, u32 divider_val)
|
||||
{
|
||||
ufshcd_writel(hba, divider_val, DWC_UFS_REG_HCLKDIV);
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_dwc_link_is_up()
|
||||
* Check if link is up
|
||||
* @hba: private structure poitner
|
||||
*
|
||||
* Returns 0 on success, non-zero value on failure
|
||||
*/
|
||||
static int ufshcd_dwc_link_is_up(struct ufs_hba *hba)
|
||||
{
|
||||
int dme_result = 0;
|
||||
|
||||
ufshcd_dme_get(hba, UIC_ARG_MIB(VS_POWERSTATE), &dme_result);
|
||||
|
||||
if (dme_result == UFSHCD_LINK_IS_UP) {
|
||||
ufshcd_set_link_active(hba);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_dwc_connection_setup()
|
||||
* This function configures both the local side (host) and the peer side
|
||||
* (device) unipro attributes to establish the connection to application/
|
||||
* cport.
|
||||
* This function is not required if the hardware is properly configured to
|
||||
* have this connection setup on reset. But invoking this function does no
|
||||
* harm and should be fine even working with any ufs device.
|
||||
*
|
||||
* @hba: pointer to drivers private data
|
||||
*
|
||||
* Returns 0 on success non-zero value on failure
|
||||
*/
|
||||
static int ufshcd_dwc_connection_setup(struct ufs_hba *hba)
|
||||
{
|
||||
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 },
|
||||
{ UIC_ARG_MIB(T_PEERDEVICEID), 1, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(T_PEERCPORTID), 0, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(T_TRAFFICCLASS), 0, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(T_CPORTFLAGS), 0x6, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(T_CPORTMODE), 1, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(T_CONNECTIONSTATE), 1, DME_LOCAL },
|
||||
{ UIC_ARG_MIB(T_CONNECTIONSTATE), 0, DME_PEER },
|
||||
{ UIC_ARG_MIB(N_DEVICEID), 1, DME_PEER },
|
||||
{ UIC_ARG_MIB(N_DEVICEID_VALID), 1, DME_PEER },
|
||||
{ UIC_ARG_MIB(T_PEERDEVICEID), 1, DME_PEER },
|
||||
{ UIC_ARG_MIB(T_PEERCPORTID), 0, DME_PEER },
|
||||
{ UIC_ARG_MIB(T_TRAFFICCLASS), 0, DME_PEER },
|
||||
{ UIC_ARG_MIB(T_CPORTFLAGS), 0x6, DME_PEER },
|
||||
{ UIC_ARG_MIB(T_CPORTMODE), 1, DME_PEER },
|
||||
{ UIC_ARG_MIB(T_CONNECTIONSTATE), 1, DME_PEER }
|
||||
};
|
||||
|
||||
return ufshcd_dwc_dme_set_attrs(hba, setup_attrs, ARRAY_SIZE(setup_attrs));
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_dwc_link_startup_notify()
|
||||
* UFS Host DWC specific link startup sequence
|
||||
* @hba: private structure poitner
|
||||
* @status: Callback notify status
|
||||
*
|
||||
* Returns 0 on success, non-zero value on failure
|
||||
*/
|
||||
int ufshcd_dwc_link_startup_notify(struct ufs_hba *hba,
|
||||
enum ufs_notify_change_status status)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (status == PRE_CHANGE) {
|
||||
ufshcd_dwc_program_clk_div(hba, DWC_UFS_REG_HCLKDIV_DIV_125);
|
||||
|
||||
if (hba->vops->phy_initialization) {
|
||||
err = hba->vops->phy_initialization(hba);
|
||||
if (err) {
|
||||
dev_err(hba->dev, "Phy setup failed (%d)\n",
|
||||
err);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
} else { /* POST_CHANGE */
|
||||
err = ufshcd_dwc_link_is_up(hba);
|
||||
if (err) {
|
||||
dev_err(hba->dev, "Link is not up\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = ufshcd_dwc_connection_setup(hba);
|
||||
if (err)
|
||||
dev_err(hba->dev, "Connection setup failed (%d)\n",
|
||||
err);
|
||||
}
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(ufshcd_dwc_link_startup_notify);
|
||||
|
||||
MODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>");
|
||||
MODULE_DESCRIPTION("UFS Host driver for Synopsys Designware Core");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* UFS Host driver for Synopsys Designware Core
|
||||
*
|
||||
* Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
|
||||
*
|
||||
* Authors: Joao Pinto <jpinto@synopsys.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _UFSHCD_DWC_H
|
||||
#define _UFSHCD_DWC_H
|
||||
|
||||
struct ufshcd_dme_attr_val {
|
||||
u32 attr_sel;
|
||||
u32 mib_val;
|
||||
u8 peer;
|
||||
};
|
||||
|
||||
int ufshcd_dwc_link_startup_notify(struct ufs_hba *hba,
|
||||
enum ufs_notify_change_status status);
|
||||
int ufshcd_dwc_dme_set_attrs(struct ufs_hba *hba,
|
||||
const struct ufshcd_dme_attr_val *v, int n);
|
||||
#endif /* End of Header */
|
|
@ -372,6 +372,6 @@ EXPORT_SYMBOL_GPL(ufshcd_pltfrm_init);
|
|||
|
||||
MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
|
||||
MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
|
||||
MODULE_DESCRIPTION("UFS host controller Pltform bus based glue driver");
|
||||
MODULE_DESCRIPTION("UFS host controller Platform bus based glue driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(UFSHCD_DRIVER_VERSION);
|
||||
|
|
|
@ -1173,7 +1173,7 @@ static void ufshcd_disable_intr(struct ufs_hba *hba, u32 intrs)
|
|||
* @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)
|
||||
u32 *upiu_flags, enum dma_data_direction cmd_dir)
|
||||
{
|
||||
struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr;
|
||||
u32 data_direction;
|
||||
|
@ -1299,47 +1299,55 @@ static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
|
|||
}
|
||||
|
||||
/**
|
||||
* ufshcd_compose_upiu - form UFS Protocol Information Unit(UPIU)
|
||||
* ufshcd_comp_devman_upiu - UFS Protocol Information Unit(UPIU)
|
||||
* for Device Management Purposes
|
||||
* @hba - per adapter instance
|
||||
* @lrb - pointer to local reference block
|
||||
*/
|
||||
static int ufshcd_compose_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
|
||||
static int ufshcd_comp_devman_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
|
||||
{
|
||||
u32 upiu_flags;
|
||||
int ret = 0;
|
||||
|
||||
switch (lrbp->command_type) {
|
||||
case UTP_CMD_TYPE_SCSI:
|
||||
if (likely(lrbp->cmd)) {
|
||||
ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags,
|
||||
lrbp->cmd->sc_data_direction);
|
||||
ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
break;
|
||||
case UTP_CMD_TYPE_DEV_MANAGE:
|
||||
ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE);
|
||||
if (hba->dev_cmd.type == DEV_CMD_TYPE_QUERY)
|
||||
ufshcd_prepare_utp_query_req_upiu(
|
||||
hba, lrbp, upiu_flags);
|
||||
else if (hba->dev_cmd.type == DEV_CMD_TYPE_NOP)
|
||||
ufshcd_prepare_utp_nop_upiu(lrbp);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
case UTP_CMD_TYPE_UFS:
|
||||
/* For UFS native command implementation */
|
||||
ret = -ENOTSUPP;
|
||||
dev_err(hba->dev, "%s: UFS native command are not supported\n",
|
||||
__func__);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUPP;
|
||||
dev_err(hba->dev, "%s: unknown command type: 0x%x\n",
|
||||
__func__, lrbp->command_type);
|
||||
break;
|
||||
} /* end of switch */
|
||||
if (hba->ufs_version == UFSHCI_VERSION_20)
|
||||
lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE;
|
||||
else
|
||||
lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
|
||||
|
||||
ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE);
|
||||
if (hba->dev_cmd.type == DEV_CMD_TYPE_QUERY)
|
||||
ufshcd_prepare_utp_query_req_upiu(hba, lrbp, upiu_flags);
|
||||
else if (hba->dev_cmd.type == DEV_CMD_TYPE_NOP)
|
||||
ufshcd_prepare_utp_nop_upiu(lrbp);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_comp_scsi_upiu - UFS Protocol Information Unit(UPIU)
|
||||
* for SCSI Purposes
|
||||
* @hba - per adapter instance
|
||||
* @lrb - pointer to local reference block
|
||||
*/
|
||||
static int ufshcd_comp_scsi_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
|
||||
{
|
||||
u32 upiu_flags;
|
||||
int ret = 0;
|
||||
|
||||
if (hba->ufs_version == UFSHCI_VERSION_20)
|
||||
lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE;
|
||||
else
|
||||
lrbp->command_type = UTP_CMD_TYPE_SCSI;
|
||||
|
||||
if (likely(lrbp->cmd)) {
|
||||
ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags,
|
||||
lrbp->cmd->sc_data_direction);
|
||||
ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1451,10 +1459,9 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
|
|||
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;
|
||||
lrbp->command_type = UTP_CMD_TYPE_SCSI;
|
||||
|
||||
/* form UPIU before issuing the command */
|
||||
ufshcd_compose_upiu(hba, lrbp);
|
||||
ufshcd_comp_scsi_upiu(hba, lrbp);
|
||||
|
||||
err = ufshcd_map_sg(lrbp);
|
||||
if (err) {
|
||||
lrbp->cmd = NULL;
|
||||
|
@ -1479,11 +1486,10 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba,
|
|||
lrbp->sense_buffer = NULL;
|
||||
lrbp->task_tag = tag;
|
||||
lrbp->lun = 0; /* device management cmd is not specific to any LUN */
|
||||
lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
|
||||
lrbp->intr_cmd = true; /* No interrupt aggregation */
|
||||
hba->dev_cmd.type = cmd_type;
|
||||
|
||||
return ufshcd_compose_upiu(hba, lrbp);
|
||||
return ufshcd_comp_devman_upiu(hba, lrbp);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -2131,7 +2137,7 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, u8 *buf,
|
|||
buff_ascii = kmalloc(ascii_len, GFP_KERNEL);
|
||||
if (!buff_ascii) {
|
||||
err = -ENOMEM;
|
||||
goto out_free_buff;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2150,7 +2156,6 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, u8 *buf,
|
|||
size - QUERY_DESC_HDR_SIZE);
|
||||
memcpy(buf + QUERY_DESC_HDR_SIZE, buff_ascii, ascii_len);
|
||||
buf[QUERY_DESC_LENGTH_OFFSET] = ascii_len + QUERY_DESC_HDR_SIZE;
|
||||
out_free_buff:
|
||||
kfree(buff_ascii);
|
||||
}
|
||||
out:
|
||||
|
@ -3539,7 +3544,8 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
|
|||
/* Do not touch lrbp after scsi done */
|
||||
cmd->scsi_done(cmd);
|
||||
__ufshcd_release(hba);
|
||||
} else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE) {
|
||||
} else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE ||
|
||||
lrbp->command_type == UTP_CMD_TYPE_UFS_STORAGE) {
|
||||
if (hba->dev_cmd.complete)
|
||||
complete(hba->dev_cmd.complete);
|
||||
}
|
||||
|
|
|
@ -264,6 +264,7 @@ struct ufs_pwr_mode_info {
|
|||
* @suspend: called during host controller PM callback
|
||||
* @resume: called during host controller PM callback
|
||||
* @dbg_register_dump: used to dump controller debug information
|
||||
* @phy_initialization: used to initialize phys
|
||||
*/
|
||||
struct ufs_hba_variant_ops {
|
||||
const char *name;
|
||||
|
@ -285,6 +286,7 @@ struct ufs_hba_variant_ops {
|
|||
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 *);
|
||||
};
|
||||
|
||||
/* clock gating state */
|
||||
|
@ -567,11 +569,16 @@ static inline bool ufshcd_can_autobkops_during_suspend(struct ufs_hba *hba)
|
|||
|
||||
static inline bool ufshcd_is_intr_aggr_allowed(struct ufs_hba *hba)
|
||||
{
|
||||
/* DWC UFS Core has the Interrupt aggregation feature but is not detectable*/
|
||||
#ifndef CONFIG_SCSI_UFS_DWC
|
||||
if ((hba->caps & UFSHCD_CAP_INTR_AGGR) &&
|
||||
!(hba->quirks & UFSHCD_QUIRK_BROKEN_INTR_AGGR))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define ufshcd_writel(hba, val, reg) \
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* UFS Host driver for Synopsys Designware Core
|
||||
*
|
||||
* Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
|
||||
*
|
||||
* Authors: Joao Pinto <jpinto@synopsys.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _UFSHCI_DWC_H
|
||||
#define _UFSHCI_DWC_H
|
||||
|
||||
/* DWC HC UFSHCI specific Registers */
|
||||
enum dwc_specific_registers {
|
||||
DWC_UFS_REG_HCLKDIV = 0xFC,
|
||||
};
|
||||
|
||||
/* Clock Divider Values: Hex equivalent of frequency in MHz */
|
||||
enum clk_div_values {
|
||||
DWC_UFS_REG_HCLKDIV_DIV_62_5 = 0x3e,
|
||||
DWC_UFS_REG_HCLKDIV_DIV_125 = 0x7d,
|
||||
DWC_UFS_REG_HCLKDIV_DIV_200 = 0xc8,
|
||||
};
|
||||
|
||||
/* Selector Index */
|
||||
enum selector_index {
|
||||
SELIND_LN0_TX = 0x00,
|
||||
SELIND_LN1_TX = 0x01,
|
||||
SELIND_LN0_RX = 0x04,
|
||||
SELIND_LN1_RX = 0x05,
|
||||
};
|
||||
|
||||
#endif /* End of Header */
|
|
@ -220,6 +220,12 @@ enum {
|
|||
#define UIC_ARG_ATTR_TYPE(t) (((t) & 0xFF) << 16)
|
||||
#define UIC_GET_ATTR_ID(v) (((v) >> 16) & 0xFFFF)
|
||||
|
||||
/* Link Status*/
|
||||
enum link_status {
|
||||
UFSHCD_LINK_IS_DOWN = 1,
|
||||
UFSHCD_LINK_IS_UP = 2,
|
||||
};
|
||||
|
||||
/* UIC Commands */
|
||||
enum uic_cmd_dme {
|
||||
UIC_CMD_DME_GET = 0x01,
|
||||
|
@ -279,6 +285,11 @@ enum {
|
|||
UTP_CMD_TYPE_DEV_MANAGE = 0x2,
|
||||
};
|
||||
|
||||
/* To accommodate UFS2.0 required Command type */
|
||||
enum {
|
||||
UTP_CMD_TYPE_UFS_STORAGE = 0x1,
|
||||
};
|
||||
|
||||
enum {
|
||||
UTP_SCSI_COMMAND = 0x00000000,
|
||||
UTP_NATIVE_UFS_COMMAND = 0x10000000,
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
#define TX_LCC_SEQUENCER 0x0032
|
||||
#define TX_MIN_ACTIVATETIME 0x0033
|
||||
#define TX_PWM_G6_G7_SYNC_LENGTH 0x0034
|
||||
#define TX_REFCLKFREQ 0x00EB
|
||||
#define TX_CFGCLKFREQVAL 0x00EC
|
||||
#define CFGEXTRATTR 0x00F0
|
||||
#define DITHERCTRL2 0x00F1
|
||||
|
||||
/*
|
||||
* M-RX Configuration Attributes
|
||||
|
@ -51,10 +55,40 @@
|
|||
#define RX_TERMINATION_FORCE_ENABLE 0x0089
|
||||
#define RX_MIN_ACTIVATETIME_CAPABILITY 0x008F
|
||||
#define RX_HIBERN8TIME_CAPABILITY 0x0092
|
||||
#define RX_REFCLKFREQ 0x00EB
|
||||
#define RX_CFGCLKFREQVAL 0x00EC
|
||||
#define CFGWIDEINLN 0x00F0
|
||||
#define CFGRXCDR8 0x00BA
|
||||
#define ENARXDIRECTCFG4 0x00F2
|
||||
#define CFGRXOVR8 0x00BD
|
||||
#define RXDIRECTCTRL2 0x00C7
|
||||
#define ENARXDIRECTCFG3 0x00F3
|
||||
#define RXCALCTRL 0x00B4
|
||||
#define ENARXDIRECTCFG2 0x00F4
|
||||
#define CFGRXOVR4 0x00E9
|
||||
#define RXSQCTRL 0x00B5
|
||||
#define CFGRXOVR6 0x00BF
|
||||
|
||||
#define is_mphy_tx_attr(attr) (attr < RX_MODE)
|
||||
#define RX_MIN_ACTIVATETIME_UNIT_US 100
|
||||
#define HIBERN8TIME_UNIT_US 100
|
||||
|
||||
/*
|
||||
* Common Block Attributes
|
||||
*/
|
||||
#define TX_GLOBALHIBERNATE UNIPRO_CB_OFFSET(0x002B)
|
||||
#define REFCLKMODE UNIPRO_CB_OFFSET(0x00BF)
|
||||
#define DIRECTCTRL19 UNIPRO_CB_OFFSET(0x00CD)
|
||||
#define DIRECTCTRL10 UNIPRO_CB_OFFSET(0x00E6)
|
||||
#define CDIRECTCTRL6 UNIPRO_CB_OFFSET(0x00EA)
|
||||
#define RTOBSERVESELECT UNIPRO_CB_OFFSET(0x00F0)
|
||||
#define CBDIVFACTOR UNIPRO_CB_OFFSET(0x00F1)
|
||||
#define CBDCOCTRL5 UNIPRO_CB_OFFSET(0x00F3)
|
||||
#define CBPRGPLL2 UNIPRO_CB_OFFSET(0x00F8)
|
||||
#define CBPRGTUNING UNIPRO_CB_OFFSET(0x00FB)
|
||||
|
||||
#define UNIPRO_CB_OFFSET(x) (0x8000 | x)
|
||||
|
||||
/*
|
||||
* PHY Adpater attributes
|
||||
*/
|
||||
|
@ -119,6 +153,11 @@
|
|||
#define PA_TACTIVATE_TIME_UNIT_US 10
|
||||
#define PA_HIBERN8_TIME_UNIT_US 100
|
||||
|
||||
/*Other attributes*/
|
||||
#define VS_MPHYCFGUPDT 0xD085
|
||||
#define VS_DEBUGOMC 0xD09E
|
||||
#define VS_POWERSTATE 0xD083
|
||||
|
||||
/* PHY Adapter Protocol Constants */
|
||||
#define PA_MAXDATALANES 4
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Maintained by: Arvind Kumar <arvindkumar@vmware.com>
|
||||
* Maintained by: Jim Gill <jgill@vmware.com>
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Maintained by: Arvind Kumar <arvindkumar@vmware.com>
|
||||
* Maintained by: Jim Gill <jgill@vmware.com>
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@
|
|||
#ifdef WD7000_DEBUG
|
||||
#define dprintk printk
|
||||
#else
|
||||
#define dprintk(format,args...)
|
||||
#define dprintk no_printk
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -1591,8 +1591,8 @@ static int wd7000_biosparam(struct scsi_device *sdev,
|
|||
{
|
||||
char b[BDEVNAME_SIZE];
|
||||
|
||||
dprintk("wd7000_biosparam: dev=%s, size=%d, ",
|
||||
bdevname(bdev, b), capacity);
|
||||
dprintk("wd7000_biosparam: dev=%s, size=%llu, ",
|
||||
bdevname(bdev, b), (u64)capacity);
|
||||
(void)b; /* unused var warning? */
|
||||
|
||||
/*
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
/*
|
||||
* This version is based on:
|
||||
* http://www.t11.org/ftp/t11/pub/fc/bb-5/08-543v1.pdf
|
||||
* and T11 FC-BB-6 10-019v4.pdf (June 2010 VN2VN proposal)
|
||||
* and T11 FC-BB-6 13-091v5.pdf (December 2013 VN2VN proposal)
|
||||
*/
|
||||
|
||||
#define FIP_DEF_PRI 128 /* default selection priority */
|
||||
|
@ -109,8 +109,9 @@ enum fip_reset_subcode {
|
|||
* Subcodes for FIP_OP_VLAN.
|
||||
*/
|
||||
enum fip_vlan_subcode {
|
||||
FIP_SC_VL_REQ = 1, /* request */
|
||||
FIP_SC_VL_REP = 2, /* reply */
|
||||
FIP_SC_VL_REQ = 1, /* vlan request */
|
||||
FIP_SC_VL_NOTE = 2, /* vlan notification */
|
||||
FIP_SC_VL_VN2VN_NOTE = 3, /* VN2VN vlan notification */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -130,6 +131,8 @@ enum fip_vn2vn_subcode {
|
|||
enum fip_flag {
|
||||
FIP_FL_FPMA = 0x8000, /* supports FPMA fabric-provided MACs */
|
||||
FIP_FL_SPMA = 0x4000, /* supports SPMA server-provided MACs */
|
||||
FIP_FL_FCF = 0x0020, /* originated from a controlling FCF */
|
||||
FIP_FL_FDF = 0x0010, /* originated from an FDF */
|
||||
FIP_FL_REC_OR_P2P = 0x0008, /* configured addr or point-to-point */
|
||||
FIP_FL_AVAIL = 0x0004, /* available for FLOGI/ELP */
|
||||
FIP_FL_SOL = 0x0002, /* this is a solicited message */
|
||||
|
@ -161,7 +164,9 @@ enum fip_desc_type {
|
|||
FIP_DT_VLAN = 14, /* vlan number */
|
||||
FIP_DT_FC4F = 15, /* FC-4 features */
|
||||
FIP_DT_LIMIT, /* max defined desc_type + 1 */
|
||||
FIP_DT_VENDOR_BASE = 128, /* first vendor-specific desc_type */
|
||||
FIP_DT_NON_CRITICAL = 128, /* First non-critical descriptor */
|
||||
FIP_DT_CLR_VLINKS = 128, /* Clear virtual links reason code */
|
||||
FIP_DT_VENDOR_BASE = 241, /* first vendor-specific desc_type */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -258,6 +263,14 @@ enum fip_fka_flags {
|
|||
|
||||
/* FIP_DT_FKA flags */
|
||||
|
||||
/*
|
||||
* FIP_DT_VLAN descriptor
|
||||
*/
|
||||
struct fip_vlan_desc {
|
||||
struct fip_desc fd_desc;
|
||||
__be16 fd_vlan; /* Note: highest 4 bytes are unused */
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* FIP_DT_FC4F - FC-4 features.
|
||||
*/
|
||||
|
|
|
@ -878,6 +878,7 @@ struct fc_lport {
|
|||
struct libfc_function_template tt;
|
||||
u8 link_up;
|
||||
u8 qfull;
|
||||
u16 vlan;
|
||||
enum fc_lport_state state;
|
||||
unsigned long boot_time;
|
||||
struct fc_host_statistics host_stats;
|
||||
|
|
|
@ -78,10 +78,12 @@ enum fip_state {
|
|||
* The mode is the state that is to be entered after link up.
|
||||
* It must not change after fcoe_ctlr_init() sets it.
|
||||
*/
|
||||
#define FIP_MODE_AUTO FIP_ST_AUTO
|
||||
#define FIP_MODE_NON_FIP FIP_ST_NON_FIP
|
||||
#define FIP_MODE_FABRIC FIP_ST_ENABLED
|
||||
#define FIP_MODE_VN2VN FIP_ST_VNMP_START
|
||||
enum fip_mode {
|
||||
FIP_MODE_AUTO = FIP_ST_AUTO,
|
||||
FIP_MODE_NON_FIP,
|
||||
FIP_MODE_FABRIC,
|
||||
FIP_MODE_VN2VN,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fcoe_ctlr - FCoE Controller and FIP state
|
||||
|
@ -108,8 +110,10 @@ enum fip_state {
|
|||
* @flogi_req_send: send of FLOGI requested
|
||||
* @flogi_count: number of FLOGI attempts in AUTO mode.
|
||||
* @map_dest: use the FC_MAP mode for destination MAC addresses.
|
||||
* @fip_resp: start FIP VLAN discovery responder
|
||||
* @spma: supports SPMA server-provided MACs mode
|
||||
* @probe_tries: number of FC_IDs probed
|
||||
* @priority: DCBx FCoE APP priority
|
||||
* @dest_addr: MAC address of the selected FC forwarder.
|
||||
* @ctl_src_addr: the native MAC address of our local port.
|
||||
* @send: LLD-supplied function to handle sending FIP Ethernet frames
|
||||
|
@ -124,7 +128,7 @@ enum fip_state {
|
|||
*/
|
||||
struct fcoe_ctlr {
|
||||
enum fip_state state;
|
||||
enum fip_state mode;
|
||||
enum fip_mode mode;
|
||||
struct fc_lport *lp;
|
||||
struct fcoe_fcf *sel_fcf;
|
||||
struct list_head fcfs;
|
||||
|
@ -147,7 +151,8 @@ struct fcoe_ctlr {
|
|||
u16 flogi_oxid;
|
||||
u8 flogi_req_send;
|
||||
u8 flogi_count;
|
||||
u8 map_dest;
|
||||
bool map_dest;
|
||||
bool fip_resp;
|
||||
u8 spma;
|
||||
u8 probe_tries;
|
||||
u8 priority;
|
||||
|
@ -311,7 +316,7 @@ struct fcoe_transport {
|
|||
struct list_head list;
|
||||
bool (*match) (struct net_device *device);
|
||||
int (*alloc) (struct net_device *device);
|
||||
int (*create) (struct net_device *device, enum fip_state fip_mode);
|
||||
int (*create) (struct net_device *device, enum fip_mode fip_mode);
|
||||
int (*destroy) (struct net_device *device);
|
||||
int (*enable) (struct net_device *device);
|
||||
int (*disable) (struct net_device *device);
|
||||
|
@ -319,14 +324,16 @@ struct fcoe_transport {
|
|||
|
||||
/**
|
||||
* struct fcoe_percpu_s - The context for FCoE receive thread(s)
|
||||
* @thread: The thread context
|
||||
* @kthread: The thread context (used by bnx2fc)
|
||||
* @work: The work item (used by fcoe)
|
||||
* @fcoe_rx_list: The queue of pending packets to process
|
||||
* @page: The memory page for calculating frame trailer CRCs
|
||||
* @crc_eof_offset: The offset into the CRC page pointing to available
|
||||
* memory for a new trailer
|
||||
*/
|
||||
struct fcoe_percpu_s {
|
||||
struct task_struct *thread;
|
||||
struct task_struct *kthread;
|
||||
struct work_struct work;
|
||||
struct sk_buff_head fcoe_rx_list;
|
||||
struct page *crc_eof_page;
|
||||
int crc_eof_offset;
|
||||
|
|
|
@ -94,7 +94,6 @@ struct scsi_device {
|
|||
spinlock_t list_lock;
|
||||
struct list_head cmd_list; /* queue of in use SCSI Command structures */
|
||||
struct list_head starved_entry;
|
||||
struct scsi_cmnd *current_cmnd; /* currently active command */
|
||||
unsigned short queue_depth; /* How deep of a queue we want */
|
||||
unsigned short max_queue_depth; /* max queue depth */
|
||||
unsigned short last_queue_full_depth; /* These two are used by */
|
||||
|
|
|
@ -495,9 +495,6 @@ struct scsi_host_template {
|
|||
*/
|
||||
unsigned int cmd_size;
|
||||
struct scsi_host_cmd_pool *cmd_pool;
|
||||
|
||||
/* temporary flag to disable blk-mq I/O path */
|
||||
bool disable_blk_mq;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -778,7 +775,8 @@ extern bool scsi_use_blk_mq;
|
|||
|
||||
static inline bool shost_use_blk_mq(struct Scsi_Host *shost)
|
||||
{
|
||||
return shost->use_blk_mq;
|
||||
return scsi_use_blk_mq;
|
||||
|
||||
}
|
||||
|
||||
extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *);
|
||||
|
|
Загрузка…
Ссылка в новой задаче