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
This commit is contained in:
@@ -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)
|
|||||||
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)
|
|||||||
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 {
|
|||||||
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)
|
|||||||
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);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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);
|
|||||||
|
|
||||||
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)
|
|||||||
#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 {
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 @@
|
|||||||
|
|
||||||
#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 {
|
|||||||
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 {
|
|||||||
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;
|
||||||
|
Reference in New Issue
Block a user