Commit 09d714d5 authored by Ben Collins's avatar Ben Collins

IEEE1394(r1165): Better pending packet handling, patch from Steve.

parent a33161f5
...@@ -141,13 +141,12 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size) ...@@ -141,13 +141,12 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
packet->data_size = data_size; packet->data_size = data_size;
} }
INIT_LIST_HEAD(&packet->list); INIT_LIST_HEAD(&packet->list);
packet->complete_routine = NULL; packet->state = hpsb_unused;
packet->complete_data = NULL; packet->generation = -1;
packet->state = hpsb_unused; atomic_set(&packet->refcnt, 1);
packet->generation = -1;
return packet; return packet;
} }
...@@ -160,10 +159,10 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size) ...@@ -160,10 +159,10 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
*/ */
void hpsb_free_packet(struct hpsb_packet *packet) void hpsb_free_packet(struct hpsb_packet *packet)
{ {
if (!packet) return; if (packet && atomic_dec_and_test(&packet->refcnt)) {
kfree(packet->data);
kfree(packet->data); kmem_cache_free(hpsb_packet_cache, packet);
kmem_cache_free(hpsb_packet_cache, packet); }
} }
...@@ -402,28 +401,30 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot) ...@@ -402,28 +401,30 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet, void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
int ackcode) int ackcode)
{ {
unsigned long flags; packet->ack_code = ackcode;
packet->ack_code = ackcode; if (packet->no_waiter) {
/* must not have a tlabel allocated */
if (packet->no_waiter) { hpsb_free_packet(packet);
/* must not have a tlabel allocated */ return;
hpsb_free_packet(packet); }
return;
}
if (ackcode != ACK_PENDING || !packet->expect_response) { if (ackcode != ACK_PENDING || !packet->expect_response) {
packet->state = hpsb_complete; atomic_dec(&packet->refcnt);
queue_packet_complete(packet); list_del(&packet->list);
return; packet->state = hpsb_complete;
} queue_packet_complete(packet);
return;
}
packet->state = hpsb_pending; if (packet->state == hpsb_complete) {
packet->sendtime = jiffies; hpsb_free_packet(packet);
return;
}
spin_lock_irqsave(&host->pending_pkt_lock, flags); atomic_dec(&packet->refcnt);
list_add_tail(&packet->list, &host->pending_packets); packet->state = hpsb_pending;
spin_unlock_irqrestore(&host->pending_pkt_lock, flags); packet->sendtime = jiffies;
mod_timer(&host->timeout, jiffies + host->timeout_interval); mod_timer(&host->timeout, jiffies + host->timeout_interval);
} }
...@@ -492,7 +493,7 @@ int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt) ...@@ -492,7 +493,7 @@ int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt)
*/ */
int hpsb_send_packet(struct hpsb_packet *packet) int hpsb_send_packet(struct hpsb_packet *packet)
{ {
struct hpsb_host *host = packet->host; struct hpsb_host *host = packet->host;
if (host->is_shutdown) if (host->is_shutdown)
return -EINVAL; return -EINVAL;
...@@ -502,6 +503,15 @@ int hpsb_send_packet(struct hpsb_packet *packet) ...@@ -502,6 +503,15 @@ int hpsb_send_packet(struct hpsb_packet *packet)
packet->state = hpsb_queued; packet->state = hpsb_queued;
if (!packet->no_waiter || packet->expect_response) {
unsigned long flags;
atomic_inc(&packet->refcnt);
spin_lock_irqsave(&host->pending_pkt_lock, flags);
list_add_tail(&packet->list, &host->pending_packets);
spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
}
if (packet->node_id == host->node_id) if (packet->node_id == host->node_id)
{ /* it is a local request, so handle it locally */ { /* it is a local request, so handle it locally */
quadlet_t *data; quadlet_t *data;
...@@ -658,7 +668,12 @@ void handle_packet_response(struct hpsb_host *host, int tcode, quadlet_t *data, ...@@ -658,7 +668,12 @@ void handle_packet_response(struct hpsb_host *host, int tcode, quadlet_t *data,
break; break;
} }
packet->state = hpsb_complete; if (packet->state == hpsb_queued) {
packet->sendtime = jiffies;
packet->ack_code = ACK_PENDING;
}
packet->state = hpsb_complete;
queue_packet_complete(packet); queue_packet_complete(packet);
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/devfs_fs_kernel.h> #include <linux/devfs_fs_kernel.h>
#include <asm/atomic.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include "hosts.h" #include "hosts.h"
...@@ -59,6 +60,8 @@ struct hpsb_packet { ...@@ -59,6 +60,8 @@ struct hpsb_packet {
struct hpsb_host *host; struct hpsb_host *host;
unsigned int generation; unsigned int generation;
atomic_t refcnt;
/* Function (and possible data to pass to it) to call when this /* Function (and possible data to pass to it) to call when this
* packet is completed. */ * packet is completed. */
void (*complete_routine)(void *); void (*complete_routine)(void *);
......
...@@ -2376,10 +2376,6 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id, ...@@ -2376,10 +2376,6 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
event &= ~OHCI1394_busReset; event &= ~OHCI1394_busReset;
} }
/* XXX: We need a way to also queue the OHCI1394_reqTxComplete,
* but for right now we simply run it upon reception, to make sure
* we get sent acks before response packets. This sucks mainly
* because it halts the interrupt handler. */
if (event & OHCI1394_reqTxComplete) { if (event & OHCI1394_reqTxComplete) {
struct dma_trm_ctx *d = &ohci->at_req_context; struct dma_trm_ctx *d = &ohci->at_req_context;
DBGMSG(ohci->id, "Got reqTxComplete interrupt " DBGMSG(ohci->id, "Got reqTxComplete interrupt "
...@@ -2388,7 +2384,7 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id, ...@@ -2388,7 +2384,7 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
ohci1394_stop_context(ohci, d->ctrlClear, ohci1394_stop_context(ohci, d->ctrlClear,
"reqTxComplete"); "reqTxComplete");
else else
dma_trm_tasklet ((unsigned long)d); tasklet_schedule(&d->task);
event &= ~OHCI1394_reqTxComplete; event &= ~OHCI1394_reqTxComplete;
} }
if (event & OHCI1394_respTxComplete) { if (event & OHCI1394_respTxComplete) {
......
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