1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Transport specific attributes.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved.
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun #ifndef SCSI_TRANSPORT_H
8*4882a593Smuzhiyun #define SCSI_TRANSPORT_H
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/transport_class.h>
11*4882a593Smuzhiyun #include <linux/blkdev.h>
12*4882a593Smuzhiyun #include <linux/bug.h>
13*4882a593Smuzhiyun #include <scsi/scsi_host.h>
14*4882a593Smuzhiyun #include <scsi/scsi_device.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun struct scsi_transport_template {
17*4882a593Smuzhiyun /* the attribute containers */
18*4882a593Smuzhiyun struct transport_container host_attrs;
19*4882a593Smuzhiyun struct transport_container target_attrs;
20*4882a593Smuzhiyun struct transport_container device_attrs;
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun /*
23*4882a593Smuzhiyun * If set, called from sysfs and legacy procfs rescanning code.
24*4882a593Smuzhiyun */
25*4882a593Smuzhiyun int (*user_scan)(struct Scsi_Host *, uint, uint, u64);
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun /* The size of the specific transport attribute structure (a
28*4882a593Smuzhiyun * space of this size will be left at the end of the
29*4882a593Smuzhiyun * scsi_* structure */
30*4882a593Smuzhiyun int device_size;
31*4882a593Smuzhiyun int device_private_offset;
32*4882a593Smuzhiyun int target_size;
33*4882a593Smuzhiyun int target_private_offset;
34*4882a593Smuzhiyun int host_size;
35*4882a593Smuzhiyun /* no private offset for the host; there's an alternative mechanism */
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun /*
38*4882a593Smuzhiyun * True if the transport wants to use a host-based work-queue
39*4882a593Smuzhiyun */
40*4882a593Smuzhiyun unsigned int create_work_queue : 1;
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /*
43*4882a593Smuzhiyun * Allows a transport to override the default error handler.
44*4882a593Smuzhiyun */
45*4882a593Smuzhiyun void (* eh_strategy_handler)(struct Scsi_Host *);
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #define transport_class_to_shost(tc) \
49*4882a593Smuzhiyun dev_to_shost((tc)->parent)
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /* Private area maintenance. The driver requested allocations come
53*4882a593Smuzhiyun * directly after the transport class allocations (if any). The idea
54*4882a593Smuzhiyun * is that you *must* call these only once. The code assumes that the
55*4882a593Smuzhiyun * initial values are the ones the transport specific code requires */
56*4882a593Smuzhiyun static inline void
scsi_transport_reserve_target(struct scsi_transport_template * t,int space)57*4882a593Smuzhiyun scsi_transport_reserve_target(struct scsi_transport_template * t, int space)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun BUG_ON(t->target_private_offset != 0);
60*4882a593Smuzhiyun t->target_private_offset = ALIGN(t->target_size, sizeof(void *));
61*4882a593Smuzhiyun t->target_size = t->target_private_offset + space;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun static inline void
scsi_transport_reserve_device(struct scsi_transport_template * t,int space)64*4882a593Smuzhiyun scsi_transport_reserve_device(struct scsi_transport_template * t, int space)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun BUG_ON(t->device_private_offset != 0);
67*4882a593Smuzhiyun t->device_private_offset = ALIGN(t->device_size, sizeof(void *));
68*4882a593Smuzhiyun t->device_size = t->device_private_offset + space;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun static inline void *
scsi_transport_target_data(struct scsi_target * starget)71*4882a593Smuzhiyun scsi_transport_target_data(struct scsi_target *starget)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun struct Scsi_Host *shost = dev_to_shost(&starget->dev);
74*4882a593Smuzhiyun return (u8 *)starget->starget_data
75*4882a593Smuzhiyun + shost->transportt->target_private_offset;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun static inline void *
scsi_transport_device_data(struct scsi_device * sdev)79*4882a593Smuzhiyun scsi_transport_device_data(struct scsi_device *sdev)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun struct Scsi_Host *shost = sdev->host;
82*4882a593Smuzhiyun return (u8 *)sdev->sdev_data
83*4882a593Smuzhiyun + shost->transportt->device_private_offset;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q);
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun #endif /* SCSI_TRANSPORT_H */
89