1e3cf00d0SUpinder Malhi /* 2e3cf00d0SUpinder Malhi * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved. 3e3cf00d0SUpinder Malhi * 43805eadeSJeff Squyres * This software is available to you under a choice of one of two 53805eadeSJeff Squyres * licenses. You may choose to be licensed under the terms of the GNU 63805eadeSJeff Squyres * General Public License (GPL) Version 2, available from the file 73805eadeSJeff Squyres * COPYING in the main directory of this source tree, or the 83805eadeSJeff Squyres * BSD license below: 93805eadeSJeff Squyres * 103805eadeSJeff Squyres * Redistribution and use in source and binary forms, with or 113805eadeSJeff Squyres * without modification, are permitted provided that the following 123805eadeSJeff Squyres * conditions are met: 133805eadeSJeff Squyres * 143805eadeSJeff Squyres * - Redistributions of source code must retain the above 153805eadeSJeff Squyres * copyright notice, this list of conditions and the following 163805eadeSJeff Squyres * disclaimer. 173805eadeSJeff Squyres * 183805eadeSJeff Squyres * - Redistributions in binary form must reproduce the above 193805eadeSJeff Squyres * copyright notice, this list of conditions and the following 203805eadeSJeff Squyres * disclaimer in the documentation and/or other materials 213805eadeSJeff Squyres * provided with the distribution. 22e3cf00d0SUpinder Malhi * 23e3cf00d0SUpinder Malhi * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24e3cf00d0SUpinder Malhi * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25e3cf00d0SUpinder Malhi * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26e3cf00d0SUpinder Malhi * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27e3cf00d0SUpinder Malhi * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28e3cf00d0SUpinder Malhi * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29e3cf00d0SUpinder Malhi * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30e3cf00d0SUpinder Malhi * SOFTWARE. 31e3cf00d0SUpinder Malhi * 32e3cf00d0SUpinder Malhi */ 33e3cf00d0SUpinder Malhi 34e3cf00d0SUpinder Malhi #include <linux/module.h> 35e3cf00d0SUpinder Malhi #include <linux/init.h> 36e3cf00d0SUpinder Malhi #include <linux/errno.h> 37e3cf00d0SUpinder Malhi 38e3cf00d0SUpinder Malhi #include <rdma/ib_user_verbs.h> 39e3cf00d0SUpinder Malhi #include <rdma/ib_addr.h> 40e3cf00d0SUpinder Malhi 41e3cf00d0SUpinder Malhi #include "usnic_common_util.h" 42e3cf00d0SUpinder Malhi #include "usnic_ib.h" 43e3cf00d0SUpinder Malhi #include "usnic_ib_qp_grp.h" 44e3cf00d0SUpinder Malhi #include "usnic_vnic.h" 45e3cf00d0SUpinder Malhi #include "usnic_ib_verbs.h" 4619188436SBart Van Assche #include "usnic_ib_sysfs.h" 47e3cf00d0SUpinder Malhi #include "usnic_log.h" 48e3cf00d0SUpinder Malhi 49508a523fSParav Pandit static ssize_t board_id_show(struct device *device, 50508a523fSParav Pandit struct device_attribute *attr, char *buf) 51e3cf00d0SUpinder Malhi { 52e3cf00d0SUpinder Malhi struct usnic_ib_dev *us_ibdev = 5354747231SParav Pandit rdma_device_to_drv_device(device, struct usnic_ib_dev, ib_dev); 54e3cf00d0SUpinder Malhi unsigned short subsystem_device_id; 55e3cf00d0SUpinder Malhi 56e3cf00d0SUpinder Malhi mutex_lock(&us_ibdev->usdev_lock); 57e3cf00d0SUpinder Malhi subsystem_device_id = us_ibdev->pdev->subsystem_device; 58e3cf00d0SUpinder Malhi mutex_unlock(&us_ibdev->usdev_lock); 59e3cf00d0SUpinder Malhi 60e3cf00d0SUpinder Malhi return scnprintf(buf, PAGE_SIZE, "%hu\n", subsystem_device_id); 61e3cf00d0SUpinder Malhi } 62508a523fSParav Pandit static DEVICE_ATTR_RO(board_id); 63e3cf00d0SUpinder Malhi 64e3cf00d0SUpinder Malhi /* 65e3cf00d0SUpinder Malhi * Report the configuration for this PF 66e3cf00d0SUpinder Malhi */ 67e3cf00d0SUpinder Malhi static ssize_t 68508a523fSParav Pandit config_show(struct device *device, struct device_attribute *attr, char *buf) 69e3cf00d0SUpinder Malhi { 7054747231SParav Pandit struct usnic_ib_dev *us_ibdev = 7154747231SParav Pandit rdma_device_to_drv_device(device, struct usnic_ib_dev, ib_dev); 72e3cf00d0SUpinder Malhi char *ptr; 73e3cf00d0SUpinder Malhi unsigned left; 74e3cf00d0SUpinder Malhi unsigned n; 75e3cf00d0SUpinder Malhi enum usnic_vnic_res_type res_type; 76e3cf00d0SUpinder Malhi 77e3cf00d0SUpinder Malhi /* Buffer space limit is 1 page */ 78e3cf00d0SUpinder Malhi ptr = buf; 79e3cf00d0SUpinder Malhi left = PAGE_SIZE; 80e3cf00d0SUpinder Malhi 81e3cf00d0SUpinder Malhi mutex_lock(&us_ibdev->usdev_lock); 822c935bc5SPeter Zijlstra if (kref_read(&us_ibdev->vf_cnt) > 0) { 83e3cf00d0SUpinder Malhi char *busname; 84e3cf00d0SUpinder Malhi 85e3cf00d0SUpinder Malhi /* 86e3cf00d0SUpinder Malhi * bus name seems to come with annoying prefix. 87e3cf00d0SUpinder Malhi * Remove it if it is predictable 88e3cf00d0SUpinder Malhi */ 89e3cf00d0SUpinder Malhi busname = us_ibdev->pdev->bus->name; 90e3cf00d0SUpinder Malhi if (strncmp(busname, "PCI Bus ", 8) == 0) 91e3cf00d0SUpinder Malhi busname += 8; 92e3cf00d0SUpinder Malhi 93e3cf00d0SUpinder Malhi n = scnprintf(ptr, left, 94e3cf00d0SUpinder Malhi "%s: %s:%d.%d, %s, %pM, %u VFs\n Per VF:", 959de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev), 96e3cf00d0SUpinder Malhi busname, 97e3cf00d0SUpinder Malhi PCI_SLOT(us_ibdev->pdev->devfn), 98e3cf00d0SUpinder Malhi PCI_FUNC(us_ibdev->pdev->devfn), 99e3cf00d0SUpinder Malhi netdev_name(us_ibdev->netdev), 10060b215e8SUpinder Malhi us_ibdev->ufdev->mac, 1012c935bc5SPeter Zijlstra kref_read(&us_ibdev->vf_cnt)); 102e3cf00d0SUpinder Malhi UPDATE_PTR_LEFT(n, ptr, left); 103e3cf00d0SUpinder Malhi 104e3cf00d0SUpinder Malhi for (res_type = USNIC_VNIC_RES_TYPE_EOL; 105e3cf00d0SUpinder Malhi res_type < USNIC_VNIC_RES_TYPE_MAX; 106e3cf00d0SUpinder Malhi res_type++) { 107e3cf00d0SUpinder Malhi if (us_ibdev->vf_res_cnt[res_type] == 0) 108e3cf00d0SUpinder Malhi continue; 109e3cf00d0SUpinder Malhi n = scnprintf(ptr, left, " %d %s%s", 110e3cf00d0SUpinder Malhi us_ibdev->vf_res_cnt[res_type], 111e3cf00d0SUpinder Malhi usnic_vnic_res_type_to_str(res_type), 112e3cf00d0SUpinder Malhi (res_type < (USNIC_VNIC_RES_TYPE_MAX - 1)) ? 113e3cf00d0SUpinder Malhi "," : ""); 114e3cf00d0SUpinder Malhi UPDATE_PTR_LEFT(n, ptr, left); 115e3cf00d0SUpinder Malhi } 116e3cf00d0SUpinder Malhi n = scnprintf(ptr, left, "\n"); 117e3cf00d0SUpinder Malhi UPDATE_PTR_LEFT(n, ptr, left); 118e3cf00d0SUpinder Malhi } else { 119e3cf00d0SUpinder Malhi n = scnprintf(ptr, left, "%s: no VFs\n", 1209de69861SJason Gunthorpe dev_name(&us_ibdev->ib_dev.dev)); 121e3cf00d0SUpinder Malhi UPDATE_PTR_LEFT(n, ptr, left); 122e3cf00d0SUpinder Malhi } 123e3cf00d0SUpinder Malhi mutex_unlock(&us_ibdev->usdev_lock); 124e3cf00d0SUpinder Malhi 125e3cf00d0SUpinder Malhi return ptr - buf; 126e3cf00d0SUpinder Malhi } 127508a523fSParav Pandit static DEVICE_ATTR_RO(config); 128e3cf00d0SUpinder Malhi 129e3cf00d0SUpinder Malhi static ssize_t 130508a523fSParav Pandit iface_show(struct device *device, struct device_attribute *attr, char *buf) 131e3cf00d0SUpinder Malhi { 13254747231SParav Pandit struct usnic_ib_dev *us_ibdev = 13354747231SParav Pandit rdma_device_to_drv_device(device, struct usnic_ib_dev, ib_dev); 134e3cf00d0SUpinder Malhi 135e3cf00d0SUpinder Malhi return scnprintf(buf, PAGE_SIZE, "%s\n", 136e3cf00d0SUpinder Malhi netdev_name(us_ibdev->netdev)); 137e3cf00d0SUpinder Malhi } 138508a523fSParav Pandit static DEVICE_ATTR_RO(iface); 139e3cf00d0SUpinder Malhi 140e3cf00d0SUpinder Malhi static ssize_t 141508a523fSParav Pandit max_vf_show(struct device *device, struct device_attribute *attr, char *buf) 142e3cf00d0SUpinder Malhi { 14354747231SParav Pandit struct usnic_ib_dev *us_ibdev = 14454747231SParav Pandit rdma_device_to_drv_device(device, struct usnic_ib_dev, ib_dev); 145e3cf00d0SUpinder Malhi 146e3cf00d0SUpinder Malhi return scnprintf(buf, PAGE_SIZE, "%u\n", 1472c935bc5SPeter Zijlstra kref_read(&us_ibdev->vf_cnt)); 148e3cf00d0SUpinder Malhi } 149508a523fSParav Pandit static DEVICE_ATTR_RO(max_vf); 150e3cf00d0SUpinder Malhi 151e3cf00d0SUpinder Malhi static ssize_t 152508a523fSParav Pandit qp_per_vf_show(struct device *device, struct device_attribute *attr, char *buf) 153e3cf00d0SUpinder Malhi { 15454747231SParav Pandit struct usnic_ib_dev *us_ibdev = 15554747231SParav Pandit rdma_device_to_drv_device(device, struct usnic_ib_dev, ib_dev); 156e3cf00d0SUpinder Malhi int qp_per_vf; 157e3cf00d0SUpinder Malhi 158e3cf00d0SUpinder Malhi qp_per_vf = max(us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_WQ], 159e3cf00d0SUpinder Malhi us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_RQ]); 160e3cf00d0SUpinder Malhi 161e3cf00d0SUpinder Malhi return scnprintf(buf, PAGE_SIZE, 162e3cf00d0SUpinder Malhi "%d\n", qp_per_vf); 163e3cf00d0SUpinder Malhi } 164508a523fSParav Pandit static DEVICE_ATTR_RO(qp_per_vf); 165e3cf00d0SUpinder Malhi 166e3cf00d0SUpinder Malhi static ssize_t 167508a523fSParav Pandit cq_per_vf_show(struct device *device, struct device_attribute *attr, char *buf) 168e3cf00d0SUpinder Malhi { 16954747231SParav Pandit struct usnic_ib_dev *us_ibdev = 17054747231SParav Pandit rdma_device_to_drv_device(device, struct usnic_ib_dev, ib_dev); 171e3cf00d0SUpinder Malhi 172e3cf00d0SUpinder Malhi return scnprintf(buf, PAGE_SIZE, "%d\n", 173e3cf00d0SUpinder Malhi us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_CQ]); 174e3cf00d0SUpinder Malhi } 175508a523fSParav Pandit static DEVICE_ATTR_RO(cq_per_vf); 176e3cf00d0SUpinder Malhi 177508a523fSParav Pandit static struct attribute *usnic_class_attributes[] = { 178508a523fSParav Pandit &dev_attr_board_id.attr, 179508a523fSParav Pandit &dev_attr_config.attr, 180508a523fSParav Pandit &dev_attr_iface.attr, 181508a523fSParav Pandit &dev_attr_max_vf.attr, 182508a523fSParav Pandit &dev_attr_qp_per_vf.attr, 183508a523fSParav Pandit &dev_attr_cq_per_vf.attr, 184508a523fSParav Pandit NULL 185508a523fSParav Pandit }; 186e3cf00d0SUpinder Malhi 187508a523fSParav Pandit const struct attribute_group usnic_attr_group = { 188508a523fSParav Pandit .attrs = usnic_class_attributes, 189e3cf00d0SUpinder Malhi }; 190e3cf00d0SUpinder Malhi 191e3cf00d0SUpinder Malhi struct qpn_attribute { 192e3cf00d0SUpinder Malhi struct attribute attr; 193e3cf00d0SUpinder Malhi ssize_t (*show)(struct usnic_ib_qp_grp *, char *buf); 194e3cf00d0SUpinder Malhi }; 195e3cf00d0SUpinder Malhi 196e3cf00d0SUpinder Malhi /* 197e3cf00d0SUpinder Malhi * Definitions for supporting QPN entries in sysfs 198e3cf00d0SUpinder Malhi */ 199e3cf00d0SUpinder Malhi static ssize_t 200e3cf00d0SUpinder Malhi usnic_ib_qpn_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) 201e3cf00d0SUpinder Malhi { 202e3cf00d0SUpinder Malhi struct usnic_ib_qp_grp *qp_grp; 203e3cf00d0SUpinder Malhi struct qpn_attribute *qpn_attr; 204e3cf00d0SUpinder Malhi 205e3cf00d0SUpinder Malhi qp_grp = container_of(kobj, struct usnic_ib_qp_grp, kobj); 206e3cf00d0SUpinder Malhi qpn_attr = container_of(attr, struct qpn_attribute, attr); 207e3cf00d0SUpinder Malhi 208e3cf00d0SUpinder Malhi return qpn_attr->show(qp_grp, buf); 209e3cf00d0SUpinder Malhi } 210e3cf00d0SUpinder Malhi 211e3cf00d0SUpinder Malhi static const struct sysfs_ops usnic_ib_qpn_sysfs_ops = { 212e3cf00d0SUpinder Malhi .show = usnic_ib_qpn_attr_show 213e3cf00d0SUpinder Malhi }; 214e3cf00d0SUpinder Malhi 215e3cf00d0SUpinder Malhi #define QPN_ATTR_RO(NAME) \ 216e3cf00d0SUpinder Malhi struct qpn_attribute qpn_attr_##NAME = __ATTR_RO(NAME) 217e3cf00d0SUpinder Malhi 218e3cf00d0SUpinder Malhi static ssize_t context_show(struct usnic_ib_qp_grp *qp_grp, char *buf) 219e3cf00d0SUpinder Malhi { 220e3cf00d0SUpinder Malhi return scnprintf(buf, PAGE_SIZE, "0x%p\n", qp_grp->ctx); 221e3cf00d0SUpinder Malhi } 222e3cf00d0SUpinder Malhi 223e3cf00d0SUpinder Malhi static ssize_t summary_show(struct usnic_ib_qp_grp *qp_grp, char *buf) 224e3cf00d0SUpinder Malhi { 225e3cf00d0SUpinder Malhi int i, j, n; 226e3cf00d0SUpinder Malhi int left; 227e3cf00d0SUpinder Malhi char *ptr; 228e3cf00d0SUpinder Malhi struct usnic_vnic_res_chunk *res_chunk; 229e3cf00d0SUpinder Malhi struct usnic_vnic_res *vnic_res; 230e3cf00d0SUpinder Malhi 231e3cf00d0SUpinder Malhi left = PAGE_SIZE; 232e3cf00d0SUpinder Malhi ptr = buf; 233e3cf00d0SUpinder Malhi 234e3cf00d0SUpinder Malhi n = scnprintf(ptr, left, 23560b215e8SUpinder Malhi "QPN: %d State: (%s) PID: %u VF Idx: %hu ", 236e3cf00d0SUpinder Malhi qp_grp->ibqp.qp_num, 237e3cf00d0SUpinder Malhi usnic_ib_qp_grp_state_to_string(qp_grp->state), 238e3cf00d0SUpinder Malhi qp_grp->owner_pid, 23960b215e8SUpinder Malhi usnic_vnic_get_index(qp_grp->vf->vnic)); 240e3cf00d0SUpinder Malhi UPDATE_PTR_LEFT(n, ptr, left); 241e3cf00d0SUpinder Malhi 242e3cf00d0SUpinder Malhi for (i = 0; qp_grp->res_chunk_list[i]; i++) { 243e3cf00d0SUpinder Malhi res_chunk = qp_grp->res_chunk_list[i]; 244e3cf00d0SUpinder Malhi for (j = 0; j < res_chunk->cnt; j++) { 245e3cf00d0SUpinder Malhi vnic_res = res_chunk->res[j]; 246e3cf00d0SUpinder Malhi n = scnprintf(ptr, left, "%s[%d] ", 247e3cf00d0SUpinder Malhi usnic_vnic_res_type_to_str(vnic_res->type), 248e3cf00d0SUpinder Malhi vnic_res->vnic_idx); 249e3cf00d0SUpinder Malhi UPDATE_PTR_LEFT(n, ptr, left); 250e3cf00d0SUpinder Malhi } 251e3cf00d0SUpinder Malhi } 252e3cf00d0SUpinder Malhi 253e3cf00d0SUpinder Malhi n = scnprintf(ptr, left, "\n"); 254e3cf00d0SUpinder Malhi UPDATE_PTR_LEFT(n, ptr, left); 255e3cf00d0SUpinder Malhi 256e3cf00d0SUpinder Malhi return ptr - buf; 257e3cf00d0SUpinder Malhi } 258e3cf00d0SUpinder Malhi 259e3cf00d0SUpinder Malhi static QPN_ATTR_RO(context); 260e3cf00d0SUpinder Malhi static QPN_ATTR_RO(summary); 261e3cf00d0SUpinder Malhi 262e3cf00d0SUpinder Malhi static struct attribute *usnic_ib_qpn_default_attrs[] = { 263e3cf00d0SUpinder Malhi &qpn_attr_context.attr, 264e3cf00d0SUpinder Malhi &qpn_attr_summary.attr, 265e3cf00d0SUpinder Malhi NULL 266e3cf00d0SUpinder Malhi }; 267e3cf00d0SUpinder Malhi 268e3cf00d0SUpinder Malhi static struct kobj_type usnic_ib_qpn_type = { 269e3cf00d0SUpinder Malhi .sysfs_ops = &usnic_ib_qpn_sysfs_ops, 270e3cf00d0SUpinder Malhi .default_attrs = usnic_ib_qpn_default_attrs 271e3cf00d0SUpinder Malhi }; 272e3cf00d0SUpinder Malhi 273e3cf00d0SUpinder Malhi int usnic_ib_sysfs_register_usdev(struct usnic_ib_dev *us_ibdev) 274e3cf00d0SUpinder Malhi { 275e3cf00d0SUpinder Malhi /* create kernel object for looking at individual QPs */ 276e3cf00d0SUpinder Malhi kobject_get(&us_ibdev->ib_dev.dev.kobj); 277e3cf00d0SUpinder Malhi us_ibdev->qpn_kobj = kobject_create_and_add("qpn", 278e3cf00d0SUpinder Malhi &us_ibdev->ib_dev.dev.kobj); 279e3cf00d0SUpinder Malhi if (us_ibdev->qpn_kobj == NULL) { 280e3cf00d0SUpinder Malhi kobject_put(&us_ibdev->ib_dev.dev.kobj); 281e3cf00d0SUpinder Malhi return -ENOMEM; 282e3cf00d0SUpinder Malhi } 283e3cf00d0SUpinder Malhi 284e3cf00d0SUpinder Malhi return 0; 285e3cf00d0SUpinder Malhi } 286e3cf00d0SUpinder Malhi 287e3cf00d0SUpinder Malhi void usnic_ib_sysfs_unregister_usdev(struct usnic_ib_dev *us_ibdev) 288e3cf00d0SUpinder Malhi { 289e3cf00d0SUpinder Malhi kobject_put(us_ibdev->qpn_kobj); 290e3cf00d0SUpinder Malhi } 291e3cf00d0SUpinder Malhi 292e3cf00d0SUpinder Malhi void usnic_ib_sysfs_qpn_add(struct usnic_ib_qp_grp *qp_grp) 293e3cf00d0SUpinder Malhi { 294e3cf00d0SUpinder Malhi struct usnic_ib_dev *us_ibdev; 295e3cf00d0SUpinder Malhi int err; 296e3cf00d0SUpinder Malhi 297e3cf00d0SUpinder Malhi us_ibdev = qp_grp->vf->pf; 298e3cf00d0SUpinder Malhi 299e3cf00d0SUpinder Malhi err = kobject_init_and_add(&qp_grp->kobj, &usnic_ib_qpn_type, 300e3cf00d0SUpinder Malhi kobject_get(us_ibdev->qpn_kobj), 301e3cf00d0SUpinder Malhi "%d", qp_grp->grp_id); 302e3cf00d0SUpinder Malhi if (err) { 303e3cf00d0SUpinder Malhi kobject_put(us_ibdev->qpn_kobj); 304e3cf00d0SUpinder Malhi return; 305e3cf00d0SUpinder Malhi } 306e3cf00d0SUpinder Malhi } 307e3cf00d0SUpinder Malhi 308e3cf00d0SUpinder Malhi void usnic_ib_sysfs_qpn_remove(struct usnic_ib_qp_grp *qp_grp) 309e3cf00d0SUpinder Malhi { 310e3cf00d0SUpinder Malhi struct usnic_ib_dev *us_ibdev; 311e3cf00d0SUpinder Malhi 312e3cf00d0SUpinder Malhi us_ibdev = qp_grp->vf->pf; 313e3cf00d0SUpinder Malhi 314e3cf00d0SUpinder Malhi kobject_put(&qp_grp->kobj); 315e3cf00d0SUpinder Malhi kobject_put(us_ibdev->qpn_kobj); 316e3cf00d0SUpinder Malhi } 317