Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: drivers/pcmcia/ds.c Fix up merge failures with Linus's head and fix new compile failures. Signed-Off-By: David Howells <dhowells@redhat.com>
This commit is contained in:
@ -597,10 +597,15 @@ static struct domain_device *sas_ex_discover_end_dev(
|
||||
child->iproto = phy->attached_iproto;
|
||||
memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
|
||||
sas_hash_addr(child->hashed_sas_addr, child->sas_addr);
|
||||
phy->port = sas_port_alloc(&parent->rphy->dev, phy_id);
|
||||
BUG_ON(!phy->port);
|
||||
/* FIXME: better error handling*/
|
||||
BUG_ON(sas_port_add(phy->port) != 0);
|
||||
if (!phy->port) {
|
||||
phy->port = sas_port_alloc(&parent->rphy->dev, phy_id);
|
||||
if (unlikely(!phy->port))
|
||||
goto out_err;
|
||||
if (unlikely(sas_port_add(phy->port) != 0)) {
|
||||
sas_port_free(phy->port);
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
sas_ex_get_linkrate(parent, child, phy);
|
||||
|
||||
if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) {
|
||||
@ -615,8 +620,7 @@ static struct domain_device *sas_ex_discover_end_dev(
|
||||
SAS_DPRINTK("report phy sata to %016llx:0x%x returned "
|
||||
"0x%x\n", SAS_ADDR(parent->sas_addr),
|
||||
phy_id, res);
|
||||
kfree(child);
|
||||
return NULL;
|
||||
goto out_free;
|
||||
}
|
||||
memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis,
|
||||
sizeof(struct dev_to_host_fis));
|
||||
@ -627,14 +631,14 @@ static struct domain_device *sas_ex_discover_end_dev(
|
||||
"%016llx:0x%x returned 0x%x\n",
|
||||
SAS_ADDR(child->sas_addr),
|
||||
SAS_ADDR(parent->sas_addr), phy_id, res);
|
||||
kfree(child);
|
||||
return NULL;
|
||||
goto out_free;
|
||||
}
|
||||
} else if (phy->attached_tproto & SAS_PROTO_SSP) {
|
||||
child->dev_type = SAS_END_DEV;
|
||||
rphy = sas_end_device_alloc(phy->port);
|
||||
/* FIXME: error handling */
|
||||
BUG_ON(!rphy);
|
||||
if (unlikely(!rphy))
|
||||
goto out_free;
|
||||
child->tproto = phy->attached_tproto;
|
||||
sas_init_dev(child);
|
||||
|
||||
@ -651,9 +655,7 @@ static struct domain_device *sas_ex_discover_end_dev(
|
||||
"at %016llx:0x%x returned 0x%x\n",
|
||||
SAS_ADDR(child->sas_addr),
|
||||
SAS_ADDR(parent->sas_addr), phy_id, res);
|
||||
/* FIXME: this kfrees list elements without removing them */
|
||||
//kfree(child);
|
||||
return NULL;
|
||||
goto out_list_del;
|
||||
}
|
||||
} else {
|
||||
SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n",
|
||||
@ -663,6 +665,16 @@ static struct domain_device *sas_ex_discover_end_dev(
|
||||
|
||||
list_add_tail(&child->siblings, &parent_ex->children);
|
||||
return child;
|
||||
|
||||
out_list_del:
|
||||
list_del(&child->dev_list_node);
|
||||
sas_rphy_free(rphy);
|
||||
out_free:
|
||||
sas_port_delete(phy->port);
|
||||
out_err:
|
||||
phy->port = NULL;
|
||||
kfree(child);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct domain_device *sas_ex_discover_expander(
|
||||
|
@ -114,6 +114,8 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
|
||||
}
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&sas_ha->eh_done_q);
|
||||
|
||||
return 0;
|
||||
|
||||
Undo_ports:
|
||||
@ -144,7 +146,7 @@ static int sas_get_linkerrors(struct sas_phy *phy)
|
||||
return sas_smp_get_phy_events(phy);
|
||||
}
|
||||
|
||||
static int sas_phy_reset(struct sas_phy *phy, int hard_reset)
|
||||
int sas_phy_reset(struct sas_phy *phy, int hard_reset)
|
||||
{
|
||||
int ret;
|
||||
enum phy_func reset_type;
|
||||
|
@ -29,9 +29,11 @@
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_tcq.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_eh.h>
|
||||
#include <scsi/scsi_transport.h>
|
||||
#include <scsi/scsi_transport_sas.h>
|
||||
#include "../scsi_sas_internal.h"
|
||||
#include "../scsi_transport_api.h"
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/blkdev.h>
|
||||
@ -46,6 +48,7 @@ static void sas_scsi_task_done(struct sas_task *task)
|
||||
{
|
||||
struct task_status_struct *ts = &task->task_status;
|
||||
struct scsi_cmnd *sc = task->uldd_task;
|
||||
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(sc->device->host);
|
||||
unsigned ts_flags = task->task_state_flags;
|
||||
int hs = 0, stat = 0;
|
||||
|
||||
@ -116,7 +119,7 @@ static void sas_scsi_task_done(struct sas_task *task)
|
||||
sas_free_task(task);
|
||||
/* This is very ugly but this is how SCSI Core works. */
|
||||
if (ts_flags & SAS_TASK_STATE_ABORTED)
|
||||
scsi_finish_command(sc);
|
||||
scsi_eh_finish_cmd(sc, &sas_ha->eh_done_q);
|
||||
else
|
||||
sc->scsi_done(sc);
|
||||
}
|
||||
@ -307,6 +310,15 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task)
|
||||
spin_unlock_irqrestore(&core->task_queue_lock, flags);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) {
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
SAS_DPRINTK("%s: task 0x%p already aborted\n",
|
||||
__FUNCTION__, task);
|
||||
return TASK_IS_ABORTED;
|
||||
}
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task);
|
||||
res = si->dft->lldd_abort_task(task);
|
||||
@ -409,13 +421,16 @@ Again:
|
||||
SAS_DPRINTK("going over list...\n");
|
||||
list_for_each_entry_safe(cmd, n, &error_q, eh_entry) {
|
||||
struct sas_task *task = TO_SAS_TASK(cmd);
|
||||
|
||||
SAS_DPRINTK("trying to find task 0x%p\n", task);
|
||||
list_del_init(&cmd->eh_entry);
|
||||
|
||||
if (!task) {
|
||||
SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__);
|
||||
continue;
|
||||
}
|
||||
SAS_DPRINTK("trying to find task 0x%p\n", task);
|
||||
res = sas_scsi_find_task(task);
|
||||
|
||||
cmd->eh_eflags = 0;
|
||||
shost->host_failed--;
|
||||
|
||||
switch (res) {
|
||||
case TASK_IS_DONE:
|
||||
@ -491,6 +506,7 @@ Again:
|
||||
}
|
||||
}
|
||||
out:
|
||||
scsi_eh_flush_done_q(&ha->eh_done_q);
|
||||
SAS_DPRINTK("--- Exit %s\n", __FUNCTION__);
|
||||
return;
|
||||
clear_q:
|
||||
@ -508,12 +524,18 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
|
||||
unsigned long flags;
|
||||
|
||||
if (!task) {
|
||||
SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n",
|
||||
SAS_DPRINTK("command 0x%p, task 0x%p, gone: EH_HANDLED\n",
|
||||
cmd, task);
|
||||
return EH_HANDLED;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) {
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
SAS_DPRINTK("command 0x%p, task 0x%p, aborted by initiator: "
|
||||
"EH_NOT_HANDLED\n", cmd, task);
|
||||
return EH_NOT_HANDLED;
|
||||
}
|
||||
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n",
|
||||
@ -777,6 +799,64 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha)
|
||||
spin_unlock_irqrestore(&core->task_queue_lock, flags);
|
||||
}
|
||||
|
||||
static int do_sas_task_abort(struct sas_task *task)
|
||||
{
|
||||
struct scsi_cmnd *sc = task->uldd_task;
|
||||
struct sas_internal *si =
|
||||
to_sas_internal(task->dev->port->ha->core.shost->transportt);
|
||||
unsigned long flags;
|
||||
int res;
|
||||
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
SAS_DPRINTK("%s: Task %p already aborted.\n", __FUNCTION__,
|
||||
task);
|
||||
return 0;
|
||||
}
|
||||
|
||||
task->task_state_flags |= SAS_TASK_INITIATOR_ABORTED;
|
||||
if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
|
||||
task->task_state_flags |= SAS_TASK_STATE_ABORTED;
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
|
||||
if (!si->dft->lldd_abort_task)
|
||||
return -ENODEV;
|
||||
|
||||
res = si->dft->lldd_abort_task(task);
|
||||
if ((task->task_state_flags & SAS_TASK_STATE_DONE) ||
|
||||
(res == TMF_RESP_FUNC_COMPLETE))
|
||||
{
|
||||
/* SMP commands don't have scsi_cmds(?) */
|
||||
if (!sc) {
|
||||
task->task_done(task);
|
||||
return 0;
|
||||
}
|
||||
scsi_req_abort_cmd(sc);
|
||||
scsi_schedule_eh(sc->device->host);
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&task->task_state_lock, flags);
|
||||
task->task_state_flags &= ~SAS_TASK_INITIATOR_ABORTED;
|
||||
if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
|
||||
task->task_state_flags &= ~SAS_TASK_STATE_ABORTED;
|
||||
spin_unlock_irqrestore(&task->task_state_lock, flags);
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
void sas_task_abort(struct sas_task *task)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
if (!do_sas_task_abort(task))
|
||||
return;
|
||||
|
||||
SAS_DPRINTK("%s: Could not kill task!\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(sas_queuecommand);
|
||||
EXPORT_SYMBOL_GPL(sas_target_alloc);
|
||||
EXPORT_SYMBOL_GPL(sas_slave_configure);
|
||||
@ -784,3 +864,5 @@ EXPORT_SYMBOL_GPL(sas_slave_destroy);
|
||||
EXPORT_SYMBOL_GPL(sas_change_queue_depth);
|
||||
EXPORT_SYMBOL_GPL(sas_change_queue_type);
|
||||
EXPORT_SYMBOL_GPL(sas_bios_param);
|
||||
EXPORT_SYMBOL_GPL(sas_task_abort);
|
||||
EXPORT_SYMBOL_GPL(sas_phy_reset);
|
||||
|
Reference in New Issue
Block a user