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 <andrzejtp2010@gmail.com> 11 */ 12 13 #ifndef __U_ETHER_CONFIGFS_H 14 #define __U_ETHER_CONFIGFS_H 15 16 #define USB_ETHERNET_CONFIGFS_ITEM(_f_) \ 17 static void _f_##_attr_release(struct config_item *item) \ 18 { \ 19 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 20 \ 21 usb_put_function_instance(&opts->func_inst); \ 22 } \ 23 \ 24 static struct configfs_item_operations _f_##_item_ops = { \ 25 .release = _f_##_attr_release, \ 26 } 27 28 #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(_f_) \ 29 static ssize_t _f_##_opts_dev_addr_show(struct config_item *item, \ 30 char *page) \ 31 { \ 32 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 33 int result; \ 34 \ 35 mutex_lock(&opts->lock); \ 36 result = gether_get_dev_addr(opts->net, page, PAGE_SIZE); \ 37 mutex_unlock(&opts->lock); \ 38 \ 39 return result; \ 40 } \ 41 \ 42 static ssize_t _f_##_opts_dev_addr_store(struct config_item *item, \ 43 const char *page, size_t len)\ 44 { \ 45 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 46 int ret; \ 47 \ 48 mutex_lock(&opts->lock); \ 49 if (opts->refcnt) { \ 50 mutex_unlock(&opts->lock); \ 51 return -EBUSY; \ 52 } \ 53 \ 54 ret = gether_set_dev_addr(opts->net, page); \ 55 mutex_unlock(&opts->lock); \ 56 if (!ret) \ 57 ret = len; \ 58 return ret; \ 59 } \ 60 \ 61 CONFIGFS_ATTR(_f_##_opts_, dev_addr) 62 63 #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(_f_) \ 64 static ssize_t _f_##_opts_host_addr_show(struct config_item *item, \ 65 char *page) \ 66 { \ 67 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 68 int result; \ 69 \ 70 mutex_lock(&opts->lock); \ 71 result = gether_get_host_addr(opts->net, page, PAGE_SIZE); \ 72 mutex_unlock(&opts->lock); \ 73 \ 74 return result; \ 75 } \ 76 \ 77 static ssize_t _f_##_opts_host_addr_store(struct config_item *item, \ 78 const char *page, size_t len)\ 79 { \ 80 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 81 int ret; \ 82 \ 83 mutex_lock(&opts->lock); \ 84 if (opts->refcnt) { \ 85 mutex_unlock(&opts->lock); \ 86 return -EBUSY; \ 87 } \ 88 \ 89 ret = gether_set_host_addr(opts->net, page); \ 90 mutex_unlock(&opts->lock); \ 91 if (!ret) \ 92 ret = len; \ 93 return ret; \ 94 } \ 95 \ 96 CONFIGFS_ATTR(_f_##_opts_, host_addr) 97 98 #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(_f_) \ 99 static ssize_t _f_##_opts_qmult_show(struct config_item *item, \ 100 char *page) \ 101 { \ 102 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 103 unsigned qmult; \ 104 \ 105 mutex_lock(&opts->lock); \ 106 qmult = gether_get_qmult(opts->net); \ 107 mutex_unlock(&opts->lock); \ 108 return sprintf(page, "%d\n", qmult); \ 109 } \ 110 \ 111 static ssize_t _f_##_opts_qmult_store(struct config_item *item, \ 112 const char *page, size_t len)\ 113 { \ 114 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 115 u8 val; \ 116 int ret; \ 117 \ 118 mutex_lock(&opts->lock); \ 119 if (opts->refcnt) { \ 120 ret = -EBUSY; \ 121 goto out; \ 122 } \ 123 \ 124 ret = kstrtou8(page, 0, &val); \ 125 if (ret) \ 126 goto out; \ 127 \ 128 gether_set_qmult(opts->net, val); \ 129 ret = len; \ 130 out: \ 131 mutex_unlock(&opts->lock); \ 132 return ret; \ 133 } \ 134 \ 135 CONFIGFS_ATTR(_f_##_opts_, qmult) 136 137 #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(_f_) \ 138 static ssize_t _f_##_opts_ifname_show(struct config_item *item, \ 139 char *page) \ 140 { \ 141 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 142 int ret; \ 143 \ 144 mutex_lock(&opts->lock); \ 145 ret = gether_get_ifname(opts->net, page, PAGE_SIZE); \ 146 mutex_unlock(&opts->lock); \ 147 \ 148 return ret; \ 149 } \ 150 \ 151 static ssize_t _f_##_opts_ifname_store(struct config_item *item, \ 152 const char *page, size_t len)\ 153 { \ 154 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 155 int ret = -EBUSY; \ 156 \ 157 mutex_lock(&opts->lock); \ 158 if (!opts->refcnt) \ 159 ret = gether_set_ifname(opts->net, page, len); \ 160 mutex_unlock(&opts->lock); \ 161 return ret ?: len; \ 162 } \ 163 \ 164 CONFIGFS_ATTR(_f_##_opts_, ifname) 165 166 #define USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(_f_, _n_) \ 167 static ssize_t _f_##_opts_##_n_##_show(struct config_item *item,\ 168 char *page) \ 169 { \ 170 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 171 int ret; \ 172 \ 173 mutex_lock(&opts->lock); \ 174 ret = sprintf(page, "%02x\n", opts->_n_); \ 175 mutex_unlock(&opts->lock); \ 176 \ 177 return ret; \ 178 } \ 179 \ 180 static ssize_t _f_##_opts_##_n_##_store(struct config_item *item,\ 181 const char *page, \ 182 size_t len) \ 183 { \ 184 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ 185 int ret = -EINVAL; \ 186 u8 val; \ 187 \ 188 mutex_lock(&opts->lock); \ 189 if (sscanf(page, "%02hhx", &val) > 0) { \ 190 opts->_n_ = val; \ 191 ret = len; \ 192 } \ 193 mutex_unlock(&opts->lock); \ 194 \ 195 return ret; \ 196 } \ 197 \ 198 CONFIGFS_ATTR(_f_##_opts_, _n_) 199 200 #endif /* __U_ETHER_CONFIGFS_H */ 201