]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
V4L: pvrusb2: Handle larger cx2341x firmware images
authorMike Isely <isely@pobox.com>
Sat, 3 Mar 2007 14:36:02 +0000 (09:36 -0500)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 9 Mar 2007 18:50:23 +0000 (10:50 -0800)
Rework the cx23416 firmware loader so that it longer requires the
firmware size to be a multiple of 8KB.  Until recently all cx2341x
firmware images were exactly 256KB, but newer firmware is larger than
that and also appears to have arbitrary size.  We still must check
against a multiple of 4 bytes (because the cx23416 itself uses a 32
bit word size).

This fix is already in the upstream driver source and has proven
itself there; this is a backport for the 2.6.20.y kernel series.

(backported from commit 90060d32ca0a941b158994f78e60d0381871c84b)

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/media/video/pvrusb2/pvrusb2-hdw.c

index d2004965187bf54e47455a067881abf27f444950..2fbd24cae7dc87c102333f8ee5875edc98760921 100644 (file)
@@ -1041,7 +1041,7 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
 {
        const struct firmware *fw_entry = NULL;
        void  *fw_ptr;
-       unsigned int pipe, fw_len, fw_done;
+       unsigned int pipe, fw_len, fw_done, bcnt, icnt;
        int actual_length;
        int ret = 0;
        int fwidx;
@@ -1093,11 +1093,11 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
 
        fw_len = fw_entry->size;
 
-       if (fw_len % FIRMWARE_CHUNK_SIZE) {
+       if (fw_len % sizeof(u32)) {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                           "size of %s firmware"
-                          " must be a multiple of 8192B",
-                          fw_files[fwidx]);
+                          " must be a multiple of %zu bytes",
+                          fw_files[fwidx],sizeof(u32));
                release_firmware(fw_entry);
                return -1;
        }
@@ -1112,18 +1112,21 @@ int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
 
        pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT);
 
-       for (fw_done = 0 ; (fw_done < fw_len) && !ret ;
-            fw_done += FIRMWARE_CHUNK_SIZE ) {
-               int i;
-               memcpy(fw_ptr, fw_entry->data + fw_done, FIRMWARE_CHUNK_SIZE);
-               /* Usbsnoop log  shows that we must swap bytes... */
-               for (i = 0; i < FIRMWARE_CHUNK_SIZE/4 ; i++)
-                       ((u32 *)fw_ptr)[i] = ___swab32(((u32 *)fw_ptr)[i]);
-
-               ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,
-                                   FIRMWARE_CHUNK_SIZE,
+       fw_done = 0;
+       for (fw_done = 0; fw_done < fw_len;) {
+               bcnt = fw_len - fw_done;
+               if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE;
+               memcpy(fw_ptr, fw_entry->data + fw_done, bcnt);
+               /* Usbsnoop log shows that we must swap bytes... */
+               for (icnt = 0; icnt < bcnt/4 ; icnt++)
+                       ((u32 *)fw_ptr)[icnt] =
+                               ___swab32(((u32 *)fw_ptr)[icnt]);
+
+               ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt,
                                    &actual_length, HZ);
-               ret |= (actual_length != FIRMWARE_CHUNK_SIZE);
+               ret |= (actual_length != bcnt);
+               if (ret) break;
+               fw_done += bcnt;
        }
 
        trace_firmware("upload of %s : %i / %i ",