Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

remoteproc: support virtio config space.

Support virtio configuration space and device status. The virtio
device can now access the resource table in shared memory.

Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
Acked-by: Ido Yariv <ido@wizery.com>
[rebase and style changes]
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>

authored by

Sjur Brændeland and committed by
Ohad Ben-Cohen
92b38f85 a2b950ac

+64 -22
-3
drivers/remoteproc/remoteproc_core.c
··· 345 345 goto free_rvdev; 346 346 } 347 347 348 - /* remember the device features */ 349 - rvdev->dfeatures = rsc->dfeatures; 350 - 351 348 /* remember the resource offset*/ 352 349 rvdev->rsc_offset = offset; 353 350
+64 -15
drivers/remoteproc/remoteproc_virtio.c
··· 173 173 return ret; 174 174 } 175 175 176 - /* 177 - * We don't support yet real virtio status semantics. 178 - * 179 - * The plan is to provide this via the VDEV resource entry 180 - * which is part of the firmware: this way the remote processor 181 - * will be able to access the status values as set by us. 182 - */ 183 176 static u8 rproc_virtio_get_status(struct virtio_device *vdev) 184 177 { 185 - return 0; 178 + struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 179 + struct fw_rsc_vdev *rsc; 180 + 181 + rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; 182 + 183 + return rsc->status; 186 184 } 187 185 188 186 static void rproc_virtio_set_status(struct virtio_device *vdev, u8 status) 189 187 { 188 + struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 189 + struct fw_rsc_vdev *rsc; 190 + 191 + rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; 192 + 193 + rsc->status = status; 190 194 dev_dbg(&vdev->dev, "status: %d\n", status); 191 195 } 192 196 193 197 static void rproc_virtio_reset(struct virtio_device *vdev) 194 198 { 199 + struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 200 + struct fw_rsc_vdev *rsc; 201 + 202 + rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; 203 + 204 + rsc->status = 0; 195 205 dev_dbg(&vdev->dev, "reset !\n"); 196 206 } 197 207 ··· 209 199 static u32 rproc_virtio_get_features(struct virtio_device *vdev) 210 200 { 211 201 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 202 + struct fw_rsc_vdev *rsc; 212 203 213 - return rvdev->dfeatures; 204 + rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; 205 + 206 + return rsc->dfeatures; 214 207 } 215 208 216 209 static void rproc_virtio_finalize_features(struct virtio_device *vdev) 217 210 { 218 211 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 212 + struct fw_rsc_vdev *rsc; 213 + 214 + rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; 219 215 220 216 /* Give virtio_ring a chance to accept features */ 221 217 vring_transport_features(vdev); ··· 229 213 /* 230 214 * Remember the finalized features of our vdev, and provide it 231 215 * to the remote processor once it is powered on. 232 - * 233 - * Similarly to the status field, we don't expose yet the negotiated 234 - * features to the remote processors at this point. This will be 235 - * fixed as part of a small resource table overhaul and then an 236 - * extension of the virtio resource entries. 237 216 */ 238 - rvdev->gfeatures = vdev->features[0]; 217 + rsc->gfeatures = vdev->features[0]; 218 + } 219 + 220 + static void rproc_virtio_get(struct virtio_device *vdev, unsigned offset, 221 + void *buf, unsigned len) 222 + { 223 + struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 224 + struct fw_rsc_vdev *rsc; 225 + void *cfg; 226 + 227 + rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; 228 + cfg = &rsc->vring[rsc->num_of_vrings]; 229 + 230 + if (offset + len > rsc->config_len || offset + len < len) { 231 + dev_err(&vdev->dev, "rproc_virtio_get: access out of bounds\n"); 232 + return; 233 + } 234 + 235 + memcpy(buf, cfg + offset, len); 236 + } 237 + 238 + static void rproc_virtio_set(struct virtio_device *vdev, unsigned offset, 239 + const void *buf, unsigned len) 240 + { 241 + struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 242 + struct fw_rsc_vdev *rsc; 243 + void *cfg; 244 + 245 + rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; 246 + cfg = &rsc->vring[rsc->num_of_vrings]; 247 + 248 + if (offset + len > rsc->config_len || offset + len < len) { 249 + dev_err(&vdev->dev, "rproc_virtio_set: access out of bounds\n"); 250 + return; 251 + } 252 + 253 + memcpy(cfg + offset, buf, len); 239 254 } 240 255 241 256 static const struct virtio_config_ops rproc_virtio_config_ops = { ··· 277 230 .reset = rproc_virtio_reset, 278 231 .set_status = rproc_virtio_set_status, 279 232 .get_status = rproc_virtio_get_status, 233 + .get = rproc_virtio_get, 234 + .set = rproc_virtio_set, 280 235 }; 281 236 282 237 /*
-4
include/linux/remoteproc.h
··· 469 469 * @rproc: the rproc handle 470 470 * @vdev: the virio device 471 471 * @vring: the vrings for this vdev 472 - * @dfeatures: virtio device features 473 - * @gfeatures: virtio guest features 474 472 * @rsc_offset: offset of the vdev's resource entry 475 473 */ 476 474 struct rproc_vdev { ··· 476 478 struct rproc *rproc; 477 479 struct virtio_device vdev; 478 480 struct rproc_vring vring[RVDEV_NUM_VRINGS]; 479 - unsigned long dfeatures; 480 - unsigned long gfeatures; 481 481 u32 rsc_offset; 482 482 }; 483 483