aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-card.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firewire/fw-card.c')
-rw-r--r--drivers/firewire/fw-card.c35
1 files changed, 12 insertions, 23 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index a2de680d9d52..216965615ee8 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -23,31 +23,22 @@
23#include <linux/errno.h> 23#include <linux/errno.h>
24#include <linux/device.h> 24#include <linux/device.h>
25#include <linux/rwsem.h> 25#include <linux/rwsem.h>
26#include <linux/crc-itu-t.h>
26#include "fw-transaction.h" 27#include "fw-transaction.h"
27#include "fw-topology.h" 28#include "fw-topology.h"
28#include "fw-device.h" 29#include "fw-device.h"
29 30
30/* The lib/crc16.c implementation uses the standard (0x8005) 31int fw_compute_block_crc(u32 *block)
31 * polynomial, but we need the ITU-T (or CCITT) polynomial (0x1021).
32 * The implementation below works on an array of host-endian u32
33 * words, assuming they'll be transmited msb first. */
34u16
35crc16_itu_t(const u32 *buffer, size_t length)
36{ 32{
37 int shift, i; 33 __be32 be32_block[256];
38 u32 data; 34 int i, length;
39 u16 sum, crc = 0;
40
41 for (i = 0; i < length; i++) {
42 data = *buffer++;
43 for (shift = 28; shift >= 0; shift -= 4 ) {
44 sum = ((crc >> 12) ^ (data >> shift)) & 0xf;
45 crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
46 }
47 crc &= 0xffff;
48 }
49 35
50 return crc; 36 length = (*block >> 16) & 0xff;
37 for (i = 0; i < length; i++)
38 be32_block[i] = cpu_to_be32(block[i + 1]);
39 *block |= crc_itu_t(0, (u8 *) be32_block, length * 4);
40
41 return length;
51} 42}
52 43
53static DECLARE_RWSEM(card_rwsem); 44static DECLARE_RWSEM(card_rwsem);
@@ -126,10 +117,8 @@ generate_config_rom (struct fw_card *card, size_t *config_rom_length)
126 * assumes that CRC length and info length are identical for 117 * assumes that CRC length and info length are identical for
127 * the bus info block, which is always the case for this 118 * the bus info block, which is always the case for this
128 * implementation. */ 119 * implementation. */
129 for (i = 0; i < j; i += length + 1) { 120 for (i = 0; i < j; i += length + 1)
130 length = (config_rom[i] >> 16) & 0xff; 121 length = fw_compute_block_crc(config_rom + i);
131 config_rom[i] |= crc16_itu_t(&config_rom[i + 1], length);
132 }
133 122
134 *config_rom_length = j; 123 *config_rom_length = j;
135 124