]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.fixes/scsi-misc-git-update
Merge branch 'master' of git://git.ipfire.org/ipfire-2.x
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / scsi-misc-git-update
1 From: James Bottomley <james.bottomley@hansenpartnership.com>
2 Subject: SCSI misc fixes
3 References: FATE#303485,FATE#303484
4
5 This patch pulls in the latest patches from the scsi-misc tree.
6 The functions are required by the various driver updates.
7
8 Signed-off-by: Hannes Reinecke <hare@suse.de>
9
10 ---
11 Documentation/scsi/scsi_fc_transport.txt | 36 +
12 drivers/mmc/card/block.c | 10
13 drivers/scsi/device_handler/scsi_dh_emc.c | 1
14 drivers/scsi/device_handler/scsi_dh_hp_sw.c | 2
15 drivers/scsi/device_handler/scsi_dh_rdac.c | 2
16 drivers/scsi/libiscsi.c | 2
17 drivers/scsi/scsi.c | 13
18 drivers/scsi/scsi_lib.c | 39 +-
19 drivers/scsi/scsi_netlink.c | 523 +++++++++++++++++++++++++++-
20 drivers/scsi/scsi_scan.c | 20 -
21 drivers/scsi/scsi_sysfs.c | 1
22 drivers/scsi/scsi_transport_fc.c | 54 +-
23 drivers/scsi/sd.c | 29 -
24 include/linux/string_helpers.h | 16
25 include/scsi/scsi_device.h | 21 -
26 include/scsi/scsi_netlink.h | 62 +++
27 include/scsi/scsi_transport_fc.h | 23 +
28 lib/Makefile | 3
29 lib/string_helpers.c | 64 +++
30 19 files changed, 834 insertions(+), 87 deletions(-)
31
32 --- a/Documentation/scsi/scsi_fc_transport.txt
33 +++ b/Documentation/scsi/scsi_fc_transport.txt
34 @@ -436,6 +436,42 @@ Other:
35 was updated to remove all vports for the fc_host as well.
36
37
38 +Transport supplied functions
39 +----------------------------
40 +
41 +The following functions are supplied by the FC-transport for use by LLDs.
42 +
43 + fc_vport_create - create a vport
44 + fc_vport_terminate - detach and remove a vport
45 +
46 +Details:
47 +
48 +/**
49 + * fc_vport_create - Admin App or LLDD requests creation of a vport
50 + * @shost: scsi host the virtual port is connected to.
51 + * @ids: The world wide names, FC4 port roles, etc for
52 + * the virtual port.
53 + *
54 + * Notes:
55 + * This routine assumes no locks are held on entry.
56 + */
57 +struct fc_vport *
58 +fc_vport_create(struct Scsi_Host *shost, struct fc_vport_identifiers *ids)
59 +
60 +/**
61 + * fc_vport_terminate - Admin App or LLDD requests termination of a vport
62 + * @vport: fc_vport to be terminated
63 + *
64 + * Calls the LLDD vport_delete() function, then deallocates and removes
65 + * the vport from the shost and object tree.
66 + *
67 + * Notes:
68 + * This routine assumes no locks are held on entry.
69 + */
70 +int
71 +fc_vport_terminate(struct fc_vport *vport)
72 +
73 +
74 Credits
75 =======
76 The following people have contributed to this document:
77 --- a/drivers/mmc/card/block.c
78 +++ b/drivers/mmc/card/block.c
79 @@ -29,6 +29,7 @@
80 #include <linux/blkdev.h>
81 #include <linux/mutex.h>
82 #include <linux/scatterlist.h>
83 +#include <linux/string_helpers.h>
84
85 #include <linux/mmc/card.h>
86 #include <linux/mmc/host.h>
87 @@ -532,6 +533,8 @@ static int mmc_blk_probe(struct mmc_card
88 struct mmc_blk_data *md;
89 int err;
90
91 + char cap_str[10];
92 +
93 /*
94 * Check that the card supports the command class(es) we need.
95 */
96 @@ -546,10 +549,11 @@ static int mmc_blk_probe(struct mmc_card
97 if (err)
98 goto out;
99
100 - printk(KERN_INFO "%s: %s %s %lluKiB %s\n",
101 + string_get_size(get_capacity(md->disk) << 9, STRING_UNITS_2,
102 + cap_str, sizeof(cap_str));
103 + printk(KERN_INFO "%s: %s %s %s %s\n",
104 md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
105 - (unsigned long long)(get_capacity(md->disk) >> 1),
106 - md->read_only ? "(ro)" : "");
107 + cap_str, md->read_only ? "(ro)" : "");
108
109 mmc_set_drvdata(card, md);
110 add_disk(md->disk);
111 --- a/drivers/scsi/device_handler/scsi_dh_emc.c
112 +++ b/drivers/scsi/device_handler/scsi_dh_emc.c
113 @@ -278,7 +278,6 @@ static struct request *get_req(struct sc
114 return NULL;
115 }
116
117 - memset(rq->cmd, 0, BLK_MAX_CDB);
118 rq->cmd_len = COMMAND_SIZE(cmd);
119 rq->cmd[0] = cmd;
120
121 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
122 +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
123 @@ -114,7 +114,6 @@ static int hp_sw_tur(struct scsi_device
124 req->cmd_type = REQ_TYPE_BLOCK_PC;
125 req->cmd_flags |= REQ_FAILFAST;
126 req->cmd_len = COMMAND_SIZE(TEST_UNIT_READY);
127 - memset(req->cmd, 0, MAX_COMMAND_SIZE);
128 req->cmd[0] = TEST_UNIT_READY;
129 req->timeout = HP_SW_TIMEOUT;
130 req->sense = h->sense;
131 @@ -207,7 +206,6 @@ static int hp_sw_start_stop(struct scsi_
132 req->cmd_type = REQ_TYPE_BLOCK_PC;
133 req->cmd_flags |= REQ_FAILFAST;
134 req->cmd_len = COMMAND_SIZE(START_STOP);
135 - memset(req->cmd, 0, MAX_COMMAND_SIZE);
136 req->cmd[0] = START_STOP;
137 req->cmd[4] = 1; /* Start spin cycle */
138 req->timeout = HP_SW_TIMEOUT;
139 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c
140 +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
141 @@ -225,8 +225,6 @@ static struct request *get_rdac_req(stru
142 return NULL;
143 }
144
145 - memset(rq->cmd, 0, BLK_MAX_CDB);
146 -
147 rq->cmd_type = REQ_TYPE_BLOCK_PC;
148 rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
149 rq->retries = RDAC_RETRIES;
150 --- a/drivers/scsi/libiscsi.c
151 +++ b/drivers/scsi/libiscsi.c
152 @@ -1456,7 +1456,7 @@ static void fail_all_commands(struct isc
153 if (lun == task->sc->device->lun || lun == -1) {
154 debug_scsi("failing in progress sc %p itt 0x%x\n",
155 task->sc, task->itt);
156 - fail_command(conn, task, DID_BUS_BUSY << 16);
157 + fail_command(conn, task, error << 16);
158 }
159 }
160 }
161 --- a/drivers/scsi/scsi.c
162 +++ b/drivers/scsi/scsi.c
163 @@ -668,13 +668,14 @@ int scsi_dispatch_cmd(struct scsi_cmnd *
164 goto out;
165 }
166
167 - /* Check to see if the scsi lld put this device into state SDEV_BLOCK. */
168 - if (unlikely(cmd->device->sdev_state == SDEV_BLOCK)) {
169 + /* Check to see if the scsi lld made this device blocked. */
170 + if (unlikely(scsi_device_blocked(cmd->device))) {
171 /*
172 - * in SDEV_BLOCK, the command is just put back on the device
173 - * queue. The suspend state has already blocked the queue so
174 - * future requests should not occur until the device
175 - * transitions out of the suspend state.
176 + * in blocked state, the command is just put back on
177 + * the device queue. The suspend state has already
178 + * blocked the queue so future requests should not
179 + * occur until the device transitions out of the
180 + * suspend state.
181 */
182
183 scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
184 --- a/drivers/scsi/scsi_lib.c
185 +++ b/drivers/scsi/scsi_lib.c
186 @@ -1250,6 +1250,7 @@ int scsi_prep_state_check(struct scsi_de
187 break;
188 case SDEV_QUIESCE:
189 case SDEV_BLOCK:
190 + case SDEV_CREATED_BLOCK:
191 /*
192 * If the devices is blocked we defer normal commands.
193 */
194 @@ -2073,10 +2074,13 @@ scsi_device_set_state(struct scsi_device
195
196 switch (state) {
197 case SDEV_CREATED:
198 - /* There are no legal states that come back to
199 - * created. This is the manually initialised start
200 - * state */
201 - goto illegal;
202 + switch (oldstate) {
203 + case SDEV_CREATED_BLOCK:
204 + break;
205 + default:
206 + goto illegal;
207 + }
208 + break;
209
210 case SDEV_RUNNING:
211 switch (oldstate) {
212 @@ -2114,8 +2118,17 @@ scsi_device_set_state(struct scsi_device
213
214 case SDEV_BLOCK:
215 switch (oldstate) {
216 - case SDEV_CREATED:
217 case SDEV_RUNNING:
218 + case SDEV_CREATED_BLOCK:
219 + break;
220 + default:
221 + goto illegal;
222 + }
223 + break;
224 +
225 + case SDEV_CREATED_BLOCK:
226 + switch (oldstate) {
227 + case SDEV_CREATED:
228 break;
229 default:
230 goto illegal;
231 @@ -2403,8 +2416,12 @@ scsi_internal_device_block(struct scsi_d
232 int err = 0;
233
234 err = scsi_device_set_state(sdev, SDEV_BLOCK);
235 - if (err)
236 - return err;
237 + if (err) {
238 + err = scsi_device_set_state(sdev, SDEV_CREATED_BLOCK);
239 +
240 + if (err)
241 + return err;
242 + }
243
244 /*
245 * The device has transitioned to SDEV_BLOCK. Stop the
246 @@ -2447,8 +2464,12 @@ scsi_internal_device_unblock(struct scsi
247 * and goose the device queue if successful.
248 */
249 err = scsi_device_set_state(sdev, SDEV_RUNNING);
250 - if (err)
251 - return err;
252 + if (err) {
253 + err = scsi_device_set_state(sdev, SDEV_CREATED);
254 +
255 + if (err)
256 + return err;
257 + }
258
259 spin_lock_irqsave(q->queue_lock, flags);
260 blk_start_queue(q);
261 --- a/drivers/scsi/scsi_netlink.c
262 +++ b/drivers/scsi/scsi_netlink.c
263 @@ -21,6 +21,7 @@
264 #include <linux/time.h>
265 #include <linux/jiffies.h>
266 #include <linux/security.h>
267 +#include <linux/delay.h>
268 #include <net/sock.h>
269 #include <net/netlink.h>
270
271 @@ -30,6 +31,39 @@
272 struct sock *scsi_nl_sock = NULL;
273 EXPORT_SYMBOL_GPL(scsi_nl_sock);
274
275 +static DEFINE_SPINLOCK(scsi_nl_lock);
276 +static struct list_head scsi_nl_drivers;
277 +
278 +static u32 scsi_nl_state;
279 +#define STATE_EHANDLER_BSY 0x00000001
280 +
281 +struct scsi_nl_transport {
282 + int (*msg_handler)(struct sk_buff *);
283 + void (*event_handler)(struct notifier_block *, unsigned long, void *);
284 + unsigned int refcnt;
285 + int flags;
286 +};
287 +
288 +/* flags values (bit flags) */
289 +#define HANDLER_DELETING 0x1
290 +
291 +static struct scsi_nl_transport transports[SCSI_NL_MAX_TRANSPORTS] =
292 + { {NULL, }, };
293 +
294 +
295 +struct scsi_nl_drvr {
296 + struct list_head next;
297 + int (*dmsg_handler)(struct Scsi_Host *shost, void *payload,
298 + u32 len, u32 pid);
299 + void (*devt_handler)(struct notifier_block *nb,
300 + unsigned long event, void *notify_ptr);
301 + struct scsi_host_template *hostt;
302 + u64 vendor_id;
303 + unsigned int refcnt;
304 + int flags;
305 +};
306 +
307 +
308
309 /**
310 * scsi_nl_rcv_msg - Receive message handler.
311 @@ -45,8 +79,9 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
312 {
313 struct nlmsghdr *nlh;
314 struct scsi_nl_hdr *hdr;
315 - uint32_t rlen;
316 - int err;
317 + unsigned long flags;
318 + u32 rlen;
319 + int err, tport;
320
321 while (skb->len >= NLMSG_SPACE(0)) {
322 err = 0;
323 @@ -65,7 +100,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
324
325 if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) {
326 err = -EBADMSG;
327 - return;
328 + goto next_msg;
329 }
330
331 hdr = NLMSG_DATA(nlh);
332 @@ -83,12 +118,27 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
333 if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) {
334 printk(KERN_WARNING "%s: discarding partial message\n",
335 __func__);
336 - return;
337 + goto next_msg;
338 }
339
340 /*
341 - * We currently don't support anyone sending us a message
342 + * Deliver message to the appropriate transport
343 */
344 + spin_lock_irqsave(&scsi_nl_lock, flags);
345 +
346 + tport = hdr->transport;
347 + if ((tport < SCSI_NL_MAX_TRANSPORTS) &&
348 + !(transports[tport].flags & HANDLER_DELETING) &&
349 + (transports[tport].msg_handler)) {
350 + transports[tport].refcnt++;
351 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
352 + err = transports[tport].msg_handler(skb);
353 + spin_lock_irqsave(&scsi_nl_lock, flags);
354 + transports[tport].refcnt--;
355 + } else
356 + err = -ENOENT;
357 +
358 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
359
360 next_msg:
361 if ((err) || (nlh->nlmsg_flags & NLM_F_ACK))
362 @@ -110,14 +160,42 @@ static int
363 scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr)
364 {
365 struct netlink_notify *n = ptr;
366 + struct scsi_nl_drvr *driver;
367 + unsigned long flags;
368 + int tport;
369
370 if (n->protocol != NETLINK_SCSITRANSPORT)
371 return NOTIFY_DONE;
372
373 + spin_lock_irqsave(&scsi_nl_lock, flags);
374 + scsi_nl_state |= STATE_EHANDLER_BSY;
375 +
376 + /*
377 + * Pass event on to any transports that may be listening
378 + */
379 + for (tport = 0; tport < SCSI_NL_MAX_TRANSPORTS; tport++) {
380 + if (!(transports[tport].flags & HANDLER_DELETING) &&
381 + (transports[tport].event_handler)) {
382 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
383 + transports[tport].event_handler(this, event, ptr);
384 + spin_lock_irqsave(&scsi_nl_lock, flags);
385 + }
386 + }
387 +
388 /*
389 - * Currently, we are not tracking PID's, etc. There is nothing
390 - * to handle.
391 + * Pass event on to any drivers that may be listening
392 */
393 + list_for_each_entry(driver, &scsi_nl_drivers, next) {
394 + if (!(driver->flags & HANDLER_DELETING) &&
395 + (driver->devt_handler)) {
396 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
397 + driver->devt_handler(this, event, ptr);
398 + spin_lock_irqsave(&scsi_nl_lock, flags);
399 + }
400 + }
401 +
402 + scsi_nl_state &= ~STATE_EHANDLER_BSY;
403 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
404
405 return NOTIFY_DONE;
406 }
407 @@ -128,7 +206,281 @@ static struct notifier_block scsi_netlin
408
409
410 /**
411 - * scsi_netlink_init - Called by SCSI subsystem to intialize the SCSI transport netlink interface
412 + * GENERIC SCSI transport receive and event handlers
413 + **/
414 +
415 +/**
416 + * scsi_generic_msg_handler - receive message handler for GENERIC transport
417 + * messages
418 + *
419 + * @skb: socket receive buffer
420 + *
421 + **/
422 +static int
423 +scsi_generic_msg_handler(struct sk_buff *skb)
424 +{
425 + struct nlmsghdr *nlh = nlmsg_hdr(skb);
426 + struct scsi_nl_hdr *snlh = NLMSG_DATA(nlh);
427 + struct scsi_nl_drvr *driver;
428 + struct Scsi_Host *shost;
429 + unsigned long flags;
430 + int err = 0, match, pid;
431 +
432 + pid = NETLINK_CREDS(skb)->pid;
433 +
434 + switch (snlh->msgtype) {
435 + case SCSI_NL_SHOST_VENDOR:
436 + {
437 + struct scsi_nl_host_vendor_msg *msg = NLMSG_DATA(nlh);
438 +
439 + /* Locate the driver that corresponds to the message */
440 + spin_lock_irqsave(&scsi_nl_lock, flags);
441 + match = 0;
442 + list_for_each_entry(driver, &scsi_nl_drivers, next) {
443 + if (driver->vendor_id == msg->vendor_id) {
444 + match = 1;
445 + break;
446 + }
447 + }
448 +
449 + if ((!match) || (!driver->dmsg_handler)) {
450 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
451 + err = -ESRCH;
452 + goto rcv_exit;
453 + }
454 +
455 + if (driver->flags & HANDLER_DELETING) {
456 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
457 + err = -ESHUTDOWN;
458 + goto rcv_exit;
459 + }
460 +
461 + driver->refcnt++;
462 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
463 +
464 +
465 + /* if successful, scsi_host_lookup takes a shost reference */
466 + shost = scsi_host_lookup(msg->host_no);
467 + if (!shost) {
468 + err = -ENODEV;
469 + goto driver_exit;
470 + }
471 +
472 + /* is this host owned by the vendor ? */
473 + if (shost->hostt != driver->hostt) {
474 + err = -EINVAL;
475 + goto vendormsg_put;
476 + }
477 +
478 + /* pass message on to the driver */
479 + err = driver->dmsg_handler(shost, (void *)&msg[1],
480 + msg->vmsg_datalen, pid);
481 +
482 +vendormsg_put:
483 + /* release reference by scsi_host_lookup */
484 + scsi_host_put(shost);
485 +
486 +driver_exit:
487 + /* release our own reference on the registration object */
488 + spin_lock_irqsave(&scsi_nl_lock, flags);
489 + driver->refcnt--;
490 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
491 + break;
492 + }
493 +
494 + default:
495 + err = -EBADR;
496 + break;
497 + }
498 +
499 +rcv_exit:
500 + if (err)
501 + printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n",
502 + __func__, snlh->msgtype, err);
503 + return err;
504 +}
505 +
506 +
507 +/**
508 + * scsi_nl_add_transport -
509 + * Registers message and event handlers for a transport. Enables
510 + * receipt of netlink messages and events to a transport.
511 + *
512 + * @tport: transport registering handlers
513 + * @msg_handler: receive message handler callback
514 + * @event_handler: receive event handler callback
515 + **/
516 +int
517 +scsi_nl_add_transport(u8 tport,
518 + int (*msg_handler)(struct sk_buff *),
519 + void (*event_handler)(struct notifier_block *, unsigned long, void *))
520 +{
521 + unsigned long flags;
522 + int err = 0;
523 +
524 + if (tport >= SCSI_NL_MAX_TRANSPORTS)
525 + return -EINVAL;
526 +
527 + spin_lock_irqsave(&scsi_nl_lock, flags);
528 +
529 + if (scsi_nl_state & STATE_EHANDLER_BSY) {
530 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
531 + msleep(1);
532 + spin_lock_irqsave(&scsi_nl_lock, flags);
533 + }
534 +
535 + if (transports[tport].msg_handler || transports[tport].event_handler) {
536 + err = -EALREADY;
537 + goto register_out;
538 + }
539 +
540 + transports[tport].msg_handler = msg_handler;
541 + transports[tport].event_handler = event_handler;
542 + transports[tport].flags = 0;
543 + transports[tport].refcnt = 0;
544 +
545 +register_out:
546 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
547 +
548 + return err;
549 +}
550 +EXPORT_SYMBOL_GPL(scsi_nl_add_transport);
551 +
552 +
553 +/**
554 + * scsi_nl_remove_transport -
555 + * Disable transport receiption of messages and events
556 + *
557 + * @tport: transport deregistering handlers
558 + *
559 + **/
560 +void
561 +scsi_nl_remove_transport(u8 tport)
562 +{
563 + unsigned long flags;
564 +
565 + spin_lock_irqsave(&scsi_nl_lock, flags);
566 + if (scsi_nl_state & STATE_EHANDLER_BSY) {
567 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
568 + msleep(1);
569 + spin_lock_irqsave(&scsi_nl_lock, flags);
570 + }
571 +
572 + if (tport < SCSI_NL_MAX_TRANSPORTS) {
573 + transports[tport].flags |= HANDLER_DELETING;
574 +
575 + while (transports[tport].refcnt != 0) {
576 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
577 + schedule_timeout_uninterruptible(HZ/4);
578 + spin_lock_irqsave(&scsi_nl_lock, flags);
579 + }
580 + transports[tport].msg_handler = NULL;
581 + transports[tport].event_handler = NULL;
582 + transports[tport].flags = 0;
583 + }
584 +
585 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
586 +
587 + return;
588 +}
589 +EXPORT_SYMBOL_GPL(scsi_nl_remove_transport);
590 +
591 +
592 +/**
593 + * scsi_nl_add_driver -
594 + * A driver is registering its interfaces for SCSI netlink messages
595 + *
596 + * @vendor_id: A unique identification value for the driver.
597 + * @hostt: address of the driver's host template. Used
598 + * to verify an shost is bound to the driver
599 + * @nlmsg_handler: receive message handler callback
600 + * @nlevt_handler: receive event handler callback
601 + *
602 + * Returns:
603 + * 0 on Success
604 + * error result otherwise
605 + **/
606 +int
607 +scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt,
608 + int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload,
609 + u32 len, u32 pid),
610 + void (*nlevt_handler)(struct notifier_block *nb,
611 + unsigned long event, void *notify_ptr))
612 +{
613 + struct scsi_nl_drvr *driver;
614 + unsigned long flags;
615 +
616 + driver = kzalloc(sizeof(*driver), GFP_KERNEL);
617 + if (unlikely(!driver)) {
618 + printk(KERN_ERR "%s: allocation failure\n", __func__);
619 + return -ENOMEM;
620 + }
621 +
622 + driver->dmsg_handler = nlmsg_handler;
623 + driver->devt_handler = nlevt_handler;
624 + driver->hostt = hostt;
625 + driver->vendor_id = vendor_id;
626 +
627 + spin_lock_irqsave(&scsi_nl_lock, flags);
628 + if (scsi_nl_state & STATE_EHANDLER_BSY) {
629 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
630 + msleep(1);
631 + spin_lock_irqsave(&scsi_nl_lock, flags);
632 + }
633 + list_add_tail(&driver->next, &scsi_nl_drivers);
634 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
635 +
636 + return 0;
637 +}
638 +EXPORT_SYMBOL_GPL(scsi_nl_add_driver);
639 +
640 +
641 +/**
642 + * scsi_nl_remove_driver -
643 + * An driver is unregistering with the SCSI netlink messages
644 + *
645 + * @vendor_id: The unique identification value for the driver.
646 + **/
647 +void
648 +scsi_nl_remove_driver(u64 vendor_id)
649 +{
650 + struct scsi_nl_drvr *driver;
651 + unsigned long flags;
652 +
653 + spin_lock_irqsave(&scsi_nl_lock, flags);
654 + if (scsi_nl_state & STATE_EHANDLER_BSY) {
655 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
656 + msleep(1);
657 + spin_lock_irqsave(&scsi_nl_lock, flags);
658 + }
659 +
660 + list_for_each_entry(driver, &scsi_nl_drivers, next) {
661 + if (driver->vendor_id == vendor_id) {
662 + driver->flags |= HANDLER_DELETING;
663 + while (driver->refcnt != 0) {
664 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
665 + schedule_timeout_uninterruptible(HZ/4);
666 + spin_lock_irqsave(&scsi_nl_lock, flags);
667 + }
668 + list_del(&driver->next);
669 + kfree(driver);
670 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
671 + return;
672 + }
673 + }
674 +
675 + spin_unlock_irqrestore(&scsi_nl_lock, flags);
676 +
677 + printk(KERN_ERR "%s: removal of driver failed - vendor_id 0x%llx\n",
678 + __func__, (unsigned long long)vendor_id);
679 + return;
680 +}
681 +EXPORT_SYMBOL_GPL(scsi_nl_remove_driver);
682 +
683 +
684 +/**
685 + * scsi_netlink_init - Called by SCSI subsystem to intialize
686 + * the SCSI transport netlink interface
687 *
688 **/
689 void
690 @@ -136,6 +488,8 @@ scsi_netlink_init(void)
691 {
692 int error;
693
694 + INIT_LIST_HEAD(&scsi_nl_drivers);
695 +
696 error = netlink_register_notifier(&scsi_netlink_notifier);
697 if (error) {
698 printk(KERN_ERR "%s: register of event handler failed - %d\n",
699 @@ -150,8 +504,15 @@ scsi_netlink_init(void)
700 printk(KERN_ERR "%s: register of recieve handler failed\n",
701 __func__);
702 netlink_unregister_notifier(&scsi_netlink_notifier);
703 + return;
704 }
705
706 + /* Register the entry points for the generic SCSI transport */
707 + error = scsi_nl_add_transport(SCSI_NL_TRANSPORT,
708 + scsi_generic_msg_handler, NULL);
709 + if (error)
710 + printk(KERN_ERR "%s: register of GENERIC transport handler"
711 + " failed - %d\n", __func__, error);
712 return;
713 }
714
715 @@ -163,6 +524,8 @@ scsi_netlink_init(void)
716 void
717 scsi_netlink_exit(void)
718 {
719 + scsi_nl_remove_transport(SCSI_NL_TRANSPORT);
720 +
721 if (scsi_nl_sock) {
722 netlink_kernel_release(scsi_nl_sock);
723 netlink_unregister_notifier(&scsi_netlink_notifier);
724 @@ -172,3 +535,147 @@ scsi_netlink_exit(void)
725 }
726
727
728 +/*
729 + * Exported Interfaces
730 + */
731 +
732 +/**
733 + * scsi_nl_send_transport_msg -
734 + * Generic function to send a single message from a SCSI transport to
735 + * a single process
736 + *
737 + * @pid: receiving pid
738 + * @hdr: message payload
739 + *
740 + **/
741 +void
742 +scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr)
743 +{
744 + struct sk_buff *skb;
745 + struct nlmsghdr *nlh;
746 + const char *fn;
747 + char *datab;
748 + u32 len, skblen;
749 + int err;
750 +
751 + if (!scsi_nl_sock) {
752 + err = -ENOENT;
753 + fn = "netlink socket";
754 + goto msg_fail;
755 + }
756 +
757 + len = NLMSG_SPACE(hdr->msglen);
758 + skblen = NLMSG_SPACE(len);
759 +
760 + skb = alloc_skb(skblen, GFP_KERNEL);
761 + if (!skb) {
762 + err = -ENOBUFS;
763 + fn = "alloc_skb";
764 + goto msg_fail;
765 + }
766 +
767 + nlh = nlmsg_put(skb, pid, 0, SCSI_TRANSPORT_MSG, len - sizeof(*nlh), 0);
768 + if (!nlh) {
769 + err = -ENOBUFS;
770 + fn = "nlmsg_put";
771 + goto msg_fail_skb;
772 + }
773 + datab = NLMSG_DATA(nlh);
774 + memcpy(datab, hdr, hdr->msglen);
775 +
776 + err = nlmsg_unicast(scsi_nl_sock, skb, pid);
777 + if (err < 0) {
778 + fn = "nlmsg_unicast";
779 + /* nlmsg_unicast already kfree_skb'd */
780 + goto msg_fail;
781 + }
782 +
783 + return;
784 +
785 +msg_fail_skb:
786 + kfree_skb(skb);
787 +msg_fail:
788 + printk(KERN_WARNING
789 + "%s: Dropped Message : pid %d Transport %d, msgtype x%x, "
790 + "msglen %d: %s : err %d\n",
791 + __func__, pid, hdr->transport, hdr->msgtype, hdr->msglen,
792 + fn, err);
793 + return;
794 +}
795 +EXPORT_SYMBOL_GPL(scsi_nl_send_transport_msg);
796 +
797 +
798 +/**
799 + * scsi_nl_send_vendor_msg - called to send a shost vendor unique message
800 + * to a specific process id.
801 + *
802 + * @pid: process id of the receiver
803 + * @host_no: host # sending the message
804 + * @vendor_id: unique identifier for the driver's vendor
805 + * @data_len: amount, in bytes, of vendor unique payload data
806 + * @data_buf: pointer to vendor unique data buffer
807 + *
808 + * Returns:
809 + * 0 on succesful return
810 + * otherwise, failing error code
811 + *
812 + * Notes:
813 + * This routine assumes no locks are held on entry.
814 + */
815 +int
816 +scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id,
817 + char *data_buf, u32 data_len)
818 +{
819 + struct sk_buff *skb;
820 + struct nlmsghdr *nlh;
821 + struct scsi_nl_host_vendor_msg *msg;
822 + u32 len, skblen;
823 + int err;
824 +
825 + if (!scsi_nl_sock) {
826 + err = -ENOENT;
827 + goto send_vendor_fail;
828 + }
829 +
830 + len = SCSI_NL_MSGALIGN(sizeof(*msg) + data_len);
831 + skblen = NLMSG_SPACE(len);
832 +
833 + skb = alloc_skb(skblen, GFP_KERNEL);
834 + if (!skb) {
835 + err = -ENOBUFS;
836 + goto send_vendor_fail;
837 + }
838 +
839 + nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG,
840 + skblen - sizeof(*nlh), 0);
841 + if (!nlh) {
842 + err = -ENOBUFS;
843 + goto send_vendor_fail_skb;
844 + }
845 + msg = NLMSG_DATA(nlh);
846 +
847 + INIT_SCSI_NL_HDR(&msg->snlh, SCSI_NL_TRANSPORT,
848 + SCSI_NL_SHOST_VENDOR, len);
849 + msg->vendor_id = vendor_id;
850 + msg->host_no = host_no;
851 + msg->vmsg_datalen = data_len; /* bytes */
852 + memcpy(&msg[1], data_buf, data_len);
853 +
854 + err = nlmsg_unicast(scsi_nl_sock, skb, pid);
855 + if (err)
856 + /* nlmsg_multicast already kfree_skb'd */
857 + goto send_vendor_fail;
858 +
859 + return 0;
860 +
861 +send_vendor_fail_skb:
862 + kfree_skb(skb);
863 +send_vendor_fail:
864 + printk(KERN_WARNING
865 + "%s: Dropped SCSI Msg : host %d vendor_unique - err %d\n",
866 + __func__, host_no, err);
867 + return err;
868 +}
869 +EXPORT_SYMBOL(scsi_nl_send_vendor_msg);
870 +
871 +
872 --- a/drivers/scsi/scsi_scan.c
873 +++ b/drivers/scsi/scsi_scan.c
874 @@ -730,6 +730,8 @@ static int scsi_probe_lun(struct scsi_de
875 static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
876 int *bflags, int async)
877 {
878 + int ret;
879 +
880 /*
881 * XXX do not save the inquiry, since it can change underneath us,
882 * save just vendor/model/rev.
883 @@ -885,7 +887,17 @@ static int scsi_add_lun(struct scsi_devi
884
885 /* set the device running here so that slave configure
886 * may do I/O */
887 - scsi_device_set_state(sdev, SDEV_RUNNING);
888 + ret = scsi_device_set_state(sdev, SDEV_RUNNING);
889 + if (ret) {
890 + ret = scsi_device_set_state(sdev, SDEV_BLOCK);
891 +
892 + if (ret) {
893 + sdev_printk(KERN_ERR, sdev,
894 + "in wrong state %s to complete scan\n",
895 + scsi_device_state_name(sdev->sdev_state));
896 + return SCSI_SCAN_NO_RESPONSE;
897 + }
898 + }
899
900 if (*bflags & BLIST_MS_192_BYTES_FOR_3F)
901 sdev->use_192_bytes_for_3f = 1;
902 @@ -899,7 +911,7 @@ static int scsi_add_lun(struct scsi_devi
903 transport_configure_device(&sdev->sdev_gendev);
904
905 if (sdev->host->hostt->slave_configure) {
906 - int ret = sdev->host->hostt->slave_configure(sdev);
907 + ret = sdev->host->hostt->slave_configure(sdev);
908 if (ret) {
909 /*
910 * if LLDD reports slave not present, don't clutter
911 @@ -994,7 +1006,7 @@ static int scsi_probe_and_add_lun(struct
912 */
913 sdev = scsi_device_lookup_by_target(starget, lun);
914 if (sdev) {
915 - if (rescan || sdev->sdev_state != SDEV_CREATED) {
916 + if (rescan || !scsi_device_created(sdev)) {
917 SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
918 "scsi scan: device exists on %s\n",
919 sdev->sdev_gendev.bus_id));
920 @@ -1467,7 +1479,7 @@ static int scsi_report_lun_scan(struct s
921 kfree(lun_data);
922 out:
923 scsi_device_put(sdev);
924 - if (sdev->sdev_state == SDEV_CREATED)
925 + if (scsi_device_created(sdev))
926 /*
927 * the sdev we used didn't appear in the report luns scan
928 */
929 --- a/drivers/scsi/scsi_sysfs.c
930 +++ b/drivers/scsi/scsi_sysfs.c
931 @@ -34,6 +34,7 @@ static const struct {
932 { SDEV_QUIESCE, "quiesce" },
933 { SDEV_OFFLINE, "offline" },
934 { SDEV_BLOCK, "blocked" },
935 + { SDEV_CREATED_BLOCK, "created-blocked" },
936 };
937
938 const char *scsi_device_state_name(enum scsi_device_state state)
939 --- a/drivers/scsi/scsi_transport_fc.c
940 +++ b/drivers/scsi/scsi_transport_fc.c
941 @@ -40,31 +40,7 @@
942
943 static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
944 static void fc_vport_sched_delete(struct work_struct *work);
945 -
946 -/*
947 - * This is a temporary carrier for creating a vport. It will eventually
948 - * be replaced by a real message definition for sgio or netlink.
949 - *
950 - * fc_vport_identifiers: This set of data contains all elements
951 - * to uniquely identify and instantiate a FC virtual port.
952 - *
953 - * Notes:
954 - * symbolic_name: The driver is to append the symbolic_name string data
955 - * to the symbolic_node_name data that it generates by default.
956 - * the resulting combination should then be registered with the switch.
957 - * It is expected that things like Xen may stuff a VM title into
958 - * this field.
959 - */
960 -struct fc_vport_identifiers {
961 - u64 node_name;
962 - u64 port_name;
963 - u32 roles;
964 - bool disable;
965 - enum fc_port_type vport_type; /* only FC_PORTTYPE_NPIV allowed */
966 - char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
967 -};
968 -
969 -static int fc_vport_create(struct Scsi_Host *shost, int channel,
970 +static int fc_vport_setup(struct Scsi_Host *shost, int channel,
971 struct device *pdev, struct fc_vport_identifiers *ids,
972 struct fc_vport **vport);
973
974 @@ -1760,7 +1736,7 @@ store_fc_host_vport_create(struct device
975 vid.disable = false; /* always enabled */
976
977 /* we only allow support on Channel 0 !!! */
978 - stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport);
979 + stat = fc_vport_setup(shost, 0, &shost->shost_gendev, &vid, &vport);
980 return stat ? stat : count;
981 }
982 static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
983 @@ -3103,7 +3079,7 @@ fc_scsi_scan_rport(struct work_struct *w
984
985
986 /**
987 - * fc_vport_create - allocates and creates a FC virtual port.
988 + * fc_vport_setup - allocates and creates a FC virtual port.
989 * @shost: scsi host the virtual port is connected to.
990 * @channel: Channel on shost port connected to.
991 * @pdev: parent device for vport
992 @@ -3118,7 +3094,7 @@ fc_scsi_scan_rport(struct work_struct *w
993 * This routine assumes no locks are held on entry.
994 */
995 static int
996 -fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev,
997 +fc_vport_setup(struct Scsi_Host *shost, int channel, struct device *pdev,
998 struct fc_vport_identifiers *ids, struct fc_vport **ret_vport)
999 {
1000 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
1001 @@ -3231,6 +3207,28 @@ delete_vport:
1002 return error;
1003 }
1004
1005 +/**
1006 + * fc_vport_create - Admin App or LLDD requests creation of a vport
1007 + * @shost: scsi host the virtual port is connected to.
1008 + * @channel: channel on shost port connected to.
1009 + * @ids: The world wide names, FC4 port roles, etc for
1010 + * the virtual port.
1011 + *
1012 + * Notes:
1013 + * This routine assumes no locks are held on entry.
1014 + */
1015 +struct fc_vport *
1016 +fc_vport_create(struct Scsi_Host *shost, int channel,
1017 + struct fc_vport_identifiers *ids)
1018 +{
1019 + int stat;
1020 + struct fc_vport *vport;
1021 +
1022 + stat = fc_vport_setup(shost, channel, &shost->shost_gendev,
1023 + ids, &vport);
1024 + return stat ? NULL : vport;
1025 +}
1026 +EXPORT_SYMBOL(fc_vport_create);
1027
1028 /**
1029 * fc_vport_terminate - Admin App or LLDD requests termination of a vport
1030 --- a/drivers/scsi/sd.c
1031 +++ b/drivers/scsi/sd.c
1032 @@ -47,6 +47,7 @@
1033 #include <linux/blkpg.h>
1034 #include <linux/delay.h>
1035 #include <linux/mutex.h>
1036 +#include <linux/string_helpers.h>
1037 #include <asm/uaccess.h>
1038
1039 #include <scsi/scsi.h>
1040 @@ -1436,27 +1437,21 @@ got_data:
1041 */
1042 sector_size = 512;
1043 }
1044 + blk_queue_hardsect_size(sdp->request_queue, sector_size);
1045 +
1046 {
1047 - /*
1048 - * The msdos fs needs to know the hardware sector size
1049 - * So I have created this table. See ll_rw_blk.c
1050 - * Jacques Gelinas (Jacques@solucorp.qc.ca)
1051 - */
1052 - int hard_sector = sector_size;
1053 - sector_t sz = (sdkp->capacity/2) * (hard_sector/256);
1054 - struct request_queue *queue = sdp->request_queue;
1055 - sector_t mb = sz;
1056 -
1057 - blk_queue_hardsect_size(queue, hard_sector);
1058 - /* avoid 64-bit division on 32-bit platforms */
1059 - sector_div(sz, 625);
1060 - mb -= sz - 974;
1061 - sector_div(mb, 1950);
1062 + char cap_str_2[10], cap_str_10[10];
1063 + u64 sz = sdkp->capacity << ffz(~sector_size);
1064 +
1065 + string_get_size(sz, STRING_UNITS_2, cap_str_2,
1066 + sizeof(cap_str_2));
1067 + string_get_size(sz, STRING_UNITS_10, cap_str_10,
1068 + sizeof(cap_str_10));
1069
1070 sd_printk(KERN_NOTICE, sdkp,
1071 - "%llu %d-byte hardware sectors (%llu MB)\n",
1072 + "%llu %d-byte hardware sectors: (%s/%s)\n",
1073 (unsigned long long)sdkp->capacity,
1074 - hard_sector, (unsigned long long)mb);
1075 + sector_size, cap_str_10, cap_str_2);
1076 }
1077
1078 /* Rescale capacity to 512-byte units */
1079 --- /dev/null
1080 +++ b/include/linux/string_helpers.h
1081 @@ -0,0 +1,16 @@
1082 +#ifndef _LINUX_STRING_HELPERS_H_
1083 +#define _LINUX_STRING_HELPERS_H_
1084 +
1085 +#include <linux/types.h>
1086 +
1087 +/* Descriptions of the types of units to
1088 + * print in */
1089 +enum string_size_units {
1090 + STRING_UNITS_10, /* use powers of 10^3 (standard SI) */
1091 + STRING_UNITS_2, /* use binary powers of 2^10 */
1092 +};
1093 +
1094 +int string_get_size(u64 size, enum string_size_units units,
1095 + char *buf, int len);
1096 +
1097 +#endif
1098 --- a/include/scsi/scsi_device.h
1099 +++ b/include/scsi/scsi_device.h
1100 @@ -42,9 +42,11 @@ enum scsi_device_state {
1101 * originate in the mid-layer) */
1102 SDEV_OFFLINE, /* Device offlined (by error handling or
1103 * user request */
1104 - SDEV_BLOCK, /* Device blocked by scsi lld. No scsi
1105 - * commands from user or midlayer should be issued
1106 - * to the scsi lld. */
1107 + SDEV_BLOCK, /* Device blocked by scsi lld. No
1108 + * scsi commands from user or midlayer
1109 + * should be issued to the scsi
1110 + * lld. */
1111 + SDEV_CREATED_BLOCK, /* same as above but for created devices */
1112 };
1113
1114 enum scsi_device_event {
1115 @@ -384,10 +386,23 @@ static inline unsigned int sdev_id(struc
1116 #define scmd_id(scmd) sdev_id((scmd)->device)
1117 #define scmd_channel(scmd) sdev_channel((scmd)->device)
1118
1119 +/*
1120 + * checks for positions of the SCSI state machine
1121 + */
1122 static inline int scsi_device_online(struct scsi_device *sdev)
1123 {
1124 return sdev->sdev_state != SDEV_OFFLINE;
1125 }
1126 +static inline int scsi_device_blocked(struct scsi_device *sdev)
1127 +{
1128 + return sdev->sdev_state == SDEV_BLOCK ||
1129 + sdev->sdev_state == SDEV_CREATED_BLOCK;
1130 +}
1131 +static inline int scsi_device_created(struct scsi_device *sdev)
1132 +{
1133 + return sdev->sdev_state == SDEV_CREATED ||
1134 + sdev->sdev_state == SDEV_CREATED_BLOCK;
1135 +}
1136
1137 /* accessor functions for the SCSI parameters */
1138 static inline int scsi_device_sync(struct scsi_device *sdev)
1139 --- a/include/scsi/scsi_netlink.h
1140 +++ b/include/scsi/scsi_netlink.h
1141 @@ -22,6 +22,9 @@
1142 #ifndef SCSI_NETLINK_H
1143 #define SCSI_NETLINK_H
1144
1145 +#include <linux/netlink.h>
1146 +
1147 +
1148 /*
1149 * This file intended to be included by both kernel and user space
1150 */
1151 @@ -55,7 +58,41 @@ struct scsi_nl_hdr {
1152 #define SCSI_NL_TRANSPORT_FC 1
1153 #define SCSI_NL_MAX_TRANSPORTS 2
1154
1155 -/* scsi_nl_hdr->msgtype values are defined in each transport */
1156 +/* Transport-based scsi_nl_hdr->msgtype values are defined in each transport */
1157 +
1158 +/*
1159 + * GENERIC SCSI scsi_nl_hdr->msgtype Values
1160 + */
1161 + /* kernel -> user */
1162 +#define SCSI_NL_SHOST_VENDOR 0x0001
1163 + /* user -> kernel */
1164 +/* SCSI_NL_SHOST_VENDOR msgtype is kernel->user and user->kernel */
1165 +
1166 +
1167 +/*
1168 + * Message Structures :
1169 + */
1170 +
1171 +/* macro to round up message lengths to 8byte boundary */
1172 +#define SCSI_NL_MSGALIGN(len) (((len) + 7) & ~7)
1173 +
1174 +
1175 +/*
1176 + * SCSI HOST Vendor Unique messages :
1177 + * SCSI_NL_SHOST_VENDOR
1178 + *
1179 + * Note: The Vendor Unique message payload will begin directly after
1180 + * this structure, with the length of the payload per vmsg_datalen.
1181 + *
1182 + * Note: When specifying vendor_id, be sure to read the Vendor Type and ID
1183 + * formatting requirements specified below
1184 + */
1185 +struct scsi_nl_host_vendor_msg {
1186 + struct scsi_nl_hdr snlh; /* must be 1st element ! */
1187 + uint64_t vendor_id;
1188 + uint16_t host_no;
1189 + uint16_t vmsg_datalen;
1190 +} __attribute__((aligned(sizeof(uint64_t))));
1191
1192
1193 /*
1194 @@ -83,5 +120,28 @@ struct scsi_nl_hdr {
1195 }
1196
1197
1198 +#ifdef __KERNEL__
1199 +
1200 +#include <scsi/scsi_host.h>
1201 +
1202 +/* Exported Kernel Interfaces */
1203 +int scsi_nl_add_transport(u8 tport,
1204 + int (*msg_handler)(struct sk_buff *),
1205 + void (*event_handler)(struct notifier_block *, unsigned long, void *));
1206 +void scsi_nl_remove_transport(u8 tport);
1207 +
1208 +int scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt,
1209 + int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload,
1210 + u32 len, u32 pid),
1211 + void (*nlevt_handler)(struct notifier_block *nb,
1212 + unsigned long event, void *notify_ptr));
1213 +void scsi_nl_remove_driver(u64 vendor_id);
1214 +
1215 +void scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr);
1216 +int scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id,
1217 + char *data_buf, u32 data_len);
1218 +
1219 +#endif /* __KERNEL__ */
1220 +
1221 #endif /* SCSI_NETLINK_H */
1222
1223 --- a/include/scsi/scsi_transport_fc.h
1224 +++ b/include/scsi/scsi_transport_fc.h
1225 @@ -167,6 +167,26 @@ enum fc_tgtid_binding_type {
1226 struct device_attribute dev_attr_vport_##_name = \
1227 __ATTR(_name,_mode,_show,_store)
1228
1229 +/*
1230 + * fc_vport_identifiers: This set of data contains all elements
1231 + * to uniquely identify and instantiate a FC virtual port.
1232 + *
1233 + * Notes:
1234 + * symbolic_name: The driver is to append the symbolic_name string data
1235 + * to the symbolic_node_name data that it generates by default.
1236 + * the resulting combination should then be registered with the switch.
1237 + * It is expected that things like Xen may stuff a VM title into
1238 + * this field.
1239 + */
1240 +#define FC_VPORT_SYMBOLIC_NAMELEN 64
1241 +struct fc_vport_identifiers {
1242 + u64 node_name;
1243 + u64 port_name;
1244 + u32 roles;
1245 + bool disable;
1246 + enum fc_port_type vport_type; /* only FC_PORTTYPE_NPIV allowed */
1247 + char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
1248 +};
1249
1250 /*
1251 * FC Virtual Port Attributes
1252 @@ -197,7 +217,6 @@ struct device_attribute dev_attr_vport_#
1253 * managed by the transport w/o driver interaction.
1254 */
1255
1256 -#define FC_VPORT_SYMBOLIC_NAMELEN 64
1257 struct fc_vport {
1258 /* Fixed Attributes */
1259
1260 @@ -732,6 +751,8 @@ void fc_host_post_vendor_event(struct Sc
1261 * be sure to read the Vendor Type and ID formatting requirements
1262 * specified in scsi_netlink.h
1263 */
1264 +struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel,
1265 + struct fc_vport_identifiers *);
1266 int fc_vport_terminate(struct fc_vport *vport);
1267
1268 #endif /* SCSI_TRANSPORT_FC_H */
1269 --- a/lib/Makefile
1270 +++ b/lib/Makefile
1271 @@ -19,7 +19,8 @@ lib-$(CONFIG_SMP) += cpumask.o
1272 lib-y += kobject.o kref.o klist.o
1273
1274 obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
1275 - bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o
1276 + bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
1277 + string_helpers.o
1278
1279 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
1280 CFLAGS_kobject.o += -DDEBUG
1281 --- /dev/null
1282 +++ b/lib/string_helpers.c
1283 @@ -0,0 +1,64 @@
1284 +/*
1285 + * Helpers for formatting and printing strings
1286 + *
1287 + * Copyright 31 August 2008 James Bottomley
1288 + */
1289 +#include <linux/kernel.h>
1290 +#include <linux/math64.h>
1291 +#include <linux/module.h>
1292 +#include <linux/string_helpers.h>
1293 +
1294 +/**
1295 + * string_get_size - get the size in the specified units
1296 + * @size: The size to be converted
1297 + * @units: units to use (powers of 1000 or 1024)
1298 + * @buf: buffer to format to
1299 + * @len: length of buffer
1300 + *
1301 + * This function returns a string formatted to 3 significant figures
1302 + * giving the size in the required units. Returns 0 on success or
1303 + * error on failure. @buf is always zero terminated.
1304 + *
1305 + */
1306 +int string_get_size(u64 size, const enum string_size_units units,
1307 + char *buf, int len)
1308 +{
1309 + const char *units_10[] = { "B", "KB", "MB", "GB", "TB", "PB",
1310 + "EB", "ZB", "YB", NULL};
1311 + const char *units_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB",
1312 + "EiB", "ZiB", "YiB", NULL };
1313 + const char **units_str[] = {
1314 + [STRING_UNITS_10] = units_10,
1315 + [STRING_UNITS_2] = units_2,
1316 + };
1317 + const int divisor[] = {
1318 + [STRING_UNITS_10] = 1000,
1319 + [STRING_UNITS_2] = 1024,
1320 + };
1321 + int i, j;
1322 + u64 remainder = 0, sf_cap;
1323 + char tmp[8];
1324 +
1325 + tmp[0] = '\0';
1326 +
1327 + for (i = 0; size > divisor[units] && units_str[units][i]; i++)
1328 + remainder = do_div(size, divisor[units]);
1329 +
1330 + sf_cap = size;
1331 + for (j = 0; sf_cap*10 < 1000; j++)
1332 + sf_cap *= 10;
1333 +
1334 + if (j) {
1335 + remainder *= 1000;
1336 + do_div(remainder, divisor[units]);
1337 + snprintf(tmp, sizeof(tmp), ".%03lld",
1338 + (unsigned long long)remainder);
1339 + tmp[j+1] = '\0';
1340 + }
1341 +
1342 + snprintf(buf, len, "%lld%s%s", (unsigned long long)size,
1343 + tmp, units_str[units][i]);
1344 +
1345 + return 0;
1346 +}
1347 +EXPORT_SYMBOL(string_get_size);