diff options
Diffstat (limited to 'drivers/scsi/qedf')
-rw-r--r-- | drivers/scsi/qedf/drv_fcoe_fw_funcs.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qedf/drv_fcoe_fw_funcs.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qedf/drv_scsi_fw_funcs.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qedf/drv_scsi_fw_funcs.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qedf/qedf.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qedf/qedf_attr.c | 59 | ||||
-rw-r--r-- | drivers/scsi/qedf/qedf_dbg.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qedf/qedf_debugfs.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qedf/qedf_els.c | 8 | ||||
-rw-r--r-- | drivers/scsi/qedf/qedf_fip.c | 25 | ||||
-rw-r--r-- | drivers/scsi/qedf/qedf_hsi.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qedf/qedf_io.c | 37 | ||||
-rw-r--r-- | drivers/scsi/qedf/qedf_main.c | 209 | ||||
-rw-r--r-- | drivers/scsi/qedf/qedf_version.h | 8 |
14 files changed, 251 insertions, 111 deletions
diff --git a/drivers/scsi/qedf/drv_fcoe_fw_funcs.c b/drivers/scsi/qedf/drv_fcoe_fw_funcs.c index 8c65e3b034dc..7d91e53562f8 100644 --- a/drivers/scsi/qedf/drv_fcoe_fw_funcs.c +++ b/drivers/scsi/qedf/drv_fcoe_fw_funcs.c @@ -1,5 +1,5 @@ /* QLogic FCoE Offload Driver - * Copyright (c) 2016 Cavium Inc. + * Copyright (c) 2016-2017 Cavium Inc. * * This software is available under the terms of the GNU General Public License * (GPL) Version 2, available from the file COPYING in the main directory of diff --git a/drivers/scsi/qedf/drv_fcoe_fw_funcs.h b/drivers/scsi/qedf/drv_fcoe_fw_funcs.h index 617529b058f4..f9c50faa748e 100644 --- a/drivers/scsi/qedf/drv_fcoe_fw_funcs.h +++ b/drivers/scsi/qedf/drv_fcoe_fw_funcs.h @@ -1,5 +1,5 @@ /* QLogic FCoE Offload Driver - * Copyright (c) 2016 Cavium Inc. + * Copyright (c) 2016-2017 Cavium Inc. * * This software is available under the terms of the GNU General Public License * (GPL) Version 2, available from the file COPYING in the main directory of diff --git a/drivers/scsi/qedf/drv_scsi_fw_funcs.c b/drivers/scsi/qedf/drv_scsi_fw_funcs.c index 11e0cc082ec0..5d5095e3d96d 100644 --- a/drivers/scsi/qedf/drv_scsi_fw_funcs.c +++ b/drivers/scsi/qedf/drv_scsi_fw_funcs.c @@ -1,5 +1,5 @@ /* QLogic FCoE Offload Driver - * Copyright (c) 2016 Cavium Inc. + * Copyright (c) 2016-2017 Cavium Inc. * * This software is available under the terms of the GNU General Public License * (GPL) Version 2, available from the file COPYING in the main directory of diff --git a/drivers/scsi/qedf/drv_scsi_fw_funcs.h b/drivers/scsi/qedf/drv_scsi_fw_funcs.h index 9cb45410bc45..8fbe6e4d0b4f 100644 --- a/drivers/scsi/qedf/drv_scsi_fw_funcs.h +++ b/drivers/scsi/qedf/drv_scsi_fw_funcs.h @@ -1,5 +1,5 @@ /* QLogic FCoE Offload Driver - * Copyright (c) 2016 Cavium Inc. + * Copyright (c) 2016-2017 Cavium Inc. * * This software is available under the terms of the GNU General Public License * (GPL) Version 2, available from the file COPYING in the main directory of diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h index 07ee88200e91..4d038926a455 100644 --- a/drivers/scsi/qedf/qedf.h +++ b/drivers/scsi/qedf/qedf.h @@ -1,6 +1,6 @@ /* * QLogic FCoE Offload Driver - * Copyright (c) 2016 Cavium Inc. + * Copyright (c) 2016-2017 Cavium Inc. * * This software is available under the terms of the GNU General Public License * (GPL) Version 2, available from the file COPYING in the main directory of diff --git a/drivers/scsi/qedf/qedf_attr.c b/drivers/scsi/qedf/qedf_attr.c index 47720611ad2c..fa6727685627 100644 --- a/drivers/scsi/qedf/qedf_attr.c +++ b/drivers/scsi/qedf/qedf_attr.c @@ -1,6 +1,6 @@ /* * QLogic FCoE Offload Driver - * Copyright (c) 2016 Cavium Inc. + * Copyright (c) 2016-2017 Cavium Inc. * * This software is available under the terms of the GNU General Public License * (GPL) Version 2, available from the file COPYING in the main directory of @@ -8,6 +8,25 @@ */ #include "qedf.h" +inline bool qedf_is_vport(struct qedf_ctx *qedf) +{ + return qedf->lport->vport != NULL; +} + +/* Get base qedf for physical port from vport */ +static struct qedf_ctx *qedf_get_base_qedf(struct qedf_ctx *qedf) +{ + struct fc_lport *lport; + struct fc_lport *base_lport; + + if (!(qedf_is_vport(qedf))) + return NULL; + + lport = qedf->lport; + base_lport = shost_priv(vport_to_shost(lport->vport)); + return lport_priv(base_lport); +} + static ssize_t qedf_fcoe_mac_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -26,34 +45,34 @@ qedf_fcoe_mac_show(struct device *dev, return scnprintf(buf, PAGE_SIZE, "%pM\n", fcoe_mac); } +static ssize_t +qedf_fka_period_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fc_lport *lport = shost_priv(class_to_shost(dev)); + struct qedf_ctx *qedf = lport_priv(lport); + int fka_period = -1; + + if (qedf_is_vport(qedf)) + qedf = qedf_get_base_qedf(qedf); + + if (qedf->ctlr.sel_fcf) + fka_period = qedf->ctlr.sel_fcf->fka_period; + + return scnprintf(buf, PAGE_SIZE, "%d\n", fka_period); +} + static DEVICE_ATTR(fcoe_mac, S_IRUGO, qedf_fcoe_mac_show, NULL); +static DEVICE_ATTR(fka_period, S_IRUGO, qedf_fka_period_show, NULL); struct device_attribute *qedf_host_attrs[] = { &dev_attr_fcoe_mac, + &dev_attr_fka_period, NULL, }; extern const struct qed_fcoe_ops *qed_ops; -inline bool qedf_is_vport(struct qedf_ctx *qedf) -{ - return (!(qedf->lport->vport == NULL)); -} - -/* Get base qedf for physical port from vport */ -static struct qedf_ctx *qedf_get_base_qedf(struct qedf_ctx *qedf) -{ - struct fc_lport *lport; - struct fc_lport *base_lport; - - if (!(qedf_is_vport(qedf))) - return NULL; - - lport = qedf->lport; - base_lport = shost_priv(vport_to_shost(lport->vport)); - return (struct qedf_ctx *)(lport_priv(base_lport)); -} - void qedf_capture_grc_dump(struct qedf_ctx *qedf) { struct qedf_ctx *base_qedf; diff --git a/drivers/scsi/qedf/qedf_dbg.h b/drivers/scsi/qedf/qedf_dbg.h index 7d173f48a81e..50083cae84c3 100644 --- a/drivers/scsi/qedf/qedf_dbg.h +++ b/drivers/scsi/qedf/qedf_dbg.h @@ -1,6 +1,6 @@ /* * QLogic FCoE Offload Driver - * Copyright (c) 2016 Cavium Inc. + * Copyright (c) 2016-2017 Cavium Inc. * * This software is available under the terms of the GNU General Public License * (GPL) Version 2, available from the file COPYING in the main directory of diff --git a/drivers/scsi/qedf/qedf_debugfs.c b/drivers/scsi/qedf/qedf_debugfs.c index 00a1d6405ebe..2b1ef3075e93 100644 --- a/drivers/scsi/qedf/qedf_debugfs.c +++ b/drivers/scsi/qedf/qedf_debugfs.c @@ -1,6 +1,6 @@ /* * QLogic FCoE Offload Driver - * Copyright (c) 2016 QLogic Corporation + * Copyright (c) 2016-2017 QLogic Corporation * * This software is available under the terms of the GNU General Public License * (GPL) Version 2, available from the file COPYING in the main directory of diff --git a/drivers/scsi/qedf/qedf_els.c b/drivers/scsi/qedf/qedf_els.c index 90627033bde6..eb07f1de8afa 100644 --- a/drivers/scsi/qedf/qedf_els.c +++ b/drivers/scsi/qedf/qedf_els.c @@ -1,6 +1,6 @@ /* * QLogic FCoE Offload Driver - * Copyright (c) 2016 Cavium Inc. + * Copyright (c) 2016-2017 Cavium Inc. * * This software is available under the terms of the GNU General Public License * (GPL) Version 2, available from the file COPYING in the main directory of @@ -44,7 +44,7 @@ static int qedf_initiate_els(struct qedf_rport *fcport, unsigned int op, goto els_err; } - if (!(test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags))) { + if (!test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags)) { QEDF_ERR(&(qedf->dbg_ctx), "els 0x%x: fcport not ready\n", op); rc = -EINVAL; goto els_err; @@ -225,7 +225,7 @@ int qedf_send_rrq(struct qedf_ioreq *aborted_io_req) fcport = aborted_io_req->fcport; /* Check that fcport is still offloaded */ - if (!(test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags))) { + if (!test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags)) { QEDF_ERR(NULL, "fcport is no longer offloaded.\n"); return -EINVAL; } @@ -550,7 +550,7 @@ static int qedf_send_srr(struct qedf_ioreq *orig_io_req, u32 offset, u8 r_ctl) fcport = orig_io_req->fcport; /* Check that fcport is still offloaded */ - if (!(test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags))) { + if (!test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags)) { QEDF_ERR(NULL, "fcport is no longer offloaded.\n"); return -EINVAL; } diff --git a/drivers/scsi/qedf/qedf_fip.c b/drivers/scsi/qedf/qedf_fip.c index e10b91cc3c62..aefd24ca9604 100644 --- a/drivers/scsi/qedf/qedf_fip.c +++ b/drivers/scsi/qedf/qedf_fip.c @@ -1,6 +1,6 @@ /* * QLogic FCoE Offload Driver - * Copyright (c) 2016 Cavium Inc. + * Copyright (c) 2016-2017 Cavium Inc. * * This software is available under the terms of the GNU General Public License * (GPL) Version 2, available from the file COPYING in the main directory of @@ -125,8 +125,7 @@ void qedf_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) sub = fiph->fip_subcode; if (!qedf->vlan_hw_insert) { - vlan_hdr = (struct vlan_ethhdr *)skb_push(skb, sizeof(*vlan_hdr) - - sizeof(*eth_hdr)); + vlan_hdr = skb_push(skb, sizeof(*vlan_hdr) - sizeof(*eth_hdr)); memcpy(vlan_hdr, eth_hdr, 2 * ETH_ALEN); vlan_hdr->h_vlan_proto = htons(ETH_P_8021Q); vlan_hdr->h_vlan_encapsulated_proto = eth_hdr->h_proto; @@ -156,10 +155,9 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb) struct fip_wwn_desc *wp; struct fip_vn_desc *vp; size_t rlen, dlen; - uint32_t cvl_port_id; - __u8 cvl_mac[ETH_ALEN]; u16 op; u8 sub; + bool do_reset = false; eth_hdr = (struct ethhdr *)skb_mac_header(skb); fiph = (struct fip_header *) ((void *)skb->data + 2 * ETH_ALEN + 2); @@ -190,8 +188,6 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb) return; } - cvl_port_id = 0; - memset(cvl_mac, 0, ETH_ALEN); /* * We need to loop through the CVL descriptors to determine * if we want to reset the fcoe link @@ -205,7 +201,9 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb) mp = (struct fip_mac_desc *)desc; QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, "fd_mac=%pM\n", mp->fd_mac); - ether_addr_copy(cvl_mac, mp->fd_mac); + if (ether_addr_equal(mp->fd_mac, + qedf->ctlr.sel_fcf->fcf_mac)) + do_reset = true; break; case FIP_DT_NAME: wp = (struct fip_wwn_desc *)desc; @@ -217,7 +215,9 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb) vp = (struct fip_vn_desc *)desc; QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, "fd_fc_id=%x.\n", ntoh24(vp->fd_fc_id)); - cvl_port_id = ntoh24(vp->fd_fc_id); + if (ntoh24(vp->fd_fc_id) == + qedf->lport->port_id) + do_reset = true; break; default: /* Ignore anything else */ @@ -228,11 +228,8 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb) } QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, - "cvl_port_id=%06x cvl_mac=%pM.\n", cvl_port_id, - cvl_mac); - if (cvl_port_id == qedf->lport->port_id && - ether_addr_equal(cvl_mac, - qedf->ctlr.sel_fcf->fcf_mac)) { + "do_reset=%d.\n", do_reset); + if (do_reset) { fcoe_ctlr_link_down(&qedf->ctlr); qedf_wait_for_upload(qedf); fcoe_ctlr_link_up(&qedf->ctlr); diff --git a/drivers/scsi/qedf/qedf_hsi.h b/drivers/scsi/qedf/qedf_hsi.h index dfd65dec2874..7faef80c5f7a 100644 --- a/drivers/scsi/qedf/qedf_hsi.h +++ b/drivers/scsi/qedf/qedf_hsi.h @@ -1,6 +1,6 @@ /* * QLogic FCoE Offload Driver - * Copyright (c) 2016 Cavium Inc. + * Copyright (c) 2016-2017 Cavium Inc. * * This software is available under the terms of the GNU General Public License * (GPL) Version 2, available from the file COPYING in the main directory of diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c index 1d7f90d0adc1..ded386036c27 100644 --- a/drivers/scsi/qedf/qedf_io.c +++ b/drivers/scsi/qedf/qedf_io.c @@ -1,6 +1,6 @@ /* * QLogic FCoE Offload Driver - * Copyright (c) 2016 Cavium Inc. + * Copyright (c) 2016-2017 Cavium Inc. * * This software is available under the terms of the GNU General Public License * (GPL) Version 2, available from the file COPYING in the main directory of @@ -1041,10 +1041,13 @@ static void qedf_parse_fcp_rsp(struct qedf_ioreq *io_req, fcp_sns_len = SCSI_SENSE_BUFFERSIZE; } - memset(sc_cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); - if (fcp_sns_len) - memcpy(sc_cmd->sense_buffer, sense_data, - fcp_sns_len); + /* The sense buffer can be NULL for TMF commands */ + if (sc_cmd->sense_buffer) { + memset(sc_cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); + if (fcp_sns_len) + memcpy(sc_cmd->sense_buffer, sense_data, + fcp_sns_len); + } } static void qedf_unmap_sg_list(struct qedf_ctx *qedf, struct qedf_ioreq *io_req) @@ -1476,8 +1479,8 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts) { struct fc_lport *lport; struct qedf_rport *fcport = io_req->fcport; - struct fc_rport_priv *rdata = fcport->rdata; - struct qedf_ctx *qedf = fcport->qedf; + struct fc_rport_priv *rdata; + struct qedf_ctx *qedf; u16 xid; u32 r_a_tov = 0; int rc = 0; @@ -1485,15 +1488,18 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts) struct fcoe_wqe *sqe; u16 sqe_idx; - r_a_tov = rdata->r_a_tov; - lport = qedf->lport; - + /* Sanity check qedf_rport before dereferencing any pointers */ if (!test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags)) { - QEDF_ERR(&(qedf->dbg_ctx), "tgt not offloaded\n"); + QEDF_ERR(NULL, "tgt not offloaded\n"); rc = 1; goto abts_err; } + rdata = fcport->rdata; + r_a_tov = rdata->r_a_tov; + qedf = fcport->qedf; + lport = qedf->lport; + if (lport->state != LPORT_ST_READY || !(lport->link_up)) { QEDF_ERR(&(qedf->dbg_ctx), "link is not ready\n"); rc = 1; @@ -1729,6 +1735,13 @@ int qedf_initiate_cleanup(struct qedf_ioreq *io_req, return SUCCESS; } + /* Sanity check qedf_rport before dereferencing any pointers */ + if (!test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags)) { + QEDF_ERR(NULL, "tgt not offloaded\n"); + rc = 1; + return SUCCESS; + } + qedf = fcport->qedf; if (!qedf) { QEDF_ERR(NULL, "qedf is NULL.\n"); @@ -1837,7 +1850,7 @@ static int qedf_execute_tmf(struct qedf_rport *fcport, struct scsi_cmnd *sc_cmd, return FAILED; } - if (!(test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags))) { + if (!test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags)) { QEDF_ERR(&(qedf->dbg_ctx), "fcport not offloaded\n"); rc = FAILED; return FAILED; diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index a5c97342fd5d..b58bba4604e8 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -1,6 +1,6 @@ /* * QLogic FCoE Offload Driver - * Copyright (c) 2016 Cavium Inc. + * Copyright (c) 2016-2017 Cavium Inc. * * This software is available under the terms of the GNU General Public License * (GPL) Version 2, available from the file COPYING in the main directory of @@ -22,6 +22,7 @@ #include <linux/if_vlan.h> #include <linux/cpu.h> #include "qedf.h" +#include <uapi/linux/pci_regs.h> const struct qed_fcoe_ops *qed_ops; @@ -94,7 +95,7 @@ module_param_named(dp_module, qedf_dp_module, uint, S_IRUGO); MODULE_PARM_DESC(dp_module, " bit flags control for verbose printk passed " "qed module during probe."); -static uint qedf_dp_level; +static uint qedf_dp_level = QED_LEVEL_NOTICE; module_param_named(dp_level, qedf_dp_level, uint, S_IRUGO); MODULE_PARM_DESC(dp_level, " printk verbosity control passed to qed module " "during probe (0-3: 0 more verbose)."); @@ -441,7 +442,8 @@ static void qedf_link_update(void *dev, struct qed_link_output *link) qedf_update_link_speed(qedf, link); if (atomic_read(&qedf->dcbx) == QEDF_DCBX_DONE) { - QEDF_ERR(&(qedf->dbg_ctx), "DCBx done.\n"); + QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, + "DCBx done.\n"); if (atomic_read(&qedf->link_down_tmo_valid) > 0) queue_delayed_work(qedf->link_update_wq, &qedf->link_recovery, 0); @@ -627,6 +629,16 @@ static int qedf_eh_device_reset(struct scsi_cmnd *sc_cmd) return qedf_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET); } +static int qedf_eh_bus_reset(struct scsi_cmnd *sc_cmd) +{ + QEDF_ERR(NULL, "BUS RESET Issued...\n"); + /* + * Essentially a no-op but return SUCCESS to prevent + * unnecessary escalation to the host reset handler. + */ + return SUCCESS; +} + void qedf_wait_for_upload(struct qedf_ctx *qedf) { while (1) { @@ -639,27 +651,17 @@ void qedf_wait_for_upload(struct qedf_ctx *qedf) } } -/* Reset the host by gracefully logging out and then logging back in */ -static int qedf_eh_host_reset(struct scsi_cmnd *sc_cmd) +/* Performs soft reset of qedf_ctx by simulating a link down/up */ +static void qedf_ctx_soft_reset(struct fc_lport *lport) { - struct fc_lport *lport; struct qedf_ctx *qedf; - lport = shost_priv(sc_cmd->device->host); - if (lport->vport) { QEDF_ERR(NULL, "Cannot issue host reset on NPIV port.\n"); - return SUCCESS; + return; } - qedf = (struct qedf_ctx *)lport_priv(lport); - - if (atomic_read(&qedf->link_state) == QEDF_LINK_DOWN || - test_bit(QEDF_UNLOADING, &qedf->flags) || - test_bit(QEDF_DBG_STOP_IO, &qedf->flags)) - return FAILED; - - QEDF_ERR(&(qedf->dbg_ctx), "HOST RESET Issued..."); + qedf = lport_priv(lport); /* For host reset, essentially do a soft link up/down */ atomic_set(&qedf->link_state, QEDF_LINK_DOWN); @@ -671,6 +673,24 @@ static int qedf_eh_host_reset(struct scsi_cmnd *sc_cmd) qedf->vlan_id = 0; queue_delayed_work(qedf->link_update_wq, &qedf->link_update, 0); +} + +/* Reset the host by gracefully logging out and then logging back in */ +static int qedf_eh_host_reset(struct scsi_cmnd *sc_cmd) +{ + struct fc_lport *lport; + struct qedf_ctx *qedf; + + lport = shost_priv(sc_cmd->device->host); + qedf = lport_priv(lport); + + if (atomic_read(&qedf->link_state) == QEDF_LINK_DOWN || + test_bit(QEDF_UNLOADING, &qedf->flags)) + return FAILED; + + QEDF_ERR(&(qedf->dbg_ctx), "HOST RESET Issued..."); + + qedf_ctx_soft_reset(lport); return SUCCESS; } @@ -688,7 +708,7 @@ static struct scsi_host_template qedf_host_template = { .module = THIS_MODULE, .name = QEDF_MODULE_NAME, .this_id = -1, - .cmd_per_lun = 3, + .cmd_per_lun = 32, .use_clustering = ENABLE_CLUSTERING, .max_sectors = 0xffff, .queuecommand = qedf_queuecommand, @@ -696,11 +716,13 @@ static struct scsi_host_template qedf_host_template = { .eh_abort_handler = qedf_eh_abort, .eh_device_reset_handler = qedf_eh_device_reset, /* lun reset */ .eh_target_reset_handler = qedf_eh_target_reset, /* target reset */ + .eh_bus_reset_handler = qedf_eh_bus_reset, .eh_host_reset_handler = qedf_eh_host_reset, .slave_configure = qedf_slave_configure, .dma_boundary = QED_HW_DMA_BOUNDARY, .sg_tablesize = QEDF_MAX_BDS_PER_CMD, .can_queue = FCOE_PARAMS_NUM_TASKS, + .change_queue_depth = scsi_change_queue_depth, }; static int qedf_get_paged_crc_eof(struct sk_buff *skb, int tlen) @@ -874,7 +896,7 @@ static int qedf_xmit(struct fc_lport *lport, struct fc_frame *fp) frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; cp = kmap_atomic(skb_frag_page(frag)) + frag->page_offset; } else { - cp = (struct fcoe_crc_eof *)skb_put(skb, tlen); + cp = skb_put(skb, tlen); } memset(cp, 0, sizeof(*cp)); @@ -950,25 +972,21 @@ static int qedf_alloc_sq(struct qedf_ctx *qedf, struct qedf_rport *fcport) sizeof(void *); fcport->sq_pbl_size = fcport->sq_pbl_size + QEDF_PAGE_SIZE; - fcport->sq = dma_alloc_coherent(&qedf->pdev->dev, fcport->sq_mem_size, - &fcport->sq_dma, GFP_KERNEL); + fcport->sq = dma_zalloc_coherent(&qedf->pdev->dev, + fcport->sq_mem_size, &fcport->sq_dma, GFP_KERNEL); if (!fcport->sq) { - QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate send " - "queue.\n"); + QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate send queue.\n"); rval = 1; goto out; } - memset(fcport->sq, 0, fcport->sq_mem_size); - fcport->sq_pbl = dma_alloc_coherent(&qedf->pdev->dev, + fcport->sq_pbl = dma_zalloc_coherent(&qedf->pdev->dev, fcport->sq_pbl_size, &fcport->sq_pbl_dma, GFP_KERNEL); if (!fcport->sq_pbl) { - QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate send " - "queue PBL.\n"); + QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate send queue PBL.\n"); rval = 1; goto out_free_sq; } - memset(fcport->sq_pbl, 0, fcport->sq_pbl_size); /* Create PBL */ num_pages = fcport->sq_mem_size / QEDF_PAGE_SIZE; @@ -1334,6 +1352,59 @@ static void qedf_fcoe_ctlr_setup(struct qedf_ctx *qedf) ether_addr_copy(qedf->ctlr.ctl_src_addr, qedf->mac); } +static void qedf_setup_fdmi(struct qedf_ctx *qedf) +{ + struct fc_lport *lport = qedf->lport; + struct fc_host_attrs *fc_host = shost_to_fc_host(lport->host); + u8 buf[8]; + int i, pos; + + /* + * fdmi_enabled needs to be set for libfc to execute FDMI registration. + */ + lport->fdmi_enabled = 1; + + /* + * Setup the necessary fc_host attributes to that will be used to fill + * in the FDMI information. + */ + + /* Get the PCI-e Device Serial Number Capability */ + pos = pci_find_ext_capability(qedf->pdev, PCI_EXT_CAP_ID_DSN); + if (pos) { + pos += 4; + for (i = 0; i < 8; i++) + pci_read_config_byte(qedf->pdev, pos + i, &buf[i]); + + snprintf(fc_host->serial_number, + sizeof(fc_host->serial_number), + "%02X%02X%02X%02X%02X%02X%02X%02X", + buf[7], buf[6], buf[5], buf[4], + buf[3], buf[2], buf[1], buf[0]); + } else + snprintf(fc_host->serial_number, + sizeof(fc_host->serial_number), "Unknown"); + + snprintf(fc_host->manufacturer, + sizeof(fc_host->manufacturer), "%s", "Cavium Inc."); + + snprintf(fc_host->model, sizeof(fc_host->model), "%s", "QL41000"); + + snprintf(fc_host->model_description, sizeof(fc_host->model_description), + "%s", "QLogic FastLinQ QL41000 Series 10/25/40/50GGbE Controller" + "(FCoE)"); + + snprintf(fc_host->hardware_version, sizeof(fc_host->hardware_version), + "Rev %d", qedf->pdev->revision); + + snprintf(fc_host->driver_version, sizeof(fc_host->driver_version), + "%s", QEDF_VERSION); + + snprintf(fc_host->firmware_version, sizeof(fc_host->firmware_version), + "%d.%d.%d.%d", FW_MAJOR_VERSION, FW_MINOR_VERSION, + FW_REVISION_VERSION, FW_ENGINEERING_VERSION); +} + static int qedf_lport_setup(struct qedf_ctx *qedf) { struct fc_lport *lport = qedf->lport; @@ -1377,6 +1448,8 @@ static int qedf_lport_setup(struct qedf_ctx *qedf) snprintf(fc_host_symbolic_name(lport->host), 256, "QLogic %s v%s", QEDF_MODULE_NAME, QEDF_VERSION); + qedf_setup_fdmi(qedf); + return 0; } @@ -1613,8 +1686,7 @@ static int qedf_fcoe_reset(struct Scsi_Host *shost) { struct fc_lport *lport = shost_priv(shost); - fc_fabric_logoff(lport); - fc_fabric_login(lport); + qedf_ctx_soft_reset(lport); return 0; } @@ -1979,6 +2051,8 @@ static int qedf_setup_int(struct qedf_ctx *qedf) * Learn interrupt configuration */ rc = qed_ops->common->set_fp_int(qedf->cdev, num_online_cpus()); + if (rc <= 0) + return 0; rc = qed_ops->common->get_fp_int(qedf->cdev, &qedf->int_info); if (rc) @@ -2011,6 +2085,8 @@ static void qedf_recv_frame(struct qedf_ctx *qedf, u8 *dest_mac = NULL; struct fcoe_hdr *hp; struct qedf_rport *fcport; + struct fc_lport *vn_port; + u32 f_ctl; lport = qedf->lport; if (lport == NULL || lport->state == LPORT_ST_DISABLED) { @@ -2047,6 +2123,10 @@ static void qedf_recv_frame(struct qedf_ctx *qedf, fh = fc_frame_header_get(fp); + /* + * Invalid frame filters. + */ + if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && fh->fh_type == FC_TYPE_FCP) { /* Drop FCP data. We dont this in L2 path */ @@ -2072,6 +2152,45 @@ static void qedf_recv_frame(struct qedf_ctx *qedf, return; } + if (ntoh24(&dest_mac[3]) != ntoh24(fh->fh_d_id)) { + QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, + "FC frame d_id mismatch with MAC %pM.\n", dest_mac); + return; + } + + if (qedf->ctlr.state) { + if (!ether_addr_equal(mac, qedf->ctlr.dest_addr)) { + QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, + "Wrong source address: mac:%pM dest_addr:%pM.\n", + mac, qedf->ctlr.dest_addr); + kfree_skb(skb); + return; + } + } + + vn_port = fc_vport_id_lookup(lport, ntoh24(fh->fh_d_id)); + + /* + * If the destination ID from the frame header does not match what we + * have on record for lport and the search for a NPIV port came up + * empty then this is not addressed to our port so simply drop it. + */ + if (lport->port_id != ntoh24(fh->fh_d_id) && !vn_port) { + QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, + "Dropping frame due to destination mismatch: lport->port_id=%x fh->d_id=%x.\n", + lport->port_id, ntoh24(fh->fh_d_id)); + kfree_skb(skb); + return; + } + + f_ctl = ntoh24(fh->fh_f_ctl); + if ((fh->fh_type == FC_TYPE_BLS) && (f_ctl & FC_FC_SEQ_CTX) && + (f_ctl & FC_FC_EX_CTX)) { + /* Drop incoming ABTS response that has both SEQ/EX CTX set */ + kfree_skb(skb); + return; + } + /* * If a connection is uploading, drop incoming FCoE frames as there * is a small window where we could try to return a frame while libfc @@ -2117,7 +2236,7 @@ static void qedf_ll2_process_skb(struct work_struct *work) /* Undo VLAN encapsulation */ if (eh->h_proto == htons(ETH_P_8021Q)) { memmove((u8 *)eh + VLAN_HLEN, eh, ETH_ALEN * 2); - eh = (struct ethhdr *)skb_pull(skb, VLAN_HLEN); + eh = skb_pull(skb, VLAN_HLEN); skb_reset_mac_header(skb); } @@ -2474,14 +2593,12 @@ static int qedf_alloc_bdq(struct qedf_ctx *qedf) } /* Allocate list of PBL pages */ - qedf->bdq_pbl_list = dma_alloc_coherent(&qedf->pdev->dev, + qedf->bdq_pbl_list = dma_zalloc_coherent(&qedf->pdev->dev, QEDF_PAGE_SIZE, &qedf->bdq_pbl_list_dma, GFP_KERNEL); if (!qedf->bdq_pbl_list) { - QEDF_ERR(&(qedf->dbg_ctx), "Could not allocate list of PBL " - "pages.\n"); + QEDF_ERR(&(qedf->dbg_ctx), "Could not allocate list of PBL pages.\n"); return -ENOMEM; } - memset(qedf->bdq_pbl_list, 0, QEDF_PAGE_SIZE); /* * Now populate PBL list with pages that contain pointers to the @@ -2548,8 +2665,9 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf) qedf->global_queues[i] = kzalloc(sizeof(struct global_queue), GFP_KERNEL); if (!qedf->global_queues[i]) { - QEDF_WARN(&(qedf->dbg_ctx), "Unable to allocation " + QEDF_WARN(&(qedf->dbg_ctx), "Unable to allocate " "global queue %d.\n", i); + status = -ENOMEM; goto mem_alloc_failure; } @@ -2565,32 +2683,26 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf) ALIGN(qedf->global_queues[i]->cq_pbl_size, QEDF_PAGE_SIZE); qedf->global_queues[i]->cq = - dma_alloc_coherent(&qedf->pdev->dev, + dma_zalloc_coherent(&qedf->pdev->dev, qedf->global_queues[i]->cq_mem_size, &qedf->global_queues[i]->cq_dma, GFP_KERNEL); if (!qedf->global_queues[i]->cq) { - QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate " - "cq.\n"); + QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate cq.\n"); status = -ENOMEM; goto mem_alloc_failure; } - memset(qedf->global_queues[i]->cq, 0, - qedf->global_queues[i]->cq_mem_size); qedf->global_queues[i]->cq_pbl = - dma_alloc_coherent(&qedf->pdev->dev, + dma_zalloc_coherent(&qedf->pdev->dev, qedf->global_queues[i]->cq_pbl_size, &qedf->global_queues[i]->cq_pbl_dma, GFP_KERNEL); if (!qedf->global_queues[i]->cq_pbl) { - QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate " - "cq PBL.\n"); + QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate cq PBL.\n"); status = -ENOMEM; goto mem_alloc_failure; } - memset(qedf->global_queues[i]->cq_pbl, 0, - qedf->global_queues[i]->cq_pbl_size); /* Create PBL */ num_pages = qedf->global_queues[i]->cq_mem_size / @@ -2683,8 +2795,7 @@ static int qedf_set_fcoe_pf_param(struct qedf_ctx *qedf) cq_mem_size = ALIGN(cq_mem_size, QEDF_PAGE_SIZE); cq_num_entries = cq_mem_size / sizeof(struct fcoe_cqe); - memset(&(qedf->pf_params), 0, - sizeof(qedf->pf_params)); + memset(&(qedf->pf_params), 0, sizeof(qedf->pf_params)); /* Setup the value for fcoe PF */ qedf->pf_params.fcoe_pf_params.num_cons = QEDF_MAX_SESSIONS; @@ -2954,7 +3065,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode) "WWPN=%016llx.\n", qedf->wwnn, qedf->wwpn); sprintf(host_buf, "host_%d", host->host_no); - qed_ops->common->set_id(qedf->cdev, host_buf, QEDF_VERSION); + qed_ops->common->set_name(qedf->cdev, host_buf); /* Set xid max values */ diff --git a/drivers/scsi/qedf/qedf_version.h b/drivers/scsi/qedf/qedf_version.h index 4ae5f537a440..6fa442061c32 100644 --- a/drivers/scsi/qedf/qedf_version.h +++ b/drivers/scsi/qedf/qedf_version.h @@ -1,15 +1,15 @@ /* * QLogic FCoE Offload Driver - * Copyright (c) 2016 Cavium Inc. + * Copyright (c) 2016-2017 Cavium Inc. * * This software is available under the terms of the GNU General Public License * (GPL) Version 2, available from the file COPYING in the main directory of * this source tree. */ -#define QEDF_VERSION "8.10.7.0" +#define QEDF_VERSION "8.18.22.0" #define QEDF_DRIVER_MAJOR_VER 8 -#define QEDF_DRIVER_MINOR_VER 10 -#define QEDF_DRIVER_REV_VER 7 +#define QEDF_DRIVER_MINOR_VER 18 +#define QEDF_DRIVER_REV_VER 22 #define QEDF_DRIVER_ENG_VER 0 |