18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * QLogic FCoE Offload Driver 48c2ecf20Sopenharmony_ci * Copyright (c) 2016-2018 Cavium Inc. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci#include "qedf.h" 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ciinline bool qedf_is_vport(struct qedf_ctx *qedf) 98c2ecf20Sopenharmony_ci{ 108c2ecf20Sopenharmony_ci return qedf->lport->vport != NULL; 118c2ecf20Sopenharmony_ci} 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* Get base qedf for physical port from vport */ 148c2ecf20Sopenharmony_cistatic struct qedf_ctx *qedf_get_base_qedf(struct qedf_ctx *qedf) 158c2ecf20Sopenharmony_ci{ 168c2ecf20Sopenharmony_ci struct fc_lport *lport; 178c2ecf20Sopenharmony_ci struct fc_lport *base_lport; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci if (!(qedf_is_vport(qedf))) 208c2ecf20Sopenharmony_ci return NULL; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci lport = qedf->lport; 238c2ecf20Sopenharmony_ci base_lport = shost_priv(vport_to_shost(lport->vport)); 248c2ecf20Sopenharmony_ci return lport_priv(base_lport); 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic ssize_t 288c2ecf20Sopenharmony_ciqedf_fcoe_mac_show(struct device *dev, 298c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci struct fc_lport *lport = shost_priv(class_to_shost(dev)); 328c2ecf20Sopenharmony_ci u32 port_id; 338c2ecf20Sopenharmony_ci u8 lport_src_id[3]; 348c2ecf20Sopenharmony_ci u8 fcoe_mac[6]; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci port_id = fc_host_port_id(lport->host); 378c2ecf20Sopenharmony_ci lport_src_id[2] = (port_id & 0x000000FF); 388c2ecf20Sopenharmony_ci lport_src_id[1] = (port_id & 0x0000FF00) >> 8; 398c2ecf20Sopenharmony_ci lport_src_id[0] = (port_id & 0x00FF0000) >> 16; 408c2ecf20Sopenharmony_ci fc_fcoe_set_mac(fcoe_mac, lport_src_id); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%pM\n", fcoe_mac); 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic ssize_t 468c2ecf20Sopenharmony_ciqedf_fka_period_show(struct device *dev, 478c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci struct fc_lport *lport = shost_priv(class_to_shost(dev)); 508c2ecf20Sopenharmony_ci struct qedf_ctx *qedf = lport_priv(lport); 518c2ecf20Sopenharmony_ci int fka_period = -1; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci if (qedf_is_vport(qedf)) 548c2ecf20Sopenharmony_ci qedf = qedf_get_base_qedf(qedf); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci if (qedf->ctlr.sel_fcf) 578c2ecf20Sopenharmony_ci fka_period = qedf->ctlr.sel_fcf->fka_period; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", fka_period); 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic DEVICE_ATTR(fcoe_mac, S_IRUGO, qedf_fcoe_mac_show, NULL); 638c2ecf20Sopenharmony_cistatic DEVICE_ATTR(fka_period, S_IRUGO, qedf_fka_period_show, NULL); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistruct device_attribute *qedf_host_attrs[] = { 668c2ecf20Sopenharmony_ci &dev_attr_fcoe_mac, 678c2ecf20Sopenharmony_ci &dev_attr_fka_period, 688c2ecf20Sopenharmony_ci NULL, 698c2ecf20Sopenharmony_ci}; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ciextern const struct qed_fcoe_ops *qed_ops; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_civoid qedf_capture_grc_dump(struct qedf_ctx *qedf) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci struct qedf_ctx *base_qedf; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci /* Make sure we use the base qedf to take the GRC dump */ 788c2ecf20Sopenharmony_ci if (qedf_is_vport(qedf)) 798c2ecf20Sopenharmony_ci base_qedf = qedf_get_base_qedf(qedf); 808c2ecf20Sopenharmony_ci else 818c2ecf20Sopenharmony_ci base_qedf = qedf; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci if (test_bit(QEDF_GRCDUMP_CAPTURE, &base_qedf->flags)) { 848c2ecf20Sopenharmony_ci QEDF_INFO(&(base_qedf->dbg_ctx), QEDF_LOG_INFO, 858c2ecf20Sopenharmony_ci "GRC Dump already captured.\n"); 868c2ecf20Sopenharmony_ci return; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci qedf_get_grc_dump(base_qedf->cdev, qed_ops->common, 918c2ecf20Sopenharmony_ci &base_qedf->grcdump, &base_qedf->grcdump_size); 928c2ecf20Sopenharmony_ci QEDF_ERR(&(base_qedf->dbg_ctx), "GRC Dump captured.\n"); 938c2ecf20Sopenharmony_ci set_bit(QEDF_GRCDUMP_CAPTURE, &base_qedf->flags); 948c2ecf20Sopenharmony_ci qedf_uevent_emit(base_qedf->lport->host, QEDF_UEVENT_CODE_GRCDUMP, 958c2ecf20Sopenharmony_ci NULL); 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistatic ssize_t 998c2ecf20Sopenharmony_ciqedf_sysfs_read_grcdump(struct file *filep, struct kobject *kobj, 1008c2ecf20Sopenharmony_ci struct bin_attribute *ba, char *buf, loff_t off, 1018c2ecf20Sopenharmony_ci size_t count) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci ssize_t ret = 0; 1048c2ecf20Sopenharmony_ci struct fc_lport *lport = shost_priv(dev_to_shost(container_of(kobj, 1058c2ecf20Sopenharmony_ci struct device, kobj))); 1068c2ecf20Sopenharmony_ci struct qedf_ctx *qedf = lport_priv(lport); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci if (test_bit(QEDF_GRCDUMP_CAPTURE, &qedf->flags)) { 1098c2ecf20Sopenharmony_ci ret = memory_read_from_buffer(buf, count, &off, 1108c2ecf20Sopenharmony_ci qedf->grcdump, qedf->grcdump_size); 1118c2ecf20Sopenharmony_ci } else { 1128c2ecf20Sopenharmony_ci QEDF_ERR(&(qedf->dbg_ctx), "GRC Dump not captured!\n"); 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci return ret; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic ssize_t 1198c2ecf20Sopenharmony_ciqedf_sysfs_write_grcdump(struct file *filep, struct kobject *kobj, 1208c2ecf20Sopenharmony_ci struct bin_attribute *ba, char *buf, loff_t off, 1218c2ecf20Sopenharmony_ci size_t count) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci struct fc_lport *lport = NULL; 1248c2ecf20Sopenharmony_ci struct qedf_ctx *qedf = NULL; 1258c2ecf20Sopenharmony_ci long reading; 1268c2ecf20Sopenharmony_ci int ret = 0; 1278c2ecf20Sopenharmony_ci char msg[40]; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci if (off != 0) 1308c2ecf20Sopenharmony_ci return ret; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci lport = shost_priv(dev_to_shost(container_of(kobj, 1348c2ecf20Sopenharmony_ci struct device, kobj))); 1358c2ecf20Sopenharmony_ci qedf = lport_priv(lport); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci buf[1] = 0; 1388c2ecf20Sopenharmony_ci ret = kstrtol(buf, 10, &reading); 1398c2ecf20Sopenharmony_ci if (ret) { 1408c2ecf20Sopenharmony_ci QEDF_ERR(&(qedf->dbg_ctx), "Invalid input, err(%d)\n", ret); 1418c2ecf20Sopenharmony_ci return ret; 1428c2ecf20Sopenharmony_ci } 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci memset(msg, 0, sizeof(msg)); 1458c2ecf20Sopenharmony_ci switch (reading) { 1468c2ecf20Sopenharmony_ci case 0: 1478c2ecf20Sopenharmony_ci memset(qedf->grcdump, 0, qedf->grcdump_size); 1488c2ecf20Sopenharmony_ci clear_bit(QEDF_GRCDUMP_CAPTURE, &qedf->flags); 1498c2ecf20Sopenharmony_ci break; 1508c2ecf20Sopenharmony_ci case 1: 1518c2ecf20Sopenharmony_ci qedf_capture_grc_dump(qedf); 1528c2ecf20Sopenharmony_ci break; 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci return count; 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic struct bin_attribute sysfs_grcdump_attr = { 1598c2ecf20Sopenharmony_ci .attr = { 1608c2ecf20Sopenharmony_ci .name = "grcdump", 1618c2ecf20Sopenharmony_ci .mode = S_IRUSR | S_IWUSR, 1628c2ecf20Sopenharmony_ci }, 1638c2ecf20Sopenharmony_ci .size = 0, 1648c2ecf20Sopenharmony_ci .read = qedf_sysfs_read_grcdump, 1658c2ecf20Sopenharmony_ci .write = qedf_sysfs_write_grcdump, 1668c2ecf20Sopenharmony_ci}; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic struct sysfs_bin_attrs bin_file_entries[] = { 1698c2ecf20Sopenharmony_ci {"grcdump", &sysfs_grcdump_attr}, 1708c2ecf20Sopenharmony_ci {NULL}, 1718c2ecf20Sopenharmony_ci}; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_civoid qedf_create_sysfs_ctx_attr(struct qedf_ctx *qedf) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci qedf_create_sysfs_attr(qedf->lport->host, bin_file_entries); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_civoid qedf_remove_sysfs_ctx_attr(struct qedf_ctx *qedf) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci qedf_remove_sysfs_attr(qedf->lport->host, bin_file_entries); 1818c2ecf20Sopenharmony_ci} 182