aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAndreas Herrmann <aherrman@de.ibm.com>2005-06-13 07:18:56 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-06-13 22:30:05 -0400
commit64b29a130901d5b8578e9f602cf2dae56aaff224 (patch)
treefb543d8a7c007416d99128246d4e71580ecd94ff /drivers
parent516a4201bacfd61ea957039d6f47276ee9c32a0d (diff)
[SCSI] zfcp: fix: problem in send_els_handler when D_ID assignment changes
From: Maxim Shchetynin <maxim@de.ibm.com> Fixes a bug in zfcp_send_els_handler. If D_ID assignments for ports are changing between initiation of one ELS request and its completion the wrong port might be accessed in the completion for that ELS request. Thus a pointer to the port has to be passed for ELS requests to identify the port structure if required. Signed-off-by: Andreas Herrmann <aherrman@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/s390/scsi/zfcp_def.h2
-rw-r--r--drivers/s390/scsi/zfcp_erp.c24
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c15
3 files changed, 16 insertions, 25 deletions
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 08369b9dad68..37982058e4d9 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -751,6 +751,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long);
751/** 751/**
752 * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els 752 * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els
753 * @adapter: adapter where request is sent from 753 * @adapter: adapter where request is sent from
754 * @port: port where ELS is destinated (port reference count has to be increased)
754 * @d_id: destiniation id of port where request is sent to 755 * @d_id: destiniation id of port where request is sent to
755 * @req: scatter-gather list for request 756 * @req: scatter-gather list for request
756 * @resp: scatter-gather list for response 757 * @resp: scatter-gather list for response
@@ -765,6 +766,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long);
765 */ 766 */
766struct zfcp_send_els { 767struct zfcp_send_els {
767 struct zfcp_adapter *adapter; 768 struct zfcp_adapter *adapter;
769 struct zfcp_port *port;
768 fc_id_t d_id; 770 fc_id_t d_id;
769 struct scatterlist *req; 771 struct scatterlist *req;
770 struct scatterlist *resp; 772 struct scatterlist *resp;
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 60ba1ba112d6..41c67e1ec4f7 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -35,7 +35,7 @@
35 35
36#include "zfcp_ext.h" 36#include "zfcp_ext.h"
37 37
38static int zfcp_erp_adisc(struct zfcp_adapter *, fc_id_t); 38static int zfcp_erp_adisc(struct zfcp_port *);
39static void zfcp_erp_adisc_handler(unsigned long); 39static void zfcp_erp_adisc_handler(unsigned long);
40 40
41static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int); 41static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int);
@@ -295,12 +295,12 @@ zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask)
295 295
296/** 296/**
297 * zfcp_erp_adisc - send ADISC ELS command 297 * zfcp_erp_adisc - send ADISC ELS command
298 * @adapter: adapter structure 298 * @port: port structure
299 * @d_id: d_id of port where ADISC is sent to
300 */ 299 */
301int 300int
302zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id) 301zfcp_erp_adisc(struct zfcp_port *port)
303{ 302{
303 struct zfcp_adapter *adapter = port->adapter;
304 struct zfcp_send_els *send_els; 304 struct zfcp_send_els *send_els;
305 struct zfcp_ls_adisc *adisc; 305 struct zfcp_ls_adisc *adisc;
306 void *address = NULL; 306 void *address = NULL;
@@ -332,7 +332,8 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
332 send_els->req_count = send_els->resp_count = 1; 332 send_els->req_count = send_els->resp_count = 1;
333 333
334 send_els->adapter = adapter; 334 send_els->adapter = adapter;
335 send_els->d_id = d_id; 335 send_els->port = port;
336 send_els->d_id = port->d_id;
336 send_els->handler = zfcp_erp_adisc_handler; 337 send_els->handler = zfcp_erp_adisc_handler;
337 send_els->handler_data = (unsigned long) send_els; 338 send_els->handler_data = (unsigned long) send_els;
338 339
@@ -350,7 +351,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
350 ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x " 351 ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x "
351 "(wwpn=0x%016Lx, wwnn=0x%016Lx, " 352 "(wwpn=0x%016Lx, wwnn=0x%016Lx, "
352 "hard_nport_id=0x%08x, nport_id=0x%08x)\n", 353 "hard_nport_id=0x%08x, nport_id=0x%08x)\n",
353 adapter->s_id, d_id, (wwn_t) adisc->wwpn, 354 adapter->s_id, send_els->d_id, (wwn_t) adisc->wwpn,
354 (wwn_t) adisc->wwnn, adisc->hard_nport_id, 355 (wwn_t) adisc->wwnn, adisc->hard_nport_id,
355 adisc->nport_id); 356 adisc->nport_id);
356 357
@@ -367,7 +368,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
367 retval = zfcp_fsf_send_els(send_els); 368 retval = zfcp_fsf_send_els(send_els);
368 if (retval != 0) { 369 if (retval != 0) {
369 ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port " 370 ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port "
370 "0x%08x on adapter %s\n", d_id, 371 "0x%08x on adapter %s\n", send_els->d_id,
371 zfcp_get_busid_by_adapter(adapter)); 372 zfcp_get_busid_by_adapter(adapter));
372 del_timer(send_els->timer); 373 del_timer(send_els->timer);
373 goto freemem; 374 goto freemem;
@@ -411,14 +412,9 @@ zfcp_erp_adisc_handler(unsigned long data)
411 del_timer(send_els->timer); 412 del_timer(send_els->timer);
412 413
413 adapter = send_els->adapter; 414 adapter = send_els->adapter;
415 port = send_els->port;
414 d_id = send_els->d_id; 416 d_id = send_els->d_id;
415 417
416 read_lock(&zfcp_data.config_lock);
417 port = zfcp_get_port_by_did(send_els->adapter, send_els->d_id);
418 read_unlock(&zfcp_data.config_lock);
419
420 BUG_ON(port == NULL);
421
422 /* request rejected or timed out */ 418 /* request rejected or timed out */
423 if (send_els->status != 0) { 419 if (send_els->status != 0) {
424 ZFCP_LOG_NORMAL("ELS request rejected/timed out, " 420 ZFCP_LOG_NORMAL("ELS request rejected/timed out, "
@@ -482,7 +478,7 @@ zfcp_test_link(struct zfcp_port *port)
482 int retval; 478 int retval;
483 479
484 zfcp_port_get(port); 480 zfcp_port_get(port);
485 retval = zfcp_erp_adisc(port->adapter, port->d_id); 481 retval = zfcp_erp_adisc(port);
486 if (retval != 0) { 482 if (retval != 0) {
487 zfcp_port_put(port); 483 zfcp_port_put(port);
488 ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx " 484 ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx "
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index bf66fc6d8a97..21a6d7633475 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -1771,8 +1771,8 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
1771static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) 1771static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
1772{ 1772{
1773 struct zfcp_adapter *adapter; 1773 struct zfcp_adapter *adapter;
1774 fc_id_t d_id;
1775 struct zfcp_port *port; 1774 struct zfcp_port *port;
1775 fc_id_t d_id;
1776 struct fsf_qtcb_header *header; 1776 struct fsf_qtcb_header *header;
1777 struct fsf_qtcb_bottom_support *bottom; 1777 struct fsf_qtcb_bottom_support *bottom;
1778 struct zfcp_send_els *send_els; 1778 struct zfcp_send_els *send_els;
@@ -1781,6 +1781,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
1781 1781
1782 send_els = fsf_req->data.send_els; 1782 send_els = fsf_req->data.send_els;
1783 adapter = send_els->adapter; 1783 adapter = send_els->adapter;
1784 port = send_els->port;
1784 d_id = send_els->d_id; 1785 d_id = send_els->d_id;
1785 header = &fsf_req->qtcb->header; 1786 header = &fsf_req->qtcb->header;
1786 bottom = &fsf_req->qtcb->bottom.support; 1787 bottom = &fsf_req->qtcb->bottom.support;
@@ -1817,13 +1818,8 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
1817 switch (header->fsf_status_qual.word[0]){ 1818 switch (header->fsf_status_qual.word[0]){
1818 case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: 1819 case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
1819 debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); 1820 debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
1820 if (send_els->ls_code != ZFCP_LS_ADISC) { 1821 if (port && (send_els->ls_code != ZFCP_LS_ADISC))
1821 read_lock(&zfcp_data.config_lock); 1822 zfcp_test_link(port);
1822 port = zfcp_get_port_by_did(adapter, d_id);
1823 if (port)
1824 zfcp_test_link(port);
1825 read_unlock(&zfcp_data.config_lock);
1826 }
1827 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 1823 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1828 break; 1824 break;
1829 case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: 1825 case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
@@ -1913,11 +1909,8 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
1913 } 1909 }
1914 } 1910 }
1915 debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); 1911 debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
1916 read_lock(&zfcp_data.config_lock);
1917 port = zfcp_get_port_by_did(adapter, d_id);
1918 if (port != NULL) 1912 if (port != NULL)
1919 zfcp_erp_port_access_denied(port); 1913 zfcp_erp_port_access_denied(port);
1920 read_unlock(&zfcp_data.config_lock);
1921 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; 1914 fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
1922 break; 1915 break;
1923 1916