diff options
author | Andreas Herrmann <aherrman@de.ibm.com> | 2005-09-13 15:47:52 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-09-19 14:01:23 -0400 |
commit | 059c97d0434834d291eff94669ca2dd3eaac9d28 (patch) | |
tree | 70719559f65366c74eb82ee8c7c7a01a0d80aca9 | |
parent | 3734d24b2e8d85796de70c13705cfb7cbb1d77df (diff) |
[SCSI] zfcp: remove union zfcp_req_data, use unit refcount for FCP commands
o union zfcp_req_data removed
o increment unit refcount when processing FCP commands
(This fixes a theoretical race: When all scsi commands of a unit
are aborted and the scsi_device is removed then the unit could be
removed before all fsf_requests of that unit are completely processed.)
Signed-off-by: Andreas Herrmann <aherrman@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 8 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 69 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 101 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 178 |
4 files changed, 81 insertions, 275 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index bfe3ba73bc0f..17f9989238f8 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -141,7 +141,7 @@ zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req, | |||
141 | 141 | ||
142 | spin_lock_irqsave(&adapter->dbf_lock, flags); | 142 | spin_lock_irqsave(&adapter->dbf_lock, flags); |
143 | if (zfcp_fsf_req_is_scsi_cmnd(fsf_req)) { | 143 | if (zfcp_fsf_req_is_scsi_cmnd(fsf_req)) { |
144 | scsi_cmnd = fsf_req->data.send_fcp_command_task.scsi_cmnd; | 144 | scsi_cmnd = (struct scsi_cmnd*) fsf_req->data; |
145 | debug_text_event(adapter->cmd_dbf, level, "fsferror"); | 145 | debug_text_event(adapter->cmd_dbf, level, "fsferror"); |
146 | debug_text_event(adapter->cmd_dbf, level, text); | 146 | debug_text_event(adapter->cmd_dbf, level, text); |
147 | debug_event(adapter->cmd_dbf, level, &fsf_req, | 147 | debug_event(adapter->cmd_dbf, level, &fsf_req, |
@@ -167,14 +167,12 @@ void | |||
167 | zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd) | 167 | zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd) |
168 | { | 168 | { |
169 | struct zfcp_adapter *adapter; | 169 | struct zfcp_adapter *adapter; |
170 | union zfcp_req_data *req_data; | ||
171 | struct zfcp_fsf_req *fsf_req; | 170 | struct zfcp_fsf_req *fsf_req; |
172 | int level = ((host_byte(scsi_cmnd->result) != 0) ? 1 : 5); | 171 | int level = ((host_byte(scsi_cmnd->result) != 0) ? 1 : 5); |
173 | unsigned long flags; | 172 | unsigned long flags; |
174 | 173 | ||
175 | adapter = (struct zfcp_adapter *) scsi_cmnd->device->host->hostdata[0]; | 174 | adapter = (struct zfcp_adapter *) scsi_cmnd->device->host->hostdata[0]; |
176 | req_data = (union zfcp_req_data *) scsi_cmnd->host_scribble; | 175 | fsf_req = (struct zfcp_fsf_req *) scsi_cmnd->host_scribble; |
177 | fsf_req = (req_data ? req_data->send_fcp_command_task.fsf_req : NULL); | ||
178 | spin_lock_irqsave(&adapter->dbf_lock, flags); | 176 | spin_lock_irqsave(&adapter->dbf_lock, flags); |
179 | debug_text_event(adapter->cmd_dbf, level, "hostbyte"); | 177 | debug_text_event(adapter->cmd_dbf, level, "hostbyte"); |
180 | debug_text_event(adapter->cmd_dbf, level, text); | 178 | debug_text_event(adapter->cmd_dbf, level, text); |
@@ -1609,7 +1607,7 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req) | |||
1609 | u32 els_type; | 1607 | u32 els_type; |
1610 | struct zfcp_adapter *adapter; | 1608 | struct zfcp_adapter *adapter; |
1611 | 1609 | ||
1612 | status_buffer = fsf_req->data.status_read.buffer; | 1610 | status_buffer = (struct fsf_status_read_buffer *) fsf_req->data; |
1613 | els_type = *(u32 *) (status_buffer->payload); | 1611 | els_type = *(u32 *) (status_buffer->payload); |
1614 | adapter = fsf_req->adapter; | 1612 | adapter = fsf_req->adapter; |
1615 | 1613 | ||
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 455e902533a9..9160e68c4a21 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -635,45 +635,6 @@ struct zfcp_adapter_mempool { | |||
635 | mempool_t *data_gid_pn; | 635 | mempool_t *data_gid_pn; |
636 | }; | 636 | }; |
637 | 637 | ||
638 | struct zfcp_exchange_config_data{ | ||
639 | }; | ||
640 | |||
641 | struct zfcp_open_port { | ||
642 | struct zfcp_port *port; | ||
643 | }; | ||
644 | |||
645 | struct zfcp_close_port { | ||
646 | struct zfcp_port *port; | ||
647 | }; | ||
648 | |||
649 | struct zfcp_open_unit { | ||
650 | struct zfcp_unit *unit; | ||
651 | }; | ||
652 | |||
653 | struct zfcp_close_unit { | ||
654 | struct zfcp_unit *unit; | ||
655 | }; | ||
656 | |||
657 | struct zfcp_close_physical_port { | ||
658 | struct zfcp_port *port; | ||
659 | }; | ||
660 | |||
661 | struct zfcp_send_fcp_command_task { | ||
662 | struct zfcp_fsf_req *fsf_req; | ||
663 | struct zfcp_unit *unit; | ||
664 | struct scsi_cmnd *scsi_cmnd; | ||
665 | unsigned long start_jiffies; | ||
666 | }; | ||
667 | |||
668 | struct zfcp_send_fcp_command_task_management { | ||
669 | struct zfcp_unit *unit; | ||
670 | }; | ||
671 | |||
672 | struct zfcp_abort_fcp_command { | ||
673 | struct zfcp_fsf_req *fsf_req; | ||
674 | struct zfcp_unit *unit; | ||
675 | }; | ||
676 | |||
677 | /* | 638 | /* |
678 | * header for CT_IU | 639 | * header for CT_IU |
679 | */ | 640 | */ |
@@ -781,33 +742,6 @@ struct zfcp_send_els { | |||
781 | int status; | 742 | int status; |
782 | }; | 743 | }; |
783 | 744 | ||
784 | struct zfcp_status_read { | ||
785 | struct fsf_status_read_buffer *buffer; | ||
786 | }; | ||
787 | |||
788 | struct zfcp_fsf_done { | ||
789 | struct completion *complete; | ||
790 | int status; | ||
791 | }; | ||
792 | |||
793 | /* request specific data */ | ||
794 | union zfcp_req_data { | ||
795 | struct zfcp_exchange_config_data exchange_config_data; | ||
796 | struct zfcp_open_port open_port; | ||
797 | struct zfcp_close_port close_port; | ||
798 | struct zfcp_open_unit open_unit; | ||
799 | struct zfcp_close_unit close_unit; | ||
800 | struct zfcp_close_physical_port close_physical_port; | ||
801 | struct zfcp_send_fcp_command_task send_fcp_command_task; | ||
802 | struct zfcp_send_fcp_command_task_management | ||
803 | send_fcp_command_task_management; | ||
804 | struct zfcp_abort_fcp_command abort_fcp_command; | ||
805 | struct zfcp_send_ct *send_ct; | ||
806 | struct zfcp_send_els *send_els; | ||
807 | struct zfcp_status_read status_read; | ||
808 | struct fsf_qtcb_bottom_port *port_data; | ||
809 | }; | ||
810 | |||
811 | struct zfcp_qdio_queue { | 745 | struct zfcp_qdio_queue { |
812 | struct qdio_buffer *buffer[QDIO_MAX_BUFFERS_PER_Q]; /* SBALs */ | 746 | struct qdio_buffer *buffer[QDIO_MAX_BUFFERS_PER_Q]; /* SBALs */ |
813 | u8 free_index; /* index of next free bfr | 747 | u8 free_index; /* index of next free bfr |
@@ -963,11 +897,12 @@ struct zfcp_fsf_req { | |||
963 | u32 fsf_command; /* FSF Command copy */ | 897 | u32 fsf_command; /* FSF Command copy */ |
964 | struct fsf_qtcb *qtcb; /* address of associated QTCB */ | 898 | struct fsf_qtcb *qtcb; /* address of associated QTCB */ |
965 | u32 seq_no; /* Sequence number of request */ | 899 | u32 seq_no; /* Sequence number of request */ |
966 | union zfcp_req_data data; /* Info fields of request */ | 900 | unsigned long data; /* private data of request */ |
967 | struct zfcp_erp_action *erp_action; /* used if this request is | 901 | struct zfcp_erp_action *erp_action; /* used if this request is |
968 | issued on behalf of erp */ | 902 | issued on behalf of erp */ |
969 | mempool_t *pool; /* used if request was alloacted | 903 | mempool_t *pool; /* used if request was alloacted |
970 | from emergency pool */ | 904 | from emergency pool */ |
905 | struct zfcp_unit *unit; | ||
971 | }; | 906 | }; |
972 | 907 | ||
973 | typedef void zfcp_fsf_req_handler_t(struct zfcp_fsf_req*); | 908 | typedef void zfcp_fsf_req_handler_t(struct zfcp_fsf_req*); |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index c007b6424e74..64e2c3480189 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -821,7 +821,7 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags) | |||
821 | goto failed_buf; | 821 | goto failed_buf; |
822 | } | 822 | } |
823 | memset(status_buffer, 0, sizeof (struct fsf_status_read_buffer)); | 823 | memset(status_buffer, 0, sizeof (struct fsf_status_read_buffer)); |
824 | fsf_req->data.status_read.buffer = status_buffer; | 824 | fsf_req->data = (unsigned long) status_buffer; |
825 | 825 | ||
826 | /* insert pointer to respective buffer */ | 826 | /* insert pointer to respective buffer */ |
827 | sbale = zfcp_qdio_sbale_curr(fsf_req); | 827 | sbale = zfcp_qdio_sbale_curr(fsf_req); |
@@ -859,7 +859,7 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req) | |||
859 | struct zfcp_port *port; | 859 | struct zfcp_port *port; |
860 | unsigned long flags; | 860 | unsigned long flags; |
861 | 861 | ||
862 | status_buffer = fsf_req->data.status_read.buffer; | 862 | status_buffer = (struct fsf_status_read_buffer *) fsf_req->data; |
863 | adapter = fsf_req->adapter; | 863 | adapter = fsf_req->adapter; |
864 | 864 | ||
865 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 865 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
@@ -918,7 +918,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) | |||
918 | int retval = 0; | 918 | int retval = 0; |
919 | struct zfcp_adapter *adapter = fsf_req->adapter; | 919 | struct zfcp_adapter *adapter = fsf_req->adapter; |
920 | struct fsf_status_read_buffer *status_buffer = | 920 | struct fsf_status_read_buffer *status_buffer = |
921 | fsf_req->data.status_read.buffer; | 921 | (struct fsf_status_read_buffer *) fsf_req->data; |
922 | 922 | ||
923 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { | 923 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { |
924 | mempool_free(status_buffer, adapter->pool.data_status_read); | 924 | mempool_free(status_buffer, adapter->pool.data_status_read); |
@@ -1093,7 +1093,7 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id, | |||
1093 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 1093 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
1094 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 1094 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
1095 | 1095 | ||
1096 | fsf_req->data.abort_fcp_command.unit = unit; | 1096 | fsf_req->data = (unsigned long) unit; |
1097 | 1097 | ||
1098 | /* set handles of unit and its parent port in QTCB */ | 1098 | /* set handles of unit and its parent port in QTCB */ |
1099 | fsf_req->qtcb->header.lun_handle = unit->handle; | 1099 | fsf_req->qtcb->header.lun_handle = unit->handle; |
@@ -1139,7 +1139,7 @@ static int | |||
1139 | zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) | 1139 | zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) |
1140 | { | 1140 | { |
1141 | int retval = -EINVAL; | 1141 | int retval = -EINVAL; |
1142 | struct zfcp_unit *unit = new_fsf_req->data.abort_fcp_command.unit; | 1142 | struct zfcp_unit *unit; |
1143 | unsigned char status_qual = | 1143 | unsigned char status_qual = |
1144 | new_fsf_req->qtcb->header.fsf_status_qual.word[0]; | 1144 | new_fsf_req->qtcb->header.fsf_status_qual.word[0]; |
1145 | 1145 | ||
@@ -1150,6 +1150,8 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) | |||
1150 | goto skip_fsfstatus; | 1150 | goto skip_fsfstatus; |
1151 | } | 1151 | } |
1152 | 1152 | ||
1153 | unit = (struct zfcp_unit *) new_fsf_req->data; | ||
1154 | |||
1153 | /* evaluate FSF status in QTCB */ | 1155 | /* evaluate FSF status in QTCB */ |
1154 | switch (new_fsf_req->qtcb->header.fsf_status) { | 1156 | switch (new_fsf_req->qtcb->header.fsf_status) { |
1155 | 1157 | ||
@@ -1414,7 +1416,7 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, | |||
1414 | fsf_req->qtcb->header.port_handle = port->handle; | 1416 | fsf_req->qtcb->header.port_handle = port->handle; |
1415 | fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; | 1417 | fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; |
1416 | fsf_req->qtcb->bottom.support.timeout = ct->timeout; | 1418 | fsf_req->qtcb->bottom.support.timeout = ct->timeout; |
1417 | fsf_req->data.send_ct = ct; | 1419 | fsf_req->data = (unsigned long) ct; |
1418 | 1420 | ||
1419 | /* start QDIO request for this FSF request */ | 1421 | /* start QDIO request for this FSF request */ |
1420 | ret = zfcp_fsf_req_send(fsf_req, ct->timer); | 1422 | ret = zfcp_fsf_req_send(fsf_req, ct->timer); |
@@ -1445,10 +1447,10 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, | |||
1445 | * zfcp_fsf_send_ct_handler - handler for Generic Service requests | 1447 | * zfcp_fsf_send_ct_handler - handler for Generic Service requests |
1446 | * @fsf_req: pointer to struct zfcp_fsf_req | 1448 | * @fsf_req: pointer to struct zfcp_fsf_req |
1447 | * | 1449 | * |
1448 | * Data specific for the Generic Service request is passed by | 1450 | * Data specific for the Generic Service request is passed using |
1449 | * fsf_req->data.send_ct | 1451 | * fsf_req->data. There we find the pointer to struct zfcp_send_ct. |
1450 | * Usually a specific handler for the request is called via | 1452 | * Usually a specific handler for the CT request is called which is |
1451 | * fsf_req->data.send_ct->handler at end of this function. | 1453 | * found in this structure. |
1452 | */ | 1454 | */ |
1453 | static int | 1455 | static int |
1454 | zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) | 1456 | zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) |
@@ -1462,7 +1464,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) | |||
1462 | u16 subtable, rule, counter; | 1464 | u16 subtable, rule, counter; |
1463 | 1465 | ||
1464 | adapter = fsf_req->adapter; | 1466 | adapter = fsf_req->adapter; |
1465 | send_ct = fsf_req->data.send_ct; | 1467 | send_ct = (struct zfcp_send_ct *) fsf_req->data; |
1466 | port = send_ct->port; | 1468 | port = send_ct->port; |
1467 | header = &fsf_req->qtcb->header; | 1469 | header = &fsf_req->qtcb->header; |
1468 | bottom = &fsf_req->qtcb->bottom.support; | 1470 | bottom = &fsf_req->qtcb->bottom.support; |
@@ -1714,7 +1716,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) | |||
1714 | fsf_req->qtcb->bottom.support.d_id = d_id; | 1716 | fsf_req->qtcb->bottom.support.d_id = d_id; |
1715 | fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; | 1717 | fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; |
1716 | fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT; | 1718 | fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT; |
1717 | fsf_req->data.send_els = els; | 1719 | fsf_req->data = (unsigned long) els; |
1718 | 1720 | ||
1719 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); | 1721 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); |
1720 | 1722 | ||
@@ -1746,10 +1748,10 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) | |||
1746 | * zfcp_fsf_send_els_handler - handler for ELS commands | 1748 | * zfcp_fsf_send_els_handler - handler for ELS commands |
1747 | * @fsf_req: pointer to struct zfcp_fsf_req | 1749 | * @fsf_req: pointer to struct zfcp_fsf_req |
1748 | * | 1750 | * |
1749 | * Data specific for the ELS command is passed by | 1751 | * Data specific for the ELS command is passed using |
1750 | * fsf_req->data.send_els | 1752 | * fsf_req->data. There we find the pointer to struct zfcp_send_els. |
1751 | * Usually a specific handler for the command is called via | 1753 | * Usually a specific handler for the ELS command is called which is |
1752 | * fsf_req->data.send_els->handler at end of this function. | 1754 | * found in this structure. |
1753 | */ | 1755 | */ |
1754 | static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) | 1756 | static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) |
1755 | { | 1757 | { |
@@ -1762,7 +1764,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) | |||
1762 | int retval = -EINVAL; | 1764 | int retval = -EINVAL; |
1763 | u16 subtable, rule, counter; | 1765 | u16 subtable, rule, counter; |
1764 | 1766 | ||
1765 | send_els = fsf_req->data.send_els; | 1767 | send_els = (struct zfcp_send_els *) fsf_req->data; |
1766 | adapter = send_els->adapter; | 1768 | adapter = send_els->adapter; |
1767 | port = send_els->port; | 1769 | port = send_els->port; |
1768 | d_id = send_els->d_id; | 1770 | d_id = send_els->d_id; |
@@ -2211,12 +2213,12 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, | |||
2211 | goto out; | 2213 | goto out; |
2212 | } | 2214 | } |
2213 | 2215 | ||
2216 | fsf_req->data = (unsigned long) data; | ||
2217 | |||
2214 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); | 2218 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); |
2215 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 2219 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
2216 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 2220 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
2217 | 2221 | ||
2218 | fsf_req->data.port_data = data; | ||
2219 | |||
2220 | init_timer(timer); | 2222 | init_timer(timer); |
2221 | timer->function = zfcp_fsf_request_timeout_handler; | 2223 | timer->function = zfcp_fsf_request_timeout_handler; |
2222 | timer->data = (unsigned long) adapter; | 2224 | timer->data = (unsigned long) adapter; |
@@ -2257,7 +2259,9 @@ static void | |||
2257 | zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) | 2259 | zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) |
2258 | { | 2260 | { |
2259 | struct fsf_qtcb_bottom_port *bottom; | 2261 | struct fsf_qtcb_bottom_port *bottom; |
2260 | struct fsf_qtcb_bottom_port *data = fsf_req->data.port_data; | 2262 | struct fsf_qtcb_bottom_port *data; |
2263 | |||
2264 | data = (struct fsf_qtcb_bottom_port*) fsf_req->data; | ||
2261 | 2265 | ||
2262 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) | 2266 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) |
2263 | return; | 2267 | return; |
@@ -2312,7 +2316,7 @@ zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) | |||
2312 | 2316 | ||
2313 | erp_action->fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id; | 2317 | erp_action->fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id; |
2314 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); | 2318 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); |
2315 | erp_action->fsf_req->data.open_port.port = erp_action->port; | 2319 | erp_action->fsf_req->data = (unsigned long) erp_action->port; |
2316 | erp_action->fsf_req->erp_action = erp_action; | 2320 | erp_action->fsf_req->erp_action = erp_action; |
2317 | 2321 | ||
2318 | /* start QDIO request for this FSF request */ | 2322 | /* start QDIO request for this FSF request */ |
@@ -2353,7 +2357,7 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req) | |||
2353 | struct fsf_qtcb_header *header; | 2357 | struct fsf_qtcb_header *header; |
2354 | u16 subtable, rule, counter; | 2358 | u16 subtable, rule, counter; |
2355 | 2359 | ||
2356 | port = fsf_req->data.open_port.port; | 2360 | port = (struct zfcp_port *) fsf_req->data; |
2357 | header = &fsf_req->qtcb->header; | 2361 | header = &fsf_req->qtcb->header; |
2358 | 2362 | ||
2359 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { | 2363 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { |
@@ -2566,7 +2570,7 @@ zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) | |||
2566 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 2570 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
2567 | 2571 | ||
2568 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); | 2572 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); |
2569 | erp_action->fsf_req->data.close_port.port = erp_action->port; | 2573 | erp_action->fsf_req->data = (unsigned long) erp_action->port; |
2570 | erp_action->fsf_req->erp_action = erp_action; | 2574 | erp_action->fsf_req->erp_action = erp_action; |
2571 | erp_action->fsf_req->qtcb->header.port_handle = | 2575 | erp_action->fsf_req->qtcb->header.port_handle = |
2572 | erp_action->port->handle; | 2576 | erp_action->port->handle; |
@@ -2606,7 +2610,7 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req) | |||
2606 | int retval = -EINVAL; | 2610 | int retval = -EINVAL; |
2607 | struct zfcp_port *port; | 2611 | struct zfcp_port *port; |
2608 | 2612 | ||
2609 | port = fsf_req->data.close_port.port; | 2613 | port = (struct zfcp_port *) fsf_req->data; |
2610 | 2614 | ||
2611 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { | 2615 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { |
2612 | /* don't change port status in our bookkeeping */ | 2616 | /* don't change port status in our bookkeeping */ |
@@ -2703,7 +2707,7 @@ zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) | |||
2703 | atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, | 2707 | atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, |
2704 | &erp_action->port->status); | 2708 | &erp_action->port->status); |
2705 | /* save a pointer to this port */ | 2709 | /* save a pointer to this port */ |
2706 | erp_action->fsf_req->data.close_physical_port.port = erp_action->port; | 2710 | erp_action->fsf_req->data = (unsigned long) erp_action->port; |
2707 | /* port to be closeed */ | 2711 | /* port to be closeed */ |
2708 | erp_action->fsf_req->qtcb->header.port_handle = | 2712 | erp_action->fsf_req->qtcb->header.port_handle = |
2709 | erp_action->port->handle; | 2713 | erp_action->port->handle; |
@@ -2747,7 +2751,7 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req) | |||
2747 | struct fsf_qtcb_header *header; | 2751 | struct fsf_qtcb_header *header; |
2748 | u16 subtable, rule, counter; | 2752 | u16 subtable, rule, counter; |
2749 | 2753 | ||
2750 | port = fsf_req->data.close_physical_port.port; | 2754 | port = (struct zfcp_port *) fsf_req->data; |
2751 | header = &fsf_req->qtcb->header; | 2755 | header = &fsf_req->qtcb->header; |
2752 | 2756 | ||
2753 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { | 2757 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { |
@@ -2911,7 +2915,7 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) | |||
2911 | erp_action->fsf_req->qtcb->bottom.support.option = | 2915 | erp_action->fsf_req->qtcb->bottom.support.option = |
2912 | FSF_OPEN_LUN_SUPPRESS_BOXING; | 2916 | FSF_OPEN_LUN_SUPPRESS_BOXING; |
2913 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); | 2917 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); |
2914 | erp_action->fsf_req->data.open_unit.unit = erp_action->unit; | 2918 | erp_action->fsf_req->data = (unsigned long) erp_action->unit; |
2915 | erp_action->fsf_req->erp_action = erp_action; | 2919 | erp_action->fsf_req->erp_action = erp_action; |
2916 | 2920 | ||
2917 | /* start QDIO request for this FSF request */ | 2921 | /* start QDIO request for this FSF request */ |
@@ -2957,7 +2961,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) | |||
2957 | u16 subtable, rule, counter; | 2961 | u16 subtable, rule, counter; |
2958 | u32 allowed, exclusive, readwrite; | 2962 | u32 allowed, exclusive, readwrite; |
2959 | 2963 | ||
2960 | unit = fsf_req->data.open_unit.unit; | 2964 | unit = (struct zfcp_unit *) fsf_req->data; |
2961 | 2965 | ||
2962 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { | 2966 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { |
2963 | /* don't change unit status in our bookkeeping */ | 2967 | /* don't change unit status in our bookkeeping */ |
@@ -3242,7 +3246,7 @@ zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) | |||
3242 | erp_action->port->handle; | 3246 | erp_action->port->handle; |
3243 | erp_action->fsf_req->qtcb->header.lun_handle = erp_action->unit->handle; | 3247 | erp_action->fsf_req->qtcb->header.lun_handle = erp_action->unit->handle; |
3244 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status); | 3248 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status); |
3245 | erp_action->fsf_req->data.close_unit.unit = erp_action->unit; | 3249 | erp_action->fsf_req->data = (unsigned long) erp_action->unit; |
3246 | erp_action->fsf_req->erp_action = erp_action; | 3250 | erp_action->fsf_req->erp_action = erp_action; |
3247 | 3251 | ||
3248 | /* start QDIO request for this FSF request */ | 3252 | /* start QDIO request for this FSF request */ |
@@ -3281,7 +3285,7 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req) | |||
3281 | int retval = -EINVAL; | 3285 | int retval = -EINVAL; |
3282 | struct zfcp_unit *unit; | 3286 | struct zfcp_unit *unit; |
3283 | 3287 | ||
3284 | unit = fsf_req->data.close_unit.unit; /* restore unit */ | 3288 | unit = (struct zfcp_unit *) fsf_req->data; |
3285 | 3289 | ||
3286 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { | 3290 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { |
3287 | /* don't change unit status in our bookkeeping */ | 3291 | /* don't change unit status in our bookkeeping */ |
@@ -3436,21 +3440,14 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, | |||
3436 | goto failed_req_create; | 3440 | goto failed_req_create; |
3437 | } | 3441 | } |
3438 | 3442 | ||
3439 | /* | 3443 | zfcp_unit_get(unit); |
3440 | * associate FSF request with SCSI request | 3444 | fsf_req->unit = unit; |
3441 | * (need this for look up on abort) | ||
3442 | */ | ||
3443 | fsf_req->data.send_fcp_command_task.fsf_req = fsf_req; | ||
3444 | scsi_cmnd->host_scribble = (char *) &(fsf_req->data); | ||
3445 | 3445 | ||
3446 | /* | 3446 | /* associate FSF request with SCSI request (for look up on abort) */ |
3447 | * associate SCSI command with FSF request | 3447 | scsi_cmnd->host_scribble = (char *) fsf_req; |
3448 | * (need this for look up on normal command completion) | 3448 | |
3449 | */ | 3449 | /* associate SCSI command with FSF request */ |
3450 | fsf_req->data.send_fcp_command_task.scsi_cmnd = scsi_cmnd; | 3450 | fsf_req->data = (unsigned long) scsi_cmnd; |
3451 | fsf_req->data.send_fcp_command_task.start_jiffies = jiffies; | ||
3452 | fsf_req->data.send_fcp_command_task.unit = unit; | ||
3453 | ZFCP_LOG_DEBUG("unit=%p, fcp_lun=0x%016Lx\n", unit, unit->fcp_lun); | ||
3454 | 3451 | ||
3455 | /* set handles of unit and its parent port in QTCB */ | 3452 | /* set handles of unit and its parent port in QTCB */ |
3456 | fsf_req->qtcb->header.lun_handle = unit->handle; | 3453 | fsf_req->qtcb->header.lun_handle = unit->handle; |
@@ -3584,6 +3581,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, | |||
3584 | send_failed: | 3581 | send_failed: |
3585 | no_fit: | 3582 | no_fit: |
3586 | failed_scsi_cmnd: | 3583 | failed_scsi_cmnd: |
3584 | zfcp_unit_put(unit); | ||
3587 | zfcp_fsf_req_free(fsf_req); | 3585 | zfcp_fsf_req_free(fsf_req); |
3588 | fsf_req = NULL; | 3586 | fsf_req = NULL; |
3589 | scsi_cmnd->host_scribble = NULL; | 3587 | scsi_cmnd->host_scribble = NULL; |
@@ -3640,7 +3638,7 @@ zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter, | |||
3640 | * hold a pointer to the unit being target of this | 3638 | * hold a pointer to the unit being target of this |
3641 | * task management request | 3639 | * task management request |
3642 | */ | 3640 | */ |
3643 | fsf_req->data.send_fcp_command_task_management.unit = unit; | 3641 | fsf_req->data = (unsigned long) unit; |
3644 | 3642 | ||
3645 | /* set FSF related fields in QTCB */ | 3643 | /* set FSF related fields in QTCB */ |
3646 | fsf_req->qtcb->header.lun_handle = unit->handle; | 3644 | fsf_req->qtcb->header.lun_handle = unit->handle; |
@@ -3706,9 +3704,9 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) | |||
3706 | header = &fsf_req->qtcb->header; | 3704 | header = &fsf_req->qtcb->header; |
3707 | 3705 | ||
3708 | if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)) | 3706 | if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)) |
3709 | unit = fsf_req->data.send_fcp_command_task_management.unit; | 3707 | unit = (struct zfcp_unit *) fsf_req->data; |
3710 | else | 3708 | else |
3711 | unit = fsf_req->data.send_fcp_command_task.unit; | 3709 | unit = fsf_req->unit; |
3712 | 3710 | ||
3713 | if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { | 3711 | if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { |
3714 | /* go directly to calls of special handlers */ | 3712 | /* go directly to calls of special handlers */ |
@@ -3947,6 +3945,8 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) | |||
3947 | zfcp_fsf_send_fcp_command_task_management_handler(fsf_req); | 3945 | zfcp_fsf_send_fcp_command_task_management_handler(fsf_req); |
3948 | } else { | 3946 | } else { |
3949 | retval = zfcp_fsf_send_fcp_command_task_handler(fsf_req); | 3947 | retval = zfcp_fsf_send_fcp_command_task_handler(fsf_req); |
3948 | fsf_req->unit = NULL; | ||
3949 | zfcp_unit_put(unit); | ||
3950 | } | 3950 | } |
3951 | return retval; | 3951 | return retval; |
3952 | } | 3952 | } |
@@ -3970,10 +3970,10 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) | |||
3970 | u32 sns_len; | 3970 | u32 sns_len; |
3971 | char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); | 3971 | char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); |
3972 | unsigned long flags; | 3972 | unsigned long flags; |
3973 | struct zfcp_unit *unit = fsf_req->data.send_fcp_command_task.unit; | 3973 | struct zfcp_unit *unit = fsf_req->unit; |
3974 | 3974 | ||
3975 | read_lock_irqsave(&fsf_req->adapter->abort_lock, flags); | 3975 | read_lock_irqsave(&fsf_req->adapter->abort_lock, flags); |
3976 | scpnt = fsf_req->data.send_fcp_command_task.scsi_cmnd; | 3976 | scpnt = (struct scsi_cmnd *) fsf_req->data; |
3977 | if (unlikely(!scpnt)) { | 3977 | if (unlikely(!scpnt)) { |
3978 | ZFCP_LOG_DEBUG | 3978 | ZFCP_LOG_DEBUG |
3979 | ("Command with fsf_req %p is not associated to " | 3979 | ("Command with fsf_req %p is not associated to " |
@@ -4198,8 +4198,7 @@ zfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req) | |||
4198 | struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *) | 4198 | struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *) |
4199 | &(fsf_req->qtcb->bottom.io.fcp_rsp); | 4199 | &(fsf_req->qtcb->bottom.io.fcp_rsp); |
4200 | char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); | 4200 | char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); |
4201 | struct zfcp_unit *unit = | 4201 | struct zfcp_unit *unit = (struct zfcp_unit *) fsf_req->data; |
4202 | fsf_req->data.send_fcp_command_task_management.unit; | ||
4203 | 4202 | ||
4204 | del_timer(&fsf_req->adapter->scsi_er_timer); | 4203 | del_timer(&fsf_req->adapter->scsi_er_timer); |
4205 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { | 4204 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 31a76065cf28..fffd12399010 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -414,67 +414,37 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id) | |||
414 | return (struct zfcp_port *) NULL; | 414 | return (struct zfcp_port *) NULL; |
415 | } | 415 | } |
416 | 416 | ||
417 | /* | 417 | /** |
418 | * function: zfcp_scsi_eh_abort_handler | 418 | * zfcp_scsi_eh_abort_handler - abort the specified SCSI command |
419 | * | 419 | * @scpnt: pointer to scsi_cmnd to be aborted |
420 | * purpose: tries to abort the specified (timed out) SCSI command | 420 | * Return: SUCCESS - command has been aborted and cleaned up in internal |
421 | * | 421 | * bookkeeping, SCSI stack won't be called for aborted command |
422 | * note: We do not need to care for a SCSI command which completes | 422 | * FAILED - otherwise |
423 | * normally but late during this abort routine runs. | ||
424 | * We are allowed to return late commands to the SCSI stack. | ||
425 | * It tracks the state of commands and will handle late commands. | ||
426 | * (Usually, the normal completion of late commands is ignored with | ||
427 | * respect to the running abort operation. Grep for 'done_late' | ||
428 | * in the SCSI stacks sources.) | ||
429 | * | 423 | * |
430 | * returns: SUCCESS - command has been aborted and cleaned up in internal | 424 | * We do not need to care for a SCSI command which completes normally |
431 | * bookkeeping, | 425 | * but late during this abort routine runs. We are allowed to return |
432 | * SCSI stack won't be called for aborted command | 426 | * late commands to the SCSI stack. It tracks the state of commands and |
433 | * FAILED - otherwise | 427 | * will handle late commands. (Usually, the normal completion of late |
428 | * commands is ignored with respect to the running abort operation.) | ||
434 | */ | 429 | */ |
435 | int | 430 | int |
436 | __zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | 431 | zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) |
437 | { | 432 | { |
433 | struct Scsi_Host *scsi_host; | ||
434 | struct zfcp_adapter *adapter; | ||
435 | struct zfcp_unit *unit; | ||
438 | int retval = SUCCESS; | 436 | int retval = SUCCESS; |
439 | struct zfcp_fsf_req *new_fsf_req, *old_fsf_req; | 437 | struct zfcp_fsf_req *new_fsf_req, *old_fsf_req; |
440 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; | ||
441 | struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata; | ||
442 | struct zfcp_port *port = unit->port; | ||
443 | struct Scsi_Host *scsi_host = scpnt->device->host; | ||
444 | union zfcp_req_data *req_data = NULL; | ||
445 | unsigned long flags; | 438 | unsigned long flags; |
446 | u32 status = 0; | 439 | |
447 | 440 | scsi_host = scpnt->device->host; | |
448 | /* the components of a abort_dbf record (fixed size record) */ | 441 | adapter = (struct zfcp_adapter *) scsi_host->hostdata[0]; |
449 | u64 dbf_scsi_cmnd = (unsigned long) scpnt; | 442 | unit = (struct zfcp_unit *) scpnt->device->hostdata; |
450 | char dbf_opcode[ZFCP_ABORT_DBF_LENGTH]; | ||
451 | wwn_t dbf_wwn = port->wwpn; | ||
452 | fcp_lun_t dbf_fcp_lun = unit->fcp_lun; | ||
453 | u64 dbf_retries = scpnt->retries; | ||
454 | u64 dbf_allowed = scpnt->allowed; | ||
455 | u64 dbf_timeout = 0; | ||
456 | u64 dbf_fsf_req = 0; | ||
457 | u64 dbf_fsf_status = 0; | ||
458 | u64 dbf_fsf_qual[2] = { 0, 0 }; | ||
459 | char dbf_result[ZFCP_ABORT_DBF_LENGTH] = "##undef"; | ||
460 | |||
461 | memset(dbf_opcode, 0, ZFCP_ABORT_DBF_LENGTH); | ||
462 | memcpy(dbf_opcode, | ||
463 | scpnt->cmnd, | ||
464 | min(scpnt->cmd_len, (unsigned char) ZFCP_ABORT_DBF_LENGTH)); | ||
465 | 443 | ||
466 | ZFCP_LOG_INFO("aborting scsi_cmnd=%p on adapter %s\n", | 444 | ZFCP_LOG_INFO("aborting scsi_cmnd=%p on adapter %s\n", |
467 | scpnt, zfcp_get_busid_by_adapter(adapter)); | 445 | scpnt, zfcp_get_busid_by_adapter(adapter)); |
468 | 446 | ||
469 | spin_unlock_irq(scsi_host->host_lock); | 447 | /* avoid race condition between late normal completion and abort */ |
470 | |||
471 | /* | ||
472 | * Race condition between normal (late) completion and abort has | ||
473 | * to be avoided. | ||
474 | * The entirity of all accesses to scsi_req have to be atomic. | ||
475 | * scsi_req is usually part of the fsf_req and thus we block the | ||
476 | * release of fsf_req as long as we need to access scsi_req. | ||
477 | */ | ||
478 | write_lock_irqsave(&adapter->abort_lock, flags); | 448 | write_lock_irqsave(&adapter->abort_lock, flags); |
479 | 449 | ||
480 | /* | 450 | /* |
@@ -484,144 +454,48 @@ __zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
484 | * this routine returns. (scpnt is parameter passed to this routine | 454 | * this routine returns. (scpnt is parameter passed to this routine |
485 | * and must not disappear during abort even on late completion.) | 455 | * and must not disappear during abort even on late completion.) |
486 | */ | 456 | */ |
487 | req_data = (union zfcp_req_data *) scpnt->host_scribble; | 457 | old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble; |
488 | /* DEBUG */ | ||
489 | ZFCP_LOG_DEBUG("req_data=%p\n", req_data); | ||
490 | if (!req_data) { | ||
491 | ZFCP_LOG_DEBUG("late command completion overtook abort\n"); | ||
492 | /* | ||
493 | * That's it. | ||
494 | * Do not initiate abort but return SUCCESS. | ||
495 | */ | ||
496 | write_unlock_irqrestore(&adapter->abort_lock, flags); | ||
497 | retval = SUCCESS; | ||
498 | strncpy(dbf_result, "##late1", ZFCP_ABORT_DBF_LENGTH); | ||
499 | goto out; | ||
500 | } | ||
501 | |||
502 | /* Figure out which fsf_req needs to be aborted. */ | ||
503 | old_fsf_req = req_data->send_fcp_command_task.fsf_req; | ||
504 | |||
505 | dbf_fsf_req = (unsigned long) old_fsf_req; | ||
506 | dbf_timeout = | ||
507 | (jiffies - req_data->send_fcp_command_task.start_jiffies) / HZ; | ||
508 | |||
509 | ZFCP_LOG_DEBUG("old_fsf_req=%p\n", old_fsf_req); | ||
510 | if (!old_fsf_req) { | 458 | if (!old_fsf_req) { |
511 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 459 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
512 | ZFCP_LOG_NORMAL("bug: no old fsf request found\n"); | 460 | ZFCP_LOG_NORMAL("bug: no old fsf request found\n"); |
513 | ZFCP_LOG_NORMAL("req_data:\n"); | ||
514 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, | ||
515 | (char *) req_data, sizeof (union zfcp_req_data)); | ||
516 | ZFCP_LOG_NORMAL("scsi_cmnd:\n"); | 461 | ZFCP_LOG_NORMAL("scsi_cmnd:\n"); |
517 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, | 462 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, |
518 | (char *) scpnt, sizeof (struct scsi_cmnd)); | 463 | (char *) scpnt, sizeof (struct scsi_cmnd)); |
519 | retval = FAILED; | 464 | retval = FAILED; |
520 | strncpy(dbf_result, "##bug:r", ZFCP_ABORT_DBF_LENGTH); | ||
521 | goto out; | 465 | goto out; |
522 | } | 466 | } |
523 | old_fsf_req->data.send_fcp_command_task.scsi_cmnd = NULL; | 467 | old_fsf_req->data = 0; |
524 | /* mark old request as being aborted */ | ||
525 | old_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING; | 468 | old_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING; |
526 | /* | ||
527 | * We have to collect all information (e.g. unit) needed by | ||
528 | * zfcp_fsf_abort_fcp_command before calling that routine | ||
529 | * since that routine is not allowed to access | ||
530 | * fsf_req which it is going to abort. | ||
531 | * This is because of we need to release fsf_req_list_lock | ||
532 | * before calling zfcp_fsf_abort_fcp_command. | ||
533 | * Since this lock will not be held, fsf_req may complete | ||
534 | * late and may be released meanwhile. | ||
535 | */ | ||
536 | ZFCP_LOG_DEBUG("unit 0x%016Lx (%p)\n", unit->fcp_lun, unit); | ||
537 | 469 | ||
538 | /* | 470 | /* don't access old_fsf_req after releasing the abort_lock */ |
539 | * We block (call schedule) | ||
540 | * That's why we must release the lock and enable the | ||
541 | * interrupts before. | ||
542 | * On the other hand we do not need the lock anymore since | ||
543 | * all critical accesses to scsi_req are done. | ||
544 | */ | ||
545 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 471 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
546 | /* call FSF routine which does the abort */ | 472 | /* call FSF routine which does the abort */ |
547 | new_fsf_req = zfcp_fsf_abort_fcp_command((unsigned long) old_fsf_req, | 473 | new_fsf_req = zfcp_fsf_abort_fcp_command((unsigned long) old_fsf_req, |
548 | adapter, unit, 0); | 474 | adapter, unit, 0); |
549 | ZFCP_LOG_DEBUG("new_fsf_req=%p\n", new_fsf_req); | ||
550 | if (!new_fsf_req) { | 475 | if (!new_fsf_req) { |
551 | retval = FAILED; | 476 | retval = FAILED; |
552 | ZFCP_LOG_NORMAL("error: initiation of Abort FCP Cmnd " | 477 | ZFCP_LOG_NORMAL("error: initiation of Abort FCP Cmnd " |
553 | "failed\n"); | 478 | "failed\n"); |
554 | strncpy(dbf_result, "##nores", ZFCP_ABORT_DBF_LENGTH); | ||
555 | goto out; | 479 | goto out; |
556 | } | 480 | } |
557 | 481 | ||
558 | /* wait for completion of abort */ | 482 | /* wait for completion of abort */ |
559 | ZFCP_LOG_DEBUG("waiting for cleanup...\n"); | ||
560 | #if 1 | ||
561 | /* | ||
562 | * FIXME: | ||
563 | * copying zfcp_fsf_req_wait_and_cleanup code is not really nice | ||
564 | */ | ||
565 | __wait_event(new_fsf_req->completion_wq, | 483 | __wait_event(new_fsf_req->completion_wq, |
566 | new_fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | 484 | new_fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); |
567 | status = new_fsf_req->status; | ||
568 | dbf_fsf_status = new_fsf_req->qtcb->header.fsf_status; | ||
569 | /* | ||
570 | * Ralphs special debug load provides timestamps in the FSF | ||
571 | * status qualifier. This might be specified later if being | ||
572 | * useful for debugging aborts. | ||
573 | */ | ||
574 | dbf_fsf_qual[0] = | ||
575 | *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[0]; | ||
576 | dbf_fsf_qual[1] = | ||
577 | *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[2]; | ||
578 | zfcp_fsf_req_free(new_fsf_req); | 485 | zfcp_fsf_req_free(new_fsf_req); |
579 | #else | 486 | |
580 | retval = zfcp_fsf_req_wait_and_cleanup(new_fsf_req, | ||
581 | ZFCP_UNINTERRUPTIBLE, &status); | ||
582 | #endif | ||
583 | ZFCP_LOG_DEBUG("Waiting for cleanup complete, status=0x%x\n", status); | ||
584 | /* status should be valid since signals were not permitted */ | 487 | /* status should be valid since signals were not permitted */ |
585 | if (status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { | 488 | if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { |
586 | retval = SUCCESS; | 489 | retval = SUCCESS; |
587 | strncpy(dbf_result, "##succ", ZFCP_ABORT_DBF_LENGTH); | 490 | } else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { |
588 | } else if (status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { | ||
589 | retval = SUCCESS; | 491 | retval = SUCCESS; |
590 | strncpy(dbf_result, "##late2", ZFCP_ABORT_DBF_LENGTH); | ||
591 | } else { | 492 | } else { |
592 | retval = FAILED; | 493 | retval = FAILED; |
593 | strncpy(dbf_result, "##fail", ZFCP_ABORT_DBF_LENGTH); | ||
594 | } | 494 | } |
595 | |||
596 | out: | 495 | out: |
597 | debug_event(adapter->abort_dbf, 1, &dbf_scsi_cmnd, sizeof (u64)); | ||
598 | debug_event(adapter->abort_dbf, 1, &dbf_opcode, ZFCP_ABORT_DBF_LENGTH); | ||
599 | debug_event(adapter->abort_dbf, 1, &dbf_wwn, sizeof (wwn_t)); | ||
600 | debug_event(adapter->abort_dbf, 1, &dbf_fcp_lun, sizeof (fcp_lun_t)); | ||
601 | debug_event(adapter->abort_dbf, 1, &dbf_retries, sizeof (u64)); | ||
602 | debug_event(adapter->abort_dbf, 1, &dbf_allowed, sizeof (u64)); | ||
603 | debug_event(adapter->abort_dbf, 1, &dbf_timeout, sizeof (u64)); | ||
604 | debug_event(adapter->abort_dbf, 1, &dbf_fsf_req, sizeof (u64)); | ||
605 | debug_event(adapter->abort_dbf, 1, &dbf_fsf_status, sizeof (u64)); | ||
606 | debug_event(adapter->abort_dbf, 1, &dbf_fsf_qual[0], sizeof (u64)); | ||
607 | debug_event(adapter->abort_dbf, 1, &dbf_fsf_qual[1], sizeof (u64)); | ||
608 | debug_text_event(adapter->abort_dbf, 1, dbf_result); | ||
609 | |||
610 | spin_lock_irq(scsi_host->host_lock); | ||
611 | return retval; | 496 | return retval; |
612 | } | 497 | } |
613 | 498 | ||
614 | int | ||
615 | zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | ||
616 | { | ||
617 | int rc; | ||
618 | struct Scsi_Host *scsi_host = scpnt->device->host; | ||
619 | spin_lock_irq(scsi_host->host_lock); | ||
620 | rc = __zfcp_scsi_eh_abort_handler(scpnt); | ||
621 | spin_unlock_irq(scsi_host->host_lock); | ||
622 | return rc; | ||
623 | } | ||
624 | |||
625 | /* | 499 | /* |
626 | * function: zfcp_scsi_eh_device_reset_handler | 500 | * function: zfcp_scsi_eh_device_reset_handler |
627 | * | 501 | * |