diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2007-05-08 05:17:54 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-05-08 12:56:50 -0400 |
commit | ca2d02c2f9ea476062ae181eec60b8bcd97857d6 (patch) | |
tree | dffe33856db601a173a117263b9ee4799d555ac6 | |
parent | 5f852be9e11d62223ea063f6ceed4f9677f54051 (diff) |
[SCSI] zfcp: rework request ID management.
Simplify request ID management and make sure that frequently used
functions are inlined. Also fix a memory leak in zfcp_adapter_enqueue()
which only gets hit in error handling.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 82 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 36 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_erp.c | 3 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 4 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 2 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_qdio.c | 17 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 4 |
7 files changed, 59 insertions, 89 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 49d5fc729bef..324899c96efe 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -118,97 +118,32 @@ _zfcp_hex_dump(char *addr, int count) | |||
118 | 118 | ||
119 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_FSF | 119 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_FSF |
120 | 120 | ||
121 | static int zfcp_reqlist_init(struct zfcp_adapter *adapter) | 121 | static int zfcp_reqlist_alloc(struct zfcp_adapter *adapter) |
122 | { | 122 | { |
123 | int i; | 123 | int idx; |
124 | 124 | ||
125 | adapter->req_list = kcalloc(REQUEST_LIST_SIZE, sizeof(struct list_head), | 125 | adapter->req_list = kcalloc(REQUEST_LIST_SIZE, sizeof(struct list_head), |
126 | GFP_KERNEL); | 126 | GFP_KERNEL); |
127 | |||
128 | if (!adapter->req_list) | 127 | if (!adapter->req_list) |
129 | return -ENOMEM; | 128 | return -ENOMEM; |
130 | 129 | ||
131 | for (i=0; i<REQUEST_LIST_SIZE; i++) | 130 | for (idx = 0; idx < REQUEST_LIST_SIZE; idx++) |
132 | INIT_LIST_HEAD(&adapter->req_list[i]); | 131 | INIT_LIST_HEAD(&adapter->req_list[idx]); |
133 | |||
134 | return 0; | 132 | return 0; |
135 | } | 133 | } |
136 | 134 | ||
137 | static void zfcp_reqlist_free(struct zfcp_adapter *adapter) | 135 | static void zfcp_reqlist_free(struct zfcp_adapter *adapter) |
138 | { | 136 | { |
139 | struct zfcp_fsf_req *request, *tmp; | ||
140 | unsigned int i; | ||
141 | |||
142 | for (i=0; i<REQUEST_LIST_SIZE; i++) { | ||
143 | if (list_empty(&adapter->req_list[i])) | ||
144 | continue; | ||
145 | |||
146 | list_for_each_entry_safe(request, tmp, | ||
147 | &adapter->req_list[i], list) | ||
148 | list_del(&request->list); | ||
149 | } | ||
150 | |||
151 | kfree(adapter->req_list); | 137 | kfree(adapter->req_list); |
152 | } | 138 | } |
153 | 139 | ||
154 | void zfcp_reqlist_add(struct zfcp_adapter *adapter, | ||
155 | struct zfcp_fsf_req *fsf_req) | ||
156 | { | ||
157 | unsigned int i; | ||
158 | |||
159 | i = fsf_req->req_id % REQUEST_LIST_SIZE; | ||
160 | list_add_tail(&fsf_req->list, &adapter->req_list[i]); | ||
161 | } | ||
162 | |||
163 | void zfcp_reqlist_remove(struct zfcp_adapter *adapter, unsigned long req_id) | ||
164 | { | ||
165 | struct zfcp_fsf_req *request, *tmp; | ||
166 | unsigned int i, counter; | ||
167 | u64 dbg_tmp[2]; | ||
168 | |||
169 | i = req_id % REQUEST_LIST_SIZE; | ||
170 | BUG_ON(list_empty(&adapter->req_list[i])); | ||
171 | |||
172 | counter = 0; | ||
173 | list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list) { | ||
174 | if (request->req_id == req_id) { | ||
175 | dbg_tmp[0] = (u64) atomic_read(&adapter->reqs_active); | ||
176 | dbg_tmp[1] = (u64) counter; | ||
177 | debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16); | ||
178 | list_del(&request->list); | ||
179 | break; | ||
180 | } | ||
181 | counter++; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *adapter, | ||
186 | unsigned long req_id) | ||
187 | { | ||
188 | struct zfcp_fsf_req *request, *tmp; | ||
189 | unsigned int i; | ||
190 | |||
191 | /* 0 is reserved as an invalid req_id */ | ||
192 | if (req_id == 0) | ||
193 | return NULL; | ||
194 | |||
195 | i = req_id % REQUEST_LIST_SIZE; | ||
196 | |||
197 | list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list) | ||
198 | if (request->req_id == req_id) | ||
199 | return request; | ||
200 | |||
201 | return NULL; | ||
202 | } | ||
203 | |||
204 | int zfcp_reqlist_isempty(struct zfcp_adapter *adapter) | 140 | int zfcp_reqlist_isempty(struct zfcp_adapter *adapter) |
205 | { | 141 | { |
206 | unsigned int i; | 142 | unsigned int idx; |
207 | 143 | ||
208 | for (i=0; i<REQUEST_LIST_SIZE; i++) | 144 | for (idx = 0; idx < REQUEST_LIST_SIZE; idx++) |
209 | if (!list_empty(&adapter->req_list[i])) | 145 | if (!list_empty(&adapter->req_list[idx])) |
210 | return 0; | 146 | return 0; |
211 | |||
212 | return 1; | 147 | return 1; |
213 | } | 148 | } |
214 | 149 | ||
@@ -1106,7 +1041,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
1106 | 1041 | ||
1107 | /* initialize list of fsf requests */ | 1042 | /* initialize list of fsf requests */ |
1108 | spin_lock_init(&adapter->req_list_lock); | 1043 | spin_lock_init(&adapter->req_list_lock); |
1109 | retval = zfcp_reqlist_init(adapter); | 1044 | retval = zfcp_reqlist_alloc(adapter); |
1110 | if (retval) { | 1045 | if (retval) { |
1111 | ZFCP_LOG_INFO("request list initialization failed\n"); | 1046 | ZFCP_LOG_INFO("request list initialization failed\n"); |
1112 | goto failed_low_mem_buffers; | 1047 | goto failed_low_mem_buffers; |
@@ -1167,6 +1102,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
1167 | zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); | 1102 | zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); |
1168 | sysfs_failed: | 1103 | sysfs_failed: |
1169 | dev_set_drvdata(&ccw_device->dev, NULL); | 1104 | dev_set_drvdata(&ccw_device->dev, NULL); |
1105 | zfcp_reqlist_free(adapter); | ||
1170 | failed_low_mem_buffers: | 1106 | failed_low_mem_buffers: |
1171 | zfcp_free_low_mem_buffers(adapter); | 1107 | zfcp_free_low_mem_buffers(adapter); |
1172 | if (qdio_free(ccw_device) != 0) | 1108 | if (qdio_free(ccw_device) != 0) |
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 07b0957b82f3..22649639230b 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -1090,6 +1090,42 @@ extern void _zfcp_hex_dump(char *, int); | |||
1090 | #define zfcp_get_busid_by_unit(unit) (zfcp_get_busid_by_port(unit->port)) | 1090 | #define zfcp_get_busid_by_unit(unit) (zfcp_get_busid_by_port(unit->port)) |
1091 | 1091 | ||
1092 | /* | 1092 | /* |
1093 | * Helper functions for request ID management. | ||
1094 | */ | ||
1095 | static inline int zfcp_reqlist_hash(unsigned long req_id) | ||
1096 | { | ||
1097 | return req_id % REQUEST_LIST_SIZE; | ||
1098 | } | ||
1099 | |||
1100 | static inline void zfcp_reqlist_add(struct zfcp_adapter *adapter, | ||
1101 | struct zfcp_fsf_req *fsf_req) | ||
1102 | { | ||
1103 | unsigned int idx; | ||
1104 | |||
1105 | idx = zfcp_reqlist_hash(fsf_req->req_id); | ||
1106 | list_add_tail(&fsf_req->list, &adapter->req_list[idx]); | ||
1107 | } | ||
1108 | |||
1109 | static inline void zfcp_reqlist_remove(struct zfcp_adapter *adapter, | ||
1110 | struct zfcp_fsf_req *fsf_req) | ||
1111 | { | ||
1112 | list_del(&fsf_req->list); | ||
1113 | } | ||
1114 | |||
1115 | static inline struct zfcp_fsf_req * | ||
1116 | zfcp_reqlist_find(struct zfcp_adapter *adapter, unsigned long req_id) | ||
1117 | { | ||
1118 | struct zfcp_fsf_req *request; | ||
1119 | unsigned int idx; | ||
1120 | |||
1121 | idx = zfcp_reqlist_hash(req_id); | ||
1122 | list_for_each_entry(request, &adapter->req_list[idx], list) | ||
1123 | if (request->req_id == req_id) | ||
1124 | return request; | ||
1125 | return NULL; | ||
1126 | } | ||
1127 | |||
1128 | /* | ||
1093 | * functions needed for reference/usage counting | 1129 | * functions needed for reference/usage counting |
1094 | */ | 1130 | */ |
1095 | 1131 | ||
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 885572300589..e2a3d6fe1651 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -847,8 +847,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) | |||
847 | if (erp_action->fsf_req) { | 847 | if (erp_action->fsf_req) { |
848 | /* take lock to ensure that request is not deleted meanwhile */ | 848 | /* take lock to ensure that request is not deleted meanwhile */ |
849 | spin_lock(&adapter->req_list_lock); | 849 | spin_lock(&adapter->req_list_lock); |
850 | if (zfcp_reqlist_ismember(adapter, | 850 | if (zfcp_reqlist_find(adapter, erp_action->fsf_req->req_id)) { |
851 | erp_action->fsf_req->req_id)) { | ||
852 | /* fsf_req still exists */ | 851 | /* fsf_req still exists */ |
853 | debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); | 852 | debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); |
854 | debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req, | 853 | debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req, |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 01386ac688a2..991d45667a44 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -184,10 +184,6 @@ extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *, | |||
184 | unsigned long); | 184 | unsigned long); |
185 | extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, | 185 | extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, |
186 | struct scsi_cmnd *); | 186 | struct scsi_cmnd *); |
187 | extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *); | ||
188 | extern void zfcp_reqlist_remove(struct zfcp_adapter *, unsigned long); | ||
189 | extern struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *, | ||
190 | unsigned long); | ||
191 | extern int zfcp_reqlist_isempty(struct zfcp_adapter *); | 187 | extern int zfcp_reqlist_isempty(struct zfcp_adapter *); |
192 | 188 | ||
193 | #endif /* ZFCP_EXT_H */ | 189 | #endif /* ZFCP_EXT_H */ |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 07094c3dc341..083308b1d3e2 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -4787,7 +4787,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req) | |||
4787 | retval = -EIO; | 4787 | retval = -EIO; |
4788 | del_timer(&fsf_req->timer); | 4788 | del_timer(&fsf_req->timer); |
4789 | spin_lock(&adapter->req_list_lock); | 4789 | spin_lock(&adapter->req_list_lock); |
4790 | zfcp_reqlist_remove(adapter, fsf_req->req_id); | 4790 | zfcp_reqlist_remove(adapter, fsf_req); |
4791 | spin_unlock(&adapter->req_list_lock); | 4791 | spin_unlock(&adapter->req_list_lock); |
4792 | /* undo changes in request queue made for this request */ | 4792 | /* undo changes in request queue made for this request */ |
4793 | zfcp_qdio_zero_sbals(req_queue->buffer, | 4793 | zfcp_qdio_zero_sbals(req_queue->buffer, |
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index e50e6ad4e6cb..cb08ca3cc0f9 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
@@ -283,7 +283,7 @@ zfcp_qdio_request_handler(struct ccw_device *ccw_device, | |||
283 | } | 283 | } |
284 | 284 | ||
285 | /** | 285 | /** |
286 | * zfcp_qdio_reqid_check - checks for valid reqids or unsolicited status | 286 | * zfcp_qdio_reqid_check - checks for valid reqids. |
287 | */ | 287 | */ |
288 | static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, | 288 | static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, |
289 | unsigned long req_id) | 289 | unsigned long req_id) |
@@ -294,14 +294,17 @@ static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, | |||
294 | debug_long_event(adapter->erp_dbf, 4, req_id); | 294 | debug_long_event(adapter->erp_dbf, 4, req_id); |
295 | 295 | ||
296 | spin_lock_irqsave(&adapter->req_list_lock, flags); | 296 | spin_lock_irqsave(&adapter->req_list_lock, flags); |
297 | fsf_req = zfcp_reqlist_ismember(adapter, req_id); | 297 | fsf_req = zfcp_reqlist_find(adapter, req_id); |
298 | 298 | ||
299 | if (!fsf_req) { | 299 | if (!fsf_req) |
300 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | 300 | /* |
301 | panic("error: unknown request id (%ld).\n", req_id); | 301 | * Unknown request means that we have potentially memory |
302 | } | 302 | * corruption and must stop the machine immediatly. |
303 | */ | ||
304 | panic("error: unknown request id (%ld) on adapter %s.\n", | ||
305 | req_id, zfcp_get_busid_by_adapter(adapter)); | ||
303 | 306 | ||
304 | zfcp_reqlist_remove(adapter, req_id); | 307 | zfcp_reqlist_remove(adapter, fsf_req); |
305 | atomic_dec(&adapter->reqs_active); | 308 | atomic_dec(&adapter->reqs_active); |
306 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); | 309 | spin_unlock_irqrestore(&adapter->req_list_lock, flags); |
307 | 310 | ||
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index e742b3de16ac..16e2d64658af 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -407,8 +407,8 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
407 | 407 | ||
408 | /* Check whether corresponding fsf_req is still pending */ | 408 | /* Check whether corresponding fsf_req is still pending */ |
409 | spin_lock(&adapter->req_list_lock); | 409 | spin_lock(&adapter->req_list_lock); |
410 | fsf_req = zfcp_reqlist_ismember(adapter, (unsigned long) | 410 | fsf_req = zfcp_reqlist_find(adapter, |
411 | scpnt->host_scribble); | 411 | (unsigned long) scpnt->host_scribble); |
412 | spin_unlock(&adapter->req_list_lock); | 412 | spin_unlock(&adapter->req_list_lock); |
413 | if (!fsf_req) { | 413 | if (!fsf_req) { |
414 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 414 | write_unlock_irqrestore(&adapter->abort_lock, flags); |