1 /* 2 * QLogic FCoE Offload Driver 3 * Copyright (c) 2016 Cavium Inc. 4 * 5 * This software is available under the terms of the GNU General Public License 6 * (GPL) Version 2, available from the file COPYING in the main directory of 7 * this source tree. 8 */ 9 #include "qedf.h" 10 11 static ssize_t 12 qedf_fcoe_mac_show(struct device *dev, 13 struct device_attribute *attr, char *buf) 14 { 15 struct fc_lport *lport = shost_priv(class_to_shost(dev)); 16 u32 port_id; 17 u8 lport_src_id[3]; 18 u8 fcoe_mac[6]; 19 20 port_id = fc_host_port_id(lport->host); 21 lport_src_id[2] = (port_id & 0x000000FF); 22 lport_src_id[1] = (port_id & 0x0000FF00) >> 8; 23 lport_src_id[0] = (port_id & 0x00FF0000) >> 16; 24 fc_fcoe_set_mac(fcoe_mac, lport_src_id); 25 26 return scnprintf(buf, PAGE_SIZE, "%pM\n", fcoe_mac); 27 } 28 29 static DEVICE_ATTR(fcoe_mac, S_IRUGO, qedf_fcoe_mac_show, NULL); 30 31 struct device_attribute *qedf_host_attrs[] = { 32 &dev_attr_fcoe_mac, 33 NULL, 34 }; 35 36 extern const struct qed_fcoe_ops *qed_ops; 37 38 inline bool qedf_is_vport(struct qedf_ctx *qedf) 39 { 40 return (!(qedf->lport->vport == NULL)); 41 } 42 43 /* Get base qedf for physical port from vport */ 44 static struct qedf_ctx *qedf_get_base_qedf(struct qedf_ctx *qedf) 45 { 46 struct fc_lport *lport; 47 struct fc_lport *base_lport; 48 49 if (!(qedf_is_vport(qedf))) 50 return NULL; 51 52 lport = qedf->lport; 53 base_lport = shost_priv(vport_to_shost(lport->vport)); 54 return (struct qedf_ctx *)(lport_priv(base_lport)); 55 } 56 57 void qedf_capture_grc_dump(struct qedf_ctx *qedf) 58 { 59 struct qedf_ctx *base_qedf; 60 61 /* Make sure we use the base qedf to take the GRC dump */ 62 if (qedf_is_vport(qedf)) 63 base_qedf = qedf_get_base_qedf(qedf); 64 else 65 base_qedf = qedf; 66 67 if (test_bit(QEDF_GRCDUMP_CAPTURE, &base_qedf->flags)) { 68 QEDF_INFO(&(base_qedf->dbg_ctx), QEDF_LOG_INFO, 69 "GRC Dump already captured.\n"); 70 return; 71 } 72 73 74 qedf_get_grc_dump(base_qedf->cdev, qed_ops->common, 75 &base_qedf->grcdump, &base_qedf->grcdump_size); 76 QEDF_ERR(&(base_qedf->dbg_ctx), "GRC Dump captured.\n"); 77 set_bit(QEDF_GRCDUMP_CAPTURE, &base_qedf->flags); 78 qedf_uevent_emit(base_qedf->lport->host, QEDF_UEVENT_CODE_GRCDUMP, 79 NULL); 80 } 81 82 static ssize_t 83 qedf_sysfs_read_grcdump(struct file *filep, struct kobject *kobj, 84 struct bin_attribute *ba, char *buf, loff_t off, 85 size_t count) 86 { 87 ssize_t ret = 0; 88 struct fc_lport *lport = shost_priv(dev_to_shost(container_of(kobj, 89 struct device, kobj))); 90 struct qedf_ctx *qedf = lport_priv(lport); 91 92 if (test_bit(QEDF_GRCDUMP_CAPTURE, &qedf->flags)) { 93 ret = memory_read_from_buffer(buf, count, &off, 94 qedf->grcdump, qedf->grcdump_size); 95 } else { 96 QEDF_ERR(&(qedf->dbg_ctx), "GRC Dump not captured!\n"); 97 } 98 99 return ret; 100 } 101 102 static ssize_t 103 qedf_sysfs_write_grcdump(struct file *filep, struct kobject *kobj, 104 struct bin_attribute *ba, char *buf, loff_t off, 105 size_t count) 106 { 107 struct fc_lport *lport = NULL; 108 struct qedf_ctx *qedf = NULL; 109 long reading; 110 int ret = 0; 111 char msg[40]; 112 113 if (off != 0) 114 return ret; 115 116 117 lport = shost_priv(dev_to_shost(container_of(kobj, 118 struct device, kobj))); 119 qedf = lport_priv(lport); 120 121 buf[1] = 0; 122 ret = kstrtol(buf, 10, &reading); 123 if (ret) { 124 QEDF_ERR(&(qedf->dbg_ctx), "Invalid input, err(%d)\n", ret); 125 return ret; 126 } 127 128 memset(msg, 0, sizeof(msg)); 129 switch (reading) { 130 case 0: 131 memset(qedf->grcdump, 0, qedf->grcdump_size); 132 clear_bit(QEDF_GRCDUMP_CAPTURE, &qedf->flags); 133 break; 134 case 1: 135 qedf_capture_grc_dump(qedf); 136 break; 137 } 138 139 return count; 140 } 141 142 static struct bin_attribute sysfs_grcdump_attr = { 143 .attr = { 144 .name = "grcdump", 145 .mode = S_IRUSR | S_IWUSR, 146 }, 147 .size = 0, 148 .read = qedf_sysfs_read_grcdump, 149 .write = qedf_sysfs_write_grcdump, 150 }; 151 152 static struct sysfs_bin_attrs bin_file_entries[] = { 153 {"grcdump", &sysfs_grcdump_attr}, 154 {NULL}, 155 }; 156 157 void qedf_create_sysfs_ctx_attr(struct qedf_ctx *qedf) 158 { 159 qedf_create_sysfs_attr(qedf->lport->host, bin_file_entries); 160 } 161 162 void qedf_remove_sysfs_ctx_attr(struct qedf_ctx *qedf) 163 { 164 qedf_remove_sysfs_attr(qedf->lport->host, bin_file_entries); 165 } 166