Commit b83290ea authored by Dave Jones's avatar Dave Jones

Merge delerium.codemonkey.org.uk:/mnt/nfs/sepia/bar/src/kernel/2.6/trees/bk-linus

into delerium.codemonkey.org.uk:/mnt/nfs/sepia/bar/src/kernel/2.6/trees/agpgart
parents 06477bc3 e689bf58
VERSION = 2 VERSION = 2
PATCHLEVEL = 6 PATCHLEVEL = 6
SUBLEVEL = 0 SUBLEVEL = 0
EXTRAVERSION = -test10 EXTRAVERSION = -test11
# *DOCUMENTATION* # *DOCUMENTATION*
# To see a list of typical targets execute "make help" # To see a list of typical targets execute "make help"
......
...@@ -1910,7 +1910,7 @@ unw_unwind_to_user (struct unw_frame_info *info) ...@@ -1910,7 +1910,7 @@ unw_unwind_to_user (struct unw_frame_info *info)
__FUNCTION__, ip); __FUNCTION__, ip);
return -1; return -1;
} }
if (ip < GATE_ADDR) if (ip < FIXADDR_USER_END)
return 0; return 0;
} }
unw_get_ip(info, &ip); unw_get_ip(info, &ip);
......
...@@ -472,6 +472,15 @@ extern __inline__ unsigned long do_gettimeoffset(void) ...@@ -472,6 +472,15 @@ extern __inline__ unsigned long do_gettimeoffset(void)
return (*master_l10_counter >> 10) & 0x1fffff; return (*master_l10_counter >> 10) & 0x1fffff;
} }
/*
* Returns nanoseconds
* XXX This is a suboptimal implementation.
*/
unsigned long long sched_clock(void)
{
return (unsigned long long)jiffies * (1000000000 / HZ);
}
/* Ok, my cute asm atomicity trick doesn't work anymore. /* Ok, my cute asm atomicity trick doesn't work anymore.
* There are just too many variables that need to be protected * There are just too many variables that need to be protected
* now (both members of xtime, wall_jiffies, et al.) * now (both members of xtime, wall_jiffies, et al.)
......
...@@ -202,6 +202,7 @@ static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer, ...@@ -202,6 +202,7 @@ static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
if (csraddr < CSR_TOPOLOGY_MAP) { if (csraddr < CSR_TOPOLOGY_MAP) {
if (csraddr + length > CSR_CONFIG_ROM + host->csr.rom_size) { if (csraddr + length > CSR_CONFIG_ROM + host->csr.rom_size) {
spin_unlock_irqrestore(&host->csr.lock, flags);
return RCODE_ADDRESS_ERROR; return RCODE_ADDRESS_ERROR;
} }
src = ((char *)host->csr.rom) + csraddr - CSR_CONFIG_ROM; src = ((char *)host->csr.rom) + csraddr - CSR_CONFIG_ROM;
......
...@@ -98,7 +98,7 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, ...@@ -98,7 +98,7 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
return NULL; return NULL;
} }
hi = kmalloc(sizeof(*hi) + data_size, GFP_KERNEL); hi = kmalloc(sizeof(*hi) + data_size, GFP_ATOMIC);
if (!hi) if (!hi)
return NULL; return NULL;
......
...@@ -92,7 +92,7 @@ void hpsb_unref_host(struct hpsb_host *host) ...@@ -92,7 +92,7 @@ void hpsb_unref_host(struct hpsb_host *host)
down(&hpsb_hosts_lock); down(&hpsb_hosts_lock);
if (atomic_dec_and_test(&host->refcount) && host->is_shutdown) if (atomic_dec_and_test(&host->refcount) && host->is_shutdown)
kfree(host); device_unregister(&host->device);
up(&hpsb_hosts_lock); up(&hpsb_hosts_lock);
} }
......
...@@ -137,7 +137,7 @@ int hpsb_get_tlabel(struct hpsb_packet *packet) ...@@ -137,7 +137,7 @@ int hpsb_get_tlabel(struct hpsb_packet *packet)
tp = &packet->host->tpool[packet->node_id & NODE_MASK]; tp = &packet->host->tpool[packet->node_id & NODE_MASK];
if (in_interrupt() || in_atomic()) { if (irqs_disabled() || in_atomic()) {
if (down_trylock(&tp->count)) if (down_trylock(&tp->count))
return 1; return 1;
} else { } else {
......
...@@ -13,9 +13,6 @@ ...@@ -13,9 +13,6 @@
#include <asm/byteorder.h> #include <asm/byteorder.h>
/* The great kdev_t changeover in 2.5.x */
#include <linux/kdev_t.h>
/* Transaction Label handling */ /* Transaction Label handling */
struct hpsb_tlabel_pool { struct hpsb_tlabel_pool {
DECLARE_BITMAP(pool, 64); DECLARE_BITMAP(pool, 64);
......
...@@ -420,6 +420,12 @@ static void nodemgr_release_ne(struct device *dev) ...@@ -420,6 +420,12 @@ static void nodemgr_release_ne(struct device *dev)
} }
static void nodemgr_release_host(struct device *dev)
{
kfree(container_of(dev, struct hpsb_host, device));
}
static void nodemgr_remove_ud(struct unit_directory *ud) static void nodemgr_remove_ud(struct unit_directory *ud)
{ {
struct device *dev = &ud->device; struct device *dev = &ud->device;
...@@ -513,6 +519,7 @@ static struct device nodemgr_dev_template_ne = { ...@@ -513,6 +519,7 @@ static struct device nodemgr_dev_template_ne = {
static struct device nodemgr_dev_template_host = { static struct device nodemgr_dev_template_host = {
.bus = &ieee1394_bus_type, .bus = &ieee1394_bus_type,
.release = nodemgr_release_host,
.driver = &nodemgr_driver_host, .driver = &nodemgr_driver_host,
.driver_data = &nodemgr_driverdata_host, .driver_data = &nodemgr_driverdata_host,
}; };
...@@ -676,8 +683,27 @@ static struct node_entry *nodemgr_scan_root_directory ...@@ -676,8 +683,27 @@ static struct node_entry *nodemgr_scan_root_directory
} }
static void nodemgr_process_config_rom(struct host_info *hi, static void nodemgr_update_bus_options(struct node_entry *ne,
struct node_entry *ne, quadlet_t busoptions); quadlet_t busoptions)
{
ne->busopt.irmc = (busoptions >> 31) & 1;
ne->busopt.cmc = (busoptions >> 30) & 1;
ne->busopt.isc = (busoptions >> 29) & 1;
ne->busopt.bmc = (busoptions >> 28) & 1;
ne->busopt.pmc = (busoptions >> 27) & 1;
ne->busopt.cyc_clk_acc = (busoptions >> 16) & 0xff;
ne->busopt.max_rec = 1 << (((busoptions >> 12) & 0xf) + 1);
ne->busopt.generation = (busoptions >> 4) & 0xf;
ne->busopt.lnkspd = busoptions & 0x7;
HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d "
"cyc_clk_acc=%d max_rec=%d gen=%d lspd=%d",
busoptions, ne->busopt.irmc, ne->busopt.cmc,
ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc,
ne->busopt.cyc_clk_acc, ne->busopt.max_rec,
ne->busopt.generation, ne->busopt.lnkspd);
}
static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoptions, static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoptions,
struct host_info *hi, nodeid_t nodeid, struct host_info *hi, nodeid_t nodeid,
...@@ -694,6 +720,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoption ...@@ -694,6 +720,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoption
ne->host = host; ne->host = host;
ne->nodeid = nodeid; ne->nodeid = nodeid;
ne->generation = generation; ne->generation = generation;
ne->needs_probe = 1;
ne->guid = guid; ne->guid = guid;
ne->guid_vendor_id = (guid >> 40) & 0xffffff; ne->guid_vendor_id = (guid >> 40) & 0xffffff;
...@@ -711,7 +738,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoption ...@@ -711,7 +738,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoption
device_create_file(&ne->device, &dev_attr_ne_guid_vendor_oui); device_create_file(&ne->device, &dev_attr_ne_guid_vendor_oui);
nodemgr_create_ne_dev_files(ne); nodemgr_create_ne_dev_files(ne);
nodemgr_process_config_rom (hi, ne, busoptions); nodemgr_update_bus_options(ne, busoptions);
HPSB_DEBUG("%s added: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", HPSB_DEBUG("%s added: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
(host->node_id == nodeid) ? "Host" : "Node", (host->node_id == nodeid) ? "Host" : "Node",
...@@ -806,6 +833,7 @@ static struct unit_directory *nodemgr_scan_unit_directory ...@@ -806,6 +833,7 @@ static struct unit_directory *nodemgr_scan_unit_directory
if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad)) if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad))
return NULL; return NULL;
length = CONFIG_ROM_DIRECTORY_LENGTH(quad) ; length = CONFIG_ROM_DIRECTORY_LENGTH(quad) ;
address += 4; address += 4;
...@@ -1069,6 +1097,8 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent ...@@ -1069,6 +1097,8 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
int length; int length;
unsigned int ud_id = 0; unsigned int ud_id = 0;
device_remove_file(&ne->device, &dev_attr_ne_vendor_oui);
address = CSR_REGISTER_BASE + CSR_CONFIG_ROM; address = CSR_REGISTER_BASE + CSR_CONFIG_ROM;
if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,
...@@ -1129,6 +1159,9 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent ...@@ -1129,6 +1159,9 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
break; break;
} }
} }
if (ne->vendor_oui)
device_create_file(&ne->device, &dev_attr_ne_vendor_oui);
} }
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
...@@ -1221,34 +1254,6 @@ void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver) ...@@ -1221,34 +1254,6 @@ void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver)
driver_unregister(&driver->driver); driver_unregister(&driver->driver);
} }
static void nodemgr_process_config_rom(struct host_info *hi,
struct node_entry *ne, quadlet_t busoptions)
{
ne->busopt.irmc = (busoptions >> 31) & 1;
ne->busopt.cmc = (busoptions >> 30) & 1;
ne->busopt.isc = (busoptions >> 29) & 1;
ne->busopt.bmc = (busoptions >> 28) & 1;
ne->busopt.pmc = (busoptions >> 27) & 1;
ne->busopt.cyc_clk_acc = (busoptions >> 16) & 0xff;
ne->busopt.max_rec = 1 << (((busoptions >> 12) & 0xf) + 1);
ne->busopt.generation = (busoptions >> 4) & 0xf;
ne->busopt.lnkspd = busoptions & 0x7;
HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d "
"cyc_clk_acc=%d max_rec=%d gen=%d lspd=%d",
busoptions, ne->busopt.irmc, ne->busopt.cmc,
ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc,
ne->busopt.cyc_clk_acc, ne->busopt.max_rec,
ne->busopt.generation, ne->busopt.lnkspd);
device_remove_file(&ne->device, &dev_attr_ne_vendor_oui);
nodemgr_process_root_directory(hi, ne);
if (ne->vendor_oui)
device_create_file(&ne->device, &dev_attr_ne_vendor_oui);
}
/* Searches the list of ud's that match a ne as the parent. If the ud has /* Searches the list of ud's that match a ne as the parent. If the ud has
* a driver associated with it, we call that driver's update function * a driver associated with it, we call that driver's update function
...@@ -1303,18 +1308,14 @@ static void nodemgr_update_node(struct node_entry *ne, quadlet_t busoptions, ...@@ -1303,18 +1308,14 @@ static void nodemgr_update_node(struct node_entry *ne, quadlet_t busoptions,
* unregister all the unit directories. */ * unregister all the unit directories. */
nodemgr_remove_node_uds(ne); nodemgr_remove_node_uds(ne);
/* With all the ud's gone, mark the generation current, nodemgr_update_bus_options(ne, busoptions);
* this way the probe will succeed. */
ne->generation = generation;
/* This will re-register our unitdir's */ /* Mark the node as new, so it gets re-probed */
nodemgr_process_config_rom (hi, ne, busoptions); ne->needs_probe = 1;
} else }
ne->generation = generation;
/* Update unit_dirs with attached drivers */ /* Mark the node current */
bus_for_each_dev(&ieee1394_bus_type, NULL, ne, ne->generation = generation;
nodemgr_driver_search_cb);
} }
static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid, unsigned int generation, static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid, unsigned int generation,
...@@ -1385,9 +1386,7 @@ static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid, unsigned ...@@ -1385,9 +1386,7 @@ static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid, unsigned
} }
/* This is where we probe the nodes for their information and provided static void nodemgr_node_scan_one(struct host_info *hi,
* features. */
static void nodemgr_node_probe_one(struct host_info *hi,
nodeid_t nodeid, int generation) nodeid_t nodeid, int generation)
{ {
struct hpsb_host *host = hi->host; struct hpsb_host *host = hi->host;
...@@ -1453,8 +1452,43 @@ static int nodemgr_remove_node(struct device *dev, void *__data) ...@@ -1453,8 +1452,43 @@ static int nodemgr_remove_node(struct device *dev, void *__data)
return 0; return 0;
} }
struct ne_cb_data_struct {
struct host_info *hi;
struct node_entry *ne;
};
static void nodemgr_node_probe(struct host_info *hi, int generation) static int nodemgr_probe_ne_cb(struct device *dev, void *__data)
{
struct ne_cb_data_struct *ne_cb_data = __data;
struct host_info *hi = ne_cb_data->hi;
struct node_entry *ne;
if (dev->driver_data != &nodemgr_driverdata_ne)
return 0;
ne = ne_cb_data->ne = container_of(dev, struct node_entry, device);
if (ne->host != hi->host)
return 0;
/* We can't call nodemgr_process_root_directory() here because
* that can call device_register. Since this callback is under a
* rwsem, the device_register would deadlock. So, we signal back
* to the callback, and process things there. */
if (ne->needs_probe) {
ne->needs_probe = 0;
return 1;
} else {
/* Update unit_dirs with attached drivers */
bus_for_each_dev(&ieee1394_bus_type, NULL, ne,
nodemgr_driver_search_cb);
}
return 0;
}
static void nodemgr_node_scan(struct host_info *hi, int generation)
{ {
int count; int count;
struct hpsb_host *host = hi->host; struct hpsb_host *host = hi->host;
...@@ -1470,7 +1504,32 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) ...@@ -1470,7 +1504,32 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
nodeid++; nodeid++;
continue; continue;
} }
nodemgr_node_probe_one(hi, nodeid++, generation); nodemgr_node_scan_one(hi, nodeid++, generation);
}
}
static void nodemgr_node_probe(struct host_info *hi, int generation)
{
struct hpsb_host *host = hi->host;
struct ne_cb_data_struct ne_cb_data;
ne_cb_data.hi = hi;
ne_cb_data.ne = NULL;
/* Do some processing of the nodes we've probed. This pulls them
* into the sysfs layer if needed, and can result in processing of
* unit-directories, or just updating the node and it's
* unit-directories. */
while (bus_for_each_dev(&ieee1394_bus_type, ne_cb_data.ne ? &ne_cb_data.ne->device : NULL,
&ne_cb_data, nodemgr_probe_ne_cb)) {
/* If we get in here, we've got a node that needs it's
* unit directories processed. */
struct device *dev = get_device(&ne_cb_data.ne->device);
if (dev) {
nodemgr_process_root_directory(hi, ne_cb_data.ne);
put_device(dev);
}
} }
/* If we had a bus reset while we were scanning the bus, it is /* If we had a bus reset while we were scanning the bus, it is
...@@ -1513,12 +1572,12 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) ...@@ -1513,12 +1572,12 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
/* Because we are a 1394a-2000 compliant IRM, we need to inform all the other /* Because we are a 1394a-2000 compliant IRM, we need to inform all the other
* nodes of the broadcast channel. (Really we're only setting the validity * nodes of the broadcast channel. (Really we're only setting the validity
* bit). Other IRM responsibilities go in here as well. */ * bit). Other IRM responsibilities go in here as well. */
static void nodemgr_do_irm_duties(struct hpsb_host *host) static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles)
{ {
quadlet_t bc; quadlet_t bc;
if (!host->is_irm) if (!host->is_irm)
return; return 1;
host->csr.broadcast_channel |= 0x40000000; /* set validity bit */ host->csr.broadcast_channel |= 0x40000000; /* set validity bit */
...@@ -1541,10 +1600,21 @@ static void nodemgr_do_irm_duties(struct hpsb_host *host) ...@@ -1541,10 +1600,21 @@ static void nodemgr_do_irm_duties(struct hpsb_host *host)
else { else {
HPSB_DEBUG("The root node is not cycle master capable; " HPSB_DEBUG("The root node is not cycle master capable; "
"selecting a new root node and resetting..."); "selecting a new root node and resetting...");
if (cycles >= 5) {
/* Oh screw it! Just leave the bus as it is */
HPSB_DEBUG("Stopping reset loop for IRM sanity");
return 1;
}
hpsb_send_phy_config(host, NODEID_TO_NODE(host->node_id), -1); hpsb_send_phy_config(host, NODEID_TO_NODE(host->node_id), -1);
hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT); hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT);
return 0;
} }
} }
return 1;
} }
/* We need to ensure that if we are not the IRM, that the IRM node is capable of /* We need to ensure that if we are not the IRM, that the IRM node is capable of
...@@ -1608,8 +1678,10 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1608,8 +1678,10 @@ static int nodemgr_host_thread(void *__hi)
* to make sure things settle down. */ * to make sure things settle down. */
for (i = 0; i < 4 ; i++) { for (i = 0; i < 4 ; i++) {
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (schedule_timeout(HZ/16)) if (schedule_timeout(HZ/16)) {
up(&nodemgr_serialize);
goto caught_signal; goto caught_signal;
}
/* Now get the generation in which the node ID's we collect /* Now get the generation in which the node ID's we collect
* are valid. During the bus scan we will use this generation * are valid. During the bus scan we will use this generation
...@@ -1624,16 +1696,28 @@ static int nodemgr_host_thread(void *__hi) ...@@ -1624,16 +1696,28 @@ static int nodemgr_host_thread(void *__hi)
i = 0; i = 0;
} }
if (!nodemgr_check_irm_capability(host, reset_cycles++)) { if (!nodemgr_check_irm_capability(host, reset_cycles)) {
/* Do nothing, we are resetting */ reset_cycles++;
up(&nodemgr_serialize);
continue;
}
/* Scan our nodes to get the bus options and create node
* entries. This does not do the sysfs stuff, since that
* would trigger hotplug callbacks and such, which is a
* bad idea at this point. */
nodemgr_node_scan(hi, generation);
if (!nodemgr_do_irm_duties(host, reset_cycles)) {
reset_cycles++;
up(&nodemgr_serialize); up(&nodemgr_serialize);
continue; continue;
} }
reset_cycles = 0; reset_cycles = 0;
/* This actually does the full probe, with sysfs
* registration. */
nodemgr_node_probe(hi, generation); nodemgr_node_probe(hi, generation);
nodemgr_do_irm_duties(host);
/* Update some of our sysfs symlinks */ /* Update some of our sysfs symlinks */
nodemgr_update_host_dev_links(host); nodemgr_update_host_dev_links(host);
...@@ -1778,7 +1862,6 @@ static void nodemgr_remove_host(struct hpsb_host *host) ...@@ -1778,7 +1862,6 @@ static void nodemgr_remove_host(struct hpsb_host *host)
kill_proc(hi->pid, SIGTERM, 1); kill_proc(hi->pid, SIGTERM, 1);
wait_for_completion(&hi->exited); wait_for_completion(&hi->exited);
nodemgr_remove_host_dev(&host->device); nodemgr_remove_host_dev(&host->device);
device_unregister(&host->device);
} }
} else } else
HPSB_ERR("NodeMgr: host %s does not exist, cannot remove", HPSB_ERR("NodeMgr: host %s does not exist, cannot remove",
......
...@@ -130,6 +130,7 @@ struct node_entry { ...@@ -130,6 +130,7 @@ struct node_entry {
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 */
int needs_probe;
unsigned int generation; /* Synced with hpsb generation */ unsigned int generation; /* Synced with hpsb generation */
/* The following is read from the config rom */ /* The following is read from the config rom */
......
...@@ -524,7 +524,7 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base) ...@@ -524,7 +524,7 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base)
return 0; return 0;
out3: out3:
release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT); release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT);
out2: out2:
release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT); release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT);
out1: out1:
......
...@@ -352,7 +352,8 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) ...@@ -352,7 +352,8 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
if (!__pppoe_xmit( relay_po->sk, skb)) if (!__pppoe_xmit( relay_po->sk, skb))
goto abort_put; goto abort_put;
} else { } else {
sock_queue_rcv_skb(sk, skb); if (sock_queue_rcv_skb(sk, skb))
goto abort_kfree;
} }
return NET_RX_SUCCESS; return NET_RX_SUCCESS;
......
...@@ -133,7 +133,11 @@ void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf) ...@@ -133,7 +133,11 @@ void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
struct ata_ioports *ioaddr = &ap->ioaddr; struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
if (tf->ctl != ap->last_ctl) {
outb(tf->ctl, ioaddr->ctl_addr); outb(tf->ctl, ioaddr->ctl_addr);
ap->last_ctl = tf->ctl;
ata_wait_idle(ap);
}
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
outb(tf->hob_feature, ioaddr->error_addr); outb(tf->hob_feature, ioaddr->error_addr);
...@@ -187,7 +191,11 @@ void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) ...@@ -187,7 +191,11 @@ void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
struct ata_ioports *ioaddr = &ap->ioaddr; struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
if (tf->ctl != ap->last_ctl) {
writeb(tf->ctl, ap->ioaddr.ctl_addr); writeb(tf->ctl, ap->ioaddr.ctl_addr);
ap->last_ctl = tf->ctl;
ata_wait_idle(ap);
}
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
writeb(tf->hob_feature, (void *) ioaddr->error_addr); writeb(tf->hob_feature, (void *) ioaddr->error_addr);
...@@ -1281,9 +1289,9 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, ...@@ -1281,9 +1289,9 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
/* software reset. causes dev0 to be selected */ /* software reset. causes dev0 to be selected */
if (ap->flags & ATA_FLAG_MMIO) { if (ap->flags & ATA_FLAG_MMIO) {
writeb(ap->ctl, ioaddr->ctl_addr); writeb(ap->ctl, ioaddr->ctl_addr);
udelay(10); /* FIXME: flush */ udelay(20); /* FIXME: flush */
writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr); writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
udelay(10); /* FIXME: flush */ udelay(20); /* FIXME: flush */
writeb(ap->ctl, ioaddr->ctl_addr); writeb(ap->ctl, ioaddr->ctl_addr);
} else { } else {
outb(ap->ctl, ioaddr->ctl_addr); outb(ap->ctl, ioaddr->ctl_addr);
...@@ -2755,6 +2763,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ...@@ -2755,6 +2763,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
ap->cbl = ATA_CBL_NONE; ap->cbl = ATA_CBL_NONE;
ap->device[0].flags = ATA_DFLAG_MASTER; ap->device[0].flags = ATA_DFLAG_MASTER;
ap->active_tag = ATA_TAG_POISON; ap->active_tag = ATA_TAG_POISON;
ap->last_ctl = 0xFF;
/* ata_engine init */ /* ata_engine init */
ap->eng.flags = 0; ap->eng.flags = 0;
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#define __LIBATA_H__ #define __LIBATA_H__
#define DRV_NAME "libata" #define DRV_NAME "libata"
#define DRV_VERSION "0.80" /* must be exactly four chars */ #define DRV_VERSION "0.81" /* must be exactly four chars */
struct ata_scsi_args { struct ata_scsi_args {
struct ata_port *ap; struct ata_port *ap;
......
...@@ -213,6 +213,8 @@ static struct pci_device_id pdc_sata_pci_tbl[] = { ...@@ -213,6 +213,8 @@ static struct pci_device_id pdc_sata_pci_tbl[] = {
board_2037x }, board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x }, board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 }, board_20319 },
{ PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#endif /* CONFIG_ALL_PPC */ #endif /* CONFIG_ALL_PPC */
#define DRV_NAME "ata_k2" #define DRV_NAME "ata_k2"
#define DRV_VERSION "1.02" #define DRV_VERSION "1.03"
static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
...@@ -69,8 +69,11 @@ static void k2_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf) ...@@ -69,8 +69,11 @@ static void k2_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
struct ata_ioports *ioaddr = &ap->ioaddr; struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
if (tf->ctl != ap->last_ctl) {
writeb(tf->ctl, ioaddr->ctl_addr); writeb(tf->ctl, ioaddr->ctl_addr);
ap->last_ctl = tf->ctl;
ata_wait_idle(ap);
}
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->error_addr); writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->error_addr);
writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr); writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr);
...@@ -311,9 +314,20 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -311,9 +314,20 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
rc = -ENODEV; rc = -ENODEV;
goto err_out_unmap; goto err_out_unmap;
} }
/* Clear a magic bit in SCR1 according to Darwin, those help
* some funky seagate drives (though so far, those were already
* set by the firmware on the machines I had access to
*/
writel(readl(mmio_base + 0x80) & ~0x00040000, mmio_base + 0x80);
/* Clear SATA error & interrupts we don't use */
writel(0xffffffff, mmio_base + 0x44);
writel(0x0, mmio_base + 0x88);
probe_ent->sht = &k2_sata_sht; probe_ent->sht = &k2_sata_sht;
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
ATA_FLAG_SRST | ATA_FLAG_MMIO; ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
probe_ent->port_ops = &k2_sata_ops; probe_ent->port_ops = &k2_sata_ops;
probe_ent->n_ports = 2; probe_ent->n_ports = 2;
probe_ent->irq = pdev->irq; probe_ent->irq = pdev->irq;
......
...@@ -367,6 +367,16 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) ...@@ -367,6 +367,16 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
unsigned long timeout; unsigned long timeout;
int rtn = 0; int rtn = 0;
/* check if the device is still usable */
if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
/* in SDEV_DEL we error all commands. DID_NO_CONNECT
* returns an immediate error upwards, and signals
* that the device is no longer present */
cmd->result = DID_NO_CONNECT << 16;
scsi_done(cmd);
/* return 0 (because the command has been processed) */
goto out;
}
/* Assign a unique nonzero serial_number. */ /* Assign a unique nonzero serial_number. */
/* XXX(hch): this is racy */ /* XXX(hch): this is racy */
if (++serial_number == 0) if (++serial_number == 0)
...@@ -893,7 +903,7 @@ int scsi_track_queue_full(struct scsi_device *sdev, int depth) ...@@ -893,7 +903,7 @@ int scsi_track_queue_full(struct scsi_device *sdev, int depth)
*/ */
int scsi_device_get(struct scsi_device *sdev) int scsi_device_get(struct scsi_device *sdev)
{ {
if (test_bit(SDEV_DEL, &sdev->sdev_state)) if (sdev->sdev_state == SDEV_DEL)
return -ENXIO; return -ENXIO;
if (!get_device(&sdev->sdev_gendev)) if (!get_device(&sdev->sdev_gendev))
return -ENXIO; return -ENXIO;
...@@ -1015,7 +1025,7 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery) ...@@ -1015,7 +1025,7 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery)
struct list_head *lh, *lh_sf; struct list_head *lh, *lh_sf;
unsigned long flags; unsigned long flags;
set_bit(SDEV_CANCEL, &sdev->sdev_state); sdev->sdev_state = SDEV_CANCEL;
spin_lock_irqsave(&sdev->list_lock, flags); spin_lock_irqsave(&sdev->list_lock, flags);
list_for_each_entry(scmd, &sdev->cmd_list, list) { list_for_each_entry(scmd, &sdev->cmd_list, list) {
......
...@@ -911,7 +911,9 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd) ...@@ -911,7 +911,9 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
if (rtn == SUCCESS) { if (rtn == SUCCESS) {
scsi_sleep(BUS_RESET_SETTLE_TIME); scsi_sleep(BUS_RESET_SETTLE_TIME);
spin_lock_irqsave(scmd->device->host->host_lock, flags);
scsi_report_bus_reset(scmd->device->host, scmd->device->channel); scsi_report_bus_reset(scmd->device->host, scmd->device->channel);
spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
} }
return rtn; return rtn;
...@@ -940,7 +942,9 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd) ...@@ -940,7 +942,9 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd)
if (rtn == SUCCESS) { if (rtn == SUCCESS) {
scsi_sleep(HOST_RESET_SETTLE_TIME); scsi_sleep(HOST_RESET_SETTLE_TIME);
spin_lock_irqsave(scmd->device->host->host_lock, flags);
scsi_report_bus_reset(scmd->device->host, scmd->device->channel); scsi_report_bus_reset(scmd->device->host, scmd->device->channel);
spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
} }
return rtn; return rtn;
...@@ -1608,7 +1612,7 @@ int scsi_error_handler(void *data) ...@@ -1608,7 +1612,7 @@ int scsi_error_handler(void *data)
* *
* Returns: Nothing * Returns: Nothing
* *
* Lock status: No locks are assumed held. * Lock status: Host lock must be held.
* *
* Notes: This only needs to be called if the reset is one which * Notes: This only needs to be called if the reset is one which
* originates from an unknown location. Resets originated * originates from an unknown location. Resets originated
...@@ -1622,7 +1626,7 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel) ...@@ -1622,7 +1626,7 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)
{ {
struct scsi_device *sdev; struct scsi_device *sdev;
shost_for_each_device(sdev, shost) { __shost_for_each_device(sdev, shost) {
if (channel == sdev->channel) { if (channel == sdev->channel) {
sdev->was_reset = 1; sdev->was_reset = 1;
sdev->expecting_cc_ua = 1; sdev->expecting_cc_ua = 1;
...@@ -1642,7 +1646,7 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel) ...@@ -1642,7 +1646,7 @@ void scsi_report_bus_reset(struct Scsi_Host *shost, int channel)
* *
* Returns: Nothing * Returns: Nothing
* *
* Lock status: No locks are assumed held. * Lock status: Host lock must be held
* *
* Notes: This only needs to be called if the reset is one which * Notes: This only needs to be called if the reset is one which
* originates from an unknown location. Resets originated * originates from an unknown location. Resets originated
...@@ -1656,7 +1660,7 @@ void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target) ...@@ -1656,7 +1660,7 @@ void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target)
{ {
struct scsi_device *sdev; struct scsi_device *sdev;
shost_for_each_device(sdev, shost) { __shost_for_each_device(sdev, shost) {
if (channel == sdev->channel && if (channel == sdev->channel &&
target == sdev->id) { target == sdev->id) {
sdev->was_reset = 1; sdev->was_reset = 1;
......
...@@ -923,6 +923,22 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) ...@@ -923,6 +923,22 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
{ {
struct scsi_device *sdev = q->queuedata; struct scsi_device *sdev = q->queuedata;
struct scsi_cmnd *cmd; struct scsi_cmnd *cmd;
int specials_only = 0;
if(unlikely(sdev->sdev_state != SDEV_RUNNING)) {
/* OK, we're not in a running state don't prep
* user commands */
if(sdev->sdev_state == SDEV_DEL) {
/* Device is fully deleted, no commands
* at all allowed down */
printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to dead device\n",
sdev->host->host_no, sdev->id, sdev->lun);
return BLKPREP_KILL;
}
/* OK, we only allow special commands (i.e. not
* user initiated ones */
specials_only = 1;
}
/* /*
* Find the actual device driver associated with this command. * Find the actual device driver associated with this command.
...@@ -945,6 +961,14 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) ...@@ -945,6 +961,14 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
} else } else
cmd = req->special; cmd = req->special;
} else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
if(unlikely(specials_only)) {
printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to device being removed\n",
sdev->host->host_no, sdev->id, sdev->lun);
return BLKPREP_KILL;
}
/* /*
* Just check to see if the device is online. If * Just check to see if the device is online. If
* it isn't, we refuse to process ordinary commands * it isn't, we refuse to process ordinary commands
...@@ -1127,6 +1151,10 @@ static void scsi_request_fn(struct request_queue *q) ...@@ -1127,6 +1151,10 @@ static void scsi_request_fn(struct request_queue *q)
struct scsi_cmnd *cmd; struct scsi_cmnd *cmd;
struct request *req; struct request *req;
if(!get_device(&sdev->sdev_gendev))
/* We must be tearing the block queue down already */
return;
/* /*
* To start with, we keep looping until the queue is empty, or until * To start with, we keep looping until the queue is empty, or until
* the host is no longer able to accept any more requests. * the host is no longer able to accept any more requests.
...@@ -1199,7 +1227,7 @@ static void scsi_request_fn(struct request_queue *q) ...@@ -1199,7 +1227,7 @@ static void scsi_request_fn(struct request_queue *q)
} }
} }
return; goto out;
not_ready: not_ready:
spin_unlock_irq(shost->host_lock); spin_unlock_irq(shost->host_lock);
...@@ -1217,6 +1245,12 @@ static void scsi_request_fn(struct request_queue *q) ...@@ -1217,6 +1245,12 @@ static void scsi_request_fn(struct request_queue *q)
sdev->device_busy--; sdev->device_busy--;
if(sdev->device_busy == 0) if(sdev->device_busy == 0)
blk_plug_device(q); blk_plug_device(q);
out:
/* must be careful here...if we trigger the ->remove() function
* we cannot be holding the q lock */
spin_unlock_irq(q->queue_lock);
put_device(&sdev->sdev_gendev);
spin_lock_irq(q->queue_lock);
} }
u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost)
......
...@@ -130,7 +130,6 @@ extern void scsi_exit_procfs(void); ...@@ -130,7 +130,6 @@ extern void scsi_exit_procfs(void);
extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int, extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int,
unsigned int, unsigned int, int); unsigned int, unsigned int, int);
extern void scsi_forget_host(struct Scsi_Host *); extern void scsi_forget_host(struct Scsi_Host *);
extern void scsi_free_sdev(struct scsi_device *);
extern void scsi_rescan_device(struct device *); extern void scsi_rescan_device(struct device *);
/* scsi_sysctl.c */ /* scsi_sysctl.c */
...@@ -143,7 +142,8 @@ extern void scsi_exit_sysctl(void); ...@@ -143,7 +142,8 @@ extern void scsi_exit_sysctl(void);
#endif /* CONFIG_SYSCTL */ #endif /* CONFIG_SYSCTL */
/* scsi_sysfs.c */ /* scsi_sysfs.c */
extern int scsi_device_register(struct scsi_device *); extern void scsi_device_dev_release(struct device *);
extern int scsi_sysfs_add_sdev(struct scsi_device *);
extern int scsi_sysfs_add_host(struct Scsi_Host *); extern int scsi_sysfs_add_host(struct Scsi_Host *);
extern int scsi_sysfs_register(void); extern int scsi_sysfs_register(void);
extern void scsi_sysfs_unregister(void); extern void scsi_sysfs_unregister(void);
......
...@@ -205,6 +205,7 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, ...@@ -205,6 +205,7 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
sdev->lun = lun; sdev->lun = lun;
sdev->channel = channel; sdev->channel = channel;
sdev->online = TRUE; sdev->online = TRUE;
sdev->sdev_state = SDEV_CREATED;
INIT_LIST_HEAD(&sdev->siblings); INIT_LIST_HEAD(&sdev->siblings);
INIT_LIST_HEAD(&sdev->same_target_siblings); INIT_LIST_HEAD(&sdev->same_target_siblings);
INIT_LIST_HEAD(&sdev->cmd_list); INIT_LIST_HEAD(&sdev->cmd_list);
...@@ -236,6 +237,25 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, ...@@ -236,6 +237,25 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
goto out_free_queue; goto out_free_queue;
} }
if (get_device(&sdev->host->shost_gendev)) {
device_initialize(&sdev->sdev_gendev);
sdev->sdev_gendev.parent = &sdev->host->shost_gendev;
sdev->sdev_gendev.bus = &scsi_bus_type;
sdev->sdev_gendev.release = scsi_device_dev_release;
sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d",
sdev->host->host_no, sdev->channel, sdev->id,
sdev->lun);
class_device_initialize(&sdev->sdev_classdev);
sdev->sdev_classdev.dev = &sdev->sdev_gendev;
sdev->sdev_classdev.class = &sdev_class;
snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE,
"%d:%d:%d:%d", sdev->host->host_no,
sdev->channel, sdev->id, sdev->lun);
} else
goto out_free_queue;
/* /*
* If there are any same target siblings, add this to the * If there are any same target siblings, add this to the
* sibling list * sibling list
...@@ -272,36 +292,6 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost, ...@@ -272,36 +292,6 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
return NULL; return NULL;
} }
/**
* scsi_free_sdev - cleanup and free a scsi_device
* @sdev: cleanup and free this scsi_device
*
* Description:
* Undo the actions in scsi_alloc_sdev, including removing @sdev from
* the list, and freeing @sdev.
**/
void scsi_free_sdev(struct scsi_device *sdev)
{
unsigned long flags;
spin_lock_irqsave(sdev->host->host_lock, flags);
list_del(&sdev->siblings);
list_del(&sdev->same_target_siblings);
spin_unlock_irqrestore(sdev->host->host_lock, flags);
if (sdev->request_queue)
scsi_free_queue(sdev->request_queue);
spin_lock_irqsave(sdev->host->host_lock, flags);
list_del(&sdev->starved_entry);
if (sdev->single_lun && --sdev->sdev_target->starget_refcnt == 0)
kfree(sdev->sdev_target);
spin_unlock_irqrestore(sdev->host->host_lock, flags);
kfree(sdev->inquiry);
kfree(sdev);
}
/** /**
* scsi_probe_lun - probe a single LUN using a SCSI INQUIRY * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY
* @sreq: used to send the INQUIRY * @sreq: used to send the INQUIRY
...@@ -642,7 +632,7 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) ...@@ -642,7 +632,7 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
* register it and tell the rest of the kernel * register it and tell the rest of the kernel
* about it. * about it.
*/ */
scsi_device_register(sdev); scsi_sysfs_add_sdev(sdev);
return SCSI_SCAN_LUN_PRESENT; return SCSI_SCAN_LUN_PRESENT;
} }
...@@ -748,8 +738,11 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host, ...@@ -748,8 +738,11 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host,
if (res == SCSI_SCAN_LUN_PRESENT) { if (res == SCSI_SCAN_LUN_PRESENT) {
if (sdevp) if (sdevp)
*sdevp = sdev; *sdevp = sdev;
} else } else {
scsi_free_sdev(sdev); if (sdev->host->hostt->slave_destroy)
sdev->host->hostt->slave_destroy(sdev);
put_device(&sdev->sdev_gendev);
}
out: out:
return res; return res;
} }
...@@ -1301,5 +1294,8 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) ...@@ -1301,5 +1294,8 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
void scsi_free_host_dev(struct scsi_device *sdev) void scsi_free_host_dev(struct scsi_device *sdev)
{ {
BUG_ON(sdev->id != sdev->host->this_id); BUG_ON(sdev->id != sdev->host->this_id);
scsi_free_sdev(sdev);
if (sdev->host->hostt->slave_destroy)
sdev->host->hostt->slave_destroy(sdev);
put_device(&sdev->sdev_gendev);
} }
...@@ -115,14 +115,29 @@ static void scsi_device_cls_release(struct class_device *class_dev) ...@@ -115,14 +115,29 @@ static void scsi_device_cls_release(struct class_device *class_dev)
put_device(&sdev->sdev_gendev); put_device(&sdev->sdev_gendev);
} }
static void scsi_device_dev_release(struct device *dev) void scsi_device_dev_release(struct device *dev)
{ {
struct scsi_device *sdev; struct scsi_device *sdev;
struct device *parent; struct device *parent;
unsigned long flags;
parent = dev->parent; parent = dev->parent;
sdev = to_scsi_device(dev); sdev = to_scsi_device(dev);
scsi_free_sdev(sdev);
spin_lock_irqsave(sdev->host->host_lock, flags);
list_del(&sdev->siblings);
list_del(&sdev->same_target_siblings);
list_del(&sdev->starved_entry);
if (sdev->single_lun && --sdev->sdev_target->starget_refcnt == 0)
kfree(sdev->sdev_target);
spin_unlock_irqrestore(sdev->host->host_lock, flags);
if (sdev->request_queue)
scsi_free_queue(sdev->request_queue);
kfree(sdev->inquiry);
kfree(sdev);
put_device(parent); put_device(parent);
} }
...@@ -321,29 +336,20 @@ static int attr_add(struct device *dev, struct device_attribute *attr) ...@@ -321,29 +336,20 @@ static int attr_add(struct device *dev, struct device_attribute *attr)
} }
/** /**
* scsi_device_register - register a scsi device with the scsi bus * scsi_sysfs_add_sdev - add scsi device to sysfs
* @sdev: scsi_device to register * @sdev: scsi_device to add
* *
* Return value: * Return value:
* 0 on Success / non-zero on Failure * 0 on Success / non-zero on Failure
**/ **/
int scsi_device_register(struct scsi_device *sdev) int scsi_sysfs_add_sdev(struct scsi_device *sdev)
{ {
int error = 0, i; int error = -EINVAL, i;
set_bit(SDEV_ADD, &sdev->sdev_state); if (sdev->sdev_state != SDEV_CREATED)
device_initialize(&sdev->sdev_gendev); return error;
sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d",
sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); sdev->sdev_state = SDEV_RUNNING;
sdev->sdev_gendev.parent = &sdev->host->shost_gendev;
sdev->sdev_gendev.bus = &scsi_bus_type;
sdev->sdev_gendev.release = scsi_device_dev_release;
class_device_initialize(&sdev->sdev_classdev);
sdev->sdev_classdev.dev = &sdev->sdev_gendev;
sdev->sdev_classdev.class = &sdev_class;
snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, "%d:%d:%d:%d",
sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
error = device_add(&sdev->sdev_gendev); error = device_add(&sdev->sdev_gendev);
if (error) { if (error) {
...@@ -351,8 +357,6 @@ int scsi_device_register(struct scsi_device *sdev) ...@@ -351,8 +357,6 @@ int scsi_device_register(struct scsi_device *sdev)
return error; return error;
} }
get_device(sdev->sdev_gendev.parent);
error = class_device_add(&sdev->sdev_classdev); error = class_device_add(&sdev->sdev_classdev);
if (error) { if (error) {
printk(KERN_INFO "error 2\n"); printk(KERN_INFO "error 2\n");
...@@ -384,8 +388,11 @@ int scsi_device_register(struct scsi_device *sdev) ...@@ -384,8 +388,11 @@ int scsi_device_register(struct scsi_device *sdev)
return error; return error;
clean_device: clean_device:
sdev->sdev_state = SDEV_CANCEL;
device_del(&sdev->sdev_gendev); device_del(&sdev->sdev_gendev);
put_device(&sdev->sdev_gendev); put_device(&sdev->sdev_gendev);
return error; return error;
} }
...@@ -396,12 +403,14 @@ int scsi_device_register(struct scsi_device *sdev) ...@@ -396,12 +403,14 @@ int scsi_device_register(struct scsi_device *sdev)
**/ **/
void scsi_remove_device(struct scsi_device *sdev) void scsi_remove_device(struct scsi_device *sdev)
{ {
if (sdev->sdev_state == SDEV_RUNNING || sdev->sdev_state == SDEV_CANCEL) {
sdev->sdev_state = SDEV_DEL;
class_device_unregister(&sdev->sdev_classdev); class_device_unregister(&sdev->sdev_classdev);
set_bit(SDEV_DEL, &sdev->sdev_state); device_del(&sdev->sdev_gendev);
if (sdev->host->hostt->slave_destroy) if (sdev->host->hostt->slave_destroy)
sdev->host->hostt->slave_destroy(sdev); sdev->host->hostt->slave_destroy(sdev);
device_del(&sdev->sdev_gendev);
put_device(&sdev->sdev_gendev); put_device(&sdev->sdev_gendev);
}
} }
int scsi_register_driver(struct device_driver *drv) int scsi_register_driver(struct device_driver *drv)
......
...@@ -70,8 +70,8 @@ struct fb_info fb_info; ...@@ -70,8 +70,8 @@ struct fb_info fb_info;
struct fb_fix_screeninfo igafb_fix __initdata = { struct fb_fix_screeninfo igafb_fix __initdata = {
.id = "IGA 1682", .id = "IGA 1682",
.type = FB_TYPE_PACKED_PIXELS; .type = FB_TYPE_PACKED_PIXELS,
.mmio_len = 1000; .mmio_len = 1000
}; };
struct fb_var_screeninfo default_var = { struct fb_var_screeninfo default_var = {
...@@ -149,7 +149,7 @@ struct fb_var_screeninfo default_var_1280x1024 __initdata = { ...@@ -149,7 +149,7 @@ struct fb_var_screeninfo default_var_1280x1024 __initdata = {
.xres = 1280, .xres = 1280,
.yres = 1024, .yres = 1024,
.xres_virtual = 1280, .xres_virtual = 1280,
.yres_virtaul = 1024, .yres_virtual = 1024,
.bits_per_pixel = 8, .bits_per_pixel = 8,
.red = {0, 8, 0 }, .red = {0, 8, 0 },
.green = {0, 8, 0 }, .green = {0, 8, 0 },
...@@ -300,17 +300,17 @@ static int igafb_setcolreg(unsigned regno, unsigned red, unsigned green, ...@@ -300,17 +300,17 @@ static int igafb_setcolreg(unsigned regno, unsigned red, unsigned green,
if (regno < 16) { if (regno < 16) {
switch (info->var.bits_per_pixel) { switch (info->var.bits_per_pixel) {
case 16: case 16:
info->pseudo_palette[regno] = ((u16*)(info->pseudo_palette))[regno] =
(regno << 10) | (regno << 5) | regno; (regno << 10) | (regno << 5) | regno;
break; break;
case 24: case 24:
info->pseudo_palette[regno] = ((u32*)(info->pseudo_palette))[regno] =
(regno << 16) | (regno << 8) | regno; (regno << 16) | (regno << 8) | regno;
break; break;
case 32: case 32:
{ int i; { int i;
i = (regno << 8) | regno; i = (regno << 8) | regno;
info->pseudo_palette[regno] = (i << 16) | i; ((u32*)(info->pseudo_palette))[regno] = (i << 16) | i;
} }
break; break;
} }
...@@ -359,7 +359,7 @@ static int __init iga_init(struct fb_info *info, struct iga_par *par) ...@@ -359,7 +359,7 @@ static int __init iga_init(struct fb_info *info, struct iga_par *par)
info->fbops = &igafb_ops; info->fbops = &igafb_ops;
info->flags = FBINFO_FLAG_DEFAULT; info->flags = FBINFO_FLAG_DEFAULT;
fb_alloc_cmap(info->cmap, video_cmap_len, 0); fb_alloc_cmap(&info->cmap, video_cmap_len, 0);
if (register_framebuffer(info) < 0) if (register_framebuffer(info) < 0)
return 0; return 0;
......
...@@ -1415,6 +1415,10 @@ void jfs_flush_journal(struct jfs_log *log, int wait) ...@@ -1415,6 +1415,10 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
int i; int i;
struct tblock *target; struct tblock *target;
/* jfs_write_inode may call us during read-only mount */
if (!log)
return;
jfs_info("jfs_flush_journal: log:0x%p wait=%d", log, wait); jfs_info("jfs_flush_journal: log:0x%p wait=%d", log, wait);
LOGGC_LOCK(log); LOGGC_LOCK(log);
......
...@@ -198,6 +198,7 @@ void proc_tty_register_driver(struct tty_driver *driver) ...@@ -198,6 +198,7 @@ void proc_tty_register_driver(struct tty_driver *driver)
return; return;
ent->read_proc = driver->read_proc; ent->read_proc = driver->read_proc;
ent->write_proc = driver->write_proc; ent->write_proc = driver->write_proc;
ent->owner = driver->owner;
ent->data = driver; ent->data = driver;
driver->proc_entry = ent; driver->proc_entry = ent;
......
...@@ -496,6 +496,6 @@ extern void update_mmu_cache (struct vm_area_struct *vma, unsigned long vaddr, p ...@@ -496,6 +496,6 @@ extern void update_mmu_cache (struct vm_area_struct *vma, unsigned long vaddr, p
/* These tell get_user_pages() that the first gate page is accessible from user-level. */ /* These tell get_user_pages() that the first gate page is accessible from user-level. */
#define FIXADDR_USER_START GATE_ADDR #define FIXADDR_USER_START GATE_ADDR
#define FIXADDR_USER_END (GATE_ADDR + 2*PAGE_SIZE) #define FIXADDR_USER_END (GATE_ADDR + 2*PERCPU_PAGE_SIZE)
#endif /* _ASM_IA64_PGTABLE_H */ #endif /* _ASM_IA64_PGTABLE_H */
...@@ -310,6 +310,7 @@ struct ata_port { ...@@ -310,6 +310,7 @@ struct ata_port {
struct ata_ioports ioaddr; /* ATA cmd/ctl/dma register blocks */ struct ata_ioports ioaddr; /* ATA cmd/ctl/dma register blocks */
u8 ctl; /* cache of ATA control register */ u8 ctl; /* cache of ATA control register */
u8 last_ctl; /* Cache last written value */
unsigned int bus_state; unsigned int bus_state;
unsigned int port_state; unsigned int port_state;
unsigned int pio_mask; unsigned int pio_mask;
...@@ -522,12 +523,12 @@ static inline u8 ata_irq_on(struct ata_port *ap) ...@@ -522,12 +523,12 @@ static inline u8 ata_irq_on(struct ata_port *ap)
struct ata_ioports *ioaddr = &ap->ioaddr; struct ata_ioports *ioaddr = &ap->ioaddr;
ap->ctl &= ~ATA_NIEN; ap->ctl &= ~ATA_NIEN;
ap->last_ctl = ap->ctl;
if (ap->flags & ATA_FLAG_MMIO) if (ap->flags & ATA_FLAG_MMIO)
writeb(ap->ctl, ioaddr->ctl_addr); writeb(ap->ctl, ioaddr->ctl_addr);
else else
outb(ap->ctl, ioaddr->ctl_addr); outb(ap->ctl, ioaddr->ctl_addr);
return ata_wait_idle(ap); return ata_wait_idle(ap);
} }
......
...@@ -917,6 +917,7 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk) ...@@ -917,6 +917,7 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{ {
int err = 0; int err = 0;
int skb_len;
/* Cast skb->rcvbuf to unsigned... It's pointless, but reduces /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
number of warnings when compiling with -W --ANK number of warnings when compiling with -W --ANK
...@@ -937,9 +938,18 @@ static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -937,9 +938,18 @@ static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
skb->dev = NULL; skb->dev = NULL;
skb_set_owner_r(skb, sk); skb_set_owner_r(skb, sk);
/* Cache the SKB length before we tack it onto the receive
* queue. Once it is added it no longer belongs to us and
* may be freed by other threads of control pulling packets
* from the queue.
*/
skb_len = skb->len;
skb_queue_tail(&sk->sk_receive_queue, skb); skb_queue_tail(&sk->sk_receive_queue, skb);
if (!sock_flag(sk, SOCK_DEAD)) if (!sock_flag(sk, SOCK_DEAD))
sk->sk_data_ready(sk, skb->len); sk->sk_data_ready(sk, skb_len);
out: out:
return err; return err;
} }
......
...@@ -14,11 +14,15 @@ struct scsi_mode_data; ...@@ -14,11 +14,15 @@ struct scsi_mode_data;
/* /*
* sdev state * sdev state
*/ */
enum { enum scsi_device_state {
SDEV_ADD, SDEV_CREATED, /* device created but not added to sysfs
SDEV_DEL, * Only internal commands allowed (for inq) */
SDEV_CANCEL, SDEV_RUNNING, /* device properly configured
SDEV_RECOVERY, * All commands allowed */
SDEV_CANCEL, /* beginning to delete device
* Only error handler commands allowed */
SDEV_DEL, /* device deleted
* no commands allowed */
}; };
struct scsi_device { struct scsi_device {
...@@ -99,7 +103,7 @@ struct scsi_device { ...@@ -99,7 +103,7 @@ struct scsi_device {
struct device sdev_gendev; struct device sdev_gendev;
struct class_device sdev_classdev; struct class_device sdev_classdev;
unsigned long sdev_state; enum scsi_device_state sdev_state;
}; };
#define to_scsi_device(d) \ #define to_scsi_device(d) \
container_of(d, struct scsi_device, sdev_gendev) container_of(d, struct scsi_device, sdev_gendev)
......
...@@ -1014,6 +1014,7 @@ struct task_struct *copy_process(unsigned long clone_flags, ...@@ -1014,6 +1014,7 @@ struct task_struct *copy_process(unsigned long clone_flags,
if (current->signal->group_exit) { if (current->signal->group_exit) {
spin_unlock(&current->sighand->siglock); spin_unlock(&current->sighand->siglock);
write_unlock_irq(&tasklist_lock); write_unlock_irq(&tasklist_lock);
retval = -EAGAIN;
goto bad_fork_cleanup_namespace; goto bad_fork_cleanup_namespace;
} }
p->tgid = current->tgid; p->tgid = current->tgid;
......
...@@ -32,7 +32,7 @@ int (*br_should_route_hook) (struct sk_buff **pskb) = NULL; ...@@ -32,7 +32,7 @@ int (*br_should_route_hook) (struct sk_buff **pskb) = NULL;
static int __init br_init(void) static int __init br_init(void)
{ {
#if defined(CONFIG_INET) && defined(CONFIG_NETFILTER) #ifdef CONFIG_BRIDGE_NETFILTER
if (br_netfilter_init()) if (br_netfilter_init())
return 1; return 1;
#endif #endif
...@@ -50,7 +50,7 @@ static int __init br_init(void) ...@@ -50,7 +50,7 @@ static int __init br_init(void)
static void __exit br_deinit(void) static void __exit br_deinit(void)
{ {
#if defined(CONFIG_INET) && defined(CONFIG_NETFILTER) #ifdef CONFIG_BRIDGE_NETFILTER
br_netfilter_fini(); br_netfilter_fini();
#endif #endif
unregister_netdevice_notifier(&br_device_notifier); unregister_netdevice_notifier(&br_device_notifier);
......
...@@ -1041,12 +1041,15 @@ static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet ...@@ -1041,12 +1041,15 @@ static int econet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
if (!sk) if (!sk)
goto drop; goto drop;
return ec_queue_packet(sk, skb, edev->net, hdr->src_stn, hdr->cb, if (ec_queue_packet(sk, skb, edev->net, hdr->src_stn, hdr->cb,
hdr->port); hdr->port))
goto drop;
return 0;
drop: drop:
kfree_skb(skb); kfree_skb(skb);
return 0; return NET_RX_DROP;
} }
static struct packet_type econet_packet_type = { static struct packet_type econet_packet_type = {
......
...@@ -1924,9 +1924,13 @@ static int addrconf_ifdown(struct net_device *dev, int how) ...@@ -1924,9 +1924,13 @@ static int addrconf_ifdown(struct net_device *dev, int how)
write_unlock_bh(&addrconf_hash_lock); write_unlock_bh(&addrconf_hash_lock);
} }
/* Step 3: clear address list */
write_lock_bh(&idev->lock); write_lock_bh(&idev->lock);
/* Step 3: clear flags for stateless addrconf */
if (how != 1)
idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD);
/* Step 4: clear address list */
#ifdef CONFIG_IPV6_PRIVACY #ifdef CONFIG_IPV6_PRIVACY
if (how == 1 && del_timer(&idev->regen_timer)) if (how == 1 && del_timer(&idev->regen_timer))
in6_dev_put(idev); in6_dev_put(idev);
...@@ -1962,7 +1966,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) ...@@ -1962,7 +1966,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
} }
write_unlock_bh(&idev->lock); write_unlock_bh(&idev->lock);
/* Step 4: Discard multicast list */ /* Step 5: Discard multicast list */
if (how == 1) if (how == 1)
ipv6_mc_destroy_dev(idev); ipv6_mc_destroy_dev(idev);
......
...@@ -47,6 +47,9 @@ ...@@ -47,6 +47,9 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv6.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/snmp.h> #include <net/snmp.h>
...@@ -1270,6 +1273,7 @@ static void mld_sendpack(struct sk_buff *skb) ...@@ -1270,6 +1273,7 @@ static void mld_sendpack(struct sk_buff *skb)
struct mld2_report *pmr = (struct mld2_report *)skb->h.raw; struct mld2_report *pmr = (struct mld2_report *)skb->h.raw;
int payload_len, mldlen; int payload_len, mldlen;
struct inet6_dev *idev = in6_dev_get(skb->dev); struct inet6_dev *idev = in6_dev_get(skb->dev);
int err;
payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h - payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h -
sizeof(struct ipv6hdr); sizeof(struct ipv6hdr);
...@@ -1278,7 +1282,9 @@ static void mld_sendpack(struct sk_buff *skb) ...@@ -1278,7 +1282,9 @@ static void mld_sendpack(struct sk_buff *skb)
pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
IPPROTO_ICMPV6, csum_partial(skb->h.raw, mldlen, 0)); IPPROTO_ICMPV6, csum_partial(skb->h.raw, mldlen, 0));
dev_queue_xmit(skb); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
dev_queue_xmit);
if (!err)
ICMP6_INC_STATS(idev,Icmp6OutMsgs); ICMP6_INC_STATS(idev,Icmp6OutMsgs);
if (likely(idev != NULL)) if (likely(idev != NULL))
in6_dev_put(idev); in6_dev_put(idev);
...@@ -1608,12 +1614,15 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) ...@@ -1608,12 +1614,15 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
idev = in6_dev_get(skb->dev); idev = in6_dev_get(skb->dev);
dev_queue_xmit(skb); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
dev_queue_xmit);
if (!err) {
if (type == ICMPV6_MGM_REDUCTION) if (type == ICMPV6_MGM_REDUCTION)
ICMP6_INC_STATS(idev, Icmp6OutGroupMembReductions); ICMP6_INC_STATS(idev, Icmp6OutGroupMembReductions);
else else
ICMP6_INC_STATS(idev, Icmp6OutGroupMembResponses); ICMP6_INC_STATS(idev, Icmp6OutGroupMembResponses);
ICMP6_INC_STATS(idev, Icmp6OutMsgs); ICMP6_INC_STATS(idev, Icmp6OutMsgs);
}
if (likely(idev != NULL)) if (likely(idev != NULL))
in6_dev_put(idev); in6_dev_put(idev);
......
...@@ -859,10 +859,10 @@ static int irttp_udata_indication(void *instance, void *sap, ...@@ -859,10 +859,10 @@ static int irttp_udata_indication(void *instance, void *sap,
err = self->notify.udata_indication(self->notify.instance, err = self->notify.udata_indication(self->notify.instance,
self,skb); self,skb);
/* Same comment as in irttp_do_data_indication() */ /* Same comment as in irttp_do_data_indication() */
if (err != -ENOMEM) if (!err)
return 0; return 0;
} }
/* Either no handler, or -ENOMEM */ /* Either no handler, or handler returns an error */
dev_kfree_skb(skb); dev_kfree_skb(skb);
return 0; return 0;
...@@ -1620,7 +1620,7 @@ void irttp_do_data_indication(struct tsap_cb *self, struct sk_buff *skb) ...@@ -1620,7 +1620,7 @@ void irttp_do_data_indication(struct tsap_cb *self, struct sk_buff *skb)
* be difficult, so it can instead just refuse to eat it and just * be difficult, so it can instead just refuse to eat it and just
* give an error back * give an error back
*/ */
if (err == -ENOMEM) { if (err) {
IRDA_DEBUG(0, "%s() requeueing skb!\n", __FUNCTION__); IRDA_DEBUG(0, "%s() requeueing skb!\n", __FUNCTION__);
/* Make sure we take a break */ /* Make sure we take a break */
......
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