 Good morning everyone. I am Smitha from Samsung Foundry Software Division and along with my colleague Ajay will be presenting today's topic deep dive into today's VB2 framework. Agenda for today will be VB2 introduction and a brief insight into evolution of VB2. VB2 framework overview which will give a link from application to kernel to memory allocators. VB2 memops which are the current memory allocators we have and how ops are linked to different allocators. VB2 queue operations which will be the entire management of buffers. VB2 V4L2 APIs flow example using a map and DME buff. VB2 introduction. VB2 is basically video buff too, which by definition is a V4L2 compatible device driver buffer management framework. It is implemented for mostly multimedia devices. It provides support for complex media device use cases and it has zero copy media pipeline. This framework provides streaming IO V4L2 iOctals and file operations, high level video buffer queue and state management functions, video buffer memory allocation and management. It has a list of straightforward APIs, which are basically a small list and they're also easy to use. It ensures smooth buffer flow between user space and kernel space using user ptr or mmap way or buffer flow between drivers by sharing buffers via DME buff. Brief history into evolution of VB2. Around 2010, video buff framework was deprecated in favor of video buffer to framework. A few problems faced in video buff framework where V4L2 API violations, wrong memory management design, like it was impossible to pause streaming or when we caught request buffs with count zero, it doesn't free memory. It was impossible to reallocate through request buff. There was per buffer weight queues. It was not extensible enough. There was poor support for handling cache coherency IOMMU. To add any new memory handling routines, there was code duplication, unused fields, etc. Few more main goals of redesign were correct V4L2 API implementation, fixing video buffer one framework problems which I have discussed earlier, full separation in queue and memory management, flexible and pluggable memory allocators, and support for new V4L2 APIs. This diagram shows complete overview from application to driver using VB2 or V4L2 frameworks. We'll be using a video device like MFC, multi format codec as a driver example for all the use cases in this presentation. Also all the code structure, driver hierarchy and screenshots are based on latest kernel version 5.14 RC7. The application talks to the video device drivers via the IOCTL calls, but in case of multimedia use cases, there is another layer present, which is the V4L2 interface. So this framework is the interface from the user space to the driver for multimedia devices, and therefore the IOCTLs cannot reach the video device driver directly. The entire VB2 framework is depicted in this green box and the source code for VB2 framework can be found in drivers, media, common, media buff too. The main components in VB2 framework are V4L2 interface, VB2 core and VB2 memcore. The video device driver talks to the VB2 core via the VB2 core APIs. It can also use the V4L2 APIs to talk to the VB2 core APIs. The advantage of using the V4L2 APIs is it performs extra sanity check like the V4L2 buffer type is valid or not. If Q timestamp flags are used and appropriate V4L2 flags are not set. If null VB2 Q structures are present and if VB2 memory is not matching with the V4L2 memory and if VB2 Q is busy, that is the Q is busy if there's an owner and you're not the owner. The VB2 core uses the VB2 memmops when it talks to VB2 memcore. So this VB2 memcore is responsible for allocation of our memory. It uses kernel core allocators like DMA memory allocator, slab or slab page allocator, VMA allocator. The VB2 memmops is chosen by the driver during VB2 Q in it at an early stage, usually during device open, where all the context Qs for a particular run is set. We'll discuss in the upcoming slide more in detail about the VB2 Q in it. VB2 Q in it. This is the first function in terms of VB2 operation, which will be calling from the driver to the VB2 framework. It initializes the VB2 Q, which the driver will use throughout its run cycle. The struct VB2 Q will be allocated by the driver and the driver is responsible for clearing its content and setting initial values for some required entries before calling this function. Q ops, Q memmops, Q type and Q IU modes are mandatory to be set before we call VB2 Q in it. Q type can be of capture, output, single or multi-planar. Q IU modes are based on the memory model like VB2 MMAP, VB2 user PTR or VB2 DMA buff. The VB2 memmops are based on the kernel allocators. It can be VB2 DMA content memmops, VB2 DMA SG memmops, VB2 VMA lock memmops and this is completely driver defined. The VB2 ops are also completely driver defined. It can be like Q setup buff in it. This part will be covering in the later part of the presentation. Just for a brief idea here, for Q setup, the driver needs to provide its own callback like in the case of MFC, we provide SPYP MFC Q setup. Or you can also use generic VB2 APIs like VB2 ops, wait prepare for wait prepare. Once all this callback reaches this VB2 VFURL2 API, there's a basic sanity check if driver has chosen appropriate timestamp type and VB2 and VFURL2 memory type should match. Then this interface will set all the Q parameters like if it's multi-planar and if Q is output and also the Q buff ops, which will be the VFURL2 buffer ops. The important callbacks are shown here. The init buffer for a given VB2 buffer initializes the extra data in the struct VB2 buffer. For VFURL2, this is struct VB2 VFURL2 buffer. Fill user buffer, as mentioned it is a user space structure. For VFURL2, this will be struct VFURL2 buffer which will be filled from the user space. Fill VB2 buffer. Given a user space structure, this is going to fill VB2 buffer. Copy timestamp, it is going to fill the user space structure, copy timestamp structure to the VB2 buffer. Then this calls the VB2 core queue init in VB2 core. This again performs extra level of sanity check. Here it checks if the queue is null and if ops like queue ops, queue type, queue IO mode are all set. It then initializes queued list, done list and another queue initialization operations like spinlock init, mutex init. Also it checks if the queue is bi-directional to set the field dmi underscore dir to bi-directional. Or if queues of output type it sets it to dmi2 device else it will set it to dmi from device. Using this VB2 ops, the VB2 core is going to talk to the video device drivers from no one. VB2 memops, the memory handling and memory allocator operations are present in this VB2 memops. We'll be providing ops based on the allocators use which I have discussed in the previous slide. I will go through a few fields which are important for us. Required memops based on the memory models like when we use user ptr that is the user space allocates memory. We need get user ptr and put user ptr. And when we use a map memory model where the kernel allocates memory, we need a lock, put numusers and map. And when we use dmi for memory model where buffer is allocated by one driver and shared to other drivers. We require attached dmi above, detached dmi above, mapped dmi above and unmapped dmi above. Allocate allocates video memory and allocator private data. This returns a pointer to allocator private per buffer data on success. This returned private structure will be then passed as buffer to other ops in this structure. All the allocations in a lock call will be page aligned. Put it informs the allocator that the buffer will no longer be used. It will usually result in allocator frame the buffer if no other users of this buffer is present. Num user this returns the current number of users of a memory buffer. Buff ref count field is used to maintain this count and it returns one if the video buff layer or actually the driver using it is only is the only user. A map it is used to set up a user space mapping for a given memory buffer under the provided virtual region. Get user ptr this call is used to acquire user space memory for a hardware operation. The V address is the address passed to video buff layer when doing a video buffer of user ptr type. This also returns an allocator private buffer structure associated with the buffer. This buffer structure is passed inside buff proof to other ops in this structure. Put user ptr it informs the allocator the user ptr will no longer be used. Attach dmember from this attaches the structure dmember for a hardware operation. And dev is the unlock device debuff is the share dmember. This also returns allocated private buffer structure and success. This needs to be used for further access of the buffer. Detach dmember. It informs the exporter of the buffer that the current dmember buffer is no longer used. Map dmember it request for access to a dmember from allocator and allocator of dmember is informed this that this driver is going to use the dmember. Unmap dmember it releases access control to the dmember allocator is notified that the driver is done using the dmember for now. This table gives a brief idea based on our requirement which kernel memory allocator to choose. When we're using DMA content the physical memory address depends on the kernel DMA memory allocator. It can be either contiguous or non contiguous for DMA SG it depends on the kernel page allocator. It can be either contiguous or non contiguous in case of email or it depends on the kernel VMA locator it can be the contiguous or non contiguous. The device DMA address for DMA content will be contiguous in single chunk. For DMA SG and VMA address will be non contiguous and distributed into multiple pages for kernel virtual address in all three cases of kernel allocator it will be a contiguous chunk. The file location will be inside drivers media common media buff to media buff to DMA content dot c media buff to DMA SG dot c media buff to VMA loc dot c. Usage for DMA content will be depending on if the device does DMA engine doesn't support scatter gather list and it needs only continuous addresses in case of DMA SG if device DMA engine supports scatter gather list we go for DMA SG. If there's only one CPU was the user here and device can use it only if either board or device DMA engine supports the scatter gather list then we go for VMA locator. VB to Q operation. It is a set of functions which are defined by driver of the device for which we're managing all the buffers and these functions are very specific to the particular driver for which we are defining it. These functions are called out by the VB to framework in response to any of the VB to referral to APS. The main functionality of the VB to Q operation is to facilitate the communication and synchronization between VB to and the driver VB to Q operations. As mentioned earlier, this are very driver specific callbacks, and it is called not from the interrupt context. The requirement for each callback and time at which each callback should be called I'll be describing in the upcoming slides. This the driver developer has to take care during VB to ops implementation for the specific driver to set up. It is either called from request buff or create buff before actual memory allocation takes place. It can be called twice if the original number of requested buffers could not be allocated. Then it will be called the second time with the actually allocated number of buffers to verify if that is okay. The driver should return the exact number, the required number of buffers in number first and the required number of planes per buffer in num planes, sizes of each plane in the sizes area and the per plane allocator specific devices in the log devices area. When it is called from request bug, the num planes is set to zero to signal that the queue setup is called for the request buff case. The driver has to use the correctly configured format to determine the plane sizes. The number, the number of us is the total number of buffers that are being allocated. When it is called from create buffs, the num planes will not be equal to zero, and it describes the requested number of planes. The sizes contains the requested plane sizes. And in this case, the number of us are the buffers being allocated additional to the queue number first buff in it. It is called once after allocating a buffer in a map case, or after acquiring a new user PTA buffer. Here the driver can perform additional buffer related initializations. We take the VB buffer index and fill its data into driver context. Initialization failure will prevent queue setup from completing and this callback is optional. Buff cleanup, it is called once before the buffer is free and the driver can perform any additional cleanup as necessary. This is also an additional optional callback. Buff prepare, it is invoked from the I octal prepare buff and it is called every time the buffer is queued from the user space. In this callback driver can perform any initialization which is required before each hardware operation. We normally check VB to plane sizes with the driver calculated plane size and driver can access or modify the buffer here as it's still synced with the CPU. If your driver supports I octal create buffs, then this callback also needs to validate the buffer sizes. And if an error is returned, the buffer will not be queued to the driver. Again this callback is optional. Buff queue, it is always called after stream on I octal. It can be called before stream on if the user provides per queue to buffers before stream start streaming is called. This buffer VB is passed to the driver. Driver may start the hardware operation on this buffer and driver should give the buffer back by calling VB to buffer done functions. This VB to buffer done function should be called by the driver after the hardware operation on the buffer is finished and the buffer can be returned to the user space. The driver cannot use this buffer anymore until it is queued back by the video buff layer by means of buff queue callback. Only buffers which are previously queued to the driver by buff queue can be passed to this function VB to buffer done. Before the buffer is finished, it is called before every DQ of the buffer back to user space and the buffer is synced for the CPU. So drivers can access or modify the buffer contents. Driver can perform any operation which is required before user space accesses this buffer. Buff finish is an optional callback. The buffer state can be either one of the following done or error. Typically we have to do something if the state is VB to state done. Since in all other cases the buffer contents will be ignored anyway. Wait prepare. It releases any logs which are taken while calling the VB to functions. It is called before and I often needs to wait for a new buffer to arrive. It is required to avoid any callback in blocking access type call. Wait finish. It is used to reacquire all logs which are released in previous callback. It is required to continue operation after sleeping while waiting for a new buffer to arrive. Start streaming. It is called once to enter the streaming state and driver can receive buffers with buff queue callback before start streaming is called. Driver gets the number of already queued buffers in count parameter. Driver can return an error hardware fails. In that case all the buffers that has been already queued through buff queue callback are returned by the driver by calling VB to buffer done. But here the state of the buffers will be VB to buff state queued. If you need minimum number of buffers before you can start streaming then we need to set VB to queue min buffers needed. If this variable is set to non zero then only start streaming won't be called until at least that many buffers has been queued by the user space. Stop streaming. It is called when streaming state must be disabled. Driver should stop any DMA transactions or wait until they finish and give all the buffers back by calling VB to buffer done. It will be either in the state of VB to buff state done or VB to buff state error. We can also additionally use VB to wait for all buffers function. This function will wait until all buffers that has been given to the driver through buff queue are given back to VB to and VB to buffer done. It doesn't call wait prepare and wait finish pair. It is intended to be called with all logs taken, which is very important. These are the two newly added callbacks buff out validate and buff request complete. Buff out validate is called when the output buffer is prepared or chewed for a request. Drivers can use this to validate user space provided information and is required only for the output queues. Buff request complete. It is a buffer that was never queued the driver, but is associated with the queued request which was cancelled. The driver will have to mark associated objects in the request as completed. It is required if this kind of requests are supported. The coming upcoming part of the presentation will be handled by my colleague Ajay from Samsung. Hello everybody. I am Ajay Kumar. I am from Foundry Design Solutions software team in Samsung Semiconductor India Research Team Bangalore. Today, I will be taking you guys through the remaining slides for VB to presentation. So there we will be discussing the main VB to calls and the mem ops we will be using the buff ops we will be using the queue ops we will be using. And then sum up all this into a flow chart to display how all these ops and the VB to calls work in tandem. So the main VB to calls we will be going through today are Rick buffs, EXP buff, Q buff, DQ buff, buffer done, stream on, stream off and core queue release. Let's get started with the Rick buffs. Rick buffs is used to allocate the memory for the buffer and the planes inside the buffer and it also initializes the VB to queue. EXP buff is for exporting the buffer. It exports a previously allocated buffer for use by another driver using a FD. Q buff queues a buffer to the software queue of the driver and it also makes the buffer and the hardware environment ready for the device usage. DQ buff is called to DQ the buffer from the software queue and it makes sure now the buffer can be used by the user space application or the kernel driver. VB to buffer done is called when the device has completely finished usage of this particular VB to buffer and also make sure now the buffer and the hardware environment is ready for CPU usage of the buffer. VB to stream on is for signaling start streaming inside the V4A2 driver. When we say streaming it is usually for the DMA operation. So stream on is responsible for DMA on inside the V4A2 driver. Similarly stream off is responsible for DMA off and it is possible by calling the stop streaming inside the driver. VB to core queue release is to destroy all the VB to buffers and the queues which we have allocated till now or mapped till now and also completely release all the memory related to the same. This is usually the last step of your application flow. Now let's go into each of these VB to calls in much more depth. So VB to rig buff stands for request buffers is usually called from the IOCTL VDOC rig buff. This calls the call VB to rig buff. VB to rig buff now goes to the driver callback for queue setup. Here the driver owner is supposed to take care of two things. One is specifying how many planes this buffer is going to use and what is the size for each plane of this buffer. So we packed that information in the queue setup call of the V4A2 driver. After this information is available, the VB to rig buff can go ahead for allocating the buffer using the memops alloc call. Also, please note that this alloc call is only called if your VB to buffer type is MF. Only when your VB to buffer type is MF, we actually allocate the buffer or allocate a new memory for the buffer. In case of other VB to memory types like user pointer or DMA buff, we don't actually allocate any new memory for the actual buffer, but we may probably create new memory only for the mappings. So after the alloc, we call buff in it in the V4A2 driver so that the driver can perform any initialization for the buffer. Next call we are going to discuss is queue buff. Again, this queue buff behaves differently for different VB to memory types like MF, user pointer and DMA buff. In this slide, we are going to discuss MF. If you remember from the previous slide, once we called rig buffs for MF, it already allocated the buffer memory for it and it also called buff in it for the same. So once we call queue buff here, you already have all the required memory information for the buffer. So we call buff prepare call of the V4A2 driver. This buff prepare is called for every queue buff call. And once the buff prepare call is called, then the memops prepare call is called. This memops prepare call usually contains the caching operation for the CPU side. After this caching call, the CPU would have flushed and make sure all the data in the buffer is ready for use by the device. So when the device accesses this buffer, there will be no side effects due to caching that is promised after this prepare call. So after the prepare, now the buffer is ready to be queued into the internal driver queue. So we are going to queue the same using the buff queue call. Remember, we could call prepare as soon as queue buff prepare because we already had the information of the buffer. In the next few slides, we will see if the buffer related memory information was not available, what extra steps we had to take. So let's go with the user pointer example. So if you remember from the rig buff call, in rig buff call, if the user memory type was vb2 user pointer, we actually did not call the alloc calls from memops. We actually skip that part and we even skip the buff init part. So since that buffer is being queued now, we have to make sure all the memory related information is grabbed before we queue into the driver queue. So in case of user pointer, the memops call the get user pointer. This function returns you a device address for the buffer I just allocated at user space. So now you have the device address, then you are going to call the buff init because till now you had not called buff init for this buffer. And this buff init is only called once. Even if you do multiple cycles of queue and dequeue for this buffer, buff init will only be called for the first time. After buff init, buff prepare is called for the v4l2 driver. Once the buff prepare is done, we go and call the memops prepare call. As we discussed prepare call, make sure the buffer is now ready for the device usage after syncing the buffer at CPU side. So now the buffer is ready for putting onto the device queue. We queue the same to using buff queue call. Similar to user pointer, we will not have memory related information. So we have to grab the memory related information using memops callback for the DMA buff. So when we would have got FD, the DMA buff FD from another driver passed to this in the cube of structure. So we take that FD, we get a DMA buff structure for the buffer. After we get the DMA buff structure, we call attach DMA buff. After we attach to the DMA buff, we can now call map underscore DMA buff. And this map DMA buff is going to return you the device address for the corresponding FD. So since now you got the device address, you can call buff init. As we mentioned in the previous slide, buff init will be called only once, even for the multiple cycles of queue and dequeue. So only in the first cycle buff init will be called. Thereon only buff prepare buff queue and prepare will be called. So after buff prepare, the CPU sync call prepare will be called. After memops prepare is called, your buffer is ready for use by the device. So we take it and queue the same using the referral to callback for buff queue. So till now we discussed rig buffs and how cube buff differs for different memory types. Going ahead, we will discuss about export buffer I have tell. This export buffer is for exporting the DMA buff FD. So let me give you a simple overview of how DMA buff works. In DMA buffer, we will have two entities. One is the exporter entity. Another will be a importer entity. The exporter entity usually creates a buffer and it exports the buffer with the FD. The FD is then passed on to the importer. Importer takes that FD and then calls its internal functions to attach to the DMA buff framework and get the necessary pages or mapping related information. So this slide represents a exporter and an importer and what happens during the rig buff call in the exporter and the importer. If you remember from the VB to MAP rig buff call for the MAP, we actually call the ALOCK. So here the memory was created for your buffer. Once your memory was created for the buffer, you call buffing it for the same. And if your memory type was DMA buff, this ALOCK will not be called. For this path, the ALOCK will not be called. It just calls QSETUP and it returns. So the PHY is only applicable for this path. In this slide, we will see what happens during the export buffer call of the exporter and the QBUFF of the importer. In the previous slide we have seen during rig buff, exporter had already allocated the buffer and importer rig buff did nothing but just the QSETUP call. So after the memory is allocated, exporter calls the callback VB to expBUFF. This expBUFF prepares a DMA buff FD for your buffer and it returns to the user space. Once your FD is available, this FD is passed on to the importer. This importer passes this FD to the QBUFF call and now this QBUFF call calls your GET DMA buff structure and attaches to the DMA buff. And after attaching to the DMA buff, it calls you MAP DMA buff. MAP DMA buff returns the device address for that FD. So once you have the device address, you go on with the init prepare and the memops prepare call to sync the buffer for the device usage. So once you have synced the buffer for device usage, you can queue the same using the buff queue. So from the previous slide and this slide, you got an idea how the DMA buffer is created in one V4L2 device and it was exchanged to another V4L2 device for the sharing. Till now we saw VB2 calls which also had an equivalent V4L2 IOctel in its name. But VB2 buffer done is not actually called from an IOctel. It is called from your V4L2 driver. Once your V4L2 device is done using a VB2 buffer, then the driver calls VB2 buffer done for that particular buffer. For VB2 buffer done, the driver also needs to pass a state flag. The state for the buffer can be buff state done or buff state error. As the name indicates, buff state done means it indicates the buffer was successfully processed by the device and the data inside the buffer can be deemed valid. If the buffer state was buff state error, then the buffer data can be chosen to be ignored. VB2 buffer done also calls memops finish call. This memops finish call is complementary to the memops prepare call which we called in QBuff state. In memops prepare call, we made sure now the VB2 buffer was synced from CPU side and was ready for usage by the device. In memops finish case, we make sure the buffer is synced from the device side and now it is ready to be used by the CPU. So after call to VB2 buffer done, now our buffer is ready to be used by consumption from CPU. VB2 DQBuff. VB2 DQBuff is called from VDF DQBuff Ioptel. VDF DQBuff Ioptel calls VB2 DQBuff. VB2 DQBuff mainly calls buff finish for all those buffers for which VB2 buffer done has already happened. In this buff finish, you can make sure if there is any manipulation is need to be done for the buffer data, you can do that in buff finish call. This is possible because that buffer was synced for CPU usage in prior call for VB2 buffer done. The DQBuff call can also be parsed with a non-blocking state flag which can detect whether the state of DQBuff should be blocking or non-blocking. There can be cases when application called DQBuff but there were no buffers ready to be DQD in your driver. In such case, we can make the user space wait till the buffers were available by making non-blocking flag as zero in which case it becomes the blocking state and two extra call gets called wait prepare and wait finish and this keeps looping inside the VB2 layer till buffers are available. Wait prepare call releases VB2 QLock before going into sleep till buffers are available. Wait finish helps in reacquiring that VB2 QLock after we have opened up by an event denoting that buffers are now available. The next call we are going to discuss is VB2 stream on. VB2 stream on is actually the call which triggers the DMA operation inside the driver. And if there are any buffers which were already queued before start streaming, they are now queued into the driver. When we were discussing QBuff call we safely assume that every buffer which was queued from application to VB2 layer was also queued to the driver internal queue but that is not always true that is only true if start streaming was enabled forever before into driver. VB2 stream off is to stop the DMA operation during stream off we might face different scenarios. When we are stopping the stream and there are few buffers which were already submitted to the driver for those buffers we need to explicitly call finish. This finish make sure those buffers are safe to be accessed by the CPU side. Also if there were any buffers for which VB2 buffer done was called but DQ buff was not called those buffers buff finish is called and made sure after this call user space access to those buffers is fine. The last VB2 call we are going to discuss is VB2 core Q release. This is also the last VB2 call which gets called in the application flow. This usually gets called when we are closing the FD so we are closing the FD means we need to D in it all the queues destroy all the queues destroy all the mappings which we have created and free the buffer memories any. So core Q release make sure if the driver is still streaming gets stop streaming and then the finish is called for those buffers for which VB2 buffer done was not called yet. And then calls buff finish for those buffers for which VB2 buffer done was called but was not DQ yet. So after buff finish it is ready to be DQ and then it calls buff cleanup for the initialization of any buffer. Buff cleanup is complementary to the buff in it which was called during the rig buff stage. After buff cleanup now all the V4L2 and VB2 stuff is taken care of we need to release the buffer memory buffer memory is released from the put call. This whole slide keeps in mind a use case of memory type M map only in memory type M map we are actually freeing the buffer memory for VB2 buffer using the put call. In case of user pointer and also DM above all the preliminary steps remain the same but what kind of mappings we remove do differs. As we know there was no buffer created in user point of state we only created the mappings. So we put back those mapping and free them using the put user PTR call in VB2 DM above memory type case again the preliminary step remain same the way how we release the mappings or free the mappings differs. So we have the FD now using the FD we get the DM above structure and from the DM above structure we call unmapped DM above followed by detached DM above after this there will be no buffer map. In now we have seen the implementation of major VB2 calls and how they make use of ops like VB2 memops and the VB2 queue ops. Now we are going to add an extra layer DM a map ops and discuss the same calls how they work in tandem to achieve our VB2 goal. We will take an example of a map exporter under DM above importer to explain the same in step one the exporter is going to create the buffer. So the exporter called VB2 core rebuff with a map memory type which in turn called the memops a lock the memops a lock then calls the lock function from the DM a map ops layer. After the buffer is allocated the VB2 core calls VB2 ops buff in it which is the driver implementation for buffing it. Here the driver does any initialization required for the buffer. In step two the exporter is creating a DM above FD for the buffer created in step one the VB2 core exp buff calls memops get DM above which in turn calls the DM a map ops call get SG table for the buffer created with the SG table. It creates the DM above export structure and then creates the DM above FD for the same and returns from the exporter. Step three is how the importer has received the FD and it is queuing to the driver. After the importer has received the FD in cube of call it attaches to the DM above FD using the FD. After attaching it calls map DM above where we get the device address map DM above got the address by calling map underscore SG from the DM a map ops layer. After this VB2 core layer calls buff prepare in the driver. And then we are calling memops prepare to make sure now the buffer is synced from the CPU side and is ready to be used from the device side that happens by the call to DM a map ops layer sync SG for device. In steps one two three the buffer was created to sex ported and imported and put on to the device queue. In step four the importer has now processed the buffer and it is calling VB2 buffer done. VB2 buffer done internally uses memops call for finish which is a complimentary call for this memops prepare in finish we are syncing the buffer from device side and we are making it ready to be used from the CPU side by calling the DM a map ops sync SG for CPU. After VB2 buffer done the buffer should be ready to be DQ to the user space we do the same by calling DQ buff VB2 core DQ buff in turn calls the buff finish in the driver. Now all the buffer consumption is complete so we are releasing the buffers and the buffer mappings for the importer here VB2 core queue release gets called when we are closing the FD for the importer that in turn calls buff finish if there are any buffers which are pending to be DQ and then it calls buff underscore clean up in the driver. After that unmapped DMA buff is called from the memops layer which calls the unmapped SG from the DMA map ops layer here the mapping is released after the mapping is released the detached DMA buff call happens. What remains is the freeing of the buffer from the exporter which is done in step 7 VB2 core queue release gets called for the exporter which in turn calls the memops put where we actually free the buffer memory. How it is freed? It is freed by the call to DMA map ops layer free call. By this we reach the end of the presentation if you have any questions regarding this presentation or any question in general related to VB2 you can feel free to ask the same.