Commit 0a97b16a authored by Linus Torvalds's avatar Linus Torvalds

v2.4.10.2 -> v2.4.10.3

  - Al Viro: superblock cleanups, partition handling fixes and cleanups
  - Ben Collins: firewire update
  - Jeff Garzik: network driver updates
  - Urban Widmark: smbfs updates
  - Kai Mäkisara: SCSI tape driver update
  - various: embarrassing lack of error checking in ELF loader
  - Neil Brown: md formatting cleanup.
parent 5bf3be03
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 11
EXTRAVERSION =-pre2
EXTRAVERSION =-pre3
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
......
/*
* BK Id: SCCS/s.fault.c 1.13 06/28/01 15:50:17 paulus
* BK Id: SCCS/s.fault.c 1.15 09/24/01 16:35:10 paulus
*/
/*
* arch/ppc/mm/fault.c
......@@ -150,6 +150,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
* make sure we exit gracefully rather than endlessly redo
* the fault.
*/
survive:
switch (handle_mm_fault(mm, vma, address, is_write)) {
case 1:
current->min_flt++;
......@@ -195,6 +196,12 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
*/
out_of_memory:
up_read(&mm->mmap_sem);
if (current->pid == 1) {
current->policy |= SCHED_YIELD;
schedule();
down_read(&mm->mmap_sem);
goto survive;
}
printk("VM: killing process %s\n", current->comm);
if (user_mode(regs))
do_exit(SIGKILL);
......@@ -346,34 +353,3 @@ get_8xx_pte(struct mm_struct *mm, unsigned long addr)
return(retval);
}
#endif /* CONFIG_8xx */
#if 0
/*
* Misc debugging functions. Please leave them here. -- Cort
*/
void print_pte(struct _PTE p)
{
printk(
"%08x %08x vsid: %06x h: %01x api: %02x rpn: %05x rcwimg: %d%d%d%d%d%d pp: %02x\n",
*((unsigned long *)(&p)), *((long *)&p+1),
p.vsid, p.h, p.api, p.rpn,
p.r,p.c,p.w,p.i,p.m,p.g,p.pp);
}
/*
* Search the hw hash table for a mapping to the given physical
* address. -- Cort
*/
unsigned long htab_phys_to_va(unsigned long address)
{
extern PTE *Hash, *Hash_end;
PTE *ptr;
for ( ptr = Hash ; ptr < Hash_end ; ptr++ )
{
if ( ptr->rpn == (address>>12) )
printk("phys %08lX -> va ???\n",
address);
}
}
#endif
/*
* BK Id: SCCS/s.init.c 1.34 08/20/01 22:12:43 paulus
* BK Id: SCCS/s.init.c 1.36 09/22/01 14:03:09 paulus
*/
/*
* PowerPC version
......@@ -44,12 +44,15 @@
#include <asm/smp.h>
#include <asm/machdep.h>
#include <asm/btext.h>
#include <asm/tlb.h>
#include "mem_pieces.h"
#include "mmu_decl.h"
#define MAX_LOW_MEM (0xF0000000UL - KERNELBASE)
mmu_gather_t mmu_gathers[NR_CPUS];
void *end_of_DRAM;
unsigned long total_memory;
unsigned long total_lowmem;
......
......@@ -36,7 +36,7 @@
#include <asm/mmu_context.h>
mm_context_t next_mmu_context;
unsigned long context_map[(LAST_CONTEXT+1) / (8*sizeof(unsigned long))];
unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
#ifdef FEW_CONTEXTS
atomic_t nr_free_contexts;
struct mm_struct *context_mm[LAST_CONTEXT+1];
......@@ -57,7 +57,7 @@ void __init mmu_context_init(void)
context_map[0] = (1 << FIRST_CONTEXT) - 1;
next_mmu_context = FIRST_CONTEXT;
#ifdef FEW_CONTEXTS
atomic_set(&nr_free_contexts, LAST_CONTEXT);
atomic_set(&nr_free_contexts, LAST_CONTEXT - FIRST_CONTEXT + 1);
#endif /* FEW_CONTEXTS */
}
......
......@@ -211,12 +211,12 @@ void __init mapin_ram(void)
#else
if ((char *) v < _stext || (char *) v >= etext)
f |= _PAGE_RW | _PAGE_DIRTY;
#ifndef CONFIG_8xx
#ifdef CONFIG_PPC_STD_MMU
else
/* On the powerpc (not 8xx), no user access
/* On the powerpc (not all), no user access
forces R/W kernel access */
f |= _PAGE_USER;
#endif /* CONFIG_8xx */
#endif /* CONFIG_PPC_STD_MMU */
#endif /* CONFIG_KGDB */
map_page(v, p, f);
v += PAGE_SIZE;
......
......@@ -231,12 +231,12 @@ static struct sysrq_key_op sysrq_sync_op = {
static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
emergency_sync_scheduled = EMERG_REMOUNT;
wakeup_bdflush(0);
wakeup_bdflush();
}
static struct sysrq_key_op sysrq_mountro_op = {
handler: sysrq_handle_mountro,
help_msg: "Unmount",
action_msg: "Emergency Remount R/0",
action_msg: "Emergency Remount R/O",
};
/* END SYNC SYSRQ HANDLERS BLOCK */
......
This diff is collapsed.
......@@ -157,16 +157,13 @@ void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
#define DEFINE_MULTIPLEXER(Function) \
void highlevel_##Function(struct hpsb_host *host) \
{ \
struct list_head *entry,*next; \
struct list_head *lh; \
void (*funcptr)(struct hpsb_host*); \
read_lock(&hl_drivers_lock); \
entry = hl_drivers.next; \
while (entry != &hl_drivers) { \
next = entry->next; \
funcptr = list_entry(entry, struct hpsb_highlevel, hl_list) \
list_for_each(lh, &hl_drivers) { \
funcptr = list_entry(lh, struct hpsb_highlevel, hl_list) \
->op->Function; \
if (funcptr) funcptr(host); \
entry = next; \
} \
read_unlock(&hl_drivers_lock); \
}
......
......@@ -23,8 +23,8 @@
#include "highlevel.h"
static struct hpsb_host_template *templates = NULL;
spinlock_t templates_lock = SPIN_LOCK_UNLOCKED;
static LIST_HEAD(templates);
static spinlock_t templates_lock = SPIN_LOCK_UNLOCKED;
/*
* This function calls the add_host/remove_host hooks for every host currently
......@@ -32,13 +32,16 @@ spinlock_t templates_lock = SPIN_LOCK_UNLOCKED;
*/
void hl_all_hosts(struct hpsb_highlevel *hl, int init)
{
struct list_head *tlh, *hlh;
struct hpsb_host_template *tmpl;
struct hpsb_host *host;
spin_lock(&templates_lock);
for (tmpl = templates; tmpl != NULL; tmpl = tmpl->next) {
for (host = tmpl->hosts; host != NULL; host = host->next) {
list_for_each(tlh, &templates) {
tmpl = list_entry(tlh, struct hpsb_host_template, list);
list_for_each(hlh, &tmpl->hosts) {
host = list_entry(hlh, struct hpsb_host, list);
if (host->initialized) {
if (init) {
if (hl->op->add_host) {
......@@ -58,21 +61,24 @@ void hl_all_hosts(struct hpsb_highlevel *hl, int init)
int hpsb_inc_host_usage(struct hpsb_host *host)
{
struct list_head *tlh, *hlh;
struct hpsb_host_template *tmpl;
struct hpsb_host *h;
int retval = 0;
unsigned long flags;
spin_lock_irqsave(&templates_lock, flags);
for (tmpl = templates; (tmpl != NULL) && !retval; tmpl = tmpl->next) {
for (h = tmpl->hosts; h != NULL; h = h->next) {
if (h == host) {
tmpl->devctl(h, MODIFY_USAGE, 1);
list_for_each(tlh, &templates) {
tmpl = list_entry(tlh, struct hpsb_host_template, list);
list_for_each(hlh, &tmpl->hosts) {
if (host == list_entry(hlh, struct hpsb_host, list)) {
tmpl->devctl(host, MODIFY_USAGE, 1);
retval = 1;
break;
}
}
if (retval)
break;
}
spin_unlock_irqrestore(&templates_lock, flags);
......@@ -113,32 +119,22 @@ struct hpsb_host *hpsb_get_host(struct hpsb_host_template *tmpl,
h->speed_map = (u8 *)(h->csr.speed_map + 2);
h->template = tmpl;
if (hd_size) {
if (hd_size)
h->hostdata = &h->embedded_hostdata[0];
}
if (tmpl->hosts == NULL) {
tmpl->hosts = h;
} else {
struct hpsb_host *last = tmpl->hosts;
while (last->next != NULL) {
last = last->next;
}
last->next = h;
}
list_add_tail(&h->list, &tmpl->hosts);
return h;
}
static void free_all_hosts(struct hpsb_host_template *tmpl)
{
struct hpsb_host *next, *host = tmpl->hosts;
struct list_head *hlh, *next;
struct hpsb_host *host;
while (host) {
next = host->next;
list_for_each_safe(hlh, next, &tmpl->hosts) {
host = list_entry(hlh, struct hpsb_host, list);
vfree(host);
host = next;
}
}
......@@ -146,11 +142,13 @@ static void free_all_hosts(struct hpsb_host_template *tmpl)
static void init_hosts(struct hpsb_host_template *tmpl)
{
int count;
struct list_head *hlh;
struct hpsb_host *host;
count = tmpl->detect_hosts(tmpl);
for (host = tmpl->hosts; host != NULL; host = host->next) {
list_for_each(hlh, &tmpl->hosts) {
host = list_entry(hlh, struct hpsb_host, list);
if (tmpl->initialize_host(host)) {
host->initialized = 1;
......@@ -166,9 +164,11 @@ static void init_hosts(struct hpsb_host_template *tmpl)
static void shutdown_hosts(struct hpsb_host_template *tmpl)
{
struct list_head *hlh;
struct hpsb_host *host;
for (host = tmpl->hosts; host != NULL; host = host->next) {
list_for_each(hlh, &tmpl->hosts) {
host = list_entry(hlh, struct hpsb_host, list);
if (host->initialized) {
host->initialized = 0;
abort_requests(host);
......@@ -188,68 +188,17 @@ static void shutdown_hosts(struct hpsb_host_template *tmpl)
}
static int add_template(struct hpsb_host_template *new)
{
new->next = NULL;
new->hosts = NULL;
new->number_of_hosts = 0;
spin_lock(&templates_lock);
if (templates == NULL) {
templates = new;
} else {
struct hpsb_host_template *last = templates;
while (last->next != NULL) {
last = last->next;
}
last->next = new;
}
spin_unlock(&templates_lock);
return 0;
}
static int remove_template(struct hpsb_host_template *tmpl)
{
int retval = 0;
if (tmpl->number_of_hosts) {
HPSB_ERR("attempted to remove busy host template "
"of %s at address 0x%p", tmpl->name, tmpl);
return 1;
}
spin_lock(&templates_lock);
if (templates == tmpl) {
templates = tmpl->next;
} else {
struct hpsb_host_template *t;
t = templates;
while (t->next != tmpl && t->next != NULL) {
t = t->next;
}
if (t->next == NULL) {
HPSB_ERR("attempted to remove unregistered host template "
"of %s at address 0x%p", tmpl->name, tmpl);
retval = -1;
} else {
t->next = tmpl->next;
}
}
spin_unlock(&templates_lock);
return retval;
}
/*
* The following two functions are exported symbols for module usage.
*/
int hpsb_register_lowlevel(struct hpsb_host_template *tmpl)
{
add_template(tmpl);
INIT_LIST_HEAD(&tmpl->hosts);
tmpl->number_of_hosts = 0;
spin_lock(&templates_lock);
list_add_tail(&tmpl->list, &templates);
spin_unlock(&templates_lock);
/* PCI cards should be smart and use the PCI detection layer, and
* not this one shot deal. detect_hosts() will be obsoleted soon. */
......@@ -265,7 +214,12 @@ void hpsb_unregister_lowlevel(struct hpsb_host_template *tmpl)
{
shutdown_hosts(tmpl);
if (remove_template(tmpl)) {
HPSB_PANIC("remove_template failed on %s", tmpl->name);
if (tmpl->number_of_hosts)
HPSB_PANIC("attempted to remove busy host template "
"of %s at address 0x%p", tmpl->name, tmpl);
else {
spin_lock(&templates_lock);
list_del(&tmpl->list);
spin_unlock(&templates_lock);
}
}
......@@ -3,6 +3,7 @@
#include <linux/wait.h>
#include <linux/tqueue.h>
#include <linux/list.h>
#include <asm/semaphore.h>
#include "ieee1394_types.h"
......@@ -13,7 +14,7 @@ struct hpsb_packet;
struct hpsb_host {
/* private fields (hosts, do not use them) */
struct hpsb_host *next;
struct list_head list;
atomic_t generation;
......@@ -109,9 +110,9 @@ enum reset_types {
};
struct hpsb_host_template {
struct hpsb_host_template *next;
struct list_head list;
struct hpsb_host *hosts;
struct list_head hosts;
int number_of_hosts;
/* fields above will be ignored and overwritten after registering */
......
......@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <asm/bitops.h>
#include <asm/byteorder.h>
#include <asm/semaphore.h>
......@@ -30,6 +31,13 @@
#include "csr.h"
#include "nodemgr.h"
/*
* 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 kmem_cache_t *hpsb_packet_cache;
......@@ -95,7 +103,7 @@ struct hpsb_packet *alloc_hpsb_packet(size_t data_size)
INIT_TQ_HEAD(packet->complete_tq);
INIT_LIST_HEAD(&packet->list);
sema_init(&packet->state_change, 0);
packet->state = unused;
packet->state = hpsb_unused;
packet->generation = -1;
packet->data_be = 1;
......@@ -352,14 +360,14 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
}
if (ackcode != ACK_PENDING || !packet->expect_response) {
packet->state = completed;
packet->state = hpsb_complete;
up(&packet->state_change);
up(&packet->state_change);
run_task_queue(&packet->complete_tq);
return;
}
packet->state = pending;
packet->state = hpsb_pending;
packet->sendtime = jiffies;
spin_lock_irqsave(&host->pending_pkt_lock, flags);
......@@ -393,9 +401,9 @@ int hpsb_send_packet(struct hpsb_packet *packet)
return 0;
}
packet->state = queued;
packet->state = hpsb_queued;
if (packet->type == async && packet->node_id != ALL_NODES) {
if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
packet->speed_code =
host->speed_map[(host->node_id & NODE_MASK) * 64
+ (packet->node_id & NODE_MASK)];
......@@ -503,14 +511,14 @@ void handle_packet_response(struct hpsb_host *host, int tcode, quadlet_t *data,
break;
}
packet->state = completed;
packet->state = hpsb_complete;
up(&packet->state_change);
run_task_queue(&packet->complete_tq);
}
struct hpsb_packet *create_reply_packet(struct hpsb_host *host, quadlet_t *data,
size_t dsize)
static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,
quadlet_t *data, size_t dsize)
{
struct hpsb_packet *p;
......@@ -522,13 +530,15 @@ struct hpsb_packet *create_reply_packet(struct hpsb_host *host, quadlet_t *data,
return NULL;
}
p->type = async;
p->state = unused;
p->type = hpsb_async;
p->state = hpsb_unused;
p->host = host;
p->node_id = data[1] >> 16;
p->tlabel = (data[0] >> 10) & 0x3f;
p->no_waiter = 1;
p->generation = get_hpsb_generation(host);
if (dsize % 4) {
p->data[dsize / 4] = 0;
}
......@@ -540,8 +550,8 @@ struct hpsb_packet *create_reply_packet(struct hpsb_host *host, quadlet_t *data,
packet = create_reply_packet(host, data, length); \
if (packet == NULL) break
void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data,
size_t size, int write_acked)
static void handle_incoming_packet(struct hpsb_host *host, int tcode,
quadlet_t *data, size_t size, int write_acked)
{
struct hpsb_packet *packet;
int length, rcode, extcode;
......@@ -720,7 +730,7 @@ void abort_requests(struct hpsb_host *host)
list_for_each(lh, &llist) {
packet = list_entry(lh, struct hpsb_packet, list);
packet->state = completed;
packet->state = hpsb_complete;
packet->ack_code = ACKX_ABORTED;
up(&packet->state_change);
run_task_queue(&packet->complete_tq);
......@@ -732,7 +742,7 @@ void abort_timedouts(struct hpsb_host *host)
unsigned long flags;
struct hpsb_packet *packet;
unsigned long expire;
struct list_head *lh;
struct list_head *lh, *next;
LIST_HEAD(expiredlist);
spin_lock_irqsave(&host->csr.lock, flags);
......@@ -746,8 +756,9 @@ void abort_timedouts(struct hpsb_host *host)
spin_lock_irqsave(&host->pending_pkt_lock, flags);
list_for_each(lh, &host->pending_packets) {
for (lh = host->pending_packets.next; lh != &host->pending_packets; lh = next) {
packet = list_entry(lh, struct hpsb_packet, list);
next = lh->next;
if (time_before(packet->sendtime + expire, jiffies)) {
list_del(&packet->list);
list_add(&packet->list, &expiredlist);
......@@ -761,7 +772,7 @@ void abort_timedouts(struct hpsb_host *host)
list_for_each(lh, &expiredlist) {
packet = list_entry(lh, struct hpsb_packet, list);
packet->state = completed;
packet->state = hpsb_complete;
packet->ack_code = ACKX_TIMEOUT;
up(&packet->state_change);
run_task_queue(&packet->complete_tq);
......@@ -775,13 +786,19 @@ static int __init ieee1394_init(void)
0, 0, NULL, NULL);
init_hpsb_highlevel();
init_csr();
if (!disable_nodemgr)
init_ieee1394_nodemgr();
else
HPSB_INFO("nodemgr functionality disabled");
return 0;
}
static void __exit ieee1394_cleanup(void)
{
if (!disable_nodemgr)
cleanup_ieee1394_nodemgr();
cleanup_csr();
kmem_cache_destroy(hpsb_packet_cache);
}
......
......@@ -20,16 +20,16 @@ struct hpsb_packet {
/* Async and Iso types should be clear, raw means send-as-is, do not
* CRC! Byte swapping shall still be done in this case. */
enum { async, iso, raw } __attribute__((packed)) type;
enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
/* Okay, this is core internal and a no care for hosts.
* queued = queued for sending
* pending = sent, waiting for response
* completed = processing completed, successful or not
* complete = processing completed, successful or not
* incoming = incoming packet
*/
enum {
unused, queued, pending, completed, incoming
hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete, hpsb_incoming
} __attribute__((packed)) state;
/* These are core internal. */
......
......@@ -2,32 +2,75 @@
#define _IEEE1394_HOTPLUG_H
#include "ieee1394_core.h"
#include "nodemgr.h"
#define IEEE1394_DEVICE_ID_MATCH_VENDOR_ID 0x0001
#define IEEE1394_DEVICE_ID_MATCH_MODEL_ID 0x0002
#define IEEE1394_DEVICE_ID_MATCH_SW_SPECIFIER_ID 0x0004
#define IEEE1394_DEVICE_ID_MATCH_SW_SPECIFIER_VERSION 0x0008
#define IEEE1394_MATCH_VENDOR_ID 0x0001
#define IEEE1394_MATCH_MODEL_ID 0x0002
#define IEEE1394_MATCH_SPECIFIER_ID 0x0004
#define IEEE1394_MATCH_VERSION 0x0008
struct ieee1394_device_id {
u32 match_flags;
u32 vendor_id;
u32 model_id;
u32 sw_specifier_id;
u32 sw_specifier_version;
u32 specifier_id;
u32 version;
void *driver_data;
};
#define IEEE1394_PROTOCOL(id, version) { \
match_flags: IEEE1394_DEVICE_ID_MATCH_SW_SPECIFIER_ID | \
IEEE1394_DEVICE_ID_MATCH_SW_SPECIFIER_VERSION, \
sw_specifier_id: id, \
sw_specifier_version: version \
}
#define IEEE1394_DEVICE(vendor_id, model_id) { \
match_flags: IEEE1394_DEVICE_ID_MATCH_VENDOR_ID | \
IEEE1394_DEVICE_ID_MATCH_MODEL_ID, \
vendor_id: vendor_id, \
model_id: vendor_id, \
}
struct hpsb_protocol_driver {
/* The name of the driver, e.g. SBP2 or IP1394 */
const char *name;
/*
* The device id table describing the protocols and/or devices
* supported by this driver. This is used by the nodemgr to
* decide if a driver could support a given node, but the
* probe function below can implement further protocol
* dependent or vendor dependent checking.
*/
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.
* However, it may be necessary to reestablish the connection
* or login into the node again, depending on the protocol.
*/
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;
};
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 */
......@@ -18,6 +18,7 @@
#include "hosts.h"
#include "ieee1394_core.h"
#include "ieee1394_transactions.h"
#include "ieee1394_hotplug.h"
#include "highlevel.h"
#include "nodemgr.h"
......@@ -75,8 +76,12 @@ EXPORT_SYMBOL(highlevel_add_host);
EXPORT_SYMBOL(highlevel_remove_host);
EXPORT_SYMBOL(highlevel_host_reset);
EXPORT_SYMBOL(highlevel_add_one_host);
EXPORT_SYMBOL(hpsb_guid_get_entry);
EXPORT_SYMBOL(hpsb_nodeid_get_entry);
EXPORT_SYMBOL(hpsb_get_host_by_ne);
EXPORT_SYMBOL(hpsb_guid_fill_packet);
EXPORT_SYMBOL(hpsb_register_protocol);
EXPORT_SYMBOL(hpsb_unregister_protocol);
EXPORT_SYMBOL(hpsb_release_unit_directory);
MODULE_LICENSE("GPL");
......@@ -131,7 +131,7 @@ void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
packet->header_size = 4;
packet->data_size = length;
packet->type = iso;
packet->type = hpsb_iso;
packet->tcode = TCODE_ISO_DATA;
}
......@@ -142,7 +142,7 @@ void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
packet->header_size = 8;
packet->data_size = 0;
packet->expect_response = 0;
packet->type = raw; /* No CRC added */
packet->type = hpsb_raw; /* No CRC added */
packet->speed_code = SPEED_100; /* Force speed to be 100Mbps */
}
......@@ -488,7 +488,9 @@ struct hpsb_packet *hpsb_make_packet (struct hpsb_host *host, nodeid_t node,
if (!packet)
return NULL;
if (length != 4)
/* Sometimes this may be called without data, just to allocate the
* packet. */
if (length != 4 && buffer)
memcpy(packet->data, buffer, length);
return packet;
......
......@@ -26,6 +26,13 @@
#include <linux/spinlock.h>
#endif
#ifndef list_for_each_safe
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
#endif
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
......
This diff is collapsed.
......@@ -43,8 +43,18 @@ struct bus_options {
#define UNIT_DIRECTORY_SPECIFIER_ID 0x04
#define UNIT_DIRECTORY_VERSION 0x08
/*
* 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 list_head list;
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;
......@@ -53,6 +63,20 @@ struct unit_directory {
char *model_name;
quadlet_t specifier_id;
quadlet_t version;
/* Groupings for arbitrary key/value pairs */
int arb_count; /* Number of arbitrary key/values */
char arb_keys[16]; /* Up to 16 keys */
quadlet_t arb_values[16]; /* Same for values */
struct hpsb_protocol_driver *driver;
void *driver_data;
/* For linking the nodes managed by the driver, or unmanaged nodes */
struct list_head driver_list;
/* For linking directories belonging to a node */
struct list_head node_list;
};
struct node_entry {
......@@ -69,6 +93,11 @@ struct node_entry {
struct list_head unit_directories;
};
static inline int hpsb_node_entry_valid(struct node_entry *ne)
{
return atomic_read(&ne->generation) == get_hpsb_generation(ne->host);
}
/*
* Returns a node entry (which has its reference count incremented) or NULL if
* the GUID in question is not known. Getting a valid entry does not mean that
......
This diff is collapsed.
......@@ -191,15 +191,14 @@ struct ti_ohci {
spinlock_t event_lock;
int self_id_errors;
int NumBusResets;
/* video device */
struct video_template *video_tmpl;
/* Swap the selfid buffer? */
unsigned int selfid_swap:1;
/* Swap the payload? */
unsigned int payload_swap:1;
/* Some Apple chipset seem to swap incoming headers for us */
unsigned int no_swap_incoming:1;
};
static inline int cross_bound(unsigned long addr, unsigned int size)
......@@ -332,14 +331,16 @@ static inline u32 reg_read(const struct ti_ohci *ohci, int offset)
#define OHCI1394_phyRegRcvd 0x04000000
#define OHCI1394_masterIntEnable 0x80000000
#define OUTPUT_MORE 0x00000000
#define OUTPUT_MORE_IMMEDIATE 0x02000000
#define OUTPUT_LAST 0x103c0000
#define OUTPUT_LAST_IMMEDIATE 0x123c0000
#define DMA_SPEED_100 0x0
#define DMA_SPEED_200 0x1
#define DMA_SPEED_400 0x2
/* DMA Control flags */
#define DMA_CTL_OUTPUT_MORE 0x00000000
#define DMA_CTL_OUTPUT_LAST 0x10000000
#define DMA_CTL_INPUT_MORE 0x20000000
#define DMA_CTL_INPUT_LAST 0x30000000
#define DMA_CTL_UPDATE 0x08000000
#define DMA_CTL_IMMEDIATE 0x02000000
#define DMA_CTL_IRQ 0x00300000
#define DMA_CTL_BRANCH 0x000c0000
#define DMA_CTL_WAIT 0x00030000
#define OHCI1394_TCODE_PHY 0xE
......
......@@ -38,6 +38,7 @@
#include "ieee1394_types.h"
#include "hosts.h"
#include "ieee1394_core.h"
#include "highlevel.h"
#include "pcilynx.h"
......@@ -393,7 +394,7 @@ static void send_next(struct ti_lynx *lynx, int what)
struct lynx_send_data *d;
struct hpsb_packet *packet;
d = (what == iso ? &lynx->iso_send : &lynx->async);
d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);
packet = d->queue;
d->header_dma = pci_map_single(lynx->dev, packet->header,
......@@ -419,13 +420,13 @@ static void send_next(struct ti_lynx *lynx, int what)
pcl.buffer[1].pointer = d->data_dma;
switch (packet->type) {
case async:
case hpsb_async:
pcl.buffer[0].control |= PCL_CMD_XMT;
break;
case iso:
case hpsb_iso:
pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE;
break;
case raw:
case hpsb_raw:
pcl.buffer[0].control |= PCL_CMD_UNFXMT;
break;
}
......@@ -606,11 +607,11 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
}
switch (packet->type) {
case async:
case raw:
case hpsb_async:
case hpsb_raw:
d = &lynx->async;
break;
case iso:
case hpsb_iso:
d = &lynx->iso_send;
break;
default:
......@@ -1227,7 +1228,7 @@ static void lynx_irq_handler(int irq, void *dev_id,
}
if (lynx->async.queue != NULL) {
send_next(lynx, async);
send_next(lynx, hpsb_async);
}
spin_unlock(&lynx->async.queue_lock);
......@@ -1259,7 +1260,7 @@ static void lynx_irq_handler(int irq, void *dev_id,
}
if (lynx->iso_send.queue != NULL) {
send_next(lynx, iso);
send_next(lynx, hpsb_iso);
}
spin_unlock(&lynx->iso_send.queue_lock);
......@@ -1368,7 +1369,7 @@ static int __devinit add_card(struct pci_dev *dev,
FAIL("failed to allocate host structure");
lynx->state = have_host_struct;
lynx->host->hostdata = lynx;
lynx->id = num_of_cards-1;
lynx->dev = dev;
lynx->host->pdev = dev;
......@@ -1501,6 +1502,9 @@ static int __devinit add_card(struct pci_dev *dev,
PRINT(KERN_INFO, lynx->id, "found old 1394 PHY");
}
/* Tell the highlevel this host is ready */
highlevel_add_one_host (lynx->host);
return 0;
#undef FAIL
}
......@@ -1633,8 +1637,8 @@ MODULE_DEVICE_TABLE(pci, pci_table);
static void __exit pcilynx_cleanup(void)
{
pci_unregister_driver(&lynx_pcidriver);
hpsb_unregister_lowlevel(&lynx_template);
pci_unregister_driver(&lynx_pcidriver);
PRINT_G(KERN_INFO, "removed " PCILYNX_DRIVER_NAME " module");
}
......
......@@ -290,8 +290,11 @@ static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data,
}
spin_unlock_irqrestore(&host_info_lock, flags);
list_for_each(lh, &reqs) {
lh = reqs.next;
while (lh != &reqs) {
req = list_entry(lh, struct pending_request, list);
lh = lh->next;
queue_complete_req(req);
}
}
......@@ -356,8 +359,11 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
}
spin_unlock_irqrestore(&host_info_lock, flags);
list_for_each(lh, &reqs) {
lh = reqs.next;
while (lh != &reqs) {
req = list_entry(lh, struct pending_request, list);
lh = lh->next;
queue_complete_req(req);
}
}
......@@ -746,6 +752,8 @@ static int handle_remote_request(struct file_info *fi,
list_add_tail(&req->list, &fi->req_pending);
spin_unlock_irq(&fi->reqlists_lock);
packet->generation = req->req.generation;
if (!hpsb_send_packet(packet)) {
req->req.error = RAW1394_ERROR_SEND_ERROR;
req->req.length = 0;
......@@ -766,7 +774,7 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req,
fill_iso_packet(packet, req->req.length, channel & 0x3f,
(req->req.misc >> 16) & 0x3, req->req.misc & 0xf);
packet->type = iso;
packet->type = hpsb_iso;
packet->speed_code = req->req.address & 0x3;
packet->host = fi->host;
......@@ -787,6 +795,9 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req,
list_add_tail(&req->list, &fi->req_pending);
spin_unlock_irq(&fi->reqlists_lock);
/* Update the generation of the packet just before sending. */
packet->generation = get_hpsb_generation(fi->host);
if (!hpsb_send_packet(packet)) {
req->req.error = RAW1394_ERROR_SEND_ERROR;
queue_complete_req(req);
......
This diff is collapsed.
......@@ -36,13 +36,6 @@
#define ORB_DIRECTION_READ_FROM_MEDIA 0x1
#define ORB_DIRECTION_NO_DATA_TRANSFER 0x2
#define SPEED_S100 0x0
#define SPEED_S200 0x1
#define SPEED_S400 0x2
#define SPEED_S800 0x3
#define SPEED_S1600 0x4
#define SPEED_S3200 0x5
/* 2^(MAX_PAYLOAD+1) = Maximum data transfer length */
#define MAX_PAYLOAD_S100 0x7
#define MAX_PAYLOAD_S200 0x8
......@@ -232,8 +225,8 @@ struct sbp2_status_block {
* Unit spec id and sw version entry for SBP-2 devices
*/
#define SBP2_UNIT_SPEC_ID_ENTRY 0x1200609e
#define SBP2_SW_VERSION_ENTRY 0x13010483
#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e
#define SBP2_SW_VERSION_ENTRY 0x00010483
/*
* Miscellaneous general config rom related defines
......@@ -243,11 +236,8 @@ struct sbp2_status_block {
#define CONFIG_ROM_BASE_ADDRESS 0xfffff0000400ULL
#define CONFIG_ROM_ROOT_DIR_BASE 0xfffff0000414ULL
#define CONFIG_ROM_SIGNATURE_ADDRESS 0xfffff0000404ULL
#define CONFIG_ROM_UNIT_DIRECTORY_OFFSET 0xfffff0000424ULL
#define IEEE1394_CONFIG_ROM_SIGNATURE 0x31333934
#define SBP2_128KB_BROKEN_FIRMWARE 0xa0b800
#define SBP2_BROKEN_FIRMWARE_MAX_TRANSFER 0x20000
......@@ -350,6 +340,8 @@ struct sbp2_command_info {
* Information needed on a per scsi id basis (one for each sbp2 device)
*/
struct scsi_id_instance_data {
/* SCSI ID */
int id;
/*
* Various sbp2 specific structures
......@@ -368,18 +360,15 @@ struct scsi_id_instance_data {
/*
* Stuff we need to know about the sbp2 device itself
*/
u64 node_unique_id;
u64 sbp2_management_agent_addr;
u64 sbp2_command_block_agent_addr;
u32 node_id;
u32 speed_code;
u32 max_payload_size;
/*
* Values pulled from the device's unit directory
*/
u32 sbp2_unit_spec_id;
u32 sbp2_unit_sw_version;
struct unit_directory *ud;
u32 sbp2_command_set_spec_id;
u32 sbp2_command_set;
u32 sbp2_unit_characteristics;
......@@ -391,12 +380,6 @@ struct scsi_id_instance_data {
*/
wait_queue_head_t sbp2_login_wait;
/*
* Flag noting whether the sbp2 device is currently validated (for use during
* bus resets).
*/
u32 validated;
/*
* Pool of command orbs, so we can have more than overlapped command per id
*/
......@@ -405,6 +388,8 @@ struct scsi_id_instance_data {
struct list_head sbp2_command_orb_completed;
u32 sbp2_total_command_orbs;
/* Node entry, as retrieved from NodeMgr entries */
struct node_entry *ne;
};
/*
......@@ -424,22 +409,6 @@ struct sbp2scsi_host_info {
spinlock_t sbp2_command_lock;
spinlock_t sbp2_request_packet_lock;
/*
* Flag indicating if a bus reset (or device detection) is in progress
*/
u32 bus_reset_in_progress;
/*
* We currently use a kernel thread for dealing with bus resets and sbp2
* device detection. We use this to wake up the thread when needed.
*/
wait_queue_head_t sbp2_detection_wait;
/*
* PID of sbp2 detection kernel thread
*/
int sbp2_detection_pid;
/*
* Lists keeping track of inuse/free sbp2_request_packets. These structures are
* used for sending out sbp2 command and agent reset packets. We initially create
......@@ -449,13 +418,6 @@ struct sbp2scsi_host_info {
struct list_head sbp2_req_inuse;
struct list_head sbp2_req_free;
/*
* Stuff to keep track of the initial scsi bus scan (so that we don't miss it)
*/
u32 initial_scsi_bus_scan_complete;
Scsi_Cmnd *bus_scan_SCpnt;
void (*bus_scan_done)(Scsi_Cmnd *);
/*
* Here is the pool of request packets. All the hpsb packets (for 1394 bus transactions)
* are allocated at init and simply re-initialized when needed.
......@@ -476,9 +438,6 @@ struct sbp2scsi_host_info {
/*
* Various utility prototypes
*/
static int sbp2util_read_quadlet(struct sbp2scsi_host_info *hi, nodeid_t node, u64 addr,
quadlet_t *buffer);
static int sbp2util_unit_directory(struct sbp2scsi_host_info *hi, nodeid_t node, u64 *addr);
static int sbp2util_create_request_packet_pool(struct sbp2scsi_host_info *hi);
static void sbp2util_remove_request_packet_pool(struct sbp2scsi_host_info *hi);
static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct sbp2scsi_host_info *hi,
......@@ -500,23 +459,19 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_i
/*
* IEEE-1394 core driver related prototypes
*/
static void sbp2_remove_unvalidated_devices(struct sbp2scsi_host_info *hi);
static int sbp2_start_device(struct sbp2scsi_host_info *hi, int node_id);
static int sbp2_check_device(struct sbp2scsi_host_info *hi, int node_id);
static void sbp2_bus_reset_handler(void *context);
static void 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 void sbp2_host_reset(struct hpsb_host *host);
static int sbp2_detection_thread(void *__sbp2);
int sbp2_init(void);
void sbp2_cleanup(void);
#if 0
static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, quadlet_t *data,
u64 addr, unsigned int length);
static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data,
u64 addr, unsigned int length);
#endif
static int sbp2_probe(struct unit_directory *ud);
static void sbp2_disconnect(struct unit_directory *ud);
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);
/*
* SBP-2 protocol related prototypes
*/
......@@ -543,7 +498,7 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense
static void sbp2_check_sbp2_command(unchar *cmd);
static void sbp2_check_sbp2_response(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id,
Scsi_Cmnd *SCpnt);
static int sbp2_parse_unit_directory(struct sbp2scsi_host_info *hi, 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_max_speed_and_size(struct sbp2scsi_host_info *hi, struct scsi_id_instance_data *scsi_id);
......
......@@ -488,24 +488,27 @@ static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags)
int i;
/* the first descriptor will read only 4 bytes */
ir_prg[0].control = (0x280C << 16) | 4;
ir_prg[0].control = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
DMA_CTL_BRANCH | 4;
/* set the sync flag */
if (flags & VIDEO1394_SYNC_FRAMES)
ir_prg[0].control |= 0x00030000;
ir_prg[0].control |= DMA_CTL_WAIT;
ir_prg[0].address = kvirt_to_bus(buf);
ir_prg[0].branchAddress = (virt_to_bus(&(ir_prg[1].control))
& 0xfffffff0) | 0x1;
/* the second descriptor will read PAGE_SIZE-4 bytes */
ir_prg[1].control = (0x280C << 16) | (PAGE_SIZE-4);
ir_prg[1].control = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
DMA_CTL_BRANCH | (PAGE_SIZE-4);
ir_prg[1].address = kvirt_to_bus(buf+4);
ir_prg[1].branchAddress = (virt_to_bus(&(ir_prg[2].control))
& 0xfffffff0) | 0x1;
for (i=2;i<d->nb_cmd-1;i++) {
ir_prg[i].control = (0x280C << 16) | PAGE_SIZE;
ir_prg[i].control = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
DMA_CTL_BRANCH | PAGE_SIZE;
ir_prg[i].address = kvirt_to_bus(buf+(i-1)*PAGE_SIZE);
ir_prg[i].branchAddress =
......@@ -514,7 +517,8 @@ static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags)
}
/* the last descriptor will generate an interrupt */
ir_prg[i].control = (0x283C << 16) | d->left_size;
ir_prg[i].control = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size;
ir_prg[i].address = kvirt_to_bus(buf+(i-1)*PAGE_SIZE);
}
......@@ -691,13 +695,14 @@ static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
d->last_used_cmd[n] = d->nb_cmd - 1;
for (i=0;i<d->nb_cmd;i++) {
it_prg[i].begin.control = OUTPUT_MORE_IMMEDIATE | 8 ;
it_prg[i].begin.control = DMA_CTL_OUTPUT_MORE |
DMA_CTL_IMMEDIATE | 8 ;
it_prg[i].begin.address = 0;
it_prg[i].begin.status = 0;
it_prg[i].data[0] =
(DMA_SPEED_100 << 16)
(SPEED_100 << 16)
| (/* tag */ 1 << 14)
| (d->channel << 8)
| (TCODE_ISO_DATA << 4);
......@@ -706,7 +711,7 @@ static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
it_prg[i].data[2] = 0;
it_prg[i].data[3] = 0;
it_prg[i].end.control = 0x100c0000;
it_prg[i].end.control = DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH;
it_prg[i].end.address =
kvirt_to_bus(buf+i*d->packet_size);
......@@ -721,7 +726,8 @@ static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
}
else {
/* the last prg generates an interrupt */
it_prg[i].end.control |= 0x08300000 | d->left_size;
it_prg[i].end.control |= DMA_CTL_UPDATE |
DMA_CTL_IRQ | d->left_size;
/* the last prg doesn't branch */
it_prg[i].begin.branchAddress = 0;
it_prg[i].end.branchAddress = 0;
......@@ -761,7 +767,7 @@ static void initialize_dma_it_prg_var_packet_queue(
size = packet_sizes[i];
}
it_prg[i].data[1] = size << 16;
it_prg[i].end.control = 0x100c0000;
it_prg[i].end.control = DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH;
if (i < d->nb_cmd-1 && packet_sizes[i+1] != 0) {
it_prg[i].end.control |= size;
......@@ -773,7 +779,8 @@ static void initialize_dma_it_prg_var_packet_queue(
& 0xfffffff0) | 0x3;
} else {
/* the last prg generates an interrupt */
it_prg[i].end.control |= 0x08300000 | size;
it_prg[i].end.control |= DMA_CTL_UPDATE |
DMA_CTL_IRQ | size;
/* the last prg doesn't branch */
it_prg[i].begin.branchAddress = 0;
it_prg[i].end.branchAddress = 0;
......@@ -1560,7 +1567,6 @@ static int video1394_init(struct ti_ohci *ohci)
static void remove_card(struct video_card *video)
{
int i;
unsigned long flags;
ohci1394_unregister_video(video->ohci, &video_tmpl);
......@@ -1581,9 +1587,7 @@ static void remove_card(struct video_card *video)
}
kfree(video->it_context);
}
spin_lock_irqsave(&video1394_cards_lock, flags);
list_del(&video->list);
spin_unlock_irqrestore(&video1394_cards_lock, flags);
kfree(video);
}
......@@ -1607,7 +1611,7 @@ static void video1394_remove_host (struct hpsb_host *host)
p = list_entry(lh, struct video_card, list);
if (p ->ohci == ohci) {
remove_card(p);
return;
break;
}
}
}
......
This diff is collapsed.
......@@ -137,7 +137,7 @@ an MMIO register read.
*/
#define DRV_NAME "8139too"
#define DRV_VERSION "0.9.18a"
#define DRV_VERSION "0.9.19"
#include <linux/config.h>
......@@ -620,6 +620,7 @@ static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
static struct net_device_stats *rtl8139_get_stats (struct net_device *dev);
static inline u32 ether_crc (int length, unsigned char *data);
static void rtl8139_set_rx_mode (struct net_device *dev);
static void __set_rx_mode (struct net_device *dev);
static void rtl8139_hw_start (struct net_device *dev);
#ifdef USE_IO_OPS
......@@ -962,6 +963,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
dev->do_ioctl = netdev_ioctl;
dev->tx_timeout = rtl8139_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
dev->irq = pdev->irq;
......@@ -1725,18 +1727,21 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
assert (tp->tx_info[entry].mapping == 0);
tp->tx_info[entry].skb = skb;
if ((long) skb->data & 3) { /* Must use alignment buffer. */
/* tp->tx_info[entry].mapping = 0; */
memcpy (tp->tx_buf[entry], skb->data, skb->len);
dma_addr = tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs);
} else {
if ( !((unsigned long)skb->data & 3) && skb_shinfo(skb)->nr_frags == 0 &&
skb->ip_summed != CHECKSUM_HW) {
tp->xstats.tx_buf_mapped++;
tp->tx_info[entry].mapping =
pci_map_single (tp->pci_dev, skb->data, skb->len,
PCI_DMA_TODEVICE);
dma_addr = tp->tx_info[entry].mapping;
} else if (skb->len < TX_BUF_SIZE) {
skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
dma_addr = tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs);
} else {
dev_kfree_skb(skb);
tp->tx_info[entry].skb = NULL;
return 0;
}
/* Note: the chip doesn't have auto-pad! */
spin_lock_irq(&tp->lock);
RTL_W32_F (TxAddr0 + (entry * 4), dma_addr);
......@@ -1847,7 +1852,7 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
struct rtl8139_private *tp, void *ioaddr)
{
u8 tmp8;
int tmp_work = 1000;
int tmp_work;
DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n",
dev->name, rx_status);
......@@ -1863,33 +1868,52 @@ static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
tp->stats.rx_length_errors++;
if (rx_status & RxCRCErr)
tp->stats.rx_crc_errors++;
/* Reset the receiver, based on RealTek recommendation. (Bug?) */
tp->cur_rx = 0;
/* disable receive */
RTL_W8 (ChipCmd, CmdTxEnb);
/* A.C.: Reset the multicast list. */
rtl8139_set_rx_mode (dev);
/* XXX potentially temporary hack to
* restart hung receiver */
RTL_W8_F (ChipCmd, CmdTxEnb);
tmp_work = 200;
while (--tmp_work > 0) {
barrier();
udelay(1);
tmp8 = RTL_R8 (ChipCmd);
if (!(tmp8 & CmdRxEnb))
break;
}
if (tmp_work <= 0)
printk (KERN_WARNING PFX "rx stop wait too long\n");
/* restart receive */
tmp_work = 200;
while (--tmp_work > 0) {
RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb);
udelay(1);
tmp8 = RTL_R8 (ChipCmd);
if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb))
break;
RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
}
/* G.S.: Re-enable receiver */
/* XXX temporary hack to work around receiver hang */
rtl8139_set_rx_mode (dev);
if (tmp_work <= 0)
printk (KERN_WARNING PFX "tx/rx enable wait too long\n");
}
/* and reinitialize all rx related registers */
RTL_W8_F (Cfg9346, Cfg9346_Unlock);
/* Must enable Tx/Rx before setting transfer thresholds! */
RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys;
RTL_W32 (RxConfig, tp->rx_config);
tp->cur_rx = 0;
DPRINTK("init buffer addresses\n");
/* Lock Config[01234] and BMCR register writes */
RTL_W8 (Cfg9346, Cfg9346_Lock);
/* init Rx ring buffer DMA address */
RTL_W32_F (RxBuf, tp->rx_ring_dma);
/* A.C.: Reset the multicast list. */
__set_rx_mode (dev);
}
static void rtl8139_rx_interrupt (struct net_device *dev,
struct rtl8139_private *tp, void *ioaddr)
......@@ -2312,11 +2336,10 @@ static inline u32 ether_crc (int length, unsigned char *data)
}
static void rtl8139_set_rx_mode (struct net_device *dev)
static void __set_rx_mode (struct net_device *dev)
{
struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
unsigned long flags;
u32 mc_filter[2]; /* Multicast hash filter */
int i, rx_mode;
u32 tmp;
......@@ -2353,22 +2376,28 @@ static void rtl8139_set_rx_mode (struct net_device *dev)
}
}
spin_lock_irqsave (&tp->lock, flags);
/* We can safely update without stopping the chip. */
tmp = rtl8139_rx_config | rx_mode;
if (tp->rx_config != tmp) {
RTL_W32 (RxConfig, tmp);
RTL_W32_F (RxConfig, tmp);
tp->rx_config = tmp;
}
RTL_W32_F (MAR0 + 0, mc_filter[0]);
RTL_W32_F (MAR0 + 4, mc_filter[1]);
spin_unlock_irqrestore (&tp->lock, flags);
DPRINTK ("EXIT\n");
}
static void rtl8139_set_rx_mode (struct net_device *dev)
{
unsigned long flags;
struct rtl8139_private *tp = dev->priv;
spin_lock_irqsave (&tp->lock, flags);
__set_rx_mode(dev);
spin_unlock_irqrestore (&tp->lock, flags);
}
#ifdef CONFIG_PM
......
This diff is collapsed.
......@@ -148,10 +148,10 @@ void __devinit tulip_parse_eeprom(struct net_device *dev)
for (i = 0; i < count; i++) {
unsigned char media_block = *p++;
int media_code = media_block & MEDIA_MASK;
if (media_code & 0x40)
if (media_block & 0x40)
p += 6;
printk(KERN_INFO "%s: 21041 media #%d, %s.\n",
dev->name, media_code & 15, medianame[media_code & 15]);
dev->name, media_code, medianame[media_code]);
}
} else {
unsigned char *p = (void *)ee_data + ee_data[27];
......
......@@ -301,7 +301,7 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
long ioaddr = dev->base_addr;
int csr5;
int entry;
int missed;
int csr8;
int rx = 0;
int tx = 0;
int oi = 0;
......@@ -434,7 +434,6 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
}
}
if (csr5 & RxDied) { /* Missed a Rx frame. */
tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
#ifdef CONFIG_NET_HW_FLOWCONTROL
if (tp->fc_bit && !test_bit(tp->fc_bit, &netdev_fc_xoff)) {
tp->stats.rx_errors++;
......@@ -548,9 +547,8 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
}
}
if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) {
tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
}
csr8 = inl(ioaddr + CSR8);
tp->stats.rx_dropped += (csr8 & 0x1ffff) + ((csr8 >> 17) & 0xfff);
if (tulip_debug > 4)
printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
......
......@@ -15,8 +15,8 @@
*/
#define DRV_NAME "tulip"
#define DRV_VERSION "0.9.15-pre6"
#define DRV_RELDATE "July 2, 2001"
#define DRV_VERSION "0.9.15-pre7"
#define DRV_RELDATE "Oct 2, 2001"
#include <linux/config.h>
#include <linux/module.h>
......
......@@ -341,6 +341,7 @@ static int do8bitIO = 0;
/* The RIDs */
#define RID_CAPABILITIES 0xFF00
#define RID_RSSI 0xFF04
#define RID_CONFIG 0xFF10
#define RID_SSID 0xFF11
#define RID_APLIST 0xFF12
......@@ -627,6 +628,16 @@ typedef struct {
u16 atimWindow;
} BSSListRid;
typedef struct {
u8 rssipct;
u8 rssidBm;
} tdsRssiEntry;
typedef struct {
u16 len;
tdsRssiEntry x[256];
} tdsRssiRid;
#pragma pack()
#define TXCTL_TXOK (1<<1) /* report if tx is ok */
......@@ -774,6 +785,7 @@ struct airo_info {
int whichbap);
int (*header_parse)(struct sk_buff*, unsigned char *);
unsigned short *flash;
tdsRssiEntry *rssi;
#ifdef WIRELESS_EXT
int need_commit; // Need to set config
struct iw_statistics wstats; // wireless stats
......@@ -1076,6 +1088,8 @@ void stop_airo_card( struct net_device *dev, int freeres )
struct airo_info *ai = (struct airo_info*)dev->priv;
if (ai->flash)
kfree(ai->flash);
if (ai->rssi)
kfree(ai->rssi);
takedown_proc_entry( dev, ai );
if (ai->registered) {
unregister_netdev( dev );
......@@ -1382,7 +1396,10 @@ static void airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) {
if (!memcmp(sa,apriv->spy_address[i],6))
{
apriv->spy_stat[i].qual = hdr.rssi[0];
apriv->spy_stat[i].level = hdr.rssi[1];
if (apriv->rssi)
apriv->spy_stat[i].level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm;
else
apriv->spy_stat[i].level = (hdr.rssi[1] + 321) / 2;
apriv->spy_stat[i].noise = 0;
apriv->spy_stat[i].updated = 3;
break;
......@@ -1568,9 +1585,29 @@ static u16 setup_card(struct airo_info *ai, u8 *mac,
if ( config->len ) {
cfg = *config;
} else {
tdsRssiRid rssi_rid;
// general configuration (read/modify/write)
status = readConfigRid(ai, &cfg);
if ( status != SUCCESS ) return ERROR;
status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid));
if ( status == SUCCESS ) {
if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512);
}
else {
CapabilityRid cap_rid;
if (ai->rssi) {
kfree(ai->rssi);
ai->rssi = NULL;
}
status = readCapabilityRid(ai, &cap_rid);
if ((status == SUCCESS) && (cap_rid.softCap & 8))
cfg.rmode |= RXMODE_NORMALIZED_RSSI;
else
printk(KERN_WARNING "airo: unknown received signal level\n");
}
cfg.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;
/* Save off the MAC */
......@@ -3814,7 +3851,7 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
/* Hum... Should put the right values there */
range.max_qual.qual = 10;
range.max_qual.level = 100;
range.max_qual.level = 0;
range.max_qual.noise = 0;
range.sensitivity = 65535;
......@@ -3976,7 +4013,10 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
loseSync = 0;
memcpy(s[i].sa_data, BSSList.bssid, 6);
s[i].sa_family = ARPHRD_ETHER;
qual[i].level = BSSList.rssi;
if (local->rssi)
qual[i].level = 0x100 - local->rssi[BSSList.rssi].rssidBm;
else
qual[i].level = (BSSList.rssi + 321) / 2;
qual[i].qual = qual[i].noise = 0;
qual[i].updated = 2;
if (BSSList.index == 0xffff) break;
......@@ -4190,7 +4230,10 @@ struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
/* Signal quality and co. But where is the noise level ??? */
local->wstats.qual.qual = status_rid.signalQuality;
local->wstats.qual.level = status_rid.normalizedSignalStrength;
if (local->rssi)
local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm;
else
local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
local->wstats.qual.noise = 0;
local->wstats.qual.updated = 3;
......
......@@ -14,8 +14,31 @@
* particular order).
*
* Copyright (C) 2000, David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
* Copyright (C) 2001, David Gibson, IBM <hermes@gibson.dropbear.id.au>
*
* This file distributed under the GPL, version 2. */
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
......@@ -30,10 +53,10 @@
#include "hermes.h"
static char version[] __initdata = "hermes.c: 1 Aug 2001 David Gibson <hermes@gibson.dropbear.id.au>";
static char version[] __initdata = "hermes.c: 3 Oct 2001 David Gibson <hermes@gibson.dropbear.id.au>";
MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller");
MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
MODULE_LICENSE("GPL");
MODULE_LICENSE("Dual MPL/GPL");
/* These are maximum timeouts. Most often, card wil react much faster */
#define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
......@@ -42,9 +65,6 @@ MODULE_LICENSE("GPL");
#define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
#define BAP_BUSY_TIMEOUT (500) /* In iterations of ~1us */
#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
/*
* Debugging helpers
*/
......@@ -292,7 +312,7 @@ int hermes_allocate(hermes_t *hw, uint16_t size, uint16_t *fid)
* from firmware
*
* Callable from any context */
static int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset)
int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset)
{
int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
......@@ -305,9 +325,14 @@ static int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset)
k = BAP_BUSY_TIMEOUT;
reg = hermes_read_reg(hw, oreg);
while ((reg & HERMES_OFFSET_BUSY) & k) {
k--;
udelay(1);
reg = hermes_read_reg(hw, oreg);
}
if (reg & HERMES_OFFSET_BUSY)
return -EBUSY;
return -ETIMEDOUT;
/* Now we actually set up the transfer */
hermes_write_reg(hw, sreg, id);
......@@ -342,7 +367,7 @@ static int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset)
*
* Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
*/
int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
uint16_t id, uint16_t offset)
{
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
......@@ -356,7 +381,7 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
goto out;
/* Actually do the transfer */
hermes_read_data(hw, dreg, buf, len/2);
hermes_read_words(hw, dreg, buf, len/2);
out:
return err;
......@@ -368,7 +393,7 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
*
* Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
*/
int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, uint16_t len,
int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
uint16_t id, uint16_t offset)
{
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
......@@ -382,7 +407,7 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, uint16_t len,
goto out;
/* Actually do the transfer */
hermes_write_data(hw, dreg, buf, len/2);
hermes_write_words(hw, dreg, buf, len/2);
out:
return err;
......@@ -434,17 +459,7 @@ int hermes_read_ltv(hermes_t *hw, int bap, uint16_t rid, int buflen,
lengths in the records seem to be wrong, frequently */
count = buflen / 2;
#if 0
if (length)
count = (MIN(buflen, rlength) + 1) / 2;
else {
count = buflen / 2;
if (rlength != buflen)
printk(KERN_WARNING "hermes_read_ltv(): Incorrect \
record length %d instead of %d on RID 0x%04x\n", rlength, buflen, rid);
}
#endif
hermes_read_data(hw, dreg, buf, count);
hermes_read_words(hw, dreg, buf, count);
out:
return err;
......@@ -470,7 +485,7 @@ int hermes_write_ltv(hermes_t *hw, int bap, uint16_t rid,
count = length - 1;
hermes_write_data(hw, dreg, value, count);
hermes_write_words(hw, dreg, value, count);
err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE,
rid, &resp);
......
......@@ -50,6 +50,7 @@
#define HERMES_FRAME_LEN_MAX (2304)
#define HERMES_MAX_MULTICAST (16)
#define HERMES_MAGIC (0x7d1f)
#define HERMES_SYMBOL_MAX_VER (14)
/*
* Hermes register offsets
......@@ -202,24 +203,21 @@
#define HERMES_RID_WEP_AVAIL (0xfd4f)
#define HERMES_RID_CURRENT_CHANNEL (0xfdc1)
#define HERMES_RID_DATARATES (0xfdc6)
#define HERMES_RID_SYMBOL_PRIMARY_VER (0xfd03)
#define HERMES_RID_SYMBOL_SECONDARY_VER (0xfd21)
#define HERMES_RID_SYMBOL_SECONDARY_VER (0xfd24)
#define HERMES_RID_SYMBOL_KEY_LENGTH (0xfc2B)
/*
* Frame structures and constants
*/
#define __PACKED__ __attribute__ ((packed))
typedef struct hermes_frame_desc {
/* Hermes - i.e. little-endian byte-order */
uint16_t status __PACKED__;
uint16_t res1, res2 __PACKED__;
uint16_t q_info __PACKED__;
uint16_t res3, res4 __PACKED__;
uint16_t tx_ctl __PACKED__;
} hermes_frame_desc_t;
uint16_t status;
uint16_t res1, res2;
uint16_t q_info;
uint16_t res3, res4;
uint16_t tx_ctl;
} __attribute__ ((packed)) hermes_frame_desc_t;
#define HERMES_RXSTAT_ERR (0x0003)
#define HERMES_RXSTAT_MACPORT (0x0700)
......@@ -265,20 +263,16 @@ typedef struct hermes_multicast {
#define hermes_read_regn(hw, name) (hermes_read_reg((hw), HERMES_##name))
#define hermes_write_regn(hw, name, val) (hermes_write_reg((hw), HERMES_##name, (val)))
/* Note that for the next two, the count is in 16-bit words, not bytes */
#define hermes_read_data(hw, off, buf, count) (insw((hw)->iobase + (off), (buf), (count)))
#define hermes_write_data(hw, off, buf, count) (outsw((hw)->iobase + (off), (buf), (count)))
/* Function prototypes */
void hermes_struct_init(hermes_t *hw, uint io);
int hermes_reset(hermes_t *hw);
int hermes_docmd_wait(hermes_t *hw, uint16_t cmd, uint16_t parm0, hermes_response_t *resp);
int hermes_allocate(hermes_t *hw, uint16_t size, uint16_t *fid);
int hermes_bap_pread(hermes_t *hw, int bap, void *buf, uint16_t len,
int hermes_bap_seek(hermes_t *hw, int bap, uint16_t id, uint16_t offset);
int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
uint16_t id, uint16_t offset);
int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, uint16_t len,
int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
uint16_t id, uint16_t offset);
int hermes_read_ltv(hermes_t *hw, int bap, uint16_t rid, int buflen,
uint16_t *length, void *buf);
......@@ -323,6 +317,10 @@ static inline int hermes_disable_port(hermes_t *hw, int port)
#define HERMES_BYTES_TO_RECLEN(n) ( ((n) % 2) ? (((n)+1)/2)+1 : ((n)/2)+1 )
#define HERMES_RECLEN_TO_BYTES(n) ( ((n)-1) * 2 )
/* Note that for the next two, the count is in 16-bit words, not bytes */
#define hermes_read_words(hw, off, buf, count) (insw((hw)->iobase + (off), (buf), (count)))
#define hermes_write_words(hw, off, buf, count) (outsw((hw)->iobase + (off), (buf), (count)))
#define HERMES_READ_RECORD(hw, bap, rid, buf) \
(hermes_read_ltv((hw),(bap),(rid), sizeof(*buf), NULL, (buf)))
#define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -99,7 +99,7 @@ decode_pathname(u32 *p, char **namp, int *lenp)
char *name;
int i;
if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXPATHLEN)) != NULL) {
if ((p = xdr_decode_string(p, namp, lenp, NFS3_MAXPATHLEN)) != NULL) {
for (i = 0, name = *namp; i < *lenp; i++, name++) {
if (*name == '\0')
return NULL;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
int ibm_partition(struct gendisk *, kdev_t, unsigned long, int);
int ibm_partition(struct gendisk *, struct block_device *, unsigned long, int);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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