diff options
Diffstat (limited to 'drivers/firewire/ohci.c')
-rw-r--r-- | drivers/firewire/ohci.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 673c8970749e..a309d89f4df7 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
@@ -68,6 +68,8 @@ | |||
68 | #define DESCRIPTOR_BRANCH_ALWAYS (3 << 2) | 68 | #define DESCRIPTOR_BRANCH_ALWAYS (3 << 2) |
69 | #define DESCRIPTOR_WAIT (3 << 0) | 69 | #define DESCRIPTOR_WAIT (3 << 0) |
70 | 70 | ||
71 | #define DESCRIPTOR_CMD (0xf << 12) | ||
72 | |||
71 | struct descriptor { | 73 | struct descriptor { |
72 | __le16 req_count; | 74 | __le16 req_count; |
73 | __le16 control; | 75 | __le16 control; |
@@ -149,10 +151,11 @@ struct context { | |||
149 | struct descriptor *last; | 151 | struct descriptor *last; |
150 | 152 | ||
151 | /* | 153 | /* |
152 | * The last descriptor in the DMA program. It contains the branch | 154 | * The last descriptor block in the DMA program. It contains the branch |
153 | * address that must be updated upon appending a new descriptor. | 155 | * address that must be updated upon appending a new descriptor. |
154 | */ | 156 | */ |
155 | struct descriptor *prev; | 157 | struct descriptor *prev; |
158 | int prev_z; | ||
156 | 159 | ||
157 | descriptor_callback_t callback; | 160 | descriptor_callback_t callback; |
158 | 161 | ||
@@ -270,7 +273,9 @@ static char ohci_driver_name[] = KBUILD_MODNAME; | |||
270 | #define PCI_DEVICE_ID_TI_TSB12LV22 0x8009 | 273 | #define PCI_DEVICE_ID_TI_TSB12LV22 0x8009 |
271 | #define PCI_DEVICE_ID_TI_TSB12LV26 0x8020 | 274 | #define PCI_DEVICE_ID_TI_TSB12LV26 0x8020 |
272 | #define PCI_DEVICE_ID_TI_TSB82AA2 0x8025 | 275 | #define PCI_DEVICE_ID_TI_TSB82AA2 0x8025 |
276 | #define PCI_DEVICE_ID_VIA_VT630X 0x3044 | ||
273 | #define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd | 277 | #define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd |
278 | #define PCI_REV_ID_VIA_VT6306 0x46 | ||
274 | 279 | ||
275 | #define QUIRK_CYCLE_TIMER 1 | 280 | #define QUIRK_CYCLE_TIMER 1 |
276 | #define QUIRK_RESET_PACKET 2 | 281 | #define QUIRK_RESET_PACKET 2 |
@@ -278,6 +283,7 @@ static char ohci_driver_name[] = KBUILD_MODNAME; | |||
278 | #define QUIRK_NO_1394A 8 | 283 | #define QUIRK_NO_1394A 8 |
279 | #define QUIRK_NO_MSI 16 | 284 | #define QUIRK_NO_MSI 16 |
280 | #define QUIRK_TI_SLLZ059 32 | 285 | #define QUIRK_TI_SLLZ059 32 |
286 | #define QUIRK_IR_WAKE 64 | ||
281 | 287 | ||
282 | /* In case of multiple matches in ohci_quirks[], only the first one is used. */ | 288 | /* In case of multiple matches in ohci_quirks[], only the first one is used. */ |
283 | static const struct { | 289 | static const struct { |
@@ -319,6 +325,9 @@ static const struct { | |||
319 | {PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID, | 325 | {PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID, |
320 | QUIRK_RESET_PACKET}, | 326 | QUIRK_RESET_PACKET}, |
321 | 327 | ||
328 | {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT630X, PCI_REV_ID_VIA_VT6306, | ||
329 | QUIRK_CYCLE_TIMER | QUIRK_IR_WAKE}, | ||
330 | |||
322 | {PCI_VENDOR_ID_VIA, PCI_ANY_ID, PCI_ANY_ID, | 331 | {PCI_VENDOR_ID_VIA, PCI_ANY_ID, PCI_ANY_ID, |
323 | QUIRK_CYCLE_TIMER | QUIRK_NO_MSI}, | 332 | QUIRK_CYCLE_TIMER | QUIRK_NO_MSI}, |
324 | }; | 333 | }; |
@@ -333,6 +342,7 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0" | |||
333 | ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A) | 342 | ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A) |
334 | ", disable MSI = " __stringify(QUIRK_NO_MSI) | 343 | ", disable MSI = " __stringify(QUIRK_NO_MSI) |
335 | ", TI SLLZ059 erratum = " __stringify(QUIRK_TI_SLLZ059) | 344 | ", TI SLLZ059 erratum = " __stringify(QUIRK_TI_SLLZ059) |
345 | ", IR wake unreliable = " __stringify(QUIRK_IR_WAKE) | ||
336 | ")"); | 346 | ")"); |
337 | 347 | ||
338 | #define OHCI_PARAM_DEBUG_AT_AR 1 | 348 | #define OHCI_PARAM_DEBUG_AT_AR 1 |
@@ -1157,6 +1167,7 @@ static int context_init(struct context *ctx, struct fw_ohci *ohci, | |||
1157 | ctx->buffer_tail->used += sizeof(*ctx->buffer_tail->buffer); | 1167 | ctx->buffer_tail->used += sizeof(*ctx->buffer_tail->buffer); |
1158 | ctx->last = ctx->buffer_tail->buffer; | 1168 | ctx->last = ctx->buffer_tail->buffer; |
1159 | ctx->prev = ctx->buffer_tail->buffer; | 1169 | ctx->prev = ctx->buffer_tail->buffer; |
1170 | ctx->prev_z = 1; | ||
1160 | 1171 | ||
1161 | return 0; | 1172 | return 0; |
1162 | } | 1173 | } |
@@ -1221,14 +1232,35 @@ static void context_append(struct context *ctx, | |||
1221 | { | 1232 | { |
1222 | dma_addr_t d_bus; | 1233 | dma_addr_t d_bus; |
1223 | struct descriptor_buffer *desc = ctx->buffer_tail; | 1234 | struct descriptor_buffer *desc = ctx->buffer_tail; |
1235 | struct descriptor *d_branch; | ||
1224 | 1236 | ||
1225 | d_bus = desc->buffer_bus + (d - desc->buffer) * sizeof(*d); | 1237 | d_bus = desc->buffer_bus + (d - desc->buffer) * sizeof(*d); |
1226 | 1238 | ||
1227 | desc->used += (z + extra) * sizeof(*d); | 1239 | desc->used += (z + extra) * sizeof(*d); |
1228 | 1240 | ||
1229 | wmb(); /* finish init of new descriptors before branch_address update */ | 1241 | wmb(); /* finish init of new descriptors before branch_address update */ |
1230 | ctx->prev->branch_address = cpu_to_le32(d_bus | z); | 1242 | |
1231 | ctx->prev = find_branch_descriptor(d, z); | 1243 | d_branch = find_branch_descriptor(ctx->prev, ctx->prev_z); |
1244 | d_branch->branch_address = cpu_to_le32(d_bus | z); | ||
1245 | |||
1246 | /* | ||
1247 | * VT6306 incorrectly checks only the single descriptor at the | ||
1248 | * CommandPtr when the wake bit is written, so if it's a | ||
1249 | * multi-descriptor block starting with an INPUT_MORE, put a copy of | ||
1250 | * the branch address in the first descriptor. | ||
1251 | * | ||
1252 | * Not doing this for transmit contexts since not sure how it interacts | ||
1253 | * with skip addresses. | ||
1254 | */ | ||
1255 | if (unlikely(ctx->ohci->quirks & QUIRK_IR_WAKE) && | ||
1256 | d_branch != ctx->prev && | ||
1257 | (ctx->prev->control & cpu_to_le16(DESCRIPTOR_CMD)) == | ||
1258 | cpu_to_le16(DESCRIPTOR_INPUT_MORE)) { | ||
1259 | ctx->prev->branch_address = cpu_to_le32(d_bus | z); | ||
1260 | } | ||
1261 | |||
1262 | ctx->prev = d; | ||
1263 | ctx->prev_z = z; | ||
1232 | } | 1264 | } |
1233 | 1265 | ||
1234 | static void context_stop(struct context *ctx) | 1266 | static void context_stop(struct context *ctx) |