1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * u_ether_configfs.h 4 * 5 * Utility definitions for configfs support in USB Ethernet functions 6 * 7 * Copyright (c) 2013 Samsung Electronics Co., Ltd. 8 * http://www.samsung.com 9 * 10 * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License version 2 as 14 * published by the Free Software Foundation. 15 */ 16 17 #ifndef __U_ETHER_CONFIGFS_H 18 #define __U_ETHER_CONFIGFS_H 19 20 #define USB_ETHERNET_CONFIGFS_ITEM(_f_) \ 21 static void _f_##_attr_release(struct config_item *item) \ 22 { \ 23 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 24 \ 25 usb_put_function_instance(&opts->func_inst); \ 26 } \ 27 \ 28 static struct configfs_item_operations _f_##_item_ops = { \ 29 .release = _f_##_attr_release, \ 30 } 31 32 #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(_f_) \ 33 static ssize_t _f_##_opts_dev_addr_show(struct config_item *item, \ 34 char *page) \ 35 { \ 36 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 37 int result; \ 38 \ 39 mutex_lock(&opts->lock); \ 40 result = gether_get_dev_addr(opts->net, page, PAGE_SIZE); \ 41 mutex_unlock(&opts->lock); \ 42 \ 43 return result; \ 44 } \ 45 \ 46 static ssize_t _f_##_opts_dev_addr_store(struct config_item *item, \ 47 const char *page, size_t len)\ 48 { \ 49 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 50 int ret; \ 51 \ 52 mutex_lock(&opts->lock); \ 53 if (opts->refcnt) { \ 54 mutex_unlock(&opts->lock); \ 55 return -EBUSY; \ 56 } \ 57 \ 58 ret = gether_set_dev_addr(opts->net, page); \ 59 mutex_unlock(&opts->lock); \ 60 if (!ret) \ 61 ret = len; \ 62 return ret; \ 63 } \ 64 \ 65 CONFIGFS_ATTR(_f_##_opts_, dev_addr) 66 67 #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(_f_) \ 68 static ssize_t _f_##_opts_host_addr_show(struct config_item *item, \ 69 char *page) \ 70 { \ 71 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 72 int result; \ 73 \ 74 mutex_lock(&opts->lock); \ 75 result = gether_get_host_addr(opts->net, page, PAGE_SIZE); \ 76 mutex_unlock(&opts->lock); \ 77 \ 78 return result; \ 79 } \ 80 \ 81 static ssize_t _f_##_opts_host_addr_store(struct config_item *item, \ 82 const char *page, size_t len)\ 83 { \ 84 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 85 int ret; \ 86 \ 87 mutex_lock(&opts->lock); \ 88 if (opts->refcnt) { \ 89 mutex_unlock(&opts->lock); \ 90 return -EBUSY; \ 91 } \ 92 \ 93 ret = gether_set_host_addr(opts->net, page); \ 94 mutex_unlock(&opts->lock); \ 95 if (!ret) \ 96 ret = len; \ 97 return ret; \ 98 } \ 99 \ 100 CONFIGFS_ATTR(_f_##_opts_, host_addr) 101 102 #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(_f_) \ 103 static ssize_t _f_##_opts_qmult_show(struct config_item *item, \ 104 char *page) \ 105 { \ 106 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 107 unsigned qmult; \ 108 \ 109 mutex_lock(&opts->lock); \ 110 qmult = gether_get_qmult(opts->net); \ 111 mutex_unlock(&opts->lock); \ 112 return sprintf(page, "%d\n", qmult); \ 113 } \ 114 \ 115 static ssize_t _f_##_opts_qmult_store(struct config_item *item, \ 116 const char *page, size_t len)\ 117 { \ 118 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 119 u8 val; \ 120 int ret; \ 121 \ 122 mutex_lock(&opts->lock); \ 123 if (opts->refcnt) { \ 124 ret = -EBUSY; \ 125 goto out; \ 126 } \ 127 \ 128 ret = kstrtou8(page, 0, &val); \ 129 if (ret) \ 130 goto out; \ 131 \ 132 gether_set_qmult(opts->net, val); \ 133 ret = len; \ 134 out: \ 135 mutex_unlock(&opts->lock); \ 136 return ret; \ 137 } \ 138 \ 139 CONFIGFS_ATTR(_f_##_opts_, qmult) 140 141 #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(_f_) \ 142 static ssize_t _f_##_opts_ifname_show(struct config_item *item, \ 143 char *page) \ 144 { \ 145 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 146 int ret; \ 147 \ 148 mutex_lock(&opts->lock); \ 149 ret = gether_get_ifname(opts->net, page, PAGE_SIZE); \ 150 mutex_unlock(&opts->lock); \ 151 \ 152 return ret; \ 153 } \ 154 \ 155 CONFIGFS_ATTR_RO(_f_##_opts_, ifname) 156 157 #define USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(_f_, _n_) \ 158 static ssize_t _f_##_opts_##_n_##_show(struct config_item *item,\ 159 char *page) \ 160 { \ 161 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 162 int ret; \ 163 \ 164 mutex_lock(&opts->lock); \ 165 ret = sprintf(page, "%02x\n", opts->_n_); \ 166 mutex_unlock(&opts->lock); \ 167 \ 168 return ret; \ 169 } \ 170 \ 171 static ssize_t _f_##_opts_##_n_##_store(struct config_item *item,\ 172 const char *page, \ 173 size_t len) \ 174 { \ 175 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 176 int ret; \ 177 u8 val; \ 178 \ 179 mutex_lock(&opts->lock); \ 180 ret = sscanf(page, "%02hhx", &val); \ 181 if (ret > 0) { \ 182 opts->_n_ = val; \ 183 ret = len; \ 184 } \ 185 mutex_unlock(&opts->lock); \ 186 \ 187 return ret; \ 188 } \ 189 \ 190 CONFIGFS_ATTR(_f_##_opts_, _n_) 191 192 #endif /* __U_ETHER_CONFIGFS_H */ 193