cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

usnic_ib_sysfs.c (8125B)


      1/*
      2 * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
      3 *
      4 * This software is available to you under a choice of one of two
      5 * licenses.  You may choose to be licensed under the terms of the GNU
      6 * General Public License (GPL) Version 2, available from the file
      7 * COPYING in the main directory of this source tree, or the
      8 * BSD license below:
      9 *
     10 *     Redistribution and use in source and binary forms, with or
     11 *     without modification, are permitted provided that the following
     12 *     conditions are met:
     13 *
     14 *      - Redistributions of source code must retain the above
     15 *        copyright notice, this list of conditions and the following
     16 *        disclaimer.
     17 *
     18 *      - Redistributions in binary form must reproduce the above
     19 *        copyright notice, this list of conditions and the following
     20 *        disclaimer in the documentation and/or other materials
     21 *        provided with the distribution.
     22 *
     23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     30 * SOFTWARE.
     31 *
     32 */
     33
     34#include <linux/init.h>
     35#include <linux/errno.h>
     36
     37#include <rdma/ib_user_verbs.h>
     38#include <rdma/ib_addr.h>
     39
     40#include "usnic_common_util.h"
     41#include "usnic_ib.h"
     42#include "usnic_ib_qp_grp.h"
     43#include "usnic_vnic.h"
     44#include "usnic_ib_verbs.h"
     45#include "usnic_ib_sysfs.h"
     46#include "usnic_log.h"
     47
     48static ssize_t board_id_show(struct device *device,
     49			     struct device_attribute *attr, char *buf)
     50{
     51	struct usnic_ib_dev *us_ibdev =
     52		rdma_device_to_drv_device(device, struct usnic_ib_dev, ib_dev);
     53	unsigned short subsystem_device_id;
     54
     55	mutex_lock(&us_ibdev->usdev_lock);
     56	subsystem_device_id = us_ibdev->pdev->subsystem_device;
     57	mutex_unlock(&us_ibdev->usdev_lock);
     58
     59	return sysfs_emit(buf, "%u\n", subsystem_device_id);
     60}
     61static DEVICE_ATTR_RO(board_id);
     62
     63/*
     64 * Report the configuration for this PF
     65 */
     66static ssize_t
     67config_show(struct device *device, struct device_attribute *attr, char *buf)
     68{
     69	struct usnic_ib_dev *us_ibdev =
     70		rdma_device_to_drv_device(device, struct usnic_ib_dev, ib_dev);
     71	enum usnic_vnic_res_type res_type;
     72	int len;
     73
     74	mutex_lock(&us_ibdev->usdev_lock);
     75	if (kref_read(&us_ibdev->vf_cnt) > 0) {
     76		char *busname;
     77		char *sep = "";
     78		/*
     79		 * bus name seems to come with annoying prefix.
     80		 * Remove it if it is predictable
     81		 */
     82		busname = us_ibdev->pdev->bus->name;
     83		if (strncmp(busname, "PCI Bus ", 8) == 0)
     84			busname += 8;
     85
     86		len = sysfs_emit(buf, "%s: %s:%d.%d, %s, %pM, %u VFs\n",
     87				 dev_name(&us_ibdev->ib_dev.dev),
     88				 busname,
     89				 PCI_SLOT(us_ibdev->pdev->devfn),
     90				 PCI_FUNC(us_ibdev->pdev->devfn),
     91				 netdev_name(us_ibdev->netdev),
     92				 us_ibdev->ufdev->mac,
     93				 kref_read(&us_ibdev->vf_cnt));
     94
     95		len += sysfs_emit_at(buf, len, " Per VF:");
     96		for (res_type = USNIC_VNIC_RES_TYPE_EOL;
     97		     res_type < USNIC_VNIC_RES_TYPE_MAX; res_type++) {
     98			if (us_ibdev->vf_res_cnt[res_type] == 0)
     99				continue;
    100			len += sysfs_emit_at(buf, len, "%s %d %s",
    101					     sep,
    102					     us_ibdev->vf_res_cnt[res_type],
    103					     usnic_vnic_res_type_to_str(res_type));
    104			sep = ",";
    105		}
    106		len += sysfs_emit_at(buf, len, "\n");
    107	} else {
    108		len = sysfs_emit(buf, "%s: no VFs\n",
    109				 dev_name(&us_ibdev->ib_dev.dev));
    110	}
    111
    112	mutex_unlock(&us_ibdev->usdev_lock);
    113
    114	return len;
    115}
    116static DEVICE_ATTR_RO(config);
    117
    118static ssize_t
    119iface_show(struct device *device, struct device_attribute *attr, char *buf)
    120{
    121	struct usnic_ib_dev *us_ibdev =
    122		rdma_device_to_drv_device(device, struct usnic_ib_dev, ib_dev);
    123
    124	return sysfs_emit(buf, "%s\n", netdev_name(us_ibdev->netdev));
    125}
    126static DEVICE_ATTR_RO(iface);
    127
    128static ssize_t
    129max_vf_show(struct device *device, struct device_attribute *attr, char *buf)
    130{
    131	struct usnic_ib_dev *us_ibdev =
    132		rdma_device_to_drv_device(device, struct usnic_ib_dev, ib_dev);
    133
    134	return sysfs_emit(buf, "%u\n", kref_read(&us_ibdev->vf_cnt));
    135}
    136static DEVICE_ATTR_RO(max_vf);
    137
    138static ssize_t
    139qp_per_vf_show(struct device *device, struct device_attribute *attr, char *buf)
    140{
    141	struct usnic_ib_dev *us_ibdev =
    142		rdma_device_to_drv_device(device, struct usnic_ib_dev, ib_dev);
    143	int qp_per_vf;
    144
    145	qp_per_vf = max(us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_WQ],
    146			us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_RQ]);
    147
    148	return sysfs_emit(buf, "%d\n", qp_per_vf);
    149}
    150static DEVICE_ATTR_RO(qp_per_vf);
    151
    152static ssize_t
    153cq_per_vf_show(struct device *device, struct device_attribute *attr, char *buf)
    154{
    155	struct usnic_ib_dev *us_ibdev =
    156		rdma_device_to_drv_device(device, struct usnic_ib_dev, ib_dev);
    157
    158	return sysfs_emit(buf, "%d\n",
    159			  us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_CQ]);
    160}
    161static DEVICE_ATTR_RO(cq_per_vf);
    162
    163static struct attribute *usnic_class_attributes[] = {
    164	&dev_attr_board_id.attr,
    165	&dev_attr_config.attr,
    166	&dev_attr_iface.attr,
    167	&dev_attr_max_vf.attr,
    168	&dev_attr_qp_per_vf.attr,
    169	&dev_attr_cq_per_vf.attr,
    170	NULL
    171};
    172
    173const struct attribute_group usnic_attr_group = {
    174	.attrs = usnic_class_attributes,
    175};
    176
    177struct qpn_attribute {
    178	struct attribute attr;
    179	ssize_t (*show)(struct usnic_ib_qp_grp *, char *buf);
    180};
    181
    182/*
    183 * Definitions for supporting QPN entries in sysfs
    184 */
    185static ssize_t
    186usnic_ib_qpn_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
    187{
    188	struct usnic_ib_qp_grp *qp_grp;
    189	struct qpn_attribute *qpn_attr;
    190
    191	qp_grp = container_of(kobj, struct usnic_ib_qp_grp, kobj);
    192	qpn_attr = container_of(attr, struct qpn_attribute, attr);
    193
    194	return qpn_attr->show(qp_grp, buf);
    195}
    196
    197static const struct sysfs_ops usnic_ib_qpn_sysfs_ops = {
    198	.show = usnic_ib_qpn_attr_show
    199};
    200
    201#define QPN_ATTR_RO(NAME) \
    202struct qpn_attribute qpn_attr_##NAME = __ATTR_RO(NAME)
    203
    204static ssize_t context_show(struct usnic_ib_qp_grp *qp_grp, char *buf)
    205{
    206	return sysfs_emit(buf, "0x%p\n", qp_grp->ctx);
    207}
    208
    209static ssize_t summary_show(struct usnic_ib_qp_grp *qp_grp, char *buf)
    210{
    211	int i, j;
    212	struct usnic_vnic_res_chunk *res_chunk;
    213	struct usnic_vnic_res *vnic_res;
    214	int len;
    215
    216	len = sysfs_emit(buf, "QPN: %d State: (%s) PID: %u VF Idx: %hu",
    217			 qp_grp->ibqp.qp_num,
    218			 usnic_ib_qp_grp_state_to_string(qp_grp->state),
    219			 qp_grp->owner_pid,
    220			 usnic_vnic_get_index(qp_grp->vf->vnic));
    221
    222	for (i = 0; qp_grp->res_chunk_list[i]; i++) {
    223		res_chunk = qp_grp->res_chunk_list[i];
    224		for (j = 0; j < res_chunk->cnt; j++) {
    225			vnic_res = res_chunk->res[j];
    226			len += sysfs_emit_at(buf, len, " %s[%d]",
    227				usnic_vnic_res_type_to_str(vnic_res->type),
    228				vnic_res->vnic_idx);
    229		}
    230	}
    231
    232	len += sysfs_emit_at(buf, len, "\n");
    233
    234	return len;
    235}
    236
    237static QPN_ATTR_RO(context);
    238static QPN_ATTR_RO(summary);
    239
    240static struct attribute *usnic_ib_qpn_default_attrs[] = {
    241	&qpn_attr_context.attr,
    242	&qpn_attr_summary.attr,
    243	NULL
    244};
    245ATTRIBUTE_GROUPS(usnic_ib_qpn_default);
    246
    247static struct kobj_type usnic_ib_qpn_type = {
    248	.sysfs_ops = &usnic_ib_qpn_sysfs_ops,
    249	.default_groups = usnic_ib_qpn_default_groups,
    250};
    251
    252int usnic_ib_sysfs_register_usdev(struct usnic_ib_dev *us_ibdev)
    253{
    254	/* create kernel object for looking at individual QPs */
    255	kobject_get(&us_ibdev->ib_dev.dev.kobj);
    256	us_ibdev->qpn_kobj = kobject_create_and_add("qpn",
    257			&us_ibdev->ib_dev.dev.kobj);
    258	if (us_ibdev->qpn_kobj == NULL) {
    259		kobject_put(&us_ibdev->ib_dev.dev.kobj);
    260		return -ENOMEM;
    261	}
    262
    263	return 0;
    264}
    265
    266void usnic_ib_sysfs_unregister_usdev(struct usnic_ib_dev *us_ibdev)
    267{
    268	kobject_put(us_ibdev->qpn_kobj);
    269}
    270
    271void usnic_ib_sysfs_qpn_add(struct usnic_ib_qp_grp *qp_grp)
    272{
    273	struct usnic_ib_dev *us_ibdev;
    274	int err;
    275
    276	us_ibdev = qp_grp->vf->pf;
    277
    278	err = kobject_init_and_add(&qp_grp->kobj, &usnic_ib_qpn_type,
    279			kobject_get(us_ibdev->qpn_kobj),
    280			"%d", qp_grp->grp_id);
    281	if (err) {
    282		kobject_put(us_ibdev->qpn_kobj);
    283		return;
    284	}
    285}
    286
    287void usnic_ib_sysfs_qpn_remove(struct usnic_ib_qp_grp *qp_grp)
    288{
    289	struct usnic_ib_dev *us_ibdev;
    290
    291	us_ibdev = qp_grp->vf->pf;
    292
    293	kobject_put(&qp_grp->kobj);
    294	kobject_put(us_ibdev->qpn_kobj);
    295}