diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 20:34:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-22 20:34:15 -0400 |
commit | c70b5296e775cde46cfcb2d860ba160108a5ec7a (patch) | |
tree | 30419cb982acca44499236adcca65f2f87698c74 /drivers/s390/scsi/zfcp_cfdc.c | |
parent | 80c226fbef56576946c9655fcb2ab62e63404d12 (diff) | |
parent | 58ff4bd042adf8013c8f70fd03c2c0f8d022e387 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (84 commits)
[SCSI] be2iscsi: SGE Len == 64K
[SCSI] be2iscsi: Remove premature free of cid
[SCSI] be2iscsi: More time for FW
[SCSI] libsas: fix bug for vacant phy
[SCSI] sd: Fix overflow with big physical blocks
[SCSI] st: add MTWEOFI to write filemarks without flushing drive buffer
[SCSI] libsas: Don't issue commands to devices that have been hot-removed
[SCSI] megaraid_sas: Add Online Controller Reset to MegaRAID SAS drive
[SCSI] lpfc 8.3.17: Update lpfc driver version to 8.3.17
[SCSI] lpfc 8.3.17: Replace function reset methodology
[SCSI] lpfc 8.3.17: SCSI fixes
[SCSI] lpfc 8.3.17: BSG fixes
[SCSI] lpfc 8.3.17: SLI Additions and Fixes
[SCSI] lpfc 8.3.17: Code Cleanup and Locking fixes
[SCSI] zfcp: Remove scsi_cmnd->serial_number from debug traces
[SCSI] ipr: fix array error logging
[SCSI] aha152x: enable PCMCIA on 64bit
[SCSI] scsi_dh_alua: Handle all states correctly
[SCSI] cxgb4i: connection and ddp setting update
[SCSI] cxgb3i: fixed connection over vlan
...
Diffstat (limited to 'drivers/s390/scsi/zfcp_cfdc.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_cfdc.c | 186 |
1 files changed, 184 insertions, 2 deletions
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index 1838cda68ba8..d692e229ecba 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c | |||
@@ -2,9 +2,10 @@ | |||
2 | * zfcp device driver | 2 | * zfcp device driver |
3 | * | 3 | * |
4 | * Userspace interface for accessing the | 4 | * Userspace interface for accessing the |
5 | * Access Control Lists / Control File Data Channel | 5 | * Access Control Lists / Control File Data Channel; |
6 | * handling of response code and states for ports and LUNs. | ||
6 | * | 7 | * |
7 | * Copyright IBM Corporation 2008, 2009 | 8 | * Copyright IBM Corporation 2008, 2010 |
8 | */ | 9 | */ |
9 | 10 | ||
10 | #define KMSG_COMPONENT "zfcp" | 11 | #define KMSG_COMPONENT "zfcp" |
@@ -261,3 +262,184 @@ struct miscdevice zfcp_cfdc_misc = { | |||
261 | .name = "zfcp_cfdc", | 262 | .name = "zfcp_cfdc", |
262 | .fops = &zfcp_cfdc_fops, | 263 | .fops = &zfcp_cfdc_fops, |
263 | }; | 264 | }; |
265 | |||
266 | /** | ||
267 | * zfcp_cfdc_adapter_access_changed - Process change in adapter ACT | ||
268 | * @adapter: Adapter where the Access Control Table (ACT) changed | ||
269 | * | ||
270 | * After a change in the adapter ACT, check if access to any | ||
271 | * previously denied resources is now possible. | ||
272 | */ | ||
273 | void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *adapter) | ||
274 | { | ||
275 | unsigned long flags; | ||
276 | struct zfcp_port *port; | ||
277 | struct scsi_device *sdev; | ||
278 | struct zfcp_scsi_dev *zfcp_sdev; | ||
279 | int status; | ||
280 | |||
281 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) | ||
282 | return; | ||
283 | |||
284 | read_lock_irqsave(&adapter->port_list_lock, flags); | ||
285 | list_for_each_entry(port, &adapter->port_list, list) { | ||
286 | status = atomic_read(&port->status); | ||
287 | if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) || | ||
288 | (status & ZFCP_STATUS_COMMON_ACCESS_BOXED)) | ||
289 | zfcp_erp_port_reopen(port, | ||
290 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
291 | "cfaac_1", NULL); | ||
292 | } | ||
293 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | ||
294 | |||
295 | shost_for_each_device(sdev, port->adapter->scsi_host) { | ||
296 | zfcp_sdev = sdev_to_zfcp(sdev); | ||
297 | status = atomic_read(&zfcp_sdev->status); | ||
298 | if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) || | ||
299 | (status & ZFCP_STATUS_COMMON_ACCESS_BOXED)) | ||
300 | zfcp_erp_lun_reopen(sdev, | ||
301 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
302 | "cfaac_2", NULL); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table) | ||
307 | { | ||
308 | u16 subtable = table >> 16; | ||
309 | u16 rule = table & 0xffff; | ||
310 | const char *act_type[] = { "unknown", "OS", "WWPN", "DID", "LUN" }; | ||
311 | |||
312 | if (subtable && subtable < ARRAY_SIZE(act_type)) | ||
313 | dev_warn(&adapter->ccw_device->dev, | ||
314 | "Access denied according to ACT rule type %s, " | ||
315 | "rule %d\n", act_type[subtable], rule); | ||
316 | } | ||
317 | |||
318 | /** | ||
319 | * zfcp_cfdc_port_denied - Process "access denied" for port | ||
320 | * @port: The port where the acces has been denied | ||
321 | * @qual: The FSF status qualifier for the access denied FSF status | ||
322 | */ | ||
323 | void zfcp_cfdc_port_denied(struct zfcp_port *port, | ||
324 | union fsf_status_qual *qual) | ||
325 | { | ||
326 | dev_warn(&port->adapter->ccw_device->dev, | ||
327 | "Access denied to port 0x%016Lx\n", | ||
328 | (unsigned long long)port->wwpn); | ||
329 | |||
330 | zfcp_act_eval_err(port->adapter, qual->halfword[0]); | ||
331 | zfcp_act_eval_err(port->adapter, qual->halfword[1]); | ||
332 | zfcp_erp_set_port_status(port, | ||
333 | ZFCP_STATUS_COMMON_ERP_FAILED | | ||
334 | ZFCP_STATUS_COMMON_ACCESS_DENIED); | ||
335 | } | ||
336 | |||
337 | /** | ||
338 | * zfcp_cfdc_lun_denied - Process "access denied" for LUN | ||
339 | * @sdev: The SCSI device / LUN where the access has been denied | ||
340 | * @qual: The FSF status qualifier for the access denied FSF status | ||
341 | */ | ||
342 | void zfcp_cfdc_lun_denied(struct scsi_device *sdev, | ||
343 | union fsf_status_qual *qual) | ||
344 | { | ||
345 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
346 | |||
347 | dev_warn(&zfcp_sdev->port->adapter->ccw_device->dev, | ||
348 | "Access denied to LUN 0x%016Lx on port 0x%016Lx\n", | ||
349 | zfcp_scsi_dev_lun(sdev), | ||
350 | (unsigned long long)zfcp_sdev->port->wwpn); | ||
351 | zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->halfword[0]); | ||
352 | zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->halfword[1]); | ||
353 | zfcp_erp_set_lun_status(sdev, | ||
354 | ZFCP_STATUS_COMMON_ERP_FAILED | | ||
355 | ZFCP_STATUS_COMMON_ACCESS_DENIED); | ||
356 | |||
357 | atomic_clear_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status); | ||
358 | atomic_clear_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status); | ||
359 | } | ||
360 | |||
361 | /** | ||
362 | * zfcp_cfdc_lun_shrng_vltn - Evaluate LUN sharing violation status | ||
363 | * @sdev: The LUN / SCSI device where sharing violation occurred | ||
364 | * @qual: The FSF status qualifier from the LUN sharing violation | ||
365 | */ | ||
366 | void zfcp_cfdc_lun_shrng_vltn(struct scsi_device *sdev, | ||
367 | union fsf_status_qual *qual) | ||
368 | { | ||
369 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
370 | |||
371 | if (qual->word[0]) | ||
372 | dev_warn(&zfcp_sdev->port->adapter->ccw_device->dev, | ||
373 | "LUN 0x%Lx on port 0x%Lx is already in " | ||
374 | "use by CSS%d, MIF Image ID %x\n", | ||
375 | zfcp_scsi_dev_lun(sdev), | ||
376 | (unsigned long long)zfcp_sdev->port->wwpn, | ||
377 | qual->fsf_queue_designator.cssid, | ||
378 | qual->fsf_queue_designator.hla); | ||
379 | else | ||
380 | zfcp_act_eval_err(zfcp_sdev->port->adapter, qual->word[2]); | ||
381 | |||
382 | zfcp_erp_set_lun_status(sdev, | ||
383 | ZFCP_STATUS_COMMON_ERP_FAILED | | ||
384 | ZFCP_STATUS_COMMON_ACCESS_DENIED); | ||
385 | atomic_clear_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status); | ||
386 | atomic_clear_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status); | ||
387 | } | ||
388 | |||
389 | /** | ||
390 | * zfcp_cfdc_open_lun_eval - Eval access ctrl. status for successful "open lun" | ||
391 | * @sdev: The SCSI device / LUN where to evaluate the status | ||
392 | * @bottom: The qtcb bottom with the status from the "open lun" | ||
393 | * | ||
394 | * Returns: 0 if LUN is usable, -EACCES if the access control table | ||
395 | * reports an unsupported configuration. | ||
396 | */ | ||
397 | int zfcp_cfdc_open_lun_eval(struct scsi_device *sdev, | ||
398 | struct fsf_qtcb_bottom_support *bottom) | ||
399 | { | ||
400 | int shared, rw; | ||
401 | struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); | ||
402 | struct zfcp_adapter *adapter = zfcp_sdev->port->adapter; | ||
403 | |||
404 | if ((adapter->connection_features & FSF_FEATURE_NPIV_MODE) || | ||
405 | !(adapter->adapter_features & FSF_FEATURE_LUN_SHARING) || | ||
406 | zfcp_ccw_priv_sch(adapter)) | ||
407 | return 0; | ||
408 | |||
409 | shared = !(bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE); | ||
410 | rw = (bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER); | ||
411 | |||
412 | if (shared) | ||
413 | atomic_set_mask(ZFCP_STATUS_LUN_SHARED, &zfcp_sdev->status); | ||
414 | |||
415 | if (!rw) { | ||
416 | atomic_set_mask(ZFCP_STATUS_LUN_READONLY, &zfcp_sdev->status); | ||
417 | dev_info(&adapter->ccw_device->dev, "SCSI device at LUN " | ||
418 | "0x%016Lx on port 0x%016Lx opened read-only\n", | ||
419 | zfcp_scsi_dev_lun(sdev), | ||
420 | (unsigned long long)zfcp_sdev->port->wwpn); | ||
421 | } | ||
422 | |||
423 | if (!shared && !rw) { | ||
424 | dev_err(&adapter->ccw_device->dev, "Exclusive read-only access " | ||
425 | "not supported (LUN 0x%016Lx, port 0x%016Lx)\n", | ||
426 | zfcp_scsi_dev_lun(sdev), | ||
427 | (unsigned long long)zfcp_sdev->port->wwpn); | ||
428 | zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED); | ||
429 | zfcp_erp_lun_shutdown(sdev, 0, "fsouh_6", NULL); | ||
430 | return -EACCES; | ||
431 | } | ||
432 | |||
433 | if (shared && rw) { | ||
434 | dev_err(&adapter->ccw_device->dev, | ||
435 | "Shared read-write access not supported " | ||
436 | "(LUN 0x%016Lx, port 0x%016Lx)\n", | ||
437 | zfcp_scsi_dev_lun(sdev), | ||
438 | (unsigned long long)zfcp_sdev->port->wwpn); | ||
439 | zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED); | ||
440 | zfcp_erp_lun_shutdown(sdev, 0, "fsosh_8", NULL); | ||
441 | return -EACCES; | ||
442 | } | ||
443 | |||
444 | return 0; | ||
445 | } | ||