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)
* Return Value: a pointer to the &hpsb_host if succesful, %NULL if
* 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 device *dev)
......@@ -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->speed_map = (u8 *)(h->csr.speed_map + 2);
while (1) {
if (!nodemgr_for_each_host(&hostnum, alloc_hostnum_cb)) {
h->id = hostnum;
break;
}
down(&host_num_alloc);
while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb))
hostnum++;
}
h->id = hostnum;
memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
h->device.parent = dev;
......@@ -169,6 +168,8 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
class_device_register(&h->class_dev);
get_device(&h->device);
up(&host_num_alloc);
return h;
}
......
......@@ -36,8 +36,11 @@
#define ACK_BUSY_X 0x4
#define ACK_BUSY_A 0x5
#define ACK_BUSY_B 0x6
#define ACK_TARDY 0xb
#define ACK_CONFLICT_ERROR 0xc
#define ACK_DATA_ERROR 0xd
#define ACK_TYPE_ERROR 0xe
#define ACK_ADDRESS_ERROR 0xf
/* Non-standard "ACK codes" for internal use */
#define ACKX_NONE (-1)
......
......@@ -127,9 +127,6 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
if (packet == NULL)
return NULL;
memset(packet, 0, sizeof(struct hpsb_packet));
packet->header = packet->embedded_header;
if (data_size) {
data = kmalloc(data_size + 8, GFP_ATOMIC);
if (data == NULL) {
......@@ -141,13 +138,7 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
packet->data_size = data_size;
}
INIT_LIST_HEAD(&packet->list);
packet->complete_routine = NULL;
packet->complete_data = NULL;
packet->state = hpsb_unused;
packet->generation = -1;
return packet;
return packet;
}
......@@ -155,15 +146,14 @@ struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
* hpsb_free_packet - free packet and data associated with it
* @packet: packet to free (is NULL safe)
*
* This function will free packet->data, packet->header and finally the packet
* itself.
* This function will free packet->data and finally the packet itself.
*/
void hpsb_free_packet(struct hpsb_packet *packet)
{
if (!packet) return;
kfree(packet->data);
kmem_cache_free(hpsb_packet_cache, packet);
if (packet && atomic_dec_and_test(&packet->refcnt)) {
kfree(packet->data);
kmem_cache_free(hpsb_packet_cache, packet);
}
}
......@@ -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,
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) {
/* must not have a tlabel allocated */
hpsb_free_packet(packet);
return;
}
if (ackcode != ACK_PENDING || !packet->expect_response) {
atomic_dec(&packet->refcnt);
list_del(&packet->list);
packet->state = hpsb_complete;
queue_packet_complete(packet);
return;
}
if (ackcode != ACK_PENDING || !packet->expect_response) {
packet->state = hpsb_complete;
queue_packet_complete(packet);
return;
}
if (packet->state == hpsb_complete) {
hpsb_free_packet(packet);
return;
}
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);
atomic_dec(&packet->refcnt);
packet->state = hpsb_pending;
packet->sendtime = jiffies;
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)
*/
int hpsb_send_packet(struct hpsb_packet *packet)
{
struct hpsb_host *host = packet->host;
struct hpsb_host *host = packet->host;
if (host->is_shutdown)
return -EINVAL;
......@@ -502,6 +494,15 @@ int hpsb_send_packet(struct hpsb_packet *packet)
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)
{ /* it is a local request, so handle it locally */
quadlet_t *data;
......@@ -658,7 +659,12 @@ void handle_packet_response(struct hpsb_host *host, int tcode, quadlet_t *data,
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);
}
......@@ -1024,6 +1030,21 @@ static int hpsbpkt_thread(void *__hi)
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)
{
int i;
......@@ -1044,7 +1065,7 @@ static int __init ieee1394_init(void)
devfs_mk_dir("ieee1394");
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);
for (i = 0; fw_bus_attrs[i]; i++)
......
......@@ -4,6 +4,7 @@
#include <linux/slab.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/atomic.h>
#include <asm/semaphore.h>
#include "hosts.h"
......@@ -59,6 +60,8 @@ struct hpsb_packet {
struct hpsb_host *host;
unsigned int generation;
atomic_t refcnt;
/* Function (and possible data to pass to it) to call when this
* packet is completed. */
void (*complete_routine)(void *);
......
......@@ -239,6 +239,11 @@ int hpsb_packet_success(struct hpsb_packet *packet)
return -EAGAIN;
}
case ACK_ADDRESS_ERROR:
return -EINVAL;
case ACK_TARDY:
case ACK_CONFLICT_ERROR:
case ACKX_NONE:
case ACKX_SEND_ERROR:
case ACKX_ABORTED:
......
......@@ -2376,10 +2376,6 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
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) {
struct dma_trm_ctx *d = &ohci->at_req_context;
DBGMSG(ohci->id, "Got reqTxComplete interrupt "
......@@ -2388,7 +2384,7 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
ohci1394_stop_context(ohci, d->ctrlClear,
"reqTxComplete");
else
dma_trm_tasklet ((unsigned long)d);
tasklet_schedule(&d->task);
event &= ~OHCI1394_reqTxComplete;
}
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