Commit f63bafe5 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 4148df9b ebbb16bf
...@@ -196,8 +196,8 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation) ...@@ -196,8 +196,8 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation)
{ {
int channel, bandwidth = 0; int channel, bandwidth = 0;
fw_iso_resource_manage(card, generation, 1ULL << 31, fw_iso_resource_manage(card, generation, 1ULL << 31, &channel,
&channel, &bandwidth, true); &bandwidth, true, card->bm_transaction_data);
if (channel == 31) { if (channel == 31) {
card->broadcast_channel_allocated = true; card->broadcast_channel_allocated = true;
device_for_each_child(card->device, (void *)(long)generation, device_for_each_child(card->device, (void *)(long)generation,
...@@ -230,7 +230,6 @@ static void fw_card_bm_work(struct work_struct *work) ...@@ -230,7 +230,6 @@ static void fw_card_bm_work(struct work_struct *work)
bool do_reset = false; bool do_reset = false;
bool root_device_is_running; bool root_device_is_running;
bool root_device_is_cmc; bool root_device_is_cmc;
__be32 lock_data[2];
spin_lock_irqsave(&card->lock, flags); spin_lock_irqsave(&card->lock, flags);
...@@ -273,22 +272,23 @@ static void fw_card_bm_work(struct work_struct *work) ...@@ -273,22 +272,23 @@ static void fw_card_bm_work(struct work_struct *work)
goto pick_me; goto pick_me;
} }
lock_data[0] = cpu_to_be32(0x3f); card->bm_transaction_data[0] = cpu_to_be32(0x3f);
lock_data[1] = cpu_to_be32(local_id); card->bm_transaction_data[1] = cpu_to_be32(local_id);
spin_unlock_irqrestore(&card->lock, flags); spin_unlock_irqrestore(&card->lock, flags);
rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
irm_id, generation, SCODE_100, irm_id, generation, SCODE_100,
CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
lock_data, sizeof(lock_data)); card->bm_transaction_data,
sizeof(card->bm_transaction_data));
if (rcode == RCODE_GENERATION) if (rcode == RCODE_GENERATION)
/* Another bus reset, BM work has been rescheduled. */ /* Another bus reset, BM work has been rescheduled. */
goto out; goto out;
if (rcode == RCODE_COMPLETE && if (rcode == RCODE_COMPLETE &&
lock_data[0] != cpu_to_be32(0x3f)) { card->bm_transaction_data[0] != cpu_to_be32(0x3f)) {
/* Somebody else is BM. Only act as IRM. */ /* Somebody else is BM. Only act as IRM. */
if (local_id == irm_id) if (local_id == irm_id)
......
...@@ -125,6 +125,7 @@ struct iso_resource { ...@@ -125,6 +125,7 @@ struct iso_resource {
int generation; int generation;
u64 channels; u64 channels;
s32 bandwidth; s32 bandwidth;
__be32 transaction_data[2];
struct iso_resource_event *e_alloc, *e_dealloc; struct iso_resource_event *e_alloc, *e_dealloc;
}; };
...@@ -1049,7 +1050,8 @@ static void iso_resource_work(struct work_struct *work) ...@@ -1049,7 +1050,8 @@ static void iso_resource_work(struct work_struct *work)
r->channels, &channel, &bandwidth, r->channels, &channel, &bandwidth,
todo == ISO_RES_ALLOC || todo == ISO_RES_ALLOC ||
todo == ISO_RES_REALLOC || todo == ISO_RES_REALLOC ||
todo == ISO_RES_ALLOC_ONCE); todo == ISO_RES_ALLOC_ONCE,
r->transaction_data);
/* /*
* Is this generation outdated already? As long as this resource sticks * Is this generation outdated already? As long as this resource sticks
* in the idr, it will be scheduled again for a newer generation or at * in the idr, it will be scheduled again for a newer generation or at
......
...@@ -177,9 +177,8 @@ EXPORT_SYMBOL(fw_iso_context_stop); ...@@ -177,9 +177,8 @@ EXPORT_SYMBOL(fw_iso_context_stop);
*/ */
static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
int bandwidth, bool allocate) int bandwidth, bool allocate, __be32 data[2])
{ {
__be32 data[2];
int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0;
/* /*
...@@ -215,9 +214,9 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, ...@@ -215,9 +214,9 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
} }
static int manage_channel(struct fw_card *card, int irm_id, int generation, static int manage_channel(struct fw_card *card, int irm_id, int generation,
u32 channels_mask, u64 offset, bool allocate) u32 channels_mask, u64 offset, bool allocate, __be32 data[2])
{ {
__be32 data[2], c, all, old; __be32 c, all, old;
int i, retry = 5; int i, retry = 5;
old = all = allocate ? cpu_to_be32(~0) : 0; 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,7 +259,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation,
} }
static void deallocate_channel(struct fw_card *card, int irm_id, static void deallocate_channel(struct fw_card *card, int irm_id,
int generation, int channel) int generation, int channel, __be32 buffer[2])
{ {
u32 mask; u32 mask;
u64 offset; u64 offset;
...@@ -269,7 +268,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, ...@@ -269,7 +268,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id,
offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI :
CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO;
manage_channel(card, irm_id, generation, mask, offset, false); manage_channel(card, irm_id, generation, mask, offset, false, buffer);
} }
/** /**
...@@ -298,7 +297,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, ...@@ -298,7 +297,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id,
*/ */
void fw_iso_resource_manage(struct fw_card *card, int generation, void fw_iso_resource_manage(struct fw_card *card, int generation,
u64 channels_mask, int *channel, int *bandwidth, u64 channels_mask, int *channel, int *bandwidth,
bool allocate) bool allocate, __be32 buffer[2])
{ {
u32 channels_hi = channels_mask; /* channels 31...0 */ u32 channels_hi = channels_mask; /* channels 31...0 */
u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ 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,10 +309,12 @@ void fw_iso_resource_manage(struct fw_card *card, int generation,
if (channels_hi) if (channels_hi)
c = manage_channel(card, irm_id, generation, channels_hi, c = manage_channel(card, irm_id, generation, channels_hi,
CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, allocate); CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI,
allocate, buffer);
if (channels_lo && c < 0) { if (channels_lo && c < 0) {
c = manage_channel(card, irm_id, generation, channels_lo, c = manage_channel(card, irm_id, generation, channels_lo,
CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, allocate); CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO,
allocate, buffer);
if (c >= 0) if (c >= 0)
c += 32; c += 32;
} }
...@@ -325,12 +326,13 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, ...@@ -325,12 +326,13 @@ void fw_iso_resource_manage(struct fw_card *card, int generation,
if (*bandwidth == 0) if (*bandwidth == 0)
return; return;
ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); ret = manage_bandwidth(card, irm_id, generation, *bandwidth,
allocate, buffer);
if (ret < 0) if (ret < 0)
*bandwidth = 0; *bandwidth = 0;
if (allocate && ret < 0 && c >= 0) { if (allocate && ret < 0 && c >= 0) {
deallocate_channel(card, irm_id, generation, c); deallocate_channel(card, irm_id, generation, c, buffer);
*channel = ret; *channel = ret;
} }
} }
...@@ -120,7 +120,8 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event); ...@@ -120,7 +120,8 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event);
int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma);
void fw_iso_resource_manage(struct fw_card *card, int generation, void fw_iso_resource_manage(struct fw_card *card, int generation,
u64 channels_mask, int *channel, int *bandwidth, bool allocate); u64 channels_mask, int *channel, int *bandwidth,
bool allocate, __be32 buffer[2]);
/* -topology */ /* -topology */
......
...@@ -200,6 +200,12 @@ static struct fw_device *target_device(struct sbp2_target *tgt) ...@@ -200,6 +200,12 @@ static struct fw_device *target_device(struct sbp2_target *tgt)
#define SBP2_RETRY_LIMIT 0xf /* 15 retries */ #define SBP2_RETRY_LIMIT 0xf /* 15 retries */
#define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */ #define SBP2_CYCLE_LIMIT (0xc8 << 12) /* 200 125us cycles */
/*
* There is no transport protocol limit to the CDB length, but we implement
* a fixed length only. 16 bytes is enough for disks larger than 2 TB.
*/
#define SBP2_MAX_CDB_SIZE 16
/* /*
* The default maximum s/g segment size of a FireWire controller is * The default maximum s/g segment size of a FireWire controller is
* usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
...@@ -312,7 +318,7 @@ struct sbp2_command_orb { ...@@ -312,7 +318,7 @@ struct sbp2_command_orb {
struct sbp2_pointer next; struct sbp2_pointer next;
struct sbp2_pointer data_descriptor; struct sbp2_pointer data_descriptor;
__be32 misc; __be32 misc;
u8 command_block[12]; u8 command_block[SBP2_MAX_CDB_SIZE];
} request; } request;
struct scsi_cmnd *cmd; struct scsi_cmnd *cmd;
scsi_done_fn_t done; scsi_done_fn_t done;
...@@ -1146,6 +1152,8 @@ static int sbp2_probe(struct device *dev) ...@@ -1146,6 +1152,8 @@ static int sbp2_probe(struct device *dev)
if (fw_device_enable_phys_dma(device) < 0) if (fw_device_enable_phys_dma(device) < 0)
goto fail_shost_put; goto fail_shost_put;
shost->max_cmd_len = SBP2_MAX_CDB_SIZE;
if (scsi_add_host(shost, &unit->device) < 0) if (scsi_add_host(shost, &unit->device) < 0)
goto fail_shost_put; goto fail_shost_put;
......
...@@ -880,6 +880,7 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) ...@@ -880,6 +880,7 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud)
} }
shost->hostdata[0] = (unsigned long)lu; shost->hostdata[0] = (unsigned long)lu;
shost->max_cmd_len = SBP2_MAX_CDB_SIZE;
if (!scsi_add_host(shost, &ud->device)) { if (!scsi_add_host(shost, &ud->device)) {
lu->shost = shost; lu->shost = shost;
......
...@@ -24,6 +24,12 @@ ...@@ -24,6 +24,12 @@
#define SBP2_DEVICE_NAME "sbp2" #define SBP2_DEVICE_NAME "sbp2"
/*
* There is no transport protocol limit to the CDB length, but we implement
* a fixed length only. 16 bytes is enough for disks larger than 2 TB.
*/
#define SBP2_MAX_CDB_SIZE 16
/* /*
* SBP-2 specific definitions * SBP-2 specific definitions
*/ */
...@@ -51,7 +57,7 @@ struct sbp2_command_orb { ...@@ -51,7 +57,7 @@ struct sbp2_command_orb {
u32 data_descriptor_hi; u32 data_descriptor_hi;
u32 data_descriptor_lo; u32 data_descriptor_lo;
u32 misc; u32 misc;
u8 cdb[12]; u8 cdb[SBP2_MAX_CDB_SIZE];
} __attribute__((packed)); } __attribute__((packed));
#define SBP2_LOGIN_REQUEST 0x0 #define SBP2_LOGIN_REQUEST 0x0
......
...@@ -127,6 +127,7 @@ struct fw_card { ...@@ -127,6 +127,7 @@ struct fw_card {
struct delayed_work work; struct delayed_work work;
int bm_retries; int bm_retries;
int bm_generation; int bm_generation;
__be32 bm_transaction_data[2];
bool broadcast_channel_allocated; bool broadcast_channel_allocated;
u32 broadcast_channel; u32 broadcast_channel;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment