1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/firmware.h> 4 #include <linux/module.h> 5 #include <linux/slab.h> 6 7 #include "sysfs.h" 8 #include "sysfs_upload.h" 9 10 /* 11 * Support for user-space to initiate a firmware upload to a device. 12 */ 13 14 static void fw_upload_update_progress(struct fw_upload_priv *fwlp, 15 enum fw_upload_prog new_progress) 16 { 17 mutex_lock(&fwlp->lock); 18 fwlp->progress = new_progress; 19 mutex_unlock(&fwlp->lock); 20 } 21 22 static void fw_upload_set_error(struct fw_upload_priv *fwlp, 23 enum fw_upload_err err_code) 24 { 25 mutex_lock(&fwlp->lock); 26 fwlp->err_progress = fwlp->progress; 27 fwlp->err_code = err_code; 28 mutex_unlock(&fwlp->lock); 29 } 30 31 static void fw_upload_prog_complete(struct fw_upload_priv *fwlp) 32 { 33 mutex_lock(&fwlp->lock); 34 fwlp->progress = FW_UPLOAD_PROG_IDLE; 35 mutex_unlock(&fwlp->lock); 36 } 37 38 static void fw_upload_main(struct work_struct *work) 39 { 40 struct fw_upload_priv *fwlp; 41 struct fw_sysfs *fw_sysfs; 42 u32 written = 0, offset = 0; 43 enum fw_upload_err ret; 44 struct device *fw_dev; 45 struct fw_upload *fwl; 46 47 fwlp = container_of(work, struct fw_upload_priv, work); 48 fwl = fwlp->fw_upload; 49 fw_sysfs = (struct fw_sysfs *)fwl->priv; 50 fw_dev = &fw_sysfs->dev; 51 52 fw_upload_update_progress(fwlp, FW_UPLOAD_PROG_PREPARING); 53 ret = fwlp->ops->prepare(fwl, fwlp->data, fwlp->remaining_size); 54 if (ret != FW_UPLOAD_ERR_NONE) { 55 fw_upload_set_error(fwlp, ret); 56 goto putdev_exit; 57 } 58 59 fw_upload_update_progress(fwlp, FW_UPLOAD_PROG_TRANSFERRING); 60 while (fwlp->remaining_size) { 61 ret = fwlp->ops->write(fwl, fwlp->data, offset, 62 fwlp->remaining_size, &written); 63 if (ret != FW_UPLOAD_ERR_NONE || !written) { 64 if (ret == FW_UPLOAD_ERR_NONE) { 65 dev_warn(fw_dev, "write-op wrote zero data\n"); 66 ret = FW_UPLOAD_ERR_RW_ERROR; 67 } 68 fw_upload_set_error(fwlp, ret); 69 goto done; 70 } 71 72 fwlp->remaining_size -= written; 73 offset += written; 74 } 75 76 fw_upload_update_progress(fwlp, FW_UPLOAD_PROG_PROGRAMMING); 77 ret = fwlp->ops->poll_complete(fwl); 78 if (ret != FW_UPLOAD_ERR_NONE) 79 fw_upload_set_error(fwlp, ret); 80 81 done: 82 if (fwlp->ops->cleanup) 83 fwlp->ops->cleanup(fwl); 84 85 putdev_exit: 86 put_device(fw_dev->parent); 87 88 /* 89 * Note: fwlp->remaining_size is left unmodified here to provide 90 * additional information on errors. It will be reinitialized when 91 * the next firmeware upload begins. 92 */ 93 mutex_lock(&fw_lock); 94 fw_free_paged_buf(fw_sysfs->fw_priv); 95 fw_state_init(fw_sysfs->fw_priv); 96 mutex_unlock(&fw_lock); 97 fwlp->data = NULL; 98 fw_upload_prog_complete(fwlp); 99 } 100 101 /* 102 * Start a worker thread to upload data to the parent driver. 103 * Must be called with fw_lock held. 104 */ 105 int fw_upload_start(struct fw_sysfs *fw_sysfs) 106 { 107 struct fw_priv *fw_priv = fw_sysfs->fw_priv; 108 struct device *fw_dev = &fw_sysfs->dev; 109 struct fw_upload_priv *fwlp; 110 111 if (!fw_sysfs->fw_upload_priv) 112 return 0; 113 114 if (!fw_priv->size) { 115 fw_free_paged_buf(fw_priv); 116 fw_state_init(fw_sysfs->fw_priv); 117 return 0; 118 } 119 120 fwlp = fw_sysfs->fw_upload_priv; 121 mutex_lock(&fwlp->lock); 122 123 /* Do not interfere with an on-going fw_upload */ 124 if (fwlp->progress != FW_UPLOAD_PROG_IDLE) { 125 mutex_unlock(&fwlp->lock); 126 return -EBUSY; 127 } 128 129 get_device(fw_dev->parent); /* released in fw_upload_main */ 130 131 fwlp->progress = FW_UPLOAD_PROG_RECEIVING; 132 fwlp->err_code = 0; 133 fwlp->remaining_size = fw_priv->size; 134 fwlp->data = fw_priv->data; 135 136 pr_debug("%s: fw-%s fw_priv=%p data=%p size=%u\n", 137 __func__, fw_priv->fw_name, 138 fw_priv, fw_priv->data, 139 (unsigned int)fw_priv->size); 140 141 queue_work(system_long_wq, &fwlp->work); 142 mutex_unlock(&fwlp->lock); 143 144 return 0; 145 } 146 147 /** 148 * firmware_upload_register() - register for the firmware upload sysfs API 149 * @parent: parent device instantiating firmware upload 150 * @name: firmware name to be associated with this device 151 * @ops: pointer to structure of firmware upload ops 152 * @dd_handle: pointer to parent driver private data 153 * 154 * @name must be unique among all users of firmware upload. The firmware 155 * sysfs files for this device will be found at /sys/class/firmware/@name. 156 * 157 * Return: struct fw_upload pointer or ERR_PTR() 158 * 159 **/ 160 struct fw_upload * 161 firmware_upload_register(struct module *module, struct device *parent, 162 const char *name, const struct fw_upload_ops *ops, 163 void *dd_handle) 164 { 165 u32 opt_flags = FW_OPT_NOCACHE; 166 struct fw_upload *fw_upload; 167 struct fw_upload_priv *fw_upload_priv; 168 struct fw_sysfs *fw_sysfs; 169 struct fw_priv *fw_priv; 170 struct device *fw_dev; 171 int ret; 172 173 if (!name || name[0] == '\0') 174 return ERR_PTR(-EINVAL); 175 176 if (!ops || !ops->cancel || !ops->prepare || 177 !ops->write || !ops->poll_complete) { 178 dev_err(parent, "Attempt to register without all required ops\n"); 179 return ERR_PTR(-EINVAL); 180 } 181 182 if (!try_module_get(module)) 183 return ERR_PTR(-EFAULT); 184 185 fw_upload = kzalloc(sizeof(*fw_upload), GFP_KERNEL); 186 if (!fw_upload) { 187 ret = -ENOMEM; 188 goto exit_module_put; 189 } 190 191 fw_upload_priv = kzalloc(sizeof(*fw_upload_priv), GFP_KERNEL); 192 if (!fw_upload_priv) { 193 ret = -ENOMEM; 194 goto free_fw_upload; 195 } 196 197 fw_upload_priv->fw_upload = fw_upload; 198 fw_upload_priv->ops = ops; 199 mutex_init(&fw_upload_priv->lock); 200 fw_upload_priv->module = module; 201 fw_upload_priv->name = name; 202 fw_upload_priv->err_code = 0; 203 fw_upload_priv->progress = FW_UPLOAD_PROG_IDLE; 204 INIT_WORK(&fw_upload_priv->work, fw_upload_main); 205 fw_upload->dd_handle = dd_handle; 206 207 fw_sysfs = fw_create_instance(NULL, name, parent, opt_flags); 208 if (IS_ERR(fw_sysfs)) { 209 ret = PTR_ERR(fw_sysfs); 210 goto free_fw_upload_priv; 211 } 212 fw_upload->priv = fw_sysfs; 213 fw_sysfs->fw_upload_priv = fw_upload_priv; 214 fw_dev = &fw_sysfs->dev; 215 216 ret = alloc_lookup_fw_priv(name, &fw_cache, &fw_priv, NULL, 0, 0, 217 FW_OPT_NOCACHE); 218 if (ret != 0) { 219 if (ret > 0) 220 ret = -EINVAL; 221 goto free_fw_sysfs; 222 } 223 fw_priv->is_paged_buf = true; 224 fw_sysfs->fw_priv = fw_priv; 225 226 ret = device_add(fw_dev); 227 if (ret) { 228 dev_err(fw_dev, "%s: device_register failed\n", __func__); 229 put_device(fw_dev); 230 goto exit_module_put; 231 } 232 233 return fw_upload; 234 235 free_fw_sysfs: 236 kfree(fw_sysfs); 237 238 free_fw_upload_priv: 239 kfree(fw_upload_priv); 240 241 free_fw_upload: 242 kfree(fw_upload); 243 244 exit_module_put: 245 module_put(module); 246 247 return ERR_PTR(ret); 248 } 249 EXPORT_SYMBOL_GPL(firmware_upload_register); 250 251 /** 252 * firmware_upload_unregister() - Unregister firmware upload interface 253 * @fw_upload: pointer to struct fw_upload 254 **/ 255 void firmware_upload_unregister(struct fw_upload *fw_upload) 256 { 257 struct fw_sysfs *fw_sysfs = fw_upload->priv; 258 struct fw_upload_priv *fw_upload_priv = fw_sysfs->fw_upload_priv; 259 260 mutex_lock(&fw_upload_priv->lock); 261 if (fw_upload_priv->progress == FW_UPLOAD_PROG_IDLE) { 262 mutex_unlock(&fw_upload_priv->lock); 263 goto unregister; 264 } 265 266 fw_upload_priv->ops->cancel(fw_upload); 267 mutex_unlock(&fw_upload_priv->lock); 268 269 /* Ensure lower-level device-driver is finished */ 270 flush_work(&fw_upload_priv->work); 271 272 unregister: 273 device_unregister(&fw_sysfs->dev); 274 module_put(fw_upload_priv->module); 275 } 276 EXPORT_SYMBOL_GPL(firmware_upload_unregister); 277