summaryrefslogtreecommitdiff
path: root/drivers/scsi/qedf/qedf_main.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-09-21 10:50:15 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2019-09-21 10:50:15 -0700
commit10fd71780f7d155f4e35fecfad0ebd4a725a244b (patch)
treeb88976120fd8f620669ed239842ea26ecc2c5e52 /drivers/scsi/qedf/qedf_main.c
parent3e414b5bd28f965fb39b9e9419d877df0cf3111a (diff)
parente74006edd0d42b45ff37ae4ae13c614cfa30056b (diff)
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley: "This is mostly update of the usual drivers: qla2xxx, ufs, smartpqi, lpfc, hisi_sas, qedf, mpt3sas; plus a whole load of minor updates. The only core change this time around is the addition of request batching for virtio. Since batching requires an additional flag to use, it should be invisible to the rest of the drivers" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (264 commits) scsi: hisi_sas: Fix the conflict between device gone and host reset scsi: hisi_sas: Add BIST support for phy loopback scsi: hisi_sas: Add hisi_sas_debugfs_alloc() to centralise allocation scsi: hisi_sas: Remove some unused function arguments scsi: hisi_sas: Remove redundant work declaration scsi: hisi_sas: Remove hisi_sas_hw.slot_complete scsi: hisi_sas: Assign NCQ tag for all NCQ commands scsi: hisi_sas: Update all the registers after suspend and resume scsi: hisi_sas: Retry 3 times TMF IO for SAS disks when init device scsi: hisi_sas: Remove sleep after issue phy reset if sas_smp_phy_control() fails scsi: hisi_sas: Directly return when running I_T_nexus reset if phy disabled scsi: hisi_sas: Use true/false as input parameter of sas_phy_reset() scsi: hisi_sas: add debugfs auto-trigger for internal abort time out scsi: virtio_scsi: unplug LUNs when events missed scsi: scsi_dh_rdac: zero cdb in send_mode_select() scsi: fcoe: fix null-ptr-deref Read in fc_release_transport scsi: ufs-hisi: use devm_platform_ioremap_resource() to simplify code scsi: ufshcd: use devm_platform_ioremap_resource() to simplify code scsi: hisi_sas: use devm_platform_ioremap_resource() to simplify code scsi: ufs: Use kmemdup in ufshcd_read_string_desc() ...
Diffstat (limited to 'drivers/scsi/qedf/qedf_main.c')
-rw-r--r--drivers/scsi/qedf/qedf_main.c178
1 files changed, 113 insertions, 65 deletions
diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index 42542720962f..1659d35cd37b 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -27,6 +27,7 @@ const struct qed_fcoe_ops *qed_ops;
static int qedf_probe(struct pci_dev *pdev, const struct pci_device_id *id);
static void qedf_remove(struct pci_dev *pdev);
+static void qedf_shutdown(struct pci_dev *pdev);
/*
* Driver module parameters.
@@ -110,16 +111,18 @@ static struct kmem_cache *qedf_io_work_cache;
void qedf_set_vlan_id(struct qedf_ctx *qedf, int vlan_id)
{
- qedf->vlan_id = vlan_id;
- qedf->vlan_id |= qedf->prio << VLAN_PRIO_SHIFT;
- QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "Setting vlan_id=%04x "
- "prio=%d.\n", vlan_id, qedf->prio);
+ int vlan_id_tmp = 0;
+
+ vlan_id_tmp = vlan_id | (qedf->prio << VLAN_PRIO_SHIFT);
+ qedf->vlan_id = vlan_id_tmp;
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
+ "Setting vlan_id=0x%04x prio=%d.\n",
+ vlan_id_tmp, qedf->prio);
}
/* Returns true if we have a valid vlan, false otherwise */
static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf)
{
- int rc;
while (qedf->fipvlan_retries--) {
/* This is to catch if link goes down during fipvlan retries */
@@ -128,20 +131,25 @@ static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf)
return false;
}
- if (qedf->vlan_id > 0)
+ if (test_bit(QEDF_UNLOADING, &qedf->flags)) {
+ QEDF_ERR(&qedf->dbg_ctx, "Driver unloading.\n");
+ return false;
+ }
+
+ if (qedf->vlan_id > 0) {
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
+ "vlan = 0x%x already set, calling ctlr_link_up.\n",
+ qedf->vlan_id);
+ if (atomic_read(&qedf->link_state) == QEDF_LINK_UP)
+ fcoe_ctlr_link_up(&qedf->ctlr);
return true;
+ }
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
"Retry %d.\n", qedf->fipvlan_retries);
init_completion(&qedf->fipvlan_compl);
qedf_fcoe_send_vlan_req(qedf);
- rc = wait_for_completion_timeout(&qedf->fipvlan_compl,
- 1 * HZ);
- if (rc > 0 &&
- (atomic_read(&qedf->link_state) == QEDF_LINK_UP)) {
- fcoe_ctlr_link_up(&qedf->ctlr);
- return true;
- }
+ wait_for_completion_timeout(&qedf->fipvlan_compl, 1 * HZ);
}
return false;
@@ -162,6 +170,8 @@ static void qedf_handle_link_update(struct work_struct *work)
return;
if (atomic_read(&qedf->link_state) != QEDF_LINK_UP) {
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
+ "Link is down, resetting vlan_id.\n");
qedf->vlan_id = 0;
return;
}
@@ -311,8 +321,10 @@ int qedf_send_flogi(struct qedf_ctx *qedf)
lport = qedf->lport;
- if (!lport->tt.elsct_send)
+ if (!lport->tt.elsct_send) {
+ QEDF_ERR(&qedf->dbg_ctx, "tt.elsct_send not set.\n");
return -EINVAL;
+ }
fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
if (!fp) {
@@ -330,11 +342,6 @@ int qedf_send_flogi(struct qedf_ctx *qedf)
return 0;
}
-struct qedf_tmp_rdata_item {
- struct fc_rport_priv *rdata;
- struct list_head list;
-};
-
/*
* This function is called if link_down_tmo is in use. If we get a link up and
* link_down_tmo has not expired then use just FLOGI/ADISC to recover our
@@ -344,9 +351,8 @@ static void qedf_link_recovery(struct work_struct *work)
{
struct qedf_ctx *qedf =
container_of(work, struct qedf_ctx, link_recovery.work);
- struct qedf_rport *fcport;
+ struct fc_lport *lport = qedf->lport;
struct fc_rport_priv *rdata;
- struct qedf_tmp_rdata_item *rdata_item, *tmp_rdata_item;
bool rc;
int retries = 30;
int rval, i;
@@ -413,33 +419,14 @@ static void qedf_link_recovery(struct work_struct *work)
* Call lport->tt.rport_login which will cause libfc to send an
* ADISC since the rport is in state ready.
*/
- rcu_read_lock();
- list_for_each_entry_rcu(fcport, &qedf->fcports, peers) {
- rdata = fcport->rdata;
- if (rdata == NULL)
- continue;
- rdata_item = kzalloc(sizeof(struct qedf_tmp_rdata_item),
- GFP_ATOMIC);
- if (!rdata_item)
- continue;
+ mutex_lock(&lport->disc.disc_mutex);
+ list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) {
if (kref_get_unless_zero(&rdata->kref)) {
- rdata_item->rdata = rdata;
- list_add(&rdata_item->list, &rdata_login_list);
- } else
- kfree(rdata_item);
- }
- rcu_read_unlock();
- /*
- * Do the fc_rport_login outside of the rcu lock so we don't take a
- * mutex in an atomic context.
- */
- list_for_each_entry_safe(rdata_item, tmp_rdata_item, &rdata_login_list,
- list) {
- list_del(&rdata_item->list);
- fc_rport_login(rdata_item->rdata);
- kref_put(&rdata_item->rdata->kref, fc_rport_destroy);
- kfree(rdata_item);
+ fc_rport_login(rdata);
+ kref_put(&rdata->kref, fc_rport_destroy);
+ }
}
+ mutex_unlock(&lport->disc.disc_mutex);
}
static void qedf_update_link_speed(struct qedf_ctx *qedf,
@@ -467,6 +454,9 @@ static void qedf_update_link_speed(struct qedf_ctx *qedf,
case 100000:
lport->link_speed = FC_PORTSPEED_100GBIT;
break;
+ case 20000:
+ lport->link_speed = FC_PORTSPEED_20GBIT;
+ break;
default:
lport->link_speed = FC_PORTSPEED_UNKNOWN;
break;
@@ -476,16 +466,40 @@ static void qedf_update_link_speed(struct qedf_ctx *qedf,
* Set supported link speed by querying the supported
* capabilities of the link.
*/
- if (link->supported_caps & SUPPORTED_10000baseKR_Full)
+ if ((link->supported_caps & QED_LM_10000baseT_Full_BIT) ||
+ (link->supported_caps & QED_LM_10000baseKX4_Full_BIT) ||
+ (link->supported_caps & QED_LM_10000baseR_FEC_BIT) ||
+ (link->supported_caps & QED_LM_10000baseCR_Full_BIT) ||
+ (link->supported_caps & QED_LM_10000baseSR_Full_BIT) ||
+ (link->supported_caps & QED_LM_10000baseLR_Full_BIT) ||
+ (link->supported_caps & QED_LM_10000baseLRM_Full_BIT) ||
+ (link->supported_caps & QED_LM_10000baseKR_Full_BIT)) {
lport->link_supported_speeds |= FC_PORTSPEED_10GBIT;
- if (link->supported_caps & SUPPORTED_25000baseKR_Full)
+ }
+ if ((link->supported_caps & QED_LM_25000baseKR_Full_BIT) ||
+ (link->supported_caps & QED_LM_25000baseCR_Full_BIT) ||
+ (link->supported_caps & QED_LM_25000baseSR_Full_BIT)) {
lport->link_supported_speeds |= FC_PORTSPEED_25GBIT;
- if (link->supported_caps & SUPPORTED_40000baseLR4_Full)
+ }
+ if ((link->supported_caps & QED_LM_40000baseLR4_Full_BIT) ||
+ (link->supported_caps & QED_LM_40000baseKR4_Full_BIT) ||
+ (link->supported_caps & QED_LM_40000baseCR4_Full_BIT) ||
+ (link->supported_caps & QED_LM_40000baseSR4_Full_BIT)) {
lport->link_supported_speeds |= FC_PORTSPEED_40GBIT;
- if (link->supported_caps & SUPPORTED_50000baseKR2_Full)
+ }
+ if ((link->supported_caps & QED_LM_50000baseKR2_Full_BIT) ||
+ (link->supported_caps & QED_LM_50000baseCR2_Full_BIT) ||
+ (link->supported_caps & QED_LM_50000baseSR2_Full_BIT)) {
lport->link_supported_speeds |= FC_PORTSPEED_50GBIT;
- if (link->supported_caps & SUPPORTED_100000baseKR4_Full)
+ }
+ if ((link->supported_caps & QED_LM_100000baseKR4_Full_BIT) ||
+ (link->supported_caps & QED_LM_100000baseSR4_Full_BIT) ||
+ (link->supported_caps & QED_LM_100000baseCR4_Full_BIT) ||
+ (link->supported_caps & QED_LM_100000baseLR4_ER4_Full_BIT)) {
lport->link_supported_speeds |= FC_PORTSPEED_100GBIT;
+ }
+ if (link->supported_caps & QED_LM_20000baseKR2_Full_BIT)
+ lport->link_supported_speeds |= FC_PORTSPEED_20GBIT;
fc_host_supported_speeds(lport->host) = lport->link_supported_speeds;
}
@@ -493,6 +507,16 @@ static void qedf_link_update(void *dev, struct qed_link_output *link)
{
struct qedf_ctx *qedf = (struct qedf_ctx *)dev;
+ /*
+ * Prevent race where we're removing the module and we get link update
+ * for qed.
+ */
+ if (test_bit(QEDF_UNLOADING, &qedf->flags)) {
+ QEDF_ERR(&qedf->dbg_ctx,
+ "Ignore link update, driver getting unload.\n");
+ return;
+ }
+
if (link->link_up) {
if (atomic_read(&qedf->link_state) == QEDF_LINK_UP) {
QEDF_INFO((&qedf->dbg_ctx), QEDF_LOG_DISC,
@@ -2340,12 +2364,14 @@ static void qedf_recv_frame(struct qedf_ctx *qedf,
fr_dev(fp) = lport;
fr_sof(fp) = hp->fcoe_sof;
if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) {
+ QEDF_INFO(NULL, QEDF_LOG_LL2, "skb_copy_bits failed.\n");
kfree_skb(skb);
return;
}
fr_eof(fp) = crc_eof.fcoe_eof;
fr_crc(fp) = crc_eof.fcoe_crc32;
if (pskb_trim(skb, fr_len)) {
+ QEDF_INFO(NULL, QEDF_LOG_LL2, "pskb_trim failed.\n");
kfree_skb(skb);
return;
}
@@ -2406,9 +2432,9 @@ static void qedf_recv_frame(struct qedf_ctx *qedf,
* 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));
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_LL2,
+ "Dropping frame due to destination mismatch: lport->port_id=0x%x fh->d_id=0x%x.\n",
+ lport->port_id, ntoh24(fh->fh_d_id));
kfree_skb(skb);
return;
}
@@ -2417,6 +2443,8 @@ static void qedf_recv_frame(struct qedf_ctx *qedf,
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 */
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_LL2,
+ "Dropping ABTS response as both SEQ/EX CTX set.\n");
kfree_skb(skb);
return;
}
@@ -2560,8 +2588,9 @@ static int qedf_alloc_and_init_sb(struct qedf_ctx *qedf,
sizeof(struct status_block_e4), &sb_phys, GFP_KERNEL);
if (!sb_virt) {
- QEDF_ERR(&(qedf->dbg_ctx), "Status block allocation failed "
- "for id = %d.\n", sb_id);
+ QEDF_ERR(&qedf->dbg_ctx,
+ "Status block allocation failed for id = %d.\n",
+ sb_id);
return -ENOMEM;
}
@@ -2569,8 +2598,9 @@ static int qedf_alloc_and_init_sb(struct qedf_ctx *qedf,
sb_id, QED_SB_TYPE_STORAGE);
if (ret) {
- QEDF_ERR(&(qedf->dbg_ctx), "Status block initialization "
- "failed for id = %d.\n", sb_id);
+ QEDF_ERR(&qedf->dbg_ctx,
+ "Status block initialization failed (0x%x) for id = %d.\n",
+ ret, sb_id);
return ret;
}
@@ -2654,13 +2684,18 @@ void qedf_process_cqe(struct qedf_ctx *qedf, struct fcoe_cqe *cqe)
io_req = &qedf->cmd_mgr->cmds[xid];
/* Completion not for a valid I/O anymore so just return */
- if (!io_req)
+ if (!io_req) {
+ QEDF_ERR(&qedf->dbg_ctx,
+ "io_req is NULL for xid=0x%x.\n", xid);
return;
+ }
fcport = io_req->fcport;
if (fcport == NULL) {
- QEDF_ERR(&(qedf->dbg_ctx), "fcport is NULL.\n");
+ QEDF_ERR(&qedf->dbg_ctx,
+ "fcport is NULL for xid=0x%x io_req=%p.\n",
+ xid, io_req);
return;
}
@@ -2669,7 +2704,8 @@ void qedf_process_cqe(struct qedf_ctx *qedf, struct fcoe_cqe *cqe)
* isn't valid and shouldn't be taken. We should just return.
*/
if (!test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags)) {
- QEDF_ERR(&(qedf->dbg_ctx), "Session not offloaded yet.\n");
+ QEDF_ERR(&qedf->dbg_ctx,
+ "Session not offloaded yet, fcport = %p.\n", fcport);
return;
}
@@ -2881,6 +2917,7 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf)
*/
if (!qedf->p_cpuq) {
status = 1;
+ QEDF_ERR(&qedf->dbg_ctx, "p_cpuq is NULL.\n");
goto mem_alloc_failure;
}
@@ -2896,8 +2933,10 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf)
/* Allocate DMA coherent buffers for BDQ */
rc = qedf_alloc_bdq(qedf);
- if (rc)
+ if (rc) {
+ QEDF_ERR(&qedf->dbg_ctx, "Unable to allocate bdq.\n");
goto mem_alloc_failure;
+ }
/* Allocate a CQ and an associated PBL for each MSI-X vector */
for (i = 0; i < qedf->num_queues; i++) {
@@ -3107,6 +3146,7 @@ static struct pci_driver qedf_pci_driver = {
.id_table = qedf_pci_tbl,
.probe = qedf_probe,
.remove = qedf_remove,
+ .shutdown = qedf_shutdown,
};
static int __qedf_probe(struct pci_dev *pdev, int mode)
@@ -3209,6 +3249,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
qed_params.is_vf = is_vf;
qedf->cdev = qed_ops->common->probe(pdev, &qed_params);
if (!qedf->cdev) {
+ QEDF_ERR(&qedf->dbg_ctx, "common probe failed.\n");
rc = -ENODEV;
goto err1;
}
@@ -3277,8 +3318,10 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
/* Setup interrupts */
rc = qedf_setup_int(qedf);
- if (rc)
+ if (rc) {
+ QEDF_ERR(&qedf->dbg_ctx, "Setup interrupts failed.\n");
goto err3;
+ }
rc = qed_ops->start(qedf->cdev, &qedf->tasks);
if (rc) {
@@ -3360,7 +3403,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
}
memset(&params, 0, sizeof(params));
- params.mtu = 9000;
+ params.mtu = QEDF_LL2_BUF_SIZE;
ether_addr_copy(params.ll2_mac_address, qedf->mac);
/* Start LL2 processing thread */
@@ -3719,6 +3762,11 @@ void qedf_get_protocol_tlv_data(void *dev, void *data)
fcoe->scsi_tsk_full = qedf->task_set_fulls;
}
+static void qedf_shutdown(struct pci_dev *pdev)
+{
+ __qedf_remove(pdev, QEDF_MODE_NORMAL);
+}
+
/* Generic TLV data callback */
void qedf_get_generic_tlv_data(void *dev, struct qed_generic_tlvs *data)
{
@@ -3845,7 +3893,7 @@ static void __exit qedf_cleanup(void)
}
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("QLogic QEDF 25/40/50/100Gb FCoE Driver");
+MODULE_DESCRIPTION("QLogic FastLinQ 4xxxx FCoE Module");
MODULE_AUTHOR("QLogic Corporation");
MODULE_VERSION(QEDF_VERSION);
module_init(qedf_init);