Commit 1eee21ab 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:
  firewire: Add more documentation to firewire-cdev.h
  firewire: fix ioctl() return code
  firewire: fix setting tag and sy in iso transmission
  firewire: fw-sbp2: fix another small generation access bug
  firewire: fw-sbp2: enforce s/g segment size limit
  firewire: fw_send_request_sync()
  ieee1394: survive a few seconds connection loss
  ieee1394: nodemgr clean up class iterators
  ieee1394: dv1394, video1394: remove unnecessary expressions
  ieee1394: raw1394: make write() thread-safe
  ieee1394: raw1394: narrow down the state_mutex protected region
  ieee1394: raw1394: replace BKL by local mutex, make ioctl() and mmap() thread-safe
  ieee1394: sbp2: enforce s/g segment size limit
  ieee1394: sbp2: check for DMA mapping failures
  ieee1394: sbp2: stricter dma_sync
  ieee1394: Use DIV_ROUND_UP
parents 9d85db22 be585c07
...@@ -189,39 +189,16 @@ static const char gap_count_table[] = { ...@@ -189,39 +189,16 @@ static const char gap_count_table[] = {
63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
}; };
struct bm_data {
struct fw_transaction t;
struct {
__be32 arg;
__be32 data;
} lock;
u32 old;
int rcode;
struct completion done;
};
static void
complete_bm_lock(struct fw_card *card, int rcode,
void *payload, size_t length, void *data)
{
struct bm_data *bmd = data;
if (rcode == RCODE_COMPLETE)
bmd->old = be32_to_cpu(*(__be32 *) payload);
bmd->rcode = rcode;
complete(&bmd->done);
}
static void static void
fw_card_bm_work(struct work_struct *work) fw_card_bm_work(struct work_struct *work)
{ {
struct fw_card *card = container_of(work, struct fw_card, work.work); struct fw_card *card = container_of(work, struct fw_card, work.work);
struct fw_device *root_device; struct fw_device *root_device;
struct fw_node *root_node, *local_node; struct fw_node *root_node, *local_node;
struct bm_data bmd;
unsigned long flags; unsigned long flags;
int root_id, new_root_id, irm_id, gap_count, generation, grace; int root_id, new_root_id, irm_id, gap_count, generation, grace, rcode;
bool do_reset = false; bool do_reset = false;
__be32 lock_data[2];
spin_lock_irqsave(&card->lock, flags); spin_lock_irqsave(&card->lock, flags);
local_node = card->local_node; local_node = card->local_node;
...@@ -263,33 +240,28 @@ fw_card_bm_work(struct work_struct *work) ...@@ -263,33 +240,28 @@ fw_card_bm_work(struct work_struct *work)
goto pick_me; goto pick_me;
} }
bmd.lock.arg = cpu_to_be32(0x3f); lock_data[0] = cpu_to_be32(0x3f);
bmd.lock.data = cpu_to_be32(local_node->node_id); lock_data[1] = cpu_to_be32(local_node->node_id);
spin_unlock_irqrestore(&card->lock, flags); spin_unlock_irqrestore(&card->lock, flags);
init_completion(&bmd.done); rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
fw_send_request(card, &bmd.t, TCODE_LOCK_COMPARE_SWAP, irm_id, generation, SCODE_100,
irm_id, generation, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, lock_data, sizeof(lock_data));
&bmd.lock, sizeof(bmd.lock),
complete_bm_lock, &bmd);
wait_for_completion(&bmd.done);
if (bmd.rcode == RCODE_GENERATION) { if (rcode == RCODE_GENERATION)
/* /* Another bus reset, BM work has been rescheduled. */
* Another bus reset happened. Just return,
* the BM work has been rescheduled.
*/
goto out; goto out;
}
if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f) if (rcode == RCODE_COMPLETE &&
lock_data[0] != cpu_to_be32(0x3f))
/* Somebody else is BM, let them do the work. */ /* Somebody else is BM, let them do the work. */
goto out; goto out;
spin_lock_irqsave(&card->lock, flags); spin_lock_irqsave(&card->lock, flags);
if (bmd.rcode != RCODE_COMPLETE) {
if (rcode != RCODE_COMPLETE) {
/* /*
* The lock request failed, maybe the IRM * The lock request failed, maybe the IRM
* isn't really IRM capable after all. Let's * isn't really IRM capable after all. Let's
......
...@@ -720,8 +720,8 @@ static int ioctl_create_iso_context(struct client *client, void *buffer) ...@@ -720,8 +720,8 @@ static int ioctl_create_iso_context(struct client *client, void *buffer)
#define GET_PAYLOAD_LENGTH(v) ((v) & 0xffff) #define GET_PAYLOAD_LENGTH(v) ((v) & 0xffff)
#define GET_INTERRUPT(v) (((v) >> 16) & 0x01) #define GET_INTERRUPT(v) (((v) >> 16) & 0x01)
#define GET_SKIP(v) (((v) >> 17) & 0x01) #define GET_SKIP(v) (((v) >> 17) & 0x01)
#define GET_TAG(v) (((v) >> 18) & 0x02) #define GET_TAG(v) (((v) >> 18) & 0x03)
#define GET_SY(v) (((v) >> 20) & 0x04) #define GET_SY(v) (((v) >> 20) & 0x0f)
#define GET_HEADER_LENGTH(v) (((v) >> 24) & 0xff) #define GET_HEADER_LENGTH(v) (((v) >> 24) & 0xff)
static int ioctl_queue_iso(struct client *client, void *buffer) static int ioctl_queue_iso(struct client *client, void *buffer)
...@@ -913,7 +913,7 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) ...@@ -913,7 +913,7 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg)
return -EFAULT; return -EFAULT;
} }
return 0; return retval;
} }
static long static long
......
...@@ -381,46 +381,21 @@ static struct device_attribute fw_device_attributes[] = { ...@@ -381,46 +381,21 @@ static struct device_attribute fw_device_attributes[] = {
__ATTR_NULL, __ATTR_NULL,
}; };
struct read_quadlet_callback_data {
struct completion done;
int rcode;
u32 data;
};
static void
complete_transaction(struct fw_card *card, int rcode,
void *payload, size_t length, void *data)
{
struct read_quadlet_callback_data *callback_data = data;
if (rcode == RCODE_COMPLETE)
callback_data->data = be32_to_cpu(*(__be32 *)payload);
callback_data->rcode = rcode;
complete(&callback_data->done);
}
static int static int
read_rom(struct fw_device *device, int generation, int index, u32 *data) read_rom(struct fw_device *device, int generation, int index, u32 *data)
{ {
struct read_quadlet_callback_data callback_data; int rcode;
struct fw_transaction t;
u64 offset;
/* device->node_id, accessed below, must not be older than generation */ /* device->node_id, accessed below, must not be older than generation */
smp_rmb(); smp_rmb();
init_completion(&callback_data.done); rcode = fw_run_transaction(device->card, TCODE_READ_QUADLET_REQUEST,
offset = (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4;
fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
device->node_id, generation, device->max_speed, device->node_id, generation, device->max_speed,
offset, NULL, 4, complete_transaction, &callback_data); (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4,
data, 4);
wait_for_completion(&callback_data.done); be32_to_cpus(data);
*data = callback_data.data;
return callback_data.rcode; return rcode;
} }
#define READ_BIB_ROM_SIZE 256 #define READ_BIB_ROM_SIZE 256
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
*/ */
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/bug.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
...@@ -181,10 +182,16 @@ struct sbp2_target { ...@@ -181,10 +182,16 @@ struct sbp2_target {
#define SBP2_MAX_LOGIN_ORB_TIMEOUT 40000U /* Timeout in ms */ #define SBP2_MAX_LOGIN_ORB_TIMEOUT 40000U /* Timeout in ms */
#define SBP2_ORB_TIMEOUT 2000U /* Timeout in ms */ #define SBP2_ORB_TIMEOUT 2000U /* Timeout in ms */
#define SBP2_ORB_NULL 0x80000000 #define SBP2_ORB_NULL 0x80000000
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
#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 */
/*
* The default maximum s/g segment size of a FireWire controller is
* usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
* be quadlet-aligned, we set the length limit to 0xffff & ~3.
*/
#define SBP2_MAX_SEG_SIZE 0xfffc
/* Unit directory keys */ /* Unit directory keys */
#define SBP2_CSR_UNIT_CHARACTERISTICS 0x3a #define SBP2_CSR_UNIT_CHARACTERISTICS 0x3a
#define SBP2_CSR_FIRMWARE_REVISION 0x3c #define SBP2_CSR_FIRMWARE_REVISION 0x3c
...@@ -621,25 +628,15 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, ...@@ -621,25 +628,15 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
return retval; return retval;
} }
static void
complete_agent_reset_write(struct fw_card *card, int rcode,
void *payload, size_t length, void *done)
{
complete(done);
}
static void sbp2_agent_reset(struct sbp2_logical_unit *lu) static void sbp2_agent_reset(struct sbp2_logical_unit *lu)
{ {
struct fw_device *device = fw_device(lu->tgt->unit->device.parent); struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
DECLARE_COMPLETION_ONSTACK(done); __be32 d = 0;
struct fw_transaction t;
static u32 z;
fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST, fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
lu->tgt->node_id, lu->generation, device->max_speed, lu->tgt->node_id, lu->generation, device->max_speed,
lu->command_block_agent_address + SBP2_AGENT_RESET, lu->command_block_agent_address + SBP2_AGENT_RESET,
&z, sizeof(z), complete_agent_reset_write, &done); &d, sizeof(d));
wait_for_completion(&done);
} }
static void static void
...@@ -653,7 +650,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu) ...@@ -653,7 +650,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
{ {
struct fw_device *device = fw_device(lu->tgt->unit->device.parent); struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
struct fw_transaction *t; struct fw_transaction *t;
static u32 z; static __be32 d;
t = kmalloc(sizeof(*t), GFP_ATOMIC); t = kmalloc(sizeof(*t), GFP_ATOMIC);
if (t == NULL) if (t == NULL)
...@@ -662,7 +659,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu) ...@@ -662,7 +659,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
lu->tgt->node_id, lu->generation, device->max_speed, lu->tgt->node_id, lu->generation, device->max_speed,
lu->command_block_agent_address + SBP2_AGENT_RESET, lu->command_block_agent_address + SBP2_AGENT_RESET,
&z, sizeof(z), complete_agent_reset_write_no_wait, t); &d, sizeof(d), complete_agent_reset_write_no_wait, t);
} }
static void sbp2_set_generation(struct sbp2_logical_unit *lu, int generation) static void sbp2_set_generation(struct sbp2_logical_unit *lu, int generation)
...@@ -823,13 +820,6 @@ static void sbp2_target_put(struct sbp2_target *tgt) ...@@ -823,13 +820,6 @@ static void sbp2_target_put(struct sbp2_target *tgt)
kref_put(&tgt->kref, sbp2_release_target); kref_put(&tgt->kref, sbp2_release_target);
} }
static void
complete_set_busy_timeout(struct fw_card *card, int rcode,
void *payload, size_t length, void *done)
{
complete(done);
}
/* /*
* Write retransmit retry values into the BUSY_TIMEOUT register. * Write retransmit retry values into the BUSY_TIMEOUT register.
* - The single-phase retry protocol is supported by all SBP-2 devices, but the * - The single-phase retry protocol is supported by all SBP-2 devices, but the
...@@ -849,17 +839,12 @@ complete_set_busy_timeout(struct fw_card *card, int rcode, ...@@ -849,17 +839,12 @@ complete_set_busy_timeout(struct fw_card *card, int rcode,
static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu) static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
{ {
struct fw_device *device = fw_device(lu->tgt->unit->device.parent); struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
DECLARE_COMPLETION_ONSTACK(done); __be32 d = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
struct fw_transaction t;
static __be32 busy_timeout;
busy_timeout = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST, fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
lu->tgt->node_id, lu->generation, device->max_speed, lu->tgt->node_id, lu->generation, device->max_speed,
CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT, &busy_timeout, CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT,
sizeof(busy_timeout), complete_set_busy_timeout, &done); &d, sizeof(d));
wait_for_completion(&done);
} }
static void sbp2_reconnect(struct work_struct *work); static void sbp2_reconnect(struct work_struct *work);
...@@ -1121,6 +1106,10 @@ static int sbp2_probe(struct device *dev) ...@@ -1121,6 +1106,10 @@ static int sbp2_probe(struct device *dev)
struct Scsi_Host *shost; struct Scsi_Host *shost;
u32 model, firmware_revision; u32 model, firmware_revision;
if (dma_get_max_seg_size(device->card->device) > SBP2_MAX_SEG_SIZE)
BUG_ON(dma_set_max_seg_size(device->card->device,
SBP2_MAX_SEG_SIZE));
shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt)); shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt));
if (shost == NULL) if (shost == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -1369,14 +1358,12 @@ static int ...@@ -1369,14 +1358,12 @@ static int
sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
struct sbp2_logical_unit *lu) struct sbp2_logical_unit *lu)
{ {
struct scatterlist *sg; struct scatterlist *sg = scsi_sglist(orb->cmd);
int sg_len, l, i, j, count; int i, n;
dma_addr_t sg_addr;
n = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
sg = scsi_sglist(orb->cmd); orb->cmd->sc_data_direction);
count = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd), if (n == 0)
orb->cmd->sc_data_direction);
if (count == 0)
goto fail; goto fail;
/* /*
...@@ -1386,7 +1373,7 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, ...@@ -1386,7 +1373,7 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
* as the second generation iPod which doesn't support page * as the second generation iPod which doesn't support page
* tables. * tables.
*/ */
if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) { if (n == 1) {
orb->request.data_descriptor.high = orb->request.data_descriptor.high =
cpu_to_be32(lu->tgt->address_high); cpu_to_be32(lu->tgt->address_high);
orb->request.data_descriptor.low = orb->request.data_descriptor.low =
...@@ -1396,29 +1383,9 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, ...@@ -1396,29 +1383,9 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
return 0; return 0;
} }
/* for_each_sg(sg, sg, n, i) {
* Convert the scatterlist to an sbp2 page table. If any orb->page_table[i].high = cpu_to_be32(sg_dma_len(sg) << 16);
* scatterlist entries are too big for sbp2, we split them as we orb->page_table[i].low = cpu_to_be32(sg_dma_address(sg));
* go. Even if we ask the block I/O layer to not give us sg
* elements larger than 65535 bytes, some IOMMUs may merge sg elements
* during DMA mapping, and Linux currently doesn't prevent this.
*/
for (i = 0, j = 0; i < count; i++, sg = sg_next(sg)) {
sg_len = sg_dma_len(sg);
sg_addr = sg_dma_address(sg);
while (sg_len) {
/* FIXME: This won't get us out of the pinch. */
if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
fw_error("page table overflow\n");
goto fail_page_table;
}
l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
orb->page_table[j].low = cpu_to_be32(sg_addr);
orb->page_table[j].high = cpu_to_be32(l << 16);
sg_addr += l;
sg_len -= l;
j++;
}
} }
orb->page_table_bus = orb->page_table_bus =
...@@ -1437,13 +1404,13 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, ...@@ -1437,13 +1404,13 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
orb->request.data_descriptor.high = cpu_to_be32(lu->tgt->address_high); orb->request.data_descriptor.high = cpu_to_be32(lu->tgt->address_high);
orb->request.data_descriptor.low = cpu_to_be32(orb->page_table_bus); orb->request.data_descriptor.low = cpu_to_be32(orb->page_table_bus);
orb->request.misc |= cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT | orb->request.misc |= cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT |
COMMAND_ORB_DATA_SIZE(j)); COMMAND_ORB_DATA_SIZE(n));
return 0; return 0;
fail_page_table: fail_page_table:
dma_unmap_sg(device->card->device, sg, scsi_sg_count(orb->cmd), dma_unmap_sg(device->card->device, scsi_sglist(orb->cmd),
orb->cmd->sc_data_direction); scsi_sg_count(orb->cmd), orb->cmd->sc_data_direction);
fail: fail:
return -ENOMEM; return -ENOMEM;
} }
...@@ -1456,7 +1423,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) ...@@ -1456,7 +1423,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
struct fw_device *device = fw_device(lu->tgt->unit->device.parent); struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
struct sbp2_command_orb *orb; struct sbp2_command_orb *orb;
unsigned int max_payload; unsigned int max_payload;
int retval = SCSI_MLQUEUE_HOST_BUSY; int generation, retval = SCSI_MLQUEUE_HOST_BUSY;
/* /*
* Bidirectional commands are not yet implemented, and unknown * Bidirectional commands are not yet implemented, and unknown
...@@ -1500,6 +1467,9 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) ...@@ -1500,6 +1467,9 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
if (cmd->sc_data_direction == DMA_FROM_DEVICE) if (cmd->sc_data_direction == DMA_FROM_DEVICE)
orb->request.misc |= cpu_to_be32(COMMAND_ORB_DIRECTION); orb->request.misc |= cpu_to_be32(COMMAND_ORB_DIRECTION);
generation = device->generation;
smp_rmb(); /* sbp2_map_scatterlist looks at tgt->address_high */
if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0) if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0)
goto out; goto out;
...@@ -1512,7 +1482,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) ...@@ -1512,7 +1482,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
if (dma_mapping_error(device->card->device, orb->base.request_bus)) if (dma_mapping_error(device->card->device, orb->base.request_bus))
goto out; goto out;
sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, lu->generation, sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, generation,
lu->command_block_agent_address + SBP2_ORB_POINTER); lu->command_block_agent_address + SBP2_ORB_POINTER);
retval = 0; retval = 0;
out: out:
...@@ -1564,6 +1534,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev) ...@@ -1564,6 +1534,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512); blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE);
return 0; return 0;
} }
......
...@@ -247,7 +247,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, ...@@ -247,7 +247,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
*/ */
void void
fw_send_request(struct fw_card *card, struct fw_transaction *t, fw_send_request(struct fw_card *card, struct fw_transaction *t,
int tcode, int node_id, int generation, int speed, int tcode, int destination_id, int generation, int speed,
unsigned long long offset, unsigned long long offset,
void *payload, size_t length, void *payload, size_t length,
fw_transaction_callback_t callback, void *callback_data) fw_transaction_callback_t callback, void *callback_data)
...@@ -279,13 +279,14 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t, ...@@ -279,13 +279,14 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
card->current_tlabel = (card->current_tlabel + 1) & 0x1f; card->current_tlabel = (card->current_tlabel + 1) & 0x1f;
card->tlabel_mask |= (1 << tlabel); card->tlabel_mask |= (1 << tlabel);
t->node_id = node_id; t->node_id = destination_id;
t->tlabel = tlabel; t->tlabel = tlabel;
t->callback = callback; t->callback = callback;
t->callback_data = callback_data; t->callback_data = callback_data;
fw_fill_request(&t->packet, tcode, t->tlabel, node_id, card->node_id, fw_fill_request(&t->packet, tcode, t->tlabel,
generation, speed, offset, payload, length); destination_id, card->node_id, generation,
speed, offset, payload, length);
t->packet.callback = transmit_complete_callback; t->packet.callback = transmit_complete_callback;
list_add_tail(&t->link, &card->transaction_list); list_add_tail(&t->link, &card->transaction_list);
...@@ -296,6 +297,45 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t, ...@@ -296,6 +297,45 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
} }
EXPORT_SYMBOL(fw_send_request); EXPORT_SYMBOL(fw_send_request);
struct transaction_callback_data {
struct completion done;
void *payload;
int rcode;
};
static void transaction_callback(struct fw_card *card, int rcode,
void *payload, size_t length, void *data)
{
struct transaction_callback_data *d = data;
if (rcode == RCODE_COMPLETE)
memcpy(d->payload, payload, length);
d->rcode = rcode;
complete(&d->done);
}
/**
* fw_run_transaction - send request and sleep until transaction is completed
*
* Returns the RCODE.
*/
int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
int generation, int speed, unsigned long long offset,
void *data, size_t length)
{
struct transaction_callback_data d;
struct fw_transaction t;
init_completion(&d.done);
d.payload = data;
fw_send_request(card, &t, tcode, destination_id, generation, speed,
offset, data, length, transaction_callback, &d);
wait_for_completion(&d.done);
return d.rcode;
}
EXPORT_SYMBOL(fw_run_transaction);
static DEFINE_MUTEX(phy_config_mutex); static DEFINE_MUTEX(phy_config_mutex);
static DECLARE_COMPLETION(phy_config_done); static DECLARE_COMPLETION(phy_config_done);
......
...@@ -426,11 +426,14 @@ fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); ...@@ -426,11 +426,14 @@ fw_core_initiate_bus_reset(struct fw_card *card, int short_reset);
void void
fw_send_request(struct fw_card *card, struct fw_transaction *t, fw_send_request(struct fw_card *card, struct fw_transaction *t,
int tcode, int node_id, int generation, int speed, int tcode, int destination_id, int generation, int speed,
unsigned long long offset, unsigned long long offset, void *data, size_t length,
void *data, size_t length,
fw_transaction_callback_t callback, void *callback_data); fw_transaction_callback_t callback, void *callback_data);
int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
int generation, int speed, unsigned long long offset,
void *data, size_t length);
int fw_cancel_transaction(struct fw_card *card, int fw_cancel_transaction(struct fw_card *card,
struct fw_transaction *transaction); struct fw_transaction *transaction);
......
...@@ -84,7 +84,7 @@ static const u8 csr1212_key_id_type_map[0x30] = { ...@@ -84,7 +84,7 @@ static const u8 csr1212_key_id_type_map[0x30] = {
#define quads_to_bytes(_q) ((_q) * sizeof(u32)) #define quads_to_bytes(_q) ((_q) * sizeof(u32))
#define bytes_to_quads(_b) (((_b) + sizeof(u32) - 1) / sizeof(u32)) #define bytes_to_quads(_b) DIV_ROUND_UP(_b, sizeof(u32))
static void free_keyval(struct csr1212_keyval *kv) static void free_keyval(struct csr1212_keyval *kv)
{ {
......
...@@ -918,7 +918,7 @@ static int do_dv1394_init(struct video_card *video, struct dv1394_init *init) ...@@ -918,7 +918,7 @@ static int do_dv1394_init(struct video_card *video, struct dv1394_init *init)
/* default SYT offset is 3 cycles */ /* default SYT offset is 3 cycles */
init->syt_offset = 3; init->syt_offset = 3;
if ( (init->channel > 63) || (init->channel < 0) ) if (init->channel > 63)
init->channel = 63; init->channel = 63;
chan_mask = (u64)1 << init->channel; chan_mask = (u64)1 << init->channel;
......
...@@ -1361,7 +1361,7 @@ static unsigned int ether1394_encapsulate_prep(unsigned int max_payload, ...@@ -1361,7 +1361,7 @@ static unsigned int ether1394_encapsulate_prep(unsigned int max_payload,
hdr->ff.dgl = dgl; hdr->ff.dgl = dgl;
adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_FF]; adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_FF];
} }
return (dg_size + adj_max_payload - 1) / adj_max_payload; return DIV_ROUND_UP(dg_size, adj_max_payload);
} }
static unsigned int ether1394_encapsulate(struct sk_buff *skb, static unsigned int ether1394_encapsulate(struct sk_buff *skb,
......
This diff is collapsed.
...@@ -110,7 +110,7 @@ struct node_entry { ...@@ -110,7 +110,7 @@ struct node_entry {
struct device node_dev; struct device node_dev;
/* Means this node is not attached anymore */ /* Means this node is not attached anymore */
int in_limbo; bool in_limbo;
struct csr1212_csr *csr; struct csr1212_csr *csr;
}; };
......
...@@ -22,6 +22,7 @@ enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0, ...@@ -22,6 +22,7 @@ enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0,
struct file_info { struct file_info {
struct list_head list; struct list_head list;
struct mutex state_mutex;
enum { opened, initialized, connected } state; enum { opened, initialized, connected } state;
unsigned int protocol_version; unsigned int protocol_version;
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
...@@ -2267,6 +2268,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, ...@@ -2267,6 +2268,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
return -EFAULT; return -EFAULT;
} }
mutex_lock(&fi->state_mutex);
switch (fi->state) { switch (fi->state) {
case opened: case opened:
retval = state_opened(fi, req); retval = state_opened(fi, req);
...@@ -2281,6 +2284,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, ...@@ -2281,6 +2284,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
break; break;
} }
mutex_unlock(&fi->state_mutex);
if (retval < 0) { if (retval < 0) {
free_pending_request(req); free_pending_request(req);
} else { } else {
...@@ -2541,109 +2546,120 @@ static int raw1394_read_cycle_timer(struct file_info *fi, void __user * uaddr) ...@@ -2541,109 +2546,120 @@ static int raw1394_read_cycle_timer(struct file_info *fi, void __user * uaddr)
static int raw1394_mmap(struct file *file, struct vm_area_struct *vma) static int raw1394_mmap(struct file *file, struct vm_area_struct *vma)
{ {
struct file_info *fi = file->private_data; struct file_info *fi = file->private_data;
int ret;
mutex_lock(&fi->state_mutex);
if (fi->iso_state == RAW1394_ISO_INACTIVE) if (fi->iso_state == RAW1394_ISO_INACTIVE)
return -EINVAL; ret = -EINVAL;
else
ret = dma_region_mmap(&fi->iso_handle->data_buf, file, vma);
mutex_unlock(&fi->state_mutex);
return dma_region_mmap(&fi->iso_handle->data_buf, file, vma); return ret;
} }
/* ioctl is only used for rawiso operations */ static long raw1394_ioctl_inactive(struct file_info *fi, unsigned int cmd,
static long do_raw1394_ioctl(struct file *file, unsigned int cmd, void __user *argp)
unsigned long arg) {
switch (cmd) {
case RAW1394_IOC_ISO_XMIT_INIT:
return raw1394_iso_xmit_init(fi, argp);
case RAW1394_IOC_ISO_RECV_INIT:
return raw1394_iso_recv_init(fi, argp);
default:
return -EINVAL;
}
}
static long raw1394_ioctl_recv(struct file_info *fi, unsigned int cmd,
unsigned long arg)
{ {
struct file_info *fi = file->private_data;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
switch (fi->iso_state) { switch (cmd) {
case RAW1394_ISO_INACTIVE: case RAW1394_IOC_ISO_RECV_START:{
switch (cmd) { int args[3];
case RAW1394_IOC_ISO_XMIT_INIT:
return raw1394_iso_xmit_init(fi, argp); if (copy_from_user(&args[0], argp, sizeof(args)))
case RAW1394_IOC_ISO_RECV_INIT: return -EFAULT;
return raw1394_iso_recv_init(fi, argp); return hpsb_iso_recv_start(fi->iso_handle,
default: args[0], args[1], args[2]);
break;
} }
break; case RAW1394_IOC_ISO_XMIT_RECV_STOP:
case RAW1394_ISO_RECV: hpsb_iso_stop(fi->iso_handle);
switch (cmd) { return 0;
case RAW1394_IOC_ISO_RECV_START:{ case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
/* copy args from user-space */ return hpsb_iso_recv_listen_channel(fi->iso_handle, arg);
int args[3]; case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
if (copy_from_user return hpsb_iso_recv_unlisten_channel(fi->iso_handle, arg);
(&args[0], argp, sizeof(args))) case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{
return -EFAULT; u64 mask;
return hpsb_iso_recv_start(fi->iso_handle,
args[0], args[1], if (copy_from_user(&mask, argp, sizeof(mask)))
args[2]); return -EFAULT;
} return hpsb_iso_recv_set_channel_mask(fi->iso_handle,
case RAW1394_IOC_ISO_XMIT_RECV_STOP: mask);
hpsb_iso_stop(fi->iso_handle);
return 0;
case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
return hpsb_iso_recv_listen_channel(fi->iso_handle,
arg);
case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
return hpsb_iso_recv_unlisten_channel(fi->iso_handle,
arg);
case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{
/* copy the u64 from user-space */
u64 mask;
if (copy_from_user(&mask, argp, sizeof(mask)))
return -EFAULT;
return hpsb_iso_recv_set_channel_mask(fi->
iso_handle,
mask);
}
case RAW1394_IOC_ISO_GET_STATUS:
return raw1394_iso_get_status(fi, argp);
case RAW1394_IOC_ISO_RECV_PACKETS:
return raw1394_iso_recv_packets(fi, argp);
case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
return hpsb_iso_recv_release_packets(fi->iso_handle,
arg);
case RAW1394_IOC_ISO_RECV_FLUSH:
return hpsb_iso_recv_flush(fi->iso_handle);
case RAW1394_IOC_ISO_SHUTDOWN:
raw1394_iso_shutdown(fi);
return 0;
case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
queue_rawiso_event(fi);
return 0;
} }
break; case RAW1394_IOC_ISO_GET_STATUS:
case RAW1394_ISO_XMIT: return raw1394_iso_get_status(fi, argp);
switch (cmd) { case RAW1394_IOC_ISO_RECV_PACKETS:
case RAW1394_IOC_ISO_XMIT_START:{ return raw1394_iso_recv_packets(fi, argp);
/* copy two ints from user-space */ case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
int args[2]; return hpsb_iso_recv_release_packets(fi->iso_handle, arg);
if (copy_from_user case RAW1394_IOC_ISO_RECV_FLUSH:
(&args[0], argp, sizeof(args))) return hpsb_iso_recv_flush(fi->iso_handle);
return -EFAULT; case RAW1394_IOC_ISO_SHUTDOWN:
return hpsb_iso_xmit_start(fi->iso_handle, raw1394_iso_shutdown(fi);
args[0], args[1]); return 0;
} case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
case RAW1394_IOC_ISO_XMIT_SYNC: queue_rawiso_event(fi);
return hpsb_iso_xmit_sync(fi->iso_handle); return 0;
case RAW1394_IOC_ISO_XMIT_RECV_STOP: default:
hpsb_iso_stop(fi->iso_handle); return -EINVAL;
return 0; }
case RAW1394_IOC_ISO_GET_STATUS: }
return raw1394_iso_get_status(fi, argp);
case RAW1394_IOC_ISO_XMIT_PACKETS: static long raw1394_ioctl_xmit(struct file_info *fi, unsigned int cmd,
return raw1394_iso_send_packets(fi, argp); void __user *argp)
case RAW1394_IOC_ISO_SHUTDOWN: {
raw1394_iso_shutdown(fi); switch (cmd) {
return 0; case RAW1394_IOC_ISO_XMIT_START:{
case RAW1394_IOC_ISO_QUEUE_ACTIVITY: int args[2];
queue_rawiso_event(fi);
return 0; if (copy_from_user(&args[0], argp, sizeof(args)))
return -EFAULT;
return hpsb_iso_xmit_start(fi->iso_handle,
args[0], args[1]);
} }
break; case RAW1394_IOC_ISO_XMIT_SYNC:
return hpsb_iso_xmit_sync(fi->iso_handle);
case RAW1394_IOC_ISO_XMIT_RECV_STOP:
hpsb_iso_stop(fi->iso_handle);
return 0;
case RAW1394_IOC_ISO_GET_STATUS:
return raw1394_iso_get_status(fi, argp);
case RAW1394_IOC_ISO_XMIT_PACKETS:
return raw1394_iso_send_packets(fi, argp);
case RAW1394_IOC_ISO_SHUTDOWN:
raw1394_iso_shutdown(fi);
return 0;
case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
queue_rawiso_event(fi);
return 0;
default: default:
break; return -EINVAL;
} }
}
/* ioctl is only used for rawiso operations */
static long raw1394_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct file_info *fi = file->private_data;
void __user *argp = (void __user *)arg;
long ret;
/* state-independent commands */ /* state-independent commands */
switch(cmd) { switch(cmd) {
...@@ -2653,16 +2669,25 @@ static long do_raw1394_ioctl(struct file *file, unsigned int cmd, ...@@ -2653,16 +2669,25 @@ static long do_raw1394_ioctl(struct file *file, unsigned int cmd,
break; break;
} }
return -EINVAL; mutex_lock(&fi->state_mutex);
}
switch (fi->iso_state) {
case RAW1394_ISO_INACTIVE:
ret = raw1394_ioctl_inactive(fi, cmd, argp);
break;
case RAW1394_ISO_RECV:
ret = raw1394_ioctl_recv(fi, cmd, arg);
break;
case RAW1394_ISO_XMIT:
ret = raw1394_ioctl_xmit(fi, cmd, argp);
break;
default:
ret = -EINVAL;
break;
}
mutex_unlock(&fi->state_mutex);
static long raw1394_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
long ret;
lock_kernel();
ret = do_raw1394_ioctl(file, cmd, arg);
unlock_kernel();
return ret; return ret;
} }
...@@ -2700,7 +2725,7 @@ static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd, ...@@ -2700,7 +2725,7 @@ static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd,
!copy_from_user(&infos32, &arg->infos, sizeof infos32)) { !copy_from_user(&infos32, &arg->infos, sizeof infos32)) {
infos = compat_ptr(infos32); infos = compat_ptr(infos32);
if (!copy_to_user(&dst->infos, &infos, sizeof infos)) if (!copy_to_user(&dst->infos, &infos, sizeof infos))
err = do_raw1394_ioctl(file, cmd, (unsigned long)dst); err = raw1394_ioctl(file, cmd, (unsigned long)dst);
} }
return err; return err;
} }
...@@ -2724,7 +2749,6 @@ static long raw1394_compat_ioctl(struct file *file, ...@@ -2724,7 +2749,6 @@ static long raw1394_compat_ioctl(struct file *file,
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
long err; long err;
lock_kernel();
switch (cmd) { switch (cmd) {
/* These requests have same format as long as 'int' has same size. */ /* These requests have same format as long as 'int' has same size. */
case RAW1394_IOC_ISO_RECV_INIT: case RAW1394_IOC_ISO_RECV_INIT:
...@@ -2741,7 +2765,7 @@ static long raw1394_compat_ioctl(struct file *file, ...@@ -2741,7 +2765,7 @@ static long raw1394_compat_ioctl(struct file *file,
case RAW1394_IOC_ISO_GET_STATUS: case RAW1394_IOC_ISO_GET_STATUS:
case RAW1394_IOC_ISO_SHUTDOWN: case RAW1394_IOC_ISO_SHUTDOWN:
case RAW1394_IOC_ISO_QUEUE_ACTIVITY: case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
err = do_raw1394_ioctl(file, cmd, arg); err = raw1394_ioctl(file, cmd, arg);
break; break;
/* These request have different format. */ /* These request have different format. */
case RAW1394_IOC_ISO_RECV_PACKETS32: case RAW1394_IOC_ISO_RECV_PACKETS32:
...@@ -2757,7 +2781,6 @@ static long raw1394_compat_ioctl(struct file *file, ...@@ -2757,7 +2781,6 @@ static long raw1394_compat_ioctl(struct file *file,
err = -EINVAL; err = -EINVAL;
break; break;
} }
unlock_kernel();
return err; return err;
} }
...@@ -2791,6 +2814,7 @@ static int raw1394_open(struct inode *inode, struct file *file) ...@@ -2791,6 +2814,7 @@ static int raw1394_open(struct inode *inode, struct file *file)
fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */ fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */
INIT_LIST_HEAD(&fi->list); INIT_LIST_HEAD(&fi->list);
mutex_init(&fi->state_mutex);
fi->state = opened; fi->state = opened;
INIT_LIST_HEAD(&fi->req_pending); INIT_LIST_HEAD(&fi->req_pending);
INIT_LIST_HEAD(&fi->req_complete); INIT_LIST_HEAD(&fi->req_complete);
......
This diff is collapsed.
...@@ -139,13 +139,10 @@ struct sbp2_logout_orb { ...@@ -139,13 +139,10 @@ struct sbp2_logout_orb {
u32 status_fifo_lo; u32 status_fifo_lo;
} __attribute__((packed)); } __attribute__((packed));
#define PAGE_TABLE_SET_SEGMENT_BASE_HI(v) ((v) & 0xffff)
#define PAGE_TABLE_SET_SEGMENT_LENGTH(v) (((v) & 0xffff) << 16)
struct sbp2_unrestricted_page_table { struct sbp2_unrestricted_page_table {
u32 length_segment_base_hi; __be32 high;
u32 segment_base_lo; __be32 low;
} __attribute__((packed)); };
#define RESP_STATUS_REQUEST_COMPLETE 0x0 #define RESP_STATUS_REQUEST_COMPLETE 0x0
#define RESP_STATUS_TRANSPORT_FAILURE 0x1 #define RESP_STATUS_TRANSPORT_FAILURE 0x1
...@@ -216,15 +213,18 @@ struct sbp2_status_block { ...@@ -216,15 +213,18 @@ struct sbp2_status_block {
#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e #define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e
#define SBP2_SW_VERSION_ENTRY 0x00010483 #define SBP2_SW_VERSION_ENTRY 0x00010483
/* /*
* SCSI specific definitions * The default maximum s/g segment size of a FireWire controller is
* usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
* be quadlet-aligned, we set the length limit to 0xffff & ~3.
*/ */
#define SBP2_MAX_SEG_SIZE 0xfffc
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 /*
/* There is no real limitation of the queue depth (i.e. length of the linked * There is no real limitation of the queue depth (i.e. length of the linked
* list of command ORBs) at the target. The chosen depth is merely an * list of command ORBs) at the target. The chosen depth is merely an
* implementation detail of the sbp2 driver. */ * implementation detail of the sbp2 driver.
*/
#define SBP2_MAX_CMDS 8 #define SBP2_MAX_CMDS 8
#define SBP2_SCSI_STATUS_GOOD 0x0 #define SBP2_SCSI_STATUS_GOOD 0x0
...@@ -240,12 +240,6 @@ struct sbp2_status_block { ...@@ -240,12 +240,6 @@ struct sbp2_status_block {
* Representations of commands and devices * Representations of commands and devices
*/ */
enum sbp2_dma_types {
CMD_DMA_NONE,
CMD_DMA_PAGE,
CMD_DMA_SINGLE
};
/* Per SCSI command */ /* Per SCSI command */
struct sbp2_command_info { struct sbp2_command_info {
struct list_head list; struct list_head list;
...@@ -258,11 +252,6 @@ struct sbp2_command_info { ...@@ -258,11 +252,6 @@ struct sbp2_command_info {
struct sbp2_unrestricted_page_table struct sbp2_unrestricted_page_table
scatter_gather_element[SG_ALL] __attribute__((aligned(8))); scatter_gather_element[SG_ALL] __attribute__((aligned(8)));
dma_addr_t sge_dma; dma_addr_t sge_dma;
void *sge_buffer;
dma_addr_t cmd_dma;
enum sbp2_dma_types dma_type;
unsigned long dma_size;
enum dma_data_direction dma_dir;
}; };
/* Per FireWire host */ /* Per FireWire host */
......
...@@ -893,7 +893,7 @@ static long video1394_ioctl(struct file *file, ...@@ -893,7 +893,7 @@ static long video1394_ioctl(struct file *file,
if (unlikely(d == NULL)) if (unlikely(d == NULL))
return -EFAULT; return -EFAULT;
if (unlikely((v.buffer<0) || (v.buffer>=d->num_desc - 1))) { if (unlikely(v.buffer >= d->num_desc - 1)) {
PRINT(KERN_ERR, ohci->host->id, PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer); "Buffer %d out of range",v.buffer);
return -EINVAL; return -EINVAL;
...@@ -959,7 +959,7 @@ static long video1394_ioctl(struct file *file, ...@@ -959,7 +959,7 @@ static long video1394_ioctl(struct file *file,
if (unlikely(d == NULL)) if (unlikely(d == NULL))
return -EFAULT; return -EFAULT;
if (unlikely((v.buffer<0) || (v.buffer>d->num_desc - 1))) { if (unlikely(v.buffer > d->num_desc - 1)) {
PRINT(KERN_ERR, ohci->host->id, PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer); "Buffer %d out of range",v.buffer);
return -EINVAL; return -EINVAL;
...@@ -1030,7 +1030,7 @@ static long video1394_ioctl(struct file *file, ...@@ -1030,7 +1030,7 @@ static long video1394_ioctl(struct file *file,
d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
if (d == NULL) return -EFAULT; if (d == NULL) return -EFAULT;
if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) { if (v.buffer >= d->num_desc - 1) {
PRINT(KERN_ERR, ohci->host->id, PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer); "Buffer %d out of range",v.buffer);
return -EINVAL; return -EINVAL;
...@@ -1137,7 +1137,7 @@ static long video1394_ioctl(struct file *file, ...@@ -1137,7 +1137,7 @@ static long video1394_ioctl(struct file *file,
d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
if (d == NULL) return -EFAULT; if (d == NULL) return -EFAULT;
if ((v.buffer<0) || (v.buffer>=d->num_desc-1)) { if (v.buffer >= d->num_desc - 1) {
PRINT(KERN_ERR, ohci->host->id, PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer); "Buffer %d out of range",v.buffer);
return -EINVAL; return -EINVAL;
......
...@@ -154,8 +154,13 @@ struct fw_cdev_event_iso_interrupt { ...@@ -154,8 +154,13 @@ struct fw_cdev_event_iso_interrupt {
* @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST
* @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT
* *
* Convenience union for userspace use. Events could be read(2) into a char * Convenience union for userspace use. Events could be read(2) into an
* buffer and then cast to this union for further processing. * appropriately aligned char buffer and then cast to this union for further
* processing. Note that for a request, response or iso_interrupt event,
* the data[] or header[] may make the size of the full event larger than
* sizeof(union fw_cdev_event). Also note that if you attempt to read(2)
* an event into a buffer that is not large enough for it, the data that does
* not fit will be discarded so that the next read(2) will return a new event.
*/ */
union fw_cdev_event { union fw_cdev_event {
struct fw_cdev_event_common common; struct fw_cdev_event_common common;
......
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