diff options
Diffstat (limited to 'drivers/scsi/qedf/qedf_main.c')
-rw-r--r-- | drivers/scsi/qedf/qedf_main.c | 178 |
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(¶ms, 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); |