Commit af17e3f3 authored by Ben Collins's avatar Ben Collins

Many files:

IEEE-1394 Sync with r1088

- Cleanup Kconfig so that ieee1394 core doesn't require PCI.

- Some function renames to make things consistent.

- Fixup ISO API so that packet-per-buffer and irq-interval work
  correctly.

- Get rid of host list and use driver model for handling host ref count
  and host accounting.

- Get rid of packet semaphore.

- Move bus registration into core ieee1394 initialization.

- Get rid of ancient unused data_be (big-endian) flag in packet struct.

- Fix recursive use of bus_for_each_dev() in nodemgr.

- Revert changes to oui.db. This file is verbatim from IEEE, so if any
  changes should be made, register them with the IEEE database and keep
  this one pristine.

- Fix PCILynx so that it checks for errors on calls to copy_from_user().

- Add ARM API handlers to raw1394.

- Cleanup sbp2's packet sending to accomodate for a case where a packet
  was free'd while sbp2 was waiting on it.
parent 67e9bb60
# -*- shell-script -*-
menu "IEEE 1394 (FireWire) support (EXPERIMENTAL)"
depends on PCI && EXPERIMENTAL
depends on EXPERIMENTAL
config IEEE1394
tristate "IEEE 1394 (FireWire) support (EXPERIMENTAL)"
......@@ -15,7 +15,7 @@ config IEEE1394
is the core support only, you will also need to select a driver for
your IEEE 1394 adapter.
To compile this driver as a module, choose M here: the
To compile this driver as a module, say M here: the
module will be called ieee1394.
comment "Subsystem Options"
......@@ -56,13 +56,13 @@ comment "Texas Instruments PCILynx requires I2C bit-banging"
config IEEE1394_PCILYNX
tristate "Texas Instruments PCILynx support"
depends on IEEE1394 && I2C_ALGOBIT
depends on PCI && IEEE1394 && I2C_ALGOBIT
help
Say Y here if you have an IEEE-1394 controller with the Texas
Instruments PCILynx chip. Note: this driver is written for revision
2 of this chip and may not work with revision 0.
To compile this driver as a module, choose M here: the
To compile this driver as a module, say M here: the
module will be called pcilynx.
# Non-maintained pcilynx options
......@@ -72,7 +72,7 @@ config IEEE1394_PCILYNX
# fi
config IEEE1394_OHCI1394
tristate "OHCI-1394 support"
depends on IEEE1394
depends on PCI && IEEE1394
help
Enable this driver if you have an IEEE 1394 controller based on the
OHCI-1394 specification. The current driver is only tested with OHCI
......@@ -80,7 +80,7 @@ config IEEE1394_OHCI1394
use one of these chipsets. It should work with any OHCI-1394
compliant card, however.
To compile this driver as a module, choose M here: the
To compile this driver as a module, say M here: the
module will be called ohci1394.
comment "Protocol Drivers"
......@@ -122,7 +122,7 @@ config IEEE1394_DV1394
The user-space API for dv1394 is documented in dv1394.h.
To compile this driver as a module, choose M here: the
To compile this driver as a module, say M here: the
module will be called dv1394.
config IEEE1394_RAWIO
......@@ -134,7 +134,7 @@ config IEEE1394_RAWIO
direct communication of user programs with the IEEE 1394 bus and
thus with the attached peripherals.
To compile this driver as a module, choose M here: the
To compile this driver as a module, say M here: the
module will be called raw1394.
config IEEE1394_CMP
......@@ -144,7 +144,7 @@ config IEEE1394_CMP
This option enables the Connection Management Procedures
(IEC61883-1) driver, which implements input and output plugs.
To compile this driver as a module, choose M here: the
To compile this driver as a module, say M here: the
module will be called cmp.
config IEEE1394_AMDTP
......@@ -157,7 +157,7 @@ config IEEE1394_AMDTP
The userspace interface is documented in amdtp.h.
To compile this driver as a module, choose M here: the
To compile this driver as a module, say M here: the
module will be called amdtp.
endmenu
......@@ -89,7 +89,7 @@
#define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__)
static char version[] __devinitdata =
"$Rev: 1043 $ Ben Collins <bcollins@debian.org>";
"$Rev: 1079 $ Ben Collins <bcollins@debian.org>";
struct fragment_info {
struct list_head list;
......@@ -220,7 +220,7 @@ static int ether1394_init_bc(struct net_device *dev)
priv->iso = hpsb_iso_recv_init(priv->host, 16 * 4096,
16, priv->broadcast_channel,
1, ether1394_iso);
HPSB_ISO_DMA_PACKET_PER_BUFFER, 1, ether1394_iso);
if (priv->iso == NULL) {
ETH1394_PRINT(KERN_ERR, dev->name,
"failed to change broadcast "
......@@ -475,7 +475,7 @@ static void ether1394_add_host (struct hpsb_host *host)
priv->broadcast_channel = host->csr.broadcast_channel & 0x3f;
priv->iso = hpsb_iso_recv_init(host, 16 * 4096, 16, priv->broadcast_channel,
1, ether1394_iso);
HPSB_ISO_DMA_PACKET_PER_BUFFER, 1, ether1394_iso);
if (priv->iso == NULL) {
priv->bc_state = ETHER1394_BC_CLOSED;
}
......@@ -1258,7 +1258,7 @@ static inline struct hpsb_packet *ether1394_alloc_common_packet(struct hpsb_host
{
struct hpsb_packet *p;
p = alloc_hpsb_packet(0);
p = hpsb_alloc_packet(0);
if (p) {
p->host = host;
p->data = NULL;
......@@ -1327,7 +1327,7 @@ static inline void ether1394_free_packet(struct hpsb_packet *packet)
if (packet->tcode != TCODE_STREAM_DATA)
hpsb_free_tlabel(packet);
packet->data = NULL;
free_hpsb_packet(packet);
hpsb_free_packet(packet);
}
static void ether1394_complete_cb(void *__ptask);
......@@ -1349,7 +1349,7 @@ static int ether1394_send_packet(struct packet_task *ptask, unsigned int tx_len)
ptask->dest_node,
ptask->addr, ptask->skb->data,
tx_len)) {
free_hpsb_packet(packet);
hpsb_free_packet(packet);
return -1;
}
......@@ -1357,7 +1357,7 @@ static int ether1394_send_packet(struct packet_task *ptask, unsigned int tx_len)
hpsb_set_packet_complete_task(ptask->packet, ether1394_complete_cb,
ptask);
if (!hpsb_send_packet(packet)) {
if (hpsb_send_packet(packet) < 0) {
ether1394_free_packet(packet);
return -1;
}
......@@ -1599,7 +1599,7 @@ static int ether1394_ethtool_ioctl(struct net_device *dev, void *useraddr)
case ETHTOOL_GDRVINFO: {
struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
strcpy (info.driver, driver_name);
strcpy (info.version, "$Rev: 1043 $");
strcpy (info.version, "$Rev: 1079 $");
/* FIXME XXX provide sane businfo */
strcpy (info.bus_info, "ieee1394");
if (copy_to_user (useraddr, &info, sizeof (info)))
......
......@@ -26,6 +26,7 @@
#include "hosts.h"
#include "ieee1394_core.h"
#include "highlevel.h"
#include "nodemgr.h"
struct hl_host_info {
......@@ -227,10 +228,17 @@ struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long k
return host;
}
static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data)
{
struct hpsb_highlevel *hl = __data;
hl->add_host(host);
return 0;
}
void hpsb_register_highlevel(struct hpsb_highlevel *hl)
{
struct list_head *lh;
unsigned long flags;
INIT_LIST_HEAD(&hl->addr_list);
......@@ -242,21 +250,25 @@ void hpsb_register_highlevel(struct hpsb_highlevel *hl)
list_add_tail(&hl->hl_list, &hl_drivers);
write_unlock_irqrestore(&hl_drivers_lock, flags);
if (hl->add_host) {
down(&hpsb_hosts_lock);
list_for_each (lh, &hpsb_hosts) {
struct hpsb_host *host = list_entry(lh, struct hpsb_host, host_list);
hl->add_host(host);
}
up(&hpsb_hosts_lock);
}
if (hl->add_host)
nodemgr_for_each_host(hl, highlevel_for_each_host_reg);
return;
}
static int highlevel_for_each_host_unreg(struct hpsb_host *host, void *__data)
{
struct hpsb_highlevel *hl = __data;
hl->remove_host(host);
hpsb_destroy_hostinfo(hl, host);
return 0;
}
void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
{
struct list_head *lh, *next;
struct list_head *lh, *next;
struct hpsb_address_serve *as;
unsigned long flags;
......@@ -272,16 +284,8 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
list_del(&hl->hl_list);
write_unlock_irqrestore(&hl_drivers_lock, flags);
if (hl->remove_host) {
down(&hpsb_hosts_lock);
list_for_each(lh, &hpsb_hosts) {
struct hpsb_host *host = list_entry(lh, struct hpsb_host, host_list);
hl->remove_host(host);
hpsb_destroy_hostinfo(hl, host);
}
up(&hpsb_hosts_lock);
}
if (hl->remove_host)
nodemgr_for_each_host(hl, highlevel_for_each_host_unreg);
}
int hpsb_register_addrspace(struct hpsb_highlevel *hl,
......
......@@ -92,8 +92,6 @@ struct hpsb_address_ops {
};
void init_hpsb_highlevel(void);
void highlevel_add_host(struct hpsb_host *host);
void highlevel_remove_host(struct hpsb_host *host);
void highlevel_host_reset(struct hpsb_host *host);
......@@ -180,4 +178,7 @@ int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, void *d
/* Retrieve hpsb_host using a highlevel handle and a key */
struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key);
/* Initialize the highlevel system */
void init_hpsb_highlevel(void);
#endif /* IEEE1394_HIGHLEVEL_H */
......@@ -16,14 +16,14 @@
#include <linux/list.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include "ieee1394_types.h"
#include "hosts.h"
#include "ieee1394_core.h"
#include "highlevel.h"
#include "nodemgr.h"
LIST_HEAD(hpsb_hosts);
DECLARE_MUTEX(hpsb_hosts_lock);
static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p)
{
......@@ -46,54 +46,14 @@ static struct hpsb_host_driver dummy_driver = {
.isoctl = dummy_isoctl
};
/**
* hpsb_ref_host - increase reference count for host controller.
* @host: the host controller
*
* Increase the reference count for the specified host controller.
* When holding a reference to a host, the memory allocated for the
* host struct will not be freed and the host is guaranteed to be in a
* consistent state. The driver may be unloaded or the controller may
* be removed (PCMCIA), but the host struct will remain valid.
*/
int hpsb_ref_host(struct hpsb_host *host)
static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
{
struct list_head *lh;
int retval = 0;
down(&hpsb_hosts_lock);
list_for_each(lh, &hpsb_hosts) {
if (host == list_entry(lh, struct hpsb_host, host_list)) {
if (try_module_get(host->driver->owner)) {
atomic_inc(&host->refcount);
retval = 1;
}
break;
}
}
up(&hpsb_hosts_lock);
int *hostnum = __data;
return retval;
}
if (host->id == *hostnum)
return 1;
/**
* hpsb_unref_host - decrease reference count for host controller.
* @host: the host controller
*
* Decrease the reference count for the specified host controller.
* When the reference count reaches zero, the memory allocated for the
* &hpsb_host will be freed.
*/
void hpsb_unref_host(struct hpsb_host *host)
{
module_put(host->driver->owner);
down(&hpsb_hosts_lock);
if (atomic_dec_and_test(&host->refcount) && host->is_shutdown)
device_unregister(&host->device);
up(&hpsb_hosts_lock);
return 0;
}
/**
......@@ -108,19 +68,16 @@ void hpsb_unref_host(struct hpsb_host *host)
* driver specific parts, enable the controller and make it available
* to the general subsystem using hpsb_add_host().
*
* The &hpsb_host is allocated with an single initial reference
* belonging to the driver. Once the driver is done with the struct,
* for example, when the driver is unloaded, it should release this
* reference using hpsb_unref_host().
*
* Return Value: a pointer to the &hpsb_host if succesful, %NULL if
* no memory was available.
*/
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 hpsb_host *h;
int i;
int hostnum = 0;
h = kmalloc(sizeof(struct hpsb_host) + extra, SLAB_KERNEL);
if (!h) return NULL;
......@@ -128,7 +85,6 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra)
h->hostdata = h + 1;
h->driver = drv;
atomic_set(&h->refcount, 1);
INIT_LIST_HEAD(&h->pending_packets);
spin_lock_init(&h->pending_pkt_lock);
......@@ -146,53 +102,35 @@ 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);
return h;
}
static int alloc_hostnum(void)
{
int hostnum = 0;
while (1) {
struct list_head *lh;
int found = 0;
list_for_each(lh, &hpsb_hosts) {
struct hpsb_host *host = list_entry(lh, struct hpsb_host, host_list);
if (host->id == hostnum) {
found = 1;
break;
}
if (!nodemgr_for_each_host(&hostnum, alloc_hostnum_cb)) {
h->id = hostnum;
break;
}
if (!found)
return hostnum;
hostnum++;
}
return 0;
memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
h->device.parent = dev;
snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
device_register(&h->device);
return h;
}
void hpsb_add_host(struct hpsb_host *host)
{
down(&hpsb_hosts_lock);
host->id = alloc_hostnum();
list_add_tail(&host->host_list, &hpsb_hosts);
up(&hpsb_hosts_lock);
highlevel_add_host(host);
host->driver->devctl(host, RESET_BUS, LONG_RESET);
}
void hpsb_remove_host(struct hpsb_host *host)
{
down(&hpsb_hosts_lock);
host->is_shutdown = 1;
host->driver = &dummy_driver;
list_del(&host->host_list);
up(&hpsb_hosts_lock);
highlevel_remove_host(host);
device_unregister(&host->device);
}
......@@ -29,8 +29,6 @@ struct hpsb_host {
atomic_t generation;
atomic_t refcount;
struct list_head pending_packets;
spinlock_t pending_pkt_lock;
struct timer_list timeout;
......@@ -165,7 +163,7 @@ struct hpsb_host_driver {
* packet->type == raw) and do byte-swapping as necessary or instruct
* the hardware to do so. It can return immediately after the packet
* was queued for sending. After sending, hpsb_sent_packet() has to be
* called. Return 0 for failure.
* called. Return 0 on success, negative errno on failure.
* NOTE: The function must be callable in interrupt context.
*/
int (*transmit_packet) (struct hpsb_host *host,
......@@ -195,22 +193,8 @@ struct hpsb_host_driver {
};
extern struct list_head hpsb_hosts;
extern struct semaphore hpsb_hosts_lock;
/*
* In order to prevent hosts from unloading, use hpsb_ref_host(). This prevents
* the host from going away (e.g. makes module unloading of the driver
* impossible), but still can not guarantee it (e.g. PC-Card being pulled by the
* user). hpsb_ref_host() returns false if host could not be locked. If it is
* successful, host is valid as a pointer until hpsb_unref_host() (not just
* until after remove_host).
*/
int hpsb_ref_host(struct hpsb_host *host);
void hpsb_unref_host(struct hpsb_host *host);
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);
void hpsb_add_host(struct hpsb_host *host);
void hpsb_remove_host(struct hpsb_host *h);
......
......@@ -109,7 +109,7 @@ void hpsb_set_packet_complete_task(struct hpsb_packet *packet,
}
/**
* alloc_hpsb_packet - allocate new packet structure
* hpsb_alloc_packet - allocate new packet structure
* @data_size: size of the data block to be allocated
*
* This function allocates, initializes and returns a new &struct hpsb_packet.
......@@ -128,7 +128,7 @@ void hpsb_set_packet_complete_task(struct hpsb_packet *packet,
* Return value: A pointer to a &struct hpsb_packet or NULL on allocation
* failure.
*/
struct hpsb_packet *alloc_hpsb_packet(size_t data_size)
struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
{
struct hpsb_packet *packet = NULL;
void *data = NULL;
......@@ -152,25 +152,23 @@ struct hpsb_packet *alloc_hpsb_packet(size_t data_size)
}
INIT_LIST_HEAD(&packet->list);
sema_init(&packet->state_change, 0);
packet->complete_routine = NULL;
packet->complete_data = NULL;
packet->state = hpsb_unused;
packet->generation = -1;
packet->data_be = 1;
return packet;
}
/**
* free_hpsb_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)
*
* This function will free packet->data, packet->header and finally the packet
* itself.
*/
void free_hpsb_packet(struct hpsb_packet *packet)
void hpsb_free_packet(struct hpsb_packet *packet)
{
if (!packet) return;
......@@ -420,14 +418,12 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
if (packet->no_waiter) {
/* must not have a tlabel allocated */
free_hpsb_packet(packet);
hpsb_free_packet(packet);
return;
}
if (ackcode != ACK_PENDING || !packet->expect_response) {
packet->state = hpsb_complete;
up(&packet->state_change);
up(&packet->state_change);
run_packet_complete(packet);
return;
}
......@@ -439,7 +435,6 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
list_add_tail(&packet->list, &host->pending_packets);
spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
up(&packet->state_change);
mod_timer(&host->timeout, jiffies + host->timeout_interval);
}
......@@ -465,7 +460,7 @@ int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt)
return -EINVAL;
}
packet = alloc_hpsb_packet(0);
packet = hpsb_alloc_packet(0);
if (!packet)
return -ENOMEM;
......@@ -485,16 +480,8 @@ int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt)
packet->generation = get_hpsb_generation(host);
if (!hpsb_send_packet(packet)) {
retval = -EINVAL;
goto fail;
}
down(&packet->state_change);
down(&packet->state_change);
fail:
free_hpsb_packet(packet);
retval = hpsb_send_packet_and_wait(packet);
hpsb_free_packet(packet);
return retval;
}
......@@ -504,23 +491,24 @@ int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt)
* @packet: packet to send
*
* The packet is sent through the host specified in the packet->host field.
* Before sending, the packet's transmit speed is automatically determined using
* the local speed map when it is an async, non-broadcast packet.
* Before sending, the packet's transmit speed is automatically determined
* using the local speed map when it is an async, non-broadcast packet.
*
* Possibilities for failure are that host is either not initialized, in bus
* reset, the packet's generation number doesn't match the current generation
* number or the host reports a transmit error.
*
* Return value: False (0) on failure, true (1) otherwise.
* Return value: 0 on success, negative errno on failure.
*/
int hpsb_send_packet(struct hpsb_packet *packet)
{
struct hpsb_host *host = packet->host;
if (host->is_shutdown || host->in_bus_reset
|| (packet->generation != get_hpsb_generation(host))) {
return 0;
}
if (host->is_shutdown)
return -EINVAL;
if (host->in_bus_reset ||
(packet->generation != get_hpsb_generation(host)))
return -EAGAIN;
packet->state = hpsb_queued;
......@@ -532,23 +520,13 @@ int hpsb_send_packet(struct hpsb_packet *packet)
data = kmalloc(packet->header_size + packet->data_size, GFP_ATOMIC);
if (!data) {
HPSB_ERR("unable to allocate memory for concatenating header and data");
return 0;
return -ENOMEM;
}
memcpy(data, packet->header, packet->header_size);
if (packet->data_size)
{
if (packet->data_be) {
memcpy(((u8*)data)+packet->header_size, packet->data, packet->data_size);
} else {
int i;
quadlet_t *my_data=(quadlet_t*) ((u8*) data + packet->data_size);
for (i=0; i < packet->data_size/4; i++) {
my_data[i] = cpu_to_be32(packet->data[i]);
}
}
}
memcpy(((u8*)data)+packet->header_size, packet->data, packet->data_size);
dump_packet("send packet local:", packet->header,
packet->header_size);
......@@ -558,7 +536,7 @@ int hpsb_send_packet(struct hpsb_packet *packet)
kfree(data);
return 1;
return 0;
}
if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
......@@ -584,10 +562,33 @@ int hpsb_send_packet(struct hpsb_packet *packet)
return host->driver->transmit_packet(host, packet);
}
/* We could just use complete() directly as the packet complete
* callback, but this is more typesafe, in the sense that we get a
* compiler error if the prototype for complete() changes. */
static void complete_packet(void *data)
{
complete((struct completion *) data);
}
int hpsb_send_packet_and_wait(struct hpsb_packet *packet)
{
struct completion done;
int retval;
init_completion(&done);
hpsb_set_packet_complete_task(packet, complete_packet, &done);
retval = hpsb_send_packet(packet);
if (retval == 0)
wait_for_completion(&done);
return retval;
}
static void send_packet_nocare(struct hpsb_packet *packet)
{
if (!hpsb_send_packet(packet)) {
free_hpsb_packet(packet);
if (hpsb_send_packet(packet) < 0) {
hpsb_free_packet(packet);
}
}
......@@ -668,7 +669,6 @@ void handle_packet_response(struct hpsb_host *host, int tcode, quadlet_t *data,
}
packet->state = hpsb_complete;
up(&packet->state_change);
run_packet_complete(packet);
}
......@@ -680,7 +680,7 @@ static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,
dsize += (dsize % 4 ? 4 - (dsize % 4) : 0);
p = alloc_hpsb_packet(dsize);
p = hpsb_alloc_packet(dsize);
if (p == NULL) {
/* FIXME - send data_error response */
return NULL;
......@@ -820,6 +820,8 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
if (rcode >= 0) {
fill_async_readblock_resp(packet, rcode, length);
send_packet_nocare(packet);
} else {
hpsb_free_packet(packet);
}
break;
......@@ -874,7 +876,7 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
if (rcode >= 0) {
send_packet_nocare(packet);
} else {
free_hpsb_packet(packet);
hpsb_free_packet(packet);
}
break;
}
......@@ -949,7 +951,6 @@ void abort_requests(struct hpsb_host *host)
list_del(&packet->list);
packet->state = hpsb_complete;
packet->ack_code = ACKX_ABORTED;
up(&packet->state_change);
run_packet_complete(packet);
}
}
......@@ -987,7 +988,6 @@ void abort_timedouts(unsigned long __opaque)
list_del(&packet->list);
packet->state = hpsb_complete;
packet->ack_code = ACKX_TIMEOUT;
up(&packet->state_change);
run_packet_complete(packet);
}
}
......@@ -1171,19 +1171,22 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file)
static int __init ieee1394_init(void)
{
hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet),
0, 0, NULL, NULL);
devfs_mk_dir("ieee1394");
if (register_chrdev(IEEE1394_MAJOR, "ieee1394", &ieee1394_chardev_ops)) {
HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR);
devfs_remove("ieee1394");
return -ENODEV;
}
devfs_mk_dir("ieee1394");
hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet),
0, 0, NULL, NULL);
bus_register(&ieee1394_bus_type);
init_hpsb_highlevel();
init_csr();
if (!disable_nodemgr)
init_ieee1394_nodemgr();
else
......@@ -1198,6 +1201,9 @@ static void __exit ieee1394_cleanup(void)
cleanup_ieee1394_nodemgr();
cleanup_csr();
bus_unregister(&ieee1394_bus_type);
kmem_cache_destroy(hpsb_packet_cache);
unregister_chrdev(IEEE1394_MAJOR, "ieee1394");
......@@ -1213,16 +1219,15 @@ module_exit(ieee1394_cleanup);
EXPORT_SYMBOL(hpsb_alloc_host);
EXPORT_SYMBOL(hpsb_add_host);
EXPORT_SYMBOL(hpsb_remove_host);
EXPORT_SYMBOL(hpsb_ref_host);
EXPORT_SYMBOL(hpsb_unref_host);
/** ieee1394_core.c **/
EXPORT_SYMBOL(hpsb_speedto_str);
EXPORT_SYMBOL(hpsb_set_packet_complete_task);
EXPORT_SYMBOL(alloc_hpsb_packet);
EXPORT_SYMBOL(free_hpsb_packet);
EXPORT_SYMBOL(hpsb_alloc_packet);
EXPORT_SYMBOL(hpsb_free_packet);
EXPORT_SYMBOL(hpsb_send_phy_config);
EXPORT_SYMBOL(hpsb_send_packet);
EXPORT_SYMBOL(hpsb_send_packet_and_wait);
EXPORT_SYMBOL(hpsb_reset_bus);
EXPORT_SYMBOL(hpsb_bus_reset);
EXPORT_SYMBOL(hpsb_selfid_received);
......@@ -1282,6 +1287,7 @@ EXPORT_SYMBOL(hpsb_node_lock);
EXPORT_SYMBOL(hpsb_register_protocol);
EXPORT_SYMBOL(hpsb_unregister_protocol);
EXPORT_SYMBOL(ieee1394_bus_type);
EXPORT_SYMBOL(nodemgr_for_each_host);
/** csr.c **/
EXPORT_SYMBOL(hpsb_update_config_rom);
......
......@@ -40,11 +40,6 @@ struct hpsb_packet {
unsigned expect_response:1;
unsigned no_waiter:1;
/* Data big endianness flag - may vary from request to request. The
* header is always in machine byte order.
* Not really used currently. */
unsigned data_be:1;
/* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */
unsigned speed_code:2;
......@@ -64,9 +59,6 @@ struct hpsb_packet {
struct hpsb_host *host;
unsigned int generation;
/* Very core internal, don't care. */
struct semaphore state_change;
/* Function (and possible data to pass to it) to call when this
* packet is completed. */
void (*complete_routine)(void *);
......@@ -90,8 +82,8 @@ static inline struct hpsb_packet *driver_packet(struct list_head *l)
void abort_timedouts(unsigned long __opaque);
void abort_requests(struct hpsb_host *host);
struct hpsb_packet *alloc_hpsb_packet(size_t data_size);
void free_hpsb_packet(struct hpsb_packet *packet);
struct hpsb_packet *hpsb_alloc_packet(size_t data_size);
void hpsb_free_packet(struct hpsb_packet *packet);
/*
......@@ -108,15 +100,23 @@ static inline unsigned int get_hpsb_generation(struct hpsb_host *host)
}
/*
* Send a PHY configuration packet.
* Send a PHY configuration packet, return 0 on success, negative
* errno on failure.
*/
int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt);
/*
* Queue packet for transmitting, return 0 for failure.
* Queue packet for transmitting, return 0 on success, negative errno
* on failure.
*/
int hpsb_send_packet(struct hpsb_packet *packet);
/*
* Queue packet for transmitting, and block until the transaction
* completes. Return 0 on success, negative errno on failure.
*/
int hpsb_send_packet_and_wait(struct hpsb_packet *packet);
/* Initiate bus reset on the given host. Returns 1 if bus reset already in
* progress, 0 otherwise. */
int hpsb_reset_bus(struct hpsb_host *host, int type);
......
......@@ -263,7 +263,7 @@ struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
if (length == 0)
return NULL;
packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0));
if (!packet)
return NULL;
......@@ -271,7 +271,7 @@ struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
packet->node_id = node;
if (hpsb_get_tlabel(packet)) {
free_hpsb_packet(packet);
hpsb_free_packet(packet);
return NULL;
}
......@@ -291,7 +291,7 @@ struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node
if (length == 0)
return NULL;
packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0));
if (!packet)
return NULL;
......@@ -302,7 +302,7 @@ struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node
packet->node_id = node;
if (hpsb_get_tlabel(packet)) {
free_hpsb_packet(packet);
hpsb_free_packet(packet);
return NULL;
}
......@@ -325,7 +325,7 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, i
if (length == 0)
return NULL;
packet = alloc_hpsb_packet(length + (length % 4 ? 4 - (length % 4) : 0));
packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0));
if (!packet)
return NULL;
......@@ -335,7 +335,7 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, i
packet->host = host;
if (hpsb_get_tlabel(packet)) {
free_hpsb_packet(packet);
hpsb_free_packet(packet);
return NULL;
}
......@@ -353,13 +353,13 @@ struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
struct hpsb_packet *p;
u32 length;
p = alloc_hpsb_packet(8);
p = hpsb_alloc_packet(8);
if (!p) return NULL;
p->host = host;
p->node_id = node;
if (hpsb_get_tlabel(p)) {
free_hpsb_packet(p);
hpsb_free_packet(p);
return NULL;
}
......@@ -390,13 +390,13 @@ struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node
struct hpsb_packet *p;
u32 length;
p = alloc_hpsb_packet(16);
p = hpsb_alloc_packet(16);
if (!p) return NULL;
p->host = host;
p->node_id = node;
if (hpsb_get_tlabel(p)) {
free_hpsb_packet(p);
hpsb_free_packet(p);
return NULL;
}
......@@ -429,7 +429,7 @@ struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host,
{
struct hpsb_packet *p;
p = alloc_hpsb_packet(0);
p = hpsb_alloc_packet(0);
if (!p) return NULL;
p->host = host;
......@@ -444,7 +444,7 @@ struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
{
struct hpsb_packet *p;
p = alloc_hpsb_packet(length);
p = hpsb_alloc_packet(length);
if (!p) return NULL;
p->host = host;
......@@ -478,13 +478,10 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
}
packet->generation = generation;
if (!hpsb_send_packet(packet)) {
retval = -EINVAL;
retval = hpsb_send_packet_and_wait(packet);
if (retval < 0)
goto hpsb_read_fail;
}
down(&packet->state_change);
down(&packet->state_change);
retval = hpsb_packet_success(packet);
if (retval == 0) {
......@@ -497,7 +494,7 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
hpsb_read_fail:
hpsb_free_tlabel(packet);
free_hpsb_packet(packet);
hpsb_free_packet(packet);
return retval;
}
......@@ -520,18 +517,15 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
return -ENOMEM;
packet->generation = generation;
if (!hpsb_send_packet(packet)) {
retval = -EINVAL;
retval = hpsb_send_packet_and_wait(packet);
if (retval < 0)
goto hpsb_write_fail;
}
down(&packet->state_change);
down(&packet->state_change);
retval = hpsb_packet_success(packet);
hpsb_write_fail:
hpsb_free_tlabel(packet);
free_hpsb_packet(packet);
hpsb_free_packet(packet);
return retval;
}
......@@ -550,12 +544,10 @@ int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
return -ENOMEM;
packet->generation = generation;
if (!hpsb_send_packet(packet)) {
retval = -EINVAL;
retval = hpsb_send_packet_and_wait(packet);
if (retval < 0)
goto hpsb_lock_fail;
}
down(&packet->state_change);
down(&packet->state_change);
retval = hpsb_packet_success(packet);
if (retval == 0) {
......@@ -564,7 +556,7 @@ int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
hpsb_lock_fail:
hpsb_free_tlabel(packet);
free_hpsb_packet(packet);
hpsb_free_packet(packet);
return retval;
}
......@@ -582,12 +574,10 @@ int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
return -ENOMEM;
packet->generation = generation;
if (!hpsb_send_packet(packet)) {
retval = -EINVAL;
retval = hpsb_send_packet_and_wait(packet);
if (retval < 0)
goto hpsb_lock64_fail;
}
down(&packet->state_change);
down(&packet->state_change);
retval = hpsb_packet_success(packet);
if (retval == 0)
......@@ -595,7 +585,7 @@ int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
hpsb_lock64_fail:
hpsb_free_tlabel(packet);
free_hpsb_packet(packet);
hpsb_free_packet(packet);
return retval;
}
......@@ -626,10 +616,9 @@ int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
packet->no_waiter = 1;
if (!hpsb_send_packet(packet)) {
free_hpsb_packet(packet);
retval = -EINVAL;
}
retval = hpsb_send_packet(packet);
if (retval < 0)
hpsb_free_packet(packet);
return retval;
}
......@@ -40,6 +40,7 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i
unsigned int data_buf_size,
unsigned int buf_packets,
int channel,
int dma_mode,
int irq_interval,
void (*callback)(struct hpsb_iso*))
{
......@@ -58,8 +59,13 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i
if (buf_packets < 2)
buf_packets = 2;
if (irq_interval < 1 || irq_interval > buf_packets / 2)
irq_interval = buf_packets / 2;
if ((dma_mode < HPSB_ISO_DMA_DEFAULT) || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER))
dma_mode=HPSB_ISO_DMA_DEFAULT;
if (irq_interval == 0) /* really interrupt for each packet*/
irq_interval = 1;
else if ((irq_interval < 0) || (irq_interval > buf_packets / 4))
irq_interval = buf_packets / 4;
if (channel < -1 || channel >= 64)
return NULL;
......@@ -83,6 +89,7 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i
init_waitqueue_head(&iso->waitq);
iso->channel = channel;
iso->irq_interval = irq_interval;
iso->dma_mode = dma_mode;
dma_region_init(&iso->data_buf);
iso->buf_size = round_up_to_page(data_buf_size);
iso->buf_packets = buf_packets;
......@@ -136,7 +143,7 @@ struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
{
struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT,
data_buf_size, buf_packets,
channel, irq_interval, callback);
channel, HPSB_ISO_DMA_DEFAULT, irq_interval, callback);
if (!iso)
return NULL;
......@@ -158,12 +165,13 @@ struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
unsigned int data_buf_size,
unsigned int buf_packets,
int channel,
int dma_mode,
int irq_interval,
void (*callback)(struct hpsb_iso*))
{
struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV,
data_buf_size, buf_packets,
channel, irq_interval, callback);
channel, dma_mode, irq_interval, callback);
if (!iso)
return NULL;
......
......@@ -51,6 +51,14 @@ struct hpsb_iso_packet_info {
enum hpsb_iso_type { HPSB_ISO_RECV = 0, HPSB_ISO_XMIT = 1 };
/* The mode of the dma when receiving iso data. Must be supported by chip */
enum raw1394_iso_dma_recv_mode {
HPSB_ISO_DMA_DEFAULT = -1,
HPSB_ISO_DMA_OLD_ABI = 0,
HPSB_ISO_DMA_BUFFERFILL = 1,
HPSB_ISO_DMA_PACKET_PER_BUFFER = 2
};
struct hpsb_iso {
enum hpsb_iso_type type;
......@@ -68,6 +76,8 @@ struct hpsb_iso {
int speed; /* IEEE1394_SPEED_100, 200, or 400 */
int channel; /* -1 if multichannel */
int dma_mode; /* dma receive mode */
/* greatest # of packets between interrupts - controls
the maximum latency of the buffer */
......@@ -139,6 +149,7 @@ struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
unsigned int data_buf_size,
unsigned int buf_packets,
int channel,
int dma_mode,
int irq_interval,
void (*callback)(struct hpsb_iso*));
......
......@@ -516,8 +516,7 @@ static struct device nodemgr_dev_template_ne = {
.driver_data = &nodemgr_driverdata_ne,
};
static struct device nodemgr_dev_template_host = {
struct device nodemgr_dev_template_host = {
.bus = &ieee1394_bus_type,
.release = nodemgr_release_host,
.driver = &nodemgr_driver_host,
......@@ -1255,36 +1254,6 @@ void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver)
}
/* Searches the list of ud's that match a ne as the parent. If the ud has
* a driver associated with it, we call that driver's update function
* with the ud as the argument. */
static int nodemgr_driver_search_cb(struct device *dev, void *__data)
{
struct node_entry *ne = __data;
struct unit_directory *ud;
if (dev->driver_data == &nodemgr_driverdata_ne ||
dev->driver_data == &nodemgr_driverdata_host)
return 0;
ud = container_of(dev, struct unit_directory, device);
if (&ne->device != ud->device.parent)
return 0;
if (ud->device.driver) {
struct hpsb_protocol_driver *pdrv;
pdrv = container_of(ud->device.driver,
struct hpsb_protocol_driver, driver);
if (pdrv->update)
pdrv->update(ud);
}
return 0;
}
/*
* This function updates nodes that were present on the bus before the
* reset and still are after the reset. The nodeid and the config rom
......@@ -1480,9 +1449,24 @@ static int nodemgr_probe_ne_cb(struct device *dev, void *__data)
ne->needs_probe = 0;
return 1;
} else {
struct list_head *lh;
/* Update unit_dirs with attached drivers */
bus_for_each_dev(&ieee1394_bus_type, NULL, ne,
nodemgr_driver_search_cb);
list_for_each(lh, &dev->children) {
struct unit_directory *ud;
ud = container_of(list_to_dev(lh), struct unit_directory, device);
if (ud->device.driver) {
struct hpsb_protocol_driver *pdrv;
pdrv = container_of(ud->device.driver,
struct hpsb_protocol_driver, driver);
if (pdrv->update)
pdrv->update(ud);
}
}
}
return 0;
}
......@@ -1664,7 +1648,6 @@ static int nodemgr_host_thread(void *__hi)
allow_signal(SIGTERM);
/* Setup our device-model entries */
device_register(&host->device);
nodemgr_create_host_dev_files(host);
/* Sit and wait for a signal to probe the nodes on the bus. This
......@@ -1753,6 +1736,34 @@ struct node_entry *hpsb_nodeid_get_entry(struct hpsb_host *host, nodeid_t nodeid
return ne;
}
struct for_each_host_struct {
int (*cb)(struct hpsb_host *, void *);
void *data;
};
static int nodemgr_for_each_host_cb(struct device *dev, void *__data)
{
struct for_each_host_struct *host_data = __data;
struct hpsb_host *host;
if (dev->driver_data != &nodemgr_driverdata_host)
return 0;
host = container_of(dev, struct hpsb_host, device);
return host_data->cb(host, host_data->data);
}
int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
{
struct for_each_host_struct host_data;
host_data.cb = cb;
host_data.data = __data;
return bus_for_each_dev(&ieee1394_bus_type, NULL, &host_data, nodemgr_for_each_host_cb);
}
/* The following four convenience functions use a struct node_entry
* for addressing a node on the bus. They are intended for use by any
* process context, not just the nodemgr thread, so we need to be a
......@@ -1821,11 +1832,6 @@ static void nodemgr_add_host(struct hpsb_host *host)
init_completion(&hi->exited);
sema_init(&hi->reset_sem, 0);
memcpy(&host->device, &nodemgr_dev_template_host,
sizeof(host->device));
host->device.parent = &host->pdev->dev;
snprintf(host->device.bus_id, BUS_ID_SIZE, "fw-host%d", host->id);
sprintf(hi->daemon_name, "knodemgrd_%d", host->id);
hi->pid = kernel_thread(nodemgr_host_thread, hi, CLONE_KERNEL);
......@@ -1879,7 +1885,6 @@ static struct hpsb_highlevel nodemgr_highlevel = {
void init_ieee1394_nodemgr(void)
{
bus_register(&ieee1394_bus_type);
driver_register(&nodemgr_driver_host);
driver_register(&nodemgr_driver_ne);
......@@ -1892,5 +1897,4 @@ void cleanup_ieee1394_nodemgr(void)
driver_unregister(&nodemgr_driver_ne);
driver_unregister(&nodemgr_driver_host);
bus_unregister(&ieee1394_bus_type);
}
......@@ -219,7 +219,16 @@ int hpsb_node_lock(struct node_entry *ne, u64 addr,
int extcode, quadlet_t *data, quadlet_t arg);
/* Iterate the hosts, calling a given function with supplied data for each
* host. */
int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *));
void init_ieee1394_nodemgr(void);
void cleanup_ieee1394_nodemgr(void);
/* The template for a host device */
extern struct device nodemgr_dev_template_host;
#endif /* _IEEE1394_NODEMGR_H */
......@@ -134,7 +134,7 @@
#ifdef OHCI1394_DEBUG
#define DBGMSG(card, fmt, args...) \
printk(KERN_INFO "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
#else
#define DBGMSG(card, fmt, args...)
#endif
......@@ -158,10 +158,10 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
/* print card specific information */
#define PRINT(level, card, fmt, args...) \
printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
static char version[] __devinitdata =
"$Rev: 1045 $ Ben Collins <bcollins@debian.org>";
"$Rev: 1087 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */
static int phys_dma = 1;
......@@ -845,7 +845,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
PRINT(KERN_ERR, ohci->id,
"Transmit packet size %Zd is too big",
packet->data_size);
return 0;
return -EOVERFLOW;
}
/* Decide whether we have an iso, a request, or a response packet */
......@@ -862,7 +862,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
if (in_interrupt()) {
PRINT(KERN_ERR, ohci->id,
"legacy IT context cannot be initialized during interrupt");
return 0;
return -EINVAL;
}
if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context,
......@@ -870,7 +870,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
OHCI1394_IsoXmitContextBase) < 0) {
PRINT(KERN_ERR, ohci->id,
"error initializing legacy IT context");
return 0;
return -ENOMEM;
}
initialize_dma_trm_ctx(&ohci->it_legacy_context);
......@@ -890,7 +890,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
spin_unlock_irqrestore(&d->lock,flags);
return 1;
return 0;
}
static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
......@@ -1113,8 +1113,8 @@ struct ohci_iso_recv {
struct ohci1394_iso_tasklet task;
int task_active;
enum { BUFFER_FILL_MODE,
PACKET_PER_BUFFER_MODE } dma_mode;
enum { BUFFER_FILL_MODE = 0,
PACKET_PER_BUFFER_MODE = 1 } dma_mode;
/* memory and PCI mapping for the DMA descriptors */
struct dma_prog_region prog;
......@@ -1175,7 +1175,8 @@ static int ohci_iso_recv_init(struct hpsb_iso *iso)
/* use buffer-fill mode, unless irq_interval is 1
(note: multichannel requires buffer-fill) */
if (iso->irq_interval == 1 && iso->channel != -1) {
if (((iso->irq_interval == 1 && iso->dma_mode == HPSB_ISO_DMA_OLD_ABI) ||
iso->dma_mode == HPSB_ISO_DMA_PACKET_PER_BUFFER) && iso->channel != -1) {
recv->dma_mode = PACKET_PER_BUFFER_MODE;
} else {
recv->dma_mode = BUFFER_FILL_MODE;
......@@ -1194,8 +1195,11 @@ static int ohci_iso_recv_init(struct hpsb_iso *iso)
}
/* iso->irq_interval is in packets - translate that to blocks */
/* (err, sort of... 1 is always the safest value) */
recv->block_irq_interval = iso->irq_interval / recv->nblocks;
if (iso->irq_interval == 1)
recv->block_irq_interval = 1;
else
recv->block_irq_interval = iso->irq_interval *
((recv->nblocks+1)/iso->buf_packets);
if (recv->block_irq_interval*4 > recv->nblocks)
recv->block_irq_interval = recv->nblocks/4;
if (recv->block_irq_interval < 1)
......@@ -1205,6 +1209,10 @@ static int ohci_iso_recv_init(struct hpsb_iso *iso)
int max_packet_size;
recv->nblocks = iso->buf_packets;
recv->block_irq_interval = iso->irq_interval;
if (recv->block_irq_interval * 4 > iso->buf_packets)
recv->block_irq_interval = iso->buf_packets / 4;
if (recv->block_irq_interval < 1)
recv->block_irq_interval = 1;
/* choose a buffer stride */
......@@ -3271,7 +3279,6 @@ do { \
static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
static unsigned int card_id_counter = 0;
static int version_printed = 0;
struct hpsb_host *host;
......@@ -3282,15 +3289,14 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
PRINT_G(KERN_INFO, "%s", version);
if (pci_enable_device(dev))
FAIL(-ENXIO, "Failed to enable OHCI hardware %d",
card_id_counter++);
FAIL(-ENXIO, "Failed to enable OHCI hardware");
pci_set_master(dev);
host = hpsb_alloc_host(&ohci1394_driver, sizeof(struct ti_ohci));
host = hpsb_alloc_host(&ohci1394_driver, sizeof(struct ti_ohci), &dev->dev);
if (!host) FAIL(-ENOMEM, "Failed to allocate host structure");
ohci = host->hostdata;
ohci->id = card_id_counter++;
ohci->id = host->id;
ohci->dev = dev;
ohci->host = host;
ohci->init_state = OHCI_INIT_ALLOC_HOST;
......@@ -3462,11 +3468,14 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
static void ohci1394_pci_remove(struct pci_dev *pdev)
{
struct ti_ohci *ohci;
struct device *dev;
ohci = pci_get_drvdata(pdev);
if (!ohci)
return;
dev = get_device(&ohci->host->device);
switch (ohci->init_state) {
case OHCI_INIT_DONE:
hpsb_remove_host(ohci->host);
......@@ -3489,7 +3498,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
/* Disable IRM Contender */
set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4));
/* Clear link control register */
reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
......@@ -3521,7 +3530,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
ohci->selfid_buf_cpu,
ohci->selfid_buf_bus);
OHCI_DMA_FREE("consistent selfid_buf");
case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER:
pci_free_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
ohci->csr_config_rom_cpu,
......@@ -3555,8 +3564,10 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
case OHCI_INIT_ALLOC_HOST:
pci_set_drvdata(ohci->dev, NULL);
hpsb_unref_host(ohci->host);
}
if (dev)
put_device(dev);
}
......
......@@ -1612,7 +1612,7 @@
000658 Helmut Fischer GmbH & Co. KG
000659 EAL (Apeldoorn) B.V.
00065A Strix Systems
00065B Dell Inc.
00065B Dell Computer Corp.
00065C Malachite Technologies, Inc.
00065D Heidelberg Web Systems
00065E Photuris, Inc.
......@@ -3965,7 +3965,7 @@
00B0C2 Cisco Systems, Inc.
00B0C7 Tellabs Operations, Inc.
00B0CE TECHNOLOGY RESCUE
00B0D0 Dell Inc.
00B0D0 Dell Computer Corp.
00B0DB Nextcell, Inc.
00B0DF Reliable Data Technology, Inc.
00B0E7 British Federal Ltd.
......@@ -4054,7 +4054,7 @@
00C04C DEPARTMENT OF FOREIGN AFFAIRS
00C04D MITEC, INC.
00C04E COMTROL CORPORATION
00C04F Dell Inc.
00C04F DELL COMPUTER CORPORATION
00C050 TOYO DENKI SEIZO K.K.
00C051 ADVANCED INTEGRATION RESEARCH
00C052 BURR-BROWN
......
......@@ -521,10 +521,6 @@ static void send_next(struct ti_lynx *lynx, int what)
break;
}
if (!packet->data_be) {
pcl.buffer[1].control |= PCL_BIGENDIAN;
}
put_pcl(lynx, d->pcl, &pcl);
run_pcl(lynx, d->pcl_start, d->channel);
}
......@@ -540,7 +536,7 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
if (packet->data_size >= 4096) {
PRINT(KERN_ERR, lynx->id, "transmit packet data too big (%Zd)",
packet->data_size);
return 0;
return -EOVERFLOW;
}
switch (packet->type) {
......@@ -554,7 +550,7 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
default:
PRINT(KERN_ERR, lynx->id, "invalid packet type %d",
packet->type);
return 0;
return -EINVAL;
}
if (packet->tcode == TCODE_WRITEQ
......@@ -570,7 +566,7 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
spin_unlock_irqrestore(&d->queue_lock, flags);
return 1;
return 0;
}
......@@ -1120,7 +1116,7 @@ static ssize_t mem_read(struct file *file, char *buffer, size_t count,
retval = copy_to_user(buffer, md->lynx->mem_dma_buffer, count);
up(&md->lynx->mem_dma_mutex);
if (retval < 0) return retval;
if (retval) return -EFAULT;
*offset += count;
return count;
}
......@@ -1141,14 +1137,17 @@ static ssize_t mem_write(struct file *file, const char *buffer, size_t count,
/* FIXME: dereferencing pointers to PCI mem doesn't work everywhere */
switch (md->type) {
case aux:
copy_from_user(md->lynx->aux_port+(*offset), buffer, count);
if (copy_from_user(md->lynx->aux_port+(*offset), buffer, count))
return -EFAULT;
break;
case ram:
copy_from_user(md->lynx->local_ram+(*offset), buffer, count);
if (copy_from_user(md->lynx->local_ram+(*offset), buffer, count))
return -EFAULT;
break;
case rom:
/* the ROM may be writeable */
copy_from_user(md->lynx->local_rom+(*offset), buffer, count);
if (copy_from_user(md->lynx->local_rom+(*offset), buffer, count))
return -EFAULT;
break;
}
......@@ -1443,12 +1442,15 @@ static void iso_rcv_bh(struct ti_lynx *lynx)
static void remove_card(struct pci_dev *dev)
{
struct ti_lynx *lynx;
struct device *lynx_dev;
int i;
lynx = pci_get_drvdata(dev);
if (!lynx) return;
pci_set_drvdata(dev, NULL);
lynx_dev = get_device(&lynx->host->device);
switch (lynx->state) {
case is_host:
reg_write(lynx, PCI_INT_ENABLE, 0);
......@@ -1498,7 +1500,9 @@ static void remove_card(struct pci_dev *dev)
}
tasklet_kill(&lynx->iso_rcv.tq);
hpsb_unref_host(lynx->host);
if (lynx_dev)
put_device(lynx_dev);
}
......@@ -1535,7 +1539,7 @@ static int __devinit add_card(struct pci_dev *dev,
error = -ENOMEM;
host = hpsb_alloc_host(&lynx_driver, sizeof(struct ti_lynx));
host = hpsb_alloc_host(&lynx_driver, sizeof(struct ti_lynx), &dev->dev);
if (!host) FAIL("failed to allocate control structure memory");
lynx = host->hostdata;
......
......@@ -128,7 +128,7 @@ static void free_pending_request(struct pending_request *req)
} else if (req->free_data) {
kfree(req->data);
}
free_hpsb_packet(req->packet);
hpsb_free_packet(req->packet);
kfree(req);
}
......@@ -558,7 +558,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
lh = lh->next;
}
hi = list_entry(lh, struct host_info, list);
hpsb_ref_host(hi->host); // XXX Need to handle failure case
get_device(&hi->host->device); // XXX Need to handle failure case
list_add_tail(&fi->list, &hi->file_info_list);
fi->host = hi->host;
fi->state = connected;
......@@ -782,7 +782,7 @@ static int handle_async_request(struct file_info *fi,
packet->generation = req->req.generation;
if (!hpsb_send_packet(packet)) {
if (hpsb_send_packet(packet) < 0) {
req->req.error = RAW1394_ERROR_SEND_ERROR;
req->req.length = 0;
hpsb_free_tlabel(packet);
......@@ -823,7 +823,7 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req,
/* Update the generation of the packet just before sending. */
packet->generation = req->req.generation;
if (!hpsb_send_packet(packet)) {
if (hpsb_send_packet(packet) < 0) {
req->req.error = RAW1394_ERROR_SEND_ERROR;
queue_complete_req(req);
}
......@@ -846,7 +846,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
return sizeof(struct raw1394_request);
}
packet = alloc_hpsb_packet(req->req.length-header_length);
packet = hpsb_alloc_packet(req->req.length-header_length);
req->packet = packet;
if (!packet) return -ENOMEM;
......@@ -885,7 +885,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
/* Update the generation of the packet just before sending. */
packet->generation = req->req.generation;
if (!hpsb_send_packet(packet)) {
if (hpsb_send_packet(packet) < 0) {
req->req.error = RAW1394_ERROR_SEND_ERROR;
queue_complete_req(req);
}
......@@ -1797,6 +1797,106 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req)
return sizeof(struct raw1394_request);
}
/* Copy data from ARM buffer(s) to user buffer. */
static int arm_get_buf(struct file_info *fi, struct pending_request *req)
{
struct arm_addr *arm_addr = NULL;
unsigned long flags;
unsigned long offset;
struct list_head *entry;
DBGMSG("arm_get_buf "
"addr(Offset): %04X %08X length: %u",
(u32) ((req->req.address >> 32) & 0xFFFF),
(u32) (req->req.address & 0xFFFFFFFF),
(u32) req->req.length);
spin_lock_irqsave(&host_info_lock, flags);
entry = fi->addr_list.next;
while (entry != &(fi->addr_list)) {
arm_addr = list_entry(entry, struct arm_addr, addr_list);
if ((arm_addr->start <= req->req.address) &&
(arm_addr->end > req->req.address)) {
if (req->req.address + req->req.length <= arm_addr->end) {
offset = req->req.address - arm_addr->start;
DBGMSG("arm_get_buf copy_to_user( %08X, %08X, %u )",
(u32) req->req.recvb,
(u32) (arm_addr->addr_space_buffer+offset),
(u32) req->req.length);
if (copy_to_user(int2ptr(req->req.recvb), arm_addr->addr_space_buffer+offset, req->req.length)) {
spin_unlock_irqrestore(&host_info_lock, flags);
return (-EFAULT);
}
spin_unlock_irqrestore(&host_info_lock, flags);
free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
return sizeof(struct raw1394_request);
} else {
DBGMSG("arm_get_buf request exceeded mapping");
spin_unlock_irqrestore(&host_info_lock, flags);
return (-EINVAL);
}
}
entry = entry->next;
}
spin_unlock_irqrestore(&host_info_lock, flags);
return (-EINVAL);
}
/* Copy data from user buffer to ARM buffer(s). */
static int arm_set_buf(struct file_info *fi, struct pending_request *req)
{
struct arm_addr *arm_addr = NULL;
unsigned long flags;
unsigned long offset;
struct list_head *entry;
DBGMSG("arm_set_buf "
"addr(Offset): %04X %08X length: %u",
(u32) ((req->req.address >> 32) & 0xFFFF),
(u32) (req->req.address & 0xFFFFFFFF),
(u32) req->req.length);
spin_lock_irqsave(&host_info_lock, flags);
entry = fi->addr_list.next;
while (entry != &(fi->addr_list)) {
arm_addr = list_entry(entry, struct arm_addr, addr_list);
if ((arm_addr->start <= req->req.address) &&
(arm_addr->end > req->req.address)) {
if (req->req.address + req->req.length <= arm_addr->end) {
offset = req->req.address - arm_addr->start;
DBGMSG("arm_set_buf copy_from_user( %08X, %08X, %u )",
(u32) (arm_addr->addr_space_buffer+offset),
(u32) req->req.sendb,
(u32) req->req.length);
if (copy_from_user(arm_addr->addr_space_buffer+offset, int2ptr(req->req.sendb), req->req.length)) {
spin_unlock_irqrestore(&host_info_lock, flags);
return (-EFAULT);
}
spin_unlock_irqrestore(&host_info_lock, flags);
free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
return sizeof(struct raw1394_request);
} else {
DBGMSG("arm_set_buf request exceeded mapping");
spin_unlock_irqrestore(&host_info_lock, flags);
return (-EINVAL);
}
}
entry = entry->next;
}
spin_unlock_irqrestore(&host_info_lock, flags);
return (-EINVAL);
}
static int reset_notification(struct file_info *fi, struct pending_request *req)
{
DBGMSG("reset_notification called - switch %s ",
......@@ -1829,9 +1929,8 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req)
spin_unlock_irq(&fi->reqlists_lock);
packet->generation = req->req.generation;
retval = hpsb_send_packet(packet);
DBGMSG("write_phypacket send_packet called => retval: %d ",
retval);
if (! retval) {
DBGMSG("write_phypacket send_packet called => retval: %d ", retval);
if (retval < 0) {
req->req.error = RAW1394_ERROR_SEND_ERROR;
req->req.length = 0;
queue_complete_req(req);
......@@ -1912,6 +2011,12 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
case RAW1394_REQ_ARM_UNREGISTER:
return arm_unregister(fi, req);
case RAW1394_REQ_ARM_SET_BUF:
return arm_set_buf(fi, req);
case RAW1394_REQ_ARM_GET_BUF:
return arm_get_buf(fi, req);
case RAW1394_REQ_RESET_NOTIFY:
return reset_notification(fi, req);
......@@ -2137,6 +2242,7 @@ static int raw1394_iso_recv_init(struct file_info *fi, void *uaddr)
stat.config.data_buf_size,
stat.config.buf_packets,
stat.config.channel,
stat.config.dma_mode,
stat.config.irq_interval,
rawiso_activity_cb);
if (!fi->iso_handle)
......@@ -2489,7 +2595,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
list_del(&fi->list);
spin_unlock_irq(&host_info_lock);
hpsb_unref_host(fi->host);
put_device(&fi->host->device);
}
kfree(fi);
......
......@@ -30,6 +30,8 @@
#define RAW1394_REQ_ARM_REGISTER 300
#define RAW1394_REQ_ARM_UNREGISTER 301
#define RAW1394_REQ_ARM_SET_BUF 302
#define RAW1394_REQ_ARM_GET_BUF 303
#define RAW1394_REQ_RESET_NOTIFY 400
......@@ -149,6 +151,9 @@ struct raw1394_iso_config {
/* xmit only - iso transmission speed */
__u8 speed;
/* The mode of the dma when receiving iso data. Must be supported by chip */
__u8 dma_mode;
/* max. latency of buffer, in packets (-1 if you don't care) */
__s32 irq_interval;
};
......
......@@ -77,7 +77,7 @@
#include "sbp2.h"
static char version[] __devinitdata =
"$Rev: 1034 $ Ben Collins <bcollins@debian.org>";
"$Rev: 1082 $ Ben Collins <bcollins@debian.org>";
/*
* Module load parameter definitions
......@@ -361,38 +361,34 @@ static int sbp2util_down_timeout(atomic_t *done, int timeout)
static void sbp2_free_packet(struct hpsb_packet *packet)
{
hpsb_free_tlabel(packet);
free_hpsb_packet(packet);
hpsb_free_packet(packet);
}
/*
* This function is called to retrieve a block write packet from our
* packet pool. This function is used in place of calling
* alloc_hpsb_packet (which costs us three kmallocs). Instead we just pull
* out a free request packet and re-initialize values in it. I'm sure this
* can still stand some more optimization.
/* This is much like hpsb_node_write(), except it ignores the response
* subaction and returns immediately. Can be used from interrupts.
*/
static struct hpsb_packet *
sbp2util_allocate_write_packet(struct sbp2scsi_host_info *hi,
struct node_entry *ne, u64 addr,
size_t data_size,
quadlet_t *data)
int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr,
quadlet_t *buffer, size_t length)
{
struct hpsb_packet *packet;
packet = hpsb_make_writepacket(hi->host, ne->nodeid,
addr, data, data_size);
packet = hpsb_make_writepacket(ne->host, ne->nodeid,
addr, buffer, length);
if (!packet)
return NULL;
return -ENOMEM;
hpsb_set_packet_complete_task(packet, (void (*)(void*))sbp2_free_packet,
packet);
hpsb_node_fill_packet(ne, packet);
return packet;
}
if (hpsb_send_packet(packet) < 0) {
sbp2_free_packet(packet);
return -EIO;
}
return 0;
}
/*
* This function is called to create a pool of command orbs used for
......@@ -1734,35 +1730,26 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
*/
static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
{
struct sbp2scsi_host_info *hi = scsi_id->hi;
struct hpsb_packet *packet;
quadlet_t data;
u64 addr;
int retval;
SBP2_DEBUG("sbp2_agent_reset");
/*
* Ok, let's write to the target's management agent register
*/
data = ntohl(SBP2_AGENT_RESET_DATA);
packet = sbp2util_allocate_write_packet(hi, scsi_id->ne,
scsi_id->sbp2_command_block_agent_addr +
SBP2_AGENT_RESET_OFFSET,
4, &data);
if (!packet) {
SBP2_ERR("sbp2util_allocate_write_packet failed");
return(-ENOMEM);
}
addr = scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET;
if (!hpsb_send_packet(packet)) {
SBP2_ERR("hpsb_send_packet failed");
sbp2_free_packet(packet);
return(-EIO);
}
if (wait)
retval = hpsb_node_write(scsi_id->ne, addr, &data, 4);
else
retval = sbp2util_node_write_no_wait(scsi_id->ne, addr, &data, 4);
if (wait) {
down(&packet->state_change);
down(&packet->state_change);
if (retval < 0) {
SBP2_ERR("hpsb_node_write failed.\n");
return -EIO;
}
/*
......@@ -2032,8 +2019,9 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
struct sbp2_command_info *command)
{
struct sbp2scsi_host_info *hi = scsi_id->hi;
struct hpsb_packet *packet;
struct sbp2_command_orb *command_orb = &command->command_orb;
struct node_entry *ne = scsi_id->ne;
u64 addr;
outstanding_orb_incr;
SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x",
......@@ -2049,40 +2037,30 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
* Check to see if there are any previous orbs to use
*/
if (scsi_id->last_orb == NULL) {
quadlet_t data[2];
/*
* Ok, let's write to the target's management agent register
*/
if (hpsb_node_entry_valid(scsi_id->ne)) {
packet = sbp2util_allocate_write_packet(hi, scsi_id->ne,
scsi_id->sbp2_command_block_agent_addr +
SBP2_ORB_POINTER_OFFSET, 8, NULL);
if (!packet) {
SBP2_ERR("sbp2util_allocate_write_packet failed");
return(-ENOMEM);
}
packet->data[0] = ORB_SET_NODE_ID(hi->host->node_id);
packet->data[1] = command->command_orb_dma;
sbp2util_cpu_to_be32_buffer(packet->data, 8);
SBP2_ORB_DEBUG("write command agent, command orb %p", command_orb);
addr = scsi_id->sbp2_command_block_agent_addr + SBP2_ORB_POINTER_OFFSET;
data[0] = ORB_SET_NODE_ID(hi->host->node_id);
data[1] = command->command_orb_dma;
sbp2util_cpu_to_be32_buffer(data, 8);
if (!hpsb_send_packet(packet)) {
SBP2_ERR("hpsb_send_packet failed");
sbp2_free_packet(packet);
return(-EIO);
}
SBP2_ORB_DEBUG("write command agent, command orb %p", command_orb);
SBP2_ORB_DEBUG("write command agent complete");
if (sbp2util_node_write_no_wait(ne, addr, data, 8) < 0) {
SBP2_ERR("sbp2util_node_write_no_wait failed.\n");
return -EIO;
}
SBP2_ORB_DEBUG("write command agent complete");
scsi_id->last_orb = command_orb;
scsi_id->last_orb_dma = command->command_orb_dma;
} else {
quadlet_t data;
/*
* We have an orb already sent (maybe or maybe not
......@@ -2102,25 +2080,14 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
/*
* Ring the doorbell
*/
if (hpsb_node_entry_valid(scsi_id->ne)) {
quadlet_t data = cpu_to_be32(command->command_orb_dma);
data = cpu_to_be32(command->command_orb_dma);
addr = scsi_id->sbp2_command_block_agent_addr + SBP2_DOORBELL_OFFSET;
packet = sbp2util_allocate_write_packet(hi, scsi_id->ne,
scsi_id->sbp2_command_block_agent_addr +
SBP2_DOORBELL_OFFSET, 4, &data);
if (!packet) {
SBP2_ERR("sbp2util_allocate_write_packet failed");
return(-ENOMEM);
}
SBP2_ORB_DEBUG("ring doorbell, command orb %p", command_orb);
SBP2_ORB_DEBUG("ring doorbell, command orb %p", command_orb);
if (!hpsb_send_packet(packet)) {
SBP2_ERR("hpsb_send_packet failed");
sbp2_free_packet(packet);
return(-EIO);
}
if (sbp2util_node_write_no_wait(ne, addr, &data, 4) < 0) {
SBP2_ERR("sbp2util_node_write_no_wait failed");
return(-EIO);
}
scsi_id->last_orb = command_orb;
......
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