aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/device_handler
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/scsi/device_handler
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/scsi/device_handler')
-rw-r--r--drivers/scsi/device_handler/scsi_dh.c29
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c142
-rw-r--r--drivers/scsi/device_handler/scsi_dh_emc.c14
-rw-r--r--drivers/scsi/device_handler/scsi_dh_hp_sw.c95
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c118
5 files changed, 276 insertions, 122 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c
index 3ee1cbc89479..6fae3d285ae7 100644
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ b/drivers/scsi/device_handler/scsi_dh.c
@@ -21,6 +21,7 @@
21 * Mike Anderson <andmike@linux.vnet.ibm.com> 21 * Mike Anderson <andmike@linux.vnet.ibm.com>
22 */ 22 */
23 23
24#include <linux/slab.h>
24#include <scsi/scsi_dh.h> 25#include <scsi/scsi_dh.h>
25#include "../scsi_priv.h" 26#include "../scsi_priv.h"
26 27
@@ -226,7 +227,7 @@ store_dh_state(struct device *dev, struct device_attribute *attr,
226 * Activate a device handler 227 * Activate a device handler
227 */ 228 */
228 if (scsi_dh->activate) 229 if (scsi_dh->activate)
229 err = scsi_dh->activate(sdev); 230 err = scsi_dh->activate(sdev, NULL, NULL);
230 else 231 else
231 err = 0; 232 err = 0;
232 } 233 }
@@ -304,18 +305,15 @@ static int scsi_dh_notifier(struct notifier_block *nb,
304 sdev = to_scsi_device(dev); 305 sdev = to_scsi_device(dev);
305 306
306 if (action == BUS_NOTIFY_ADD_DEVICE) { 307 if (action == BUS_NOTIFY_ADD_DEVICE) {
308 err = device_create_file(dev, &scsi_dh_state_attr);
309 /* don't care about err */
307 devinfo = device_handler_match(NULL, sdev); 310 devinfo = device_handler_match(NULL, sdev);
308 if (!devinfo) 311 if (devinfo)
309 goto out; 312 err = scsi_dh_handler_attach(sdev, devinfo);
310
311 err = scsi_dh_handler_attach(sdev, devinfo);
312 if (!err)
313 err = device_create_file(dev, &scsi_dh_state_attr);
314 } else if (action == BUS_NOTIFY_DEL_DEVICE) { 313 } else if (action == BUS_NOTIFY_DEL_DEVICE) {
315 device_remove_file(dev, &scsi_dh_state_attr); 314 device_remove_file(dev, &scsi_dh_state_attr);
316 scsi_dh_handler_detach(sdev, NULL); 315 scsi_dh_handler_detach(sdev, NULL);
317 } 316 }
318out:
319 return err; 317 return err;
320} 318}
321 319
@@ -423,10 +421,17 @@ EXPORT_SYMBOL_GPL(scsi_unregister_device_handler);
423/* 421/*
424 * scsi_dh_activate - activate the path associated with the scsi_device 422 * scsi_dh_activate - activate the path associated with the scsi_device
425 * corresponding to the given request queue. 423 * corresponding to the given request queue.
426 * @q - Request queue that is associated with the scsi_device to be 424 * Returns immediately without waiting for activation to be completed.
427 * activated. 425 * @q - Request queue that is associated with the scsi_device to be
426 * activated.
427 * @fn - Function to be called upon completion of the activation.
428 * Function fn is called with data (below) and the error code.
429 * Function fn may be called from the same calling context. So,
430 * do not hold the lock in the caller which may be needed in fn.
431 * @data - data passed to the function fn upon completion.
432 *
428 */ 433 */
429int scsi_dh_activate(struct request_queue *q) 434int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
430{ 435{
431 int err = 0; 436 int err = 0;
432 unsigned long flags; 437 unsigned long flags;
@@ -445,7 +450,7 @@ int scsi_dh_activate(struct request_queue *q)
445 return err; 450 return err;
446 451
447 if (scsi_dh->activate) 452 if (scsi_dh->activate)
448 err = scsi_dh->activate(sdev); 453 err = scsi_dh->activate(sdev, fn, data);
449 put_device(&sdev->sdev_gendev); 454 put_device(&sdev->sdev_gendev);
450 return err; 455 return err;
451} 456}
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index b5cdefaf2608..1a970a76b1b9 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -19,6 +19,7 @@
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * 20 *
21 */ 21 */
22#include <linux/slab.h>
22#include <scsi/scsi.h> 23#include <scsi/scsi.h>
23#include <scsi/scsi_eh.h> 24#include <scsi/scsi_eh.h>
24#include <scsi/scsi_dh.h> 25#include <scsi/scsi_dh.h>
@@ -60,11 +61,17 @@ struct alua_dh_data {
60 int bufflen; 61 int bufflen;
61 unsigned char sense[SCSI_SENSE_BUFFERSIZE]; 62 unsigned char sense[SCSI_SENSE_BUFFERSIZE];
62 int senselen; 63 int senselen;
64 struct scsi_device *sdev;
65 activate_complete callback_fn;
66 void *callback_data;
63}; 67};
64 68
65#define ALUA_POLICY_SWITCH_CURRENT 0 69#define ALUA_POLICY_SWITCH_CURRENT 0
66#define ALUA_POLICY_SWITCH_ALL 1 70#define ALUA_POLICY_SWITCH_ALL 1
67 71
72static char print_alua_state(int);
73static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *);
74
68static inline struct alua_dh_data *get_alua_data(struct scsi_device *sdev) 75static inline struct alua_dh_data *get_alua_data(struct scsi_device *sdev)
69{ 76{
70 struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data; 77 struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
@@ -231,18 +238,71 @@ done:
231} 238}
232 239
233/* 240/*
241 * alua_stpg - Evaluate SET TARGET GROUP STATES
242 * @sdev: the device to be evaluated
243 * @state: the new target group state
244 *
245 * Send a SET TARGET GROUP STATES command to the device.
246 * We only have to test here if we should resubmit the command;
247 * any other error is assumed as a failure.
248 */
249static void stpg_endio(struct request *req, int error)
250{
251 struct alua_dh_data *h = req->end_io_data;
252 struct scsi_sense_hdr sense_hdr;
253 unsigned err = SCSI_DH_IO;
254
255 if (error || host_byte(req->errors) != DID_OK ||
256 msg_byte(req->errors) != COMMAND_COMPLETE)
257 goto done;
258
259 if (err == SCSI_DH_IO && h->senselen > 0) {
260 err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
261 &sense_hdr);
262 if (!err) {
263 err = SCSI_DH_IO;
264 goto done;
265 }
266 err = alua_check_sense(h->sdev, &sense_hdr);
267 if (err == ADD_TO_MLQUEUE) {
268 err = SCSI_DH_RETRY;
269 goto done;
270 }
271 sdev_printk(KERN_INFO, h->sdev,
272 "%s: stpg sense code: %02x/%02x/%02x\n",
273 ALUA_DH_NAME, sense_hdr.sense_key,
274 sense_hdr.asc, sense_hdr.ascq);
275 err = SCSI_DH_IO;
276 }
277 if (err == SCSI_DH_OK) {
278 h->state = TPGS_STATE_OPTIMIZED;
279 sdev_printk(KERN_INFO, h->sdev,
280 "%s: port group %02x switched to state %c\n",
281 ALUA_DH_NAME, h->group_id,
282 print_alua_state(h->state));
283 }
284done:
285 blk_put_request(req);
286 if (h->callback_fn) {
287 h->callback_fn(h->callback_data, err);
288 h->callback_fn = h->callback_data = NULL;
289 }
290 return;
291}
292
293/*
234 * submit_stpg - Issue a SET TARGET GROUP STATES command 294 * submit_stpg - Issue a SET TARGET GROUP STATES command
235 * @sdev: sdev the command should be sent to
236 * 295 *
237 * Currently we're only setting the current target port group state 296 * Currently we're only setting the current target port group state
238 * to 'active/optimized' and let the array firmware figure out 297 * to 'active/optimized' and let the array firmware figure out
239 * the states of the remaining groups. 298 * the states of the remaining groups.
240 */ 299 */
241static unsigned submit_stpg(struct scsi_device *sdev, struct alua_dh_data *h) 300static unsigned submit_stpg(struct alua_dh_data *h)
242{ 301{
243 struct request *rq; 302 struct request *rq;
244 int err = SCSI_DH_RES_TEMP_UNAVAIL; 303 int err = SCSI_DH_RES_TEMP_UNAVAIL;
245 int stpg_len = 8; 304 int stpg_len = 8;
305 struct scsi_device *sdev = h->sdev;
246 306
247 /* Prepare the data buffer */ 307 /* Prepare the data buffer */
248 memset(h->buff, 0, stpg_len); 308 memset(h->buff, 0, stpg_len);
@@ -252,7 +312,7 @@ static unsigned submit_stpg(struct scsi_device *sdev, struct alua_dh_data *h)
252 312
253 rq = get_alua_req(sdev, h->buff, stpg_len, WRITE); 313 rq = get_alua_req(sdev, h->buff, stpg_len, WRITE);
254 if (!rq) 314 if (!rq)
255 goto done; 315 return SCSI_DH_RES_TEMP_UNAVAIL;
256 316
257 /* Prepare the command. */ 317 /* Prepare the command. */
258 rq->cmd[0] = MAINTENANCE_OUT; 318 rq->cmd[0] = MAINTENANCE_OUT;
@@ -266,17 +326,9 @@ static unsigned submit_stpg(struct scsi_device *sdev, struct alua_dh_data *h)
266 rq->sense = h->sense; 326 rq->sense = h->sense;
267 memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE); 327 memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
268 rq->sense_len = h->senselen = 0; 328 rq->sense_len = h->senselen = 0;
329 rq->end_io_data = h;
269 330
270 err = blk_execute_rq(rq->q, NULL, rq, 1); 331 blk_execute_rq_nowait(rq->q, NULL, rq, 1, stpg_endio);
271 if (err == -EIO) {
272 sdev_printk(KERN_INFO, sdev,
273 "%s: stpg failed with %x\n",
274 ALUA_DH_NAME, rq->errors);
275 h->senselen = rq->sense_len;
276 err = SCSI_DH_IO;
277 }
278 blk_put_request(rq);
279done:
280 return err; 332 return err;
281} 333}
282 334
@@ -477,50 +529,6 @@ static int alua_check_sense(struct scsi_device *sdev,
477} 529}
478 530
479/* 531/*
480 * alua_stpg - Evaluate SET TARGET GROUP STATES
481 * @sdev: the device to be evaluated
482 * @state: the new target group state
483 *
484 * Send a SET TARGET GROUP STATES command to the device.
485 * We only have to test here if we should resubmit the command;
486 * any other error is assumed as a failure.
487 */
488static int alua_stpg(struct scsi_device *sdev, int state,
489 struct alua_dh_data *h)
490{
491 struct scsi_sense_hdr sense_hdr;
492 unsigned err;
493 int retry = ALUA_FAILOVER_RETRIES;
494
495 retry:
496 err = submit_stpg(sdev, h);
497 if (err == SCSI_DH_IO && h->senselen > 0) {
498 err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
499 &sense_hdr);
500 if (!err)
501 return SCSI_DH_IO;
502 err = alua_check_sense(sdev, &sense_hdr);
503 if (retry > 0 && err == ADD_TO_MLQUEUE) {
504 retry--;
505 goto retry;
506 }
507 sdev_printk(KERN_INFO, sdev,
508 "%s: stpg sense code: %02x/%02x/%02x\n",
509 ALUA_DH_NAME, sense_hdr.sense_key,
510 sense_hdr.asc, sense_hdr.ascq);
511 err = SCSI_DH_IO;
512 }
513 if (err == SCSI_DH_OK) {
514 h->state = state;
515 sdev_printk(KERN_INFO, sdev,
516 "%s: port group %02x switched to state %c\n",
517 ALUA_DH_NAME, h->group_id,
518 print_alua_state(h->state) );
519 }
520 return err;
521}
522
523/*
524 * alua_rtpg - Evaluate REPORT TARGET GROUP STATES 532 * alua_rtpg - Evaluate REPORT TARGET GROUP STATES
525 * @sdev: the device to be evaluated. 533 * @sdev: the device to be evaluated.
526 * 534 *
@@ -652,7 +660,8 @@ out:
652 * based on a certain policy. But until we actually encounter them it 660 * based on a certain policy. But until we actually encounter them it
653 * should be okay. 661 * should be okay.
654 */ 662 */
655static int alua_activate(struct scsi_device *sdev) 663static int alua_activate(struct scsi_device *sdev,
664 activate_complete fn, void *data)
656{ 665{
657 struct alua_dh_data *h = get_alua_data(sdev); 666 struct alua_dh_data *h = get_alua_data(sdev);
658 int err = SCSI_DH_OK; 667 int err = SCSI_DH_OK;
@@ -663,11 +672,19 @@ static int alua_activate(struct scsi_device *sdev)
663 goto out; 672 goto out;
664 } 673 }
665 674
666 if (h->tpgs & TPGS_MODE_EXPLICIT && h->state != TPGS_STATE_OPTIMIZED) 675 if (h->tpgs & TPGS_MODE_EXPLICIT && h->state != TPGS_STATE_OPTIMIZED) {
667 err = alua_stpg(sdev, TPGS_STATE_OPTIMIZED, h); 676 h->callback_fn = fn;
677 h->callback_data = data;
678 err = submit_stpg(h);
679 if (err == SCSI_DH_OK)
680 return 0;
681 h->callback_fn = h->callback_data = NULL;
682 }
668 683
669out: 684out:
670 return err; 685 if (fn)
686 fn(data, err);
687 return 0;
671} 688}
672 689
673/* 690/*
@@ -701,6 +718,8 @@ static const struct scsi_dh_devlist alua_dev_list[] = {
701 {"IBM", "2145" }, 718 {"IBM", "2145" },
702 {"Pillar", "Axiom" }, 719 {"Pillar", "Axiom" },
703 {"Intel", "Multi-Flex"}, 720 {"Intel", "Multi-Flex"},
721 {"NETAPP", "LUN"},
722 {"AIX", "NVDISK"},
704 {NULL, NULL} 723 {NULL, NULL}
705}; 724};
706 725
@@ -745,6 +764,7 @@ static int alua_bus_attach(struct scsi_device *sdev)
745 h->rel_port = -1; 764 h->rel_port = -1;
746 h->buff = h->inq; 765 h->buff = h->inq;
747 h->bufflen = ALUA_INQUIRY_SIZE; 766 h->bufflen = ALUA_INQUIRY_SIZE;
767 h->sdev = sdev;
748 768
749 err = alua_initialize(sdev, h); 769 err = alua_initialize(sdev, h);
750 if (err != SCSI_DH_OK) 770 if (err != SCSI_DH_OK)
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c
index 0cffe84976fe..e8a0bc3efd49 100644
--- a/drivers/scsi/device_handler/scsi_dh_emc.c
+++ b/drivers/scsi/device_handler/scsi_dh_emc.c
@@ -20,6 +20,7 @@
20 * along with this program; see the file COPYING. If not, write to 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. 21 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 */ 22 */
23#include <linux/slab.h>
23#include <scsi/scsi.h> 24#include <scsi/scsi.h>
24#include <scsi/scsi_eh.h> 25#include <scsi/scsi_eh.h>
25#include <scsi/scsi_dh.h> 26#include <scsi/scsi_dh.h>
@@ -272,7 +273,7 @@ static struct request *get_req(struct scsi_device *sdev, int cmd,
272 int len = 0; 273 int len = 0;
273 274
274 rq = blk_get_request(sdev->request_queue, 275 rq = blk_get_request(sdev->request_queue,
275 (cmd == MODE_SELECT) ? WRITE : READ, GFP_NOIO); 276 (cmd != INQUIRY) ? WRITE : READ, GFP_NOIO);
276 if (!rq) { 277 if (!rq) {
277 sdev_printk(KERN_INFO, sdev, "get_req: blk_get_request failed"); 278 sdev_printk(KERN_INFO, sdev, "get_req: blk_get_request failed");
278 return NULL; 279 return NULL;
@@ -286,14 +287,17 @@ static struct request *get_req(struct scsi_device *sdev, int cmd,
286 len = sizeof(short_trespass); 287 len = sizeof(short_trespass);
287 rq->cmd_flags |= REQ_RW; 288 rq->cmd_flags |= REQ_RW;
288 rq->cmd[1] = 0x10; 289 rq->cmd[1] = 0x10;
290 rq->cmd[4] = len;
289 break; 291 break;
290 case MODE_SELECT_10: 292 case MODE_SELECT_10:
291 len = sizeof(long_trespass); 293 len = sizeof(long_trespass);
292 rq->cmd_flags |= REQ_RW; 294 rq->cmd_flags |= REQ_RW;
293 rq->cmd[1] = 0x10; 295 rq->cmd[1] = 0x10;
296 rq->cmd[8] = len;
294 break; 297 break;
295 case INQUIRY: 298 case INQUIRY:
296 len = CLARIION_BUFFER_SIZE; 299 len = CLARIION_BUFFER_SIZE;
300 rq->cmd[4] = len;
297 memset(buffer, 0, len); 301 memset(buffer, 0, len);
298 break; 302 break;
299 default: 303 default:
@@ -301,7 +305,6 @@ static struct request *get_req(struct scsi_device *sdev, int cmd,
301 break; 305 break;
302 } 306 }
303 307
304 rq->cmd[4] = len;
305 rq->cmd_type = REQ_TYPE_BLOCK_PC; 308 rq->cmd_type = REQ_TYPE_BLOCK_PC;
306 rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | 309 rq->cmd_flags |= REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT |
307 REQ_FAILFAST_DRIVER; 310 REQ_FAILFAST_DRIVER;
@@ -528,7 +531,8 @@ retry:
528 return err; 531 return err;
529} 532}
530 533
531static int clariion_activate(struct scsi_device *sdev) 534static int clariion_activate(struct scsi_device *sdev,
535 activate_complete fn, void *data)
532{ 536{
533 struct clariion_dh_data *csdev = get_clariion_data(sdev); 537 struct clariion_dh_data *csdev = get_clariion_data(sdev);
534 int result; 538 int result;
@@ -559,7 +563,9 @@ done:
559 csdev->port, lun_state[csdev->lun_state], 563 csdev->port, lun_state[csdev->lun_state],
560 csdev->default_sp + 'A'); 564 csdev->default_sp + 'A');
561 565
562 return result; 566 if (fn)
567 fn(data, result);
568 return 0;
563} 569}
564/* 570/*
565 * params - parameters in the following format 571 * params - parameters in the following format
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
index f7da7530875e..e3916641e627 100644
--- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
@@ -21,6 +21,7 @@
21 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 21 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 */ 22 */
23 23
24#include <linux/slab.h>
24#include <scsi/scsi.h> 25#include <scsi/scsi.h>
25#include <scsi/scsi_dbg.h> 26#include <scsi/scsi_dbg.h>
26#include <scsi/scsi_eh.h> 27#include <scsi/scsi_eh.h>
@@ -39,8 +40,14 @@ struct hp_sw_dh_data {
39 unsigned char sense[SCSI_SENSE_BUFFERSIZE]; 40 unsigned char sense[SCSI_SENSE_BUFFERSIZE];
40 int path_state; 41 int path_state;
41 int retries; 42 int retries;
43 int retry_cnt;
44 struct scsi_device *sdev;
45 activate_complete callback_fn;
46 void *callback_data;
42}; 47};
43 48
49static int hp_sw_start_stop(struct hp_sw_dh_data *);
50
44static inline struct hp_sw_dh_data *get_hp_sw_data(struct scsi_device *sdev) 51static inline struct hp_sw_dh_data *get_hp_sw_data(struct scsi_device *sdev)
45{ 52{
46 struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data; 53 struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
@@ -191,19 +198,53 @@ static int start_done(struct scsi_device *sdev, unsigned char *sense)
191 return rc; 198 return rc;
192} 199}
193 200
201static void start_stop_endio(struct request *req, int error)
202{
203 struct hp_sw_dh_data *h = req->end_io_data;
204 unsigned err = SCSI_DH_OK;
205
206 if (error || host_byte(req->errors) != DID_OK ||
207 msg_byte(req->errors) != COMMAND_COMPLETE) {
208 sdev_printk(KERN_WARNING, h->sdev,
209 "%s: sending start_stop_unit failed with %x\n",
210 HP_SW_NAME, req->errors);
211 err = SCSI_DH_IO;
212 goto done;
213 }
214
215 if (req->sense_len > 0) {
216 err = start_done(h->sdev, h->sense);
217 if (err == SCSI_DH_RETRY) {
218 err = SCSI_DH_IO;
219 if (--h->retry_cnt) {
220 blk_put_request(req);
221 err = hp_sw_start_stop(h);
222 if (err == SCSI_DH_OK)
223 return;
224 }
225 }
226 }
227done:
228 blk_put_request(req);
229 if (h->callback_fn) {
230 h->callback_fn(h->callback_data, err);
231 h->callback_fn = h->callback_data = NULL;
232 }
233 return;
234
235}
236
194/* 237/*
195 * hp_sw_start_stop - Send START STOP UNIT command 238 * hp_sw_start_stop - Send START STOP UNIT command
196 * @sdev: sdev command should be sent to 239 * @sdev: sdev command should be sent to
197 * 240 *
198 * Sending START STOP UNIT activates the SP. 241 * Sending START STOP UNIT activates the SP.
199 */ 242 */
200static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h) 243static int hp_sw_start_stop(struct hp_sw_dh_data *h)
201{ 244{
202 struct request *req; 245 struct request *req;
203 int ret, retry;
204 246
205retry: 247 req = blk_get_request(h->sdev->request_queue, WRITE, GFP_ATOMIC);
206 req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO);
207 if (!req) 248 if (!req)
208 return SCSI_DH_RES_TEMP_UNAVAIL; 249 return SCSI_DH_RES_TEMP_UNAVAIL;
209 250
@@ -217,32 +258,10 @@ retry:
217 req->sense = h->sense; 258 req->sense = h->sense;
218 memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE); 259 memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
219 req->sense_len = 0; 260 req->sense_len = 0;
220 retry = h->retries; 261 req->end_io_data = h;
221
222 ret = blk_execute_rq(req->q, NULL, req, 1);
223 if (ret == -EIO) {
224 if (req->sense_len > 0) {
225 ret = start_done(sdev, h->sense);
226 } else {
227 sdev_printk(KERN_WARNING, sdev,
228 "%s: sending start_stop_unit failed with %x\n",
229 HP_SW_NAME, req->errors);
230 ret = SCSI_DH_IO;
231 }
232 } else
233 ret = SCSI_DH_OK;
234 262
235 if (ret == SCSI_DH_RETRY) { 263 blk_execute_rq_nowait(req->q, NULL, req, 1, start_stop_endio);
236 if (--retry) { 264 return SCSI_DH_OK;
237 blk_put_request(req);
238 goto retry;
239 }
240 ret = SCSI_DH_IO;
241 }
242
243 blk_put_request(req);
244
245 return ret;
246} 265}
247 266
248static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req) 267static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req)
@@ -268,7 +287,8 @@ static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req)
268 * activate the passive path (and deactivate the 287 * activate the passive path (and deactivate the
269 * previously active one). 288 * previously active one).
270 */ 289 */
271static int hp_sw_activate(struct scsi_device *sdev) 290static int hp_sw_activate(struct scsi_device *sdev,
291 activate_complete fn, void *data)
272{ 292{
273 int ret = SCSI_DH_OK; 293 int ret = SCSI_DH_OK;
274 struct hp_sw_dh_data *h = get_hp_sw_data(sdev); 294 struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
@@ -276,14 +296,18 @@ static int hp_sw_activate(struct scsi_device *sdev)
276 ret = hp_sw_tur(sdev, h); 296 ret = hp_sw_tur(sdev, h);
277 297
278 if (ret == SCSI_DH_OK && h->path_state == HP_SW_PATH_PASSIVE) { 298 if (ret == SCSI_DH_OK && h->path_state == HP_SW_PATH_PASSIVE) {
279 ret = hp_sw_start_stop(sdev, h); 299 h->retry_cnt = h->retries;
300 h->callback_fn = fn;
301 h->callback_data = data;
302 ret = hp_sw_start_stop(h);
280 if (ret == SCSI_DH_OK) 303 if (ret == SCSI_DH_OK)
281 sdev_printk(KERN_INFO, sdev, 304 return 0;
282 "%s: activated path\n", 305 h->callback_fn = h->callback_data = NULL;
283 HP_SW_NAME);
284 } 306 }
285 307
286 return ret; 308 if (fn)
309 fn(data, ret);
310 return 0;
287} 311}
288 312
289static const struct scsi_dh_devlist hp_sw_dh_data_list[] = { 313static const struct scsi_dh_devlist hp_sw_dh_data_list[] = {
@@ -326,6 +350,7 @@ static int hp_sw_bus_attach(struct scsi_device *sdev)
326 h = (struct hp_sw_dh_data *) scsi_dh_data->buf; 350 h = (struct hp_sw_dh_data *) scsi_dh_data->buf;
327 h->path_state = HP_SW_PATH_UNINITIALIZED; 351 h->path_state = HP_SW_PATH_UNINITIALIZED;
328 h->retries = HP_SW_RETRIES; 352 h->retries = HP_SW_RETRIES;
353 h->sdev = sdev;
329 354
330 ret = hp_sw_tur(sdev, h); 355 ret = hp_sw_tur(sdev, h);
331 if (ret != SCSI_DH_OK || h->path_state == HP_SW_PATH_UNINITIALIZED) 356 if (ret != SCSI_DH_OK || h->path_state == HP_SW_PATH_UNINITIALIZED)
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index 268189d31d9c..5b683e429542 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -22,6 +22,8 @@
22#include <scsi/scsi.h> 22#include <scsi/scsi.h>
23#include <scsi/scsi_eh.h> 23#include <scsi/scsi_eh.h>
24#include <scsi/scsi_dh.h> 24#include <scsi/scsi_dh.h>
25#include <linux/workqueue.h>
26#include <linux/slab.h>
25 27
26#define RDAC_NAME "rdac" 28#define RDAC_NAME "rdac"
27#define RDAC_RETRY_COUNT 5 29#define RDAC_RETRY_COUNT 5
@@ -138,7 +140,13 @@ struct rdac_controller {
138 } mode_select; 140 } mode_select;
139 u8 index; 141 u8 index;
140 u8 array_name[ARRAY_LABEL_LEN]; 142 u8 array_name[ARRAY_LABEL_LEN];
143 spinlock_t ms_lock;
144 int ms_queued;
145 struct work_struct ms_work;
146 struct scsi_device *ms_sdev;
147 struct list_head ms_head;
141}; 148};
149
142struct c8_inquiry { 150struct c8_inquiry {
143 u8 peripheral_info; 151 u8 peripheral_info;
144 u8 page_code; /* 0xC8 */ 152 u8 page_code; /* 0xC8 */
@@ -198,8 +206,17 @@ static const char *lun_state[] =
198 "owned (AVT mode)", 206 "owned (AVT mode)",
199}; 207};
200 208
209struct rdac_queue_data {
210 struct list_head entry;
211 struct rdac_dh_data *h;
212 activate_complete callback_fn;
213 void *callback_data;
214};
215
201static LIST_HEAD(ctlr_list); 216static LIST_HEAD(ctlr_list);
202static DEFINE_SPINLOCK(list_lock); 217static DEFINE_SPINLOCK(list_lock);
218static struct workqueue_struct *kmpath_rdacd;
219static void send_mode_select(struct work_struct *work);
203 220
204/* 221/*
205 * module parameter to enable rdac debug logging. 222 * module parameter to enable rdac debug logging.
@@ -281,7 +298,6 @@ static struct request *rdac_failover_get(struct scsi_device *sdev,
281 rdac_pg->subpage_code = 0x1; 298 rdac_pg->subpage_code = 0x1;
282 rdac_pg->page_len[0] = 0x01; 299 rdac_pg->page_len[0] = 0x01;
283 rdac_pg->page_len[1] = 0x28; 300 rdac_pg->page_len[1] = 0x28;
284 rdac_pg->lun_table[h->lun] = 0x81;
285 } else { 301 } else {
286 struct rdac_pg_legacy *rdac_pg; 302 struct rdac_pg_legacy *rdac_pg;
287 303
@@ -291,7 +307,6 @@ static struct request *rdac_failover_get(struct scsi_device *sdev,
291 common = &rdac_pg->common; 307 common = &rdac_pg->common;
292 rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER; 308 rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER;
293 rdac_pg->page_len = 0x68; 309 rdac_pg->page_len = 0x68;
294 rdac_pg->lun_table[h->lun] = 0x81;
295 } 310 }
296 common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS; 311 common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS;
297 common->quiescence_timeout = RDAC_QUIESCENCE_TIME; 312 common->quiescence_timeout = RDAC_QUIESCENCE_TIME;
@@ -325,6 +340,7 @@ static void release_controller(struct kref *kref)
325 struct rdac_controller *ctlr; 340 struct rdac_controller *ctlr;
326 ctlr = container_of(kref, struct rdac_controller, kref); 341 ctlr = container_of(kref, struct rdac_controller, kref);
327 342
343 flush_workqueue(kmpath_rdacd);
328 spin_lock(&list_lock); 344 spin_lock(&list_lock);
329 list_del(&ctlr->node); 345 list_del(&ctlr->node);
330 spin_unlock(&list_lock); 346 spin_unlock(&list_lock);
@@ -363,6 +379,11 @@ static struct rdac_controller *get_controller(u8 *subsys_id, u8 *slot_id,
363 379
364 kref_init(&ctlr->kref); 380 kref_init(&ctlr->kref);
365 ctlr->use_ms10 = -1; 381 ctlr->use_ms10 = -1;
382 ctlr->ms_queued = 0;
383 ctlr->ms_sdev = NULL;
384 spin_lock_init(&ctlr->ms_lock);
385 INIT_WORK(&ctlr->ms_work, send_mode_select);
386 INIT_LIST_HEAD(&ctlr->ms_head);
366 list_add(&ctlr->node, &ctlr_list); 387 list_add(&ctlr->node, &ctlr_list);
367done: 388done:
368 spin_unlock(&list_lock); 389 spin_unlock(&list_lock);
@@ -490,7 +511,7 @@ static int set_mode_select(struct scsi_device *sdev, struct rdac_dh_data *h)
490} 511}
491 512
492static int mode_select_handle_sense(struct scsi_device *sdev, 513static int mode_select_handle_sense(struct scsi_device *sdev,
493 unsigned char *sensebuf) 514 unsigned char *sensebuf)
494{ 515{
495 struct scsi_sense_hdr sense_hdr; 516 struct scsi_sense_hdr sense_hdr;
496 int err = SCSI_DH_IO, ret; 517 int err = SCSI_DH_IO, ret;
@@ -533,11 +554,29 @@ done:
533 return err; 554 return err;
534} 555}
535 556
536static int send_mode_select(struct scsi_device *sdev, struct rdac_dh_data *h) 557static void send_mode_select(struct work_struct *work)
537{ 558{
559 struct rdac_controller *ctlr =
560 container_of(work, struct rdac_controller, ms_work);
538 struct request *rq; 561 struct request *rq;
562 struct scsi_device *sdev = ctlr->ms_sdev;
563 struct rdac_dh_data *h = get_rdac_data(sdev);
539 struct request_queue *q = sdev->request_queue; 564 struct request_queue *q = sdev->request_queue;
540 int err, retry_cnt = RDAC_RETRY_COUNT; 565 int err, retry_cnt = RDAC_RETRY_COUNT;
566 struct rdac_queue_data *tmp, *qdata;
567 LIST_HEAD(list);
568 u8 *lun_table;
569
570 spin_lock(&ctlr->ms_lock);
571 list_splice_init(&ctlr->ms_head, &list);
572 ctlr->ms_queued = 0;
573 ctlr->ms_sdev = NULL;
574 spin_unlock(&ctlr->ms_lock);
575
576 if (ctlr->use_ms10)
577 lun_table = ctlr->mode_select.expanded.lun_table;
578 else
579 lun_table = ctlr->mode_select.legacy.lun_table;
541 580
542retry: 581retry:
543 err = SCSI_DH_RES_TEMP_UNAVAIL; 582 err = SCSI_DH_RES_TEMP_UNAVAIL;
@@ -545,6 +584,10 @@ retry:
545 if (!rq) 584 if (!rq)
546 goto done; 585 goto done;
547 586
587 list_for_each_entry(qdata, &list, entry) {
588 lun_table[qdata->h->lun] = 0x81;
589 }
590
548 RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, " 591 RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, "
549 "%s MODE_SELECT command", 592 "%s MODE_SELECT command",
550 (char *) h->ctlr->array_name, h->ctlr->index, 593 (char *) h->ctlr->array_name, h->ctlr->index,
@@ -565,10 +608,45 @@ retry:
565 } 608 }
566 609
567done: 610done:
568 return err; 611 list_for_each_entry_safe(qdata, tmp, &list, entry) {
612 list_del(&qdata->entry);
613 if (err == SCSI_DH_OK)
614 qdata->h->state = RDAC_STATE_ACTIVE;
615 if (qdata->callback_fn)
616 qdata->callback_fn(qdata->callback_data, err);
617 kfree(qdata);
618 }
619 return;
620}
621
622static int queue_mode_select(struct scsi_device *sdev,
623 activate_complete fn, void *data)
624{
625 struct rdac_queue_data *qdata;
626 struct rdac_controller *ctlr;
627
628 qdata = kzalloc(sizeof(*qdata), GFP_KERNEL);
629 if (!qdata)
630 return SCSI_DH_RETRY;
631
632 qdata->h = get_rdac_data(sdev);
633 qdata->callback_fn = fn;
634 qdata->callback_data = data;
635
636 ctlr = qdata->h->ctlr;
637 spin_lock(&ctlr->ms_lock);
638 list_add_tail(&qdata->entry, &ctlr->ms_head);
639 if (!ctlr->ms_queued) {
640 ctlr->ms_queued = 1;
641 ctlr->ms_sdev = sdev;
642 queue_work(kmpath_rdacd, &ctlr->ms_work);
643 }
644 spin_unlock(&ctlr->ms_lock);
645 return SCSI_DH_OK;
569} 646}
570 647
571static int rdac_activate(struct scsi_device *sdev) 648static int rdac_activate(struct scsi_device *sdev,
649 activate_complete fn, void *data)
572{ 650{
573 struct rdac_dh_data *h = get_rdac_data(sdev); 651 struct rdac_dh_data *h = get_rdac_data(sdev);
574 int err = SCSI_DH_OK; 652 int err = SCSI_DH_OK;
@@ -577,10 +655,15 @@ static int rdac_activate(struct scsi_device *sdev)
577 if (err != SCSI_DH_OK) 655 if (err != SCSI_DH_OK)
578 goto done; 656 goto done;
579 657
580 if (h->lun_state == RDAC_LUN_UNOWNED) 658 if (h->lun_state == RDAC_LUN_UNOWNED) {
581 err = send_mode_select(sdev, h); 659 err = queue_mode_select(sdev, fn, data);
660 if (err == SCSI_DH_OK)
661 return 0;
662 }
582done: 663done:
583 return err; 664 if (fn)
665 fn(data, err);
666 return 0;
584} 667}
585 668
586static int rdac_prep_fn(struct scsi_device *sdev, struct request *req) 669static int rdac_prep_fn(struct scsi_device *sdev, struct request *req)
@@ -666,6 +749,8 @@ static const struct scsi_dh_devlist rdac_dev_list[] = {
666 {"IBM", "1724"}, 749 {"IBM", "1724"},
667 {"IBM", "1726"}, 750 {"IBM", "1726"},
668 {"IBM", "1742"}, 751 {"IBM", "1742"},
752 {"IBM", "1745"},
753 {"IBM", "1746"},
669 {"IBM", "1814"}, 754 {"IBM", "1814"},
670 {"IBM", "1815"}, 755 {"IBM", "1815"},
671 {"IBM", "1818"}, 756 {"IBM", "1818"},
@@ -790,13 +875,26 @@ static int __init rdac_init(void)
790 int r; 875 int r;
791 876
792 r = scsi_register_device_handler(&rdac_dh); 877 r = scsi_register_device_handler(&rdac_dh);
793 if (r != 0) 878 if (r != 0) {
794 printk(KERN_ERR "Failed to register scsi device handler."); 879 printk(KERN_ERR "Failed to register scsi device handler.");
880 goto done;
881 }
882
883 /*
884 * Create workqueue to handle mode selects for rdac
885 */
886 kmpath_rdacd = create_singlethread_workqueue("kmpath_rdacd");
887 if (!kmpath_rdacd) {
888 scsi_unregister_device_handler(&rdac_dh);
889 printk(KERN_ERR "kmpath_rdacd creation failed.\n");
890 }
891done:
795 return r; 892 return r;
796} 893}
797 894
798static void __exit rdac_exit(void) 895static void __exit rdac_exit(void)
799{ 896{
897 destroy_workqueue(kmpath_rdacd);
800 scsi_unregister_device_handler(&rdac_dh); 898 scsi_unregister_device_handler(&rdac_dh);
801} 899}
802 900