diff options
Diffstat (limited to 'include/scsi/scsi_host.h')
| -rw-r--r-- | include/scsi/scsi_host.h | 84 |
1 files changed, 77 insertions, 7 deletions
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index d0a6a845f20..94844fc77b9 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -6,6 +6,7 @@ #include <linux/types.h> #include <linux/workqueue.h> #include <linux/mutex.h> +#include <linux/seq_file.h> #include <scsi/scsi.h> struct request_queue; @@ -14,6 +15,7 @@ struct completion; struct module; struct scsi_cmnd; struct scsi_device; +struct scsi_host_cmd_pool; struct scsi_target; struct Scsi_Host; struct scsi_host_cmd_pool; @@ -46,7 +48,7 @@ struct blk_queue_tags; enum { SCSI_QDEPTH_DEFAULT, /* default requested change, e.g. from sysfs */ SCSI_QDEPTH_QFULL, /* scsi-ml requested due to queue full */ - SCSI_QDEPTH_RAMP_UP, /* scsi-ml requested due to threshhold event */ + SCSI_QDEPTH_RAMP_UP, /* scsi-ml requested due to threshold event */ }; struct scsi_host_template { @@ -127,8 +129,7 @@ struct scsi_host_template { * * STATUS: REQUIRED */ - int (* queuecommand)(struct scsi_cmnd *, - void (*done)(struct scsi_cmnd *)); + int (* queuecommand)(struct Scsi_Host *, struct scsi_cmnd *); /* * The transfer functions are used to queue a scsi command to @@ -341,7 +342,8 @@ struct scsi_host_template { * * Status: OBSOLETE */ - int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int); + int (*show_info)(struct seq_file *, struct Scsi_Host *); + int (*write_info)(struct Scsi_Host *, char *, int); /* * This is an optional routine that allows the transport to become @@ -356,6 +358,19 @@ struct scsi_host_template { */ enum blk_eh_timer_return (*eh_timed_out)(struct scsi_cmnd *); + /* This is an optional routine that allows transport to initiate + * LLD adapter or firmware reset using sysfs attribute. + * + * Return values: 0 on success, -ve value on failure. + * + * Status: OPTIONAL + */ + + int (*host_reset)(struct Scsi_Host *shost, int reset_type); +#define SCSI_ADAPTER_RESET 1 +#define SCSI_FIRMWARE_RESET 2 + + /* * Name of proc directory */ @@ -363,7 +378,7 @@ struct scsi_host_template { /* * Used to store the procfs directory if a driver implements the - * proc_info method. + * show_info method. */ struct proc_dir_entry *proc_dir; @@ -461,6 +476,14 @@ struct scsi_host_template { */ unsigned ordered_tag:1; + /* True if the controller does not support WRITE SAME */ + unsigned no_write_same:1; + + /* + * True if asynchronous aborts are not supported + */ + unsigned no_async_abort:1; + /* * Countdown for host blocking with no commands outstanding. */ @@ -502,9 +525,34 @@ struct scsi_host_template { * scsi_netlink.h */ u64 vendor_id; + + /* + * Additional per-command data allocated for the driver. + */ + unsigned int cmd_size; + struct scsi_host_cmd_pool *cmd_pool; }; /* + * Temporary #define for host lock push down. Can be removed when all + * drivers have been updated to take advantage of unlocked + * queuecommand. + * + */ +#define DEF_SCSI_QCMD(func_name) \ + int func_name(struct Scsi_Host *shost, struct scsi_cmnd *cmd) \ + { \ + unsigned long irq_flags; \ + int rc; \ + spin_lock_irqsave(shost->host_lock, irq_flags); \ + scsi_cmd_get_serial(shost, cmd); \ + rc = func_name##_lck (cmd, cmd->scsi_done); \ + spin_unlock_irqrestore(shost->host_lock, irq_flags); \ + return rc; \ + } + + +/* * shost state: If you alter this, you also need to alter scsi_sysfs.c * (for the ascii descriptions) and the state model enforcer: * scsi_host_set_state() @@ -565,9 +613,12 @@ struct Scsi_Host { unsigned int host_eh_scheduled; /* EH scheduled without command */ unsigned int host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */ - int resetting; /* if set, it means that last_reset is a valid value */ + + /* next two fields are used to bound the time spent in error handling */ + int eh_deadline; unsigned long last_reset; + /* * These three parameters can be used to allow for wide scsi, * and for host adapters that support multiple busses @@ -638,6 +689,12 @@ struct Scsi_Host { /* Asynchronous scan in progress */ unsigned async_scan:1; + /* Don't resume host in EH */ + unsigned eh_noresume:1; + + /* The controller does not support WRITE SAME */ + unsigned no_write_same:1; + /* * Optional work queue to be utilized by the transport */ @@ -645,6 +702,11 @@ struct Scsi_Host { struct workqueue_struct *work_q; /* + * Task management function work queue + */ + struct workqueue_struct *tmf_work_q; + + /* * Host has rejected a command because it was busy. */ unsigned int host_blocked; @@ -752,6 +814,7 @@ extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *); extern void scsi_host_put(struct Scsi_Host *t); extern struct Scsi_Host *scsi_host_lookup(unsigned short); extern const char *scsi_host_state_name(enum scsi_host_state); +extern void scsi_cmd_get_serial(struct Scsi_Host *, struct scsi_cmnd *); extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *); @@ -772,7 +835,8 @@ static inline struct device *scsi_get_device(struct Scsi_Host *shost) **/ static inline int scsi_host_scan_allowed(struct Scsi_Host *shost) { - return shost->shost_state == SHOST_RUNNING; + return shost->shost_state == SHOST_RUNNING || + shost->shost_state == SHOST_RECOVERY; } extern void scsi_unblock_requests(struct Scsi_Host *); @@ -837,6 +901,9 @@ static inline unsigned int scsi_host_dif_capable(struct Scsi_Host *shost, unsign SHOST_DIF_TYPE2_PROTECTION, SHOST_DIF_TYPE3_PROTECTION }; + if (target_type >= ARRAY_SIZE(cap)) + return 0; + return shost->prot_capabilities & cap[target_type] ? target_type : 0; } @@ -848,6 +915,9 @@ static inline unsigned int scsi_host_dix_capable(struct Scsi_Host *shost, unsign SHOST_DIX_TYPE2_PROTECTION, SHOST_DIX_TYPE3_PROTECTION }; + if (target_type >= ARRAY_SIZE(cap)) + return 0; + return shost->prot_capabilities & cap[target_type]; #endif return 0; |
