Re: [PATCH 2/9] dma: Convert from tasklet to BH workqueue
On 02-04-24, 14:25, Linus Walleij wrote: > Hi Allen, > > thanks for your patch! > > On Wed, Mar 27, 2024 at 5:03 PM Allen Pais wrote: > > > The only generic interface to execute asynchronously in the BH context is > > tasklet; however, it's marked deprecated and has some design flaws. To > > replace tasklets, BH workqueue support was recently added. A BH workqueue > > behaves similarly to regular workqueues except that the queued work items > > are executed in the BH context. > > > > This patch converts drivers/dma/* from tasklet to BH workqueue. > > > > Based on the work done by Tejun Heo > > Branch: git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 > > > > Signed-off-by: Allen Pais > (...) > > diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c > (...) > > if (d40c->pending_tx) > > - tasklet_schedule(&d40c->tasklet); > > + queue_work(system_bh_wq, &d40c->work); > > Why is "my" driver not allowed to use system_bh_highpri_wq? > > I can't see the reasoning between some drivers using system_bh_wq > and others being highpri? > > Given the DMA usecase I would expect them all to be high prio. It didnt use tasklet_hi_schedule(), I guess Allen has done the conversion of tasklet_schedule -> system_bh_wq and tasklet_hi_schedule -> system_bh_highpri_wq Anyway, we are going to use a dma queue so should be better performance -- ~Vinod
Re: [PATCH 2/9] dma: Convert from tasklet to BH workqueue
Hi Allen, thanks for your patch! On Wed, Mar 27, 2024 at 5:03 PM Allen Pais wrote: > The only generic interface to execute asynchronously in the BH context is > tasklet; however, it's marked deprecated and has some design flaws. To > replace tasklets, BH workqueue support was recently added. A BH workqueue > behaves similarly to regular workqueues except that the queued work items > are executed in the BH context. > > This patch converts drivers/dma/* from tasklet to BH workqueue. > > Based on the work done by Tejun Heo > Branch: git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 > > Signed-off-by: Allen Pais (...) > diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c (...) > if (d40c->pending_tx) > - tasklet_schedule(&d40c->tasklet); > + queue_work(system_bh_wq, &d40c->work); Why is "my" driver not allowed to use system_bh_highpri_wq? I can't see the reasoning between some drivers using system_bh_wq and others being highpri? Given the DMA usecase I would expect them all to be high prio. Yours, Linus Walleij
Re: [PATCH 2/9] dma: Convert from tasklet to BH workqueue
On 28-03-24, 12:39, Allen wrote: > > I think that is very great idea. having this wrapped in dma_chan would > > be very good way as well > > > > Am not sure if Allen is up for it :-) > > Thanks Arnd, I know we did speak about this at LPC. I did start > working on using completion. I dropped it as I thought it would > be easier to move to workqueues. > > Vinod, I would like to give this a shot and put out a RFC, I would > really appreciate review and feedback. Sounds like a good plan to me -- ~Vinod
Re: [PATCH 2/9] dma: Convert from tasklet to BH workqueue
On 28-03-24, 13:01, Allen wrote: > > >> > Since almost every driver associates the tasklet with the > > >> > dma_chan, we could go one step further and add the > > >> > work_queue structure directly into struct dma_chan, > > >> > with the wrapper operating on the dma_chan rather than > > >> > the work_queue. > > >> > > >> I think that is very great idea. having this wrapped in dma_chan would > > >> be very good way as well > > >> > > >> Am not sure if Allen is up for it :-) > > > > > > Thanks Arnd, I know we did speak about this at LPC. I did start > > > working on using completion. I dropped it as I thought it would > > > be easier to move to workqueues. > > > > It's definitely easier to do the workqueue conversion as a first > > step, and I agree adding support for the completion right away is > > probably too much. Moving the work_struct into the dma_chan > > is probably not too hard though, if you leave your current > > approach for the cases where the tasklet is part of the > > dma_dev rather than the dma_chan. > > > > Alright, I will work on moving work_struck into the dma_chan and > leave the dma_dev as is (using bh workqueues) and post a RFC. > Once reviewed, I could move to the next step. That might be better from a performance pov but the current design is a global tasklet and not a per chan one... We would need to carefully review and test this for sure -- ~Vinod
Re: [PATCH 2/9] dma: Convert from tasklet to BH workqueue
> >> > Since almost every driver associates the tasklet with the > >> > dma_chan, we could go one step further and add the > >> > work_queue structure directly into struct dma_chan, > >> > with the wrapper operating on the dma_chan rather than > >> > the work_queue. > >> > >> I think that is very great idea. having this wrapped in dma_chan would > >> be very good way as well > >> > >> Am not sure if Allen is up for it :-) > > > > Thanks Arnd, I know we did speak about this at LPC. I did start > > working on using completion. I dropped it as I thought it would > > be easier to move to workqueues. > > It's definitely easier to do the workqueue conversion as a first > step, and I agree adding support for the completion right away is > probably too much. Moving the work_struct into the dma_chan > is probably not too hard though, if you leave your current > approach for the cases where the tasklet is part of the > dma_dev rather than the dma_chan. > Alright, I will work on moving work_struck into the dma_chan and leave the dma_dev as is (using bh workqueues) and post a RFC. Once reviewed, I could move to the next step. Thank you. - Allen
Re: [PATCH 2/9] dma: Convert from tasklet to BH workqueue
On Thu, Mar 28, 2024, at 20:39, Allen wrote: >> > >> > Since almost every driver associates the tasklet with the >> > dma_chan, we could go one step further and add the >> > work_queue structure directly into struct dma_chan, >> > with the wrapper operating on the dma_chan rather than >> > the work_queue. >> >> I think that is very great idea. having this wrapped in dma_chan would >> be very good way as well >> >> Am not sure if Allen is up for it :-) > > Thanks Arnd, I know we did speak about this at LPC. I did start > working on using completion. I dropped it as I thought it would > be easier to move to workqueues. It's definitely easier to do the workqueue conversion as a first step, and I agree adding support for the completion right away is probably too much. Moving the work_struct into the dma_chan is probably not too hard though, if you leave your current approach for the cases where the tasklet is part of the dma_dev rather than the dma_chan. Arnd
Re: [PATCH 2/9] dma: Convert from tasklet to BH workqueue
> > >> The only generic interface to execute asynchronously in the BH context is > > >> tasklet; however, it's marked deprecated and has some design flaws. To > > >> replace tasklets, BH workqueue support was recently added. A BH workqueue > > >> behaves similarly to regular workqueues except that the queued work items > > >> are executed in the BH context. > > > > > > Thanks for conversion, am happy with BH alternative as it helps in > > > dmaengine where we need shortest possible time between tasklet and > > > interrupt handling to maximize dma performance > > > > I still feel that we want something different for dmaengine, > > at least in the long run. As we have discussed in the past, > > the tasklet context in these drivers is what the callbacks > > from the dma client device is run in, and a lot of these probably > > want something other than tasklet context, e.g. just call > > complete() on a client-provided completion structure. > > > > Instead of open-coding the use of the system_bh_wq in each > > dmaengine, how about we start with a custom WQ_BH > > specifically for the dmaengine subsystem and wrap them > > inside of another interface. > > > > Since almost every driver associates the tasklet with the > > dma_chan, we could go one step further and add the > > work_queue structure directly into struct dma_chan, > > with the wrapper operating on the dma_chan rather than > > the work_queue. > > I think that is very great idea. having this wrapped in dma_chan would > be very good way as well > > Am not sure if Allen is up for it :-) Thanks Arnd, I know we did speak about this at LPC. I did start working on using completion. I dropped it as I thought it would be easier to move to workqueues. Vinod, I would like to give this a shot and put out a RFC, I would really appreciate review and feedback. Thanks, Allen > > -- > ~Vinod >
Re: [PATCH 2/9] dma: Convert from tasklet to BH workqueue
On 28-03-24, 11:08, Arnd Bergmann wrote: > On Thu, Mar 28, 2024, at 06:55, Vinod Koul wrote: > > On 27-03-24, 16:03, Allen Pais wrote: > >> The only generic interface to execute asynchronously in the BH context is > >> tasklet; however, it's marked deprecated and has some design flaws. To > >> replace tasklets, BH workqueue support was recently added. A BH workqueue > >> behaves similarly to regular workqueues except that the queued work items > >> are executed in the BH context. > > > > Thanks for conversion, am happy with BH alternative as it helps in > > dmaengine where we need shortest possible time between tasklet and > > interrupt handling to maximize dma performance > > I still feel that we want something different for dmaengine, > at least in the long run. As we have discussed in the past, > the tasklet context in these drivers is what the callbacks > from the dma client device is run in, and a lot of these probably > want something other than tasklet context, e.g. just call > complete() on a client-provided completion structure. > > Instead of open-coding the use of the system_bh_wq in each > dmaengine, how about we start with a custom WQ_BH > specifically for the dmaengine subsystem and wrap them > inside of another interface. > > Since almost every driver associates the tasklet with the > dma_chan, we could go one step further and add the > work_queue structure directly into struct dma_chan, > with the wrapper operating on the dma_chan rather than > the work_queue. I think that is very great idea. having this wrapped in dma_chan would be very good way as well Am not sure if Allen is up for it :-) -- ~Vinod
Re: [PATCH 2/9] dma: Convert from tasklet to BH workqueue
> > Subsytem is dmaengine, can you rename this to dmaengine: ... My apologies, will have it fixed in v2. > > On 27-03-24, 16:03, Allen Pais wrote: > > The only generic interface to execute asynchronously in the BH context is > > tasklet; however, it's marked deprecated and has some design flaws. To > > replace tasklets, BH workqueue support was recently added. A BH workqueue > > behaves similarly to regular workqueues except that the queued work items > > are executed in the BH context. > > Thanks for conversion, am happy with BH alternative as it helps in > dmaengine where we need shortest possible time between tasklet and > interrupt handling to maximize dma performance > > > > > This patch converts drivers/dma/* from tasklet to BH workqueue. > > > > > Based on the work done by Tejun Heo > > Branch: git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 > > > > Signed-off-by: Allen Pais > > --- > > drivers/dma/altera-msgdma.c | 15 > > drivers/dma/apple-admac.c | 15 > > drivers/dma/at_hdmac.c| 2 +- > > drivers/dma/at_xdmac.c| 15 > > drivers/dma/bcm2835-dma.c | 2 +- > > drivers/dma/dma-axi-dmac.c| 2 +- > > drivers/dma/dma-jz4780.c | 2 +- > > .../dma/dw-axi-dmac/dw-axi-dmac-platform.c| 2 +- > > drivers/dma/dw-edma/dw-edma-core.c| 2 +- > > drivers/dma/dw/core.c | 13 +++ > > drivers/dma/dw/regs.h | 3 +- > > drivers/dma/ep93xx_dma.c | 15 > > drivers/dma/fsl-edma-common.c | 2 +- > > drivers/dma/fsl-qdma.c| 2 +- > > drivers/dma/fsl_raid.c| 11 +++--- > > drivers/dma/fsl_raid.h| 2 +- > > drivers/dma/fsldma.c | 15 > > drivers/dma/fsldma.h | 3 +- > > drivers/dma/hisi_dma.c| 2 +- > > drivers/dma/hsu/hsu.c | 2 +- > > drivers/dma/idma64.c | 4 +-- > > drivers/dma/img-mdc-dma.c | 2 +- > > drivers/dma/imx-dma.c | 27 +++--- > > drivers/dma/imx-sdma.c| 6 ++-- > > drivers/dma/ioat/dma.c| 17 - > > drivers/dma/ioat/dma.h| 5 +-- > > drivers/dma/ioat/init.c | 2 +- > > drivers/dma/k3dma.c | 19 +- > > drivers/dma/mediatek/mtk-cqdma.c | 35 ++- > > drivers/dma/mediatek/mtk-hsdma.c | 2 +- > > drivers/dma/mediatek/mtk-uart-apdma.c | 4 +-- > > drivers/dma/mmp_pdma.c| 13 +++ > > drivers/dma/mmp_tdma.c| 11 +++--- > > drivers/dma/mpc512x_dma.c | 17 - > > drivers/dma/mv_xor.c | 13 +++ > > drivers/dma/mv_xor.h | 5 +-- > > drivers/dma/mv_xor_v2.c | 23 ++-- > > drivers/dma/mxs-dma.c | 13 +++ > > drivers/dma/nbpfaxi.c | 15 > > drivers/dma/owl-dma.c | 2 +- > > drivers/dma/pch_dma.c | 17 - > > drivers/dma/pl330.c | 31 > > drivers/dma/plx_dma.c | 13 +++ > > drivers/dma/ppc4xx/adma.c | 17 - > > drivers/dma/ppc4xx/adma.h | 5 +-- > > drivers/dma/pxa_dma.c | 2 +- > > drivers/dma/qcom/bam_dma.c| 35 ++- > > drivers/dma/qcom/gpi.c| 18 +- > > drivers/dma/qcom/hidma.c | 11 +++--- > > drivers/dma/qcom/hidma.h | 5 +-- > > drivers/dma/qcom/hidma_ll.c | 11 +++--- > > drivers/dma/qcom/qcom_adm.c | 2 +- > > drivers/dma/sa11x0-dma.c | 27 +++--- > > drivers/dma/sf-pdma/sf-pdma.c | 23 ++-- > > drivers/dma/sf-pdma/sf-pdma.h | 5 +-- > > drivers/dma/sprd-dma.c| 2 +- > > drivers/dma/st_fdma.c | 2 +- > > drivers/dma/ste_dma40.c | 17 - > > drivers/dma/sun6i-dma.c | 33 - > > drivers/dma/tegra186-gpc-dma.c| 2 +- > > drivers/dma/tegra20-apb-dma.c | 19 +- > > drivers/dma/tegra210-adma.c | 2 +- > > drivers/dma/ti/edma.c | 2 +- > > drivers/dma/ti/k3-udma.c | 11 +++--- > > drivers/dma/ti/omap-dma.c
Re: [PATCH 2/9] dma: Convert from tasklet to BH workqueue
On Thu, Mar 28, 2024, at 06:55, Vinod Koul wrote: > On 27-03-24, 16:03, Allen Pais wrote: >> The only generic interface to execute asynchronously in the BH context is >> tasklet; however, it's marked deprecated and has some design flaws. To >> replace tasklets, BH workqueue support was recently added. A BH workqueue >> behaves similarly to regular workqueues except that the queued work items >> are executed in the BH context. > > Thanks for conversion, am happy with BH alternative as it helps in > dmaengine where we need shortest possible time between tasklet and > interrupt handling to maximize dma performance I still feel that we want something different for dmaengine, at least in the long run. As we have discussed in the past, the tasklet context in these drivers is what the callbacks from the dma client device is run in, and a lot of these probably want something other than tasklet context, e.g. just call complete() on a client-provided completion structure. Instead of open-coding the use of the system_bh_wq in each dmaengine, how about we start with a custom WQ_BH specifically for the dmaengine subsystem and wrap them inside of another interface. Since almost every driver associates the tasklet with the dma_chan, we could go one step further and add the work_queue structure directly into struct dma_chan, with the wrapper operating on the dma_chan rather than the work_queue. Arnd
Re: [PATCH 2/9] dma: Convert from tasklet to BH workqueue
Hi Allen, Subsytem is dmaengine, can you rename this to dmaengine: ... On 27-03-24, 16:03, Allen Pais wrote: > The only generic interface to execute asynchronously in the BH context is > tasklet; however, it's marked deprecated and has some design flaws. To > replace tasklets, BH workqueue support was recently added. A BH workqueue > behaves similarly to regular workqueues except that the queued work items > are executed in the BH context. Thanks for conversion, am happy with BH alternative as it helps in dmaengine where we need shortest possible time between tasklet and interrupt handling to maximize dma performance > > This patch converts drivers/dma/* from tasklet to BH workqueue. > > Based on the work done by Tejun Heo > Branch: git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 > > Signed-off-by: Allen Pais > --- > drivers/dma/altera-msgdma.c | 15 > drivers/dma/apple-admac.c | 15 > drivers/dma/at_hdmac.c| 2 +- > drivers/dma/at_xdmac.c| 15 > drivers/dma/bcm2835-dma.c | 2 +- > drivers/dma/dma-axi-dmac.c| 2 +- > drivers/dma/dma-jz4780.c | 2 +- > .../dma/dw-axi-dmac/dw-axi-dmac-platform.c| 2 +- > drivers/dma/dw-edma/dw-edma-core.c| 2 +- > drivers/dma/dw/core.c | 13 +++ > drivers/dma/dw/regs.h | 3 +- > drivers/dma/ep93xx_dma.c | 15 > drivers/dma/fsl-edma-common.c | 2 +- > drivers/dma/fsl-qdma.c| 2 +- > drivers/dma/fsl_raid.c| 11 +++--- > drivers/dma/fsl_raid.h| 2 +- > drivers/dma/fsldma.c | 15 > drivers/dma/fsldma.h | 3 +- > drivers/dma/hisi_dma.c| 2 +- > drivers/dma/hsu/hsu.c | 2 +- > drivers/dma/idma64.c | 4 +-- > drivers/dma/img-mdc-dma.c | 2 +- > drivers/dma/imx-dma.c | 27 +++--- > drivers/dma/imx-sdma.c| 6 ++-- > drivers/dma/ioat/dma.c| 17 - > drivers/dma/ioat/dma.h| 5 +-- > drivers/dma/ioat/init.c | 2 +- > drivers/dma/k3dma.c | 19 +- > drivers/dma/mediatek/mtk-cqdma.c | 35 ++- > drivers/dma/mediatek/mtk-hsdma.c | 2 +- > drivers/dma/mediatek/mtk-uart-apdma.c | 4 +-- > drivers/dma/mmp_pdma.c| 13 +++ > drivers/dma/mmp_tdma.c| 11 +++--- > drivers/dma/mpc512x_dma.c | 17 - > drivers/dma/mv_xor.c | 13 +++ > drivers/dma/mv_xor.h | 5 +-- > drivers/dma/mv_xor_v2.c | 23 ++-- > drivers/dma/mxs-dma.c | 13 +++ > drivers/dma/nbpfaxi.c | 15 > drivers/dma/owl-dma.c | 2 +- > drivers/dma/pch_dma.c | 17 - > drivers/dma/pl330.c | 31 > drivers/dma/plx_dma.c | 13 +++ > drivers/dma/ppc4xx/adma.c | 17 - > drivers/dma/ppc4xx/adma.h | 5 +-- > drivers/dma/pxa_dma.c | 2 +- > drivers/dma/qcom/bam_dma.c| 35 ++- > drivers/dma/qcom/gpi.c| 18 +- > drivers/dma/qcom/hidma.c | 11 +++--- > drivers/dma/qcom/hidma.h | 5 +-- > drivers/dma/qcom/hidma_ll.c | 11 +++--- > drivers/dma/qcom/qcom_adm.c | 2 +- > drivers/dma/sa11x0-dma.c | 27 +++--- > drivers/dma/sf-pdma/sf-pdma.c | 23 ++-- > drivers/dma/sf-pdma/sf-pdma.h | 5 +-- > drivers/dma/sprd-dma.c| 2 +- > drivers/dma/st_fdma.c | 2 +- > drivers/dma/ste_dma40.c | 17 - > drivers/dma/sun6i-dma.c | 33 - > drivers/dma/tegra186-gpc-dma.c| 2 +- > drivers/dma/tegra20-apb-dma.c | 19 +- > drivers/dma/tegra210-adma.c | 2 +- > drivers/dma/ti/edma.c | 2 +- > drivers/dma/ti/k3-udma.c | 11 +++--- > drivers/dma/ti/omap-dma.c | 2 +- > drivers/dma/timb_dma.c| 23 ++-- > drivers/dma/txx9dmac.c| 29 +++ > drivers/dma/txx9dmac.h
[PATCH 2/9] dma: Convert from tasklet to BH workqueue
The only generic interface to execute asynchronously in the BH context is tasklet; however, it's marked deprecated and has some design flaws. To replace tasklets, BH workqueue support was recently added. A BH workqueue behaves similarly to regular workqueues except that the queued work items are executed in the BH context. This patch converts drivers/dma/* from tasklet to BH workqueue. Based on the work done by Tejun Heo Branch: git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git for-6.10 Signed-off-by: Allen Pais --- drivers/dma/altera-msgdma.c | 15 drivers/dma/apple-admac.c | 15 drivers/dma/at_hdmac.c| 2 +- drivers/dma/at_xdmac.c| 15 drivers/dma/bcm2835-dma.c | 2 +- drivers/dma/dma-axi-dmac.c| 2 +- drivers/dma/dma-jz4780.c | 2 +- .../dma/dw-axi-dmac/dw-axi-dmac-platform.c| 2 +- drivers/dma/dw-edma/dw-edma-core.c| 2 +- drivers/dma/dw/core.c | 13 +++ drivers/dma/dw/regs.h | 3 +- drivers/dma/ep93xx_dma.c | 15 drivers/dma/fsl-edma-common.c | 2 +- drivers/dma/fsl-qdma.c| 2 +- drivers/dma/fsl_raid.c| 11 +++--- drivers/dma/fsl_raid.h| 2 +- drivers/dma/fsldma.c | 15 drivers/dma/fsldma.h | 3 +- drivers/dma/hisi_dma.c| 2 +- drivers/dma/hsu/hsu.c | 2 +- drivers/dma/idma64.c | 4 +-- drivers/dma/img-mdc-dma.c | 2 +- drivers/dma/imx-dma.c | 27 +++--- drivers/dma/imx-sdma.c| 6 ++-- drivers/dma/ioat/dma.c| 17 - drivers/dma/ioat/dma.h| 5 +-- drivers/dma/ioat/init.c | 2 +- drivers/dma/k3dma.c | 19 +- drivers/dma/mediatek/mtk-cqdma.c | 35 ++- drivers/dma/mediatek/mtk-hsdma.c | 2 +- drivers/dma/mediatek/mtk-uart-apdma.c | 4 +-- drivers/dma/mmp_pdma.c| 13 +++ drivers/dma/mmp_tdma.c| 11 +++--- drivers/dma/mpc512x_dma.c | 17 - drivers/dma/mv_xor.c | 13 +++ drivers/dma/mv_xor.h | 5 +-- drivers/dma/mv_xor_v2.c | 23 ++-- drivers/dma/mxs-dma.c | 13 +++ drivers/dma/nbpfaxi.c | 15 drivers/dma/owl-dma.c | 2 +- drivers/dma/pch_dma.c | 17 - drivers/dma/pl330.c | 31 drivers/dma/plx_dma.c | 13 +++ drivers/dma/ppc4xx/adma.c | 17 - drivers/dma/ppc4xx/adma.h | 5 +-- drivers/dma/pxa_dma.c | 2 +- drivers/dma/qcom/bam_dma.c| 35 ++- drivers/dma/qcom/gpi.c| 18 +- drivers/dma/qcom/hidma.c | 11 +++--- drivers/dma/qcom/hidma.h | 5 +-- drivers/dma/qcom/hidma_ll.c | 11 +++--- drivers/dma/qcom/qcom_adm.c | 2 +- drivers/dma/sa11x0-dma.c | 27 +++--- drivers/dma/sf-pdma/sf-pdma.c | 23 ++-- drivers/dma/sf-pdma/sf-pdma.h | 5 +-- drivers/dma/sprd-dma.c| 2 +- drivers/dma/st_fdma.c | 2 +- drivers/dma/ste_dma40.c | 17 - drivers/dma/sun6i-dma.c | 33 - drivers/dma/tegra186-gpc-dma.c| 2 +- drivers/dma/tegra20-apb-dma.c | 19 +- drivers/dma/tegra210-adma.c | 2 +- drivers/dma/ti/edma.c | 2 +- drivers/dma/ti/k3-udma.c | 11 +++--- drivers/dma/ti/omap-dma.c | 2 +- drivers/dma/timb_dma.c| 23 ++-- drivers/dma/txx9dmac.c| 29 +++ drivers/dma/txx9dmac.h| 5 +-- drivers/dma/virt-dma.c| 9 ++--- drivers/dma/virt-dma.h| 9 ++--- drivers/dma/xgene-dma.c | 21 +-- drivers/dma/xilinx/xilinx_dma.c | 23 ++-- drivers/dma/xilinx/xilinx_dpdma.c | 21 +-- drivers/dma/xilinx/zynqmp_dma.c | 21 +-- 74 files changed, 442 insertions(+), 395 deletions(-) diff --git a/driv