Commit a42571a8 authored by Ben Collins's avatar Ben Collins

Merge

parents afc2ce80 aab147d6
...@@ -103,6 +103,7 @@ static int alloc_hostnum_cb(struct hpsb_host *host, void *__data) ...@@ -103,6 +103,7 @@ static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
* Return Value: a pointer to the &hpsb_host if succesful, %NULL if * Return Value: a pointer to the &hpsb_host if succesful, %NULL if
* no memory was available. * no memory was available.
*/ */
static DECLARE_MUTEX(host_num_alloc);
struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
struct device *dev) struct device *dev)
...@@ -148,14 +149,12 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, ...@@ -148,14 +149,12 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
h->topology_map = h->csr.topology_map + 3; h->topology_map = h->csr.topology_map + 3;
h->speed_map = (u8 *)(h->csr.speed_map + 2); h->speed_map = (u8 *)(h->csr.speed_map + 2);
while (1) { down(&host_num_alloc);
if (!nodemgr_for_each_host(&hostnum, alloc_hostnum_cb)) {
h->id = hostnum;
break;
}
while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb))
hostnum++; hostnum++;
}
h->id = hostnum;
memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device)); memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
h->device.parent = dev; h->device.parent = dev;
...@@ -169,6 +168,8 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, ...@@ -169,6 +168,8 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
class_device_register(&h->class_dev); class_device_register(&h->class_dev);
get_device(&h->device); get_device(&h->device);
up(&host_num_alloc);
return h; return h;
} }
......
...@@ -36,8 +36,11 @@ ...@@ -36,8 +36,11 @@
#define ACK_BUSY_X 0x4 #define ACK_BUSY_X 0x4
#define ACK_BUSY_A 0x5 #define ACK_BUSY_A 0x5
#define ACK_BUSY_B 0x6 #define ACK_BUSY_B 0x6
#define ACK_TARDY 0xb
#define ACK_CONFLICT_ERROR 0xc
#define ACK_DATA_ERROR 0xd #define ACK_DATA_ERROR 0xd
#define ACK_TYPE_ERROR 0xe #define ACK_TYPE_ERROR 0xe
#define ACK_ADDRESS_ERROR 0xf
/* Non-standard "ACK codes" for internal use */ /* Non-standard "ACK codes" for internal use */
#define ACKX_NONE (-1) #define ACKX_NONE (-1)
......
...@@ -127,9 +127,6 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size) ...@@ -127,9 +127,6 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
if (packet == NULL) if (packet == NULL)
return NULL; return NULL;
memset(packet, 0, sizeof(struct hpsb_packet));
packet->header = packet->embedded_header;
if (data_size) { if (data_size) {
data = kmalloc(data_size + 8, GFP_ATOMIC); data = kmalloc(data_size + 8, GFP_ATOMIC);
if (data == NULL) { if (data == NULL) {
...@@ -141,13 +138,7 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size) ...@@ -141,13 +138,7 @@ 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); return packet;
packet->complete_routine = NULL;
packet->complete_data = NULL;
packet->state = hpsb_unused;
packet->generation = -1;
return packet;
} }
...@@ -155,15 +146,14 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size) ...@@ -155,15 +146,14 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
* hpsb_free_packet - free packet and data associated with it * hpsb_free_packet - free packet and data associated with it
* @packet: packet to free (is NULL safe) * @packet: packet to free (is NULL safe)
* *
* This function will free packet->data, packet->header and finally the packet * This function will free packet->data and finally the packet itself.
* itself.
*/ */
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 +392,30 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot) ...@@ -402,28 +392,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 */
hpsb_free_packet(packet);
return;
}
if (packet->no_waiter) { if (ackcode != ACK_PENDING || !packet->expect_response) {
/* must not have a tlabel allocated */ atomic_dec(&packet->refcnt);
hpsb_free_packet(packet); list_del(&packet->list);
return; packet->state = hpsb_complete;
} queue_packet_complete(packet);
return;
}
if (ackcode != ACK_PENDING || !packet->expect_response) { if (packet->state == hpsb_complete) {
packet->state = hpsb_complete; hpsb_free_packet(packet);
queue_packet_complete(packet); return;
return; }
}
packet->state = hpsb_pending; atomic_dec(&packet->refcnt);
packet->sendtime = jiffies; packet->state = hpsb_pending;
packet->sendtime = jiffies;
spin_lock_irqsave(&host->pending_pkt_lock, flags);
list_add_tail(&packet->list, &host->pending_packets);
spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
mod_timer(&host->timeout, jiffies + host->timeout_interval); mod_timer(&host->timeout, jiffies + host->timeout_interval);
} }
...@@ -492,7 +484,7 @@ int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt) ...@@ -492,7 +484,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 +494,15 @@ int hpsb_send_packet(struct hpsb_packet *packet) ...@@ -502,6 +494,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 +659,12 @@ void handle_packet_response(struct hpsb_host *host, int tcode, quadlet_t *data, ...@@ -658,7 +659,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);
} }
...@@ -1024,6 +1030,21 @@ static int hpsbpkt_thread(void *__hi) ...@@ -1024,6 +1030,21 @@ static int hpsbpkt_thread(void *__hi)
complete_and_exit(&khpsbpkt_complete, 0); complete_and_exit(&khpsbpkt_complete, 0);
} }
static void hpsb_packet_ctor(void *__packet, kmem_cache_t *hpsb_pkt_cache, unsigned long flags)
{
struct hpsb_packet *packet = __packet;
memset(packet, 0, sizeof(*packet));
packet->header = packet->embedded_header;
INIT_LIST_HEAD(&packet->list);
packet->state = hpsb_unused;
packet->generation = -1;
atomic_set(&packet->refcnt, 1);
}
static int __init ieee1394_init(void) static int __init ieee1394_init(void)
{ {
int i; int i;
...@@ -1044,7 +1065,7 @@ static int __init ieee1394_init(void) ...@@ -1044,7 +1065,7 @@ static int __init ieee1394_init(void)
devfs_mk_dir("ieee1394"); devfs_mk_dir("ieee1394");
hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet), hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet),
0, 0, NULL, NULL); 0, 0, hpsb_packet_ctor, NULL);
bus_register(&ieee1394_bus_type); bus_register(&ieee1394_bus_type);
for (i = 0; fw_bus_attrs[i]; i++) for (i = 0; fw_bus_attrs[i]; i++)
......
...@@ -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 *);
......
...@@ -239,6 +239,11 @@ int hpsb_packet_success(struct hpsb_packet *packet) ...@@ -239,6 +239,11 @@ int hpsb_packet_success(struct hpsb_packet *packet)
return -EAGAIN; return -EAGAIN;
} }
case ACK_ADDRESS_ERROR:
return -EINVAL;
case ACK_TARDY:
case ACK_CONFLICT_ERROR:
case ACKX_NONE: case ACKX_NONE:
case ACKX_SEND_ERROR: case ACKX_SEND_ERROR:
case ACKX_ABORTED: case ACKX_ABORTED:
......
...@@ -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