diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-07-06 17:03:44 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-07-06 17:03:44 -0400 |
| commit | f63bafe55654caf3a62f73500eafd1b89ca6f7ff (patch) | |
| tree | d8c80b71e1197fb805c07282139377e9542421ea | |
| parent | 4148df9b0f38bdd362dd91d52076926c11cbe5a9 (diff) | |
| parent | ebbb16bffa646f853899ef3fdc0ac7abab888703 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6:
ieee1394: sbp2: add support for disks >2 TB (and 16 bytes long CDBs)
firewire: sbp2: add support for disks >2 TB (and 16 bytes long CDBs)
firewire: core: do not DMA-map stack addresses
| -rw-r--r-- | drivers/firewire/core-card.c | 14 | ||||
| -rw-r--r-- | drivers/firewire/core-cdev.c | 4 | ||||
| -rw-r--r-- | drivers/firewire/core-iso.c | 24 | ||||
| -rw-r--r-- | drivers/firewire/core.h | 3 | ||||
| -rw-r--r-- | drivers/firewire/sbp2.c | 10 | ||||
| -rw-r--r-- | drivers/ieee1394/sbp2.c | 1 | ||||
| -rw-r--r-- | drivers/ieee1394/sbp2.h | 8 | ||||
| -rw-r--r-- | include/linux/firewire.h | 1 |
8 files changed, 43 insertions, 22 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 543fccac81bb..f74edae5cb4c 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c | |||
| @@ -196,8 +196,8 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation) | |||
| 196 | { | 196 | { |
| 197 | int channel, bandwidth = 0; | 197 | int channel, bandwidth = 0; |
| 198 | 198 | ||
| 199 | fw_iso_resource_manage(card, generation, 1ULL << 31, | 199 | fw_iso_resource_manage(card, generation, 1ULL << 31, &channel, |
| 200 | &channel, &bandwidth, true); | 200 | &bandwidth, true, card->bm_transaction_data); |
| 201 | if (channel == 31) { | 201 | if (channel == 31) { |
| 202 | card->broadcast_channel_allocated = true; | 202 | card->broadcast_channel_allocated = true; |
| 203 | device_for_each_child(card->device, (void *)(long)generation, | 203 | device_for_each_child(card->device, (void *)(long)generation, |
| @@ -230,7 +230,6 @@ static void fw_card_bm_work(struct work_struct *work) | |||
| 230 | bool do_reset = false; | 230 | bool do_reset = false; |
| 231 | bool root_device_is_running; | 231 | bool root_device_is_running; |
| 232 | bool root_device_is_cmc; | 232 | bool root_device_is_cmc; |
| 233 | __be32 lock_data[2]; | ||
| 234 | 233 | ||
| 235 | spin_lock_irqsave(&card->lock, flags); | 234 | spin_lock_irqsave(&card->lock, flags); |
| 236 | 235 | ||
| @@ -273,22 +272,23 @@ static void fw_card_bm_work(struct work_struct *work) | |||
| 273 | goto pick_me; | 272 | goto pick_me; |
| 274 | } | 273 | } |
| 275 | 274 | ||
| 276 | lock_data[0] = cpu_to_be32(0x3f); | 275 | card->bm_transaction_data[0] = cpu_to_be32(0x3f); |
| 277 | lock_data[1] = cpu_to_be32(local_id); | 276 | card->bm_transaction_data[1] = cpu_to_be32(local_id); |
| 278 | 277 | ||
| 279 | spin_unlock_irqrestore(&card->lock, flags); | 278 | spin_unlock_irqrestore(&card->lock, flags); |
| 280 | 279 | ||
| 281 | rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, | 280 | rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, |
| 282 | irm_id, generation, SCODE_100, | 281 | irm_id, generation, SCODE_100, |
| 283 | CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, | 282 | CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, |
| 284 | lock_data, sizeof(lock_data)); | 283 | card->bm_transaction_data, |
| 284 | sizeof(card->bm_transaction_data)); | ||
| 285 | 285 | ||
| 286 | if (rcode == RCODE_GENERATION) | 286 | if (rcode == RCODE_GENERATION) |
| 287 | /* Another bus reset, BM work has been rescheduled. */ | 287 | /* Another bus reset, BM work has been rescheduled. */ |
| 288 | goto out; | 288 | goto out; |
| 289 | 289 | ||
| 290 | if (rcode == RCODE_COMPLETE && | 290 | if (rcode == RCODE_COMPLETE && |
| 291 | lock_data[0] != cpu_to_be32(0x3f)) { | 291 | card->bm_transaction_data[0] != cpu_to_be32(0x3f)) { |
| 292 | 292 | ||
| 293 | /* Somebody else is BM. Only act as IRM. */ | 293 | /* Somebody else is BM. Only act as IRM. */ |
| 294 | if (local_id == irm_id) | 294 | if (local_id == irm_id) |
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index d1d30c615b0f..ced186d7e9a9 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c | |||
| @@ -125,6 +125,7 @@ struct iso_resource { | |||
| 125 | int generation; | 125 | int generation; |
| 126 | u64 channels; | 126 | u64 channels; |
| 127 | s32 bandwidth; | 127 | s32 bandwidth; |
| 128 | __be32 transaction_data[2]; | ||
| 128 | struct iso_resource_event *e_alloc, *e_dealloc; | 129 | struct iso_resource_event *e_alloc, *e_dealloc; |
| 129 | }; | 130 | }; |
| 130 | 131 | ||
| @@ -1049,7 +1050,8 @@ static void iso_resource_work(struct work_struct *work) | |||
| 1049 | r->channels, &channel, &bandwidth, | 1050 | r->channels, &channel, &bandwidth, |
| 1050 | todo == ISO_RES_ALLOC || | 1051 | todo == ISO_RES_ALLOC || |
| 1051 | todo == ISO_RES_REALLOC || | 1052 | todo == ISO_RES_REALLOC || |
| 1052 | todo == ISO_RES_ALLOC_ONCE); | 1053 | todo == ISO_RES_ALLOC_ONCE, |
| 1054 | r->transaction_data); | ||
| 1053 | /* | 1055 | /* |
| 1054 | * Is this generation outdated already? As long as this resource sticks | 1056 | * Is this generation outdated already? As long as this resource sticks |
| 1055 | * in the idr, it will be scheduled again for a newer generation or at | 1057 | * in the idr, it will be scheduled again for a newer generation or at |
diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index 166f19c6d38d..110e731f5574 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c | |||
| @@ -177,9 +177,8 @@ EXPORT_SYMBOL(fw_iso_context_stop); | |||
| 177 | */ | 177 | */ |
| 178 | 178 | ||
| 179 | static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, | 179 | static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, |
| 180 | int bandwidth, bool allocate) | 180 | int bandwidth, bool allocate, __be32 data[2]) |
| 181 | { | 181 | { |
| 182 | __be32 data[2]; | ||
| 183 | int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; | 182 | int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; |
| 184 | 183 | ||
| 185 | /* | 184 | /* |
| @@ -215,9 +214,9 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, | |||
| 215 | } | 214 | } |
| 216 | 215 | ||
| 217 | static int manage_channel(struct fw_card *card, int irm_id, int generation, | 216 | static int manage_channel(struct fw_card *card, int irm_id, int generation, |
| 218 | u32 channels_mask, u64 offset, bool allocate) | 217 | u32 channels_mask, u64 offset, bool allocate, __be32 data[2]) |
| 219 | { | 218 | { |
| 220 | __be32 data[2], c, all, old; | 219 | __be32 c, all, old; |
| 221 | int i, retry = 5; | 220 | int i, retry = 5; |
| 222 | 221 | ||
| 223 | old = all = allocate ? cpu_to_be32(~0) : 0; | 222 | old = all = allocate ? cpu_to_be32(~0) : 0; |
| @@ -260,7 +259,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation, | |||
| 260 | } | 259 | } |
| 261 | 260 | ||
| 262 | static void deallocate_channel(struct fw_card *card, int irm_id, | 261 | static void deallocate_channel(struct fw_card *card, int irm_id, |
| 263 | int generation, int channel) | 262 | int generation, int channel, __be32 buffer[2]) |
| 264 | { | 263 | { |
| 265 | u32 mask; | 264 | u32 mask; |
| 266 | u64 offset; | 265 | u64 offset; |
| @@ -269,7 +268,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, | |||
| 269 | offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : | 268 | offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : |
| 270 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; | 269 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; |
| 271 | 270 | ||
| 272 | manage_channel(card, irm_id, generation, mask, offset, false); | 271 | manage_channel(card, irm_id, generation, mask, offset, false, buffer); |
| 273 | } | 272 | } |
| 274 | 273 | ||
| 275 | /** | 274 | /** |
| @@ -298,7 +297,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, | |||
| 298 | */ | 297 | */ |
| 299 | void fw_iso_resource_manage(struct fw_card *card, int generation, | 298 | void fw_iso_resource_manage(struct fw_card *card, int generation, |
| 300 | u64 channels_mask, int *channel, int *bandwidth, | 299 | u64 channels_mask, int *channel, int *bandwidth, |
| 301 | bool allocate) | 300 | bool allocate, __be32 buffer[2]) |
| 302 | { | 301 | { |
| 303 | u32 channels_hi = channels_mask; /* channels 31...0 */ | 302 | u32 channels_hi = channels_mask; /* channels 31...0 */ |
| 304 | u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ | 303 | u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ |
| @@ -310,10 +309,12 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, | |||
| 310 | 309 | ||
| 311 | if (channels_hi) | 310 | if (channels_hi) |
| 312 | c = manage_channel(card, irm_id, generation, channels_hi, | 311 | c = manage_channel(card, irm_id, generation, channels_hi, |
| 313 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, allocate); | 312 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, |
| 313 | allocate, buffer); | ||
| 314 | if (channels_lo && c < 0) { | 314 | if (channels_lo && c < 0) { |
| 315 | c = manage_channel(card, irm_id, generation, channels_lo, | 315 | c = manage_channel(card, irm_id, generation, channels_lo, |
| 316 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, allocate); | 316 | CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, |
| 317 | allocate, buffer); | ||
| 317 | if (c >= 0) | 318 | if (c >= 0) |
| 318 | c += 32; | 319 | c += 32; |
| 319 | } | 320 | } |
| @@ -325,12 +326,13 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, | |||
| 325 | if (*bandwidth == 0) | 326 | if (*bandwidth == 0) |
| 326 | return; | 327 | return; |
| 327 | 328 | ||
| 328 | ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); | 329 | ret = manage_bandwidth(card, irm_id, generation, *bandwidth, |
| 330 | allocate, buffer); | ||
| 329 | if (ret < 0) | 331 | if (ret < 0) |
| 330 | *bandwidth = 0; | 332 | *bandwidth = 0; |
| 331 | 333 | ||
| 332 | if (allocate && ret < 0 && c >= 0) { | 334 | if (allocate && ret < 0 && c >= 0) { |
| 333 | deallocate_channel(card, irm_id, generation, c); | 335 | deallocate_channel(card, irm_id, generation, c, buffer); |
| 334 | *channel = ret; | 336 | *channel = ret; |
| 335 | } | 337 | } |
| 336 | } | 338 | } |
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index c3cfc647e5e3..6052816be353 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h | |||
| @@ -120,7 +120,8 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event); | |||
| 120 | 120 | ||
| 121 | int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); | 121 | int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); |
| 122 | void fw_iso_resource_manage(struct fw_card *card, int generation, | 122 | void fw_iso_resource_manage(struct fw_card *card, int generation, |
| 123 | u64 channels_mask, int *channel, int *bandwidth, bool allocate); | 123 | u64 channels_mask, int *channel, int *bandwidth, |
| 124 | bool allocate, __be32 buffer[2]); | ||
| 124 | 125 | ||
| 125 | 126 | ||
| 126 | /* -topology */ | 127 | /* -topology */ |
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 24c45635376a..8d51568ee143 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c | |||
| @@ -201,6 +201,12 @@ static struct fw_device *target_device(struct sbp2_target *tgt) | |||
| 201 | #define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */ | 201 | #define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */ |
| 202 | 202 | ||
| 203 | /* | 203 | /* |
| 204 | * There is no transport protocol limit to the CDB length, but we implement | ||
| 205 | * a fixed length only. 16 bytes is enough for disks larger than 2 TB. | ||
| 206 | */ | ||
| 207 | #define SBP2_MAX_CDB_SIZE 16 | ||
| 208 | |||
| 209 | /* | ||
| 204 | * The default maximum s/g segment size of a FireWire controller is | 210 | * The default maximum s/g segment size of a FireWire controller is |
| 205 | * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to | 211 | * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to |
| 206 | * be quadlet-aligned, we set the length limit to 0xffff & ~3. | 212 | * be quadlet-aligned, we set the length limit to 0xffff & ~3. |
| @@ -312,7 +318,7 @@ struct sbp2_command_orb { | |||
| 312 | struct sbp2_pointer next; | 318 | struct sbp2_pointer next; |
| 313 | struct sbp2_pointer data_descriptor; | 319 | struct sbp2_pointer data_descriptor; |
| 314 | __be32 misc; | 320 | __be32 misc; |
| 315 | u8 command_block[12]; | 321 | u8 command_block[SBP2_MAX_CDB_SIZE]; |
| 316 | } request; | 322 | } request; |
| 317 | struct scsi_cmnd *cmd; | 323 | struct scsi_cmnd *cmd; |
| 318 | scsi_done_fn_t done; | 324 | scsi_done_fn_t done; |
| @@ -1146,6 +1152,8 @@ static int sbp2_probe(struct device *dev) | |||
| 1146 | if (fw_device_enable_phys_dma(device) < 0) | 1152 | if (fw_device_enable_phys_dma(device) < 0) |
| 1147 | goto fail_shost_put; | 1153 | goto fail_shost_put; |
| 1148 | 1154 | ||
| 1155 | shost->max_cmd_len = SBP2_MAX_CDB_SIZE; | ||
| 1156 | |||
| 1149 | if (scsi_add_host(shost, &unit->device) < 0) | 1157 | if (scsi_add_host(shost, &unit->device) < 0) |
| 1150 | goto fail_shost_put; | 1158 | goto fail_shost_put; |
| 1151 | 1159 | ||
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 83b734aec923..52b25f8b111d 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c | |||
| @@ -880,6 +880,7 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) | |||
| 880 | } | 880 | } |
| 881 | 881 | ||
| 882 | shost->hostdata[0] = (unsigned long)lu; | 882 | shost->hostdata[0] = (unsigned long)lu; |
| 883 | shost->max_cmd_len = SBP2_MAX_CDB_SIZE; | ||
| 883 | 884 | ||
| 884 | if (!scsi_add_host(shost, &ud->device)) { | 885 | if (!scsi_add_host(shost, &ud->device)) { |
| 885 | lu->shost = shost; | 886 | lu->shost = shost; |
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index c5036f1cc5b0..64a3a66a8a39 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h | |||
| @@ -25,6 +25,12 @@ | |||
| 25 | #define SBP2_DEVICE_NAME "sbp2" | 25 | #define SBP2_DEVICE_NAME "sbp2" |
| 26 | 26 | ||
| 27 | /* | 27 | /* |
| 28 | * There is no transport protocol limit to the CDB length, but we implement | ||
| 29 | * a fixed length only. 16 bytes is enough for disks larger than 2 TB. | ||
| 30 | */ | ||
| 31 | #define SBP2_MAX_CDB_SIZE 16 | ||
| 32 | |||
| 33 | /* | ||
| 28 | * SBP-2 specific definitions | 34 | * SBP-2 specific definitions |
| 29 | */ | 35 | */ |
| 30 | 36 | ||
| @@ -51,7 +57,7 @@ struct sbp2_command_orb { | |||
| 51 | u32 data_descriptor_hi; | 57 | u32 data_descriptor_hi; |
| 52 | u32 data_descriptor_lo; | 58 | u32 data_descriptor_lo; |
| 53 | u32 misc; | 59 | u32 misc; |
| 54 | u8 cdb[12]; | 60 | u8 cdb[SBP2_MAX_CDB_SIZE]; |
| 55 | } __attribute__((packed)); | 61 | } __attribute__((packed)); |
| 56 | 62 | ||
| 57 | #define SBP2_LOGIN_REQUEST 0x0 | 63 | #define SBP2_LOGIN_REQUEST 0x0 |
diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 9823946adbc5..192d1e43c43c 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h | |||
| @@ -127,6 +127,7 @@ struct fw_card { | |||
| 127 | struct delayed_work work; | 127 | struct delayed_work work; |
| 128 | int bm_retries; | 128 | int bm_retries; |
| 129 | int bm_generation; | 129 | int bm_generation; |
| 130 | __be32 bm_transaction_data[2]; | ||
| 130 | 131 | ||
| 131 | bool broadcast_channel_allocated; | 132 | bool broadcast_channel_allocated; |
| 132 | u32 broadcast_channel; | 133 | u32 broadcast_channel; |
