mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
media: siano: Fix coherent memory allocation failure on arm64
On some architectures such as arm64, siano chip based TV-tuner USB devices are not recognized correctly due to coherent memory allocation failure with the following error: [ 663.556135] usbcore: deregistering interface driver smsusb [ 683.624809] smsusb:smsusb_probe: board id=18, interface number 0 [ 683.633530] smsusb:smsusb_init_device: smscore_register_device(...) failed, rc -12 [ 683.641501] smsusb:smsusb_probe: Device initialized with return code -12 [ 683.652978] smsusb: probe of 1-1:1.0 failed with error -12 This is caused by dma_alloc_coherent(NULL, ...) returning NULL in smscoreapi.c. To fix this error, allocate the buffer memory for the USB devices via kmalloc() and let the USB core do the DMA mapping and free. Signed-off-by: Tomoki Sekiyama <tomoki.sekiyama@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
parent
e97c19074f
commit
564246fd3f
@ -631,7 +631,8 @@ smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
|
|||||||
|
|
||||||
cb->p = buffer;
|
cb->p = buffer;
|
||||||
cb->offset_in_common = buffer - (u8 *) common_buffer;
|
cb->offset_in_common = buffer - (u8 *) common_buffer;
|
||||||
cb->phys = common_buffer_phys + cb->offset_in_common;
|
if (common_buffer_phys)
|
||||||
|
cb->phys = common_buffer_phys + cb->offset_in_common;
|
||||||
|
|
||||||
return cb;
|
return cb;
|
||||||
}
|
}
|
||||||
@ -690,17 +691,21 @@ int smscore_register_device(struct smsdevice_params_t *params,
|
|||||||
|
|
||||||
/* alloc common buffer */
|
/* alloc common buffer */
|
||||||
dev->common_buffer_size = params->buffer_size * params->num_buffers;
|
dev->common_buffer_size = params->buffer_size * params->num_buffers;
|
||||||
dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size,
|
if (params->usb_device)
|
||||||
&dev->common_buffer_phys,
|
buffer = kzalloc(dev->common_buffer_size, GFP_KERNEL);
|
||||||
GFP_KERNEL | GFP_DMA);
|
else
|
||||||
if (!dev->common_buffer) {
|
buffer = dma_alloc_coherent(params->device,
|
||||||
|
dev->common_buffer_size,
|
||||||
|
&dev->common_buffer_phys,
|
||||||
|
GFP_KERNEL | GFP_DMA);
|
||||||
|
if (!buffer) {
|
||||||
smscore_unregister_device(dev);
|
smscore_unregister_device(dev);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
dev->common_buffer = buffer;
|
||||||
|
|
||||||
/* prepare dma buffers */
|
/* prepare dma buffers */
|
||||||
for (buffer = dev->common_buffer;
|
for (; dev->num_buffers < params->num_buffers;
|
||||||
dev->num_buffers < params->num_buffers;
|
|
||||||
dev->num_buffers++, buffer += params->buffer_size) {
|
dev->num_buffers++, buffer += params->buffer_size) {
|
||||||
struct smscore_buffer_t *cb;
|
struct smscore_buffer_t *cb;
|
||||||
|
|
||||||
@ -720,6 +725,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
|
|||||||
dev->board_id = SMS_BOARD_UNKNOWN;
|
dev->board_id = SMS_BOARD_UNKNOWN;
|
||||||
dev->context = params->context;
|
dev->context = params->context;
|
||||||
dev->device = params->device;
|
dev->device = params->device;
|
||||||
|
dev->usb_device = params->usb_device;
|
||||||
dev->setmode_handler = params->setmode_handler;
|
dev->setmode_handler = params->setmode_handler;
|
||||||
dev->detectmode_handler = params->detectmode_handler;
|
dev->detectmode_handler = params->detectmode_handler;
|
||||||
dev->sendrequest_handler = params->sendrequest_handler;
|
dev->sendrequest_handler = params->sendrequest_handler;
|
||||||
@ -1231,10 +1237,15 @@ void smscore_unregister_device(struct smscore_device_t *coredev)
|
|||||||
|
|
||||||
pr_debug("freed %d buffers\n", num_buffers);
|
pr_debug("freed %d buffers\n", num_buffers);
|
||||||
|
|
||||||
if (coredev->common_buffer)
|
if (coredev->common_buffer) {
|
||||||
dma_free_coherent(NULL, coredev->common_buffer_size,
|
if (coredev->usb_device)
|
||||||
coredev->common_buffer, coredev->common_buffer_phys);
|
kfree(coredev->common_buffer);
|
||||||
|
else
|
||||||
|
dma_free_coherent(coredev->device,
|
||||||
|
coredev->common_buffer_size,
|
||||||
|
coredev->common_buffer,
|
||||||
|
coredev->common_buffer_phys);
|
||||||
|
}
|
||||||
kfree(coredev->fw_buf);
|
kfree(coredev->fw_buf);
|
||||||
|
|
||||||
list_del(&coredev->entry);
|
list_del(&coredev->entry);
|
||||||
|
@ -134,6 +134,7 @@ struct smscore_buffer_t {
|
|||||||
|
|
||||||
struct smsdevice_params_t {
|
struct smsdevice_params_t {
|
||||||
struct device *device;
|
struct device *device;
|
||||||
|
struct usb_device *usb_device;
|
||||||
|
|
||||||
int buffer_size;
|
int buffer_size;
|
||||||
int num_buffers;
|
int num_buffers;
|
||||||
@ -176,6 +177,7 @@ struct smscore_device_t {
|
|||||||
|
|
||||||
void *context;
|
void *context;
|
||||||
struct device *device;
|
struct device *device;
|
||||||
|
struct usb_device *usb_device;
|
||||||
|
|
||||||
char devpath[32];
|
char devpath[32];
|
||||||
unsigned long device_flags;
|
unsigned long device_flags;
|
||||||
|
@ -179,8 +179,7 @@ static int smsusb_submit_urb(struct smsusb_device_t *dev,
|
|||||||
smsusb_onresponse,
|
smsusb_onresponse,
|
||||||
surb
|
surb
|
||||||
);
|
);
|
||||||
surb->urb.transfer_dma = surb->cb->phys;
|
surb->urb.transfer_flags |= URB_FREE_BUFFER;
|
||||||
surb->urb.transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
|
||||||
|
|
||||||
return usb_submit_urb(&surb->urb, GFP_ATOMIC);
|
return usb_submit_urb(&surb->urb, GFP_ATOMIC);
|
||||||
}
|
}
|
||||||
@ -446,6 +445,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
|
|||||||
dev->in_ep, dev->out_ep);
|
dev->in_ep, dev->out_ep);
|
||||||
|
|
||||||
params.device = &dev->udev->dev;
|
params.device = &dev->udev->dev;
|
||||||
|
params.usb_device = dev->udev;
|
||||||
params.buffer_size = dev->buffer_size;
|
params.buffer_size = dev->buffer_size;
|
||||||
params.num_buffers = MAX_BUFFERS;
|
params.num_buffers = MAX_BUFFERS;
|
||||||
params.sendrequest_handler = smsusb_sendrequest;
|
params.sendrequest_handler = smsusb_sendrequest;
|
||||||
|
Loading…
Reference in New Issue
Block a user