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[] = {
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
fw_card_bm_work(struct work_struct *work)
{
struct fw_card *card = container_of(work, struct fw_card, work.work);
struct fw_device *root_device;
struct fw_node *root_node, *local_node;
struct bm_data bmd;
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;
__be32 lock_data[2];
spin_lock_irqsave(&card->lock, flags);
local_node = card->local_node;
......@@ -263,33 +240,28 @@ fw_card_bm_work(struct work_struct *work)
goto pick_me;
}
bmd.lock.arg = cpu_to_be32(0x3f);
bmd.lock.data = cpu_to_be32(local_node->node_id);
lock_data[0] = cpu_to_be32(0x3f);
lock_data[1] = cpu_to_be32(local_node->node_id);
spin_unlock_irqrestore(&card->lock, flags);
init_completion(&bmd.done);
fw_send_request(card, &bmd.t, TCODE_LOCK_COMPARE_SWAP,
irm_id, generation,
SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
&bmd.lock, sizeof(bmd.lock),
complete_bm_lock, &bmd);
wait_for_completion(&bmd.done);
rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
irm_id, generation, SCODE_100,
CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
lock_data, sizeof(lock_data));
if (bmd.rcode == RCODE_GENERATION) {
/*
* Another bus reset happened. Just return,
* the BM work has been rescheduled.
*/
if (rcode == RCODE_GENERATION)
/* Another bus reset, BM work has been rescheduled. */
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. */
goto out;
spin_lock_irqsave(&card->lock, flags);
if (bmd.rcode != RCODE_COMPLETE) {
if (rcode != RCODE_COMPLETE) {
/*
* The lock request failed, maybe the IRM
* isn't really IRM capable after all. Let's
......
......@@ -720,8 +720,8 @@ static int ioctl_create_iso_context(struct client *client, void *buffer)
#define GET_PAYLOAD_LENGTH(v) ((v) & 0xffff)
#define GET_INTERRUPT(v) (((v) >> 16) & 0x01)
#define GET_SKIP(v) (((v) >> 17) & 0x01)
#define GET_TAG(v) (((v) >> 18) & 0x02)
#define GET_SY(v) (((v) >> 20) & 0x04)
#define GET_TAG(v) (((v) >> 18) & 0x03)
#define GET_SY(v) (((v) >> 20) & 0x0f)
#define GET_HEADER_LENGTH(v) (((v) >> 24) & 0xff)
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)
return -EFAULT;
}
return 0;
return retval;
}
static long
......
......@@ -381,46 +381,21 @@ static struct device_attribute fw_device_attributes[] = {
__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
read_rom(struct fw_device *device, int generation, int index, u32 *data)
{
struct read_quadlet_callback_data callback_data;
struct fw_transaction t;
u64 offset;
int rcode;
/* device->node_id, accessed below, must not be older than generation */
smp_rmb();
init_completion(&callback_data.done);
offset = (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4;
fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
rcode = fw_run_transaction(device->card, TCODE_READ_QUADLET_REQUEST,
device->node_id, generation, device->max_speed,
offset, NULL, 4, complete_transaction, &callback_data);
wait_for_completion(&callback_data.done);
*data = callback_data.data;
(CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4,
data, 4);
be32_to_cpus(data);
return callback_data.rcode;
return rcode;
}
#define READ_BIB_ROM_SIZE 256
......
......@@ -29,6 +29,7 @@
*/
#include <linux/blkdev.h>
#include <linux/bug.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
......@@ -181,10 +182,16 @@ struct sbp2_target {
#define SBP2_MAX_LOGIN_ORB_TIMEOUT 40000U /* Timeout in ms */
#define SBP2_ORB_TIMEOUT 2000U /* Timeout in ms */
#define SBP2_ORB_NULL 0x80000000
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
#define SBP2_RETRY_LIMIT 0xf /* 15 retries */
#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 */
#define SBP2_CSR_UNIT_CHARACTERISTICS 0x3a
#define SBP2_CSR_FIRMWARE_REVISION 0x3c
......@@ -621,25 +628,15 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
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)
{
struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
DECLARE_COMPLETION_ONSTACK(done);
struct fw_transaction t;
static u32 z;
__be32 d = 0;
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->command_block_agent_address + SBP2_AGENT_RESET,
&z, sizeof(z), complete_agent_reset_write, &done);
wait_for_completion(&done);
&d, sizeof(d));
}
static void
......@@ -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_transaction *t;
static u32 z;
static __be32 d;
t = kmalloc(sizeof(*t), GFP_ATOMIC);
if (t == NULL)
......@@ -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,
lu->tgt->node_id, lu->generation, device->max_speed,
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)
......@@ -823,13 +820,6 @@ static void sbp2_target_put(struct sbp2_target *tgt)
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.
* - 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,
static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
{
struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
DECLARE_COMPLETION_ONSTACK(done);
struct fw_transaction t;
static __be32 busy_timeout;
__be32 d = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
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,
CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT, &busy_timeout,
sizeof(busy_timeout), complete_set_busy_timeout, &done);
wait_for_completion(&done);
CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT,
&d, sizeof(d));
}
static void sbp2_reconnect(struct work_struct *work);
......@@ -1121,6 +1106,10 @@ static int sbp2_probe(struct device *dev)
struct Scsi_Host *shost;
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));
if (shost == NULL)
return -ENOMEM;
......@@ -1369,14 +1358,12 @@ static int
sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
struct sbp2_logical_unit *lu)
{
struct scatterlist *sg;
int sg_len, l, i, j, count;
dma_addr_t sg_addr;
struct scatterlist *sg = scsi_sglist(orb->cmd);
int i, n;
sg = scsi_sglist(orb->cmd);
count = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
n = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
orb->cmd->sc_data_direction);
if (count == 0)
if (n == 0)
goto fail;
/*
......@@ -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
* tables.
*/
if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) {
if (n == 1) {
orb->request.data_descriptor.high =
cpu_to_be32(lu->tgt->address_high);
orb->request.data_descriptor.low =
......@@ -1396,29 +1383,9 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
return 0;
}
/*
* Convert the scatterlist to an sbp2 page table. If any
* scatterlist entries are too big for sbp2, we split them as we
* 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++;
}
for_each_sg(sg, sg, n, i) {
orb->page_table[i].high = cpu_to_be32(sg_dma_len(sg) << 16);
orb->page_table[i].low = cpu_to_be32(sg_dma_address(sg));
}
orb->page_table_bus =
......@@ -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.low = cpu_to_be32(orb->page_table_bus);
orb->request.misc |= cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT |
COMMAND_ORB_DATA_SIZE(j));
COMMAND_ORB_DATA_SIZE(n));
return 0;
fail_page_table:
dma_unmap_sg(device->card->device, sg, scsi_sg_count(orb->cmd),
orb->cmd->sc_data_direction);
dma_unmap_sg(device->card->device, scsi_sglist(orb->cmd),
scsi_sg_count(orb->cmd), orb->cmd->sc_data_direction);
fail:
return -ENOMEM;
}
......@@ -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 sbp2_command_orb *orb;
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
......@@ -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)
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)
goto out;
......@@ -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))
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);
retval = 0;
out:
......@@ -1564,6 +1534,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE);
return 0;
}
......
......@@ -247,7 +247,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
*/
void
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,
void *payload, size_t length,
fw_transaction_callback_t callback, void *callback_data)
......@@ -279,13 +279,14 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
card->current_tlabel = (card->current_tlabel + 1) & 0x1f;
card->tlabel_mask |= (1 << tlabel);
t->node_id = node_id;
t->node_id = destination_id;
t->tlabel = tlabel;
t->callback = callback;
t->callback_data = callback_data;
fw_fill_request(&t->packet, tcode, t->tlabel, node_id, card->node_id,
generation, speed, offset, payload, length);
fw_fill_request(&t->packet, tcode, t->tlabel,
destination_id, card->node_id, generation,
speed, offset, payload, length);
t->packet.callback = transmit_complete_callback;
list_add_tail(&t->link, &card->transaction_list);
......@@ -296,6 +297,45 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
}
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 DECLARE_COMPLETION(phy_config_done);
......
......@@ -426,11 +426,14 @@ fw_core_initiate_bus_reset(struct fw_card *card, int short_reset);
void
fw_send_request(struct fw_card *card, struct fw_transaction *t,
int tcode, int node_id, int generation, int speed,
unsigned long long offset,
void *data, size_t length,
int tcode, int destination_id, int generation, int speed,
unsigned long long offset, void *data, size_t length,
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,
struct fw_transaction *transaction);
......
......@@ -84,7 +84,7 @@ static const u8 csr1212_key_id_type_map[0x30] = {
#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)
{
......
......@@ -918,7 +918,7 @@ static int do_dv1394_init(struct video_card *video, struct dv1394_init *init)
/* default SYT offset is 3 cycles */
init->syt_offset = 3;
if ( (init->channel > 63) || (init->channel < 0) )
if (init->channel > 63)
init->channel = 63;
chan_mask = (u64)1 << init->channel;
......
......@@ -1361,7 +1361,7 @@ static unsigned int ether1394_encapsulate_prep(unsigned int max_payload,
hdr->ff.dgl = dgl;
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,
......
......@@ -154,9 +154,6 @@ struct host_info {
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env);
static void nodemgr_resume_ne(struct node_entry *ne);
static void nodemgr_remove_ne(struct node_entry *ne);
static struct node_entry *find_entry_by_guid(u64 guid);
struct bus_type ieee1394_bus_type = {
.name = "ieee1394",
......@@ -385,27 +382,6 @@ static ssize_t fw_get_ignore_driver(struct device *dev, struct device_attribute
static DEVICE_ATTR(ignore_driver, S_IWUSR | S_IRUGO, fw_get_ignore_driver, fw_set_ignore_driver);
static ssize_t fw_set_destroy_node(struct bus_type *bus, const char *buf, size_t count)
{
struct node_entry *ne;
u64 guid = (u64)simple_strtoull(buf, NULL, 16);
ne = find_entry_by_guid(guid);
if (ne == NULL || !ne->in_limbo)
return -EINVAL;
nodemgr_remove_ne(ne);
return count;
}
static ssize_t fw_get_destroy_node(struct bus_type *bus, char *buf)
{
return sprintf(buf, "You can destroy in_limbo nodes by writing their GUID to this file\n");
}
static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node);
static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf,
size_t count)
{
......@@ -442,7 +418,6 @@ static BUS_ATTR(ignore_drivers, S_IWUSR | S_IRUGO, fw_get_ignore_drivers, fw_set
struct bus_attribute *const fw_bus_attrs[] = {
&bus_attr_destroy_node,
&bus_attr_rescan,
&bus_attr_ignore_drivers,
NULL
......@@ -734,10 +709,10 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
static DEFINE_MUTEX(nodemgr_serialize_remove_uds);
static int __match_ne(struct device *dev, void *data)
static int match_ne(struct device *dev, void *data)
{
struct unit_directory *ud;
struct node_entry *ne = (struct node_entry *)data;
struct node_entry *ne = data;
ud = container_of(dev, struct unit_directory, unit_dev);
return ud->ne == ne;
......@@ -754,8 +729,7 @@ static void nodemgr_remove_uds(struct node_entry *ne)
*/
mutex_lock(&nodemgr_serialize_remove_uds);
for (;;) {
dev = class_find_device(&nodemgr_ud_class, NULL, ne,
__match_ne);
dev = class_find_device(&nodemgr_ud_class, NULL, ne, match_ne);
if (!dev)
break;
ud = container_of(dev, struct unit_directory, unit_dev);
......@@ -785,7 +759,7 @@ static void nodemgr_remove_ne(struct node_entry *ne)
put_device(dev);
}
static int __nodemgr_remove_host_dev(struct device *dev, void *data)
static int remove_host_dev(struct device *dev, void *data)
{
if (dev->bus == &ieee1394_bus_type)
nodemgr_remove_ne(container_of(dev, struct node_entry,
......@@ -795,7 +769,7 @@ static int __nodemgr_remove_host_dev(struct device *dev, void *data)
static void nodemgr_remove_host_dev(struct device *dev)
{
WARN_ON(device_for_each_child(dev, NULL, __nodemgr_remove_host_dev));
device_for_each_child(dev, NULL, remove_host_dev);
sysfs_remove_link(&dev->kobj, "irm_id");
sysfs_remove_link(&dev->kobj, "busmgr_id");
sysfs_remove_link(&dev->kobj, "host_id");
......@@ -830,11 +804,10 @@ static void nodemgr_update_bus_options(struct node_entry *ne)
}
static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr *csr,
struct host_info *hi, nodeid_t nodeid,
unsigned int generation)
static struct node_entry *nodemgr_create_node(octlet_t guid,
struct csr1212_csr *csr, struct hpsb_host *host,
nodeid_t nodeid, unsigned int generation)
{
struct hpsb_host *host = hi->host;
struct node_entry *ne;
ne = kzalloc(sizeof(*ne), GFP_KERNEL);
......@@ -888,10 +861,10 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
return NULL;
}
static int __match_ne_guid(struct device *dev, void *data)
static int match_ne_guid(struct device *dev, void *data)
{
struct node_entry *ne;
u64 *guid = (u64 *)data;
u64 *guid = data;
ne = container_of(dev, struct node_entry, node_dev);
return ne->guid == *guid;
......@@ -902,8 +875,7 @@ static struct node_entry *find_entry_by_guid(u64 guid)
struct device *dev;
struct node_entry *ne;
dev = class_find_device(&nodemgr_ne_class, NULL, &guid,
__match_ne_guid);
dev = class_find_device(&nodemgr_ne_class, NULL, &guid, match_ne_guid);
if (!dev)
return NULL;
ne = container_of(dev, struct node_entry, node_dev);
......@@ -912,21 +884,21 @@ static struct node_entry *find_entry_by_guid(u64 guid)
return ne;
}
struct match_nodeid_param {
struct match_nodeid_parameter {
struct hpsb_host *host;
nodeid_t nodeid;
};
static int __match_ne_nodeid(struct device *dev, void *data)
static int match_ne_nodeid(struct device *dev, void *data)
{
int found = 0;
struct node_entry *ne;
struct match_nodeid_param *param = (struct match_nodeid_param *)data;
struct match_nodeid_parameter *p = data;
if (!dev)
goto ret;
ne = container_of(dev, struct node_entry, node_dev);
if (ne->host == param->host && ne->nodeid == param->nodeid)
if (ne->host == p->host && ne->nodeid == p->nodeid)
found = 1;
ret:
return found;
......@@ -937,13 +909,12 @@ static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
{
struct device *dev;
struct node_entry *ne;
struct match_nodeid_param param;
struct match_nodeid_parameter p;
param.host = host;
param.nodeid = nodeid;
p.host = host;
p.nodeid = nodeid;
dev = class_find_device(&nodemgr_ne_class, NULL, &param,
__match_ne_nodeid);
dev = class_find_device(&nodemgr_ne_class, NULL, &p, match_ne_nodeid);
if (!dev)
return NULL;
ne = container_of(dev, struct node_entry, node_dev);
......@@ -990,7 +961,7 @@ static void nodemgr_register_device(struct node_entry *ne,
* immediate unit directories looking for software_id and
* software_version entries, in order to get driver autoloading working. */
static struct unit_directory *nodemgr_process_unit_directory
(struct host_info *hi, struct node_entry *ne, struct csr1212_keyval *ud_kv,
(struct node_entry *ne, struct csr1212_keyval *ud_kv,
unsigned int *id, struct unit_directory *parent)
{
struct unit_directory *ud;
......@@ -1083,7 +1054,7 @@ static struct unit_directory *nodemgr_process_unit_directory
nodemgr_register_device(ne, ud, &ne->device);
/* process the child unit */
ud_child = nodemgr_process_unit_directory(hi, ne, kv, id, ud);
ud_child = nodemgr_process_unit_directory(ne, kv, id, ud);
if (ud_child == NULL)
break;
......@@ -1137,7 +1108,7 @@ static struct unit_directory *nodemgr_process_unit_directory
}
static void nodemgr_process_root_directory(struct host_info *hi, struct node_entry *ne)
static void nodemgr_process_root_directory(struct node_entry *ne)
{
unsigned int ud_id = 0;
struct csr1212_dentry *dentry;
......@@ -1157,7 +1128,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
break;
case CSR1212_KV_ID_UNIT:
nodemgr_process_unit_directory(hi, ne, kv, &ud_id, NULL);
nodemgr_process_unit_directory(ne, kv, &ud_id, NULL);
break;
case CSR1212_KV_ID_DESCRIPTOR:
......@@ -1273,8 +1244,7 @@ void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver)
* the to take whatever actions required.
*/
static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
struct host_info *hi, nodeid_t nodeid,
unsigned int generation)
nodeid_t nodeid, unsigned int generation)
{
if (ne->nodeid != nodeid) {
HPSB_DEBUG("Node changed: " NODE_BUS_FMT " -> " NODE_BUS_FMT,
......@@ -1305,19 +1275,23 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
csr1212_destroy_csr(csr);
}
if (ne->in_limbo)
nodemgr_resume_ne(ne);
/* Mark the node current */
ne->generation = generation;
}
if (ne->in_limbo) {
device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
ne->in_limbo = false;
HPSB_DEBUG("Node reactivated: "
"ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
NODE_BUS_ARGS(ne->host, ne->nodeid),
(unsigned long long)ne->guid);
}
}
static void nodemgr_node_scan_one(struct host_info *hi,
static void nodemgr_node_scan_one(struct hpsb_host *host,
nodeid_t nodeid, int generation)
{
struct hpsb_host *host = hi->host;
struct node_entry *ne;
octlet_t guid;
struct csr1212_csr *csr;
......@@ -1373,16 +1347,15 @@ static void nodemgr_node_scan_one(struct host_info *hi,
}
if (!ne)
nodemgr_create_node(guid, csr, hi, nodeid, generation);
nodemgr_create_node(guid, csr, host, nodeid, generation);
else
nodemgr_update_node(ne, csr, hi, nodeid, generation);
nodemgr_update_node(ne, csr, nodeid, generation);
}
static void nodemgr_node_scan(struct host_info *hi, int generation)
static void nodemgr_node_scan(struct hpsb_host *host, int generation)
{
int count;
struct hpsb_host *host = hi->host;
struct selfid *sid = (struct selfid *)host->topology_map;
nodeid_t nodeid = LOCAL_BUS;
......@@ -1395,89 +1368,26 @@ static void nodemgr_node_scan(struct host_info *hi, int generation)
nodeid++;
continue;
}
nodemgr_node_scan_one(hi, nodeid++, generation);
}
}
static int __nodemgr_driver_suspend(struct device *dev, void *data)
{
struct unit_directory *ud;
struct device_driver *drv;
struct node_entry *ne = (struct node_entry *)data;
int error;
ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne == ne) {
drv = get_driver(ud->device.driver);
if (drv) {
error = 1; /* release if suspend is not implemented */
if (drv->suspend) {
down(&ud->device.sem);
error = drv->suspend(&ud->device, PMSG_SUSPEND);
up(&ud->device.sem);
}
if (error)
device_release_driver(&ud->device);
put_driver(drv);
}
}
return 0;
}
static int __nodemgr_driver_resume(struct device *dev, void *data)
{
struct unit_directory *ud;
struct device_driver *drv;
struct node_entry *ne = (struct node_entry *)data;
ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne == ne) {
drv = get_driver(ud->device.driver);
if (drv) {
if (drv->resume) {
down(&ud->device.sem);
drv->resume(&ud->device);
up(&ud->device.sem);
}
put_driver(drv);
}
nodemgr_node_scan_one(host, nodeid++, generation);
}
return 0;
}
static void nodemgr_suspend_ne(struct node_entry *ne)
static void nodemgr_pause_ne(struct node_entry *ne)
{
HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
HPSB_DEBUG("Node paused: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
NODE_BUS_ARGS(ne->host, ne->nodeid),
(unsigned long long)ne->guid);
ne->in_limbo = 1;
ne->in_limbo = true;
WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
class_for_each_device(&nodemgr_ud_class, NULL, ne,
__nodemgr_driver_suspend);
}
static void nodemgr_resume_ne(struct node_entry *ne)
{
ne->in_limbo = 0;
device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
class_for_each_device(&nodemgr_ud_class, NULL, ne,
__nodemgr_driver_resume);
HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
}
static int __nodemgr_update_pdrv(struct device *dev, void *data)
static int update_pdrv(struct device *dev, void *data)
{
struct unit_directory *ud;
struct device_driver *drv;
struct hpsb_protocol_driver *pdrv;
struct node_entry *ne = (struct node_entry *)data;
struct node_entry *ne = data;
int error;
ud = container_of(dev, struct unit_directory, unit_dev);
......@@ -1503,11 +1413,9 @@ static int __nodemgr_update_pdrv(struct device *dev, void *data)
static void nodemgr_update_pdrv(struct node_entry *ne)
{
class_for_each_device(&nodemgr_ud_class, NULL, ne,
__nodemgr_update_pdrv);
class_for_each_device(&nodemgr_ud_class, NULL, ne, update_pdrv);
}
/* Write the BROADCAST_CHANNEL as per IEEE1394a 8.3.2.3.11 and 8.4.2.3. This
* seems like an optional service but in the end it is practically mandatory
* as a consequence of these clauses.
......@@ -1535,11 +1443,12 @@ static void nodemgr_irm_write_bc(struct node_entry *ne, int generation)
}
static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation)
static void nodemgr_probe_ne(struct hpsb_host *host, struct node_entry *ne,
int generation)
{
struct device *dev;
if (ne->host != hi->host || ne->in_limbo)
if (ne->host != host || ne->in_limbo)
return;
dev = get_device(&ne->device);
......@@ -1554,40 +1463,40 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
* down to the drivers. Otherwise, this is a dead node and we
* suspend it. */
if (ne->needs_probe)
nodemgr_process_root_directory(hi, ne);
nodemgr_process_root_directory(ne);
else if (ne->generation == generation)
nodemgr_update_pdrv(ne);
else
nodemgr_suspend_ne(ne);
nodemgr_pause_ne(ne);
put_device(dev);
}
struct probe_param {
struct host_info *hi;
struct node_probe_parameter {
struct hpsb_host *host;
int generation;
bool probe_now;
};
static int node_probe(struct device *dev, void *data)
{
struct probe_param *p = data;
struct node_probe_parameter *p = data;
struct node_entry *ne;
if (p->generation != get_hpsb_generation(p->hi->host))
if (p->generation != get_hpsb_generation(p->host))
return -EAGAIN;
ne = container_of(dev, struct node_entry, node_dev);
if (ne->needs_probe == p->probe_now)
nodemgr_probe_ne(p->hi, ne, p->generation);
nodemgr_probe_ne(p->host, ne, p->generation);
return 0;
}
static void nodemgr_node_probe(struct host_info *hi, int generation)
static int nodemgr_node_probe(struct hpsb_host *host, int generation)
{
struct probe_param p;
struct node_probe_parameter p;
p.hi = hi;
p.host = host;
p.generation = generation;
/*
* Do some processing of the nodes we've probed. This pulls them
......@@ -1604,11 +1513,11 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
*/
p.probe_now = false;
if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
return;
return 0;
p.probe_now = true;
if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
return;
return 0;
/*
* Now let's tell the bus to rescan our devices. This may seem
* like overhead, but the driver-model core will only scan a
......@@ -1620,6 +1529,27 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
*/
if (bus_rescan_devices(&ieee1394_bus_type) != 0)
HPSB_DEBUG("bus_rescan_devices had an error");
return 1;
}
static int remove_nodes_in_limbo(struct device *dev, void *data)
{
struct node_entry *ne;
if (dev->bus != &ieee1394_bus_type)
return 0;
ne = container_of(dev, struct node_entry, device);
if (ne->in_limbo)
nodemgr_remove_ne(ne);
return 0;
}
static void nodemgr_remove_nodes_in_limbo(struct hpsb_host *host)
{
device_for_each_child(&host->device, NULL, remove_nodes_in_limbo);
}
static int nodemgr_send_resume_packet(struct hpsb_host *host)
......@@ -1730,10 +1660,9 @@ static int nodemgr_check_irm_capability(struct hpsb_host *host, int cycles)
return 1;
}
static int nodemgr_host_thread(void *__hi)
static int nodemgr_host_thread(void *data)
{
struct host_info *hi = (struct host_info *)__hi;
struct hpsb_host *host = hi->host;
struct hpsb_host *host = data;
unsigned int g, generation = 0;
int i, reset_cycles = 0;
......@@ -1787,36 +1716,48 @@ static int nodemgr_host_thread(void *__hi)
* entries. This does not do the sysfs stuff, since that
* would trigger uevents and such, which is a bad idea at
* this point. */
nodemgr_node_scan(hi, generation);
nodemgr_node_scan(host, generation);
/* This actually does the full probe, with sysfs
* registration. */
nodemgr_node_probe(hi, generation);
if (!nodemgr_node_probe(host, generation))
continue;
/* Update some of our sysfs symlinks */
nodemgr_update_host_dev_links(host);
/* Sleep 3 seconds */
for (i = 3000/200; i; i--) {
msleep_interruptible(200);
if (kthread_should_stop())
goto exit;
if (generation != get_hpsb_generation(host))
break;
}
/* Remove nodes which are gone, unless a bus reset happened */
if (!i)
nodemgr_remove_nodes_in_limbo(host);
}
exit:
HPSB_VERBOSE("NodeMgr: Exiting thread");
return 0;
}
struct host_iter_param {
struct per_host_parameter {
void *data;
int (*cb)(struct hpsb_host *, void *);
};
static int __nodemgr_for_each_host(struct device *dev, void *data)
static int per_host(struct device *dev, void *data)
{
struct hpsb_host *host;
struct host_iter_param *hip = (struct host_iter_param *)data;
int error = 0;
struct per_host_parameter *p = data;
host = container_of(dev, struct hpsb_host, host_dev);
error = hip->cb(host, hip->data);
return error;
return p->cb(host, p->data);
}
/**
* nodemgr_for_each_host - call a function for each IEEE 1394 host
* @data: an address to supply to the callback
......@@ -1831,15 +1772,11 @@ static int __nodemgr_for_each_host(struct device *dev, void *data)
*/
int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
{
struct host_iter_param hip;
int error;
hip.cb = cb;
hip.data = data;
error = class_for_each_device(&hpsb_host_class, NULL, &hip,
__nodemgr_for_each_host);
struct per_host_parameter p;
return error;
p.cb = cb;
p.data = data;
return class_for_each_device(&hpsb_host_class, NULL, &p, per_host);
}
/* The following two convenience functions use a struct node_entry
......@@ -1893,7 +1830,7 @@ static void nodemgr_add_host(struct hpsb_host *host)
return;
}
hi->host = host;
hi->thread = kthread_run(nodemgr_host_thread, hi, "knodemgrd_%d",
hi->thread = kthread_run(nodemgr_host_thread, host, "knodemgrd_%d",
host->id);
if (IS_ERR(hi->thread)) {
HPSB_ERR("NodeMgr: cannot start thread for host %d", host->id);
......
......@@ -110,7 +110,7 @@ struct node_entry {
struct device node_dev;
/* Means this node is not attached anymore */
int in_limbo;
bool in_limbo;
struct csr1212_csr *csr;
};
......
......@@ -22,6 +22,7 @@ enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0,
struct file_info {
struct list_head list;
struct mutex state_mutex;
enum { opened, initialized, connected } state;
unsigned int protocol_version;
......
......@@ -34,6 +34,7 @@
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
......@@ -2267,6 +2268,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
return -EFAULT;
}
mutex_lock(&fi->state_mutex);
switch (fi->state) {
case opened:
retval = state_opened(fi, req);
......@@ -2281,6 +2284,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
break;
}
mutex_unlock(&fi->state_mutex);
if (retval < 0) {
free_pending_request(req);
} else {
......@@ -2541,59 +2546,60 @@ 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)
{
struct file_info *fi = file->private_data;
int ret;
mutex_lock(&fi->state_mutex);
if (fi->iso_state == RAW1394_ISO_INACTIVE)
return -EINVAL;
ret = -EINVAL;
else
ret = dma_region_mmap(&fi->iso_handle->data_buf, file, vma);
return dma_region_mmap(&fi->iso_handle->data_buf, file, vma);
mutex_unlock(&fi->state_mutex);
return ret;
}
/* ioctl is only used for rawiso operations */
static long do_raw1394_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
static long raw1394_ioctl_inactive(struct file_info *fi, unsigned int cmd,
void __user *argp)
{
struct file_info *fi = file->private_data;
void __user *argp = (void __user *)arg;
switch (fi->iso_state) {
case RAW1394_ISO_INACTIVE:
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:
break;
return -EINVAL;
}
break;
case RAW1394_ISO_RECV:
}
static long raw1394_ioctl_recv(struct file_info *fi, unsigned int cmd,
unsigned long arg)
{
void __user *argp = (void __user *)arg;
switch (cmd) {
case RAW1394_IOC_ISO_RECV_START:{
/* copy args from user-space */
int args[3];
if (copy_from_user
(&args[0], argp, sizeof(args)))
if (copy_from_user(&args[0], argp, sizeof(args)))
return -EFAULT;
return hpsb_iso_recv_start(fi->iso_handle,
args[0], args[1],
args[2]);
args[0], args[1], args[2]);
}
case RAW1394_IOC_ISO_XMIT_RECV_STOP:
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);
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);
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,
return hpsb_iso_recv_set_channel_mask(fi->iso_handle,
mask);
}
case RAW1394_IOC_ISO_GET_STATUS:
......@@ -2601,8 +2607,7 @@ static long do_raw1394_ioctl(struct file *file, unsigned int cmd,
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);
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:
......@@ -2611,15 +2616,19 @@ static long do_raw1394_ioctl(struct file *file, unsigned int cmd,
case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
queue_rawiso_event(fi);
return 0;
default:
return -EINVAL;
}
break;
case RAW1394_ISO_XMIT:
}
static long raw1394_ioctl_xmit(struct file_info *fi, unsigned int cmd,
void __user *argp)
{
switch (cmd) {
case RAW1394_IOC_ISO_XMIT_START:{
/* copy two ints from user-space */
int args[2];
if (copy_from_user
(&args[0], argp, sizeof(args)))
if (copy_from_user(&args[0], argp, sizeof(args)))
return -EFAULT;
return hpsb_iso_xmit_start(fi->iso_handle,
args[0], args[1]);
......@@ -2639,11 +2648,18 @@ static long do_raw1394_ioctl(struct file *file, unsigned int cmd,
case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
queue_rawiso_event(fi);
return 0;
}
break;
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 */
switch(cmd) {
......@@ -2653,16 +2669,25 @@ static long do_raw1394_ioctl(struct file *file, unsigned int cmd,
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;
}
......@@ -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)) {
infos = compat_ptr(infos32);
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;
}
......@@ -2724,7 +2749,6 @@ static long raw1394_compat_ioctl(struct file *file,
void __user *argp = (void __user *)arg;
long err;
lock_kernel();
switch (cmd) {
/* These requests have same format as long as 'int' has same size. */
case RAW1394_IOC_ISO_RECV_INIT:
......@@ -2741,7 +2765,7 @@ static long raw1394_compat_ioctl(struct file *file,
case RAW1394_IOC_ISO_GET_STATUS:
case RAW1394_IOC_ISO_SHUTDOWN:
case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
err = do_raw1394_ioctl(file, cmd, arg);
err = raw1394_ioctl(file, cmd, arg);
break;
/* These request have different format. */
case RAW1394_IOC_ISO_RECV_PACKETS32:
......@@ -2757,7 +2781,6 @@ static long raw1394_compat_ioctl(struct file *file,
err = -EINVAL;
break;
}
unlock_kernel();
return err;
}
......@@ -2791,6 +2814,7 @@ static int raw1394_open(struct inode *inode, struct file *file)
fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */
INIT_LIST_HEAD(&fi->list);
mutex_init(&fi->state_mutex);
fi->state = opened;
INIT_LIST_HEAD(&fi->req_pending);
INIT_LIST_HEAD(&fi->req_complete);
......
......@@ -526,26 +526,41 @@ static void sbp2util_write_doorbell(struct work_struct *work)
static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
{
struct sbp2_fwhost_info *hi = lu->hi;
struct sbp2_command_info *cmd;
struct device *dmadev = lu->hi->host->device.parent;
int i, orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS;
for (i = 0; i < orbs; i++) {
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
cmd->command_orb_dma = dma_map_single(hi->host->device.parent,
&cmd->command_orb,
goto failed_alloc;
cmd->command_orb_dma =
dma_map_single(dmadev, &cmd->command_orb,
sizeof(struct sbp2_command_orb),
DMA_TO_DEVICE);
cmd->sge_dma = dma_map_single(hi->host->device.parent,
&cmd->scatter_gather_element,
if (dma_mapping_error(dmadev, cmd->command_orb_dma))
goto failed_orb;
cmd->sge_dma =
dma_map_single(dmadev, &cmd->scatter_gather_element,
sizeof(cmd->scatter_gather_element),
DMA_TO_DEVICE);
if (dma_mapping_error(dmadev, cmd->sge_dma))
goto failed_sge;
INIT_LIST_HEAD(&cmd->list);
list_add_tail(&cmd->list, &lu->cmd_orb_completed);
}
return 0;
failed_sge:
dma_unmap_single(dmadev, cmd->command_orb_dma,
sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
failed_orb:
kfree(cmd);
failed_alloc:
return -ENOMEM;
}
static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu,
......@@ -641,24 +656,11 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
static void sbp2util_mark_command_completed(struct sbp2_lu *lu,
struct sbp2_command_info *cmd)
{
struct hpsb_host *host = lu->ud->ne->host;
if (cmd->cmd_dma) {
if (cmd->dma_type == CMD_DMA_SINGLE)
dma_unmap_single(host->device.parent, cmd->cmd_dma,
cmd->dma_size, cmd->dma_dir);
else if (cmd->dma_type == CMD_DMA_PAGE)
dma_unmap_page(host->device.parent, cmd->cmd_dma,
cmd->dma_size, cmd->dma_dir);
/* XXX: Check for CMD_DMA_NONE bug */
cmd->dma_type = CMD_DMA_NONE;
cmd->cmd_dma = 0;
}
if (cmd->sge_buffer) {
dma_unmap_sg(host->device.parent, cmd->sge_buffer,
cmd->dma_size, cmd->dma_dir);
cmd->sge_buffer = NULL;
}
if (scsi_sg_count(cmd->Current_SCpnt))
dma_unmap_sg(lu->ud->ne->host->device.parent,
scsi_sglist(cmd->Current_SCpnt),
scsi_sg_count(cmd->Current_SCpnt),
cmd->Current_SCpnt->sc_data_direction);
list_move_tail(&cmd->list, &lu->cmd_orb_completed);
}
......@@ -823,6 +825,10 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud)
#endif
}
if (dma_get_max_seg_size(hi->host->device.parent) > SBP2_MAX_SEG_SIZE)
BUG_ON(dma_set_max_seg_size(hi->host->device.parent,
SBP2_MAX_SEG_SIZE));
/* Prevent unloading of the 1394 host */
if (!try_module_get(hi->host->driver->owner)) {
SBP2_ERR("failed to get a reference on 1394 host driver");
......@@ -1494,84 +1500,65 @@ static int sbp2_agent_reset(struct sbp2_lu *lu, int wait)
return 0;
}
static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
static int sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
struct sbp2_fwhost_info *hi,
struct sbp2_command_info *cmd,
unsigned int scsi_use_sg,
unsigned int sg_count,
struct scatterlist *sg,
u32 orb_direction,
enum dma_data_direction dma_dir)
{
cmd->dma_dir = dma_dir;
struct device *dmadev = hi->host->device.parent;
struct sbp2_unrestricted_page_table *pt;
int i, n;
n = dma_map_sg(dmadev, sg, sg_count, dma_dir);
if (n == 0)
return -ENOMEM;
orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
orb->misc |= ORB_SET_DIRECTION(orb_direction);
/* special case if only one element (and less than 64KB in size) */
if (scsi_use_sg == 1 && sg->length <= SBP2_MAX_SG_ELEMENT_LENGTH) {
cmd->dma_size = sg->length;
cmd->dma_type = CMD_DMA_PAGE;
cmd->cmd_dma = dma_map_page(hi->host->device.parent,
sg_page(sg), sg->offset,
cmd->dma_size, cmd->dma_dir);
orb->data_descriptor_lo = cmd->cmd_dma;
orb->misc |= ORB_SET_DATA_SIZE(cmd->dma_size);
if (n == 1) {
orb->misc |= ORB_SET_DATA_SIZE(sg_dma_len(sg));
orb->data_descriptor_lo = sg_dma_address(sg);
} else {
struct sbp2_unrestricted_page_table *sg_element =
&cmd->scatter_gather_element[0];
u32 sg_count, sg_len;
dma_addr_t sg_addr;
int i, count = dma_map_sg(hi->host->device.parent, sg,
scsi_use_sg, dma_dir);
cmd->dma_size = scsi_use_sg;
cmd->sge_buffer = sg;
/* use page tables (s/g) */
orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
orb->data_descriptor_lo = cmd->sge_dma;
pt = &cmd->scatter_gather_element[0];
/* loop through and fill out our SBP-2 page tables
* (and split up anything too large) */
for (i = 0, sg_count = 0; i < count; i++, sg = sg_next(sg)) {
sg_len = sg_dma_len(sg);
sg_addr = sg_dma_address(sg);
while (sg_len) {
sg_element[sg_count].segment_base_lo = sg_addr;
if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
sg_element[sg_count].length_segment_base_hi =
PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
} else {
sg_element[sg_count].length_segment_base_hi =
PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
sg_len = 0;
}
sg_count++;
}
dma_sync_single_for_cpu(dmadev, cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_TO_DEVICE);
for_each_sg(sg, sg, n, i) {
pt[i].high = cpu_to_be32(sg_dma_len(sg) << 16);
pt[i].low = cpu_to_be32(sg_dma_address(sg));
}
orb->misc |= ORB_SET_DATA_SIZE(sg_count);
orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1) |
ORB_SET_DATA_SIZE(n);
orb->data_descriptor_lo = cmd->sge_dma;
sbp2util_cpu_to_be32_buffer(sg_element,
(sizeof(struct sbp2_unrestricted_page_table)) *
sg_count);
dma_sync_single_for_device(dmadev, cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_TO_DEVICE);
}
return 0;
}
static void sbp2_create_command_orb(struct sbp2_lu *lu,
static int sbp2_create_command_orb(struct sbp2_lu *lu,
struct sbp2_command_info *cmd,
struct scsi_cmnd *SCpnt)
{
struct sbp2_fwhost_info *hi = lu->hi;
struct device *dmadev = lu->hi->host->device.parent;
struct sbp2_command_orb *orb = &cmd->command_orb;
u32 orb_direction;
unsigned int scsi_request_bufflen = scsi_bufflen(SCpnt);
enum dma_data_direction dma_dir = SCpnt->sc_data_direction;
u32 orb_direction;
int ret;
dma_sync_single_for_cpu(dmadev, cmd->command_orb_dma,
sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
/*
* Set-up our command ORB.
*
......@@ -1602,15 +1589,21 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu,
orb->data_descriptor_hi = 0x0;
orb->data_descriptor_lo = 0x0;
orb->misc |= ORB_SET_DIRECTION(1);
} else
sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_sg_count(SCpnt),
ret = 0;
} else {
ret = sbp2_prep_command_orb_sg(orb, lu->hi, cmd,
scsi_sg_count(SCpnt),
scsi_sglist(SCpnt),
orb_direction, dma_dir);
}
sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
memset(orb->cdb, 0, sizeof(orb->cdb));
memcpy(orb->cdb, SCpnt->cmnd, SCpnt->cmd_len);
dma_sync_single_for_device(dmadev, cmd->command_orb_dma,
sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
return ret;
}
static void sbp2_link_orb_command(struct sbp2_lu *lu,
......@@ -1624,14 +1617,6 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu,
size_t length;
unsigned long flags;
dma_sync_single_for_device(hi->host->device.parent,
cmd->command_orb_dma,
sizeof(struct sbp2_command_orb),
DMA_TO_DEVICE);
dma_sync_single_for_device(hi->host->device.parent, cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_TO_DEVICE);
/* check to see if there are any previous orbs to use */
spin_lock_irqsave(&lu->cmd_orb_lock, flags);
last_orb = lu->last_orb;
......@@ -1699,9 +1684,10 @@ static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt,
if (!cmd)
return -EIO;
sbp2_create_command_orb(lu, cmd, SCpnt);
sbp2_link_orb_command(lu, cmd);
if (sbp2_create_command_orb(lu, cmd, SCpnt))
return -ENOMEM;
sbp2_link_orb_command(lu, cmd);
return 0;
}
......@@ -1789,13 +1775,6 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
else
cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo);
if (cmd) {
dma_sync_single_for_cpu(hi->host->device.parent,
cmd->command_orb_dma,
sizeof(struct sbp2_command_orb),
DMA_TO_DEVICE);
dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_TO_DEVICE);
/* Grab SCSI command pointers and check status. */
/*
* FIXME: If the src field in the status is 1, the ORB DMA must
......@@ -1912,7 +1891,6 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status)
{
struct sbp2_fwhost_info *hi = lu->hi;
struct list_head *lh;
struct sbp2_command_info *cmd;
unsigned long flags;
......@@ -1921,13 +1899,6 @@ static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status)
while (!list_empty(&lu->cmd_orb_inuse)) {
lh = lu->cmd_orb_inuse.next;
cmd = list_entry(lh, struct sbp2_command_info, list);
dma_sync_single_for_cpu(hi->host->device.parent,
cmd->command_orb_dma,
sizeof(struct sbp2_command_orb),
DMA_TO_DEVICE);
dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_TO_DEVICE);
sbp2util_mark_command_completed(lu, cmd);
if (cmd->Current_SCpnt) {
cmd->Current_SCpnt->result = status << 16;
......@@ -2033,6 +2004,8 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev)
sdev->start_stop_pwr_cond = 1;
if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE);
return 0;
}
......@@ -2049,7 +2022,6 @@ static void sbp2scsi_slave_destroy(struct scsi_device *sdev)
static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
{
struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];
struct sbp2_fwhost_info *hi = lu->hi;
struct sbp2_command_info *cmd;
unsigned long flags;
......@@ -2063,14 +2035,6 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
spin_lock_irqsave(&lu->cmd_orb_lock, flags);
cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt);
if (cmd) {
dma_sync_single_for_cpu(hi->host->device.parent,
cmd->command_orb_dma,
sizeof(struct sbp2_command_orb),
DMA_TO_DEVICE);
dma_sync_single_for_cpu(hi->host->device.parent,
cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_TO_DEVICE);
sbp2util_mark_command_completed(lu, cmd);
if (cmd->Current_SCpnt) {
cmd->Current_SCpnt->result = DID_ABORT << 16;
......
......@@ -139,13 +139,10 @@ struct sbp2_logout_orb {
u32 status_fifo_lo;
} __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 {
u32 length_segment_base_hi;
u32 segment_base_lo;
} __attribute__((packed));
__be32 high;
__be32 low;
};
#define RESP_STATUS_REQUEST_COMPLETE 0x0
#define RESP_STATUS_TRANSPORT_FAILURE 0x1
......@@ -216,15 +213,18 @@ struct sbp2_status_block {
#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e
#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
* implementation detail of the sbp2 driver. */
* implementation detail of the sbp2 driver.
*/
#define SBP2_MAX_CMDS 8
#define SBP2_SCSI_STATUS_GOOD 0x0
......@@ -240,12 +240,6 @@ struct sbp2_status_block {
* Representations of commands and devices
*/
enum sbp2_dma_types {
CMD_DMA_NONE,
CMD_DMA_PAGE,
CMD_DMA_SINGLE
};
/* Per SCSI command */
struct sbp2_command_info {
struct list_head list;
......@@ -258,11 +252,6 @@ struct sbp2_command_info {
struct sbp2_unrestricted_page_table
scatter_gather_element[SG_ALL] __attribute__((aligned(8)));
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 */
......
......@@ -893,7 +893,7 @@ static long video1394_ioctl(struct file *file,
if (unlikely(d == NULL))
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,
"Buffer %d out of range",v.buffer);
return -EINVAL;
......@@ -959,7 +959,7 @@ static long video1394_ioctl(struct file *file,
if (unlikely(d == NULL))
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,
"Buffer %d out of range",v.buffer);
return -EINVAL;
......@@ -1030,7 +1030,7 @@ static long video1394_ioctl(struct file *file,
d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
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,
"Buffer %d out of range",v.buffer);
return -EINVAL;
......@@ -1137,7 +1137,7 @@ static long video1394_ioctl(struct file *file,
d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
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,
"Buffer %d out of range",v.buffer);
return -EINVAL;
......
......@@ -154,8 +154,13 @@ struct fw_cdev_event_iso_interrupt {
* @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST
* @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT
*
* Convenience union for userspace use. Events could be read(2) into a char
* buffer and then cast to this union for further processing.
* Convenience union for userspace use. Events could be read(2) into an
* 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 {
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