virthba.c revision 79014eb1f25e145ea0dc70c628d1ad24106afba3
1/* virthba.c 2 * 3 * Copyright (C) 2010 - 2013 UNISYS CORPORATION 4 * All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or (at 9 * your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 14 * NON INFRINGEMENT. See the GNU General Public License for more 15 * details. 16 */ 17 18#define EXPORT_SYMTAB 19 20/* if you want to turn on some debugging of write device data or read 21 * device data, define these two undefs. You will probably want to 22 * customize the code which is here since it was written assuming 23 * reading and writing a specific data file df.64M.txt which is a 24 * 64Megabyte file created by Art Nilson using a scritp I wrote called 25 * cr_test_data.pl. The data file consists of 256 byte lines of text 26 * which start with an 8 digit sequence number, a colon, and then 27 * letters after that */ 28 29#undef DBGINF 30 31#include <linux/kernel.h> 32#ifdef CONFIG_MODVERSIONS 33#include <config/modversions.h> 34#endif 35 36#include "uniklog.h" 37#include "diagnostics/appos_subsystems.h" 38#include "uisutils.h" 39#include "uisqueue.h" 40#include "uisthread.h" 41 42#include <linux/module.h> 43#include <linux/init.h> 44#include <linux/pci.h> 45#include <linux/spinlock.h> 46#include <linux/device.h> 47#include <linux/slab.h> 48#include <scsi/scsi.h> 49#include <scsi/scsi_host.h> 50#include <scsi/scsi_cmnd.h> 51#include <scsi/scsi_device.h> 52#include <asm/param.h> 53#include <linux/debugfs.h> 54#include <linux/types.h> 55 56#include "virthba.h" 57#include "virtpci.h" 58#include "visorchipset.h" 59#include "version.h" 60#include "guestlinuxdebug.h" 61/* this is shorter than using __FILE__ (full path name) in 62 * debug/info/error messages 63 */ 64#define CURRENT_FILE_PC VIRT_HBA_PC_virthba_c 65#define __MYFILE__ "virthba.c" 66 67/* NOTE: L1_CACHE_BYTES >=128 */ 68#define DEVICE_ATTRIBUTE struct device_attribute 69 70 /* MAX_BUF = 6 lines x 10 MAXVHBA x 80 characters 71 * = 4800 bytes ~ 2^13 = 8192 bytes 72 */ 73#define MAX_BUF 8192 74 75/*****************************************************/ 76/* Forward declarations */ 77/*****************************************************/ 78static int virthba_probe(struct virtpci_dev *dev, 79 const struct pci_device_id *id); 80static void virthba_remove(struct virtpci_dev *dev); 81static int virthba_abort_handler(struct scsi_cmnd *scsicmd); 82static int virthba_bus_reset_handler(struct scsi_cmnd *scsicmd); 83static int virthba_device_reset_handler(struct scsi_cmnd *scsicmd); 84static int virthba_host_reset_handler(struct scsi_cmnd *scsicmd); 85static const char *virthba_get_info(struct Scsi_Host *shp); 86static int virthba_ioctl(struct scsi_device *dev, int cmd, void __user *arg); 87static int virthba_queue_command_lck(struct scsi_cmnd *scsicmd, 88 void (*virthba_cmnd_done)(struct scsi_cmnd *)); 89 90static const struct x86_cpu_id unisys_spar_ids[] = { 91 { X86_VENDOR_INTEL, 6, 62, X86_FEATURE_ANY }, 92 {} 93}; 94 95/* Autoload */ 96MODULE_DEVICE_TABLE(x86cpu, unisys_spar_ids); 97 98#ifdef DEF_SCSI_QCMD 99static DEF_SCSI_QCMD(virthba_queue_command) 100#else 101#define virthba_queue_command virthba_queue_command_lck 102#endif 103 104 105static int virthba_slave_alloc(struct scsi_device *scsidev); 106static int virthba_slave_configure(struct scsi_device *scsidev); 107static void virthba_slave_destroy(struct scsi_device *scsidev); 108static int process_incoming_rsps(void *); 109static int virthba_serverup(struct virtpci_dev *virtpcidev); 110static int virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state); 111static void doDiskAddRemove(struct work_struct *work); 112static void virthba_serverdown_complete(struct work_struct *work); 113static ssize_t info_debugfs_read(struct file *file, char __user *buf, 114 size_t len, loff_t *offset); 115static ssize_t enable_ints_write(struct file *file, 116 const char __user *buffer, size_t count, loff_t *ppos); 117 118/*****************************************************/ 119/* Globals */ 120/*****************************************************/ 121 122static int rsltq_wait_usecs = 4000; /* Default 4ms */ 123static unsigned int MaxBuffLen; 124 125/* Module options */ 126static char *virthba_options = "NONE"; 127 128static const struct pci_device_id virthba_id_table[] = { 129 {PCI_DEVICE(PCI_VENDOR_ID_UNISYS, PCI_DEVICE_ID_VIRTHBA)}, 130 {0}, 131}; 132 133/* export virthba_id_table */ 134MODULE_DEVICE_TABLE(pci, virthba_id_table); 135 136static struct workqueue_struct *virthba_serverdown_workqueue; 137 138static struct virtpci_driver virthba_driver = { 139 .name = "uisvirthba", 140 .version = VERSION, 141 .vertag = NULL, 142 .id_table = virthba_id_table, 143 .probe = virthba_probe, 144 .remove = virthba_remove, 145 .resume = virthba_serverup, 146 .suspend = virthba_serverdown 147}; 148 149/* The Send and Recive Buffers of the IO Queue may both be full */ 150#define MAX_PENDING_REQUESTS (MIN_NUMSIGNALS*2) 151#define INTERRUPT_VECTOR_MASK 0x3F 152 153struct scsipending { 154 char cmdtype; /* Type of pointer that is being stored */ 155 void *sent; /* The Data being tracked */ 156 /* struct scsi_cmnd *type for virthba_queue_command */ 157 /* struct uiscmdrsp *type for management commands */ 158}; 159 160#define VIRTHBA_ERROR_COUNT 30 161#define IOS_ERROR_THRESHOLD 1000 162struct virtdisk_info { 163 U32 valid; 164 U32 channel, id, lun; /* Disk Path */ 165 atomic_t ios_threshold; 166 atomic_t error_count; 167 struct virtdisk_info *next; 168}; 169/* Each Scsi_Host has a host_data area that contains this struct. */ 170struct virthba_info { 171 struct Scsi_Host *scsihost; 172 struct virtpci_dev *virtpcidev; 173 struct list_head dev_info_list; 174 struct chaninfo chinfo; 175 struct InterruptInfo intr; /* use recvInterrupt info to receive 176 interrupts when IOs complete */ 177 int interrupt_vector; 178 struct scsipending pending[MAX_PENDING_REQUESTS]; /* Tracks the requests 179 that have been */ 180 /* forwarded to the IOVM and haven't returned yet */ 181 unsigned int nextinsert; /* Start search for next pending 182 free slot here */ 183 spinlock_t privlock; 184 bool serverdown; 185 bool serverchangingstate; 186 unsigned long long acquire_failed_cnt; 187 unsigned long long interrupts_rcvd; 188 unsigned long long interrupts_notme; 189 unsigned long long interrupts_disabled; 190 struct work_struct serverdown_completion; 191 U64 __iomem *flags_addr; 192 atomic_t interrupt_rcvd; 193 wait_queue_head_t rsp_queue; 194 struct virtdisk_info head; 195}; 196 197/* Work Data for DARWorkQ */ 198struct diskaddremove { 199 U8 add; /* 0-remove, 1-add */ 200 struct Scsi_Host *shost; /* Scsi Host for this virthba instance */ 201 U32 channel, id, lun; /* Disk Path */ 202 struct diskaddremove *next; 203}; 204 205#define virtpci_dev_to_virthba_virthba_get_info(d) \ 206 container_of(d, struct virthba_info, virtpcidev) 207 208static DEVICE_ATTRIBUTE *virthba_shost_attrs[]; 209static struct scsi_host_template virthba_driver_template = { 210 .name = "Unisys Virtual HBA", 211 .info = virthba_get_info, 212 .ioctl = virthba_ioctl, 213 .queuecommand = virthba_queue_command, 214 .eh_abort_handler = virthba_abort_handler, 215 .eh_device_reset_handler = virthba_device_reset_handler, 216 .eh_bus_reset_handler = virthba_bus_reset_handler, 217 .eh_host_reset_handler = virthba_host_reset_handler, 218 .shost_attrs = virthba_shost_attrs, 219 220#define VIRTHBA_MAX_CMNDS 128 221 .can_queue = VIRTHBA_MAX_CMNDS, 222 .sg_tablesize = 64, /* largest number of address/length pairs */ 223 .this_id = -1, 224 .slave_alloc = virthba_slave_alloc, 225 .slave_configure = virthba_slave_configure, 226 .slave_destroy = virthba_slave_destroy, 227 .use_clustering = ENABLE_CLUSTERING, 228}; 229 230struct virthba_devices_open { 231 struct virthba_info *virthbainfo; 232}; 233 234static const struct file_operations debugfs_info_fops = { 235 .read = info_debugfs_read, 236}; 237 238static const struct file_operations debugfs_enable_ints_fops = { 239 .write = enable_ints_write, 240}; 241 242/*****************************************************/ 243/* Structs */ 244/*****************************************************/ 245 246#define VIRTHBASOPENMAX 1 247/* array of open devices maintained by open() and close(); */ 248static struct virthba_devices_open VirtHbasOpen[VIRTHBASOPENMAX]; 249static struct dentry *virthba_debugfs_dir; 250 251/*****************************************************/ 252/* Local Functions */ 253/*****************************************************/ 254static int 255add_scsipending_entry(struct virthba_info *vhbainfo, char cmdtype, void *new) 256{ 257 unsigned long flags; 258 int insert_location; 259 260 spin_lock_irqsave(&vhbainfo->privlock, flags); 261 insert_location = vhbainfo->nextinsert; 262 while (vhbainfo->pending[insert_location].sent != NULL) { 263 insert_location = (insert_location + 1) % MAX_PENDING_REQUESTS; 264 if (insert_location == (int) vhbainfo->nextinsert) { 265 LOGERR("Queue should be full. insert_location<<%d>> Unable to find open slot for pending commands.\n", 266 insert_location); 267 spin_unlock_irqrestore(&vhbainfo->privlock, flags); 268 return -1; 269 } 270 } 271 272 vhbainfo->pending[insert_location].cmdtype = cmdtype; 273 vhbainfo->pending[insert_location].sent = new; 274 vhbainfo->nextinsert = (insert_location + 1) % MAX_PENDING_REQUESTS; 275 spin_unlock_irqrestore(&vhbainfo->privlock, flags); 276 277 return insert_location; 278} 279 280static unsigned int 281add_scsipending_entry_with_wait(struct virthba_info *vhbainfo, char cmdtype, 282 void *new) 283{ 284 int insert_location = add_scsipending_entry(vhbainfo, cmdtype, new); 285 286 while (insert_location == -1) { 287 LOGERR("Failed to find empty queue slot. Waiting to try again\n"); 288 set_current_state(TASK_INTERRUPTIBLE); 289 schedule_timeout(msecs_to_jiffies(10)); 290 insert_location = add_scsipending_entry(vhbainfo, cmdtype, new); 291 } 292 293 return (unsigned int) insert_location; 294} 295 296static void * 297del_scsipending_entry(struct virthba_info *vhbainfo, uintptr_t del) 298{ 299 unsigned long flags; 300 void *sent = NULL; 301 302 if (del >= MAX_PENDING_REQUESTS) { 303 LOGERR("Invalid queue position <<%lu>> given to delete. MAX_PENDING_REQUESTS <<%d>>\n", 304 (unsigned long) del, MAX_PENDING_REQUESTS); 305 } else { 306 spin_lock_irqsave(&vhbainfo->privlock, flags); 307 308 if (vhbainfo->pending[del].sent == NULL) 309 LOGERR("Deleting already cleared queue entry at <<%lu>>.\n", 310 (unsigned long) del); 311 312 sent = vhbainfo->pending[del].sent; 313 314 vhbainfo->pending[del].cmdtype = 0; 315 vhbainfo->pending[del].sent = NULL; 316 spin_unlock_irqrestore(&vhbainfo->privlock, flags); 317 } 318 319 return sent; 320} 321 322/* DARWorkQ (Disk Add/Remove) */ 323static struct work_struct DARWorkQ; 324static struct diskaddremove *DARWorkQHead; 325static spinlock_t DARWorkQLock; 326static unsigned short DARWorkQSched; 327#define QUEUE_DISKADDREMOVE(dar) { \ 328 spin_lock_irqsave(&DARWorkQLock, flags); \ 329 if (!DARWorkQHead) { \ 330 DARWorkQHead = dar; \ 331 dar->next = NULL; \ 332 } \ 333 else { \ 334 dar->next = DARWorkQHead; \ 335 DARWorkQHead = dar; \ 336 } \ 337 if (!DARWorkQSched) { \ 338 schedule_work(&DARWorkQ); \ 339 DARWorkQSched = 1; \ 340 } \ 341 spin_unlock_irqrestore(&DARWorkQLock, flags); \ 342} 343 344static inline void 345SendDiskAddRemove(struct diskaddremove *dar) 346{ 347 struct scsi_device *sdev; 348 int error; 349 350 sdev = scsi_device_lookup(dar->shost, dar->channel, dar->id, dar->lun); 351 if (sdev) { 352 if (!(dar->add)) 353 scsi_remove_device(sdev); 354 } else if (dar->add) { 355 error = 356 scsi_add_device(dar->shost, dar->channel, dar->id, 357 dar->lun); 358 if (error) 359 LOGERR("Failed scsi_add_device: host_no=%d[chan=%d:id=%d:lun=%d]\n", 360 dar->shost->host_no, dar->channel, dar->id, 361 dar->lun); 362 } else 363 LOGERR("Failed scsi_device_lookup:[chan=%d:id=%d:lun=%d]\n", 364 dar->channel, dar->id, dar->lun); 365 kfree(dar); 366} 367 368/*****************************************************/ 369/* DARWorkQ Handler Thread */ 370/*****************************************************/ 371static void 372doDiskAddRemove(struct work_struct *work) 373{ 374 struct diskaddremove *dar; 375 struct diskaddremove *tmphead; 376 int i = 0; 377 unsigned long flags; 378 379 spin_lock_irqsave(&DARWorkQLock, flags); 380 tmphead = DARWorkQHead; 381 DARWorkQHead = NULL; 382 DARWorkQSched = 0; 383 spin_unlock_irqrestore(&DARWorkQLock, flags); 384 while (tmphead) { 385 dar = tmphead; 386 tmphead = dar->next; 387 SendDiskAddRemove(dar); 388 i++; 389 } 390} 391 392/*****************************************************/ 393/* Routine to add entry to DARWorkQ */ 394/*****************************************************/ 395static void 396process_disk_notify(struct Scsi_Host *shost, struct uiscmdrsp *cmdrsp) 397{ 398 struct diskaddremove *dar; 399 unsigned long flags; 400 401 dar = kzalloc(sizeof(struct diskaddremove), GFP_ATOMIC); 402 if (dar) { 403 dar->add = cmdrsp->disknotify.add; 404 dar->shost = shost; 405 dar->channel = cmdrsp->disknotify.channel; 406 dar->id = cmdrsp->disknotify.id; 407 dar->lun = cmdrsp->disknotify.lun; 408 QUEUE_DISKADDREMOVE(dar); 409 } else { 410 LOGERR("kmalloc failed for dar. host_no=%d[chan=%d:id=%d:lun=%d]\n", 411 shost->host_no, cmdrsp->disknotify.channel, 412 cmdrsp->disknotify.id, cmdrsp->disknotify.lun); 413 } 414} 415 416/*****************************************************/ 417/* Probe Remove Functions */ 418/*****************************************************/ 419static irqreturn_t 420virthba_ISR(int irq, void *dev_id) 421{ 422 struct virthba_info *virthbainfo = (struct virthba_info *) dev_id; 423 CHANNEL_HEADER __iomem *pChannelHeader; 424 SIGNAL_QUEUE_HEADER __iomem *pqhdr; 425 U64 mask; 426 unsigned long long rc1; 427 428 if (virthbainfo == NULL) 429 return IRQ_NONE; 430 virthbainfo->interrupts_rcvd++; 431 pChannelHeader = virthbainfo->chinfo.queueinfo->chan; 432 if (((readq(&pChannelHeader->Features) 433 & ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS) != 0) 434 && ((readq(&pChannelHeader->Features) & 435 ULTRA_IO_DRIVER_DISABLES_INTS) != 436 0)) { 437 virthbainfo->interrupts_disabled++; 438 mask = ~ULTRA_CHANNEL_ENABLE_INTS; 439 rc1 = uisqueue_InterlockedAnd(virthbainfo->flags_addr, mask); 440 } 441 if (visor_signalqueue_empty(pChannelHeader, IOCHAN_FROM_IOPART)) { 442 virthbainfo->interrupts_notme++; 443 return IRQ_NONE; 444 } 445 pqhdr = (SIGNAL_QUEUE_HEADER __iomem *) 446 ((char __iomem *) pChannelHeader + 447 readq(&pChannelHeader->oChannelSpace)) + IOCHAN_FROM_IOPART; 448 writeq(readq(&pqhdr->NumInterruptsReceived) + 1, 449 &pqhdr->NumInterruptsReceived); 450 atomic_set(&virthbainfo->interrupt_rcvd, 1); 451 wake_up_interruptible(&virthbainfo->rsp_queue); 452 return IRQ_HANDLED; 453} 454 455static int 456virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) 457{ 458 int error; 459 struct Scsi_Host *scsihost; 460 struct virthba_info *virthbainfo; 461 int rsp; 462 int i; 463 irq_handler_t handler = virthba_ISR; 464 CHANNEL_HEADER __iomem *pChannelHeader; 465 SIGNAL_QUEUE_HEADER __iomem *pqhdr; 466 U64 mask; 467 468 LOGVER("entering virthba_probe...\n"); 469 LOGVER("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo, 470 virtpcidev->deviceNo); 471 472 LOGINF("entering virthba_probe...\n"); 473 LOGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo, 474 virtpcidev->deviceNo); 475 POSTCODE_LINUX_2(VHBA_PROBE_ENTRY_PC, POSTCODE_SEVERITY_INFO); 476 /* call scsi_host_alloc to register a scsi host adapter 477 * instance - this virthba that has just been created is an 478 * instance of a scsi host adapter. This scsi_host_alloc 479 * function allocates a new Scsi_Host struct & performs basic 480 * initializatoin. The host is not published to the scsi 481 * midlayer until scsi_add_host is called. 482 */ 483 DBGINF("calling scsi_host_alloc.\n"); 484 485 /* arg 2 passed in length of extra space we want allocated 486 * with scsi_host struct for our own use scsi_host_alloc 487 * assign host_no 488 */ 489 scsihost = scsi_host_alloc(&virthba_driver_template, 490 sizeof(struct virthba_info)); 491 if (scsihost == NULL) 492 return -ENODEV; 493 494 DBGINF("scsihost: 0x%p, scsihost->this_id: %d, host_no: %d.\n", 495 scsihost, scsihost->this_id, scsihost->host_no); 496 497 scsihost->this_id = UIS_MAGIC_VHBA; 498 /* linux treats max-channel differently than max-id & max-lun. 499 * In the latter cases, those two values result in 0 to max-1 500 * (inclusive) being scanned. But in the case of channels, the 501 * scan is 0 to max (inclusive); so we will subtract one from 502 * the max-channel value. 503 */ 504 LOGINF("virtpcidev->scsi.max.max_channel=%u, max_id=%u, max_lun=%u, cmd_per_lun=%u, max_io_size=%u\n", 505 (unsigned) virtpcidev->scsi.max.max_channel - 1, 506 (unsigned) virtpcidev->scsi.max.max_id, 507 (unsigned) virtpcidev->scsi.max.max_lun, 508 (unsigned) virtpcidev->scsi.max.cmd_per_lun, 509 (unsigned) virtpcidev->scsi.max.max_io_size); 510 scsihost->max_channel = (unsigned) virtpcidev->scsi.max.max_channel; 511 scsihost->max_id = (unsigned) virtpcidev->scsi.max.max_id; 512 scsihost->max_lun = (unsigned) virtpcidev->scsi.max.max_lun; 513 scsihost->cmd_per_lun = (unsigned) virtpcidev->scsi.max.cmd_per_lun; 514 scsihost->max_sectors = 515 (unsigned short) (virtpcidev->scsi.max.max_io_size >> 9); 516 scsihost->sg_tablesize = 517 (unsigned short) (virtpcidev->scsi.max.max_io_size / PAGE_SIZE); 518 if (scsihost->sg_tablesize > MAX_PHYS_INFO) 519 scsihost->sg_tablesize = MAX_PHYS_INFO; 520 LOGINF("scsihost->max_channel=%u, max_id=%u, max_lun=%u, cmd_per_lun=%u, max_sectors=%hu, sg_tablesize=%hu\n", 521 scsihost->max_channel, scsihost->max_id, scsihost->max_lun, 522 scsihost->cmd_per_lun, scsihost->max_sectors, 523 scsihost->sg_tablesize); 524 LOGINF("scsihost->can_queue=%u, scsihost->cmd_per_lun=%u, max_sectors=%hu, sg_tablesize=%hu\n", 525 scsihost->can_queue, scsihost->cmd_per_lun, scsihost->max_sectors, 526 scsihost->sg_tablesize); 527 528 DBGINF("calling scsi_add_host\n"); 529 530 /* this creates "host%d" in sysfs. If 2nd argument is NULL, 531 * then this generic /sys/devices/platform/host? device is 532 * created and /sys/scsi_host/host? -> 533 * /sys/devices/platform/host? If 2nd argument is not NULL, 534 * then this generic /sys/devices/<path>/host? is created and 535 * host? points to that device instead. 536 */ 537 error = scsi_add_host(scsihost, &virtpcidev->generic_dev); 538 if (error) { 539 LOGERR("scsi_add_host ****FAILED 0x%x TBD - RECOVER\n", error); 540 POSTCODE_LINUX_2(VHBA_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR); 541 /* decr refcount on scsihost which was incremented by 542 * scsi_add_host so the scsi_host gets deleted 543 */ 544 scsi_host_put(scsihost); 545 return -ENODEV; 546 } 547 548 virthbainfo = (struct virthba_info *) scsihost->hostdata; 549 memset(virthbainfo, 0, sizeof(struct virthba_info)); 550 for (i = 0; i < VIRTHBASOPENMAX; i++) { 551 if (VirtHbasOpen[i].virthbainfo == NULL) { 552 VirtHbasOpen[i].virthbainfo = virthbainfo; 553 break; 554 } 555 } 556 virthbainfo->interrupt_vector = -1; 557 virthbainfo->chinfo.queueinfo = &virtpcidev->queueinfo; 558 virthbainfo->virtpcidev = virtpcidev; 559 spin_lock_init(&virthbainfo->chinfo.insertlock); 560 561 DBGINF("generic_dev: 0x%p, queueinfo: 0x%p.\n", 562 &virtpcidev->generic_dev, &virtpcidev->queueinfo); 563 564 init_waitqueue_head(&virthbainfo->rsp_queue); 565 spin_lock_init(&virthbainfo->privlock); 566 memset(&virthbainfo->pending, 0, sizeof(virthbainfo->pending)); 567 virthbainfo->serverdown = false; 568 virthbainfo->serverchangingstate = false; 569 570 virthbainfo->intr = virtpcidev->intr; 571 /* save of host within virthba_info */ 572 virthbainfo->scsihost = scsihost; 573 574 /* save of host within virtpci_dev */ 575 virtpcidev->scsi.scsihost = scsihost; 576 577 /* Setup workqueue for serverdown messages */ 578 INIT_WORK(&virthbainfo->serverdown_completion, 579 virthba_serverdown_complete); 580 581 writeq(readq(&virthbainfo->chinfo.queueinfo->chan->Features) | 582 ULTRA_IO_CHANNEL_IS_POLLING, 583 &virthbainfo->chinfo.queueinfo->chan->Features); 584 /* start thread that will receive scsicmnd responses */ 585 DBGINF("starting rsp thread -- queueinfo: 0x%p, threadinfo: 0x%p.\n", 586 virthbainfo->chinfo.queueinfo, &virthbainfo->chinfo.threadinfo); 587 588 pChannelHeader = virthbainfo->chinfo.queueinfo->chan; 589 pqhdr = (SIGNAL_QUEUE_HEADER __iomem *) 590 ((char __iomem *)pChannelHeader + 591 readq(&pChannelHeader->oChannelSpace)) + IOCHAN_FROM_IOPART; 592 virthbainfo->flags_addr = &pqhdr->FeatureFlags; 593 594 if (!uisthread_start(&virthbainfo->chinfo.threadinfo, 595 process_incoming_rsps, 596 virthbainfo, "vhba_incoming")) { 597 LOGERR("uisthread_start rsp ****FAILED\n"); 598 /* decr refcount on scsihost which was incremented by 599 * scsi_add_host so the scsi_host gets deleted 600 */ 601 POSTCODE_LINUX_2(VHBA_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR); 602 scsi_host_put(scsihost); 603 return -ENODEV; 604 } 605 LOGINF("sendInterruptHandle=0x%16llX", 606 virthbainfo->intr.sendInterruptHandle); 607 LOGINF("recvInterruptHandle=0x%16llX", 608 virthbainfo->intr.recvInterruptHandle); 609 LOGINF("recvInterruptVector=0x%8X", 610 virthbainfo->intr.recvInterruptVector); 611 LOGINF("recvInterruptShared=0x%2X", 612 virthbainfo->intr.recvInterruptShared); 613 LOGINF("scsihost.hostt->name=%s", scsihost->hostt->name); 614 virthbainfo->interrupt_vector = 615 virthbainfo->intr.recvInterruptHandle & INTERRUPT_VECTOR_MASK; 616 rsp = request_irq(virthbainfo->interrupt_vector, handler, IRQF_SHARED, 617 scsihost->hostt->name, virthbainfo); 618 if (rsp != 0) { 619 LOGERR("request_irq(%d) uislib_virthba_ISR request failed with rsp=%d\n", 620 virthbainfo->interrupt_vector, rsp); 621 virthbainfo->interrupt_vector = -1; 622 POSTCODE_LINUX_2(VHBA_PROBE_FAILURE_PC, POSTCODE_SEVERITY_ERR); 623 } else { 624 U64 __iomem *Features_addr = 625 &virthbainfo->chinfo.queueinfo->chan->Features; 626 LOGERR("request_irq(%d) uislib_virthba_ISR request succeeded\n", 627 virthbainfo->interrupt_vector); 628 mask = ~(ULTRA_IO_CHANNEL_IS_POLLING | 629 ULTRA_IO_DRIVER_DISABLES_INTS); 630 uisqueue_InterlockedAnd(Features_addr, mask); 631 mask = ULTRA_IO_DRIVER_ENABLES_INTS; 632 uisqueue_InterlockedOr(Features_addr, mask); 633 rsltq_wait_usecs = 4000000; 634 } 635 636 DBGINF("calling scsi_scan_host.\n"); 637 scsi_scan_host(scsihost); 638 DBGINF("return from scsi_scan_host.\n"); 639 640 LOGINF("virthba added scsihost:0x%p\n", scsihost); 641 POSTCODE_LINUX_2(VHBA_PROBE_EXIT_PC, POSTCODE_SEVERITY_INFO); 642 return 0; 643} 644 645static void 646virthba_remove(struct virtpci_dev *virtpcidev) 647{ 648 struct virthba_info *virthbainfo; 649 struct Scsi_Host *scsihost = 650 (struct Scsi_Host *) virtpcidev->scsi.scsihost; 651 652 LOGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo, 653 virtpcidev->deviceNo); 654 virthbainfo = (struct virthba_info *) scsihost->hostdata; 655 if (virthbainfo->interrupt_vector != -1) 656 free_irq(virthbainfo->interrupt_vector, virthbainfo); 657 LOGINF("Removing virtpcidev: 0x%p, virthbainfo: 0x%p\n", virtpcidev, 658 virthbainfo); 659 660 DBGINF("removing scsihost: 0x%p, scsihost->this_id: %d\n", scsihost, 661 scsihost->this_id); 662 scsi_remove_host(scsihost); 663 664 DBGINF("stopping thread.\n"); 665 uisthread_stop(&virthbainfo->chinfo.threadinfo); 666 667 DBGINF("calling scsi_host_put\n"); 668 669 /* decr refcount on scsihost which was incremented by 670 * scsi_add_host so the scsi_host gets deleted 671 */ 672 scsi_host_put(scsihost); 673 LOGINF("virthba removed scsi_host.\n"); 674} 675 676static int 677forward_vdiskmgmt_command(VDISK_MGMT_TYPES vdiskcmdtype, 678 struct Scsi_Host *scsihost, 679 struct uisscsi_dest *vdest) 680{ 681 struct uiscmdrsp *cmdrsp; 682 struct virthba_info *virthbainfo = 683 (struct virthba_info *) scsihost->hostdata; 684 int notifyresult = 0xffff; 685 wait_queue_head_t notifyevent; 686 687 LOGINF("vDiskMgmt:%d %d:%d:%d\n", vdiskcmdtype, 688 vdest->channel, vdest->id, vdest->lun); 689 690 if (virthbainfo->serverdown || virthbainfo->serverchangingstate) { 691 DBGINF("Server is down/changing state. Returning Failure.\n"); 692 return FAILED; 693 } 694 695 cmdrsp = kzalloc(SIZEOF_CMDRSP, GFP_ATOMIC); 696 if (cmdrsp == NULL) { 697 LOGERR("kmalloc of cmdrsp failed.\n"); 698 return FAILED; /* reject */ 699 } 700 701 init_waitqueue_head(¬ifyevent); 702 703 /* issue VDISK_MGMT_CMD 704 * set type to command - as opposed to task mgmt 705 */ 706 cmdrsp->cmdtype = CMD_VDISKMGMT_TYPE; 707 /* specify the event that has to be triggered when this cmd is 708 * complete 709 */ 710 cmdrsp->vdiskmgmt.notify = (void *) ¬ifyevent; 711 cmdrsp->vdiskmgmt.notifyresult = (void *) ¬ifyresult; 712 713 /* save destination */ 714 cmdrsp->vdiskmgmt.vdisktype = vdiskcmdtype; 715 cmdrsp->vdiskmgmt.vdest.channel = vdest->channel; 716 cmdrsp->vdiskmgmt.vdest.id = vdest->id; 717 cmdrsp->vdiskmgmt.vdest.lun = vdest->lun; 718 cmdrsp->vdiskmgmt.scsicmd = 719 (void *) (uintptr_t) 720 add_scsipending_entry_with_wait(virthbainfo, CMD_VDISKMGMT_TYPE, 721 (void *) cmdrsp); 722 723 uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo, 724 cmdrsp, IOCHAN_TO_IOPART, 725 &virthbainfo->chinfo.insertlock, 726 DONT_ISSUE_INTERRUPT, (U64) NULL, 727 OK_TO_WAIT, "vhba"); 728 LOGINF("VdiskMgmt waiting on event notifyevent=0x%p\n", 729 cmdrsp->scsitaskmgmt.notify); 730 wait_event(notifyevent, notifyresult != 0xffff); 731 LOGINF("VdiskMgmt complete; result:%d\n", cmdrsp->vdiskmgmt.result); 732 kfree(cmdrsp); 733 return SUCCESS; 734} 735 736/*****************************************************/ 737/* Scsi Host support functions */ 738/*****************************************************/ 739 740static int 741forward_taskmgmt_command(TASK_MGMT_TYPES tasktype, struct scsi_device *scsidev) 742{ 743 struct uiscmdrsp *cmdrsp; 744 struct virthba_info *virthbainfo = 745 (struct virthba_info *) scsidev->host->hostdata; 746 int notifyresult = 0xffff; 747 wait_queue_head_t notifyevent; 748 749 LOGINF("TaskMgmt:%d %d:%d:%d\n", tasktype, 750 scsidev->channel, scsidev->id, scsidev->lun); 751 752 if (virthbainfo->serverdown || virthbainfo->serverchangingstate) { 753 DBGINF("Server is down/changing state. Returning Failure.\n"); 754 return FAILED; 755 } 756 757 cmdrsp = kzalloc(SIZEOF_CMDRSP, GFP_ATOMIC); 758 if (cmdrsp == NULL) { 759 LOGERR("kmalloc of cmdrsp failed.\n"); 760 return FAILED; /* reject */ 761 } 762 763 init_waitqueue_head(¬ifyevent); 764 765 /* issue TASK_MGMT_ABORT_TASK */ 766 /* set type to command - as opposed to task mgmt */ 767 cmdrsp->cmdtype = CMD_SCSITASKMGMT_TYPE; 768 /* specify the event that has to be triggered when this */ 769 /* cmd is complete */ 770 cmdrsp->scsitaskmgmt.notify = (void *) ¬ifyevent; 771 cmdrsp->scsitaskmgmt.notifyresult = (void *) ¬ifyresult; 772 773 /* save destination */ 774 cmdrsp->scsitaskmgmt.tasktype = tasktype; 775 cmdrsp->scsitaskmgmt.vdest.channel = scsidev->channel; 776 cmdrsp->scsitaskmgmt.vdest.id = scsidev->id; 777 cmdrsp->scsitaskmgmt.vdest.lun = scsidev->lun; 778 cmdrsp->scsitaskmgmt.scsicmd = 779 (void *) (uintptr_t) 780 add_scsipending_entry_with_wait(virthbainfo, 781 CMD_SCSITASKMGMT_TYPE, 782 (void *) cmdrsp); 783 784 uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo, 785 cmdrsp, IOCHAN_TO_IOPART, 786 &virthbainfo->chinfo.insertlock, 787 DONT_ISSUE_INTERRUPT, (U64) NULL, 788 OK_TO_WAIT, "vhba"); 789 LOGINF("TaskMgmt waiting on event notifyevent=0x%p\n", 790 cmdrsp->scsitaskmgmt.notify); 791 wait_event(notifyevent, notifyresult != 0xffff); 792 LOGINF("TaskMgmt complete; result:%d\n", cmdrsp->scsitaskmgmt.result); 793 kfree(cmdrsp); 794 return SUCCESS; 795} 796 797/* The abort handler returns SUCCESS if it has succeeded to make LLDD 798 * and all related hardware forget about the scmd. 799 */ 800static int 801virthba_abort_handler(struct scsi_cmnd *scsicmd) 802{ 803 /* issue TASK_MGMT_ABORT_TASK */ 804 struct scsi_device *scsidev; 805 struct virtdisk_info *vdisk; 806 807 scsidev = scsicmd->device; 808 for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head; 809 vdisk->next; vdisk = vdisk->next) { 810 if ((scsidev->channel == vdisk->channel) 811 && (scsidev->id == vdisk->id) 812 && (scsidev->lun == vdisk->lun)) { 813 if (atomic_read(&vdisk->error_count) < 814 VIRTHBA_ERROR_COUNT) { 815 atomic_inc(&vdisk->error_count); 816 POSTCODE_LINUX_2(VHBA_COMMAND_HANDLER_PC, 817 POSTCODE_SEVERITY_INFO); 818 } else 819 atomic_set(&vdisk->ios_threshold, 820 IOS_ERROR_THRESHOLD); 821 } 822 } 823 return forward_taskmgmt_command(TASK_MGMT_ABORT_TASK, scsicmd->device); 824} 825 826static int 827virthba_bus_reset_handler(struct scsi_cmnd *scsicmd) 828{ 829 /* issue TASK_MGMT_TARGET_RESET for each target on the bus */ 830 struct scsi_device *scsidev; 831 struct virtdisk_info *vdisk; 832 833 scsidev = scsicmd->device; 834 for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head; 835 vdisk->next; vdisk = vdisk->next) { 836 if ((scsidev->channel == vdisk->channel) 837 && (scsidev->id == vdisk->id) 838 && (scsidev->lun == vdisk->lun)) { 839 if (atomic_read(&vdisk->error_count) < 840 VIRTHBA_ERROR_COUNT) { 841 atomic_inc(&vdisk->error_count); 842 POSTCODE_LINUX_2(VHBA_COMMAND_HANDLER_PC, 843 POSTCODE_SEVERITY_INFO); 844 } else 845 atomic_set(&vdisk->ios_threshold, 846 IOS_ERROR_THRESHOLD); 847 } 848 } 849 return forward_taskmgmt_command(TASK_MGMT_BUS_RESET, scsicmd->device); 850} 851 852static int 853virthba_device_reset_handler(struct scsi_cmnd *scsicmd) 854{ 855 /* issue TASK_MGMT_LUN_RESET */ 856 struct scsi_device *scsidev; 857 struct virtdisk_info *vdisk; 858 859 scsidev = scsicmd->device; 860 for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head; 861 vdisk->next; vdisk = vdisk->next) { 862 if ((scsidev->channel == vdisk->channel) 863 && (scsidev->id == vdisk->id) 864 && (scsidev->lun == vdisk->lun)) { 865 if (atomic_read(&vdisk->error_count) < 866 VIRTHBA_ERROR_COUNT) { 867 atomic_inc(&vdisk->error_count); 868 POSTCODE_LINUX_2(VHBA_COMMAND_HANDLER_PC, 869 POSTCODE_SEVERITY_INFO); 870 } else 871 atomic_set(&vdisk->ios_threshold, 872 IOS_ERROR_THRESHOLD); 873 } 874 } 875 return forward_taskmgmt_command(TASK_MGMT_LUN_RESET, scsicmd->device); 876} 877 878static int 879virthba_host_reset_handler(struct scsi_cmnd *scsicmd) 880{ 881 /* issue TASK_MGMT_TARGET_RESET for each target on each bus for host */ 882 LOGERR("virthba_host_reset_handler Not yet implemented\n"); 883 return SUCCESS; 884} 885 886static char virthba_get_info_str[256]; 887 888static const char * 889virthba_get_info(struct Scsi_Host *shp) 890{ 891 /* Return version string */ 892 sprintf(virthba_get_info_str, "virthba, version %s\n", VIRTHBA_VERSION); 893 return virthba_get_info_str; 894} 895 896static int 897virthba_ioctl(struct scsi_device *dev, int cmd, void __user *arg) 898{ 899 DBGINF("In virthba_ioctl: ioctl: cmd=0x%x\n", cmd); 900 return -EINVAL; 901} 902 903/* This returns SCSI_MLQUEUE_DEVICE_BUSY if the signal queue to IOpart 904 * is full. 905 */ 906static int 907virthba_queue_command_lck(struct scsi_cmnd *scsicmd, 908 void (*virthba_cmnd_done)(struct scsi_cmnd *)) 909{ 910 struct scsi_device *scsidev = scsicmd->device; 911 int insert_location; 912 unsigned char op; 913 unsigned char *cdb = scsicmd->cmnd; 914 struct Scsi_Host *scsihost = scsidev->host; 915 struct uiscmdrsp *cmdrsp; 916 unsigned int i; 917 struct virthba_info *virthbainfo = 918 (struct virthba_info *) scsihost->hostdata; 919 struct scatterlist *sg = NULL; 920 struct scatterlist *sgl = NULL; 921 int sg_failed = 0; 922 923 if (virthbainfo->serverdown || virthbainfo->serverchangingstate) { 924 DBGINF("Server is down/changing state. Returning SCSI_MLQUEUE_DEVICE_BUSY.\n"); 925 return SCSI_MLQUEUE_DEVICE_BUSY; 926 } 927 928 cmdrsp = kzalloc(SIZEOF_CMDRSP, GFP_ATOMIC); 929 if (cmdrsp == NULL) { 930 LOGERR("kmalloc of cmdrsp failed.\n"); 931 return 1; /* reject the command */ 932 } 933 934 /* now saving everything we need from scsi_cmd into cmdrsp 935 * before we queue cmdrsp set type to command - as opposed to 936 * task mgmt 937 */ 938 cmdrsp->cmdtype = CMD_SCSI_TYPE; 939 /* save the pending insertion location. Deletion from pending 940 * will return the scsicmd pointer for completion 941 */ 942 insert_location = 943 add_scsipending_entry(virthbainfo, CMD_SCSI_TYPE, (void *) scsicmd); 944 if (insert_location != -1) { 945 cmdrsp->scsi.scsicmd = (void *) (uintptr_t) insert_location; 946 } else { 947 LOGERR("Queue is full. Returning busy.\n"); 948 kfree(cmdrsp); 949 return SCSI_MLQUEUE_DEVICE_BUSY; 950 } 951 /* save done function that we have call when cmd is complete */ 952 scsicmd->scsi_done = virthba_cmnd_done; 953 /* save destination */ 954 cmdrsp->scsi.vdest.channel = scsidev->channel; 955 cmdrsp->scsi.vdest.id = scsidev->id; 956 cmdrsp->scsi.vdest.lun = scsidev->lun; 957 /* save datadir */ 958 cmdrsp->scsi.data_dir = scsicmd->sc_data_direction; 959 memcpy(cmdrsp->scsi.cmnd, cdb, MAX_CMND_SIZE); 960 961 cmdrsp->scsi.bufflen = scsi_bufflen(scsicmd); 962 963 /* keep track of the max buffer length so far. */ 964 if (cmdrsp->scsi.bufflen > MaxBuffLen) 965 MaxBuffLen = cmdrsp->scsi.bufflen; 966 967 if (scsi_sg_count(scsicmd) > MAX_PHYS_INFO) { 968 LOGERR("scsicmd use_sg:%d greater than MAX:%d\n", 969 scsi_sg_count(scsicmd), MAX_PHYS_INFO); 970 del_scsipending_entry(virthbainfo, (uintptr_t) insert_location); 971 kfree(cmdrsp); 972 return 1; /* reject the command */ 973 } 974 975 /* This is what we USED to do when we assumed we were running */ 976 /* uissd & virthba on the same Linux system. */ 977 /* cmdrsp->scsi.buffer = scsicmd->request_buffer; */ 978 /* The following code does NOT make that assumption. */ 979 /* convert buffer to phys information */ 980 if (scsi_sg_count(scsicmd) == 0) { 981 if (scsi_bufflen(scsicmd) > 0) { 982 LOGERR("**** FAILED No scatter list for bufflen > 0\n"); 983 BUG_ON(scsi_sg_count(scsicmd) == 0); 984 } 985 DBGINF("No sg; buffer:0x%p bufflen:%d\n", 986 scsi_sglist(scsicmd), scsi_bufflen(scsicmd)); 987 } else { 988 /* buffer is scatterlist - copy it out */ 989 sgl = scsi_sglist(scsicmd); 990 991 for_each_sg(sgl, sg, scsi_sg_count(scsicmd), i) { 992 993 cmdrsp->scsi.gpi_list[i].address = sg_phys(sg); 994 cmdrsp->scsi.gpi_list[i].length = sg->length; 995 if ((i != 0) && (sg->offset != 0)) 996 LOGINF("Offset on a sg_entry other than zero =<<%d>>.\n", 997 sg->offset); 998 } 999 1000 if (sg_failed) { 1001 LOGERR("Start sg_list dump (entries %d, bufflen %d)...\n", 1002 scsi_sg_count(scsicmd), cmdrsp->scsi.bufflen); 1003 for_each_sg(sgl, sg, scsi_sg_count(scsicmd), i) { 1004 LOGERR(" Entry(%d): page->[0x%p], phys->[0x%Lx], off(%d), len(%d)\n", 1005 i, sg_page(sg), 1006 (unsigned long long) sg_phys(sg), 1007 sg->offset, sg->length); 1008 } 1009 LOGERR("Done sg_list dump.\n"); 1010 /* BUG(); ***** For now, let it fail in uissd 1011 * if it is a problem, as it might just 1012 * work 1013 */ 1014 } 1015 1016 cmdrsp->scsi.guest_phys_entries = scsi_sg_count(scsicmd); 1017 } 1018 1019 op = cdb[0]; 1020 i = uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo, 1021 cmdrsp, IOCHAN_TO_IOPART, 1022 &virthbainfo->chinfo. 1023 insertlock, 1024 DONT_ISSUE_INTERRUPT, 1025 (U64) NULL, DONT_WAIT, "vhba"); 1026 if (i == 0) { 1027 /* queue must be full - and we said don't wait - return busy */ 1028 LOGERR("uisqueue_put_cmdrsp_with_lock ****FAILED\n"); 1029 kfree(cmdrsp); 1030 del_scsipending_entry(virthbainfo, (uintptr_t) insert_location); 1031 return SCSI_MLQUEUE_DEVICE_BUSY; 1032 } 1033 1034 /* we're done with cmdrsp space - data from it has been copied 1035 * into channel - free it now. 1036 */ 1037 kfree(cmdrsp); 1038 return 0; /* non-zero implies host/device is busy */ 1039} 1040 1041static int 1042virthba_slave_alloc(struct scsi_device *scsidev) 1043{ 1044 /* this called by the midlayer before scan for new devices - 1045 * LLD can alloc any struct & do init if needed. 1046 */ 1047 struct virtdisk_info *vdisk; 1048 struct virtdisk_info *tmpvdisk; 1049 struct virthba_info *virthbainfo; 1050 struct Scsi_Host *scsihost = (struct Scsi_Host *) scsidev->host; 1051 1052 virthbainfo = (struct virthba_info *) scsihost->hostdata; 1053 if (!virthbainfo) { 1054 LOGERR("Could not find virthba_info for scsihost\n"); 1055 return 0; /* even though we errored, treat as success */ 1056 } 1057 for (vdisk = &virthbainfo->head; vdisk->next; vdisk = vdisk->next) { 1058 if (vdisk->next->valid && 1059 (vdisk->next->channel == scsidev->channel) && 1060 (vdisk->next->id == scsidev->id) && 1061 (vdisk->next->lun == scsidev->lun)) 1062 return 0; 1063 } 1064 tmpvdisk = kzalloc(sizeof(struct virtdisk_info), GFP_ATOMIC); 1065 if (!tmpvdisk) { /* error allocating */ 1066 LOGERR("Could not allocate memory for disk\n"); 1067 return 0; 1068 } 1069 1070 tmpvdisk->channel = scsidev->channel; 1071 tmpvdisk->id = scsidev->id; 1072 tmpvdisk->lun = scsidev->lun; 1073 tmpvdisk->valid = 1; 1074 vdisk->next = tmpvdisk; 1075 return 0; /* success */ 1076} 1077 1078static int 1079virthba_slave_configure(struct scsi_device *scsidev) 1080{ 1081 return 0; /* success */ 1082} 1083 1084static void 1085virthba_slave_destroy(struct scsi_device *scsidev) 1086{ 1087 /* midlevel calls this after device has been quiesced and 1088 * before it is to be deleted. 1089 */ 1090 struct virtdisk_info *vdisk, *delvdisk; 1091 struct virthba_info *virthbainfo; 1092 struct Scsi_Host *scsihost = (struct Scsi_Host *) scsidev->host; 1093 1094 virthbainfo = (struct virthba_info *) scsihost->hostdata; 1095 if (!virthbainfo) 1096 LOGERR("Could not find virthba_info for scsihost\n"); 1097 for (vdisk = &virthbainfo->head; vdisk->next; vdisk = vdisk->next) { 1098 if (vdisk->next->valid && 1099 (vdisk->next->channel == scsidev->channel) && 1100 (vdisk->next->id == scsidev->id) && 1101 (vdisk->next->lun == scsidev->lun)) { 1102 delvdisk = vdisk->next; 1103 vdisk->next = vdisk->next->next; 1104 kfree(delvdisk); 1105 return; 1106 } 1107 } 1108 return; 1109} 1110 1111/*****************************************************/ 1112/* Scsi Cmnd support thread */ 1113/*****************************************************/ 1114 1115static void 1116do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) 1117{ 1118 struct virtdisk_info *vdisk; 1119 struct scsi_device *scsidev; 1120 struct sense_data *sd; 1121 1122 scsidev = scsicmd->device; 1123 memcpy(scsicmd->sense_buffer, cmdrsp->scsi.sensebuf, MAX_SENSE_SIZE); 1124 sd = (struct sense_data *) scsicmd->sense_buffer; 1125 1126 /* Do not log errors for disk-not-present inquiries */ 1127 if ((cmdrsp->scsi.cmnd[0] == INQUIRY) && 1128 (host_byte(cmdrsp->scsi.linuxstat) == DID_NO_CONNECT) && 1129 (cmdrsp->scsi.addlstat == ADDL_SEL_TIMEOUT)) 1130 return; 1131 1132 /* Okay see what our error_count is here.... */ 1133 for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head; 1134 vdisk->next; vdisk = vdisk->next) { 1135 if ((scsidev->channel != vdisk->channel) 1136 || (scsidev->id != vdisk->id) 1137 || (scsidev->lun != vdisk->lun)) 1138 continue; 1139 1140 if (atomic_read(&vdisk->error_count) < VIRTHBA_ERROR_COUNT) { 1141 atomic_inc(&vdisk->error_count); 1142 LOGERR("SCSICMD ****FAILED scsicmd:0x%p op:0x%x <%d:%d:%d:%d> 0x%x-0x%x-0x%x-0x%x-0x%x.\n", 1143 scsicmd, cmdrsp->scsi.cmnd[0], 1144 scsidev->host->host_no, scsidev->id, 1145 scsidev->channel, scsidev->lun, 1146 cmdrsp->scsi.linuxstat, sd->Valid, sd->SenseKey, 1147 sd->AdditionalSenseCode, 1148 sd->AdditionalSenseCodeQualifier); 1149 if (atomic_read(&vdisk->error_count) == 1150 VIRTHBA_ERROR_COUNT) { 1151 LOGERR("Throtling SCSICMD errors disk <%d:%d:%d:%d>\n", 1152 scsidev->host->host_no, scsidev->id, 1153 scsidev->channel, scsidev->lun); 1154 } 1155 atomic_set(&vdisk->ios_threshold, IOS_ERROR_THRESHOLD); 1156 } 1157 } 1158} 1159 1160static void 1161do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) 1162{ 1163 struct scsi_device *scsidev; 1164 unsigned char buf[36]; 1165 struct scatterlist *sg; 1166 unsigned int i; 1167 char *thispage; 1168 char *thispage_orig; 1169 int bufind = 0; 1170 struct virtdisk_info *vdisk; 1171 1172 scsidev = scsicmd->device; 1173 if ((cmdrsp->scsi.cmnd[0] == INQUIRY) 1174 && (cmdrsp->scsi.bufflen >= MIN_INQUIRY_RESULT_LEN)) { 1175 if (cmdrsp->scsi.no_disk_result == 0) 1176 return; 1177 1178 /* Linux scsi code is weird; it wants 1179 * a device at Lun 0 to issue report 1180 * luns, but we don't want a disk 1181 * there so we'll present a processor 1182 * there. */ 1183 SET_NO_DISK_INQUIRY_RESULT(buf, cmdrsp->scsi.bufflen, 1184 scsidev->lun, 1185 DEV_DISK_CAPABLE_NOT_PRESENT, 1186 DEV_NOT_CAPABLE); 1187 1188 if (scsi_sg_count(scsicmd) == 0) { 1189 if (scsi_bufflen(scsicmd) > 0) { 1190 LOGERR("**** FAILED No scatter list for bufflen > 0\n"); 1191 BUG_ON(scsi_sg_count(scsicmd) == 1192 0); 1193 } 1194 memcpy(scsi_sglist(scsicmd), buf, 1195 cmdrsp->scsi.bufflen); 1196 return; 1197 } 1198 1199 sg = scsi_sglist(scsicmd); 1200 for (i = 0; i < scsi_sg_count(scsicmd); i++) { 1201 DBGVER("copying OUT OF buf into 0x%p %d\n", 1202 sg_page(sg + i), sg[i].length); 1203 thispage_orig = kmap_atomic(sg_page(sg + i)); 1204 thispage = (void *) ((unsigned long)thispage_orig | 1205 sg[i].offset); 1206 memcpy(thispage, buf + bufind, sg[i].length); 1207 kunmap_atomic(thispage_orig); 1208 bufind += sg[i].length; 1209 } 1210 } else { 1211 1212 vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; 1213 for ( ; vdisk->next; vdisk = vdisk->next) { 1214 if ((scsidev->channel != vdisk->channel) 1215 || (scsidev->id != vdisk->id) 1216 || (scsidev->lun != vdisk->lun)) 1217 continue; 1218 1219 if (atomic_read(&vdisk->ios_threshold) > 0) { 1220 atomic_dec(&vdisk->ios_threshold); 1221 if (atomic_read(&vdisk->ios_threshold) == 0) { 1222 LOGERR("Resetting error count for disk\n"); 1223 atomic_set(&vdisk->error_count, 0); 1224 } 1225 } 1226 } 1227 } 1228} 1229 1230static void 1231complete_scsi_command(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) 1232{ 1233 DBGINF("cmdrsp: 0x%p, scsistat:0x%x.\n", cmdrsp, cmdrsp->scsi.scsistat); 1234 1235 /* take what we need out of cmdrsp and complete the scsicmd */ 1236 scsicmd->result = cmdrsp->scsi.linuxstat; 1237 if (cmdrsp->scsi.linuxstat) 1238 do_scsi_linuxstat(cmdrsp, scsicmd); 1239 else 1240 do_scsi_nolinuxstat(cmdrsp, scsicmd); 1241 1242 if (scsicmd->scsi_done) { 1243 DBGVER("Scsi_DONE\n"); 1244 scsicmd->scsi_done(scsicmd); 1245 } 1246} 1247 1248static inline void 1249complete_vdiskmgmt_command(struct uiscmdrsp *cmdrsp) 1250{ 1251 /* copy the result of the taskmgmt and */ 1252 /* wake up the error handler that is waiting for this */ 1253 *(int *) cmdrsp->vdiskmgmt.notifyresult = cmdrsp->vdiskmgmt.result; 1254 wake_up_all((wait_queue_head_t *) cmdrsp->vdiskmgmt.notify); 1255 LOGINF("set notify result to %d\n", cmdrsp->vdiskmgmt.result); 1256} 1257 1258static inline void 1259complete_taskmgmt_command(struct uiscmdrsp *cmdrsp) 1260{ 1261 /* copy the result of the taskmgmt and */ 1262 /* wake up the error handler that is waiting for this */ 1263 *(int *) cmdrsp->scsitaskmgmt.notifyresult = 1264 cmdrsp->scsitaskmgmt.result; 1265 wake_up_all((wait_queue_head_t *) cmdrsp->scsitaskmgmt.notify); 1266 LOGINF("set notify result to %d\n", cmdrsp->scsitaskmgmt.result); 1267} 1268 1269static void 1270drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc, 1271 struct uiscmdrsp *cmdrsp) 1272{ 1273 unsigned long flags; 1274 int qrslt = 0; 1275 struct scsi_cmnd *scsicmd; 1276 struct Scsi_Host *shost = virthbainfo->scsihost; 1277 1278 while (1) { 1279 spin_lock_irqsave(&virthbainfo->chinfo.insertlock, flags); 1280 if (!ULTRA_CHANNEL_CLIENT_ACQUIRE_OS(dc->queueinfo->chan, 1281 "vhba", NULL)) { 1282 spin_unlock_irqrestore(&virthbainfo->chinfo.insertlock, 1283 flags); 1284 virthbainfo->acquire_failed_cnt++; 1285 break; 1286 } 1287 qrslt = uisqueue_get_cmdrsp(dc->queueinfo, cmdrsp, 1288 IOCHAN_FROM_IOPART); 1289 ULTRA_CHANNEL_CLIENT_RELEASE_OS(dc->queueinfo->chan, 1290 "vhba", NULL); 1291 spin_unlock_irqrestore(&virthbainfo->chinfo.insertlock, flags); 1292 if (qrslt == 0) 1293 break; 1294 if (cmdrsp->cmdtype == CMD_SCSI_TYPE) { 1295 /* scsicmd location is returned by the 1296 * deletion 1297 */ 1298 scsicmd = del_scsipending_entry(virthbainfo, 1299 (uintptr_t) cmdrsp->scsi.scsicmd); 1300 if (!scsicmd) 1301 break; 1302 /* complete the orig cmd */ 1303 complete_scsi_command(cmdrsp, scsicmd); 1304 } else if (cmdrsp->cmdtype == CMD_SCSITASKMGMT_TYPE) { 1305 if (!del_scsipending_entry(virthbainfo, 1306 (uintptr_t) cmdrsp->scsitaskmgmt.scsicmd)) 1307 break; 1308 complete_taskmgmt_command(cmdrsp); 1309 } else if (cmdrsp->cmdtype == CMD_NOTIFYGUEST_TYPE) { 1310 /* The vHba pointer has no meaning in 1311 * a Client/Guest Partition. Let's be 1312 * safe and set it to NULL now. Do 1313 * not use it here! */ 1314 cmdrsp->disknotify.vHba = NULL; 1315 process_disk_notify(shost, cmdrsp); 1316 } else if (cmdrsp->cmdtype == CMD_VDISKMGMT_TYPE) { 1317 if (!del_scsipending_entry(virthbainfo, 1318 (uintptr_t) cmdrsp->vdiskmgmt.scsicmd)) 1319 break; 1320 complete_vdiskmgmt_command(cmdrsp); 1321 } else 1322 LOGERR("Invalid cmdtype %d\n", cmdrsp->cmdtype); 1323 /* cmdrsp is now available for reuse */ 1324 } 1325} 1326 1327 1328/* main function for the thread that waits for scsi commands to arrive 1329 * in a specified queue 1330 */ 1331static int 1332process_incoming_rsps(void *v) 1333{ 1334 struct virthba_info *virthbainfo = v; 1335 struct chaninfo *dc = &virthbainfo->chinfo; 1336 struct uiscmdrsp *cmdrsp = NULL; 1337 const int SZ = sizeof(struct uiscmdrsp); 1338 U64 mask; 1339 unsigned long long rc1; 1340 1341 UIS_DAEMONIZE("vhba_incoming"); 1342 /* alloc once and reuse */ 1343 cmdrsp = kmalloc(SZ, GFP_ATOMIC); 1344 if (cmdrsp == NULL) { 1345 LOGERR("process_incoming_rsps ****FAILED to malloc - thread exiting\n"); 1346 complete_and_exit(&dc->threadinfo.has_stopped, 0); 1347 return 0; 1348 } 1349 mask = ULTRA_CHANNEL_ENABLE_INTS; 1350 while (1) { 1351 wait_event_interruptible_timeout(virthbainfo->rsp_queue, 1352 (atomic_read(&virthbainfo->interrupt_rcvd) == 1), 1353 usecs_to_jiffies(rsltq_wait_usecs)); 1354 atomic_set(&virthbainfo->interrupt_rcvd, 0); 1355 /* drain queue */ 1356 drain_queue(virthbainfo, dc, cmdrsp); 1357 rc1 = uisqueue_InterlockedOr(virthbainfo->flags_addr, mask); 1358 if (dc->threadinfo.should_stop) 1359 break; 1360 } 1361 1362 kfree(cmdrsp); 1363 1364 DBGINF("exiting processing incoming rsps.\n"); 1365 complete_and_exit(&dc->threadinfo.has_stopped, 0); 1366} 1367 1368/*****************************************************/ 1369/* Debugfs filesystem functions */ 1370/*****************************************************/ 1371 1372static ssize_t info_debugfs_read(struct file *file, 1373 char __user *buf, size_t len, loff_t *offset) 1374{ 1375 ssize_t bytes_read = 0; 1376 int str_pos = 0; 1377 U64 phys_flags_addr; 1378 int i; 1379 struct virthba_info *virthbainfo; 1380 char *vbuf; 1381 1382 if (len > MAX_BUF) 1383 len = MAX_BUF; 1384 vbuf = kzalloc(len, GFP_KERNEL); 1385 if (!vbuf) 1386 return -ENOMEM; 1387 1388 for (i = 0; i < VIRTHBASOPENMAX; i++) { 1389 if (VirtHbasOpen[i].virthbainfo == NULL) 1390 continue; 1391 1392 virthbainfo = VirtHbasOpen[i].virthbainfo; 1393 1394 str_pos += scnprintf(vbuf + str_pos, 1395 len - str_pos, "MaxBuffLen:%u\n", MaxBuffLen); 1396 1397 str_pos += scnprintf(vbuf + str_pos, len - str_pos, 1398 "\nvirthba result queue poll wait:%d usecs.\n", 1399 rsltq_wait_usecs); 1400 str_pos += scnprintf(vbuf + str_pos, len - str_pos, 1401 "\ninterrupts_rcvd = %llu, interrupts_disabled = %llu\n", 1402 virthbainfo->interrupts_rcvd, 1403 virthbainfo->interrupts_disabled); 1404 str_pos += scnprintf(vbuf + str_pos, 1405 len - str_pos, "\ninterrupts_notme = %llu,\n", 1406 virthbainfo->interrupts_notme); 1407 phys_flags_addr = virt_to_phys((__force void *) 1408 virthbainfo->flags_addr); 1409 str_pos += scnprintf(vbuf + str_pos, len - str_pos, 1410 "flags_addr = %p, phys_flags_addr=0x%016llx, FeatureFlags=%llu\n", 1411 virthbainfo->flags_addr, phys_flags_addr, 1412 (__le64)readq(virthbainfo->flags_addr)); 1413 str_pos += scnprintf(vbuf + str_pos, 1414 len - str_pos, "acquire_failed_cnt:%llu\n", 1415 virthbainfo->acquire_failed_cnt); 1416 str_pos += scnprintf(vbuf + str_pos, len - str_pos, "\n"); 1417 } 1418 1419 bytes_read = simple_read_from_buffer(buf, len, offset, vbuf, str_pos); 1420 kfree(vbuf); 1421 return bytes_read; 1422} 1423 1424static ssize_t enable_ints_write(struct file *file, 1425 const char __user *buffer, size_t count, loff_t *ppos) 1426{ 1427 char buf[4]; 1428 int i, new_value; 1429 struct virthba_info *virthbainfo; 1430 1431 U64 __iomem *Features_addr; 1432 U64 mask; 1433 1434 if (count >= ARRAY_SIZE(buf)) 1435 return -EINVAL; 1436 1437 buf[count] = '\0'; 1438 if (copy_from_user(buf, buffer, count)) { 1439 LOGERR("copy_from_user failed. buf<<%.*s>> count<<%lu>>\n", 1440 (int) count, buf, count); 1441 return -EFAULT; 1442 } 1443 1444 i = kstrtoint(buf, 10 , &new_value); 1445 1446 if (i != 0) { 1447 LOGERR("Failed to scan value for enable_ints, buf<<%.*s>>", 1448 (int) count, buf); 1449 return -EFAULT; 1450 } 1451 1452 /*set all counts to new_value usually 0*/ 1453 for (i = 0; i < VIRTHBASOPENMAX; i++) { 1454 if (VirtHbasOpen[i].virthbainfo != NULL) { 1455 virthbainfo = VirtHbasOpen[i].virthbainfo; 1456 Features_addr = 1457 &virthbainfo->chinfo.queueinfo->chan->Features; 1458 if (new_value == 1) { 1459 mask = ~(ULTRA_IO_CHANNEL_IS_POLLING | 1460 ULTRA_IO_DRIVER_DISABLES_INTS); 1461 uisqueue_InterlockedAnd(Features_addr, mask); 1462 mask = ULTRA_IO_DRIVER_ENABLES_INTS; 1463 uisqueue_InterlockedOr(Features_addr, mask); 1464 rsltq_wait_usecs = 4000000; 1465 } else { 1466 mask = ~(ULTRA_IO_DRIVER_ENABLES_INTS | 1467 ULTRA_IO_DRIVER_DISABLES_INTS); 1468 uisqueue_InterlockedAnd(Features_addr, mask); 1469 mask = ULTRA_IO_CHANNEL_IS_POLLING; 1470 uisqueue_InterlockedOr(Features_addr, mask); 1471 rsltq_wait_usecs = 4000; 1472 } 1473 } 1474 } 1475 return count; 1476} 1477 1478/* As per VirtpciFunc returns 1 for success and 0 for failure */ 1479static int 1480virthba_serverup(struct virtpci_dev *virtpcidev) 1481{ 1482 struct virthba_info *virthbainfo = 1483 (struct virthba_info *) ((struct Scsi_Host *) virtpcidev->scsi. 1484 scsihost)->hostdata; 1485 1486 DBGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo, 1487 virtpcidev->deviceNo); 1488 1489 if (!virthbainfo->serverdown) { 1490 DBGINF("Server up message received while server is already up.\n"); 1491 return 1; 1492 } 1493 if (virthbainfo->serverchangingstate) { 1494 LOGERR("Server already processing change state message\n"); 1495 return 0; 1496 } 1497 1498 virthbainfo->serverchangingstate = true; 1499 /* Must transition channel to ATTACHED state BEFORE we 1500 * can start using the device again 1501 */ 1502 ULTRA_CHANNEL_CLIENT_TRANSITION(virthbainfo->chinfo.queueinfo->chan, 1503 dev_name(&virtpcidev->generic_dev), 1504 CHANNELCLI_ATTACHED, NULL); 1505 1506 /* Start Processing the IOVM Response Queue Again */ 1507 if (!uisthread_start(&virthbainfo->chinfo.threadinfo, 1508 process_incoming_rsps, 1509 virthbainfo, "vhba_incoming")) { 1510 LOGERR("uisthread_start rsp ****FAILED\n"); 1511 return 0; 1512 } 1513 virthbainfo->serverdown = false; 1514 virthbainfo->serverchangingstate = false; 1515 1516 return 1; 1517} 1518 1519static void 1520virthba_serverdown_complete(struct work_struct *work) 1521{ 1522 struct virthba_info *virthbainfo; 1523 struct virtpci_dev *virtpcidev; 1524 int i; 1525 struct scsipending *pendingdel = NULL; 1526 struct scsi_cmnd *scsicmd = NULL; 1527 struct uiscmdrsp *cmdrsp; 1528 unsigned long flags; 1529 1530 virthbainfo = container_of(work, struct virthba_info, 1531 serverdown_completion); 1532 1533 /* Stop Using the IOVM Response Queue (queue should be drained 1534 * by the end) 1535 */ 1536 uisthread_stop(&virthbainfo->chinfo.threadinfo); 1537 1538 /* Fail Commands that weren't completed */ 1539 spin_lock_irqsave(&virthbainfo->privlock, flags); 1540 for (i = 0; i < MAX_PENDING_REQUESTS; i++) { 1541 pendingdel = &(virthbainfo->pending[i]); 1542 switch (pendingdel->cmdtype) { 1543 case CMD_SCSI_TYPE: 1544 scsicmd = (struct scsi_cmnd *) pendingdel->sent; 1545 scsicmd->result = (DID_RESET << 16); 1546 if (scsicmd->scsi_done) 1547 scsicmd->scsi_done(scsicmd); 1548 break; 1549 case CMD_SCSITASKMGMT_TYPE: 1550 cmdrsp = (struct uiscmdrsp *) pendingdel->sent; 1551 DBGINF("cmdrsp=0x%x, notify=0x%x\n", cmdrsp, 1552 cmdrsp->scsitaskmgmt.notify); 1553 *(int *) cmdrsp->scsitaskmgmt.notifyresult = 1554 TASK_MGMT_FAILED; 1555 wake_up_all((wait_queue_head_t *) 1556 cmdrsp->scsitaskmgmt.notify); 1557 break; 1558 case CMD_VDISKMGMT_TYPE: 1559 cmdrsp = (struct uiscmdrsp *) pendingdel->sent; 1560 *(int *) cmdrsp->vdiskmgmt.notifyresult = 1561 VDISK_MGMT_FAILED; 1562 wake_up_all((wait_queue_head_t *) 1563 cmdrsp->vdiskmgmt.notify); 1564 break; 1565 default: 1566 if (pendingdel->sent != NULL) 1567 LOGERR("Unknown command type: 0x%x. Only freeing list structure.\n", 1568 pendingdel->cmdtype); 1569 } 1570 pendingdel->cmdtype = 0; 1571 pendingdel->sent = NULL; 1572 } 1573 spin_unlock_irqrestore(&virthbainfo->privlock, flags); 1574 1575 virtpcidev = virthbainfo->virtpcidev; 1576 1577 DBGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo, 1578 virtpcidev->deviceNo); 1579 virthbainfo->serverdown = true; 1580 virthbainfo->serverchangingstate = false; 1581 /* Return the ServerDown response to Command */ 1582 visorchipset_device_pause_response(virtpcidev->busNo, 1583 virtpcidev->deviceNo, 0); 1584} 1585 1586/* As per VirtpciFunc returns 1 for success and 0 for failure */ 1587static int 1588virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state) 1589{ 1590 struct virthba_info *virthbainfo = 1591 (struct virthba_info *) ((struct Scsi_Host *) virtpcidev->scsi. 1592 scsihost)->hostdata; 1593 1594 DBGINF("virthba_serverdown"); 1595 DBGINF("virtpcidev busNo<<%d>>devNo<<%d>>", virtpcidev->busNo, 1596 virtpcidev->deviceNo); 1597 1598 if (!virthbainfo->serverdown && !virthbainfo->serverchangingstate) { 1599 virthbainfo->serverchangingstate = true; 1600 queue_work(virthba_serverdown_workqueue, 1601 &virthbainfo->serverdown_completion); 1602 } else if (virthbainfo->serverchangingstate) { 1603 LOGERR("Server already processing change state message\n"); 1604 return 0; 1605 } else 1606 LOGERR("Server already down, but another server down message received."); 1607 1608 return 1; 1609} 1610 1611/*****************************************************/ 1612/* Module Init & Exit functions */ 1613/*****************************************************/ 1614 1615static int __init 1616virthba_parse_line(char *str) 1617{ 1618 DBGINF("In virthba_parse_line %s\n", str); 1619 return 1; 1620} 1621 1622static void __init 1623virthba_parse_options(char *line) 1624{ 1625 char *next = line; 1626 1627 POSTCODE_LINUX_2(VHBA_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO); 1628 if (line == NULL || !*line) 1629 return; 1630 while ((line = next) != NULL) { 1631 next = strchr(line, ' '); 1632 if (next != NULL) 1633 *next++ = 0; 1634 if (!virthba_parse_line(line)) 1635 DBGINF("Unknown option '%s'\n", line); 1636 } 1637 1638 POSTCODE_LINUX_2(VHBA_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO); 1639} 1640 1641static int __init 1642virthba_mod_init(void) 1643{ 1644 int error; 1645 int i; 1646 1647 if (!unisys_spar_platform) 1648 return -ENODEV; 1649 1650 LOGINF("Entering virthba_mod_init...\n"); 1651 1652 POSTCODE_LINUX_2(VHBA_CREATE_ENTRY_PC, POSTCODE_SEVERITY_INFO); 1653 virthba_parse_options(virthba_options); 1654 1655 error = virtpci_register_driver(&virthba_driver); 1656 if (error < 0) { 1657 LOGERR("register ****FAILED 0x%x\n", error); 1658 POSTCODE_LINUX_3(VHBA_CREATE_FAILURE_PC, error, 1659 POSTCODE_SEVERITY_ERR); 1660 } else { 1661 1662 /* create the debugfs directories and entries */ 1663 virthba_debugfs_dir = debugfs_create_dir("virthba", NULL); 1664 debugfs_create_file("info", S_IRUSR, virthba_debugfs_dir, 1665 NULL, &debugfs_info_fops); 1666 debugfs_create_u32("rqwait_usecs", S_IRUSR | S_IWUSR, 1667 virthba_debugfs_dir, &rsltq_wait_usecs); 1668 debugfs_create_file("enable_ints", S_IWUSR, 1669 virthba_debugfs_dir, NULL, 1670 &debugfs_enable_ints_fops); 1671 /* Initialize DARWorkQ */ 1672 INIT_WORK(&DARWorkQ, doDiskAddRemove); 1673 spin_lock_init(&DARWorkQLock); 1674 1675 /* clear out array */ 1676 for (i = 0; i < VIRTHBASOPENMAX; i++) 1677 VirtHbasOpen[i].virthbainfo = NULL; 1678 /* Initialize the serverdown workqueue */ 1679 virthba_serverdown_workqueue = 1680 create_singlethread_workqueue("virthba_serverdown"); 1681 if (virthba_serverdown_workqueue == NULL) { 1682 LOGERR("**** FAILED virthba_serverdown_workqueue creation\n"); 1683 POSTCODE_LINUX_2(VHBA_CREATE_FAILURE_PC, 1684 POSTCODE_SEVERITY_ERR); 1685 error = -1; 1686 } 1687 } 1688 1689 POSTCODE_LINUX_2(VHBA_CREATE_EXIT_PC, POSTCODE_SEVERITY_INFO); 1690 LOGINF("Leaving virthba_mod_init\n"); 1691 return error; 1692} 1693 1694static ssize_t 1695virthba_acquire_lun(struct device *cdev, struct device_attribute *attr, 1696 const char *buf, size_t count) 1697{ 1698 struct uisscsi_dest vdest; 1699 struct Scsi_Host *shost = class_to_shost(cdev); 1700 int i; 1701 1702 i = sscanf(buf, "%d-%d-%d", &vdest.channel, &vdest.id, &vdest.lun); 1703 if (i != 3) 1704 return i; 1705 1706 return forward_vdiskmgmt_command(VDISK_MGMT_ACQUIRE, shost, &vdest); 1707} 1708 1709static ssize_t 1710virthba_release_lun(struct device *cdev, struct device_attribute *attr, 1711 const char *buf, size_t count) 1712{ 1713 struct uisscsi_dest vdest; 1714 struct Scsi_Host *shost = class_to_shost(cdev); 1715 int i; 1716 1717 i = sscanf(buf, "%d-%d-%d", &vdest.channel, &vdest.id, &vdest.lun); 1718 if (i != 3) 1719 return i; 1720 1721 return forward_vdiskmgmt_command(VDISK_MGMT_RELEASE, shost, &vdest); 1722} 1723 1724#define CLASS_DEVICE_ATTR(_name, _mode, _show, _store) \ 1725 struct device_attribute class_device_attr_##_name = \ 1726 __ATTR(_name, _mode, _show, _store) 1727 1728static CLASS_DEVICE_ATTR(acquire_lun, S_IWUSR, NULL, virthba_acquire_lun); 1729static CLASS_DEVICE_ATTR(release_lun, S_IWUSR, NULL, virthba_release_lun); 1730 1731static DEVICE_ATTRIBUTE *virthba_shost_attrs[] = { 1732 &class_device_attr_acquire_lun, 1733 &class_device_attr_release_lun, 1734 NULL 1735}; 1736 1737static void __exit 1738virthba_mod_exit(void) 1739{ 1740 LOGINF("entering virthba_mod_exit...\n"); 1741 1742 virtpci_unregister_driver(&virthba_driver); 1743 /* unregister is going to call virthba_remove */ 1744 /* destroy serverdown completion workqueue */ 1745 if (virthba_serverdown_workqueue) { 1746 destroy_workqueue(virthba_serverdown_workqueue); 1747 virthba_serverdown_workqueue = NULL; 1748 } 1749 1750 /* remove debugfs directory and files. */ 1751 debugfs_remove_recursive(virthba_debugfs_dir); 1752 LOGINF("Leaving virthba_mod_exit\n"); 1753 1754} 1755 1756/* specify function to be run at module insertion time */ 1757module_init(virthba_mod_init); 1758 1759/* specify function to be run when module is removed */ 1760module_exit(virthba_mod_exit); 1761 1762MODULE_LICENSE("GPL"); 1763MODULE_AUTHOR("Usha Srinivasan"); 1764MODULE_ALIAS("uisvirthba"); 1765 /* this is extracted during depmod and kept in modules.dep */ 1766/* module parameter */ 1767module_param(virthba_options, charp, S_IRUGO); 1768