Commit 7b55ea65 authored by Ben Collins's avatar Ben Collins Committed by Linus Torvalds

[PATCH] IEEE-1394/Firewire updates

- Convert nodemgr to new driver model.
- Convert to new module_param() calls.
- Merged fixes for devfs mkdir and some sleep-in-atomic fixes from
  mainline 2.5-bk
- Fix possible memory corruption on highlevel local read/write.
- Fix bitmap usage for some bitops.
- Fix bug in closing ISO stream.
- Fixes for nodemgr probing in the event of a reset storm.
- Workaround for nForce2 firewire chipset. This is preliminary.
- Conversion of SBP-2 to use new driver model in nodemgr, including
  providing a driver for firewire unit directories and registering
  proper callbacks.
parent 54fa1ff0
......@@ -18,7 +18,8 @@
*/
#include <linux/string.h>
#include <linux/module.h> /* needed for MODULE_PARM */
#include <linux/module.h>
#include <linux/moduleparam.h>
#include "ieee1394_types.h"
#include "hosts.h"
......@@ -27,9 +28,10 @@
/* Module Parameters */
/* this module parameter can be used to disable mapping of the FCP registers */
MODULE_PARM(fcp,"i");
MODULE_PARM_DESC(fcp, "Map FCP registers (default = 1, disable = 0).");
static int fcp = 1;
module_param(fcp, int, 0444);
MODULE_PARM_DESC(fcp, "Map FCP registers (default = 1, disable = 0).");
static u16 csr_crc16(unsigned *data, int length)
{
......
......@@ -2919,11 +2919,7 @@ static int __init dv1394_init_module(void)
}
#ifdef CONFIG_DEVFS_FS
if (!devfs_mk_dir("ieee1394/dv")) {
printk(KERN_ERR "dv1394: unable to create /dev/ieee1394/dv\n");
ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394);
return -ENOMEM;
}
devfs_mk_dir("ieee1394/dv");
#endif
#ifdef CONFIG_PROC_FS
......
......@@ -57,6 +57,7 @@ struct hpsb_highlevel *hpsb_register_highlevel(const char *name,
list_add_tail(&hl->hl_list, &hl_drivers);
up(&hl_drivers_lock);
if (hl->op->add_host)
hl_all_hosts(hl->op->add_host);
return hl;
......@@ -98,6 +99,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl,
struct hpsb_address_serve *as;
struct list_head *entry;
int retval = 0;
unsigned long flags;
if (((start|end) & 3) || (start >= end) || (end > 0x1000000000000ULL)) {
HPSB_ERR("%s called with invalid addresses", __FUNCTION__);
......@@ -116,7 +118,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl,
as->start = start;
as->end = end;
write_lock_irq(&addr_space_lock);
write_lock_irqsave(&addr_space_lock, flags);
entry = addr_space.next;
while (list_entry(entry, struct hpsb_address_serve, as_list)->end <= start) {
......@@ -128,7 +130,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl,
}
entry = entry->next;
}
write_unlock_irq(&addr_space_lock);
write_unlock_irqrestore(&addr_space_lock, flags);
if (retval == 0) {
kfree(as);
......@@ -142,8 +144,9 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start)
int retval = 0;
struct hpsb_address_serve *as;
struct list_head *entry;
unsigned long flags;
write_lock_irq(&addr_space_lock);
write_lock_irqsave(&addr_space_lock, flags);
entry = hl->addr_list.next;
......@@ -159,7 +162,7 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start)
}
}
write_unlock_irq(&addr_space_lock);
write_unlock_irqrestore(&addr_space_lock, flags);
return retval;
}
......@@ -202,6 +205,7 @@ void highlevel_add_host(struct hpsb_host *host)
list_for_each(entry, &hl_drivers) {
hl = list_entry(entry, struct hpsb_highlevel, hl_list);
if (hl->op->add_host)
hl->op->add_host(host);
}
up(&hl_drivers_lock);
......@@ -237,48 +241,40 @@ void highlevel_host_reset(struct hpsb_host *host)
up(&hl_drivers_lock);
}
void highlevel_iso_receive(struct hpsb_host *host, quadlet_t *data,
void highlevel_iso_receive(struct hpsb_host *host, void *data,
unsigned int length)
{
struct list_head *entry;
struct hpsb_highlevel *hl;
int channel = (data[0] >> 8) & 0x3f;
int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f;
down(&hl_drivers_lock);
entry = hl_drivers.next;
while (entry != &hl_drivers) {
list_for_each(entry, &hl_drivers) {
hl = list_entry(entry, struct hpsb_highlevel, hl_list);
if (hl->op->iso_receive) {
if (hl->op->iso_receive)
hl->op->iso_receive(host, channel, data, length);
}
entry = entry->next;
}
up(&hl_drivers_lock);
}
void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
u8 *data, unsigned int length)
void *data, unsigned int length)
{
struct list_head *entry;
struct hpsb_highlevel *hl;
int cts = data[0] >> 4;
int cts = ((quadlet_t *)data)[0] >> 4;
down(&hl_drivers_lock);
entry = hl_drivers.next;
while (entry != &hl_drivers) {
list_for_each(entry, &hl_drivers) {
hl = list_entry(entry, struct hpsb_highlevel, hl_list);
if (hl->op->fcp_request) {
hl->op->fcp_request(host, nodeid, direction, cts, data,
length);
}
entry = entry->next;
if (hl->op->fcp_request)
hl->op->fcp_request(host, nodeid, direction, cts, data, length);
}
up(&hl_drivers_lock);
}
int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
int highlevel_read(struct hpsb_host *host, int nodeid, void *data,
u64 addr, unsigned int length, u16 flags)
{
struct hpsb_address_serve *as;
......@@ -295,13 +291,14 @@ int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
if (as->end > addr) {
partlength = min(as->end - addr, (u64) length);
if (as->op->read != NULL) {
rcode = as->op->read(host, nodeid, buffer,
if (as->op->read) {
rcode = as->op->read(host, nodeid, data,
addr, partlength, flags);
} else {
rcode = RCODE_TYPE_ERROR;
}
(u8 *)data += partlength;
length -= partlength;
addr += partlength;
......@@ -324,7 +321,7 @@ int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
}
int highlevel_write(struct hpsb_host *host, int nodeid, int destid,
quadlet_t *data, u64 addr, unsigned int length, u16 flags)
void *data, u64 addr, unsigned int length, u16 flags)
{
struct hpsb_address_serve *as;
struct list_head *entry;
......@@ -340,13 +337,14 @@ int highlevel_write(struct hpsb_host *host, int nodeid, int destid,
if (as->end > addr) {
partlength = min(as->end - addr, (u64) length);
if (as->op->write != NULL) {
if (as->op->write) {
rcode = as->op->write(host, nodeid, destid,
data, addr, partlength, flags);
} else {
rcode = RCODE_TYPE_ERROR;
}
(u8 *)data += partlength;
length -= partlength;
addr += partlength;
......@@ -383,7 +381,7 @@ int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
while (as->start <= addr) {
if (as->end > addr) {
if (as->op->lock != NULL) {
if (as->op->lock) {
rcode = as->op->lock(host, nodeid, store, addr,
data, arg, ext_tcode, flags);
} else {
......@@ -416,7 +414,7 @@ int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
while (as->start <= addr) {
if (as->end > addr) {
if (as->op->lock64 != NULL) {
if (as->op->lock64) {
rcode = as->op->lock64(host, nodeid, store,
addr, data, arg,
ext_tcode, flags);
......
......@@ -108,19 +108,19 @@ void highlevel_host_reset(struct hpsb_host *host);
later case, no response will be sent and the driver, that handled the request
will send the response itself.
*/
int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
int highlevel_read(struct hpsb_host *host, int nodeid, void *data,
u64 addr, unsigned int length, u16 flags);
int highlevel_write(struct hpsb_host *host, int nodeid, int destid,
quadlet_t *data, u64 addr, unsigned int length, u16 flags);
void *data, u64 addr, unsigned int length, u16 flags);
int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags);
int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags);
void highlevel_iso_receive(struct hpsb_host *host, quadlet_t *data,
void highlevel_iso_receive(struct hpsb_host *host, void *data,
unsigned int length);
void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
u8 *data, unsigned int length);
void *data, unsigned int length);
/*
......
#ifndef _IEEE1394_HOSTS_H
#define _IEEE1394_HOSTS_H
#include <linux/device.h>
#include <linux/wait.h>
#include <linux/list.h>
#include <asm/semaphore.h>
......@@ -64,6 +65,8 @@ struct hpsb_host {
struct hpsb_host_driver *driver;
struct pci_dev *pdev;
struct device device;
};
......
......@@ -46,9 +46,13 @@
#define ACKX_TIMEOUT (-4)
#define SPEED_100 0x0
#define SPEED_200 0x1
#define SPEED_400 0x2
#define SPEED_100 0x00
#define SPEED_200 0x01
#define SPEED_400 0x02
#define SPEED_800 0x03
#define SPEED_1600 0x04
#define SPEED_3200 0x05
/* Maps speed values above to a string representation */
extern const char *hpsb_speedto_str[];
......
......@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/proc_fs.h>
#include <linux/bitops.h>
#include <asm/byteorder.h>
......@@ -48,13 +49,9 @@
/*
* Disable the nodemgr detection and config rom reading functionality.
*/
MODULE_PARM(disable_nodemgr, "i");
MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
static int disable_nodemgr = 0;
MODULE_PARM(disable_hotplug, "i");
MODULE_PARM_DESC(disable_hotplug, "Disable hotplug for detected nodes.");
static int disable_hotplug = 0;
module_param(disable_nodemgr, int, 0444);
MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
/* We are GPL, so treat us special */
MODULE_LICENSE("GPL");
......@@ -62,7 +59,7 @@ MODULE_LICENSE("GPL");
static kmem_cache_t *hpsb_packet_cache;
/* Some globals used */
const char *hpsb_speedto_str[] = { "S100", "S200", "S400" };
const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" };
static void dump_packet(const char *text, quadlet_t *data, int size)
{
......@@ -130,9 +127,8 @@ struct hpsb_packet *alloc_hpsb_packet(size_t data_size)
{
struct hpsb_packet *packet = NULL;
void *data = NULL;
int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
packet = kmem_cache_alloc(hpsb_packet_cache, kmflags);
packet = kmem_cache_alloc(hpsb_packet_cache, GFP_ATOMIC);
if (packet == NULL)
return NULL;
......@@ -140,7 +136,7 @@ struct hpsb_packet *alloc_hpsb_packet(size_t data_size)
packet->header = packet->embedded_header;
if (data_size) {
data = kmalloc(data_size + 8, kmflags);
data = kmalloc(data_size + 8, GFP_ATOMIC);
if (data == NULL) {
kmem_cache_free(hpsb_packet_cache, packet);
return NULL;
......@@ -496,8 +492,7 @@ int hpsb_send_packet(struct hpsb_packet *packet)
quadlet_t *data;
size_t size=packet->data_size+packet->header_size;
int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
data = kmalloc(packet->header_size + packet->data_size, kmflags);
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;
......@@ -1120,7 +1115,7 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file)
/* follow through with the open() */
retval = file_ops->open(inode, file);
if(retval == 0) {
if (retval == 0) {
/* If the open() succeeded, then ieee1394 will be left
* with an extra module reference, so we discard it here.
......@@ -1166,7 +1161,7 @@ static int __init ieee1394_init(void)
#ifdef CONFIG_PROC_FS
/* Must be done before we start everything else, since the drivers
* may use it. */
ieee1394_procfs_entry = proc_mkdir( "ieee1394", proc_bus);
ieee1394_procfs_entry = proc_mkdir("ieee1394", proc_bus);
if (ieee1394_procfs_entry == NULL) {
HPSB_ERR("unable to create /proc/bus/ieee1394\n");
unregister_chrdev(IEEE1394_MAJOR, "ieee1394");
......@@ -1179,7 +1174,7 @@ static int __init ieee1394_init(void)
init_hpsb_highlevel();
init_csr();
if (!disable_nodemgr)
init_ieee1394_nodemgr(disable_hotplug);
init_ieee1394_nodemgr();
else
HPSB_INFO("nodemgr functionality disabled");
......@@ -1273,7 +1268,7 @@ EXPORT_SYMBOL(hpsb_node_write);
EXPORT_SYMBOL(hpsb_node_lock);
EXPORT_SYMBOL(hpsb_register_protocol);
EXPORT_SYMBOL(hpsb_unregister_protocol);
EXPORT_SYMBOL(hpsb_release_unit_directory);
EXPORT_SYMBOL(ieee1394_bus_type);
/** csr.c **/
EXPORT_SYMBOL(hpsb_update_config_rom);
......
......@@ -231,4 +231,7 @@ extern devfs_handle_t ieee1394_devfs_handle;
/* the proc_fs entry for /proc/ieee1394 */
extern struct proc_dir_entry *ieee1394_procfs_entry;
/* Our sysfs bus entry */
extern struct bus_type ieee1394_bus_type;
#endif /* _IEEE1394_CORE_H */
#ifndef _IEEE1394_HOTPLUG_H
#define _IEEE1394_HOTPLUG_H
#include <linux/device.h>
#include "ieee1394_core.h"
#include "nodemgr.h"
......@@ -31,26 +33,6 @@ struct hpsb_protocol_driver {
*/
struct ieee1394_device_id *id_table;
/*
* The probe function is called when a device is added to the
* bus and the nodemgr finds a matching entry in the drivers
* device id table or when registering this driver and a
* previously unhandled device can be handled. The driver may
* decline to handle the device based on further investigation
* of the device (or whatever reason) in which case a negative
* error code should be returned, otherwise 0 should be
* returned. The driver may use the driver_data field in the
* unit directory to store per device driver specific data.
*/
int (*probe)(struct unit_directory *ud);
/*
* The disconnect function is called when a device is removed
* from the bus or if it wasn't possible to read the guid
* after the last bus reset.
*/
void (*disconnect)(struct unit_directory *ud);
/*
* The update function is called when the node has just
* survived a bus reset, i.e. it is still present on the bus.
......@@ -59,18 +41,12 @@ struct hpsb_protocol_driver {
*/
void (*update)(struct unit_directory *ud);
/* Driver in list of all registered drivers */
struct list_head list;
/* The list of unit directories managed by this driver */
struct list_head unit_directories;
/* Our LDM structure */
struct device_driver driver;
};
int hpsb_register_protocol(struct hpsb_protocol_driver *driver);
void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver);
int hpsb_claim_unit_directory(struct unit_directory *ud,
struct hpsb_protocol_driver *driver);
void hpsb_release_unit_directory(struct unit_directory *ud);
#endif /* _IEEE1394_HOTPLUG_H */
......@@ -146,10 +146,10 @@ int hpsb_get_tlabel(struct hpsb_packet *packet, int wait)
spin_lock_irqsave(&tp->lock, flags);
packet->tlabel = find_next_zero_bit(&tp->pool, 64, tp->next);
packet->tlabel = find_next_zero_bit(tp->pool, 64, tp->next);
tp->next = (packet->tlabel + 1) % 64;
/* Should _never_ happen */
BUG_ON(test_and_set_bit(packet->tlabel, &tp->pool));
BUG_ON(test_and_set_bit(packet->tlabel, tp->pool));
tp->allocations++;
spin_unlock_irqrestore(&tp->lock, flags);
......@@ -177,7 +177,7 @@ void hpsb_free_tlabel(struct hpsb_packet *packet)
BUG_ON(packet->tlabel > 63 || packet->tlabel < 0);
spin_lock_irqsave(&tp->lock, flags);
BUG_ON(!test_and_clear_bit(packet->tlabel, &tp->pool));
BUG_ON(!test_and_clear_bit(packet->tlabel, tp->pool));
spin_unlock_irqrestore(&tp->lock, flags);
up(&tp->count);
......
......@@ -72,7 +72,7 @@
/* Transaction Label handling */
struct hpsb_tlabel_pool {
u64 pool;
DECLARE_BITMAP(pool, 64);
spinlock_t lock;
u8 next;
u32 allocations;
......@@ -81,10 +81,11 @@ struct hpsb_tlabel_pool {
#define HPSB_TPOOL_INIT(_tp) \
do { \
sema_init(&(_tp)->count, 63); \
CLEAR_BITMAP((_tp)->pool, 64); \
spin_lock_init(&(_tp)->lock); \
(_tp)->next = 0; \
(_tp)->pool = 0; \
(_tp)->allocations = 0; \
sema_init(&(_tp)->count, 63); \
} while(0)
......
......@@ -14,7 +14,7 @@
void hpsb_iso_stop(struct hpsb_iso *iso)
{
if(!iso->flags & HPSB_ISO_DRIVER_STARTED)
if (!(iso->flags & HPSB_ISO_DRIVER_STARTED))
return;
iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ?
......
This diff is collapsed.
......@@ -20,6 +20,8 @@
#ifndef _IEEE1394_NODEMGR_H
#define _IEEE1394_NODEMGR_H
#include <linux/device.h>
#define CONFIG_ROM_BUS_INFO_LENGTH(q) ((q) >> 24)
#define CONFIG_ROM_BUS_CRC_LENGTH(q) (((q) >> 16) & 0xff)
#define CONFIG_ROM_BUS_CRC(q) ((q) & 0xffff)
......@@ -76,6 +78,12 @@ struct bus_options {
u16 max_rec; /* Maximum packet size node can receive */
};
enum {
DEV_CLASS_NODE,
DEV_CLASS_UNIT_DIRECTORY,
DEV_CLASS_HOST,
};
#define UNIT_DIRECTORY_VENDOR_ID 0x01
#define UNIT_DIRECTORY_MODEL_ID 0x02
#define UNIT_DIRECTORY_SPECIFIER_ID 0x04
......@@ -87,18 +95,16 @@ struct bus_options {
* A unit directory corresponds to a protocol supported by the
* node. If a node supports eg. IP/1394 and AV/C, its config rom has a
* unit directory for each of these protocols.
*
* Unit directories appear on two types of lists: for each node we
* maintain a list of the unit directories found in its config rom and
* for each driver we maintain a list of the unit directories
* (ie. devices) the driver manages.
*/
struct unit_directory {
struct node_entry *ne; /* The node which this directory belongs to */
octlet_t address; /* Address of the unit directory on the node */
u8 flags; /* Indicates which entries were read */
quadlet_t vendor_id;
const char *vendor_name;
const char *vendor_oui;
int vendor_name_size;
quadlet_t model_id;
const char *model_name;
......@@ -106,22 +112,21 @@ struct unit_directory {
quadlet_t specifier_id;
quadlet_t version;
struct hpsb_protocol_driver *driver;
void *driver_data;
unsigned int id;
/* For linking the nodes managed by the driver, or unmanaged nodes */
struct list_head driver_list;
int length; /* Number of quadlets */
/* For linking directories belonging to a node */
struct list_head node_list;
struct device device;
int count; /* Number of quadlets */
/* XXX Must be last in the struct! */
quadlet_t quadlets[0];
};
struct node_entry {
struct list_head list;
u64 guid; /* GUID of this node */
u32 guid_vendor_id; /* Top 24bits of guid */
const char *guid_vendor_oui; /* OUI name of guid vendor id */
struct hpsb_host *host; /* Host this node is attached to */
nodeid_t nodeid; /* NodeID */
struct bus_options busopt; /* Bus Options */
......@@ -129,14 +134,16 @@ struct node_entry {
/* The following is read from the config rom */
u32 vendor_id;
const char *vendor_name;
const char *vendor_oui;
u32 capabilities;
struct list_head unit_directories;
struct hpsb_tlabel_pool *tpool;
const char *vendor_name;
char *oui_name;
struct device device;
/* XXX Must be last in the struct! */
quadlet_t quadlets[0];
};
......@@ -154,11 +161,11 @@ struct node_entry *hpsb_guid_get_entry(u64 guid);
/* Same as above, but use the nodeid to get an node entry. This is not
* fool-proof by itself, since the nodeid can change. */
struct node_entry *hpsb_nodeid_get_entry(nodeid_t nodeid);
struct node_entry *hpsb_nodeid_get_entry(struct hpsb_host *host, nodeid_t nodeid);
/* Same as above except that it will not block waiting for the nodemgr
* serialize semaphore. */
struct node_entry *hpsb_check_nodeid(nodeid_t nodeid);
struct node_entry *hpsb_check_nodeid(struct hpsb_host *host, nodeid_t nodeid);
/*
* If the entry refers to a local host, this function will return the pointer
......@@ -188,7 +195,7 @@ int hpsb_node_lock(struct node_entry *ne, u64 addr,
int extcode, quadlet_t *data, quadlet_t arg);
void init_ieee1394_nodemgr(int disable_hotplug);
void init_ieee1394_nodemgr(void);
void cleanup_ieee1394_nodemgr(void);
#endif /* _IEEE1394_NODEMGR_H */
......@@ -80,6 +80,10 @@
* Manfred Weihs <weihs@ict.tuwien.ac.at>
* . Reworked code for initiating bus resets
* (long, short, with or without hold-off)
*
* Nandu Santhi <contactnandu@users.sourceforge.net>
* . Added support for nVidia nForce2 onboard Firewire chipset
*
*/
#include <linux/config.h>
......@@ -90,6 +94,7 @@
#include <linux/wait.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <linux/fs.h>
#include <linux/poll.h>
......@@ -145,7 +150,7 @@ printk(KERN_INFO "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
#define OHCI_DMA_FREE(fmt, args...) \
HPSB_ERR("%s(%s)free(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
--global_outstanding_dmas, ## args)
u32 global_outstanding_dmas = 0;
static int global_outstanding_dmas = 0;
#else
#define OHCI_DMA_ALLOC(fmt, args...)
#define OHCI_DMA_FREE(fmt, args...)
......@@ -160,12 +165,12 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
static char version[] __devinitdata =
"$Rev: 801 $ Ben Collins <bcollins@debian.org>";
"$Rev: 858 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */
MODULE_PARM(phys_dma,"i");
MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1).");
static int phys_dma = 1;
module_param(phys_dma, int, 0644);
MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1).");
static void dma_trm_tasklet(unsigned long data);
static void dma_trm_reset(struct dma_trm_ctx *d);
......@@ -354,10 +359,10 @@ static void handle_selfid(struct ti_ohci *ohci, struct hpsb_host *host,
static void ohci_soft_reset(struct ti_ohci *ohci) {
int i;
reg_write(ohci, OHCI1394_HCControlSet, 0x00010000);
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
for (i = 0; i < OHCI_LOOP_COUNT; i++) {
if (reg_read(ohci, OHCI1394_HCControlSet) & 0x00010000)
if (!reg_read(ohci, OHCI1394_HCControlSet) & OHCI1394_HCControl_softReset)
break;
mdelay(1);
}
......@@ -514,7 +519,7 @@ static void ohci_initialize(struct ti_ohci *ohci)
reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0);
/* Enable posted writes */
reg_write(ohci, OHCI1394_HCControlSet, 0x00040000);
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_postedWriteEnable);
/* Clear link control register */
reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
......@@ -577,7 +582,7 @@ static void ohci_initialize(struct ti_ohci *ohci)
(OHCI1394_MAX_PHYS_RESP_RETRIES<<8));
/* We don't want hardware swapping */
reg_write(ohci, OHCI1394_HCControlClear, 0x40000000);
reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap);
/* Enable interrupts */
reg_write(ohci, OHCI1394_IntMaskSet,
......@@ -594,7 +599,7 @@ static void ohci_initialize(struct ti_ohci *ohci)
OHCI1394_cycleInconsistent);
/* Enable link */
reg_write(ohci, OHCI1394_HCControlSet, 0x00020000);
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
buf = reg_read(ohci, OHCI1394_Version);
PRINT(KERN_INFO, ohci->id, "OHCI-1394 %d.%d (PCI): IRQ=[%d] "
......@@ -1190,10 +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(recv->block_irq_interval*4 > recv->nblocks)
recv->block_irq_interval = recv->nblocks/4;
if(recv->block_irq_interval < 1)
recv->block_irq_interval = 1;
else if(recv->block_irq_interval*4 > recv->nblocks)
recv->block_irq_interval = recv->nblocks/4;
} else {
int max_packet_size;
......@@ -2292,14 +2298,32 @@ static void ohci_irq_handler(int irq, void *dev_id,
* avoid burying the cpu in interrupt requests. */
spin_lock_irqsave(&ohci->event_lock, flags);
reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset);
if (ohci->dev->vendor == PCI_VENDOR_ID_APPLE &&
ohci->dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW) {
if (ohci->check_busreset) {
int loop_count = 0;
udelay(10);
while(reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
while (reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
spin_unlock_irqrestore(&ohci->event_lock, flags);
udelay(10);
spin_lock_irqsave(&ohci->event_lock, flags);
/* The loop counter check is to prevent the driver
* from remaining in this state forever. For the
* initial bus reset, the loop continues for ever
* and the system hangs, until some device is plugged-in
* or out manually into a port! The forced reset seems
* to solve this problem. This mainly effects nForce2. */
if (loop_count > 10000) {
hpsb_reset_bus(host, 1);
DBGMSG(ohci->id, "Detected bus-reset loop. Forced a bus reset!");
loop_count = 0;
}
loop_count++;
}
}
spin_unlock_irqrestore(&ohci->event_lock, flags);
......@@ -2438,6 +2462,8 @@ static void ohci_irq_handler(int irq, void *dev_id,
if (event)
PRINT(KERN_ERR, ohci->id, "Unhandled interrupt(s) 0x%08x",
event);
return;
}
/* Put the buffer back into the dma context */
......@@ -3277,6 +3303,18 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->selfid_swap = 1;
#endif
#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE2_FW
#define PCI_DEVICE_ID_NVIDIA_NFORCE2_FW 0x006e
#endif
/* These chipsets require a bit of extra care when checking after
* a busreset. */
if ((dev->vendor == PCI_VENDOR_ID_APPLE &&
dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW) ||
(dev->vendor == PCI_VENDOR_ID_NVIDIA &&
dev->device == PCI_DEVICE_ID_NVIDIA_NFORCE2_FW))
ohci->check_busreset = 1;
/* We hardwire the MMIO length, since some CardBus adaptors
* fail to report the right length. Anyway, the ohci spec
* clearly says it's 2kb, so this shouldn't be a problem. */
......@@ -3363,7 +3401,7 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
* accessing registers in the SClk domain without LPS enabled
* will lock up the machine. Wait 50msec to make sure we have
* full link enabled. */
reg_write(ohci, OHCI1394_HCControlSet, 0x00080000);
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
mdelay(50);
/* Determine the number of available IR and IT contexts. */
......@@ -3489,7 +3527,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = {
{
.class = PCI_CLASS_FIREWIRE_OHCI,
.class_mask = ~0,
.class_mask = PCI_ANY_ID,
.vendor = PCI_ANY_ID,
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
......
......@@ -233,6 +233,9 @@ struct ti_ohci {
unsigned int selfid_swap:1;
/* Some Apple chipset seem to swap incoming headers for us */
unsigned int no_swap_incoming:1;
/* Force extra paranoia checking on bus-reset handling */
unsigned int check_busreset:1;
};
static inline int cross_bound(unsigned long addr, unsigned int size)
......@@ -288,6 +291,13 @@ static inline u32 reg_read(const struct ti_ohci *ohci, int offset)
#define OHCI1394_VendorID 0x040
#define OHCI1394_HCControlSet 0x050
#define OHCI1394_HCControlClear 0x054
#define OHCI1394_HCControl_noByteSwap 0x40000000
#define OHCI1394_HCControl_programPhyEnable 0x00800000
#define OHCI1394_HCControl_aPhyEnhanceEnable 0x00400000
#define OHCI1394_HCControl_LPS 0x00080000
#define OHCI1394_HCControl_postedWriteEnable 0x00040000
#define OHCI1394_HCControl_linkEnable 0x00020000
#define OHCI1394_HCControl_softReset 0x00010000
#define OHCI1394_SelfIDBuffer 0x064
#define OHCI1394_SelfIDCount 0x068
#define OHCI1394_IRMultiChanMaskHiSet 0x070
......
......@@ -37,6 +37,7 @@
#include <linux/wait.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/fs.h>
......@@ -71,8 +72,8 @@
/* Module Parameters */
MODULE_PARM(skip_eeprom,"i");
MODULE_PARM_DESC(skip_eeprom, "Do not try to read bus info block from serial eeprom, but user generic one (default = 0).");
module_param(skip_eeprom, int, 0444);
MODULE_PARM_DESC(skip_eeprom, "Use generic bus info block instead of serial eeprom (default = 0).");
static int skip_eeprom = 0;
......@@ -983,8 +984,9 @@ loff_t mem_llseek(struct file *file, loff_t offs, int orig)
* on performance - the value 2400 was found by experiment and may not work
* everywhere as good as here - use mem_mindma option for modules to change
*/
short mem_mindma = 2400;
MODULE_PARM(mem_mindma, "h");
static short mem_mindma = 2400;
module_param(mem_mindma, short, 0444);
MODULE_PARM_DESC(mem_mindma, "Minimum amount of data required to use DMA");
static ssize_t mem_dmaread(struct memdata *md, u32 physbuf, ssize_t count,
int offset)
......
This diff is collapsed.
......@@ -238,7 +238,7 @@ struct sbp2_status_block {
*/
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
#define SBP2SCSI_MAX_SCSI_IDS 16 /* Max sbp2 device instances supported */
#define SBP2SCSI_MAX_SCSI_IDS 32 /* Max sbp2 device instances supported */
#define SBP2_MAX_SECTORS 255 /* Max sectors supported */
#ifndef TYPE_SDAD
......@@ -320,6 +320,10 @@ struct sbp2_command_info {
#define SBP2_BREAKAGE_128K_MAX_TRANSFER 0x1
#define SBP2_BREAKAGE_INQUIRY_HACK 0x2
struct sbp2scsi_host_info;
/*
* Information needed on a per scsi id basis (one for each sbp2 device)
*/
......@@ -375,6 +379,9 @@ struct scsi_id_instance_data {
/* Node entry, as retrieved from NodeMgr entries */
struct node_entry *ne;
/* A backlink to our host_info */
struct sbp2scsi_host_info *hi;
/* Device specific workarounds/brokeness */
u32 workarounds;
};
......@@ -406,7 +413,6 @@ struct sbp2scsi_host_info {
* SCSI ID instance data (one for each sbp2 device instance possible)
*/
struct scsi_id_instance_data *scsi_id[SBP2SCSI_MAX_SCSI_IDS];
};
/*
......@@ -416,30 +422,30 @@ struct sbp2scsi_host_info {
/*
* Various utility prototypes
*/
static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id, struct sbp2scsi_host_info *hi);
static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id, struct sbp2scsi_host_info *hi);
static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id);
static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id);
static struct sbp2_command_info *sbp2util_find_command_for_orb(struct scsi_id_instance_data *scsi_id, dma_addr_t orb);
static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt);
static struct sbp2_command_info *sbp2util_allocate_command_orb(struct scsi_id_instance_data *scsi_id,
Scsi_Cmnd *Current_SCpnt,
void (*Current_done)(Scsi_Cmnd *),
struct sbp2scsi_host_info *hi);
void (*Current_done)(Scsi_Cmnd *));
static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
struct sbp2_command_info *command);
/*
* IEEE-1394 core driver related prototypes
*/
static void sbp2_add_host(struct hpsb_host *host);
static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host);
static struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host);
static void sbp2_remove_host(struct hpsb_host *host);
static int sbp2_probe(struct unit_directory *ud);
static void sbp2_disconnect(struct unit_directory *ud);
static int sbp2_probe(struct device *dev);
static int sbp2_remove(struct device *dev);
static void sbp2_update(struct unit_directory *ud);
static int sbp2_start_device(struct sbp2scsi_host_info *hi,
struct unit_directory *ud);
static void sbp2_remove_device(struct sbp2scsi_host_info *hi,
struct scsi_id_instance_data *scsi_id);
static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id);
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data,
......@@ -451,29 +457,28 @@ static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_
/*
* SBP-2 protocol related prototypes
*/
static int sbp2_login_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
static int sbp2_reconnect_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
static int sbp2_logout_device(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
static int sbp2_login_device(struct scsi_id_instance_data *scsi_id);
static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id);
static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id);
static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
quadlet_t *data, u64 addr, unsigned int length, u16 flags);
static int sbp2_agent_reset(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id, int wait);
static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi,
struct scsi_id_instance_data *scsi_id,
static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait);
static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
struct sbp2_command_info *command,
unchar *scsi_cmd,
unsigned int scsi_use_sg,
unsigned int scsi_request_bufflen,
void *scsi_request_buffer,
unsigned char scsi_dir);
static int sbp2_link_orb_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
struct sbp2_command_info *command);
static int sbp2_send_command(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data);
static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd);
static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, Scsi_Cmnd *SCpnt);
static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id);
static int sbp2_set_busy_timeout(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
static int sbp2_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id);
static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id);
#endif /* SBP2_H */
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