PageRenderTime 46ms CodeModel.GetById 17ms app.highlight 22ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/scsi/device_handler/scsi_dh_emc.c

https://bitbucket.org/abioy/linux
C | 737 lines | 515 code | 95 blank | 127 comment | 112 complexity | 74fcfdc77b13168553d479822163d23b MD5 | raw file
Possible License(s): CC-BY-SA-3.0, GPL-2.0, LGPL-2.0, AGPL-1.0
  1/*
  2 * Target driver for EMC CLARiiON AX/CX-series hardware.
  3 * Based on code from Lars Marowsky-Bree <lmb@suse.de>
  4 * and Ed Goggin <egoggin@emc.com>.
  5 *
  6 * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
  7 * Copyright (C) 2006 Mike Christie
  8 *
  9 * This program is free software; you can redistribute it and/or modify
 10 * it under the terms of the GNU General Public License as published by
 11 * the Free Software Foundation; either version 2, or (at your option)
 12 * any later version.
 13 *
 14 * This program is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17 * GNU General Public License for more details.
 18 *
 19 * You should have received a copy of the GNU General Public License
 20 * along with this program; see the file COPYING.  If not, write to
 21 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 22 */
 23#include <linux/slab.h>
 24#include <scsi/scsi.h>
 25#include <scsi/scsi_eh.h>
 26#include <scsi/scsi_dh.h>
 27#include <scsi/scsi_device.h>
 28
 29#define CLARIION_NAME			"emc"
 30
 31#define CLARIION_TRESPASS_PAGE		0x22
 32#define CLARIION_BUFFER_SIZE		0xFC
 33#define CLARIION_TIMEOUT		(60 * HZ)
 34#define CLARIION_RETRIES		3
 35#define CLARIION_UNBOUND_LU		-1
 36#define CLARIION_SP_A			0
 37#define CLARIION_SP_B			1
 38
 39/* Flags */
 40#define CLARIION_SHORT_TRESPASS		1
 41#define CLARIION_HONOR_RESERVATIONS	2
 42
 43/* LUN states */
 44#define CLARIION_LUN_UNINITIALIZED	-1
 45#define CLARIION_LUN_UNBOUND		0
 46#define CLARIION_LUN_BOUND		1
 47#define CLARIION_LUN_OWNED		2
 48
 49static unsigned char long_trespass[] = {
 50	0, 0, 0, 0, 0, 0, 0, 0,
 51	CLARIION_TRESPASS_PAGE,	/* Page code */
 52	0x09,			/* Page length - 2 */
 53	0x01,			/* Trespass code */
 54	0xff, 0xff,		/* Trespass target */
 55	0, 0, 0, 0, 0, 0	/* Reserved bytes / unknown */
 56};
 57
 58static unsigned char short_trespass[] = {
 59	0, 0, 0, 0,
 60	CLARIION_TRESPASS_PAGE,	/* Page code */
 61	0x02,			/* Page length - 2 */
 62	0x01,			/* Trespass code */
 63	0xff,			/* Trespass target */
 64};
 65
 66static const char * lun_state[] =
 67{
 68    "not bound",
 69    "bound",
 70    "owned",
 71};
 72
 73struct clariion_dh_data {
 74	/*
 75	 * Flags:
 76	 *  CLARIION_SHORT_TRESPASS
 77	 * Use short trespass command (FC-series) or the long version
 78	 * (default for AX/CX CLARiiON arrays).
 79	 *
 80	 *  CLARIION_HONOR_RESERVATIONS
 81	 * Whether or not (default) to honor SCSI reservations when
 82	 * initiating a switch-over.
 83	 */
 84	unsigned flags;
 85	/*
 86	 * I/O buffer for both MODE_SELECT and INQUIRY commands.
 87	 */
 88	unsigned char buffer[CLARIION_BUFFER_SIZE];
 89	/*
 90	 * SCSI sense buffer for commands -- assumes serial issuance
 91	 * and completion sequence of all commands for same multipath.
 92	 */
 93	unsigned char sense[SCSI_SENSE_BUFFERSIZE];
 94	unsigned int senselen;
 95	/*
 96	 * LUN state
 97	 */
 98	int lun_state;
 99	/*
100	 * SP Port number
101	 */
102	int port;
103	/*
104	 * which SP (A=0,B=1,UNBOUND=-1) is the default SP for this
105	 * path's mapped LUN
106	 */
107	int default_sp;
108	/*
109	 * which SP (A=0,B=1,UNBOUND=-1) is the active SP for this
110	 * path's mapped LUN
111	 */
112	int current_sp;
113};
114
115static inline struct clariion_dh_data
116			*get_clariion_data(struct scsi_device *sdev)
117{
118	struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
119	BUG_ON(scsi_dh_data == NULL);
120	return ((struct clariion_dh_data *) scsi_dh_data->buf);
121}
122
123/*
124 * Parse MODE_SELECT cmd reply.
125 */
126static int trespass_endio(struct scsi_device *sdev, char *sense)
127{
128	int err = SCSI_DH_IO;
129	struct scsi_sense_hdr sshdr;
130
131	if (!scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) {
132		sdev_printk(KERN_ERR, sdev, "%s: Found valid sense data 0x%2x, "
133			    "0x%2x, 0x%2x while sending CLARiiON trespass "
134			    "command.\n", CLARIION_NAME, sshdr.sense_key,
135			    sshdr.asc, sshdr.ascq);
136
137		if ((sshdr.sense_key == 0x05) && (sshdr.asc == 0x04) &&
138		     (sshdr.ascq == 0x00)) {
139			/*
140			 * Array based copy in progress -- do not send
141			 * mode_select or copy will be aborted mid-stream.
142			 */
143			sdev_printk(KERN_INFO, sdev, "%s: Array Based Copy in "
144				    "progress while sending CLARiiON trespass "
145				    "command.\n", CLARIION_NAME);
146			err = SCSI_DH_DEV_TEMP_BUSY;
147		} else if ((sshdr.sense_key == 0x02) && (sshdr.asc == 0x04) &&
148			    (sshdr.ascq == 0x03)) {
149			/*
150			 * LUN Not Ready - Manual Intervention Required
151			 * indicates in-progress ucode upgrade (NDU).
152			 */
153			sdev_printk(KERN_INFO, sdev, "%s: Detected in-progress "
154				    "ucode upgrade NDU operation while sending "
155				    "CLARiiON trespass command.\n", CLARIION_NAME);
156			err = SCSI_DH_DEV_TEMP_BUSY;
157		} else
158			err = SCSI_DH_DEV_FAILED;
159	} else {
160		sdev_printk(KERN_INFO, sdev,
161			    "%s: failed to send MODE SELECT, no sense available\n",
162			    CLARIION_NAME);
163	}
164	return err;
165}
166
167static int parse_sp_info_reply(struct scsi_device *sdev,
168			       struct clariion_dh_data *csdev)
169{
170	int err = SCSI_DH_OK;
171
172	/* check for in-progress ucode upgrade (NDU) */
173	if (csdev->buffer[48] != 0) {
174		sdev_printk(KERN_NOTICE, sdev, "%s: Detected in-progress "
175			    "ucode upgrade NDU operation while finding "
176			    "current active SP.", CLARIION_NAME);
177		err = SCSI_DH_DEV_TEMP_BUSY;
178		goto out;
179	}
180	if (csdev->buffer[4] > 2) {
181		/* Invalid buffer format */
182		sdev_printk(KERN_NOTICE, sdev,
183			    "%s: invalid VPD page 0xC0 format\n",
184			    CLARIION_NAME);
185		err = SCSI_DH_NOSYS;
186		goto out;
187	}
188	switch (csdev->buffer[28] & 0x0f) {
189	case 6:
190		sdev_printk(KERN_NOTICE, sdev,
191			    "%s: ALUA failover mode detected\n",
192			    CLARIION_NAME);
193		break;
194	case 4:
195		/* Linux failover */
196		break;
197	default:
198		sdev_printk(KERN_WARNING, sdev,
199			    "%s: Invalid failover mode %d\n",
200			    CLARIION_NAME, csdev->buffer[28] & 0x0f);
201		err = SCSI_DH_NOSYS;
202		goto out;
203	}
204
205	csdev->default_sp = csdev->buffer[5];
206	csdev->lun_state = csdev->buffer[4];
207	csdev->current_sp = csdev->buffer[8];
208	csdev->port = csdev->buffer[7];
209
210out:
211	return err;
212}
213
214#define emc_default_str "FC (Legacy)"
215
216static char * parse_sp_model(struct scsi_device *sdev, unsigned char *buffer)
217{
218	unsigned char len = buffer[4] + 5;
219	char *sp_model = NULL;
220	unsigned char sp_len, serial_len;
221
222	if (len < 160) {
223		sdev_printk(KERN_WARNING, sdev,
224			    "%s: Invalid information section length %d\n",
225			    CLARIION_NAME, len);
226		/* Check for old FC arrays */
227		if (!strncmp(buffer + 8, "DGC", 3)) {
228			/* Old FC array, not supporting extended information */
229			sp_model = emc_default_str;
230		}
231		goto out;
232	}
233
234	/*
235	 * Parse extended information for SP model number
236	 */
237	serial_len = buffer[160];
238	if (serial_len == 0 || serial_len + 161 > len) {
239		sdev_printk(KERN_WARNING, sdev,
240			    "%s: Invalid array serial number length %d\n",
241			    CLARIION_NAME, serial_len);
242		goto out;
243	}
244	sp_len = buffer[99];
245	if (sp_len == 0 || serial_len + sp_len + 161 > len) {
246		sdev_printk(KERN_WARNING, sdev,
247			    "%s: Invalid model number length %d\n",
248			    CLARIION_NAME, sp_len);
249		goto out;
250	}
251	sp_model = &buffer[serial_len + 161];
252	/* Strip whitespace at the end */
253	while (sp_len > 1 && sp_model[sp_len - 1] == ' ')
254		sp_len--;
255
256	sp_model[sp_len] = '\0';
257
258out:
259	return sp_model;
260}
261
262/*
263 * Get block request for REQ_BLOCK_PC command issued to path.  Currently
264 * limited to MODE_SELECT (trespass) and INQUIRY (VPD page 0xC0) commands.
265 *
266 * Uses data and sense buffers in hardware handler context structure and
267 * assumes serial servicing of commands, both issuance and completion.
268 */
269static struct request *get_req(struct scsi_device *sdev, int cmd,
270				unsigned char *buffer)
271{
272	struct request *rq;
273	int len = 0;
274
275	rq = blk_get_request(sdev->request_queue,
276			(cmd != INQUIRY) ? WRITE : READ, GFP_NOIO);
277	if (!rq) {
278		sdev_printk(KERN_INFO, sdev, "get_req: blk_get_request failed");
279		return NULL;
280	}
281
282	rq->cmd_len = COMMAND_SIZE(cmd);
283	rq->cmd[0] = cmd;
284
285	switch (cmd) {
286	case MODE_SELECT:
287		len = sizeof(short_trespass);
288		rq->cmd_flags |= REQ_RW;
289		rq->cmd[1] = 0x10;
290		rq->cmd[4] = len;
291		break;
292	case MODE_SELECT_10:
293		len = sizeof(long_trespass);
294		rq->cmd_flags |= REQ_RW;
295		rq->cmd[1] = 0x10;
296		rq->cmd[8] = len;
297		break;
298	case INQUIRY:
299		len = CLARIION_BUFFER_SIZE;
300		rq->cmd[4] = len;
301		memset(buffer, 0, len);
302		break;
303	default:
304		BUG_ON(1);
305		break;
306	}
307
308	rq->cmd_type = REQ_TYPE_BLOCK_PC;
309	rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
310			 REQ_FAILFAST_DRIVER;
311	rq->timeout = CLARIION_TIMEOUT;
312	rq->retries = CLARIION_RETRIES;
313
314	if (blk_rq_map_kern(rq->q, rq, buffer, len, GFP_NOIO)) {
315		blk_put_request(rq);
316		return NULL;
317	}
318
319	return rq;
320}
321
322static int send_inquiry_cmd(struct scsi_device *sdev, int page,
323			    struct clariion_dh_data *csdev)
324{
325	struct request *rq = get_req(sdev, INQUIRY, csdev->buffer);
326	int err;
327
328	if (!rq)
329		return SCSI_DH_RES_TEMP_UNAVAIL;
330
331	rq->sense = csdev->sense;
332	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
333	rq->sense_len = csdev->senselen = 0;
334
335	rq->cmd[0] = INQUIRY;
336	if (page != 0) {
337		rq->cmd[1] = 1;
338		rq->cmd[2] = page;
339	}
340	err = blk_execute_rq(sdev->request_queue, NULL, rq, 1);
341	if (err == -EIO) {
342		sdev_printk(KERN_INFO, sdev,
343			    "%s: failed to send %s INQUIRY: %x\n",
344			    CLARIION_NAME, page?"EVPD":"standard",
345			    rq->errors);
346		csdev->senselen = rq->sense_len;
347		err = SCSI_DH_IO;
348	}
349
350	blk_put_request(rq);
351
352	return err;
353}
354
355static int send_trespass_cmd(struct scsi_device *sdev,
356			    struct clariion_dh_data *csdev)
357{
358	struct request *rq;
359	unsigned char *page22;
360	int err, len, cmd;
361
362	if (csdev->flags & CLARIION_SHORT_TRESPASS) {
363		page22 = short_trespass;
364		if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS))
365			/* Set Honor Reservations bit */
366			page22[6] |= 0x80;
367		len = sizeof(short_trespass);
368		cmd = MODE_SELECT;
369	} else {
370		page22 = long_trespass;
371		if (!(csdev->flags & CLARIION_HONOR_RESERVATIONS))
372			/* Set Honor Reservations bit */
373			page22[10] |= 0x80;
374		len = sizeof(long_trespass);
375		cmd = MODE_SELECT_10;
376	}
377	BUG_ON((len > CLARIION_BUFFER_SIZE));
378	memcpy(csdev->buffer, page22, len);
379
380	rq = get_req(sdev, cmd, csdev->buffer);
381	if (!rq)
382		return SCSI_DH_RES_TEMP_UNAVAIL;
383
384	rq->sense = csdev->sense;
385	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
386	rq->sense_len = csdev->senselen = 0;
387
388	err = blk_execute_rq(sdev->request_queue, NULL, rq, 1);
389	if (err == -EIO) {
390		if (rq->sense_len) {
391			err = trespass_endio(sdev, csdev->sense);
392		} else {
393			sdev_printk(KERN_INFO, sdev,
394				    "%s: failed to send MODE SELECT: %x\n",
395				    CLARIION_NAME, rq->errors);
396		}
397	}
398
399	blk_put_request(rq);
400
401	return err;
402}
403
404static int clariion_check_sense(struct scsi_device *sdev,
405				struct scsi_sense_hdr *sense_hdr)
406{
407	switch (sense_hdr->sense_key) {
408	case NOT_READY:
409		if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x03)
410			/*
411			 * LUN Not Ready - Manual Intervention Required
412			 * indicates this is a passive path.
413			 *
414			 * FIXME: However, if this is seen and EVPD C0
415			 * indicates that this is due to a NDU in
416			 * progress, we should set FAIL_PATH too.
417			 * This indicates we might have to do a SCSI
418			 * inquiry in the end_io path. Ugh.
419			 *
420			 * Can return FAILED only when we want the error
421			 * recovery process to kick in.
422			 */
423			return SUCCESS;
424		break;
425	case ILLEGAL_REQUEST:
426		if (sense_hdr->asc == 0x25 && sense_hdr->ascq == 0x01)
427			/*
428			 * An array based copy is in progress. Do not
429			 * fail the path, do not bypass to another PG,
430			 * do not retry. Fail the IO immediately.
431			 * (Actually this is the same conclusion as in
432			 * the default handler, but lets make sure.)
433			 *
434			 * Can return FAILED only when we want the error
435			 * recovery process to kick in.
436			 */
437			return SUCCESS;
438		break;
439	case UNIT_ATTENTION:
440		if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00)
441			/*
442			 * Unit Attention Code. This is the first IO
443			 * to the new path, so just retry.
444			 */
445			return ADD_TO_MLQUEUE;
446		break;
447	}
448
449	return SCSI_RETURN_NOT_HANDLED;
450}
451
452static int clariion_prep_fn(struct scsi_device *sdev, struct request *req)
453{
454	struct clariion_dh_data *h = get_clariion_data(sdev);
455	int ret = BLKPREP_OK;
456
457	if (h->lun_state != CLARIION_LUN_OWNED) {
458		ret = BLKPREP_KILL;
459		req->cmd_flags |= REQ_QUIET;
460	}
461	return ret;
462
463}
464
465static int clariion_std_inquiry(struct scsi_device *sdev,
466				struct clariion_dh_data *csdev)
467{
468	int err;
469	char *sp_model;
470
471	err = send_inquiry_cmd(sdev, 0, csdev);
472	if (err != SCSI_DH_OK && csdev->senselen) {
473		struct scsi_sense_hdr sshdr;
474
475		if (scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE,
476					 &sshdr)) {
477			sdev_printk(KERN_ERR, sdev, "%s: INQUIRY sense code "
478				    "%02x/%02x/%02x\n", CLARIION_NAME,
479				    sshdr.sense_key, sshdr.asc, sshdr.ascq);
480		}
481		err = SCSI_DH_IO;
482		goto out;
483	}
484
485	sp_model = parse_sp_model(sdev, csdev->buffer);
486	if (!sp_model) {
487		err = SCSI_DH_DEV_UNSUPP;
488		goto out;
489	}
490
491	/*
492	 * FC Series arrays do not support long trespass
493	 */
494	if (!strlen(sp_model) || !strncmp(sp_model, "FC",2))
495		csdev->flags |= CLARIION_SHORT_TRESPASS;
496
497	sdev_printk(KERN_INFO, sdev,
498		    "%s: detected Clariion %s, flags %x\n",
499		    CLARIION_NAME, sp_model, csdev->flags);
500out:
501	return err;
502}
503
504static int clariion_send_inquiry(struct scsi_device *sdev,
505				 struct clariion_dh_data *csdev)
506{
507	int err, retry = CLARIION_RETRIES;
508
509retry:
510	err = send_inquiry_cmd(sdev, 0xC0, csdev);
511	if (err != SCSI_DH_OK && csdev->senselen) {
512		struct scsi_sense_hdr sshdr;
513
514		err = scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE,
515					   &sshdr);
516		if (!err)
517			return SCSI_DH_IO;
518
519		err = clariion_check_sense(sdev, &sshdr);
520		if (retry > 0 && err == ADD_TO_MLQUEUE) {
521			retry--;
522			goto retry;
523		}
524		sdev_printk(KERN_ERR, sdev, "%s: INQUIRY sense code "
525			    "%02x/%02x/%02x\n", CLARIION_NAME,
526			      sshdr.sense_key, sshdr.asc, sshdr.ascq);
527		err = SCSI_DH_IO;
528	} else {
529		err = parse_sp_info_reply(sdev, csdev);
530	}
531	return err;
532}
533
534static int clariion_activate(struct scsi_device *sdev,
535				activate_complete fn, void *data)
536{
537	struct clariion_dh_data *csdev = get_clariion_data(sdev);
538	int result;
539
540	result = clariion_send_inquiry(sdev, csdev);
541	if (result != SCSI_DH_OK)
542		goto done;
543
544	if (csdev->lun_state == CLARIION_LUN_OWNED)
545		goto done;
546
547	result = send_trespass_cmd(sdev, csdev);
548	if (result != SCSI_DH_OK)
549		goto done;
550	sdev_printk(KERN_INFO, sdev,"%s: %s trespass command sent\n",
551		    CLARIION_NAME,
552		    csdev->flags&CLARIION_SHORT_TRESPASS?"short":"long" );
553
554	/* Update status */
555	result = clariion_send_inquiry(sdev, csdev);
556	if (result != SCSI_DH_OK)
557		goto done;
558
559done:
560	sdev_printk(KERN_INFO, sdev,
561		    "%s: at SP %c Port %d (%s, default SP %c)\n",
562		    CLARIION_NAME, csdev->current_sp + 'A',
563		    csdev->port, lun_state[csdev->lun_state],
564		    csdev->default_sp + 'A');
565
566	if (fn)
567		fn(data, result);
568	return 0;
569}
570/*
571 * params - parameters in the following format
572 *      "no_of_params\0param1\0param2\0param3\0...\0"
573 *      for example, string for 2 parameters with value 10 and 21
574 *      is specified as "2\010\021\0".
575 */
576static int clariion_set_params(struct scsi_device *sdev, const char *params)
577{
578	struct clariion_dh_data *csdev = get_clariion_data(sdev);
579	unsigned int hr = 0, st = 0, argc;
580	const char *p = params;
581	int result = SCSI_DH_OK;
582
583	if ((sscanf(params, "%u", &argc) != 1) || (argc != 2))
584		return -EINVAL;
585
586	while (*p++)
587		;
588	if ((sscanf(p, "%u", &st) != 1) || (st > 1))
589		return -EINVAL;
590
591	while (*p++)
592		;
593	if ((sscanf(p, "%u", &hr) != 1) || (hr > 1))
594		return -EINVAL;
595
596	if (st)
597		csdev->flags |= CLARIION_SHORT_TRESPASS;
598	else
599		csdev->flags &= ~CLARIION_SHORT_TRESPASS;
600
601	if (hr)
602		csdev->flags |= CLARIION_HONOR_RESERVATIONS;
603	else
604		csdev->flags &= ~CLARIION_HONOR_RESERVATIONS;
605
606	/*
607	 * If this path is owned, we have to send a trespass command
608	 * with the new parameters. If not, simply return. Next trespass
609	 * command would use the parameters.
610	 */
611	if (csdev->lun_state != CLARIION_LUN_OWNED)
612		goto done;
613
614	csdev->lun_state = CLARIION_LUN_UNINITIALIZED;
615	result = send_trespass_cmd(sdev, csdev);
616	if (result != SCSI_DH_OK)
617		goto done;
618
619	/* Update status */
620	result = clariion_send_inquiry(sdev, csdev);
621
622done:
623	return result;
624}
625
626static const struct scsi_dh_devlist clariion_dev_list[] = {
627	{"DGC", "RAID"},
628	{"DGC", "DISK"},
629	{"DGC", "VRAID"},
630	{NULL, NULL},
631};
632
633static int clariion_bus_attach(struct scsi_device *sdev);
634static void clariion_bus_detach(struct scsi_device *sdev);
635
636static struct scsi_device_handler clariion_dh = {
637	.name		= CLARIION_NAME,
638	.module		= THIS_MODULE,
639	.devlist	= clariion_dev_list,
640	.attach		= clariion_bus_attach,
641	.detach		= clariion_bus_detach,
642	.check_sense	= clariion_check_sense,
643	.activate	= clariion_activate,
644	.prep_fn	= clariion_prep_fn,
645	.set_params	= clariion_set_params,
646};
647
648static int clariion_bus_attach(struct scsi_device *sdev)
649{
650	struct scsi_dh_data *scsi_dh_data;
651	struct clariion_dh_data *h;
652	unsigned long flags;
653	int err;
654
655	scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
656			       + sizeof(*h) , GFP_KERNEL);
657	if (!scsi_dh_data) {
658		sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
659			    CLARIION_NAME);
660		return -ENOMEM;
661	}
662
663	scsi_dh_data->scsi_dh = &clariion_dh;
664	h = (struct clariion_dh_data *) scsi_dh_data->buf;
665	h->lun_state = CLARIION_LUN_UNINITIALIZED;
666	h->default_sp = CLARIION_UNBOUND_LU;
667	h->current_sp = CLARIION_UNBOUND_LU;
668
669	err = clariion_std_inquiry(sdev, h);
670	if (err != SCSI_DH_OK)
671		goto failed;
672
673	err = clariion_send_inquiry(sdev, h);
674	if (err != SCSI_DH_OK)
675		goto failed;
676
677	if (!try_module_get(THIS_MODULE))
678		goto failed;
679
680	spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
681	sdev->scsi_dh_data = scsi_dh_data;
682	spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
683
684	sdev_printk(KERN_INFO, sdev,
685		    "%s: connected to SP %c Port %d (%s, default SP %c)\n",
686		    CLARIION_NAME, h->current_sp + 'A',
687		    h->port, lun_state[h->lun_state],
688		    h->default_sp + 'A');
689
690	return 0;
691
692failed:
693	kfree(scsi_dh_data);
694	sdev_printk(KERN_ERR, sdev, "%s: not attached\n",
695		    CLARIION_NAME);
696	return -EINVAL;
697}
698
699static void clariion_bus_detach(struct scsi_device *sdev)
700{
701	struct scsi_dh_data *scsi_dh_data;
702	unsigned long flags;
703
704	spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
705	scsi_dh_data = sdev->scsi_dh_data;
706	sdev->scsi_dh_data = NULL;
707	spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
708
709	sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n",
710		    CLARIION_NAME);
711
712	kfree(scsi_dh_data);
713	module_put(THIS_MODULE);
714}
715
716static int __init clariion_init(void)
717{
718	int r;
719
720	r = scsi_register_device_handler(&clariion_dh);
721	if (r != 0)
722		printk(KERN_ERR "%s: Failed to register scsi device handler.",
723			CLARIION_NAME);
724	return r;
725}
726
727static void __exit clariion_exit(void)
728{
729	scsi_unregister_device_handler(&clariion_dh);
730}
731
732module_init(clariion_init);
733module_exit(clariion_exit);
734
735MODULE_DESCRIPTION("EMC CX/AX/FC-family driver");
736MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, Chandra Seetharaman <sekharan@us.ibm.com>");
737MODULE_LICENSE("GPL");