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

dmaengine: shdma: use normal interface for passing slave id

in dma_slave_config, which is incompatible with the way that the
dmaengine API normally works.

I've had a closer look at the existing code now and found that all
slave drivers that pass a slave_id in dma_slave_config for SH do that
right after passing the same ID into shdma_chan_filter, so we can just
rely on that. However, the various shdma drivers currently do not
remember the slave ID that was passed into the filter function when
used in non-DT mode and only check the value to find a matching channel,
unlike all other drivers.

There might still be drivers that are not part of the kernel that rely
on setting the slave_id to some other value, so to be on the safe side,
this adds another 'real_slave_id' field to shdma_chan that remembers
the ID and uses it when a driver passes a zero slave_id in dma_slave_config,
like most drivers do.

Eventually, the real_slave_id and slave_id fields should just get merged
into one field, but that requires other changes.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>

authored by

Arnd Bergmann and committed by
Vinod Koul
411fdaf8 c517d838

+56 -22
+55 -22
drivers/dma/sh/shdma-base.c
··· 171 171 return NULL; 172 172 } 173 173 174 - static int shdma_setup_slave(struct shdma_chan *schan, int slave_id, 175 - dma_addr_t slave_addr) 174 + static int shdma_setup_slave(struct shdma_chan *schan, dma_addr_t slave_addr) 176 175 { 177 176 struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device); 178 177 const struct shdma_ops *ops = sdev->ops; ··· 182 183 ret = ops->set_slave(schan, match, slave_addr, true); 183 184 if (ret < 0) 184 185 return ret; 185 - 186 - slave_id = schan->slave_id; 187 186 } else { 188 - match = slave_id; 187 + match = schan->real_slave_id; 189 188 } 190 189 191 - if (slave_id < 0 || slave_id >= slave_num) 190 + if (schan->real_slave_id < 0 || schan->real_slave_id >= slave_num) 192 191 return -EINVAL; 193 192 194 - if (test_and_set_bit(slave_id, shdma_slave_used)) 193 + if (test_and_set_bit(schan->real_slave_id, shdma_slave_used)) 195 194 return -EBUSY; 196 195 197 196 ret = ops->set_slave(schan, match, slave_addr, false); 198 197 if (ret < 0) { 199 - clear_bit(slave_id, shdma_slave_used); 198 + clear_bit(schan->real_slave_id, shdma_slave_used); 200 199 return ret; 201 200 } 202 201 203 - schan->slave_id = slave_id; 202 + schan->slave_id = schan->real_slave_id; 204 203 205 204 return 0; 206 205 } ··· 218 221 */ 219 222 if (slave) { 220 223 /* Legacy mode: .private is set in filter */ 221 - ret = shdma_setup_slave(schan, slave->slave_id, 0); 224 + schan->real_slave_id = slave->slave_id; 225 + ret = shdma_setup_slave(schan, 0); 222 226 if (ret < 0) 223 227 goto esetslave; 224 228 } else { 229 + /* Normal mode: real_slave_id was set by filter */ 225 230 schan->slave_id = -EINVAL; 226 231 } 227 232 ··· 257 258 258 259 /* 259 260 * This is the standard shdma filter function to be used as a replacement to the 260 - * "old" method, using the .private pointer. If for some reason you allocate a 261 - * channel without slave data, use something like ERR_PTR(-EINVAL) as a filter 261 + * "old" method, using the .private pointer. 262 + * You always have to pass a valid slave id as the argument, old drivers that 263 + * pass ERR_PTR(-EINVAL) as a filter parameter and set it up in dma_slave_config 264 + * need to be updated so we can remove the slave_id field from dma_slave_config. 262 265 * parameter. If this filter is used, the slave driver, after calling 263 266 * dma_request_channel(), will also have to call dmaengine_slave_config() with 264 - * .slave_id, .direction, and either .src_addr or .dst_addr set. 267 + * .direction, and either .src_addr or .dst_addr set. 268 + * 265 269 * NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE 266 270 * capability! If this becomes a requirement, hardware glue drivers, using this 267 271 * services would have to provide their own filters, which first would check ··· 278 276 { 279 277 struct shdma_chan *schan; 280 278 struct shdma_dev *sdev; 281 - int match = (long)arg; 279 + int slave_id = (long)arg; 282 280 int ret; 283 281 284 282 /* Only support channels handled by this driver. */ ··· 286 284 shdma_alloc_chan_resources) 287 285 return false; 288 286 289 - if (match < 0) 290 - /* No slave requested - arbitrary channel */ 291 - return true; 292 - 293 287 schan = to_shdma_chan(chan); 294 - if (!schan->dev->of_node && match >= slave_num) 288 + sdev = to_shdma_dev(chan->device); 289 + 290 + /* 291 + * For DT, the schan->slave_id field is generated by the 292 + * set_slave function from the slave ID that is passed in 293 + * from xlate. For the non-DT case, the slave ID is 294 + * directly passed into the filter function by the driver 295 + */ 296 + if (schan->dev->of_node) { 297 + ret = sdev->ops->set_slave(schan, slave_id, 0, true); 298 + if (ret < 0) 299 + return false; 300 + 301 + schan->real_slave_id = schan->slave_id; 302 + return true; 303 + } 304 + 305 + if (slave_id < 0) { 306 + /* No slave requested - arbitrary channel */ 307 + dev_warn(sdev->dma_dev.dev, "invalid slave ID passed to dma_request_slave\n"); 308 + return true; 309 + } 310 + 311 + if (slave_id >= slave_num) 295 312 return false; 296 313 297 - sdev = to_shdma_dev(schan->dma_chan.device); 298 - ret = sdev->ops->set_slave(schan, match, 0, true); 314 + ret = sdev->ops->set_slave(schan, slave_id, 0, true); 299 315 if (ret < 0) 300 316 return false; 317 + 318 + schan->real_slave_id = slave_id; 301 319 302 320 return true; 303 321 } ··· 473 451 clear_bit(schan->slave_id, shdma_slave_used); 474 452 chan->private = NULL; 475 453 } 454 + 455 + schan->real_slave_id = 0; 476 456 477 457 spin_lock_irq(&schan->chan_lock); 478 458 ··· 788 764 */ 789 765 if (!config) 790 766 return -EINVAL; 767 + 768 + /* 769 + * overriding the slave_id through dma_slave_config is deprecated, 770 + * but possibly some out-of-tree drivers still do it. 771 + */ 772 + if (WARN_ON_ONCE(config->slave_id && 773 + config->slave_id != schan->real_slave_id)) 774 + schan->real_slave_id = config->slave_id; 775 + 791 776 /* 792 777 * We could lock this, but you shouldn't be configuring the 793 778 * channel, while using it... 794 779 */ 795 - return shdma_setup_slave(schan, config->slave_id, 780 + return shdma_setup_slave(schan, 796 781 config->direction == DMA_DEV_TO_MEM ? 797 782 config->src_addr : config->dst_addr); 798 783 }
+1
include/linux/shdma-base.h
··· 69 69 int id; /* Raw id of this channel */ 70 70 int irq; /* Channel IRQ */ 71 71 int slave_id; /* Client ID for slave DMA */ 72 + int real_slave_id; /* argument passed to filter function */ 72 73 int hw_req; /* DMA request line for slave DMA - same 73 74 * as MID/RID, used with DT */ 74 75 enum shdma_pm_state pm_state;