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 @@ ...@@ -18,7 +18,8 @@
*/ */
#include <linux/string.h> #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 "ieee1394_types.h"
#include "hosts.h" #include "hosts.h"
...@@ -27,9 +28,10 @@ ...@@ -27,9 +28,10 @@
/* Module Parameters */ /* Module Parameters */
/* this module parameter can be used to disable mapping of the FCP registers */ /* 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; 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) static u16 csr_crc16(unsigned *data, int length)
{ {
......
...@@ -2919,11 +2919,7 @@ static int __init dv1394_init_module(void) ...@@ -2919,11 +2919,7 @@ static int __init dv1394_init_module(void)
} }
#ifdef CONFIG_DEVFS_FS #ifdef CONFIG_DEVFS_FS
if (!devfs_mk_dir("ieee1394/dv")) { 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;
}
#endif #endif
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
......
...@@ -57,7 +57,8 @@ struct hpsb_highlevel *hpsb_register_highlevel(const char *name, ...@@ -57,7 +57,8 @@ struct hpsb_highlevel *hpsb_register_highlevel(const char *name,
list_add_tail(&hl->hl_list, &hl_drivers); list_add_tail(&hl->hl_list, &hl_drivers);
up(&hl_drivers_lock); up(&hl_drivers_lock);
hl_all_hosts(hl->op->add_host); if (hl->op->add_host)
hl_all_hosts(hl->op->add_host);
return hl; return hl;
} }
...@@ -98,6 +99,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, ...@@ -98,6 +99,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl,
struct hpsb_address_serve *as; struct hpsb_address_serve *as;
struct list_head *entry; struct list_head *entry;
int retval = 0; int retval = 0;
unsigned long flags;
if (((start|end) & 3) || (start >= end) || (end > 0x1000000000000ULL)) { if (((start|end) & 3) || (start >= end) || (end > 0x1000000000000ULL)) {
HPSB_ERR("%s called with invalid addresses", __FUNCTION__); HPSB_ERR("%s called with invalid addresses", __FUNCTION__);
...@@ -116,7 +118,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, ...@@ -116,7 +118,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl,
as->start = start; as->start = start;
as->end = end; as->end = end;
write_lock_irq(&addr_space_lock); write_lock_irqsave(&addr_space_lock, flags);
entry = addr_space.next; entry = addr_space.next;
while (list_entry(entry, struct hpsb_address_serve, as_list)->end <= start) { while (list_entry(entry, struct hpsb_address_serve, as_list)->end <= start) {
...@@ -128,7 +130,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, ...@@ -128,7 +130,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl,
} }
entry = entry->next; entry = entry->next;
} }
write_unlock_irq(&addr_space_lock); write_unlock_irqrestore(&addr_space_lock, flags);
if (retval == 0) { if (retval == 0) {
kfree(as); kfree(as);
...@@ -142,8 +144,9 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start) ...@@ -142,8 +144,9 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start)
int retval = 0; int retval = 0;
struct hpsb_address_serve *as; struct hpsb_address_serve *as;
struct list_head *entry; 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; entry = hl->addr_list.next;
...@@ -159,7 +162,7 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start) ...@@ -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; return retval;
} }
...@@ -202,7 +205,8 @@ void highlevel_add_host(struct hpsb_host *host) ...@@ -202,7 +205,8 @@ void highlevel_add_host(struct hpsb_host *host)
list_for_each(entry, &hl_drivers) { list_for_each(entry, &hl_drivers) {
hl = list_entry(entry, struct hpsb_highlevel, hl_list); hl = list_entry(entry, struct hpsb_highlevel, hl_list);
hl->op->add_host(host); if (hl->op->add_host)
hl->op->add_host(host);
} }
up(&hl_drivers_lock); up(&hl_drivers_lock);
} }
...@@ -237,48 +241,40 @@ void highlevel_host_reset(struct hpsb_host *host) ...@@ -237,48 +241,40 @@ void highlevel_host_reset(struct hpsb_host *host)
up(&hl_drivers_lock); 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) unsigned int length)
{ {
struct list_head *entry; struct list_head *entry;
struct hpsb_highlevel *hl; struct hpsb_highlevel *hl;
int channel = (data[0] >> 8) & 0x3f; int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f;
down(&hl_drivers_lock); down(&hl_drivers_lock);
entry = hl_drivers.next; list_for_each(entry, &hl_drivers) {
while (entry != &hl_drivers) {
hl = list_entry(entry, struct hpsb_highlevel, hl_list); 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); hl->op->iso_receive(host, channel, data, length);
}
entry = entry->next;
} }
up(&hl_drivers_lock); up(&hl_drivers_lock);
} }
void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction, 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 list_head *entry;
struct hpsb_highlevel *hl; struct hpsb_highlevel *hl;
int cts = data[0] >> 4; int cts = ((quadlet_t *)data)[0] >> 4;
down(&hl_drivers_lock); down(&hl_drivers_lock);
entry = hl_drivers.next; list_for_each(entry, &hl_drivers) {
while (entry != &hl_drivers) {
hl = list_entry(entry, struct hpsb_highlevel, hl_list); hl = list_entry(entry, struct hpsb_highlevel, hl_list);
if (hl->op->fcp_request) { if (hl->op->fcp_request)
hl->op->fcp_request(host, nodeid, direction, cts, data, hl->op->fcp_request(host, nodeid, direction, cts, data, length);
length);
}
entry = entry->next;
} }
up(&hl_drivers_lock); 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) u64 addr, unsigned int length, u16 flags)
{ {
struct hpsb_address_serve *as; struct hpsb_address_serve *as;
...@@ -295,13 +291,14 @@ int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer, ...@@ -295,13 +291,14 @@ int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
if (as->end > addr) { if (as->end > addr) {
partlength = min(as->end - addr, (u64) length); partlength = min(as->end - addr, (u64) length);
if (as->op->read != NULL) { if (as->op->read) {
rcode = as->op->read(host, nodeid, buffer, rcode = as->op->read(host, nodeid, data,
addr, partlength, flags); addr, partlength, flags);
} else { } else {
rcode = RCODE_TYPE_ERROR; rcode = RCODE_TYPE_ERROR;
} }
(u8 *)data += partlength;
length -= partlength; length -= partlength;
addr += partlength; addr += partlength;
...@@ -324,7 +321,7 @@ int highlevel_read(struct hpsb_host *host, int nodeid, quadlet_t *buffer, ...@@ -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, 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 hpsb_address_serve *as;
struct list_head *entry; struct list_head *entry;
...@@ -340,13 +337,14 @@ int highlevel_write(struct hpsb_host *host, int nodeid, int destid, ...@@ -340,13 +337,14 @@ int highlevel_write(struct hpsb_host *host, int nodeid, int destid,
if (as->end > addr) { if (as->end > addr) {
partlength = min(as->end - addr, (u64) length); partlength = min(as->end - addr, (u64) length);
if (as->op->write != NULL) { if (as->op->write) {
rcode = as->op->write(host, nodeid, destid, rcode = as->op->write(host, nodeid, destid,
data, addr, partlength, flags); data, addr, partlength, flags);
} else { } else {
rcode = RCODE_TYPE_ERROR; rcode = RCODE_TYPE_ERROR;
} }
(u8 *)data += partlength;
length -= partlength; length -= partlength;
addr += partlength; addr += partlength;
...@@ -383,7 +381,7 @@ int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, ...@@ -383,7 +381,7 @@ int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
while (as->start <= addr) { while (as->start <= addr) {
if (as->end > addr) { if (as->end > addr) {
if (as->op->lock != NULL) { if (as->op->lock) {
rcode = as->op->lock(host, nodeid, store, addr, rcode = as->op->lock(host, nodeid, store, addr,
data, arg, ext_tcode, flags); data, arg, ext_tcode, flags);
} else { } else {
...@@ -416,7 +414,7 @@ int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store, ...@@ -416,7 +414,7 @@ int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
while (as->start <= addr) { while (as->start <= addr) {
if (as->end > addr) { if (as->end > addr) {
if (as->op->lock64 != NULL) { if (as->op->lock64) {
rcode = as->op->lock64(host, nodeid, store, rcode = as->op->lock64(host, nodeid, store,
addr, data, arg, addr, data, arg,
ext_tcode, flags); ext_tcode, flags);
......
...@@ -108,19 +108,19 @@ void highlevel_host_reset(struct hpsb_host *host); ...@@ -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 later case, no response will be sent and the driver, that handled the request
will send the response itself. 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); u64 addr, unsigned int length, u16 flags);
int highlevel_write(struct hpsb_host *host, int nodeid, int destid, 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, 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); 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, 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); 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); unsigned int length);
void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction, 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 #ifndef _IEEE1394_HOSTS_H
#define _IEEE1394_HOSTS_H #define _IEEE1394_HOSTS_H
#include <linux/device.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/list.h> #include <linux/list.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
...@@ -64,6 +65,8 @@ struct hpsb_host { ...@@ -64,6 +65,8 @@ struct hpsb_host {
struct hpsb_host_driver *driver; struct hpsb_host_driver *driver;
struct pci_dev *pdev; struct pci_dev *pdev;
struct device device;
}; };
......
...@@ -46,9 +46,13 @@ ...@@ -46,9 +46,13 @@
#define ACKX_TIMEOUT (-4) #define ACKX_TIMEOUT (-4)
#define SPEED_100 0x0 #define SPEED_100 0x00
#define SPEED_200 0x1 #define SPEED_200 0x01
#define SPEED_400 0x2 #define SPEED_400 0x02
#define SPEED_800 0x03
#define SPEED_1600 0x04
#define SPEED_3200 0x05
/* Maps speed values above to a string representation */ /* Maps speed values above to a string representation */
extern const char *hpsb_speedto_str[]; extern const char *hpsb_speedto_str[];
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
...@@ -48,13 +49,9 @@ ...@@ -48,13 +49,9 @@
/* /*
* Disable the nodemgr detection and config rom reading functionality. * 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; static int disable_nodemgr = 0;
module_param(disable_nodemgr, int, 0444);
MODULE_PARM(disable_hotplug, "i"); MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
MODULE_PARM_DESC(disable_hotplug, "Disable hotplug for detected nodes.");
static int disable_hotplug = 0;
/* We are GPL, so treat us special */ /* We are GPL, so treat us special */
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -62,7 +59,7 @@ MODULE_LICENSE("GPL"); ...@@ -62,7 +59,7 @@ MODULE_LICENSE("GPL");
static kmem_cache_t *hpsb_packet_cache; static kmem_cache_t *hpsb_packet_cache;
/* Some globals used */ /* 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) 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) ...@@ -130,9 +127,8 @@ struct hpsb_packet *alloc_hpsb_packet(size_t data_size)
{ {
struct hpsb_packet *packet = NULL; struct hpsb_packet *packet = NULL;
void *data = 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) if (packet == NULL)
return NULL; return NULL;
...@@ -140,7 +136,7 @@ struct hpsb_packet *alloc_hpsb_packet(size_t data_size) ...@@ -140,7 +136,7 @@ struct hpsb_packet *alloc_hpsb_packet(size_t data_size)
packet->header = packet->embedded_header; packet->header = packet->embedded_header;
if (data_size) { if (data_size) {
data = kmalloc(data_size + 8, kmflags); data = kmalloc(data_size + 8, GFP_ATOMIC);
if (data == NULL) { if (data == NULL) {
kmem_cache_free(hpsb_packet_cache, packet); kmem_cache_free(hpsb_packet_cache, packet);
return NULL; return NULL;
...@@ -496,8 +492,7 @@ int hpsb_send_packet(struct hpsb_packet *packet) ...@@ -496,8 +492,7 @@ int hpsb_send_packet(struct hpsb_packet *packet)
quadlet_t *data; quadlet_t *data;
size_t size=packet->data_size+packet->header_size; 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, GFP_ATOMIC);
data = kmalloc(packet->header_size + packet->data_size, kmflags);
if (!data) { if (!data) {
HPSB_ERR("unable to allocate memory for concatenating header and data"); HPSB_ERR("unable to allocate memory for concatenating header and data");
return 0; return 0;
...@@ -1120,7 +1115,7 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file) ...@@ -1120,7 +1115,7 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file)
/* follow through with the open() */ /* follow through with the open() */
retval = file_ops->open(inode, file); retval = file_ops->open(inode, file);
if(retval == 0) { if (retval == 0) {
/* If the open() succeeded, then ieee1394 will be left /* If the open() succeeded, then ieee1394 will be left
* with an extra module reference, so we discard it here. * with an extra module reference, so we discard it here.
...@@ -1166,7 +1161,7 @@ static int __init ieee1394_init(void) ...@@ -1166,7 +1161,7 @@ static int __init ieee1394_init(void)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
/* Must be done before we start everything else, since the drivers /* Must be done before we start everything else, since the drivers
* may use it. */ * may use it. */
ieee1394_procfs_entry = proc_mkdir( "ieee1394", proc_bus); ieee1394_procfs_entry = proc_mkdir("ieee1394", proc_bus);
if (ieee1394_procfs_entry == NULL) { if (ieee1394_procfs_entry == NULL) {
HPSB_ERR("unable to create /proc/bus/ieee1394\n"); HPSB_ERR("unable to create /proc/bus/ieee1394\n");
unregister_chrdev(IEEE1394_MAJOR, "ieee1394"); unregister_chrdev(IEEE1394_MAJOR, "ieee1394");
...@@ -1179,7 +1174,7 @@ static int __init ieee1394_init(void) ...@@ -1179,7 +1174,7 @@ static int __init ieee1394_init(void)
init_hpsb_highlevel(); init_hpsb_highlevel();
init_csr(); init_csr();
if (!disable_nodemgr) if (!disable_nodemgr)
init_ieee1394_nodemgr(disable_hotplug); init_ieee1394_nodemgr();
else else
HPSB_INFO("nodemgr functionality disabled"); HPSB_INFO("nodemgr functionality disabled");
...@@ -1273,7 +1268,7 @@ EXPORT_SYMBOL(hpsb_node_write); ...@@ -1273,7 +1268,7 @@ EXPORT_SYMBOL(hpsb_node_write);
EXPORT_SYMBOL(hpsb_node_lock); EXPORT_SYMBOL(hpsb_node_lock);
EXPORT_SYMBOL(hpsb_register_protocol); EXPORT_SYMBOL(hpsb_register_protocol);
EXPORT_SYMBOL(hpsb_unregister_protocol); EXPORT_SYMBOL(hpsb_unregister_protocol);
EXPORT_SYMBOL(hpsb_release_unit_directory); EXPORT_SYMBOL(ieee1394_bus_type);
/** csr.c **/ /** csr.c **/
EXPORT_SYMBOL(hpsb_update_config_rom); EXPORT_SYMBOL(hpsb_update_config_rom);
......
...@@ -231,4 +231,7 @@ extern devfs_handle_t ieee1394_devfs_handle; ...@@ -231,4 +231,7 @@ extern devfs_handle_t ieee1394_devfs_handle;
/* the proc_fs entry for /proc/ieee1394 */ /* the proc_fs entry for /proc/ieee1394 */
extern struct proc_dir_entry *ieee1394_procfs_entry; extern struct proc_dir_entry *ieee1394_procfs_entry;
/* Our sysfs bus entry */
extern struct bus_type ieee1394_bus_type;
#endif /* _IEEE1394_CORE_H */ #endif /* _IEEE1394_CORE_H */
#ifndef _IEEE1394_HOTPLUG_H #ifndef _IEEE1394_HOTPLUG_H
#define _IEEE1394_HOTPLUG_H #define _IEEE1394_HOTPLUG_H
#include <linux/device.h>
#include "ieee1394_core.h" #include "ieee1394_core.h"
#include "nodemgr.h" #include "nodemgr.h"
...@@ -31,26 +33,6 @@ struct hpsb_protocol_driver { ...@@ -31,26 +33,6 @@ struct hpsb_protocol_driver {
*/ */
struct ieee1394_device_id *id_table; 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 * The update function is called when the node has just
* survived a bus reset, i.e. it is still present on the bus. * survived a bus reset, i.e. it is still present on the bus.
...@@ -59,18 +41,12 @@ struct hpsb_protocol_driver { ...@@ -59,18 +41,12 @@ struct hpsb_protocol_driver {
*/ */
void (*update)(struct unit_directory *ud); 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 */ /* Our LDM structure */
struct list_head unit_directories; struct device_driver driver;
}; };
int hpsb_register_protocol(struct hpsb_protocol_driver *driver); int hpsb_register_protocol(struct hpsb_protocol_driver *driver);
void hpsb_unregister_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 */ #endif /* _IEEE1394_HOTPLUG_H */
...@@ -146,10 +146,10 @@ int hpsb_get_tlabel(struct hpsb_packet *packet, int wait) ...@@ -146,10 +146,10 @@ int hpsb_get_tlabel(struct hpsb_packet *packet, int wait)
spin_lock_irqsave(&tp->lock, flags); 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; tp->next = (packet->tlabel + 1) % 64;
/* Should _never_ happen */ /* 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++; tp->allocations++;
spin_unlock_irqrestore(&tp->lock, flags); spin_unlock_irqrestore(&tp->lock, flags);
...@@ -177,7 +177,7 @@ void hpsb_free_tlabel(struct hpsb_packet *packet) ...@@ -177,7 +177,7 @@ void hpsb_free_tlabel(struct hpsb_packet *packet)
BUG_ON(packet->tlabel > 63 || packet->tlabel < 0); BUG_ON(packet->tlabel > 63 || packet->tlabel < 0);
spin_lock_irqsave(&tp->lock, flags); 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); spin_unlock_irqrestore(&tp->lock, flags);
up(&tp->count); up(&tp->count);
......
...@@ -72,19 +72,20 @@ ...@@ -72,19 +72,20 @@
/* Transaction Label handling */ /* Transaction Label handling */
struct hpsb_tlabel_pool { struct hpsb_tlabel_pool {
u64 pool; DECLARE_BITMAP(pool, 64);
spinlock_t lock; spinlock_t lock;
u8 next; u8 next;
u32 allocations; u32 allocations;
struct semaphore count; struct semaphore count;
}; };
#define HPSB_TPOOL_INIT(_tp) \ #define HPSB_TPOOL_INIT(_tp) \
do { \ do { \
sema_init(&(_tp)->count, 63); \ CLEAR_BITMAP((_tp)->pool, 64); \
spin_lock_init(&(_tp)->lock); \ spin_lock_init(&(_tp)->lock); \
(_tp)->next = 0; \ (_tp)->next = 0; \
(_tp)->pool = 0; \ (_tp)->allocations = 0; \
sema_init(&(_tp)->count, 63); \
} while(0) } while(0)
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
void hpsb_iso_stop(struct hpsb_iso *iso) void hpsb_iso_stop(struct hpsb_iso *iso)
{ {
if(!iso->flags & HPSB_ISO_DRIVER_STARTED) if (!(iso->flags & HPSB_ISO_DRIVER_STARTED))
return; return;
iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ? iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ?
......
This diff is collapsed.
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#ifndef _IEEE1394_NODEMGR_H #ifndef _IEEE1394_NODEMGR_H
#define _IEEE1394_NODEMGR_H #define _IEEE1394_NODEMGR_H
#include <linux/device.h>
#define CONFIG_ROM_BUS_INFO_LENGTH(q) ((q) >> 24) #define CONFIG_ROM_BUS_INFO_LENGTH(q) ((q) >> 24)
#define CONFIG_ROM_BUS_CRC_LENGTH(q) (((q) >> 16) & 0xff) #define CONFIG_ROM_BUS_CRC_LENGTH(q) (((q) >> 16) & 0xff)
#define CONFIG_ROM_BUS_CRC(q) ((q) & 0xffff) #define CONFIG_ROM_BUS_CRC(q) ((q) & 0xffff)
...@@ -76,6 +78,12 @@ struct bus_options { ...@@ -76,6 +78,12 @@ struct bus_options {
u16 max_rec; /* Maximum packet size node can receive */ 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_VENDOR_ID 0x01
#define UNIT_DIRECTORY_MODEL_ID 0x02 #define UNIT_DIRECTORY_MODEL_ID 0x02
#define UNIT_DIRECTORY_SPECIFIER_ID 0x04 #define UNIT_DIRECTORY_SPECIFIER_ID 0x04
...@@ -87,18 +95,16 @@ struct bus_options { ...@@ -87,18 +95,16 @@ struct bus_options {
* A unit directory corresponds to a protocol supported by the * 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 * node. If a node supports eg. IP/1394 and AV/C, its config rom has a
* unit directory for each of these protocols. * 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 unit_directory {
struct node_entry *ne; /* The node which this directory belongs to */ struct node_entry *ne; /* The node which this directory belongs to */
octlet_t address; /* Address of the unit directory on the node */ octlet_t address; /* Address of the unit directory on the node */
u8 flags; /* Indicates which entries were read */ u8 flags; /* Indicates which entries were read */
quadlet_t vendor_id; quadlet_t vendor_id;
const char *vendor_name; const char *vendor_name;
const char *vendor_oui;
int vendor_name_size; int vendor_name_size;
quadlet_t model_id; quadlet_t model_id;
const char *model_name; const char *model_name;
...@@ -106,22 +112,21 @@ struct unit_directory { ...@@ -106,22 +112,21 @@ struct unit_directory {
quadlet_t specifier_id; quadlet_t specifier_id;
quadlet_t version; quadlet_t version;
struct hpsb_protocol_driver *driver; unsigned int id;
void *driver_data;
/* For linking the nodes managed by the driver, or unmanaged nodes */ int length; /* Number of quadlets */
struct list_head driver_list;
/* For linking directories belonging to a node */ struct device device;
struct list_head node_list;
int count; /* Number of quadlets */ /* XXX Must be last in the struct! */
quadlet_t quadlets[0]; quadlet_t quadlets[0];
}; };
struct node_entry { struct node_entry {
struct list_head list;
u64 guid; /* GUID of this node */ 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 */ struct hpsb_host *host; /* Host this node is attached to */
nodeid_t nodeid; /* NodeID */ nodeid_t nodeid; /* NodeID */
struct bus_options busopt; /* Bus Options */ struct bus_options busopt; /* Bus Options */
...@@ -129,14 +134,16 @@ struct node_entry { ...@@ -129,14 +134,16 @@ struct node_entry {
/* The following is read from the config rom */ /* The following is read from the config rom */
u32 vendor_id; u32 vendor_id;
const char *vendor_name;
const char *vendor_oui;
u32 capabilities; u32 capabilities;
struct list_head unit_directories;
struct hpsb_tlabel_pool *tpool; struct hpsb_tlabel_pool *tpool;
const char *vendor_name; struct device device;
char *oui_name;
/* XXX Must be last in the struct! */
quadlet_t quadlets[0]; quadlet_t quadlets[0];
}; };
...@@ -154,11 +161,11 @@ struct node_entry *hpsb_guid_get_entry(u64 guid); ...@@ -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 /* Same as above, but use the nodeid to get an node entry. This is not
* fool-proof by itself, since the nodeid can change. */ * 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 /* Same as above except that it will not block waiting for the nodemgr
* serialize semaphore. */ * 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 * 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, ...@@ -188,7 +195,7 @@ int hpsb_node_lock(struct node_entry *ne, u64 addr,
int extcode, quadlet_t *data, quadlet_t arg); 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); void cleanup_ieee1394_nodemgr(void);
#endif /* _IEEE1394_NODEMGR_H */ #endif /* _IEEE1394_NODEMGR_H */
...@@ -80,6 +80,10 @@ ...@@ -80,6 +80,10 @@
* Manfred Weihs <weihs@ict.tuwien.ac.at> * Manfred Weihs <weihs@ict.tuwien.ac.at>
* . Reworked code for initiating bus resets * . Reworked code for initiating bus resets
* (long, short, with or without hold-off) * (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> #include <linux/config.h>
...@@ -90,6 +94,7 @@ ...@@ -90,6 +94,7 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/poll.h> #include <linux/poll.h>
...@@ -145,7 +150,7 @@ printk(KERN_INFO "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args) ...@@ -145,7 +150,7 @@ printk(KERN_INFO "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
#define OHCI_DMA_FREE(fmt, args...) \ #define OHCI_DMA_FREE(fmt, args...) \
HPSB_ERR("%s(%s)free(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \ HPSB_ERR("%s(%s)free(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
--global_outstanding_dmas, ## args) --global_outstanding_dmas, ## args)
u32 global_outstanding_dmas = 0; static int global_outstanding_dmas = 0;
#else #else
#define OHCI_DMA_ALLOC(fmt, args...) #define OHCI_DMA_ALLOC(fmt, args...)
#define OHCI_DMA_FREE(fmt, args...) #define OHCI_DMA_FREE(fmt, args...)
...@@ -160,12 +165,12 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## 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) printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
static char version[] __devinitdata = static char version[] __devinitdata =
"$Rev: 801 $ Ben Collins <bcollins@debian.org>"; "$Rev: 858 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */ /* Module Parameters */
MODULE_PARM(phys_dma,"i");
MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1).");
static int phys_dma = 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_tasklet(unsigned long data);
static void dma_trm_reset(struct dma_trm_ctx *d); 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, ...@@ -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) { static void ohci_soft_reset(struct ti_ohci *ohci) {
int i; int i;
reg_write(ohci, OHCI1394_HCControlSet, 0x00010000); reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
for (i = 0; i < OHCI_LOOP_COUNT; i++) { 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; break;
mdelay(1); mdelay(1);
} }
...@@ -514,7 +519,7 @@ static void ohci_initialize(struct ti_ohci *ohci) ...@@ -514,7 +519,7 @@ static void ohci_initialize(struct ti_ohci *ohci)
reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0); reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0);
/* Enable posted writes */ /* Enable posted writes */
reg_write(ohci, OHCI1394_HCControlSet, 0x00040000); reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_postedWriteEnable);
/* Clear link control register */ /* Clear link control register */
reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff); reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
...@@ -577,7 +582,7 @@ static void ohci_initialize(struct ti_ohci *ohci) ...@@ -577,7 +582,7 @@ static void ohci_initialize(struct ti_ohci *ohci)
(OHCI1394_MAX_PHYS_RESP_RETRIES<<8)); (OHCI1394_MAX_PHYS_RESP_RETRIES<<8));
/* We don't want hardware swapping */ /* We don't want hardware swapping */
reg_write(ohci, OHCI1394_HCControlClear, 0x40000000); reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap);
/* Enable interrupts */ /* Enable interrupts */
reg_write(ohci, OHCI1394_IntMaskSet, reg_write(ohci, OHCI1394_IntMaskSet,
...@@ -594,7 +599,7 @@ static void ohci_initialize(struct ti_ohci *ohci) ...@@ -594,7 +599,7 @@ static void ohci_initialize(struct ti_ohci *ohci)
OHCI1394_cycleInconsistent); OHCI1394_cycleInconsistent);
/* Enable link */ /* Enable link */
reg_write(ohci, OHCI1394_HCControlSet, 0x00020000); reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
buf = reg_read(ohci, OHCI1394_Version); buf = reg_read(ohci, OHCI1394_Version);
PRINT(KERN_INFO, ohci->id, "OHCI-1394 %d.%d (PCI): IRQ=[%d] " 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) ...@@ -1190,10 +1195,11 @@ static int ohci_iso_recv_init(struct hpsb_iso *iso)
/* iso->irq_interval is in packets - translate that to blocks */ /* iso->irq_interval is in packets - translate that to blocks */
/* (err, sort of... 1 is always the safest value) */ /* (err, sort of... 1 is always the safest value) */
recv->block_irq_interval = iso->irq_interval / recv->nblocks; 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) if(recv->block_irq_interval < 1)
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 { } else {
int max_packet_size; int max_packet_size;
...@@ -2291,17 +2297,35 @@ static void ohci_irq_handler(int irq, void *dev_id, ...@@ -2291,17 +2297,35 @@ static void ohci_irq_handler(int irq, void *dev_id,
* selfID phase, so we disable busReset interrupts, to * selfID phase, so we disable busReset interrupts, to
* avoid burying the cpu in interrupt requests. */ * avoid burying the cpu in interrupt requests. */
spin_lock_irqsave(&ohci->event_lock, flags); spin_lock_irqsave(&ohci->event_lock, flags);
reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset); 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) {
udelay(10); int loop_count = 0;
while(reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); udelay(10);
while (reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
spin_unlock_irqrestore(&ohci->event_lock, flags); spin_unlock_irqrestore(&ohci->event_lock, flags);
udelay(10); udelay(10);
spin_lock_irqsave(&ohci->event_lock, flags); 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); spin_unlock_irqrestore(&ohci->event_lock, flags);
if (!host->in_bus_reset) { if (!host->in_bus_reset) {
DBGMSG(ohci->id, "irq_handler: Bus reset requested"); DBGMSG(ohci->id, "irq_handler: Bus reset requested");
...@@ -2438,6 +2462,8 @@ static void ohci_irq_handler(int irq, void *dev_id, ...@@ -2438,6 +2462,8 @@ static void ohci_irq_handler(int irq, void *dev_id,
if (event) if (event)
PRINT(KERN_ERR, ohci->id, "Unhandled interrupt(s) 0x%08x", PRINT(KERN_ERR, ohci->id, "Unhandled interrupt(s) 0x%08x",
event); event);
return;
} }
/* Put the buffer back into the dma context */ /* Put the buffer back into the dma context */
...@@ -3277,6 +3303,18 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev, ...@@ -3277,6 +3303,18 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->selfid_swap = 1; ohci->selfid_swap = 1;
#endif #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 /* We hardwire the MMIO length, since some CardBus adaptors
* fail to report the right length. Anyway, the ohci spec * fail to report the right length. Anyway, the ohci spec
* clearly says it's 2kb, so this shouldn't be a problem. */ * 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, ...@@ -3363,7 +3401,7 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
* accessing registers in the SClk domain without LPS enabled * accessing registers in the SClk domain without LPS enabled
* will lock up the machine. Wait 50msec to make sure we have * will lock up the machine. Wait 50msec to make sure we have
* full link enabled. */ * full link enabled. */
reg_write(ohci, OHCI1394_HCControlSet, 0x00080000); reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
mdelay(50); mdelay(50);
/* Determine the number of available IR and IT contexts. */ /* Determine the number of available IR and IT contexts. */
...@@ -3489,7 +3527,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) ...@@ -3489,7 +3527,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = { static struct pci_device_id ohci1394_pci_tbl[] __devinitdata = {
{ {
.class = PCI_CLASS_FIREWIRE_OHCI, .class = PCI_CLASS_FIREWIRE_OHCI,
.class_mask = ~0, .class_mask = PCI_ANY_ID,
.vendor = PCI_ANY_ID, .vendor = PCI_ANY_ID,
.device = PCI_ANY_ID, .device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
......
...@@ -233,6 +233,9 @@ struct ti_ohci { ...@@ -233,6 +233,9 @@ struct ti_ohci {
unsigned int selfid_swap:1; unsigned int selfid_swap:1;
/* Some Apple chipset seem to swap incoming headers for us */ /* Some Apple chipset seem to swap incoming headers for us */
unsigned int no_swap_incoming:1; 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) 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) ...@@ -288,6 +291,13 @@ static inline u32 reg_read(const struct ti_ohci *ohci, int offset)
#define OHCI1394_VendorID 0x040 #define OHCI1394_VendorID 0x040
#define OHCI1394_HCControlSet 0x050 #define OHCI1394_HCControlSet 0x050
#define OHCI1394_HCControlClear 0x054 #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_SelfIDBuffer 0x064
#define OHCI1394_SelfIDCount 0x068 #define OHCI1394_SelfIDCount 0x068
#define OHCI1394_IRMultiChanMaskHiSet 0x070 #define OHCI1394_IRMultiChanMaskHiSet 0x070
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/fs.h> #include <linux/fs.h>
...@@ -71,8 +72,8 @@ ...@@ -71,8 +72,8 @@
/* Module Parameters */ /* Module Parameters */
MODULE_PARM(skip_eeprom,"i"); module_param(skip_eeprom, int, 0444);
MODULE_PARM_DESC(skip_eeprom, "Do not try to read bus info block from serial eeprom, but user generic one (default = 0)."); MODULE_PARM_DESC(skip_eeprom, "Use generic bus info block instead of serial eeprom (default = 0).");
static int skip_eeprom = 0; static int skip_eeprom = 0;
...@@ -983,8 +984,9 @@ loff_t mem_llseek(struct file *file, loff_t offs, int orig) ...@@ -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 * 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 * everywhere as good as here - use mem_mindma option for modules to change
*/ */
short mem_mindma = 2400; static short mem_mindma = 2400;
MODULE_PARM(mem_mindma, "h"); 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, static ssize_t mem_dmaread(struct memdata *md, u32 physbuf, ssize_t count,
int offset) int offset)
......
This diff is collapsed.
...@@ -238,7 +238,7 @@ struct sbp2_status_block { ...@@ -238,7 +238,7 @@ struct sbp2_status_block {
*/ */
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 #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 */ #define SBP2_MAX_SECTORS 255 /* Max sectors supported */
#ifndef TYPE_SDAD #ifndef TYPE_SDAD
...@@ -320,6 +320,10 @@ struct sbp2_command_info { ...@@ -320,6 +320,10 @@ struct sbp2_command_info {
#define SBP2_BREAKAGE_128K_MAX_TRANSFER 0x1 #define SBP2_BREAKAGE_128K_MAX_TRANSFER 0x1
#define SBP2_BREAKAGE_INQUIRY_HACK 0x2 #define SBP2_BREAKAGE_INQUIRY_HACK 0x2
struct sbp2scsi_host_info;
/* /*
* Information needed on a per scsi id basis (one for each sbp2 device) * Information needed on a per scsi id basis (one for each sbp2 device)
*/ */
...@@ -375,6 +379,9 @@ struct scsi_id_instance_data { ...@@ -375,6 +379,9 @@ struct scsi_id_instance_data {
/* Node entry, as retrieved from NodeMgr entries */ /* Node entry, as retrieved from NodeMgr entries */
struct node_entry *ne; struct node_entry *ne;
/* A backlink to our host_info */
struct sbp2scsi_host_info *hi;
/* Device specific workarounds/brokeness */ /* Device specific workarounds/brokeness */
u32 workarounds; u32 workarounds;
}; };
...@@ -406,7 +413,6 @@ struct sbp2scsi_host_info { ...@@ -406,7 +413,6 @@ struct sbp2scsi_host_info {
* SCSI ID instance data (one for each sbp2 device instance possible) * SCSI ID instance data (one for each sbp2 device instance possible)
*/ */
struct scsi_id_instance_data *scsi_id[SBP2SCSI_MAX_SCSI_IDS]; struct scsi_id_instance_data *scsi_id[SBP2SCSI_MAX_SCSI_IDS];
}; };
/* /*
...@@ -416,30 +422,30 @@ struct sbp2scsi_host_info { ...@@ -416,30 +422,30 @@ struct sbp2scsi_host_info {
/* /*
* Various utility prototypes * Various utility prototypes
*/ */
static int sbp2util_create_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, struct sbp2scsi_host_info *hi); 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_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_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, static struct sbp2_command_info *sbp2util_allocate_command_orb(struct scsi_id_instance_data *scsi_id,
Scsi_Cmnd *Current_SCpnt, Scsi_Cmnd *Current_SCpnt,
void (*Current_done)(Scsi_Cmnd *), void (*Current_done)(Scsi_Cmnd *));
struct sbp2scsi_host_info *hi);
static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id, static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
struct sbp2_command_info *command); struct sbp2_command_info *command);
/* /*
* IEEE-1394 core driver related prototypes * 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 struct sbp2scsi_host_info *sbp2_find_host_info(struct hpsb_host *host);
static void sbp2_remove_host(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 void sbp2_update(struct unit_directory *ud);
static int sbp2_start_device(struct sbp2scsi_host_info *hi, static int sbp2_start_device(struct sbp2scsi_host_info *hi,
struct unit_directory *ud); struct unit_directory *ud);
static void sbp2_remove_device(struct sbp2scsi_host_info *hi, static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id);
struct scsi_id_instance_data *scsi_id);
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data, 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_ ...@@ -451,29 +457,28 @@ static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_
/* /*
* SBP-2 protocol related prototypes * 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_login_device(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_reconnect_device(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_logout_device(struct scsi_id_instance_data *scsi_id);
static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid, static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
quadlet_t *data, u64 addr, unsigned int length, u16 flags); 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_agent_reset(struct scsi_id_instance_data *scsi_id, int wait);
static int sbp2_create_command_orb(struct sbp2scsi_host_info *hi, static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
struct scsi_id_instance_data *scsi_id,
struct sbp2_command_info *command, struct sbp2_command_info *command,
unchar *scsi_cmd, unchar *scsi_cmd,
unsigned int scsi_use_sg, unsigned int scsi_use_sg,
unsigned int scsi_request_bufflen, unsigned int scsi_request_bufflen,
void *scsi_request_buffer, void *scsi_request_buffer,
unsigned char scsi_dir); 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); 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 *)); Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data); 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_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_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 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_set_busy_timeout(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_max_speed_and_size(struct scsi_id_instance_data *scsi_id);
#endif /* SBP2_H */ #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