diff options
Diffstat (limited to 'drivers/message/fusion/mptspi.c')
| -rw-r--r-- | drivers/message/fusion/mptspi.c | 735 |
1 files changed, 681 insertions, 54 deletions
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index f148dfa39117..09c745b19cc8 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c | |||
| @@ -56,12 +56,15 @@ | |||
| 56 | #include <linux/reboot.h> /* notifier code */ | 56 | #include <linux/reboot.h> /* notifier code */ |
| 57 | #include <linux/sched.h> | 57 | #include <linux/sched.h> |
| 58 | #include <linux/workqueue.h> | 58 | #include <linux/workqueue.h> |
| 59 | #include <linux/raid_class.h> | ||
| 59 | 60 | ||
| 60 | #include <scsi/scsi.h> | 61 | #include <scsi/scsi.h> |
| 61 | #include <scsi/scsi_cmnd.h> | 62 | #include <scsi/scsi_cmnd.h> |
| 62 | #include <scsi/scsi_device.h> | 63 | #include <scsi/scsi_device.h> |
| 63 | #include <scsi/scsi_host.h> | 64 | #include <scsi/scsi_host.h> |
| 64 | #include <scsi/scsi_tcq.h> | 65 | #include <scsi/scsi_tcq.h> |
| 66 | #include <scsi/scsi_transport.h> | ||
| 67 | #include <scsi/scsi_transport_spi.h> | ||
| 65 | 68 | ||
| 66 | #include "mptbase.h" | 69 | #include "mptbase.h" |
| 67 | #include "mptscsih.h" | 70 | #include "mptscsih.h" |
| @@ -76,20 +79,6 @@ MODULE_DESCRIPTION(my_NAME); | |||
| 76 | MODULE_LICENSE("GPL"); | 79 | MODULE_LICENSE("GPL"); |
| 77 | 80 | ||
| 78 | /* Command line args */ | 81 | /* Command line args */ |
| 79 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
| 80 | static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION; | ||
| 81 | module_param(mpt_dv, int, 0); | ||
| 82 | MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)"); | ||
| 83 | |||
| 84 | static int mpt_width = MPTSCSIH_MAX_WIDTH; | ||
| 85 | module_param(mpt_width, int, 0); | ||
| 86 | MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)"); | ||
| 87 | |||
| 88 | static ushort mpt_factor = MPTSCSIH_MIN_SYNC; | ||
| 89 | module_param(mpt_factor, ushort, 0); | ||
| 90 | MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)"); | ||
| 91 | #endif | ||
| 92 | |||
| 93 | static int mpt_saf_te = MPTSCSIH_SAF_TE; | 82 | static int mpt_saf_te = MPTSCSIH_SAF_TE; |
| 94 | module_param(mpt_saf_te, int, 0); | 83 | module_param(mpt_saf_te, int, 0); |
| 95 | MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)"); | 84 | MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)"); |
| @@ -98,10 +87,308 @@ static int mpt_pq_filter = 0; | |||
| 98 | module_param(mpt_pq_filter, int, 0); | 87 | module_param(mpt_pq_filter, int, 0); |
| 99 | MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); | 88 | MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)"); |
| 100 | 89 | ||
| 90 | static void mptspi_write_offset(struct scsi_target *, int); | ||
| 91 | static void mptspi_write_width(struct scsi_target *, int); | ||
| 92 | static int mptspi_write_spi_device_pg1(struct scsi_target *, | ||
| 93 | struct _CONFIG_PAGE_SCSI_DEVICE_1 *); | ||
| 94 | |||
| 95 | static struct scsi_transport_template *mptspi_transport_template = NULL; | ||
| 96 | |||
| 101 | static int mptspiDoneCtx = -1; | 97 | static int mptspiDoneCtx = -1; |
| 102 | static int mptspiTaskCtx = -1; | 98 | static int mptspiTaskCtx = -1; |
| 103 | static int mptspiInternalCtx = -1; /* Used only for internal commands */ | 99 | static int mptspiInternalCtx = -1; /* Used only for internal commands */ |
| 104 | 100 | ||
| 101 | static int mptspi_target_alloc(struct scsi_target *starget) | ||
| 102 | { | ||
| 103 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
| 104 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; | ||
| 105 | int ret; | ||
| 106 | |||
| 107 | if (hd == NULL) | ||
| 108 | return -ENODEV; | ||
| 109 | |||
| 110 | ret = mptscsih_target_alloc(starget); | ||
| 111 | if (ret) | ||
| 112 | return ret; | ||
| 113 | |||
| 114 | /* if we're a device on virtual channel 1 and we're not part | ||
| 115 | * of an array, just return here (otherwise the setup below | ||
| 116 | * may actually affect a real physical device on channel 0 */ | ||
| 117 | if (starget->channel == 1 && | ||
| 118 | mptscsih_raid_id_to_num(hd, starget->id) < 0) | ||
| 119 | return 0; | ||
| 120 | |||
| 121 | if (hd->ioc->spi_data.nvram && | ||
| 122 | hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) { | ||
| 123 | u32 nvram = hd->ioc->spi_data.nvram[starget->id]; | ||
| 124 | spi_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; | ||
| 125 | spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; | ||
| 126 | } else { | ||
| 127 | spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor; | ||
| 128 | spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth; | ||
| 129 | } | ||
| 130 | spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset; | ||
| 131 | |||
| 132 | spi_offset(starget) = 0; | ||
| 133 | mptspi_write_width(starget, 0); | ||
| 134 | |||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | |||
| 138 | static int mptspi_read_spi_device_pg0(struct scsi_target *starget, | ||
| 139 | struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0) | ||
| 140 | { | ||
| 141 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
| 142 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; | ||
| 143 | struct _MPT_ADAPTER *ioc = hd->ioc; | ||
| 144 | struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0; | ||
| 145 | dma_addr_t pg0_dma; | ||
| 146 | int size; | ||
| 147 | struct _x_config_parms cfg; | ||
| 148 | struct _CONFIG_PAGE_HEADER hdr; | ||
| 149 | int err = -EBUSY; | ||
| 150 | |||
| 151 | /* No SPI parameters for RAID devices */ | ||
| 152 | if (starget->channel == 0 && | ||
| 153 | (hd->ioc->raid_data.isRaid & (1 << starget->id))) | ||
| 154 | return -1; | ||
| 155 | |||
| 156 | size = ioc->spi_data.sdp0length * 4; | ||
| 157 | /* | ||
| 158 | if (ioc->spi_data.sdp0length & 1) | ||
| 159 | size += size + 4; | ||
| 160 | size += 2048; | ||
| 161 | */ | ||
| 162 | |||
| 163 | pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg0_dma, GFP_KERNEL); | ||
| 164 | if (pg0 == NULL) { | ||
| 165 | starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n"); | ||
| 166 | return -EINVAL; | ||
| 167 | } | ||
| 168 | |||
| 169 | memset(&hdr, 0, sizeof(hdr)); | ||
| 170 | |||
| 171 | hdr.PageVersion = ioc->spi_data.sdp0version; | ||
| 172 | hdr.PageLength = ioc->spi_data.sdp0length; | ||
| 173 | hdr.PageNumber = 0; | ||
| 174 | hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; | ||
| 175 | |||
| 176 | memset(&cfg, 0, sizeof(cfg)); | ||
| 177 | |||
| 178 | cfg.cfghdr.hdr = &hdr; | ||
| 179 | cfg.physAddr = pg0_dma; | ||
| 180 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 181 | cfg.dir = 0; | ||
| 182 | cfg.pageAddr = starget->id; | ||
| 183 | |||
| 184 | if (mpt_config(ioc, &cfg)) { | ||
| 185 | starget_printk(KERN_ERR, starget, "mpt_config failed\n"); | ||
| 186 | goto out_free; | ||
| 187 | } | ||
| 188 | err = 0; | ||
| 189 | memcpy(pass_pg0, pg0, size); | ||
| 190 | |||
| 191 | out_free: | ||
| 192 | dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma); | ||
| 193 | return err; | ||
| 194 | } | ||
| 195 | |||
| 196 | static u32 mptspi_getRP(struct scsi_target *starget) | ||
| 197 | { | ||
| 198 | u32 nego = 0; | ||
| 199 | |||
| 200 | nego |= spi_iu(starget) ? MPI_SCSIDEVPAGE1_RP_IU : 0; | ||
| 201 | nego |= spi_dt(starget) ? MPI_SCSIDEVPAGE1_RP_DT : 0; | ||
| 202 | nego |= spi_qas(starget) ? MPI_SCSIDEVPAGE1_RP_QAS : 0; | ||
| 203 | nego |= spi_hold_mcs(starget) ? MPI_SCSIDEVPAGE1_RP_HOLD_MCS : 0; | ||
| 204 | nego |= spi_wr_flow(starget) ? MPI_SCSIDEVPAGE1_RP_WR_FLOW : 0; | ||
| 205 | nego |= spi_rd_strm(starget) ? MPI_SCSIDEVPAGE1_RP_RD_STRM : 0; | ||
| 206 | nego |= spi_rti(starget) ? MPI_SCSIDEVPAGE1_RP_RTI : 0; | ||
| 207 | nego |= spi_pcomp_en(starget) ? MPI_SCSIDEVPAGE1_RP_PCOMP_EN : 0; | ||
| 208 | |||
| 209 | nego |= (spi_period(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD) & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK; | ||
| 210 | nego |= (spi_offset(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET) & MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK; | ||
| 211 | nego |= spi_width(starget) ? MPI_SCSIDEVPAGE1_RP_WIDE : 0; | ||
| 212 | |||
| 213 | return nego; | ||
| 214 | } | ||
| 215 | |||
| 216 | static void mptspi_read_parameters(struct scsi_target *starget) | ||
| 217 | { | ||
| 218 | int nego; | ||
| 219 | struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0; | ||
| 220 | |||
| 221 | mptspi_read_spi_device_pg0(starget, &pg0); | ||
| 222 | |||
| 223 | nego = le32_to_cpu(pg0.NegotiatedParameters); | ||
| 224 | |||
| 225 | spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0; | ||
| 226 | spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0; | ||
| 227 | spi_qas(starget) = (nego & MPI_SCSIDEVPAGE0_NP_QAS) ? 1 : 0; | ||
| 228 | spi_wr_flow(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WR_FLOW) ? 1 : 0; | ||
| 229 | spi_rd_strm(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RD_STRM) ? 1 : 0; | ||
| 230 | spi_rti(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RTI) ? 1 : 0; | ||
| 231 | spi_pcomp_en(starget) = (nego & MPI_SCSIDEVPAGE0_NP_PCOMP_EN) ? 1 : 0; | ||
| 232 | spi_hold_mcs(starget) = (nego & MPI_SCSIDEVPAGE0_NP_HOLD_MCS) ? 1 : 0; | ||
| 233 | spi_period(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD; | ||
| 234 | spi_offset(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET; | ||
| 235 | spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0; | ||
| 236 | } | ||
| 237 | |||
| 238 | static int | ||
| 239 | mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, int disk) | ||
| 240 | { | ||
| 241 | MpiRaidActionRequest_t *pReq; | ||
| 242 | MPT_FRAME_HDR *mf; | ||
| 243 | |||
| 244 | /* Get and Populate a free Frame | ||
| 245 | */ | ||
| 246 | if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { | ||
| 247 | ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", | ||
| 248 | hd->ioc->name)); | ||
| 249 | return -EAGAIN; | ||
| 250 | } | ||
| 251 | pReq = (MpiRaidActionRequest_t *)mf; | ||
| 252 | if (quiesce) | ||
| 253 | pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO; | ||
| 254 | else | ||
| 255 | pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO; | ||
| 256 | pReq->Reserved1 = 0; | ||
| 257 | pReq->ChainOffset = 0; | ||
| 258 | pReq->Function = MPI_FUNCTION_RAID_ACTION; | ||
| 259 | pReq->VolumeID = disk; | ||
| 260 | pReq->VolumeBus = 0; | ||
| 261 | pReq->PhysDiskNum = 0; | ||
| 262 | pReq->MsgFlags = 0; | ||
| 263 | pReq->Reserved2 = 0; | ||
| 264 | pReq->ActionDataWord = 0; /* Reserved for this action */ | ||
| 265 | |||
| 266 | mpt_add_sge((char *)&pReq->ActionDataSGE, | ||
| 267 | MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); | ||
| 268 | |||
| 269 | ddvprintk((MYIOC_s_INFO_FMT "RAID Volume action %x id %d\n", | ||
| 270 | hd->ioc->name, action, io->id)); | ||
| 271 | |||
| 272 | hd->pLocal = NULL; | ||
| 273 | hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ | ||
| 274 | hd->scandv_wait_done = 0; | ||
| 275 | |||
| 276 | /* Save cmd pointer, for resource free if timeout or | ||
| 277 | * FW reload occurs | ||
| 278 | */ | ||
| 279 | hd->cmdPtr = mf; | ||
| 280 | |||
| 281 | add_timer(&hd->timer); | ||
| 282 | mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); | ||
| 283 | wait_event(hd->scandv_waitq, hd->scandv_wait_done); | ||
| 284 | |||
| 285 | if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0)) | ||
| 286 | return -1; | ||
| 287 | |||
| 288 | return 0; | ||
| 289 | } | ||
| 290 | |||
| 291 | static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, | ||
| 292 | struct scsi_device *sdev) | ||
| 293 | { | ||
| 294 | VirtTarget *vtarget = scsi_target(sdev)->hostdata; | ||
| 295 | |||
| 296 | /* no DV on RAID devices */ | ||
| 297 | if (sdev->channel == 0 && | ||
| 298 | (hd->ioc->raid_data.isRaid & (1 << sdev->id))) | ||
| 299 | return; | ||
| 300 | |||
| 301 | /* If this is a piece of a RAID, then quiesce first */ | ||
| 302 | if (sdev->channel == 1 && | ||
| 303 | mptscsih_quiesce_raid(hd, 1, vtarget->target_id) < 0) { | ||
| 304 | starget_printk(KERN_ERR, scsi_target(sdev), | ||
| 305 | "Integrated RAID quiesce failed\n"); | ||
| 306 | return; | ||
| 307 | } | ||
| 308 | |||
| 309 | spi_dv_device(sdev); | ||
| 310 | |||
| 311 | if (sdev->channel == 1 && | ||
| 312 | mptscsih_quiesce_raid(hd, 0, vtarget->target_id) < 0) | ||
| 313 | starget_printk(KERN_ERR, scsi_target(sdev), | ||
| 314 | "Integrated RAID resume failed\n"); | ||
| 315 | |||
| 316 | mptspi_read_parameters(sdev->sdev_target); | ||
| 317 | spi_display_xfer_agreement(sdev->sdev_target); | ||
| 318 | mptspi_read_parameters(sdev->sdev_target); | ||
| 319 | } | ||
| 320 | |||
| 321 | static int mptspi_slave_alloc(struct scsi_device *sdev) | ||
| 322 | { | ||
| 323 | int ret; | ||
| 324 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata; | ||
| 325 | /* gcc doesn't see that all uses of this variable occur within | ||
| 326 | * the if() statements, so stop it from whining */ | ||
| 327 | int physdisknum = 0; | ||
| 328 | |||
| 329 | if (sdev->channel == 1) { | ||
| 330 | physdisknum = mptscsih_raid_id_to_num(hd, sdev->id); | ||
| 331 | |||
| 332 | if (physdisknum < 0) | ||
| 333 | return physdisknum; | ||
| 334 | } | ||
| 335 | |||
| 336 | ret = mptscsih_slave_alloc(sdev); | ||
| 337 | |||
| 338 | if (ret) | ||
| 339 | return ret; | ||
| 340 | |||
| 341 | if (sdev->channel == 1) { | ||
| 342 | VirtDevice *vdev = sdev->hostdata; | ||
| 343 | sdev->no_uld_attach = 1; | ||
| 344 | vdev->vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; | ||
| 345 | /* The real channel for this device is zero */ | ||
| 346 | vdev->vtarget->bus_id = 0; | ||
| 347 | /* The actual physdisknum (for RAID passthrough) */ | ||
| 348 | vdev->vtarget->target_id = physdisknum; | ||
| 349 | } | ||
| 350 | |||
| 351 | return 0; | ||
| 352 | } | ||
| 353 | |||
| 354 | static int mptspi_slave_configure(struct scsi_device *sdev) | ||
| 355 | { | ||
| 356 | int ret = mptscsih_slave_configure(sdev); | ||
| 357 | struct _MPT_SCSI_HOST *hd = | ||
| 358 | (struct _MPT_SCSI_HOST *)sdev->host->hostdata; | ||
| 359 | |||
| 360 | if (ret) | ||
| 361 | return ret; | ||
| 362 | |||
| 363 | if ((sdev->channel == 1 || | ||
| 364 | !(hd->ioc->raid_data.isRaid & (1 << sdev->id))) && | ||
| 365 | !spi_initial_dv(sdev->sdev_target)) | ||
| 366 | mptspi_dv_device(hd, sdev); | ||
| 367 | |||
| 368 | return 0; | ||
| 369 | } | ||
| 370 | |||
| 371 | static void mptspi_slave_destroy(struct scsi_device *sdev) | ||
| 372 | { | ||
| 373 | struct scsi_target *starget = scsi_target(sdev); | ||
| 374 | VirtTarget *vtarget = starget->hostdata; | ||
| 375 | VirtDevice *vdevice = sdev->hostdata; | ||
| 376 | |||
| 377 | /* Will this be the last lun on a non-raid device? */ | ||
| 378 | if (vtarget->num_luns == 1 && vdevice->configured_lun) { | ||
| 379 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
| 380 | |||
| 381 | /* Async Narrow */ | ||
| 382 | pg1.RequestedParameters = 0; | ||
| 383 | pg1.Reserved = 0; | ||
| 384 | pg1.Configuration = 0; | ||
| 385 | |||
| 386 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
| 387 | } | ||
| 388 | |||
| 389 | mptscsih_slave_destroy(sdev); | ||
| 390 | } | ||
| 391 | |||
| 105 | static struct scsi_host_template mptspi_driver_template = { | 392 | static struct scsi_host_template mptspi_driver_template = { |
| 106 | .module = THIS_MODULE, | 393 | .module = THIS_MODULE, |
| 107 | .proc_name = "mptspi", | 394 | .proc_name = "mptspi", |
| @@ -109,11 +396,11 @@ static struct scsi_host_template mptspi_driver_template = { | |||
| 109 | .name = "MPT SPI Host", | 396 | .name = "MPT SPI Host", |
| 110 | .info = mptscsih_info, | 397 | .info = mptscsih_info, |
| 111 | .queuecommand = mptscsih_qcmd, | 398 | .queuecommand = mptscsih_qcmd, |
| 112 | .target_alloc = mptscsih_target_alloc, | 399 | .target_alloc = mptspi_target_alloc, |
| 113 | .slave_alloc = mptscsih_slave_alloc, | 400 | .slave_alloc = mptspi_slave_alloc, |
| 114 | .slave_configure = mptscsih_slave_configure, | 401 | .slave_configure = mptspi_slave_configure, |
| 115 | .target_destroy = mptscsih_target_destroy, | 402 | .target_destroy = mptscsih_target_destroy, |
| 116 | .slave_destroy = mptscsih_slave_destroy, | 403 | .slave_destroy = mptspi_slave_destroy, |
| 117 | .change_queue_depth = mptscsih_change_queue_depth, | 404 | .change_queue_depth = mptscsih_change_queue_depth, |
| 118 | .eh_abort_handler = mptscsih_abort, | 405 | .eh_abort_handler = mptscsih_abort, |
| 119 | .eh_device_reset_handler = mptscsih_dev_reset, | 406 | .eh_device_reset_handler = mptscsih_dev_reset, |
| @@ -128,6 +415,360 @@ static struct scsi_host_template mptspi_driver_template = { | |||
| 128 | .use_clustering = ENABLE_CLUSTERING, | 415 | .use_clustering = ENABLE_CLUSTERING, |
| 129 | }; | 416 | }; |
| 130 | 417 | ||
| 418 | static int mptspi_write_spi_device_pg1(struct scsi_target *starget, | ||
| 419 | struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1) | ||
| 420 | { | ||
| 421 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
| 422 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; | ||
| 423 | struct _MPT_ADAPTER *ioc = hd->ioc; | ||
| 424 | struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1; | ||
| 425 | dma_addr_t pg1_dma; | ||
| 426 | int size; | ||
| 427 | struct _x_config_parms cfg; | ||
| 428 | struct _CONFIG_PAGE_HEADER hdr; | ||
| 429 | int err = -EBUSY; | ||
| 430 | |||
| 431 | /* don't allow updating nego parameters on RAID devices */ | ||
| 432 | if (starget->channel == 0 && | ||
| 433 | (hd->ioc->raid_data.isRaid & (1 << starget->id))) | ||
| 434 | return -1; | ||
| 435 | |||
| 436 | size = ioc->spi_data.sdp1length * 4; | ||
| 437 | |||
| 438 | pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL); | ||
| 439 | if (pg1 == NULL) { | ||
| 440 | starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n"); | ||
| 441 | return -EINVAL; | ||
| 442 | } | ||
| 443 | |||
| 444 | memset(&hdr, 0, sizeof(hdr)); | ||
| 445 | |||
| 446 | hdr.PageVersion = ioc->spi_data.sdp1version; | ||
| 447 | hdr.PageLength = ioc->spi_data.sdp1length; | ||
| 448 | hdr.PageNumber = 1; | ||
| 449 | hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; | ||
| 450 | |||
| 451 | memset(&cfg, 0, sizeof(cfg)); | ||
| 452 | |||
| 453 | cfg.cfghdr.hdr = &hdr; | ||
| 454 | cfg.physAddr = pg1_dma; | ||
| 455 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
| 456 | cfg.dir = 1; | ||
| 457 | cfg.pageAddr = starget->id; | ||
| 458 | |||
| 459 | memcpy(pg1, pass_pg1, size); | ||
| 460 | |||
| 461 | pg1->Header.PageVersion = hdr.PageVersion; | ||
| 462 | pg1->Header.PageLength = hdr.PageLength; | ||
| 463 | pg1->Header.PageNumber = hdr.PageNumber; | ||
| 464 | pg1->Header.PageType = hdr.PageType; | ||
| 465 | |||
| 466 | if (mpt_config(ioc, &cfg)) { | ||
| 467 | starget_printk(KERN_ERR, starget, "mpt_config failed\n"); | ||
| 468 | goto out_free; | ||
| 469 | } | ||
| 470 | err = 0; | ||
| 471 | |||
| 472 | out_free: | ||
| 473 | dma_free_coherent(&ioc->pcidev->dev, size, pg1, pg1_dma); | ||
| 474 | return err; | ||
| 475 | } | ||
| 476 | |||
| 477 | static void mptspi_write_offset(struct scsi_target *starget, int offset) | ||
| 478 | { | ||
| 479 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
| 480 | u32 nego; | ||
| 481 | |||
| 482 | if (offset < 0) | ||
| 483 | offset = 0; | ||
| 484 | |||
| 485 | if (offset > 255) | ||
| 486 | offset = 255; | ||
| 487 | |||
| 488 | if (spi_offset(starget) == -1) | ||
| 489 | mptspi_read_parameters(starget); | ||
| 490 | |||
| 491 | spi_offset(starget) = offset; | ||
| 492 | |||
| 493 | nego = mptspi_getRP(starget); | ||
| 494 | |||
| 495 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
| 496 | pg1.Reserved = 0; | ||
| 497 | pg1.Configuration = 0; | ||
| 498 | |||
| 499 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
| 500 | } | ||
| 501 | |||
| 502 | static void mptspi_write_period(struct scsi_target *starget, int period) | ||
| 503 | { | ||
| 504 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
| 505 | u32 nego; | ||
| 506 | |||
| 507 | if (period < 8) | ||
| 508 | period = 8; | ||
| 509 | |||
| 510 | if (period > 255) | ||
| 511 | period = 255; | ||
| 512 | |||
| 513 | if (spi_period(starget) == -1) | ||
| 514 | mptspi_read_parameters(starget); | ||
| 515 | |||
| 516 | if (period == 8) { | ||
| 517 | spi_iu(starget) = 1; | ||
| 518 | spi_dt(starget) = 1; | ||
| 519 | } else if (period == 9) { | ||
| 520 | spi_dt(starget) = 1; | ||
| 521 | } | ||
| 522 | |||
| 523 | spi_period(starget) = period; | ||
| 524 | |||
| 525 | nego = mptspi_getRP(starget); | ||
| 526 | |||
| 527 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
| 528 | pg1.Reserved = 0; | ||
| 529 | pg1.Configuration = 0; | ||
| 530 | |||
| 531 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
| 532 | } | ||
| 533 | |||
| 534 | static void mptspi_write_dt(struct scsi_target *starget, int dt) | ||
| 535 | { | ||
| 536 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
| 537 | u32 nego; | ||
| 538 | |||
| 539 | if (spi_period(starget) == -1) | ||
| 540 | mptspi_read_parameters(starget); | ||
| 541 | |||
| 542 | if (!dt && spi_period(starget) < 10) | ||
| 543 | spi_period(starget) = 10; | ||
| 544 | |||
| 545 | spi_dt(starget) = dt; | ||
| 546 | |||
| 547 | nego = mptspi_getRP(starget); | ||
| 548 | |||
| 549 | |||
| 550 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
| 551 | pg1.Reserved = 0; | ||
| 552 | pg1.Configuration = 0; | ||
| 553 | |||
| 554 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
| 555 | } | ||
| 556 | |||
| 557 | static void mptspi_write_iu(struct scsi_target *starget, int iu) | ||
| 558 | { | ||
| 559 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
| 560 | u32 nego; | ||
| 561 | |||
| 562 | if (spi_period(starget) == -1) | ||
| 563 | mptspi_read_parameters(starget); | ||
| 564 | |||
| 565 | if (!iu && spi_period(starget) < 9) | ||
| 566 | spi_period(starget) = 9; | ||
| 567 | |||
| 568 | spi_iu(starget) = iu; | ||
| 569 | |||
| 570 | nego = mptspi_getRP(starget); | ||
| 571 | |||
| 572 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
| 573 | pg1.Reserved = 0; | ||
| 574 | pg1.Configuration = 0; | ||
| 575 | |||
| 576 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
| 577 | } | ||
| 578 | |||
| 579 | #define MPTSPI_SIMPLE_TRANSPORT_PARM(parm) \ | ||
| 580 | static void mptspi_write_##parm(struct scsi_target *starget, int parm)\ | ||
| 581 | { \ | ||
| 582 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; \ | ||
| 583 | u32 nego; \ | ||
| 584 | \ | ||
| 585 | spi_##parm(starget) = parm; \ | ||
| 586 | \ | ||
| 587 | nego = mptspi_getRP(starget); \ | ||
| 588 | \ | ||
| 589 | pg1.RequestedParameters = cpu_to_le32(nego); \ | ||
| 590 | pg1.Reserved = 0; \ | ||
| 591 | pg1.Configuration = 0; \ | ||
| 592 | \ | ||
| 593 | mptspi_write_spi_device_pg1(starget, &pg1); \ | ||
| 594 | } | ||
| 595 | |||
| 596 | MPTSPI_SIMPLE_TRANSPORT_PARM(rd_strm) | ||
| 597 | MPTSPI_SIMPLE_TRANSPORT_PARM(wr_flow) | ||
| 598 | MPTSPI_SIMPLE_TRANSPORT_PARM(rti) | ||
| 599 | MPTSPI_SIMPLE_TRANSPORT_PARM(hold_mcs) | ||
| 600 | MPTSPI_SIMPLE_TRANSPORT_PARM(pcomp_en) | ||
| 601 | |||
| 602 | static void mptspi_write_qas(struct scsi_target *starget, int qas) | ||
| 603 | { | ||
| 604 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
| 605 | struct Scsi_Host *shost = dev_to_shost(&starget->dev); | ||
| 606 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; | ||
| 607 | VirtTarget *vtarget = starget->hostdata; | ||
| 608 | u32 nego; | ||
| 609 | |||
| 610 | if ((vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) || | ||
| 611 | hd->ioc->spi_data.noQas) | ||
| 612 | spi_qas(starget) = 0; | ||
| 613 | else | ||
| 614 | spi_qas(starget) = qas; | ||
| 615 | |||
| 616 | nego = mptspi_getRP(starget); | ||
| 617 | |||
| 618 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
| 619 | pg1.Reserved = 0; | ||
| 620 | pg1.Configuration = 0; | ||
| 621 | |||
| 622 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
| 623 | } | ||
| 624 | |||
| 625 | static void mptspi_write_width(struct scsi_target *starget, int width) | ||
| 626 | { | ||
| 627 | struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; | ||
| 628 | u32 nego; | ||
| 629 | |||
| 630 | if (!width) { | ||
| 631 | spi_dt(starget) = 0; | ||
| 632 | if (spi_period(starget) < 10) | ||
| 633 | spi_period(starget) = 10; | ||
| 634 | } | ||
| 635 | |||
| 636 | spi_width(starget) = width; | ||
| 637 | |||
| 638 | nego = mptspi_getRP(starget); | ||
| 639 | |||
| 640 | pg1.RequestedParameters = cpu_to_le32(nego); | ||
| 641 | pg1.Reserved = 0; | ||
| 642 | pg1.Configuration = 0; | ||
| 643 | |||
| 644 | mptspi_write_spi_device_pg1(starget, &pg1); | ||
| 645 | } | ||
| 646 | |||
| 647 | struct work_queue_wrapper { | ||
| 648 | struct work_struct work; | ||
| 649 | struct _MPT_SCSI_HOST *hd; | ||
| 650 | int disk; | ||
| 651 | }; | ||
| 652 | |||
| 653 | static void mpt_work_wrapper(void *data) | ||
| 654 | { | ||
| 655 | struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data; | ||
| 656 | struct _MPT_SCSI_HOST *hd = wqw->hd; | ||
| 657 | struct Scsi_Host *shost = hd->ioc->sh; | ||
| 658 | struct scsi_device *sdev; | ||
| 659 | int disk = wqw->disk; | ||
| 660 | struct _CONFIG_PAGE_IOC_3 *pg3; | ||
| 661 | |||
| 662 | kfree(wqw); | ||
| 663 | |||
| 664 | mpt_findImVolumes(hd->ioc); | ||
| 665 | pg3 = hd->ioc->raid_data.pIocPg3; | ||
| 666 | if (!pg3) | ||
| 667 | return; | ||
| 668 | |||
| 669 | shost_for_each_device(sdev,shost) { | ||
| 670 | struct scsi_target *starget = scsi_target(sdev); | ||
| 671 | VirtTarget *vtarget = starget->hostdata; | ||
| 672 | |||
| 673 | /* only want to search RAID components */ | ||
| 674 | if (sdev->channel != 1) | ||
| 675 | continue; | ||
| 676 | |||
| 677 | /* The target_id is the raid PhysDiskNum, even if | ||
| 678 | * starget->id is the actual target address */ | ||
| 679 | if(vtarget->target_id != disk) | ||
| 680 | continue; | ||
| 681 | |||
| 682 | starget_printk(KERN_INFO, vtarget->starget, | ||
| 683 | "Integrated RAID requests DV of new device\n"); | ||
| 684 | mptspi_dv_device(hd, sdev); | ||
| 685 | } | ||
| 686 | shost_printk(KERN_INFO, shost, | ||
| 687 | "Integrated RAID detects new device %d\n", disk); | ||
| 688 | scsi_scan_target(&hd->ioc->sh->shost_gendev, 1, disk, 0, 1); | ||
| 689 | } | ||
| 690 | |||
| 691 | |||
| 692 | static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk) | ||
| 693 | { | ||
| 694 | struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC); | ||
| 695 | |||
| 696 | if (!wqw) { | ||
| 697 | shost_printk(KERN_ERR, hd->ioc->sh, | ||
| 698 | "Failed to act on RAID event for physical disk %d\n", | ||
| 699 | disk); | ||
| 700 | return; | ||
| 701 | } | ||
| 702 | INIT_WORK(&wqw->work, mpt_work_wrapper, wqw); | ||
| 703 | wqw->hd = hd; | ||
| 704 | wqw->disk = disk; | ||
| 705 | |||
| 706 | schedule_work(&wqw->work); | ||
| 707 | } | ||
| 708 | |||
| 709 | static int | ||
| 710 | mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | ||
| 711 | { | ||
| 712 | u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; | ||
| 713 | struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata; | ||
| 714 | |||
| 715 | if (hd && event == MPI_EVENT_INTEGRATED_RAID) { | ||
| 716 | int reason | ||
| 717 | = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16; | ||
| 718 | |||
| 719 | if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) { | ||
| 720 | int disk = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24; | ||
| 721 | mpt_dv_raid(hd, disk); | ||
| 722 | } | ||
| 723 | } | ||
| 724 | return mptscsih_event_process(ioc, pEvReply); | ||
| 725 | } | ||
| 726 | |||
| 727 | static int | ||
| 728 | mptspi_deny_binding(struct scsi_target *starget) | ||
| 729 | { | ||
| 730 | struct _MPT_SCSI_HOST *hd = | ||
| 731 | (struct _MPT_SCSI_HOST *)dev_to_shost(starget->dev.parent)->hostdata; | ||
| 732 | return ((hd->ioc->raid_data.isRaid & (1 << starget->id)) && | ||
| 733 | starget->channel == 0) ? 1 : 0; | ||
| 734 | } | ||
| 735 | |||
| 736 | static struct spi_function_template mptspi_transport_functions = { | ||
| 737 | .get_offset = mptspi_read_parameters, | ||
| 738 | .set_offset = mptspi_write_offset, | ||
| 739 | .show_offset = 1, | ||
| 740 | .get_period = mptspi_read_parameters, | ||
| 741 | .set_period = mptspi_write_period, | ||
| 742 | .show_period = 1, | ||
| 743 | .get_width = mptspi_read_parameters, | ||
| 744 | .set_width = mptspi_write_width, | ||
| 745 | .show_width = 1, | ||
| 746 | .get_iu = mptspi_read_parameters, | ||
| 747 | .set_iu = mptspi_write_iu, | ||
| 748 | .show_iu = 1, | ||
| 749 | .get_dt = mptspi_read_parameters, | ||
| 750 | .set_dt = mptspi_write_dt, | ||
| 751 | .show_dt = 1, | ||
| 752 | .get_qas = mptspi_read_parameters, | ||
| 753 | .set_qas = mptspi_write_qas, | ||
| 754 | .show_qas = 1, | ||
| 755 | .get_wr_flow = mptspi_read_parameters, | ||
| 756 | .set_wr_flow = mptspi_write_wr_flow, | ||
| 757 | .show_wr_flow = 1, | ||
| 758 | .get_rd_strm = mptspi_read_parameters, | ||
| 759 | .set_rd_strm = mptspi_write_rd_strm, | ||
| 760 | .show_rd_strm = 1, | ||
| 761 | .get_rti = mptspi_read_parameters, | ||
| 762 | .set_rti = mptspi_write_rti, | ||
| 763 | .show_rti = 1, | ||
| 764 | .get_pcomp_en = mptspi_read_parameters, | ||
| 765 | .set_pcomp_en = mptspi_write_pcomp_en, | ||
| 766 | .show_pcomp_en = 1, | ||
| 767 | .get_hold_mcs = mptspi_read_parameters, | ||
| 768 | .set_hold_mcs = mptspi_write_hold_mcs, | ||
| 769 | .show_hold_mcs = 1, | ||
| 770 | .deny_binding = mptspi_deny_binding, | ||
| 771 | }; | ||
| 131 | 772 | ||
| 132 | /**************************************************************************** | 773 | /**************************************************************************** |
| 133 | * Supported hardware | 774 | * Supported hardware |
| @@ -242,7 +883,14 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 242 | sh->max_id = MPT_MAX_SCSI_DEVICES; | 883 | sh->max_id = MPT_MAX_SCSI_DEVICES; |
| 243 | 884 | ||
| 244 | sh->max_lun = MPT_LAST_LUN + 1; | 885 | sh->max_lun = MPT_LAST_LUN + 1; |
| 245 | sh->max_channel = 0; | 886 | /* |
| 887 | * If RAID Firmware Detected, setup virtual channel | ||
| 888 | */ | ||
| 889 | if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) | ||
| 890 | > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) | ||
| 891 | sh->max_channel = 1; | ||
| 892 | else | ||
| 893 | sh->max_channel = 0; | ||
| 246 | sh->this_id = ioc->pfacts[0].PortSCSIID; | 894 | sh->this_id = ioc->pfacts[0].PortSCSIID; |
| 247 | 895 | ||
| 248 | /* Required entry. | 896 | /* Required entry. |
| @@ -301,7 +949,8 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 301 | * indicates a device exists. | 949 | * indicates a device exists. |
| 302 | * max_id = 1 + maximum id (hosts.h) | 950 | * max_id = 1 + maximum id (hosts.h) |
| 303 | */ | 951 | */ |
| 304 | hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC); | 952 | hd->Targets = kcalloc(sh->max_id * (sh->max_channel + 1), |
| 953 | sizeof(void *), GFP_ATOMIC); | ||
| 305 | if (!hd->Targets) { | 954 | if (!hd->Targets) { |
| 306 | error = -ENOMEM; | 955 | error = -ENOMEM; |
| 307 | goto out_mptspi_probe; | 956 | goto out_mptspi_probe; |
| @@ -334,49 +983,23 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 334 | ioc->spi_data.Saf_Te = mpt_saf_te; | 983 | ioc->spi_data.Saf_Te = mpt_saf_te; |
| 335 | hd->mpt_pq_filter = mpt_pq_filter; | 984 | hd->mpt_pq_filter = mpt_pq_filter; |
| 336 | 985 | ||
| 337 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | ||
| 338 | if (ioc->spi_data.maxBusWidth > mpt_width) | ||
| 339 | ioc->spi_data.maxBusWidth = mpt_width; | ||
| 340 | if (ioc->spi_data.minSyncFactor < mpt_factor) | ||
| 341 | ioc->spi_data.minSyncFactor = mpt_factor; | ||
| 342 | if (ioc->spi_data.minSyncFactor == MPT_ASYNC) { | ||
| 343 | ioc->spi_data.maxSyncOffset = 0; | ||
| 344 | } | ||
| 345 | ioc->spi_data.mpt_dv = mpt_dv; | ||
| 346 | hd->negoNvram = 0; | ||
| 347 | |||
| 348 | ddvprintk((MYIOC_s_INFO_FMT | ||
| 349 | "dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n", | ||
| 350 | ioc->name, | ||
| 351 | mpt_dv, | ||
| 352 | mpt_width, | ||
| 353 | mpt_factor, | ||
| 354 | mpt_saf_te, | ||
| 355 | mpt_pq_filter)); | ||
| 356 | #else | ||
| 357 | hd->negoNvram = MPT_SCSICFG_USE_NVRAM; | 986 | hd->negoNvram = MPT_SCSICFG_USE_NVRAM; |
| 358 | ddvprintk((MYIOC_s_INFO_FMT | 987 | ddvprintk((MYIOC_s_INFO_FMT |
| 359 | "saf_te %x mpt_pq_filter %x\n", | 988 | "saf_te %x mpt_pq_filter %x\n", |
| 360 | ioc->name, | 989 | ioc->name, |
| 361 | mpt_saf_te, | 990 | mpt_saf_te, |
| 362 | mpt_pq_filter)); | 991 | mpt_pq_filter)); |
| 363 | #endif | ||
| 364 | |||
| 365 | ioc->spi_data.forceDv = 0; | ||
| 366 | ioc->spi_data.noQas = 0; | 992 | ioc->spi_data.noQas = 0; |
| 367 | 993 | ||
| 368 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) | ||
| 369 | ioc->spi_data.dvStatus[ii] = | ||
| 370 | MPT_SCSICFG_NEGOTIATE; | ||
| 371 | |||
| 372 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) | ||
| 373 | ioc->spi_data.dvStatus[ii] |= | ||
| 374 | MPT_SCSICFG_DV_NOT_DONE; | ||
| 375 | |||
| 376 | init_waitqueue_head(&hd->scandv_waitq); | 994 | init_waitqueue_head(&hd->scandv_waitq); |
| 377 | hd->scandv_wait_done = 0; | 995 | hd->scandv_wait_done = 0; |
| 378 | hd->last_queue_full = 0; | 996 | hd->last_queue_full = 0; |
| 379 | 997 | ||
| 998 | /* Some versions of the firmware don't support page 0; without | ||
| 999 | * that we can't get the parameters */ | ||
| 1000 | if (hd->ioc->spi_data.sdp0length != 0) | ||
| 1001 | sh->transportt = mptspi_transport_template; | ||
| 1002 | |||
| 380 | error = scsi_add_host (sh, &ioc->pcidev->dev); | 1003 | error = scsi_add_host (sh, &ioc->pcidev->dev); |
| 381 | if(error) { | 1004 | if(error) { |
| 382 | dprintk((KERN_ERR MYNAM | 1005 | dprintk((KERN_ERR MYNAM |
| @@ -423,15 +1046,18 @@ static struct pci_driver mptspi_driver = { | |||
| 423 | static int __init | 1046 | static int __init |
| 424 | mptspi_init(void) | 1047 | mptspi_init(void) |
| 425 | { | 1048 | { |
| 426 | |||
| 427 | show_mptmod_ver(my_NAME, my_VERSION); | 1049 | show_mptmod_ver(my_NAME, my_VERSION); |
| 428 | 1050 | ||
| 1051 | mptspi_transport_template = spi_attach_transport(&mptspi_transport_functions); | ||
| 1052 | if (!mptspi_transport_template) | ||
| 1053 | return -ENODEV; | ||
| 1054 | |||
| 429 | mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER); | 1055 | mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER); |
| 430 | mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER); | 1056 | mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER); |
| 431 | mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); | 1057 | mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER); |
| 432 | 1058 | ||
| 433 | if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) { | 1059 | if (mpt_event_register(mptspiDoneCtx, mptspi_event_process) == 0) { |
| 434 | devtprintk((KERN_INFO MYNAM | 1060 | devtverboseprintk((KERN_INFO MYNAM |
| 435 | ": Registered for IOC event notifications\n")); | 1061 | ": Registered for IOC event notifications\n")); |
| 436 | } | 1062 | } |
| 437 | 1063 | ||
| @@ -465,6 +1091,7 @@ mptspi_exit(void) | |||
| 465 | mpt_deregister(mptspiInternalCtx); | 1091 | mpt_deregister(mptspiInternalCtx); |
| 466 | mpt_deregister(mptspiTaskCtx); | 1092 | mpt_deregister(mptspiTaskCtx); |
| 467 | mpt_deregister(mptspiDoneCtx); | 1093 | mpt_deregister(mptspiDoneCtx); |
| 1094 | spi_release_transport(mptspi_transport_template); | ||
| 468 | } | 1095 | } |
| 469 | 1096 | ||
| 470 | module_init(mptspi_init); | 1097 | module_init(mptspi_init); |
