Commit 47d8c881 authored by Dean Anderson's avatar Dean Anderson Committed by Mauro Carvalho Chehab

[media] s2255drv: dynamic memory allocation efficiency fix

Driver was allocating a kernel buffer each time it was sending a command.
It is better to allocate this buffer once at startup.
Signed-off-by: default avatarDean Anderson <linux-dev@sensoray.com>
Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent 8bf405a0
...@@ -260,6 +260,7 @@ struct s2255_dev { ...@@ -260,6 +260,7 @@ struct s2255_dev {
atomic_t num_channels; atomic_t num_channels;
int frames; int frames;
struct mutex lock; /* channels[].vdev.lock */ struct mutex lock; /* channels[].vdev.lock */
struct mutex cmdlock; /* protects cmdbuf */
struct usb_device *udev; struct usb_device *udev;
struct usb_interface *interface; struct usb_interface *interface;
u8 read_endpoint; u8 read_endpoint;
...@@ -273,6 +274,8 @@ struct s2255_dev { ...@@ -273,6 +274,8 @@ struct s2255_dev {
/* dsp firmware version (f2255usb.bin) */ /* dsp firmware version (f2255usb.bin) */
int dsp_fw_ver; int dsp_fw_ver;
u16 pid; /* product id */ u16 pid; /* product id */
#define S2255_CMDBUF_SIZE 512
__le32 *cmdbuf;
}; };
static inline struct s2255_dev *to_s2255_dev(struct v4l2_device *v4l2_dev) static inline struct s2255_dev *to_s2255_dev(struct v4l2_device *v4l2_dev)
...@@ -1121,11 +1124,12 @@ static int s2255_set_mode(struct s2255_vc *vc, ...@@ -1121,11 +1124,12 @@ static int s2255_set_mode(struct s2255_vc *vc,
struct s2255_mode *mode) struct s2255_mode *mode)
{ {
int res; int res;
__le32 *buffer;
unsigned long chn_rev; unsigned long chn_rev;
struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev); struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev);
int i; int i;
__le32 *buffer = dev->cmdbuf;
mutex_lock(&dev->cmdlock);
chn_rev = G_chnmap[vc->idx]; chn_rev = G_chnmap[vc->idx];
dprintk(dev, 3, "%s channel: %d\n", __func__, vc->idx); dprintk(dev, 3, "%s channel: %d\n", __func__, vc->idx);
/* if JPEG, set the quality */ /* if JPEG, set the quality */
...@@ -1139,11 +1143,6 @@ static int s2255_set_mode(struct s2255_vc *vc, ...@@ -1139,11 +1143,6 @@ static int s2255_set_mode(struct s2255_vc *vc,
vc->mode = *mode; vc->mode = *mode;
vc->req_image_size = get_transfer_size(mode); vc->req_image_size = get_transfer_size(mode);
dprintk(dev, 1, "%s: reqsize %ld\n", __func__, vc->req_image_size); dprintk(dev, 1, "%s: reqsize %ld\n", __func__, vc->req_image_size);
buffer = kzalloc(512, GFP_KERNEL);
if (buffer == NULL) {
dev_err(&dev->udev->dev, "out of mem\n");
return -ENOMEM;
}
/* set the mode */ /* set the mode */
buffer[0] = IN_DATA_TOKEN; buffer[0] = IN_DATA_TOKEN;
buffer[1] = (__le32) cpu_to_le32(chn_rev); buffer[1] = (__le32) cpu_to_le32(chn_rev);
...@@ -1154,7 +1153,6 @@ static int s2255_set_mode(struct s2255_vc *vc, ...@@ -1154,7 +1153,6 @@ static int s2255_set_mode(struct s2255_vc *vc,
res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
if (debug) if (debug)
s2255_print_cfg(dev, mode); s2255_print_cfg(dev, mode);
kfree(buffer);
/* wait at least 3 frames before continuing */ /* wait at least 3 frames before continuing */
if (mode->restart) { if (mode->restart) {
wait_event_timeout(vc->wait_setmode, wait_event_timeout(vc->wait_setmode,
...@@ -1168,22 +1166,20 @@ static int s2255_set_mode(struct s2255_vc *vc, ...@@ -1168,22 +1166,20 @@ static int s2255_set_mode(struct s2255_vc *vc,
/* clear the restart flag */ /* clear the restart flag */
vc->mode.restart = 0; vc->mode.restart = 0;
dprintk(dev, 1, "%s chn %d, result: %d\n", __func__, vc->idx, res); dprintk(dev, 1, "%s chn %d, result: %d\n", __func__, vc->idx, res);
mutex_unlock(&dev->cmdlock);
return res; return res;
} }
static int s2255_cmd_status(struct s2255_vc *vc, u32 *pstatus) static int s2255_cmd_status(struct s2255_vc *vc, u32 *pstatus)
{ {
int res; int res;
__le32 *buffer;
u32 chn_rev; u32 chn_rev;
struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev); struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev);
__le32 *buffer = dev->cmdbuf;
mutex_lock(&dev->cmdlock);
chn_rev = G_chnmap[vc->idx]; chn_rev = G_chnmap[vc->idx];
dprintk(dev, 4, "%s chan %d\n", __func__, vc->idx); dprintk(dev, 4, "%s chan %d\n", __func__, vc->idx);
buffer = kzalloc(512, GFP_KERNEL);
if (buffer == NULL) {
dev_err(&dev->udev->dev, "out of mem\n");
return -ENOMEM;
}
/* form the get vid status command */ /* form the get vid status command */
buffer[0] = IN_DATA_TOKEN; buffer[0] = IN_DATA_TOKEN;
buffer[1] = (__le32) cpu_to_le32(chn_rev); buffer[1] = (__le32) cpu_to_le32(chn_rev);
...@@ -1191,7 +1187,6 @@ static int s2255_cmd_status(struct s2255_vc *vc, u32 *pstatus) ...@@ -1191,7 +1187,6 @@ static int s2255_cmd_status(struct s2255_vc *vc, u32 *pstatus)
*pstatus = 0; *pstatus = 0;
vc->vidstatus_ready = 0; vc->vidstatus_ready = 0;
res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
kfree(buffer);
wait_event_timeout(vc->wait_vidstatus, wait_event_timeout(vc->wait_vidstatus,
(vc->vidstatus_ready != 0), (vc->vidstatus_ready != 0),
msecs_to_jiffies(S2255_VIDSTATUS_TIMEOUT)); msecs_to_jiffies(S2255_VIDSTATUS_TIMEOUT));
...@@ -1201,6 +1196,7 @@ static int s2255_cmd_status(struct s2255_vc *vc, u32 *pstatus) ...@@ -1201,6 +1196,7 @@ static int s2255_cmd_status(struct s2255_vc *vc, u32 *pstatus)
} }
*pstatus = vc->vidstatus; *pstatus = vc->vidstatus;
dprintk(dev, 4, "%s, vid status %d\n", __func__, *pstatus); dprintk(dev, 4, "%s, vid status %d\n", __func__, *pstatus);
mutex_unlock(&dev->cmdlock);
return res; return res;
} }
...@@ -1724,6 +1720,7 @@ static void s2255_destroy(struct s2255_dev *dev) ...@@ -1724,6 +1720,7 @@ static void s2255_destroy(struct s2255_dev *dev)
mutex_destroy(&dev->lock); mutex_destroy(&dev->lock);
usb_put_dev(dev->udev); usb_put_dev(dev->udev);
v4l2_device_unregister(&dev->v4l2_dev); v4l2_device_unregister(&dev->v4l2_dev);
kfree(dev->cmdbuf);
kfree(dev); kfree(dev);
} }
...@@ -2350,18 +2347,14 @@ static int s2255_start_readpipe(struct s2255_dev *dev) ...@@ -2350,18 +2347,14 @@ static int s2255_start_readpipe(struct s2255_dev *dev)
/* starts acquisition process */ /* starts acquisition process */
static int s2255_start_acquire(struct s2255_vc *vc) static int s2255_start_acquire(struct s2255_vc *vc)
{ {
unsigned char *buffer;
int res; int res;
unsigned long chn_rev; unsigned long chn_rev;
int j; int j;
struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev); struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev);
chn_rev = G_chnmap[vc->idx]; __le32 *buffer = dev->cmdbuf;
buffer = kzalloc(512, GFP_KERNEL);
if (buffer == NULL) {
dev_err(&dev->udev->dev, "out of mem\n");
return -ENOMEM;
}
mutex_lock(&dev->cmdlock);
chn_rev = G_chnmap[vc->idx];
vc->last_frame = -1; vc->last_frame = -1;
vc->bad_payload = 0; vc->bad_payload = 0;
vc->cur_frame = 0; vc->cur_frame = 0;
...@@ -2371,24 +2364,26 @@ static int s2255_start_acquire(struct s2255_vc *vc) ...@@ -2371,24 +2364,26 @@ static int s2255_start_acquire(struct s2255_vc *vc)
} }
/* send the start command */ /* send the start command */
*(__le32 *) buffer = IN_DATA_TOKEN; buffer[0] = IN_DATA_TOKEN;
*((__le32 *) buffer + 1) = (__le32) cpu_to_le32(chn_rev); buffer[1] = (__le32) cpu_to_le32(chn_rev);
*((__le32 *) buffer + 2) = CMD_START; buffer[2] = CMD_START;
res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
if (res != 0) if (res != 0)
dev_err(&dev->udev->dev, "CMD_START error\n"); dev_err(&dev->udev->dev, "CMD_START error\n");
dprintk(dev, 2, "start acquire exit[%d] %d\n", vc->idx, res); dprintk(dev, 2, "start acquire exit[%d] %d\n", vc->idx, res);
kfree(buffer); mutex_unlock(&dev->cmdlock);
return 0; return 0;
} }
static int s2255_stop_acquire(struct s2255_vc *vc) static int s2255_stop_acquire(struct s2255_vc *vc)
{ {
unsigned char *buffer;
int res; int res;
unsigned long chn_rev; unsigned long chn_rev;
struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev); struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev);
__le32 *buffer = dev->cmdbuf;
mutex_lock(&dev->cmdlock);
chn_rev = G_chnmap[vc->idx]; chn_rev = G_chnmap[vc->idx];
buffer = kzalloc(512, GFP_KERNEL); buffer = kzalloc(512, GFP_KERNEL);
if (buffer == NULL) { if (buffer == NULL) {
...@@ -2396,15 +2391,17 @@ static int s2255_stop_acquire(struct s2255_vc *vc) ...@@ -2396,15 +2391,17 @@ static int s2255_stop_acquire(struct s2255_vc *vc)
return -ENOMEM; return -ENOMEM;
} }
/* send the stop command */ /* send the stop command */
*(__le32 *) buffer = IN_DATA_TOKEN; buffer[0] = IN_DATA_TOKEN;
*((__le32 *) buffer + 1) = (__le32) cpu_to_le32(chn_rev); buffer[1] = (__le32) cpu_to_le32(chn_rev);
*((__le32 *) buffer + 2) = CMD_STOP; buffer[2] = CMD_STOP;
res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
if (res != 0) if (res != 0)
dev_err(&dev->udev->dev, "CMD_STOP error\n"); dev_err(&dev->udev->dev, "CMD_STOP error\n");
kfree(buffer);
vc->b_acquire = 0; vc->b_acquire = 0;
dprintk(dev, 4, "%s: chn %d, res %d\n", __func__, vc->idx, res); dprintk(dev, 4, "%s: chn %d, res %d\n", __func__, vc->idx, res);
mutex_unlock(&dev->cmdlock);
return res; return res;
} }
...@@ -2451,18 +2448,27 @@ static int s2255_probe(struct usb_interface *interface, ...@@ -2451,18 +2448,27 @@ static int s2255_probe(struct usb_interface *interface,
int retval = -ENOMEM; int retval = -ENOMEM;
__le32 *pdata; __le32 *pdata;
int fw_size; int fw_size;
/* allocate memory for our device state and initialize it to zero */ /* allocate memory for our device state and initialize it to zero */
dev = kzalloc(sizeof(struct s2255_dev), GFP_KERNEL); dev = kzalloc(sizeof(struct s2255_dev), GFP_KERNEL);
if (dev == NULL) { if (dev == NULL) {
s2255_dev_err(&interface->dev, "out of memory\n"); s2255_dev_err(&interface->dev, "out of memory\n");
return -ENOMEM; return -ENOMEM;
} }
dev->cmdbuf = kzalloc(S2255_CMDBUF_SIZE, GFP_KERNEL);
if (dev->cmdbuf == NULL) {
s2255_dev_err(&interface->dev, "out of memory\n");
return -ENOMEM;
}
atomic_set(&dev->num_channels, 0); atomic_set(&dev->num_channels, 0);
dev->pid = le16_to_cpu(id->idProduct); dev->pid = le16_to_cpu(id->idProduct);
dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL); dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL);
if (!dev->fw_data) if (!dev->fw_data)
goto errorFWDATA1; goto errorFWDATA1;
mutex_init(&dev->lock); mutex_init(&dev->lock);
mutex_init(&dev->cmdlock);
/* grab usb_device and save it */ /* grab usb_device and save it */
dev->udev = usb_get_dev(interface_to_usbdev(interface)); dev->udev = usb_get_dev(interface_to_usbdev(interface));
if (dev->udev == NULL) { if (dev->udev == NULL) {
...@@ -2568,6 +2574,7 @@ static int s2255_probe(struct usb_interface *interface, ...@@ -2568,6 +2574,7 @@ static int s2255_probe(struct usb_interface *interface,
kfree(dev->fw_data); kfree(dev->fw_data);
mutex_destroy(&dev->lock); mutex_destroy(&dev->lock);
errorFWDATA1: errorFWDATA1:
kfree(dev->cmdbuf);
kfree(dev); kfree(dev);
pr_warn("Sensoray 2255 driver load failed: 0x%x\n", retval); pr_warn("Sensoray 2255 driver load failed: 0x%x\n", retval);
return retval; return retval;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment