patch-2.3.99-pre3 linux/drivers/ieee1394/raw1394.c
Next file: linux/drivers/ieee1394/raw1394.h
Previous file: linux/drivers/ieee1394/pcilynx.h
Back to the patch index
Back to the overall index
- Lines: 286
- Date:
Wed Mar 22 00:02:49 2000
- Orig file:
v2.3.99-pre2/linux/drivers/ieee1394/raw1394.c
- Orig date:
Sun Feb 20 21:12:39 2000
diff -u --recursive --new-file v2.3.99-pre2/linux/drivers/ieee1394/raw1394.c linux/drivers/ieee1394/raw1394.c
@@ -59,7 +59,7 @@
{
if (req->ibs) {
if (atomic_dec_and_test(&req->ibs->refcount)) {
- atomic_sub((req->data[0] >> 16) + 4, &iso_buffer_size);
+ atomic_sub(req->ibs->data_size, &iso_buffer_size);
kfree(req->ibs);
}
} else if (req->free_data) {
@@ -109,6 +109,7 @@
}
free_tlabel(packet->host, packet->node_id, packet->tlabel);
+
queue_complete_req(req);
}
@@ -215,6 +216,7 @@
LIST_HEAD(reqs);
if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
+ HPSB_INFO("dropped iso packet");
return;
}
@@ -230,22 +232,23 @@
continue;
}
+ req = __alloc_pending_request(SLAB_ATOMIC);
+ if (!req) break;
+
if (!ibs) {
ibs = kmalloc(sizeof(struct iso_block_store)
+ length, SLAB_ATOMIC);
- if (!ibs) break;
+ if (!ibs) {
+ kfree(req);
+ break;
+ }
atomic_add(length, &iso_buffer_size);
atomic_set(&ibs->refcount, 0);
+ ibs->data_size = length;
memcpy(ibs->data, data, length);
}
- req = __alloc_pending_request(SLAB_ATOMIC);
- if (!req) {
- kfree(ibs);
- break;
- }
-
atomic_inc(&ibs->refcount);
req->file_info = fi;
@@ -270,6 +273,75 @@
}
}
+static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
+ int cts, u8 *data, unsigned int length)
+{
+ unsigned long flags;
+ struct list_head *lh;
+ struct host_info *hi;
+ struct file_info *fi;
+ struct pending_request *req;
+ struct iso_block_store *ibs = NULL;
+ LIST_HEAD(reqs);
+
+ if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
+ HPSB_INFO("dropped fcp request");
+ return;
+ }
+
+ spin_lock_irqsave(&host_info_lock, flags);
+ hi = find_host_info(host);
+
+ if (hi != NULL) {
+ for (lh = hi->file_info_list.next; lh != &hi->file_info_list;
+ lh = lh->next) {
+ fi = list_entry(lh, struct file_info, list);
+
+ if (!fi->fcp_buffer) {
+ continue;
+ }
+
+ req = __alloc_pending_request(SLAB_ATOMIC);
+ if (!req) break;
+
+ if (!ibs) {
+ ibs = kmalloc(sizeof(struct iso_block_store)
+ + length, SLAB_ATOMIC);
+ if (!ibs) {
+ kfree(req);
+ break;
+ }
+
+ atomic_add(length, &iso_buffer_size);
+ atomic_set(&ibs->refcount, 0);
+ ibs->data_size = length;
+ memcpy(ibs->data, data, length);
+ }
+
+ atomic_inc(&ibs->refcount);
+
+ req->file_info = fi;
+ req->ibs = ibs;
+ req->data = ibs->data;
+ req->req.type = RAW1394_REQ_FCP_REQUEST;
+ req->req.generation = get_hpsb_generation();
+ req->req.misc = nodeid | (direction << 16);
+ req->req.recvb = (quadlet_t *)fi->fcp_buffer;
+ req->req.length = length;
+
+ list_add_tail(&req->list, &reqs);
+ }
+ }
+ spin_unlock_irqrestore(&host_info_lock, flags);
+
+ lh = reqs.next;
+ while (lh != &reqs) {
+ req = list_entry(lh, struct pending_request, list);
+ lh = lh->next;
+ queue_complete_req(req);
+ }
+}
+
static int dev_read(struct file *file, char *buffer, size_t count,
loff_t *offset_is_ignored)
@@ -455,8 +527,28 @@
spin_unlock(&host_info_lock);
}
+static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
+{
+ if (req->req.misc) {
+ if (fi->fcp_buffer) {
+ req->req.error = RAW1394_ERROR_ALREADY;
+ } else {
+ fi->fcp_buffer = (u8 *)req->req.recvb;
+ }
+ } else {
+ if (!fi->fcp_buffer) {
+ req->req.error = RAW1394_ERROR_ALREADY;
+ } else {
+ fi->fcp_buffer = NULL;
+ }
+ }
+
+ req->req.length = 0;
+ queue_complete_req(req);
+}
+
static int handle_local_request(struct file_info *fi,
- struct pending_request *req)
+ struct pending_request *req, int node)
{
u64 addr = req->req.address & 0xffffffffffffULL;
@@ -466,7 +558,7 @@
switch (req->req.type) {
case RAW1394_REQ_ASYNC_READ:
- req->req.error = highlevel_read(fi->host, req->data, addr,
+ req->req.error = highlevel_read(fi->host, node, req->data, addr,
req->req.length);
break;
@@ -477,8 +569,8 @@
break;
}
- req->req.error = highlevel_write(fi->host, req->data, addr,
- req->req.length);
+ req->req.error = highlevel_write(fi->host, node, req->data,
+ addr, req->req.length);
req->req.length = 0;
break;
@@ -503,14 +595,16 @@
}
if (req->req.length == 8) {
- req->req.error = highlevel_lock(fi->host, req->data,
- addr, req->data[1],
+ req->req.error = highlevel_lock(fi->host, node,
+ req->data, addr,
+ req->data[1],
req->data[0],
req->req.misc);
req->req.length = 4;
} else {
- req->req.error = highlevel_lock(fi->host, req->data,
- addr, req->data[0], 0,
+ req->req.error = highlevel_lock(fi->host, node,
+ req->data, addr,
+ req->data[0], 0,
req->req.misc);
}
break;
@@ -539,28 +633,27 @@
if (!packet) return -ENOMEM;
req->data = &packet->header[3];
- } else if ((req->req.length % 4) == 0) {
+ } else {
packet = hpsb_make_readbpacket(fi->host, node, addr,
req->req.length);
if (!packet) return -ENOMEM;
req->data = packet->data;
- } else {
- req->req.error = RAW1394_ERROR_UNTIDY_LEN;
}
break;
case RAW1394_REQ_ASYNC_WRITE:
if (req->req.length == 4) {
- packet = hpsb_make_writeqpacket(fi->host, node, addr,
- 0);
- if (!packet) return -ENOMEM;
+ quadlet_t x;
- if (copy_from_user(&packet->header[3], req->req.sendb,
- 4)) {
+ if (copy_from_user(&x, req->req.sendb, 4)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
}
- } else if ((req->req.length % 4) == 0) {
+
+ packet = hpsb_make_writeqpacket(fi->host, node, addr,
+ x);
+ if (!packet) return -ENOMEM;
+ } else {
packet = hpsb_make_writebpacket(fi->host, node, addr,
req->req.length);
if (!packet) return -ENOMEM;
@@ -569,8 +662,6 @@
req->req.length)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
}
- } else {
- req->req.error = RAW1394_ERROR_UNTIDY_LEN;
}
req->req.length = 0;
break;
@@ -649,6 +740,11 @@
return sizeof(struct raw1394_request);
}
+ if (req->req.type == RAW1394_REQ_FCP_LISTEN) {
+ handle_fcp_listen(fi, req);
+ return sizeof(struct raw1394_request);
+ }
+
if (req->req.length == 0) {
req->req.error = RAW1394_ERROR_INVALID_ARG;
queue_complete_req(req);
@@ -656,7 +752,7 @@
}
if (fi->host->node_id == node) {
- return handle_local_request(fi, req);
+ return handle_local_request(fi, req, node);
}
return handle_remote_request(fi, req, node);
@@ -806,10 +902,11 @@
}
static struct hpsb_highlevel_ops hl_ops = {
- add_host,
- remove_host,
- host_reset,
- iso_receive
+ add_host: add_host,
+ remove_host: remove_host,
+ host_reset: host_reset,
+ iso_receive: iso_receive,
+ fcp_request: fcp_request,
};
static struct file_operations file_ops = {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)