]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | Subject: Add TGPS setting to scsi devices |
2 | From: Hannes Reinecke <hare@suse.de> | |
3 | ||
4 | Some multipath-capable storage arrays are capable of running | |
5 | in compatible mode, ie supporting both the original vendor-specific | |
6 | failover mode and the SPC-3 compliant ALUA mode. | |
7 | This patch stores the TGPS setting in the sdev so that we can directly | |
8 | match onto it and select the correct device handler automatically. | |
9 | And we can save code in the ALUA device handler. | |
10 | ||
11 | Signed-off-by: Hannes Reinecke <hare@suse.de> | |
12 | ||
13 | --- | |
14 | drivers/scsi/device_handler/scsi_dh.c | 9 ++- | |
15 | drivers/scsi/device_handler/scsi_dh_alua.c | 67 +++------------------------- | |
16 | drivers/scsi/device_handler/scsi_dh_emc.c | 8 +-- | |
17 | drivers/scsi/device_handler/scsi_dh_hp_sw.c | 10 ++-- | |
18 | drivers/scsi/device_handler/scsi_dh_rdac.c | 34 +++++++------- | |
19 | drivers/scsi/scsi_scan.c | 1 | |
20 | drivers/scsi/scsi_sysfs.c | 2 | |
21 | include/scsi/scsi_device.h | 4 + | |
22 | 8 files changed, 48 insertions(+), 87 deletions(-) | |
23 | ||
24 | --- a/drivers/scsi/device_handler/scsi_dh_alua.c | |
25 | +++ b/drivers/scsi/device_handler/scsi_dh_alua.c | |
26 | @@ -118,43 +118,6 @@ static struct request *get_alua_req(stru | |
27 | } | |
28 | ||
29 | /* | |
30 | - * submit_std_inquiry - Issue a standard INQUIRY command | |
31 | - * @sdev: sdev the command should be send to | |
32 | - */ | |
33 | -static int submit_std_inquiry(struct scsi_device *sdev, struct alua_dh_data *h) | |
34 | -{ | |
35 | - struct request *rq; | |
36 | - int err = SCSI_DH_RES_TEMP_UNAVAIL; | |
37 | - | |
38 | - rq = get_alua_req(sdev, h->inq, ALUA_INQUIRY_SIZE, READ); | |
39 | - if (!rq) | |
40 | - goto done; | |
41 | - | |
42 | - /* Prepare the command. */ | |
43 | - rq->cmd[0] = INQUIRY; | |
44 | - rq->cmd[1] = 0; | |
45 | - rq->cmd[2] = 0; | |
46 | - rq->cmd[4] = ALUA_INQUIRY_SIZE; | |
47 | - rq->cmd_len = COMMAND_SIZE(INQUIRY); | |
48 | - | |
49 | - rq->sense = h->sense; | |
50 | - memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE); | |
51 | - rq->sense_len = h->senselen = 0; | |
52 | - | |
53 | - err = blk_execute_rq(rq->q, NULL, rq, 1); | |
54 | - if (err == -EIO) { | |
55 | - sdev_printk(KERN_INFO, sdev, | |
56 | - "%s: std inquiry failed with %x\n", | |
57 | - ALUA_DH_NAME, rq->errors); | |
58 | - h->senselen = rq->sense_len; | |
59 | - err = SCSI_DH_IO; | |
60 | - } | |
61 | - blk_put_request(rq); | |
62 | -done: | |
63 | - return err; | |
64 | -} | |
65 | - | |
66 | -/* | |
67 | * submit_vpd_inquiry - Issue an INQUIRY VPD page 0x83 command | |
68 | * @sdev: sdev the command should be sent to | |
69 | */ | |
70 | @@ -281,23 +244,19 @@ done: | |
71 | } | |
72 | ||
73 | /* | |
74 | - * alua_std_inquiry - Evaluate standard INQUIRY command | |
75 | + * alua_check_tgps - Evaluate TGPS setting | |
76 | * @sdev: device to be checked | |
77 | * | |
78 | - * Just extract the TPGS setting to find out if ALUA | |
79 | + * Just examine the TPGS setting of the device to find out if ALUA | |
80 | * is supported. | |
81 | */ | |
82 | -static int alua_std_inquiry(struct scsi_device *sdev, struct alua_dh_data *h) | |
83 | +static int alua_check_tgps(struct scsi_device *sdev, struct alua_dh_data *h) | |
84 | { | |
85 | - int err; | |
86 | - | |
87 | - err = submit_std_inquiry(sdev, h); | |
88 | - | |
89 | - if (err != SCSI_DH_OK) | |
90 | - return err; | |
91 | + int err = SCSI_DH_OK; | |
92 | ||
93 | /* Check TPGS setting */ | |
94 | - h->tpgs = (h->inq[5] >> 4) & 0x3; | |
95 | + h->tpgs = sdev->tgps; | |
96 | + | |
97 | switch (h->tpgs) { | |
98 | case TPGS_MODE_EXPLICIT|TPGS_MODE_IMPLICIT: | |
99 | sdev_printk(KERN_INFO, sdev, | |
100 | @@ -609,7 +568,7 @@ static int alua_initialize(struct scsi_d | |
101 | { | |
102 | int err; | |
103 | ||
104 | - err = alua_std_inquiry(sdev, h); | |
105 | + err = alua_check_tgps(sdev, h); | |
106 | if (err != SCSI_DH_OK) | |
107 | goto out; | |
108 | ||
109 | @@ -674,16 +633,8 @@ static int alua_prep_fn(struct scsi_devi | |
110 | } | |
111 | ||
112 | static const struct scsi_dh_devlist alua_dev_list[] = { | |
113 | - {"HP", "MSA VOLUME" }, | |
114 | - {"HP", "HSV101" }, | |
115 | - {"HP", "HSV111" }, | |
116 | - {"HP", "HSV200" }, | |
117 | - {"HP", "HSV210" }, | |
118 | - {"HP", "HSV300" }, | |
119 | - {"IBM", "2107900" }, | |
120 | - {"IBM", "2145" }, | |
121 | - {"Pillar", "Axiom" }, | |
122 | - {NULL, NULL} | |
123 | + {"", "", 3 }, | |
124 | + {NULL, NULL, 0} | |
125 | }; | |
126 | ||
127 | static int alua_bus_attach(struct scsi_device *sdev); | |
128 | --- a/drivers/scsi/device_handler/scsi_dh.c | |
129 | +++ b/drivers/scsi/device_handler/scsi_dh.c | |
130 | @@ -28,6 +28,7 @@ struct scsi_dh_devinfo_list { | |
131 | struct list_head node; | |
132 | char vendor[9]; | |
133 | char model[17]; | |
134 | + char tgps; | |
135 | struct scsi_device_handler *handler; | |
136 | }; | |
137 | ||
138 | @@ -60,7 +61,8 @@ scsi_dh_cache_lookup(struct scsi_device | |
139 | spin_lock(&list_lock); | |
140 | list_for_each_entry(tmp, &scsi_dh_dev_list, node) { | |
141 | if (!strncmp(sdev->vendor, tmp->vendor, strlen(tmp->vendor)) && | |
142 | - !strncmp(sdev->model, tmp->model, strlen(tmp->model))) { | |
143 | + !strncmp(sdev->model, tmp->model, strlen(tmp->model)) && | |
144 | + (!tmp->tgps || (sdev->tgps & tmp->tgps) != 0)) { | |
145 | found_dh = tmp->handler; | |
146 | break; | |
147 | } | |
148 | @@ -79,7 +81,9 @@ static int scsi_dh_handler_lookup(struct | |
149 | if (!strncmp(sdev->vendor, scsi_dh->devlist[i].vendor, | |
150 | strlen(scsi_dh->devlist[i].vendor)) && | |
151 | !strncmp(sdev->model, scsi_dh->devlist[i].model, | |
152 | - strlen(scsi_dh->devlist[i].model))) { | |
153 | + strlen(scsi_dh->devlist[i].model)) && | |
154 | + (!scsi_dh->devlist[i].tgps || | |
155 | + (sdev->tgps & scsi_dh->devlist[i].tgps) != 0)) { | |
156 | found = 1; | |
157 | break; | |
158 | } | |
159 | @@ -128,6 +132,7 @@ device_handler_match(struct scsi_device_ | |
160 | strncpy(tmp->model, sdev->model, 16); | |
161 | tmp->vendor[8] = '\0'; | |
162 | tmp->model[16] = '\0'; | |
163 | + tmp->tgps = sdev->tgps; | |
164 | tmp->handler = found_dh; | |
165 | spin_lock(&list_lock); | |
166 | list_add(&tmp->node, &scsi_dh_dev_list); | |
167 | --- a/drivers/scsi/device_handler/scsi_dh_emc.c | |
168 | +++ b/drivers/scsi/device_handler/scsi_dh_emc.c | |
169 | @@ -563,10 +563,10 @@ done: | |
170 | } | |
171 | ||
172 | static const struct scsi_dh_devlist clariion_dev_list[] = { | |
173 | - {"DGC", "RAID"}, | |
174 | - {"DGC", "DISK"}, | |
175 | - {"DGC", "VRAID"}, | |
176 | - {NULL, NULL}, | |
177 | + {"DGC", "RAID", 0}, | |
178 | + {"DGC", "DISK", 0}, | |
179 | + {"DGC", "VRAID", 0}, | |
180 | + {NULL, NULL, 0}, | |
181 | }; | |
182 | ||
183 | static int clariion_bus_attach(struct scsi_device *sdev); | |
184 | --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c | |
185 | +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c | |
186 | @@ -283,11 +283,11 @@ static int hp_sw_activate(struct scsi_de | |
187 | } | |
188 | ||
189 | static const struct scsi_dh_devlist hp_sw_dh_data_list[] = { | |
190 | - {"COMPAQ", "MSA1000 VOLUME"}, | |
191 | - {"COMPAQ", "HSV110"}, | |
192 | - {"HP", "HSV100"}, | |
193 | - {"DEC", "HSG80"}, | |
194 | - {NULL, NULL}, | |
195 | + {"COMPAQ", "MSA1000 VOLUME", 0}, | |
196 | + {"COMPAQ", "HSV110", 0}, | |
197 | + {"HP", "HSV100", 0}, | |
198 | + {"DEC", "HSG80", 0}, | |
199 | + {NULL, NULL, 0}, | |
200 | }; | |
201 | ||
202 | static int hp_sw_bus_attach(struct scsi_device *sdev); | |
203 | --- a/drivers/scsi/device_handler/scsi_dh_rdac.c | |
204 | +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c | |
205 | @@ -583,23 +583,23 @@ static int rdac_check_sense(struct scsi_ | |
206 | } | |
207 | ||
208 | static const struct scsi_dh_devlist rdac_dev_list[] = { | |
209 | - {"IBM", "1722"}, | |
210 | - {"IBM", "1724"}, | |
211 | - {"IBM", "1726"}, | |
212 | - {"IBM", "1742"}, | |
213 | - {"IBM", "1814"}, | |
214 | - {"IBM", "1815"}, | |
215 | - {"IBM", "1818"}, | |
216 | - {"IBM", "3526"}, | |
217 | - {"SGI", "TP9400"}, | |
218 | - {"SGI", "TP9500"}, | |
219 | - {"SGI", "IS"}, | |
220 | - {"STK", "OPENstorage D280"}, | |
221 | - {"SUN", "CSM200_R"}, | |
222 | - {"SUN", "LCSM100_F"}, | |
223 | - {"DELL", "MD3000"}, | |
224 | - {"DELL", "MD3000i"}, | |
225 | - {NULL, NULL}, | |
226 | + {"IBM", "1722", 0}, | |
227 | + {"IBM", "1724", 0}, | |
228 | + {"IBM", "1726", 0}, | |
229 | + {"IBM", "1742", 0}, | |
230 | + {"IBM", "1814", 0}, | |
231 | + {"IBM", "1815", 0}, | |
232 | + {"IBM", "1818", 0}, | |
233 | + {"IBM", "3526", 0}, | |
234 | + {"SGI", "TP9400", 0}, | |
235 | + {"SGI", "TP9500", 0}, | |
236 | + {"SGI", "IS", 0}, | |
237 | + {"STK", "OPENstorage D280", 0}, | |
238 | + {"SUN", "CSM200_R", 0}, | |
239 | + {"SUN", "LCSM100_F", 0}, | |
240 | + {"DELL", "MD3000", 0}, | |
241 | + {"DELL", "MD3000i", 0}, | |
242 | + {NULL, NULL, 0}, | |
243 | }; | |
244 | ||
245 | static int rdac_bus_attach(struct scsi_device *sdev); | |
246 | --- a/drivers/scsi/scsi_scan.c | |
247 | +++ b/drivers/scsi/scsi_scan.c | |
248 | @@ -821,6 +821,7 @@ static int scsi_add_lun(struct scsi_devi | |
249 | sdev->inq_periph_qual = (inq_result[0] >> 5) & 7; | |
250 | sdev->lockable = sdev->removable; | |
251 | sdev->soft_reset = (inq_result[7] & 1) && ((inq_result[3] & 7) == 2); | |
252 | + sdev->tgps = (inq_result[5] >> 4) & 3; | |
253 | ||
254 | if (sdev->scsi_level >= SCSI_3 || | |
255 | (sdev->inquiry_len > 56 && inq_result[56] & 0x04)) | |
256 | --- a/drivers/scsi/scsi_sysfs.c | |
257 | +++ b/drivers/scsi/scsi_sysfs.c | |
258 | @@ -543,6 +543,7 @@ sdev_rd_attr (scsi_level, "%d\n"); | |
259 | sdev_rd_attr (vendor, "%.8s\n"); | |
260 | sdev_rd_attr (model, "%.16s\n"); | |
261 | sdev_rd_attr (rev, "%.4s\n"); | |
262 | +sdev_rd_attr (tgps, "%d\n"); | |
263 | ||
264 | /* | |
265 | * TODO: can we make these symlinks to the block layer ones? | |
266 | @@ -728,6 +729,7 @@ static struct attribute *scsi_sdev_attrs | |
267 | &dev_attr_vendor.attr, | |
268 | &dev_attr_model.attr, | |
269 | &dev_attr_rev.attr, | |
270 | + &dev_attr_tgps.attr, | |
271 | &dev_attr_rescan.attr, | |
272 | &dev_attr_delete.attr, | |
273 | &dev_attr_state.attr, | |
274 | --- a/include/scsi/scsi_device.h | |
275 | +++ b/include/scsi/scsi_device.h | |
276 | @@ -96,7 +96,8 @@ struct scsi_device { | |
277 | void *hostdata; /* available to low-level driver */ | |
278 | char type; | |
279 | char scsi_level; | |
280 | - char inq_periph_qual; /* PQ from INQUIRY data */ | |
281 | + char inq_periph_qual; /* PQ from INQUIRY data */ | |
282 | + char tgps; /* Target port group support */ | |
283 | unsigned char inquiry_len; /* valid bytes in 'inquiry' */ | |
284 | unsigned char * inquiry; /* INQUIRY response data */ | |
285 | const char * vendor; /* [back_compat] point into 'inquiry' ... */ | |
286 | @@ -174,6 +175,7 @@ struct scsi_device { | |
287 | struct scsi_dh_devlist { | |
288 | char *vendor; | |
289 | char *model; | |
290 | + char tgps; | |
291 | }; | |
292 | ||
293 | struct scsi_device_handler { |