summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS9
-rw-r--r--drivers/message/fusion/mptbase.c64
-rw-r--r--drivers/message/fusion/mptbase.h3
-rw-r--r--drivers/message/fusion/mptscsih.c10
-rw-r--r--drivers/s390/scsi/zfcp_aux.c14
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c4
-rw-r--r--drivers/s390/scsi/zfcp_erp.c94
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c110
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c2
-rw-r--r--drivers/scsi/aacraid/linit.c2
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c2
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c2
-rw-r--r--drivers/scsi/scsi_transport_spi.c28
-rw-r--r--drivers/scsi/sg.c6
-rw-r--r--drivers/scsi/st.c3
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c5
16 files changed, 225 insertions, 133 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 1fc80ec4999b..77bb08606912 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1636,6 +1636,15 @@ L: ldm-devel@lists.sourceforge.net
W: http://ldm.sourceforge.net
S: Maintained
+LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
+P: Eric Moore
+M: Eric.Moore@lsil.com
+M: support@lsil.com
+L: mpt_linux_developer@lsil.com
+L: linux-scsi@vger.kernel.org
+W: http://www.lsilogic.com/support
+S: Supported
+
LSILOGIC/SYMBIOS/NCR 53C8XX and 53C1010 PCI-SCSI drivers
P: Matthew Wilcox
M: matthew@wil.cx
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 65c2ec5c421b..4262a22adc22 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1118,6 +1118,65 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
return -1;
}
+int
+mpt_alt_ioc_wait(MPT_ADAPTER *ioc)
+{
+ int loop_count = 30 * 4; /* Wait 30 seconds */
+ int status = -1; /* -1 means failed to get board READY */
+
+ do {
+ spin_lock(&ioc->initializing_hba_lock);
+ if (ioc->initializing_hba_lock_flag == 0) {
+ ioc->initializing_hba_lock_flag=1;
+ spin_unlock(&ioc->initializing_hba_lock);
+ status = 0;
+ break;
+ }
+ spin_unlock(&ioc->initializing_hba_lock);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ/4);
+ } while (--loop_count);
+
+ return status;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mpt_bringup_adapter - This is a wrapper function for mpt_do_ioc_recovery
+ * @ioc: Pointer to MPT adapter structure
+ * @sleepFlag: Use schedule if CAN_SLEEP else use udelay.
+ *
+ * This routine performs all the steps necessary to bring the IOC
+ * to a OPERATIONAL state.
+ *
+ * Special Note: This function was added with spin lock's so as to allow
+ * the dv(domain validation) work thread to succeed on the other channel
+ * that maybe occuring at the same time when this function is called.
+ * Without this lock, the dv would fail when message frames were
+ * requested during hba bringup on the alternate ioc.
+ */
+static int
+mpt_bringup_adapter(MPT_ADAPTER *ioc, int sleepFlag)
+{
+ int r;
+
+ if(ioc->alt_ioc) {
+ if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0))
+ return r;
+ }
+
+ r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP,
+ CAN_SLEEP);
+
+ if(ioc->alt_ioc) {
+ spin_lock(&ioc->alt_ioc->initializing_hba_lock);
+ ioc->alt_ioc->initializing_hba_lock_flag=0;
+ spin_unlock(&ioc->alt_ioc->initializing_hba_lock);
+ }
+
+return r;
+}
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mpt_attach - Install a PCI intelligent MPT adapter.
@@ -1186,6 +1245,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->pcidev = pdev;
ioc->diagPending = 0;
spin_lock_init(&ioc->diagLock);
+ spin_lock_init(&ioc->initializing_hba_lock);
/* Initialize the event logging.
*/
@@ -1408,8 +1468,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
*/
mpt_detect_bound_ports(ioc, pdev);
- if ((r = mpt_do_ioc_recovery(ioc,
- MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) {
+ if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){
printk(KERN_WARNING MYNAM
": WARNING - %s did not initialize properly! (%d)\n",
ioc->name, r);
@@ -6298,6 +6357,7 @@ EXPORT_SYMBOL(mpt_read_ioc_pg_3);
EXPORT_SYMBOL(mpt_alloc_fw_memory);
EXPORT_SYMBOL(mpt_free_fw_memory);
EXPORT_SYMBOL(mptbase_sas_persist_operation);
+EXPORT_SYMBOL(mpt_alt_ioc_wait);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 5f5b3fb5b4d7..bac8eb4186d2 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -611,6 +611,8 @@ typedef struct _MPT_ADAPTER
int DoneCtx;
int TaskCtx;
int InternalCtx;
+ spinlock_t initializing_hba_lock;
+ int initializing_hba_lock_flag;
struct list_head list;
struct net_device *netdev;
struct list_head sas_topology;
@@ -1001,6 +1003,7 @@ extern void mpt_free_fw_memory(MPT_ADAPTER *ioc);
extern int mpt_findImVolumes(MPT_ADAPTER *ioc);
extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
+extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc);
/*
* Public data decl's...
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 4330ed0cedaa..b7b9846ff3fd 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -4162,6 +4162,12 @@ mptscsih_domainValidation(void *arg)
}
}
+ if(mpt_alt_ioc_wait(hd->ioc)!=0) {
+ ddvprintk((MYIOC_s_WARN_FMT "alt_ioc busy!\n",
+ hd->ioc->name));
+ continue;
+ }
+
if (mptscsih_doDv(hd, 0, id) == 1) {
/* Untagged device was busy, try again
*/
@@ -4173,6 +4179,10 @@ mptscsih_domainValidation(void *arg)
hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING);
}
+ spin_lock(&hd->ioc->initializing_hba_lock);
+ hd->ioc->initializing_hba_lock_flag=0;
+ spin_unlock(&hd->ioc->initializing_hba_lock);
+
if (isPhysDisk) {
for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
if (hd->ioc->raid_data.isRaid & (1 << ii)) {
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index c218b5c944a6..5e84c5aa7779 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -996,6 +996,20 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
spin_lock_init(&adapter->fsf_req_list_lock);
INIT_LIST_HEAD(&adapter->fsf_req_list_head);
+ /* initialize debug locks */
+
+ spin_lock_init(&adapter->erp_dbf_lock);
+ spin_lock_init(&adapter->hba_dbf_lock);
+ spin_lock_init(&adapter->san_dbf_lock);
+ spin_lock_init(&adapter->scsi_dbf_lock);
+
+ /* initialize error recovery stuff */
+
+ rwlock_init(&adapter->erp_lock);
+ sema_init(&adapter->erp_ready_sem, 0);
+ INIT_LIST_HEAD(&adapter->erp_ready_head);
+ INIT_LIST_HEAD(&adapter->erp_running_head);
+
/* initialize abort lock */
rwlock_init(&adapter->abort_lock);
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 826fb3b00605..95599719f8ab 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -926,7 +926,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
char dbf_name[DEBUG_MAX_NAME_LEN];
/* debug feature area which records recovery activity */
- spin_lock_init(&adapter->erp_dbf_lock);
sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter));
adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2,
sizeof(struct zfcp_erp_dbf_record));
@@ -936,7 +935,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
debug_set_level(adapter->erp_dbf, 3);
/* debug feature area which records HBA (FSF and QDIO) conditions */
- spin_lock_init(&adapter->hba_dbf_lock);
sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter));
adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1,
sizeof(struct zfcp_hba_dbf_record));
@@ -947,7 +945,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
debug_set_level(adapter->hba_dbf, 3);
/* debug feature area which records SAN command failures and recovery */
- spin_lock_init(&adapter->san_dbf_lock);
sprintf(dbf_name, "zfcp_%s_san", zfcp_get_busid_by_adapter(adapter));
adapter->san_dbf = debug_register(dbf_name, dbfsize, 1,
sizeof(struct zfcp_san_dbf_record));
@@ -958,7 +955,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter)
debug_set_level(adapter->san_dbf, 6);
/* debug feature area which records SCSI command failures and recovery */
- spin_lock_init(&adapter->scsi_dbf_lock);
sprintf(dbf_name, "zfcp_%s_scsi", zfcp_get_busid_by_adapter(adapter));
adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1,
sizeof(struct zfcp_scsi_dbf_record));
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 023f4e558ae4..ee7314d8c2da 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -1071,11 +1071,6 @@ zfcp_erp_thread_setup(struct zfcp_adapter *adapter)
atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
- rwlock_init(&adapter->erp_lock);
- INIT_LIST_HEAD(&adapter->erp_ready_head);
- INIT_LIST_HEAD(&adapter->erp_running_head);
- sema_init(&adapter->erp_ready_sem, 0);
-
retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD);
if (retval < 0) {
ZFCP_LOG_NORMAL("error: creation of erp thread failed for "
@@ -2248,29 +2243,26 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action)
return retval;
}
-/*
- * function: zfcp_fsf_init
- *
- * purpose: initializes FSF operation for the specified adapter
- *
- * returns: 0 - succesful initialization of FSF operation
- * !0 - failed to initialize FSF operation
- */
static int
zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
{
- int xconfig, xport;
+ int retval;
- if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &erp_action->adapter->status)) {
+ if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+ &erp_action->adapter->status)) &&
+ (erp_action->adapter->adapter_features &
+ FSF_FEATURE_HBAAPI_MANAGEMENT)) {
zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
atomic_set(&erp_action->adapter->erp_counter, 0);
return ZFCP_ERP_FAILED;
}
- xconfig = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
- xport = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
- if ((xconfig == ZFCP_ERP_FAILED) || (xport == ZFCP_ERP_FAILED))
+ retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action);
+ if (retval == ZFCP_ERP_FAILED)
+ return ZFCP_ERP_FAILED;
+
+ retval = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action);
+ if (retval == ZFCP_ERP_FAILED)
return ZFCP_ERP_FAILED;
return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action);
@@ -2359,41 +2351,29 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
static int
zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
{
- int retval = ZFCP_ERP_SUCCEEDED;
+ int ret;
int retries;
int sleep;
struct zfcp_adapter *adapter = erp_action->adapter;
atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status);
- for (retries = 0; ; retries++) {
- ZFCP_LOG_DEBUG("Doing exchange port data\n");
+ retries = 0;
+ do {
+ write_lock(&adapter->erp_lock);
zfcp_erp_action_to_running(erp_action);
+ write_unlock(&adapter->erp_lock);
zfcp_erp_timeout_init(erp_action);
- if (zfcp_fsf_exchange_port_data(erp_action, adapter, NULL)) {
- retval = ZFCP_ERP_FAILED;
- debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf");
- ZFCP_LOG_INFO("error: initiation of exchange of "
- "port data failed for adapter %s\n",
- zfcp_get_busid_by_adapter(adapter));
- break;
+ ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
+ if (ret == -EOPNOTSUPP) {
+ debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
+ return ZFCP_ERP_SUCCEEDED;
+ } else if (ret) {
+ debug_text_event(adapter->erp_dbf, 3, "a_xport_failed");
+ return ZFCP_ERP_FAILED;
}
- debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok");
- ZFCP_LOG_DEBUG("Xchange underway\n");
+ debug_text_event(adapter->erp_dbf, 6, "a_xport_ok");
- /*
- * Why this works:
- * Both the normal completion handler as well as the timeout
- * handler will do an 'up' when the 'exchange port data'
- * request completes or times out. Thus, the signal to go on
- * won't be lost utilizing this semaphore.
- * Furthermore, this 'adapter_reopen' action is
- * guaranteed to be the only action being there (highest action
- * which prevents other actions from being created).
- * Resulting from that, the wake signal recognized here
- * _must_ be the one belonging to the 'exchange port
- * data' request.
- */
down(&adapter->erp_ready_sem);
if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) {
ZFCP_LOG_INFO("error: exchange of port data "
@@ -2401,29 +2381,19 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
zfcp_get_busid_by_adapter(adapter));
break;
}
-
if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
&adapter->status))
break;
- ZFCP_LOG_DEBUG("host connection still initialising... "
- "waiting and retrying...\n");
- /* sleep a little bit before retry */
- sleep = retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES ?
- ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP :
- ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
- msleep(jiffies_to_msecs(sleep));
- }
-
- if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &adapter->status)) {
- ZFCP_LOG_INFO("error: exchange of port data for "
- "adapter %s failed\n",
- zfcp_get_busid_by_adapter(adapter));
- retval = ZFCP_ERP_FAILED;
- }
+ if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) {
+ sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP;
+ retries++;
+ } else
+ sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP;
+ schedule_timeout(sleep);
+ } while (1);
- return retval;
+ return ZFCP_ERP_SUCCEEDED;
}
/*
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 3b0fc1163f5f..59587951c847 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -554,6 +554,17 @@ static void
zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
struct fsf_link_down_info *link_down)
{
+ if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
+ &adapter->status))
+ return;
+
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
+
+ if (link_down == NULL) {
+ zfcp_erp_adapter_reopen(adapter, 0);
+ return;
+ }
+
switch (link_down->error_code) {
case FSF_PSQ_LINK_NO_LIGHT:
ZFCP_LOG_NORMAL("The local link to adapter %s is down "
@@ -634,20 +645,15 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter,
link_down->explanation_code,
link_down->vendor_specific_code);
- if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &adapter->status)) {
- atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED,
- &adapter->status);
- switch (link_down->error_code) {
- case FSF_PSQ_LINK_NO_LIGHT:
- case FSF_PSQ_LINK_WRAP_PLUG:
- case FSF_PSQ_LINK_NO_FCP:
- case FSF_PSQ_LINK_FIRMWARE_UPDATE:
- zfcp_erp_adapter_reopen(adapter, 0);
- break;
- default:
- zfcp_erp_adapter_failed(adapter);
- }
+ switch (link_down->error_code) {
+ case FSF_PSQ_LINK_NO_LIGHT:
+ case FSF_PSQ_LINK_WRAP_PLUG:
+ case FSF_PSQ_LINK_NO_FCP:
+ case FSF_PSQ_LINK_FIRMWARE_UPDATE:
+ zfcp_erp_adapter_reopen(adapter, 0);
+ break;
+ default:
+ zfcp_erp_adapter_failed(adapter);
}
}
@@ -919,30 +925,36 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK:
ZFCP_LOG_INFO("Physical link to adapter %s is down\n",
zfcp_get_busid_by_adapter(adapter));
+ zfcp_fsf_link_down_info_eval(adapter,
+ (struct fsf_link_down_info *)
+ &status_buffer->payload);
break;
case FSF_STATUS_READ_SUB_FDISC_FAILED:
ZFCP_LOG_INFO("Local link to adapter %s is down "
"due to failed FDISC login\n",
- zfcp_get_busid_by_adapter(adapter));
+ zfcp_get_busid_by_adapter(adapter));
+ zfcp_fsf_link_down_info_eval(adapter,
+ (struct fsf_link_down_info *)
+ &status_buffer->payload);
break;
case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE:
ZFCP_LOG_INFO("Local link to adapter %s is down "
"due to firmware update on adapter\n",
zfcp_get_busid_by_adapter(adapter));
+ zfcp_fsf_link_down_info_eval(adapter, NULL);
break;
default:
ZFCP_LOG_INFO("Local link to adapter %s is down "
"due to unknown reason\n",
zfcp_get_busid_by_adapter(adapter));
+ zfcp_fsf_link_down_info_eval(adapter, NULL);
};
- zfcp_fsf_link_down_info_eval(adapter,
- (struct fsf_link_down_info *) &status_buffer->payload);
break;
case FSF_STATUS_READ_LINK_UP:
ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. "
- "Restarting operations on this adapter\n",
- zfcp_get_busid_by_adapter(adapter));
+ "Restarting operations on this adapter\n",
+ zfcp_get_busid_by_adapter(adapter));
/* All ports should be marked as ready to run again */
zfcp_erp_modify_adapter_status(adapter,
ZFCP_STATUS_COMMON_RUNNING,
@@ -2191,13 +2203,10 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
return -EOPNOTSUPP;
}
- timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
- if (!timer)
- return -ENOMEM;
-
/* setup new FSF request */
retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
- 0, 0, &lock_flags, &fsf_req);
+ erp_action ? ZFCP_REQ_AUTO_CLEANUP : 0,
+ 0, &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Out of resources. Could not create an "
"exchange port data request for"
@@ -2205,25 +2214,33 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
zfcp_get_busid_by_adapter(adapter));
write_unlock_irqrestore(&adapter->request_queue.queue_lock,
lock_flags);
- goto out;
- }
-
- if (erp_action) {
- erp_action->fsf_req = fsf_req;
- fsf_req->erp_action = erp_action;
+ return retval;
}
if (data)
- fsf_req->data = (unsigned long) data;
+ fsf_req->data = (unsigned long) data;
sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- init_timer(timer);
- timer->function = zfcp_fsf_request_timeout_handler;
- timer->data = (unsigned long) adapter;
- timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
+ if (erp_action) {
+ erp_action->fsf_req = fsf_req;
+ fsf_req->erp_action = erp_action;
+ timer = &erp_action->timer;
+ } else {
+ timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC);
+ if (!timer) {
+ write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+ lock_flags);
+ zfcp_fsf_req_free(fsf_req);
+ return -ENOMEM;
+ }
+ init_timer(timer);
+ timer->function = zfcp_fsf_request_timeout_handler;
+ timer->data = (unsigned long) adapter;
+ timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
+ }
retval = zfcp_fsf_req_send(fsf_req, timer);
if (retval) {
@@ -2233,23 +2250,22 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
zfcp_fsf_req_free(fsf_req);
if (erp_action)
erp_action->fsf_req = NULL;
+ else
+ kfree(timer);
write_unlock_irqrestore(&adapter->request_queue.queue_lock,
lock_flags);
- goto out;
+ return retval;
}
- ZFCP_LOG_DEBUG("Exchange Port Data request initiated (adapter %s)\n",
- zfcp_get_busid_by_adapter(adapter));
-
- write_unlock_irqrestore(&adapter->request_queue.queue_lock,
- lock_flags);
+ write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
- wait_event(fsf_req->completion_wq,
- fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
- del_timer_sync(timer);
- zfcp_fsf_req_free(fsf_req);
- out:
- kfree(timer);
+ if (!erp_action) {
+ wait_event(fsf_req->completion_wq,
+ fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+ del_timer_sync(timer);
+ zfcp_fsf_req_free(fsf_req);
+ kfree(timer);
+ }
return retval;
}
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 3dcd1bfba3b4..66608d13a634 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -179,7 +179,7 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp)
struct zfcp_adapter *adapter;
struct zfcp_unit *unit;
unsigned long flags;
- int retval = -ENODEV;
+ int retval = -ENXIO;
adapter = (struct zfcp_adapter *) sdp->host->hostdata[0];
if (!adapter)
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index ab383d1f59e2..3cb68af90456 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -325,6 +325,8 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev,
* translations ( 64/32, 128/32, 255/63 ).
*/
buf = scsi_bios_ptable(bdev);
+ if (!buf)
+ return 0;
if(*(__le16 *)(buf + 0x40) == cpu_to_le16(0xaa55)) {
struct partition *first = (struct partition * )buf;
struct partition *entry = first;
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 31e9f40e79a2..6aab9dacdeea 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -2105,7 +2105,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
scmd_id(cmd),
scmd_channel(cmd) + 'A',
CAM_LUN_WILDCARD,
- SCB_LIST_NULL, ROLE_INITIATOR) == 0)
+ SCB_LIST_NULL, ROLE_INITIATOR))
break;
}
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 7fc6454068e4..d866213f42b8 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -2169,7 +2169,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
if (ahc_match_scb(ahc, pending_scb, scmd_id(cmd),
scmd_channel(cmd) + 'A',
CAM_LUN_WILDCARD,
- SCB_LIST_NULL, ROLE_INITIATOR) == 0)
+ SCB_LIST_NULL, ROLE_INITIATOR))
break;
}
}
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 718a2bc4ed5e..38a53b5f9e9a 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -812,12 +812,10 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer)
if (!scsi_device_sync(sdev) && !scsi_device_dt(sdev))
return;
- /* see if the device has an echo buffer. If it does we can
- * do the SPI pattern write tests */
-
- len = 0;
- if (scsi_device_dt(sdev))
- len = spi_dv_device_get_echo_buffer(sdev, buffer);
+ /* len == -1 is the signal that we need to ascertain the
+ * presence of an echo buffer before trying to use it. len ==
+ * 0 means we don't have an echo buffer */
+ len = -1;
retry:
@@ -840,11 +838,23 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer)
if (spi_min_period(starget) == 8)
DV_SET(pcomp_en, 1);
}
+ /* Do the read only INQUIRY tests */
+ spi_dv_retrain(sdev, buffer, buffer + sdev->inquiry_len,
+ spi_dv_device_compare_inquiry);
+ /* See if we actually managed to negotiate and sustain DT */
+ if (i->f->get_dt)
+ i->f->get_dt(starget);
+
+ /* see if the device has an echo buffer. If it does we can do
+ * the SPI pattern write tests. Because of some broken
+ * devices, we *only* try this on a device that has actually
+ * negotiated DT */
+
+ if (len == -1 && spi_dt(starget))
+ len = spi_dv_device_get_echo_buffer(sdev, buffer);
- if (len == 0) {
+ if (len <= 0) {
starget_printk(KERN_INFO, starget, "Domain Validation skipping write tests\n");
- spi_dv_retrain(sdev, buffer, buffer + len,
- spi_dv_device_compare_inquiry);
return;
}
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 72ec59456e69..b55c2a8a547c 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1860,9 +1860,11 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
unlock_page(pages[j]); */
res = 0;
out_unmap:
- if (res > 0)
+ if (res > 0) {
for (j=0; j < res; j++)
page_cache_release(pages[j]);
+ res = 0;
+ }
kfree(pages);
return res;
}
@@ -1878,8 +1880,6 @@ st_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages,
for (i=0; i < nr_pages; i++) {
struct page *page = sgl[i].page;
- /* XXX: just for debug. Remove when PageReserved is removed */
- BUG_ON(PageReserved(page));
if (dirtied)
SetPageDirty(page);
/* unlock_page(page); */
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 770c4324f3d5..7ac6ea141fff 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -4509,6 +4509,7 @@ static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pa
if (res > 0) {
for (j=0; j < res; j++)
page_cache_release(pages[j]);
+ res = 0;
}
kfree(pages);
return res;
@@ -4524,8 +4525,6 @@ static int sgl_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_p
for (i=0; i < nr_pages; i++) {
struct page *page = sgl[i].page;
- /* XXX: just for debug. Remove when PageReserved is removed */
- BUG_ON(PageReserved(page));
if (dirtied)
SetPageDirty(page);
/* FIXME: cache flush missing for rw==READ
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index d76766c3ce16..7fc0b97173e1 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -2086,6 +2086,7 @@ static void sym2_set_dt(struct scsi_target *starget, int dt)
tp->tgoal.check_nego = 1;
}
+#if 0
static void sym2_set_iu(struct scsi_target *starget, int iu)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -2111,7 +2112,7 @@ static void sym2_set_qas(struct scsi_target *starget, int qas)
tp->tgoal.qas = 0;
tp->tgoal.check_nego = 1;
}
-
+#endif
static struct spi_function_template sym2_transport_functions = {
.set_offset = sym2_set_offset,
@@ -2122,10 +2123,12 @@ static struct spi_function_template sym2_transport_functions = {
.show_width = 1,
.set_dt = sym2_set_dt,
.show_dt = 1,
+#if 0
.set_iu = sym2_set_iu,
.show_iu = 1,
.set_qas = sym2_set_qas,
.show_qas = 1,
+#endif
.get_signalling = sym2_get_signalling,
};