diff options
author | Anderson Lizardo <anderson.lizardo@indt.org.br> | 2008-09-17 11:34:38 -0400 |
---|---|---|
committer | David Vrabel <dv02@dv02pc01.europe.root.pri> | 2008-09-17 11:54:34 -0400 |
commit | b5784f10d559b3c7b25874b21702ad0907b6fcb7 (patch) | |
tree | c3e678d182a8c928cbb3660895458ed98e6c9b03 /drivers/uwb | |
parent | 8c7e8cb85557cc500122f3e489936582b7d11a7c (diff) |
uwb: i1480/GUWA100U: fix firmware download issues
IOGear firmware versions >= 1.4.12224 fail to be downloaded because of a
spurious (and harmless) RCEB received after the download notification. This
patch handles this RCEB and keeps compatibility with future versions that might
not emit this RCEB.
i1480_rceb_check() is reused to check for the RCEB. It is also refactored with
improved comments and reused in another place in mac.c where the checking was
being duplicated.
This patch was tested on both i1480 and GUWA100U HWAs, with all firmware
versions currently available.
Signed-off-by: Anderson Lizardo <anderson.lizardo@indt.org.br>
Diffstat (limited to 'drivers/uwb')
-rw-r--r-- | drivers/uwb/i1480/dfu/dfu.c | 54 | ||||
-rw-r--r-- | drivers/uwb/i1480/dfu/i1480-dfu.h | 2 | ||||
-rw-r--r-- | drivers/uwb/i1480/dfu/mac.c | 4 |
3 files changed, 45 insertions, 15 deletions
diff --git a/drivers/uwb/i1480/dfu/dfu.c b/drivers/uwb/i1480/dfu/dfu.c index aec4146757da..9097b3b30385 100644 --- a/drivers/uwb/i1480/dfu/dfu.c +++ b/drivers/uwb/i1480/dfu/dfu.c | |||
@@ -37,29 +37,45 @@ | |||
37 | #define D_LOCAL 0 | 37 | #define D_LOCAL 0 |
38 | #include <linux/uwb/debug.h> | 38 | #include <linux/uwb/debug.h> |
39 | 39 | ||
40 | /** @return 0 if If @evt is a valid reply event; otherwise complain */ | 40 | /** |
41 | * i1480_rceb_check - Check RCEB for expected field values | ||
42 | * @i1480: pointer to device for which RCEB is being checked | ||
43 | * @rceb: RCEB being checked | ||
44 | * @cmd: which command the RCEB is related to | ||
45 | * @context: expected context | ||
46 | * @expected_type: expected event type | ||
47 | * @expected_event: expected event | ||
48 | * | ||
49 | * If @cmd is NULL, do not print error messages, but still return an error | ||
50 | * code. | ||
51 | * | ||
52 | * Return 0 if @rceb matches the expected values, -EINVAL otherwise. | ||
53 | */ | ||
41 | int i1480_rceb_check(const struct i1480 *i1480, const struct uwb_rceb *rceb, | 54 | int i1480_rceb_check(const struct i1480 *i1480, const struct uwb_rceb *rceb, |
42 | const char *cmd, u8 context, | 55 | const char *cmd, u8 context, u8 expected_type, |
43 | unsigned expected_type, unsigned expected_event) | 56 | unsigned expected_event) |
44 | { | 57 | { |
45 | int result = 0; | 58 | int result = 0; |
46 | struct device *dev = i1480->dev; | 59 | struct device *dev = i1480->dev; |
47 | if (rceb->bEventContext != context) { | 60 | if (rceb->bEventContext != context) { |
48 | dev_err(dev, "%s: " | 61 | if (cmd) |
49 | "unexpected context id 0x%02x (expected 0x%02x)\n", | 62 | dev_err(dev, "%s: unexpected context id 0x%02x " |
50 | cmd, rceb->bEventContext, context); | 63 | "(expected 0x%02x)\n", cmd, |
64 | rceb->bEventContext, context); | ||
51 | result = -EINVAL; | 65 | result = -EINVAL; |
52 | } | 66 | } |
53 | if (rceb->bEventType != expected_type) { | 67 | if (rceb->bEventType != expected_type) { |
54 | dev_err(dev, "%s: " | 68 | if (cmd) |
55 | "unexpected event type 0x%02x (expected 0x%02x)\n", | 69 | dev_err(dev, "%s: unexpected event type 0x%02x " |
56 | cmd, rceb->bEventType, expected_type); | 70 | "(expected 0x%02x)\n", cmd, |
71 | rceb->bEventType, expected_type); | ||
57 | result = -EINVAL; | 72 | result = -EINVAL; |
58 | } | 73 | } |
59 | if (le16_to_cpu(rceb->wEvent) != expected_event) { | 74 | if (le16_to_cpu(rceb->wEvent) != expected_event) { |
60 | dev_err(dev, "%s: " | 75 | if (cmd) |
61 | "unexpected event 0x%04x (expected 0x%04x)\n", | 76 | dev_err(dev, "%s: unexpected event 0x%04x " |
62 | cmd, le16_to_cpu(rceb->wEvent), expected_event); | 77 | "(expected 0x%04x)\n", cmd, |
78 | le16_to_cpu(rceb->wEvent), expected_event); | ||
63 | result = -EINVAL; | 79 | result = -EINVAL; |
64 | } | 80 | } |
65 | return result; | 81 | return result; |
@@ -110,6 +126,20 @@ ssize_t i1480_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size, | |||
110 | cmd_name, result); | 126 | cmd_name, result); |
111 | goto error; | 127 | goto error; |
112 | } | 128 | } |
129 | /* | ||
130 | * Firmware versions >= 1.4.12224 for IOGear GUWA100U generate a | ||
131 | * spurious notification after firmware is downloaded. So check whether | ||
132 | * the receibed RCEB is such notification before assuming that the | ||
133 | * command has failed. | ||
134 | */ | ||
135 | if (i1480_rceb_check(i1480, i1480->evt_buf, NULL, | ||
136 | 0, 0xfd, 0x0022) == 0) { | ||
137 | /* Now wait for the actual RCEB for this command. */ | ||
138 | result = i1480->wait_init_done(i1480); | ||
139 | if (result < 0) | ||
140 | goto error; | ||
141 | result = i1480->evt_result; | ||
142 | } | ||
113 | if (result != reply_size) { | 143 | if (result != reply_size) { |
114 | dev_err(i1480->dev, "%s returned only %zu bytes, %zu expected\n", | 144 | dev_err(i1480->dev, "%s returned only %zu bytes, %zu expected\n", |
115 | cmd_name, result, reply_size); | 145 | cmd_name, result, reply_size); |
diff --git a/drivers/uwb/i1480/dfu/i1480-dfu.h b/drivers/uwb/i1480/dfu/i1480-dfu.h index 8035418de132..46f45e800f36 100644 --- a/drivers/uwb/i1480/dfu/i1480-dfu.h +++ b/drivers/uwb/i1480/dfu/i1480-dfu.h | |||
@@ -145,7 +145,7 @@ extern int i1480_phy_fw_upload(struct i1480 *); | |||
145 | extern ssize_t i1480_cmd(struct i1480 *, const char *, size_t, size_t); | 145 | extern ssize_t i1480_cmd(struct i1480 *, const char *, size_t, size_t); |
146 | extern int i1480_rceb_check(const struct i1480 *, | 146 | extern int i1480_rceb_check(const struct i1480 *, |
147 | const struct uwb_rceb *, const char *, u8, | 147 | const struct uwb_rceb *, const char *, u8, |
148 | unsigned, unsigned); | 148 | u8, unsigned); |
149 | 149 | ||
150 | enum { | 150 | enum { |
151 | /* Vendor specific command type */ | 151 | /* Vendor specific command type */ |
diff --git a/drivers/uwb/i1480/dfu/mac.c b/drivers/uwb/i1480/dfu/mac.c index 3d445541e8e9..8d069907a3b5 100644 --- a/drivers/uwb/i1480/dfu/mac.c +++ b/drivers/uwb/i1480/dfu/mac.c | |||
@@ -507,8 +507,8 @@ int i1480_mac_fw_upload(struct i1480 *i1480) | |||
507 | goto error_size; | 507 | goto error_size; |
508 | } | 508 | } |
509 | result = -EIO; | 509 | result = -EIO; |
510 | if (rcebe->rceb.bEventType != i1480_CET_VS1 | 510 | if (i1480_rceb_check(i1480, &rcebe->rceb, NULL, 0, i1480_CET_VS1, |
511 | || le16_to_cpu(rcebe->rceb.wEvent) != i1480_EVT_RM_INIT_DONE) { | 511 | i1480_EVT_RM_INIT_DONE) < 0) { |
512 | dev_err(i1480->dev, "wrong initialization event 0x%02x/%04x/%02x " | 512 | dev_err(i1480->dev, "wrong initialization event 0x%02x/%04x/%02x " |
513 | "received; expected 0x%02x/%04x/00\n", | 513 | "received; expected 0x%02x/%04x/00\n", |
514 | rcebe->rceb.bEventType, le16_to_cpu(rcebe->rceb.wEvent), | 514 | rcebe->rceb.bEventType, le16_to_cpu(rcebe->rceb.wEvent), |