[patch]dma on stack in dib0700

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



USB on some architectures cannot do DMA with buffers on the stack.
Therefore the dib0700 driver will fail on some architectures. The fix is
allocating buffers on the stack.

Signed-off-by: Oliver Neukum <oneukum@xxxxxxx>

	Regards
		Oliver

---

--- linux-2.6.27-rc4/drivers/media/dvb/dvb-usb/dib0700_core.c.alt	2008-08-26 15:31:31.000000000 +0200
+++ linux-2.6.27-rc4/drivers/media/dvb/dvb-usb/dib0700_core.c	2008-08-26 15:46:32.000000000 +0200
@@ -77,8 +77,19 @@ int dib0700_ctrl_rd(struct dvb_usb_devic
 
 int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
 {
-	u8 buf[3] = { REQUEST_SET_GPIO, gpio, ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6) };
-	return dib0700_ctrl_wr(d,buf,3);
+	u8 *buf;
+	int rv;
+
+	buf = kmalloc(3, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	buf[0] = REQUEST_SET_GPIO;
+	buf[1] = gpio;
+	buf[2] = ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6);
+
+	rv = dib0700_ctrl_wr(d,buf,3);
+	kfree(buf);
+	return rv;
 }
 
 /*
@@ -88,10 +99,15 @@ static int dib0700_i2c_xfer(struct i2c_a
 {
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
 	int i,len;
-	u8 buf[255];
+	u8 *buf;
 
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+	buf = kmalloc(255, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0) {
+		kfree(buf);
 		return -EAGAIN;
+	}
 
 	for (i = 0; i < num; i++) {
 		/* fill in the address */
@@ -121,6 +137,7 @@ static int dib0700_i2c_xfer(struct i2c_a
 	}
 
 	mutex_unlock(&d->i2c_mutex);
+	kfree(buf);
 	return i;
 }
 
@@ -137,9 +154,18 @@ struct i2c_algorithm dib0700_i2c_algo =
 int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
 			struct dvb_usb_device_description **desc, int *cold)
 {
-	u8 b[16];
-	s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0),
+	u8 *b;
+	s16 ret;
+
+	b = kmalloc(16, GFP_KERNEL);
+
+	if (b) {
+		ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0),
 		REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT);
+		kfree(b);
+	} else {
+		ret = 0;
+	}
 
 	deb_info("FW GET_VERSION length: %d\n",ret);
 
@@ -153,7 +179,12 @@ static int dib0700_set_clock(struct dvb_
 	u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv,
 	u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
 {
-	u8 b[10];
+	u8 *b;
+	int rv;
+
+	b = kmalloc(10, GFP_KERNEL);
+	if (!b)
+		return -ENOMEM;
 	b[0] = REQUEST_SET_CLOCK;
 	b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4);
 	b[2] = (pll_prediv >> 8)  & 0xff; // MSB
@@ -165,7 +196,9 @@ static int dib0700_set_clock(struct dvb_
 	b[8] = (dsuScaler >> 8)   & 0xff; // MSB
 	b[9] =  dsuScaler         & 0xff; // LSB
 
-	return dib0700_ctrl_wr(d, b, 10);
+	rv = dib0700_ctrl_wr(d, b, 10);
+	kfree(b);
+	return rv;
 }
 
 int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3)
@@ -179,30 +212,40 @@ int dib0700_ctrl_clock(struct dvb_usb_de
 
 static int dib0700_jumpram(struct usb_device *udev, u32 address)
 {
-	int ret, actlen;
-	u8 buf[8] = { REQUEST_JUMPRAM, 0, 0, 0,
-		(address >> 24) & 0xff,
-		(address >> 16) & 0xff,
-		(address >> 8)  & 0xff,
-		 address        & 0xff };
+	int ret = 0, actlen;
+	u8 *buf;
+
+	buf = kzalloc(8, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	buf[0] = REQUEST_JUMPRAM;
+	*(u32 *)(buf + 4) = cpu_to_be32(address);
 
 	if ((ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x01),buf,8,&actlen,1000)) < 0) {
 		deb_fw("jumpram to 0x%x failed\n",address);
-		return ret;
+		goto out;
 	}
 	if (actlen != 8) {
 		deb_fw("jumpram to 0x%x failed\n",address);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
-	return 0;
+
+out:
+	kfree(buf);
+	return ret;
 }
 
 int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw)
 {
 	struct hexline hx;
 	int pos = 0, ret, act_len;
+	u8 *buf;
 
-	u8 buf[260];
+	buf = kmalloc(260, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
 
 	while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) {
 		deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n",hx.addr, hx.len, hx.chk);
@@ -222,6 +265,7 @@ int dib0700_download_firmware(struct usb
 			1000);
 
 		if (ret < 0) {
+			kfree(buf);
 			err("firmware download failed at %d with %d",pos,ret);
 			return ret;
 		}
@@ -236,14 +280,19 @@ int dib0700_download_firmware(struct usb
 	} else
 		ret = -EIO;
 
+	kfree(buf);
 	return ret;
 }
 
 int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
 	struct dib0700_state *st = adap->dev->priv;
-	u8 b[4];
+	u8 *b;
+	int rv;
 
+	b = kmalloc(4, GFP_KERNEL);
+	if (!b)
+		return -ENOMEM;
 	b[0] = REQUEST_ENABLE_VIDEO;
 	b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */
 	b[2] = (0x01 << 4); /* Master mode */
@@ -260,18 +309,29 @@ int dib0700_streaming_ctrl(struct dvb_us
 
 	deb_info("data for streaming: %x %x\n",b[1],b[2]);
 
-	return dib0700_ctrl_wr(adap->dev, b, 4);
+	rv = dib0700_ctrl_wr(adap->dev, b, 4);
+	kfree(b);
+	return rv;
 }
 
 int dib0700_rc_setup(struct dvb_usb_device *d)
 {
-	u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0};
-	int i = dib0700_ctrl_wr(d, rc_setup, 3);
-	if (i<0) {
-		err("ir protocol setup failed");
+	u8 *rc_setup;
+	int i;
+
+	rc_setup = kmalloc(3, GFP_KERNEL);
+	if (!rc_setup)
 		return -1;
-	}
-	return 0;
+	rc_setup[0] = REQUEST_SET_RC;
+	rc_setup[1] = dvb_usb_dib0700_ir_proto;
+	rc_setup[2] = 0;
+
+	i = dib0700_ctrl_wr(d, rc_setup, 3);
+	kfree(rc_setup);
+	if (i<0)
+		err("ir protocol setup failed");
+
+	return i >= 0 ? 0 : -1;
 }
 
 static int dib0700_probe(struct usb_interface *intf,

_______________________________________________
linux-dvb mailing list
linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux