blob: 74f4368c79ab221aec72393b2acd6b718987908a [file] [log] [blame]
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001/*
2 * linux/drivers/message/fusion/mptsas.c
3 * For use with LSI Logic PCI chip/adapter(s)
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5 *
6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01008 * Copyright (c) 2005-2006 Dell
Christoph Hellwig0c33b272005-09-09 16:27:19 +02009 */
10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11/*
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 NO WARRANTY
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
31
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44*/
45/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46
47#include <linux/module.h>
48#include <linux/kernel.h>
49#include <linux/init.h>
50#include <linux/errno.h>
51#include <linux/sched.h>
52#include <linux/workqueue.h>
53
54#include <scsi/scsi_cmnd.h>
55#include <scsi/scsi_device.h>
56#include <scsi/scsi_host.h>
57#include <scsi/scsi_transport_sas.h>
58
59#include "mptbase.h"
60#include "mptscsih.h"
61
62
63#define my_NAME "Fusion MPT SAS Host driver"
64#define my_VERSION MPT_LINUX_VERSION_COMMON
65#define MYNAM "mptsas"
66
67MODULE_AUTHOR(MODULEAUTHOR);
68MODULE_DESCRIPTION(my_NAME);
69MODULE_LICENSE("GPL");
70
71static int mpt_pq_filter;
72module_param(mpt_pq_filter, int, 0);
73MODULE_PARM_DESC(mpt_pq_filter,
74 "Enable peripheral qualifier filter: enable=1 "
75 "(default=0)");
76
77static int mpt_pt_clear;
78module_param(mpt_pt_clear, int, 0);
79MODULE_PARM_DESC(mpt_pt_clear,
80 "Clear persistency table: enable=1 "
81 "(default=MPTSCSIH_PT_CLEAR=0)");
82
83static int mptsasDoneCtx = -1;
84static int mptsasTaskCtx = -1;
85static int mptsasInternalCtx = -1; /* Used only for internal commands */
Christoph Hellwigda4fa652005-10-19 20:01:42 +020086static int mptsasMgmtCtx = -1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +020087
88
Christoph Hellwig9a28f492006-01-13 18:04:41 +010089enum mptsas_hotplug_action {
90 MPTSAS_ADD_DEVICE,
91 MPTSAS_DEL_DEVICE,
Moore, Ericc73787ee2006-01-26 16:20:06 -070092 MPTSAS_ADD_RAID,
93 MPTSAS_DEL_RAID,
Christoph Hellwig9a28f492006-01-13 18:04:41 +010094};
95
96struct mptsas_hotplug_event {
97 struct work_struct work;
98 MPT_ADAPTER *ioc;
99 enum mptsas_hotplug_action event_type;
100 u64 sas_address;
101 u32 channel;
102 u32 id;
103 u32 device_info;
104 u16 handle;
105 u16 parent_handle;
106 u8 phy_id;
107};
108
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200109/*
110 * SAS topology structures
111 *
112 * The MPT Fusion firmware interface spreads information about the
113 * SAS topology over many manufacture pages, thus we need some data
114 * structure to collect it and process it for the SAS transport class.
115 */
116
117struct mptsas_devinfo {
118 u16 handle; /* unique id to address this device */
Moore, Ericc73787ee2006-01-26 16:20:06 -0700119 u16 handle_parent; /* unique id to address parent device */
Christoph Hellwige3094442006-02-16 13:25:36 +0100120 u16 handle_enclosure; /* enclosure identifier of the enclosure */
121 u16 slot; /* physical slot in enclosure */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200122 u8 phy_id; /* phy number of parent device */
123 u8 port_id; /* sas physical port this device
124 is assoc'd with */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100125 u8 id; /* logical target id of this device */
126 u8 channel; /* logical bus number of this device */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200127 u64 sas_address; /* WWN of this device,
128 SATA is assigned by HBA,expander */
129 u32 device_info; /* bitfield detailed info about this device */
130};
131
132struct mptsas_phyinfo {
133 u8 phy_id; /* phy index */
134 u8 port_id; /* port number this phy is part of */
135 u8 negotiated_link_rate; /* nego'd link rate for this phy */
136 u8 hw_link_rate; /* hardware max/min phys link rate */
137 u8 programmed_link_rate; /* programmed max/min phy link rate */
138 struct mptsas_devinfo identify; /* point to phy device info */
139 struct mptsas_devinfo attached; /* point to attached device info */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100140 struct sas_phy *phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200141 struct sas_rphy *rphy;
142};
143
144struct mptsas_portinfo {
145 struct list_head list;
146 u16 handle; /* unique id to address this */
147 u8 num_phys; /* number of phys */
148 struct mptsas_phyinfo *phy_info;
149};
150
Christoph Hellwige3094442006-02-16 13:25:36 +0100151struct mptsas_enclosure {
152 u64 enclosure_logical_id; /* The WWN for the enclosure */
153 u16 enclosure_handle; /* unique id to address this */
154 u16 flags; /* details enclosure management */
155 u16 num_slot; /* num slots */
156 u16 start_slot; /* first slot */
157 u8 start_id; /* starting logical target id */
158 u8 start_channel; /* starting logical channel id */
159 u8 sep_id; /* SEP device logical target id */
160 u8 sep_channel; /* SEP channel logical channel id */
161};
162
Christoph Hellwigb5141122005-10-28 22:07:41 +0200163
164#ifdef SASDEBUG
165static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
166{
167 printk("---- IO UNIT PAGE 0 ------------\n");
168 printk("Handle=0x%X\n",
169 le16_to_cpu(phy_data->AttachedDeviceHandle));
170 printk("Controller Handle=0x%X\n",
171 le16_to_cpu(phy_data->ControllerDevHandle));
172 printk("Port=0x%X\n", phy_data->Port);
173 printk("Port Flags=0x%X\n", phy_data->PortFlags);
174 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
175 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
176 printk("Controller PHY Device Info=0x%X\n",
177 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
178 printk("DiscoveryStatus=0x%X\n",
179 le32_to_cpu(phy_data->DiscoveryStatus));
180 printk("\n");
181}
182
183static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
184{
185 __le64 sas_address;
186
187 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
188
189 printk("---- SAS PHY PAGE 0 ------------\n");
190 printk("Attached Device Handle=0x%X\n",
191 le16_to_cpu(pg0->AttachedDevHandle));
192 printk("SAS Address=0x%llX\n",
193 (unsigned long long)le64_to_cpu(sas_address));
194 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
195 printk("Attached Device Info=0x%X\n",
196 le32_to_cpu(pg0->AttachedDeviceInfo));
197 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
198 printk("Change Count=0x%X\n", pg0->ChangeCount);
199 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
200 printk("\n");
201}
202
203static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
204{
205 printk("---- SAS PHY PAGE 1 ------------\n");
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200206 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
207 printk("Running Disparity Error Count=0x%x\n",
Christoph Hellwigb5141122005-10-28 22:07:41 +0200208 pg1->RunningDisparityErrorCount);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200209 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
210 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
211 printk("\n");
Christoph Hellwigb5141122005-10-28 22:07:41 +0200212}
213
214static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
215{
216 __le64 sas_address;
217
218 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
219
220 printk("---- SAS DEVICE PAGE 0 ---------\n");
221 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
Christoph Hellwige3094442006-02-16 13:25:36 +0100222 printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200223 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
224 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
225 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
226 printk("Target ID=0x%X\n", pg0->TargetID);
227 printk("Bus=0x%X\n", pg0->Bus);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200228 /* The PhyNum field specifies the PHY number of the parent
229 * device this device is linked to
230 */
231 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
232 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200233 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
234 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
235 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
236 printk("\n");
237}
238
239static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
240{
241 printk("---- SAS EXPANDER PAGE 1 ------------\n");
242
243 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200244 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwigb5141122005-10-28 22:07:41 +0200245 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
246 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
247 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
248 printk("Owner Device Handle=0x%X\n",
249 le16_to_cpu(pg1->OwnerDevHandle));
250 printk("Attached Device Handle=0x%X\n",
251 le16_to_cpu(pg1->AttachedDevHandle));
252}
253#else
254#define mptsas_print_phy_data(phy_data) do { } while (0)
255#define mptsas_print_phy_pg0(pg0) do { } while (0)
256#define mptsas_print_phy_pg1(pg1) do { } while (0)
257#define mptsas_print_device_pg0(pg0) do { } while (0)
258#define mptsas_print_expander_pg1(pg1) do { } while (0)
259#endif
260
Christoph Hellwige3094442006-02-16 13:25:36 +0100261static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
262{
263 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
264 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
265}
266
267static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
268{
269 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
270 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
271}
272
273static int
274mptsas_sas_exclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
275 u32 form, u32 form_specific)
276{
277 ConfigExtendedPageHeader_t hdr;
278 CONFIGPARMS cfg;
279 SasEnclosurePage0_t *buffer;
280 dma_addr_t dma_handle;
281 int error;
282 __le64 le_identifier;
283
284 memset(&hdr, 0, sizeof(hdr));
285 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
286 hdr.PageNumber = 0;
287 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
288 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
289
290 cfg.cfghdr.ehdr = &hdr;
291 cfg.physAddr = -1;
292 cfg.pageAddr = form + form_specific;
293 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
294 cfg.dir = 0; /* read */
295 cfg.timeout = 10;
296
297 error = mpt_config(ioc, &cfg);
298 if (error)
299 goto out;
300 if (!hdr.ExtPageLength) {
301 error = -ENXIO;
302 goto out;
303 }
304
305 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
306 &dma_handle);
307 if (!buffer) {
308 error = -ENOMEM;
309 goto out;
310 }
311
312 cfg.physAddr = dma_handle;
313 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
314
315 error = mpt_config(ioc, &cfg);
316 if (error)
317 goto out_free_consistent;
318
319 /* save config data */
320 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
321 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
322 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
323 enclosure->flags = le16_to_cpu(buffer->Flags);
324 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
325 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
326 enclosure->start_id = buffer->StartTargetID;
327 enclosure->start_channel = buffer->StartBus;
328 enclosure->sep_id = buffer->SEPTargetID;
329 enclosure->sep_channel = buffer->SEPBus;
330
331 out_free_consistent:
332 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
333 buffer, dma_handle);
334 out:
335 return error;
336}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200337
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200338/*
339 * This is pretty ugly. We will be able to seriously clean it up
340 * once the DV code in mptscsih goes away and we can properly
341 * implement ->target_alloc.
342 */
343static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700344mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200345{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700346 struct Scsi_Host *host = sdev->host;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200347 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
348 struct sas_rphy *rphy;
349 struct mptsas_portinfo *p;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700350 VirtTarget *vtarget;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200351 VirtDevice *vdev;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700352 struct scsi_target *starget;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200353 int i;
354
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100355 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200356 if (!vdev) {
357 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
358 hd->ioc->name, sizeof(VirtDevice));
359 return -ENOMEM;
360 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200361 vdev->ioc_id = hd->ioc->id;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700362 sdev->hostdata = vdev;
363 starget = scsi_target(sdev);
364 vtarget = starget->hostdata;
365 vdev->vtarget = vtarget;
366 if (vtarget->num_luns == 0) {
367 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
368 hd->Targets[sdev->id] = vtarget;
369 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200370
Moore, Eric816aa902006-01-13 16:25:20 -0700371 /*
372 RAID volumes placed beyond the last expected port.
373 */
374 if (sdev->channel == hd->ioc->num_ports) {
375 vdev->target_id = sdev->id;
376 vdev->bus_id = 0;
377 vdev->lun = 0;
378 goto out;
379 }
380
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700381 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100382 mutex_lock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200383 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
384 for (i = 0; i < p->num_phys; i++) {
385 if (p->phy_info[i].attached.sas_address ==
386 rphy->identify.sas_address) {
387 vdev->target_id =
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100388 p->phy_info[i].attached.id;
389 vdev->bus_id = p->phy_info[i].attached.channel;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700390 vdev->lun = sdev->lun;
Moore, Eric816aa902006-01-13 16:25:20 -0700391 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200392 goto out;
393 }
394 }
395 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100396 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200397
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200398 kfree(vdev);
Christoph Hellwig23f236e2006-01-30 19:00:43 +0100399 return -ENXIO;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200400
401 out:
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700402 vtarget->ioc_id = vdev->ioc_id;
403 vtarget->target_id = vdev->target_id;
404 vtarget->bus_id = vdev->bus_id;
405 vtarget->num_luns++;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200406 return 0;
407}
408
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100409static void
410mptsas_slave_destroy(struct scsi_device *sdev)
411{
412 struct Scsi_Host *host = sdev->host;
413 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
414 struct sas_rphy *rphy;
415 struct mptsas_portinfo *p;
416 int i;
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700417 VirtDevice *vdev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100418
419 /*
420 * Handle hotplug removal case.
421 * We need to clear out attached data structure.
422 */
423 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
424
425 mutex_lock(&hd->ioc->sas_topology_mutex);
426 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
427 for (i = 0; i < p->num_phys; i++) {
428 if (p->phy_info[i].attached.sas_address ==
429 rphy->identify.sas_address) {
430 memset(&p->phy_info[i].attached, 0,
431 sizeof(struct mptsas_devinfo));
432 p->phy_info[i].rphy = NULL;
433 goto out;
434 }
435 }
436 }
437
438 out:
439 mutex_unlock(&hd->ioc->sas_topology_mutex);
440 /*
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700441 * Issue target reset to flush firmware outstanding commands.
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100442 */
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700443 vdev = sdev->hostdata;
444 if (vdev->configured_lun){
445 if (mptscsih_TMHandler(hd,
446 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
447 vdev->bus_id,
448 vdev->target_id,
449 0, 0, 5 /* 5 second timeout */)
450 < 0){
451
452 /* The TM request failed!
453 * Fatal error case.
454 */
455 printk(MYIOC_s_WARN_FMT
456 "Error processing TaskMgmt id=%d TARGET_RESET\n",
457 hd->ioc->name,
458 vdev->target_id);
459
460 hd->tmPending = 0;
461 hd->tmState = TM_STATE_NONE;
462 }
463 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100464 mptscsih_slave_destroy(sdev);
465}
466
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200467static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700468 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200469 .proc_name = "mptsas",
470 .proc_info = mptscsih_proc_info,
471 .name = "MPT SPI Host",
472 .info = mptscsih_info,
473 .queuecommand = mptscsih_qcmd,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700474 .target_alloc = mptscsih_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200475 .slave_alloc = mptsas_slave_alloc,
476 .slave_configure = mptscsih_slave_configure,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700477 .target_destroy = mptscsih_target_destroy,
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100478 .slave_destroy = mptsas_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200479 .change_queue_depth = mptscsih_change_queue_depth,
480 .eh_abort_handler = mptscsih_abort,
481 .eh_device_reset_handler = mptscsih_dev_reset,
482 .eh_bus_reset_handler = mptscsih_bus_reset,
483 .eh_host_reset_handler = mptscsih_host_reset,
484 .bios_param = mptscsih_bios_param,
485 .can_queue = MPT_FC_CAN_QUEUE,
486 .this_id = -1,
487 .sg_tablesize = MPT_SCSI_SG_DEPTH,
488 .max_sectors = 8192,
489 .cmd_per_lun = 7,
490 .use_clustering = ENABLE_CLUSTERING,
491};
492
Christoph Hellwigb5141122005-10-28 22:07:41 +0200493static int mptsas_get_linkerrors(struct sas_phy *phy)
494{
495 MPT_ADAPTER *ioc = phy_to_ioc(phy);
496 ConfigExtendedPageHeader_t hdr;
497 CONFIGPARMS cfg;
498 SasPhyPage1_t *buffer;
499 dma_addr_t dma_handle;
500 int error;
501
502 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
503 hdr.ExtPageLength = 0;
504 hdr.PageNumber = 1 /* page number 1*/;
505 hdr.Reserved1 = 0;
506 hdr.Reserved2 = 0;
507 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
508 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
509
510 cfg.cfghdr.ehdr = &hdr;
511 cfg.physAddr = -1;
512 cfg.pageAddr = phy->identify.phy_identifier;
513 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
514 cfg.dir = 0; /* read */
515 cfg.timeout = 10;
516
517 error = mpt_config(ioc, &cfg);
518 if (error)
519 return error;
520 if (!hdr.ExtPageLength)
521 return -ENXIO;
522
523 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
524 &dma_handle);
525 if (!buffer)
526 return -ENOMEM;
527
528 cfg.physAddr = dma_handle;
529 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
530
531 error = mpt_config(ioc, &cfg);
532 if (error)
533 goto out_free_consistent;
534
535 mptsas_print_phy_pg1(buffer);
536
537 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
538 phy->running_disparity_error_count =
539 le32_to_cpu(buffer->RunningDisparityErrorCount);
540 phy->loss_of_dword_sync_count =
541 le32_to_cpu(buffer->LossDwordSynchCount);
542 phy->phy_reset_problem_count =
543 le32_to_cpu(buffer->PhyResetProblemCount);
544
545 out_free_consistent:
546 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
547 buffer, dma_handle);
548 return error;
549}
550
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200551static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
552 MPT_FRAME_HDR *reply)
553{
554 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
555 if (reply != NULL) {
556 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
557 memcpy(ioc->sas_mgmt.reply, reply,
558 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
559 }
560 complete(&ioc->sas_mgmt.done);
561 return 1;
562}
563
564static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
565{
566 MPT_ADAPTER *ioc = phy_to_ioc(phy);
567 SasIoUnitControlRequest_t *req;
568 SasIoUnitControlReply_t *reply;
569 MPT_FRAME_HDR *mf;
570 MPIHeader_t *hdr;
571 unsigned long timeleft;
572 int error = -ERESTARTSYS;
573
574 /* not implemented for expanders */
575 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
576 return -ENXIO;
577
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100578 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200579 goto out;
580
581 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
582 if (!mf) {
583 error = -ENOMEM;
584 goto out_unlock;
585 }
586
587 hdr = (MPIHeader_t *) mf;
588 req = (SasIoUnitControlRequest_t *)mf;
589 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
590 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
591 req->MsgContext = hdr->MsgContext;
592 req->Operation = hard_reset ?
593 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
594 req->PhyNum = phy->identify.phy_identifier;
595
596 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
597
598 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
599 10 * HZ);
600 if (!timeleft) {
601 /* On timeout reset the board */
602 mpt_free_msg_frame(ioc, mf);
603 mpt_HardResetHandler(ioc, CAN_SLEEP);
604 error = -ETIMEDOUT;
605 goto out_unlock;
606 }
607
608 /* a reply frame is expected */
609 if ((ioc->sas_mgmt.status &
610 MPT_IOCTL_STATUS_RF_VALID) == 0) {
611 error = -ENXIO;
612 goto out_unlock;
613 }
614
615 /* process the completed Reply Message Frame */
616 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
617 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
618 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
619 __FUNCTION__,
620 reply->IOCStatus,
621 reply->IOCLogInfo);
622 error = -ENXIO;
623 goto out_unlock;
624 }
625
626 error = 0;
627
628 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100629 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200630 out:
631 return error;
632}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200633
Christoph Hellwige3094442006-02-16 13:25:36 +0100634static int
635mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
636{
637 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
638 int i, error;
639 struct mptsas_portinfo *p;
640 struct mptsas_enclosure enclosure_info;
641 u64 enclosure_handle;
642
643 mutex_lock(&ioc->sas_topology_mutex);
644 list_for_each_entry(p, &ioc->sas_topology, list) {
645 for (i = 0; i < p->num_phys; i++) {
646 if (p->phy_info[i].attached.sas_address ==
647 rphy->identify.sas_address) {
648 enclosure_handle = p->phy_info[i].
649 attached.handle_enclosure;
650 goto found_info;
651 }
652 }
653 }
654 mutex_unlock(&ioc->sas_topology_mutex);
655 return -ENXIO;
656
657 found_info:
658 mutex_unlock(&ioc->sas_topology_mutex);
659 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
660 error = mptsas_sas_exclosure_pg0(ioc, &enclosure_info,
661 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
662 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
663 if (!error)
664 *identifier = enclosure_info.enclosure_logical_id;
665 return error;
666}
667
668static int
669mptsas_get_bay_identifier(struct sas_rphy *rphy)
670{
671 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
672 struct mptsas_portinfo *p;
673 int i, rc;
674
675 mutex_lock(&ioc->sas_topology_mutex);
676 list_for_each_entry(p, &ioc->sas_topology, list) {
677 for (i = 0; i < p->num_phys; i++) {
678 if (p->phy_info[i].attached.sas_address ==
679 rphy->identify.sas_address) {
680 rc = p->phy_info[i].attached.slot;
681 goto out;
682 }
683 }
684 }
685 rc = -ENXIO;
686 out:
687 mutex_unlock(&ioc->sas_topology_mutex);
688 return rc;
689}
690
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200691static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +0200692 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +0100693 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
694 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200695 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200696};
697
698static struct scsi_transport_template *mptsas_transport_template;
699
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200700static int
701mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
702{
703 ConfigExtendedPageHeader_t hdr;
704 CONFIGPARMS cfg;
705 SasIOUnitPage0_t *buffer;
706 dma_addr_t dma_handle;
707 int error, i;
708
709 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
710 hdr.ExtPageLength = 0;
711 hdr.PageNumber = 0;
712 hdr.Reserved1 = 0;
713 hdr.Reserved2 = 0;
714 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
715 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
716
717 cfg.cfghdr.ehdr = &hdr;
718 cfg.physAddr = -1;
719 cfg.pageAddr = 0;
720 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
721 cfg.dir = 0; /* read */
722 cfg.timeout = 10;
723
724 error = mpt_config(ioc, &cfg);
725 if (error)
726 goto out;
727 if (!hdr.ExtPageLength) {
728 error = -ENXIO;
729 goto out;
730 }
731
732 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
733 &dma_handle);
734 if (!buffer) {
735 error = -ENOMEM;
736 goto out;
737 }
738
739 cfg.physAddr = dma_handle;
740 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
741
742 error = mpt_config(ioc, &cfg);
743 if (error)
744 goto out_free_consistent;
745
746 port_info->num_phys = buffer->NumPhys;
747 port_info->phy_info = kcalloc(port_info->num_phys,
748 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
749 if (!port_info->phy_info) {
750 error = -ENOMEM;
751 goto out_free_consistent;
752 }
753
754 for (i = 0; i < port_info->num_phys; i++) {
755 mptsas_print_phy_data(&buffer->PhyData[i]);
756 port_info->phy_info[i].phy_id = i;
757 port_info->phy_info[i].port_id =
758 buffer->PhyData[i].Port;
759 port_info->phy_info[i].negotiated_link_rate =
760 buffer->PhyData[i].NegotiatedLinkRate;
761 }
762
763 out_free_consistent:
764 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
765 buffer, dma_handle);
766 out:
767 return error;
768}
769
770static int
771mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
772 u32 form, u32 form_specific)
773{
774 ConfigExtendedPageHeader_t hdr;
775 CONFIGPARMS cfg;
776 SasPhyPage0_t *buffer;
777 dma_addr_t dma_handle;
778 int error;
779
780 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
781 hdr.ExtPageLength = 0;
782 hdr.PageNumber = 0;
783 hdr.Reserved1 = 0;
784 hdr.Reserved2 = 0;
785 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
786 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
787
788 cfg.cfghdr.ehdr = &hdr;
789 cfg.dir = 0; /* read */
790 cfg.timeout = 10;
791
792 /* Get Phy Pg 0 for each Phy. */
793 cfg.physAddr = -1;
794 cfg.pageAddr = form + form_specific;
795 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
796
797 error = mpt_config(ioc, &cfg);
798 if (error)
799 goto out;
800
801 if (!hdr.ExtPageLength) {
802 error = -ENXIO;
803 goto out;
804 }
805
806 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
807 &dma_handle);
808 if (!buffer) {
809 error = -ENOMEM;
810 goto out;
811 }
812
813 cfg.physAddr = dma_handle;
814 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
815
816 error = mpt_config(ioc, &cfg);
817 if (error)
818 goto out_free_consistent;
819
820 mptsas_print_phy_pg0(buffer);
821
822 phy_info->hw_link_rate = buffer->HwLinkRate;
823 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
824 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
825 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
826
827 out_free_consistent:
828 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
829 buffer, dma_handle);
830 out:
831 return error;
832}
833
834static int
835mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
836 u32 form, u32 form_specific)
837{
838 ConfigExtendedPageHeader_t hdr;
839 CONFIGPARMS cfg;
840 SasDevicePage0_t *buffer;
841 dma_addr_t dma_handle;
842 __le64 sas_address;
843 int error;
844
845 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
846 hdr.ExtPageLength = 0;
847 hdr.PageNumber = 0;
848 hdr.Reserved1 = 0;
849 hdr.Reserved2 = 0;
850 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
851 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
852
853 cfg.cfghdr.ehdr = &hdr;
854 cfg.pageAddr = form + form_specific;
855 cfg.physAddr = -1;
856 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
857 cfg.dir = 0; /* read */
858 cfg.timeout = 10;
859
860 error = mpt_config(ioc, &cfg);
861 if (error)
862 goto out;
863 if (!hdr.ExtPageLength) {
864 error = -ENXIO;
865 goto out;
866 }
867
868 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
869 &dma_handle);
870 if (!buffer) {
871 error = -ENOMEM;
872 goto out;
873 }
874
875 cfg.physAddr = dma_handle;
876 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
877
878 error = mpt_config(ioc, &cfg);
879 if (error)
880 goto out_free_consistent;
881
882 mptsas_print_device_pg0(buffer);
883
884 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -0700885 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +0100886 device_info->handle_enclosure =
887 le16_to_cpu(buffer->EnclosureHandle);
888 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200889 device_info->phy_id = buffer->PhyNum;
890 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100891 device_info->id = buffer->TargetID;
892 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200893 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
894 device_info->sas_address = le64_to_cpu(sas_address);
895 device_info->device_info =
896 le32_to_cpu(buffer->DeviceInfo);
897
898 out_free_consistent:
899 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
900 buffer, dma_handle);
901 out:
902 return error;
903}
904
905static int
906mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
907 u32 form, u32 form_specific)
908{
909 ConfigExtendedPageHeader_t hdr;
910 CONFIGPARMS cfg;
911 SasExpanderPage0_t *buffer;
912 dma_addr_t dma_handle;
913 int error;
914
915 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
916 hdr.ExtPageLength = 0;
917 hdr.PageNumber = 0;
918 hdr.Reserved1 = 0;
919 hdr.Reserved2 = 0;
920 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
921 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
922
923 cfg.cfghdr.ehdr = &hdr;
924 cfg.physAddr = -1;
925 cfg.pageAddr = form + form_specific;
926 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
927 cfg.dir = 0; /* read */
928 cfg.timeout = 10;
929
930 error = mpt_config(ioc, &cfg);
931 if (error)
932 goto out;
933
934 if (!hdr.ExtPageLength) {
935 error = -ENXIO;
936 goto out;
937 }
938
939 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
940 &dma_handle);
941 if (!buffer) {
942 error = -ENOMEM;
943 goto out;
944 }
945
946 cfg.physAddr = dma_handle;
947 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
948
949 error = mpt_config(ioc, &cfg);
950 if (error)
951 goto out_free_consistent;
952
953 /* save config data */
954 port_info->num_phys = buffer->NumPhys;
955 port_info->handle = le16_to_cpu(buffer->DevHandle);
956 port_info->phy_info = kcalloc(port_info->num_phys,
957 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
958 if (!port_info->phy_info) {
959 error = -ENOMEM;
960 goto out_free_consistent;
961 }
962
963 out_free_consistent:
964 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
965 buffer, dma_handle);
966 out:
967 return error;
968}
969
970static int
971mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
972 u32 form, u32 form_specific)
973{
974 ConfigExtendedPageHeader_t hdr;
975 CONFIGPARMS cfg;
976 SasExpanderPage1_t *buffer;
977 dma_addr_t dma_handle;
978 int error;
979
980 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
981 hdr.ExtPageLength = 0;
982 hdr.PageNumber = 1;
983 hdr.Reserved1 = 0;
984 hdr.Reserved2 = 0;
985 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
986 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
987
988 cfg.cfghdr.ehdr = &hdr;
989 cfg.physAddr = -1;
990 cfg.pageAddr = form + form_specific;
991 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
992 cfg.dir = 0; /* read */
993 cfg.timeout = 10;
994
995 error = mpt_config(ioc, &cfg);
996 if (error)
997 goto out;
998
999 if (!hdr.ExtPageLength) {
1000 error = -ENXIO;
1001 goto out;
1002 }
1003
1004 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1005 &dma_handle);
1006 if (!buffer) {
1007 error = -ENOMEM;
1008 goto out;
1009 }
1010
1011 cfg.physAddr = dma_handle;
1012 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1013
1014 error = mpt_config(ioc, &cfg);
1015 if (error)
1016 goto out_free_consistent;
1017
1018
1019 mptsas_print_expander_pg1(buffer);
1020
1021 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001022 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001023 phy_info->port_id = buffer->PhysicalPort;
1024 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1025 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1026 phy_info->hw_link_rate = buffer->HwLinkRate;
1027 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1028 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1029
1030
1031 out_free_consistent:
1032 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1033 buffer, dma_handle);
1034 out:
1035 return error;
1036}
1037
Moore, Ericc73787ee2006-01-26 16:20:06 -07001038/*
1039 * Returns true if there is a scsi end device
1040 */
1041static inline int
1042mptsas_is_end_device(struct mptsas_devinfo * attached)
1043{
1044 if ((attached->handle) &&
1045 (attached->device_info &
1046 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
1047 ((attached->device_info &
1048 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
1049 (attached->device_info &
1050 MPI_SAS_DEVICE_INFO_STP_TARGET) |
1051 (attached->device_info &
1052 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
1053 return 1;
1054 else
1055 return 0;
1056}
1057
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001058static void
1059mptsas_parse_device_info(struct sas_identify *identify,
1060 struct mptsas_devinfo *device_info)
1061{
1062 u16 protocols;
1063
1064 identify->sas_address = device_info->sas_address;
1065 identify->phy_identifier = device_info->phy_id;
1066
1067 /*
1068 * Fill in Phy Initiator Port Protocol.
1069 * Bits 6:3, more than one bit can be set, fall through cases.
1070 */
1071 protocols = device_info->device_info & 0x78;
1072 identify->initiator_port_protocols = 0;
1073 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1074 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1075 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1076 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1077 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1078 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1079 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1080 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1081
1082 /*
1083 * Fill in Phy Target Port Protocol.
1084 * Bits 10:7, more than one bit can be set, fall through cases.
1085 */
1086 protocols = device_info->device_info & 0x780;
1087 identify->target_port_protocols = 0;
1088 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1089 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1090 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1091 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1092 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1093 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1094 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1095 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1096
1097 /*
1098 * Fill in Attached device type.
1099 */
1100 switch (device_info->device_info &
1101 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1102 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1103 identify->device_type = SAS_PHY_UNUSED;
1104 break;
1105 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1106 identify->device_type = SAS_END_DEVICE;
1107 break;
1108 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1109 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1110 break;
1111 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1112 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1113 break;
1114 }
1115}
1116
1117static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001118 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001119{
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001120 struct sas_phy *phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001121 int error;
1122
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001123 phy = sas_phy_alloc(dev, index);
1124 if (!phy)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001125 return -ENOMEM;
1126
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001127 phy->port_identifier = phy_info->port_id;
1128 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001129
1130 /*
1131 * Set Negotiated link rate.
1132 */
1133 switch (phy_info->negotiated_link_rate) {
1134 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001135 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001136 break;
1137 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001138 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001139 break;
1140 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001141 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001142 break;
1143 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001144 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001145 break;
1146 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1147 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1148 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001149 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001150 break;
1151 }
1152
1153 /*
1154 * Set Max hardware link rate.
1155 */
1156 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1157 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001158 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001159 break;
1160 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001161 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001162 break;
1163 default:
1164 break;
1165 }
1166
1167 /*
1168 * Set Max programmed link rate.
1169 */
1170 switch (phy_info->programmed_link_rate &
1171 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1172 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001173 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001174 break;
1175 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001176 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001177 break;
1178 default:
1179 break;
1180 }
1181
1182 /*
1183 * Set Min hardware link rate.
1184 */
1185 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1186 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001187 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001188 break;
1189 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001190 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001191 break;
1192 default:
1193 break;
1194 }
1195
1196 /*
1197 * Set Min programmed link rate.
1198 */
1199 switch (phy_info->programmed_link_rate &
1200 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1201 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001202 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001203 break;
1204 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001205 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001206 break;
1207 default:
1208 break;
1209 }
1210
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001211 if (local)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001212 phy->local_attached = 1;
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001213
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001214 error = sas_phy_add(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001215 if (error) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001216 sas_phy_free(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001217 return error;
1218 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001219 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001220
1221 if (phy_info->attached.handle) {
1222 struct sas_rphy *rphy;
1223
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001224 rphy = sas_rphy_alloc(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001225 if (!rphy)
1226 return 0; /* non-fatal: an rphy can be added later */
1227
1228 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1229 error = sas_rphy_add(rphy);
1230 if (error) {
1231 sas_rphy_free(rphy);
1232 return error;
1233 }
1234
1235 phy_info->rphy = rphy;
1236 }
1237
1238 return 0;
1239}
1240
1241static int
1242mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
1243{
1244 struct mptsas_portinfo *port_info;
1245 u32 handle = 0xFFFF;
1246 int error = -ENOMEM, i;
1247
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001248 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001249 if (!port_info)
1250 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001251
1252 error = mptsas_sas_io_unit_pg0(ioc, port_info);
1253 if (error)
1254 goto out_free_port_info;
1255
Moore, Eric816aa902006-01-13 16:25:20 -07001256 ioc->num_ports = port_info->num_phys;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001257 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001258 list_add_tail(&port_info->list, &ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001259 mutex_unlock(&ioc->sas_topology_mutex);
1260
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001261 for (i = 0; i < port_info->num_phys; i++) {
1262 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1263 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1264 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1265
1266 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1267 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1268 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02001269 port_info->phy_info[i].identify.phy_id =
1270 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001271 handle = port_info->phy_info[i].identify.handle;
1272
1273 if (port_info->phy_info[i].attached.handle) {
1274 mptsas_sas_device_pg0(ioc,
1275 &port_info->phy_info[i].attached,
1276 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1277 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1278 port_info->phy_info[i].attached.handle);
1279 }
1280
1281 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001282 &port_info->phy_info[i], *index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001283 (*index)++;
1284 }
1285
1286 return 0;
1287
1288 out_free_port_info:
1289 kfree(port_info);
1290 out:
1291 return error;
1292}
1293
1294static int
1295mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1296{
1297 struct mptsas_portinfo *port_info, *p;
1298 int error = -ENOMEM, i, j;
1299
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001300 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001301 if (!port_info)
1302 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001303
1304 error = mptsas_sas_expander_pg0(ioc, port_info,
1305 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1306 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1307 if (error)
1308 goto out_free_port_info;
1309
1310 *handle = port_info->handle;
1311
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001312 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001313 list_add_tail(&port_info->list, &ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001314 mutex_unlock(&ioc->sas_topology_mutex);
1315
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001316 for (i = 0; i < port_info->num_phys; i++) {
1317 struct device *parent;
1318
1319 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1320 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1321 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1322
1323 if (port_info->phy_info[i].identify.handle) {
1324 mptsas_sas_device_pg0(ioc,
1325 &port_info->phy_info[i].identify,
1326 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1327 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1328 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001329 port_info->phy_info[i].identify.phy_id =
1330 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001331 }
1332
1333 if (port_info->phy_info[i].attached.handle) {
1334 mptsas_sas_device_pg0(ioc,
1335 &port_info->phy_info[i].attached,
1336 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1337 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1338 port_info->phy_info[i].attached.handle);
1339 }
1340
1341 /*
1342 * If we find a parent port handle this expander is
1343 * attached to another expander, else it hangs of the
1344 * HBA phys.
1345 */
1346 parent = &ioc->sh->shost_gendev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001347 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001348 list_for_each_entry(p, &ioc->sas_topology, list) {
1349 for (j = 0; j < p->num_phys; j++) {
1350 if (port_info->phy_info[i].identify.handle ==
1351 p->phy_info[j].attached.handle)
1352 parent = &p->phy_info[j].rphy->dev;
1353 }
1354 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001355 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001356
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001357 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
1358 *index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001359 (*index)++;
1360 }
1361
1362 return 0;
1363
1364 out_free_port_info:
1365 kfree(port_info);
1366 out:
1367 return error;
1368}
1369
1370static void
1371mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1372{
1373 u32 handle = 0xFFFF;
1374 int index = 0;
1375
1376 mptsas_probe_hba_phys(ioc, &index);
1377 while (!mptsas_probe_expander_phys(ioc, &handle, &index))
1378 ;
1379}
1380
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001381static struct mptsas_phyinfo *
1382mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
1383{
1384 struct mptsas_portinfo *port_info;
1385 struct mptsas_devinfo device_info;
1386 struct mptsas_phyinfo *phy_info = NULL;
1387 int i, error;
1388
1389 /*
1390 * Retrieve the parent sas_address
1391 */
1392 error = mptsas_sas_device_pg0(ioc, &device_info,
1393 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1394 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1395 parent_handle);
1396 if (error) {
1397 printk("mptsas: failed to retrieve device page\n");
1398 return NULL;
1399 }
1400
1401 /*
1402 * The phy_info structures are never deallocated during lifetime of
1403 * a host, so the code below is safe without additional refcounting.
1404 */
1405 mutex_lock(&ioc->sas_topology_mutex);
1406 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1407 for (i = 0; i < port_info->num_phys; i++) {
1408 if (port_info->phy_info[i].identify.sas_address ==
1409 device_info.sas_address &&
1410 port_info->phy_info[i].phy_id == phy_id) {
1411 phy_info = &port_info->phy_info[i];
1412 break;
1413 }
1414 }
1415 }
1416 mutex_unlock(&ioc->sas_topology_mutex);
1417
1418 return phy_info;
1419}
1420
1421static struct mptsas_phyinfo *
Moore, Ericc73787ee2006-01-26 16:20:06 -07001422mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001423{
1424 struct mptsas_portinfo *port_info;
1425 struct mptsas_phyinfo *phy_info = NULL;
1426 int i;
1427
1428 /*
1429 * The phy_info structures are never deallocated during lifetime of
1430 * a host, so the code below is safe without additional refcounting.
1431 */
1432 mutex_lock(&ioc->sas_topology_mutex);
1433 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Moore, Ericc73787ee2006-01-26 16:20:06 -07001434 for (i = 0; i < port_info->num_phys; i++)
1435 if (mptsas_is_end_device(&port_info->phy_info[i].attached))
1436 if (port_info->phy_info[i].attached.id == id) {
1437 phy_info = &port_info->phy_info[i];
1438 break;
1439 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001440 }
1441 mutex_unlock(&ioc->sas_topology_mutex);
1442
1443 return phy_info;
1444}
1445
1446static void
1447mptsas_hotplug_work(void *arg)
1448{
1449 struct mptsas_hotplug_event *ev = arg;
1450 MPT_ADAPTER *ioc = ev->ioc;
1451 struct mptsas_phyinfo *phy_info;
1452 struct sas_rphy *rphy;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001453 struct scsi_device *sdev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001454 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001455 struct mptsas_devinfo sas_device;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001456
1457 switch (ev->event_type) {
1458 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001459
Moore, Ericc73787ee2006-01-26 16:20:06 -07001460 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001461 if (!phy_info) {
1462 printk("mptsas: remove event for non-existant PHY.\n");
1463 break;
1464 }
1465
Moore, Ericc73787ee2006-01-26 16:20:06 -07001466 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1467 ds = "ssp";
1468 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1469 ds = "stp";
1470 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1471 ds = "sata";
1472
1473 printk(MYIOC_s_INFO_FMT
1474 "removing %s device, channel %d, id %d, phy %d\n",
1475 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
1476
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001477 if (phy_info->rphy) {
1478 sas_rphy_delete(phy_info->rphy);
1479 phy_info->rphy = NULL;
1480 }
1481 break;
1482 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07001483
1484 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01001485 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07001486 */
Christoph Hellwige3094442006-02-16 13:25:36 +01001487 if (mptsas_sas_device_pg0(ioc, &sas_device,
1488 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
1489 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id))
1490 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001491
1492 phy_info = mptsas_find_phyinfo_by_parent(ioc,
Christoph Hellwige3094442006-02-16 13:25:36 +01001493 sas_device.handle_parent, sas_device.phy_id);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001494 if (!phy_info) {
1495 printk("mptsas: add event for non-existant PHY.\n");
1496 break;
1497 }
1498
1499 if (phy_info->rphy) {
1500 printk("mptsas: trying to add existing device.\n");
1501 break;
1502 }
1503
Christoph Hellwige3094442006-02-16 13:25:36 +01001504 memcpy(&phy_info->attached, &sas_device,
1505 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001506
Moore, Ericc73787ee2006-01-26 16:20:06 -07001507 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1508 ds = "ssp";
1509 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1510 ds = "stp";
1511 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1512 ds = "sata";
1513
1514 printk(MYIOC_s_INFO_FMT
1515 "attaching %s device, channel %d, id %d, phy %d\n",
1516 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1517
1518
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001519 rphy = sas_rphy_alloc(phy_info->phy);
1520 if (!rphy)
1521 break; /* non-fatal: an rphy can be added later */
1522
1523 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1524 if (sas_rphy_add(rphy)) {
1525 sas_rphy_free(rphy);
1526 break;
1527 }
1528
1529 phy_info->rphy = rphy;
1530 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001531 case MPTSAS_ADD_RAID:
1532 sdev = scsi_device_lookup(
1533 ioc->sh,
1534 ioc->num_ports,
1535 ev->id,
1536 0);
1537 if (sdev) {
1538 scsi_device_put(sdev);
1539 break;
1540 }
1541 printk(MYIOC_s_INFO_FMT
1542 "attaching device, channel %d, id %d\n",
1543 ioc->name, ioc->num_ports, ev->id);
1544 scsi_add_device(ioc->sh,
1545 ioc->num_ports,
1546 ev->id,
1547 0);
1548 mpt_findImVolumes(ioc);
1549 break;
1550 case MPTSAS_DEL_RAID:
1551 sdev = scsi_device_lookup(
1552 ioc->sh,
1553 ioc->num_ports,
1554 ev->id,
1555 0);
1556 if (!sdev)
1557 break;
1558 printk(MYIOC_s_INFO_FMT
1559 "removing device, channel %d, id %d\n",
1560 ioc->name, ioc->num_ports, ev->id);
1561 scsi_remove_device(sdev);
1562 scsi_device_put(sdev);
1563 mpt_findImVolumes(ioc);
1564 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001565 }
1566
1567 kfree(ev);
1568}
1569
1570static void
1571mptscsih_send_sas_event(MPT_ADAPTER *ioc,
1572 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
1573{
1574 struct mptsas_hotplug_event *ev;
1575 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
1576 __le64 sas_address;
1577
1578 if ((device_info &
1579 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
1580 MPI_SAS_DEVICE_INFO_STP_TARGET |
1581 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
1582 return;
1583
1584 if ((sas_event_data->ReasonCode &
1585 (MPI_EVENT_SAS_DEV_STAT_RC_ADDED |
1586 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0)
1587 return;
1588
1589 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1590 if (!ev) {
1591 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1592 return;
1593 }
1594
1595
1596 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1597 ev->ioc = ioc;
1598 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
1599 ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
1600 ev->channel = sas_event_data->Bus;
1601 ev->id = sas_event_data->TargetID;
1602 ev->phy_id = sas_event_data->PhyNum;
1603 memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64));
1604 ev->sas_address = le64_to_cpu(sas_address);
1605 ev->device_info = device_info;
1606
1607 if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
1608 ev->event_type = MPTSAS_ADD_DEVICE;
1609 else
1610 ev->event_type = MPTSAS_DEL_DEVICE;
1611
1612 schedule_work(&ev->work);
1613}
1614
Moore, Ericc73787ee2006-01-26 16:20:06 -07001615static void
1616mptscsih_send_raid_event(MPT_ADAPTER *ioc,
1617 EVENT_DATA_RAID *raid_event_data)
1618{
1619 struct mptsas_hotplug_event *ev;
1620 RAID_VOL0_STATUS * volumeStatus;
1621
1622 if (ioc->bus_type != SAS)
1623 return;
1624
1625 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1626 if (!ev) {
1627 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1628 return;
1629 }
1630
1631 memset(ev,0,sizeof(struct mptsas_hotplug_event));
1632 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1633 ev->ioc = ioc;
1634 ev->id = raid_event_data->VolumeID;
1635
1636 switch (raid_event_data->ReasonCode) {
1637 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
1638 ev->event_type = MPTSAS_ADD_DEVICE;
1639 break;
1640 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
1641 ev->event_type = MPTSAS_DEL_DEVICE;
1642 break;
1643 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
1644 ev->event_type = MPTSAS_DEL_RAID;
1645 break;
1646 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
1647 ev->event_type = MPTSAS_ADD_RAID;
1648 break;
1649 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
1650 volumeStatus = (RAID_VOL0_STATUS *) &
1651 raid_event_data->SettingsStatus;
1652 ev->event_type = (volumeStatus->State ==
1653 MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
1654 MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
1655 break;
1656 default:
1657 break;
1658 }
1659 schedule_work(&ev->work);
1660}
1661
Moore, Eric79de2782006-01-25 18:05:15 -07001662/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1663/* work queue thread to clear the persitency table */
1664static void
1665mptscsih_sas_persist_clear_table(void * arg)
1666{
1667 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
1668
1669 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
1670}
1671
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001672static int
1673mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
1674{
Moore, Ericc73787ee2006-01-26 16:20:06 -07001675 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001676 u8 event = le32_to_cpu(reply->Event) & 0xFF;
1677
1678 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07001679 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001680
1681 switch (event) {
1682 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1683 mptscsih_send_sas_event(ioc,
1684 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001685 break;
1686 case MPI_EVENT_INTEGRATED_RAID:
1687 mptscsih_send_raid_event(ioc,
1688 (EVENT_DATA_RAID *)reply->Data);
1689 break;
Moore, Eric79de2782006-01-25 18:05:15 -07001690 case MPI_EVENT_PERSISTENT_TABLE_FULL:
1691 INIT_WORK(&ioc->mptscsih_persistTask,
1692 mptscsih_sas_persist_clear_table,
1693 (void *)ioc);
1694 schedule_work(&ioc->mptscsih_persistTask);
1695 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001696 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07001697 rc = mptscsih_event_process(ioc, reply);
1698 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001699 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07001700 out:
1701
1702 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001703}
1704
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001705static int
1706mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1707{
1708 struct Scsi_Host *sh;
1709 MPT_SCSI_HOST *hd;
1710 MPT_ADAPTER *ioc;
1711 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001712 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001713 int numSGE = 0;
1714 int scale;
1715 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001716 int error=0;
1717 int r;
1718
1719 r = mpt_attach(pdev,id);
1720 if (r)
1721 return r;
1722
1723 ioc = pci_get_drvdata(pdev);
1724 ioc->DoneCtx = mptsasDoneCtx;
1725 ioc->TaskCtx = mptsasTaskCtx;
1726 ioc->InternalCtx = mptsasInternalCtx;
1727
1728 /* Added sanity check on readiness of the MPT adapter.
1729 */
1730 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1731 printk(MYIOC_s_WARN_FMT
1732 "Skipping because it's not operational!\n",
1733 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001734 error = -ENODEV;
1735 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001736 }
1737
1738 if (!ioc->active) {
1739 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1740 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001741 error = -ENODEV;
1742 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001743 }
1744
1745 /* Sanity check - ensure at least 1 port is INITIATOR capable
1746 */
1747 ioc_cap = 0;
1748 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
1749 if (ioc->pfacts[ii].ProtocolFlags &
1750 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1751 ioc_cap++;
1752 }
1753
1754 if (!ioc_cap) {
1755 printk(MYIOC_s_WARN_FMT
1756 "Skipping ioc=%p because SCSI Initiator mode "
1757 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06001758 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001759 }
1760
1761 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
1762 if (!sh) {
1763 printk(MYIOC_s_WARN_FMT
1764 "Unable to register controller with SCSI subsystem\n",
1765 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001766 error = -1;
1767 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001768 }
1769
1770 spin_lock_irqsave(&ioc->FreeQlock, flags);
1771
1772 /* Attach the SCSI Host to the IOC structure
1773 */
1774 ioc->sh = sh;
1775
1776 sh->io_port = 0;
1777 sh->n_io_port = 0;
1778 sh->irq = 0;
1779
1780 /* set 16 byte cdb's */
1781 sh->max_cmd_len = 16;
1782
1783 sh->max_id = ioc->pfacts->MaxDevices + 1;
1784
1785 sh->transportt = mptsas_transport_template;
1786
1787 sh->max_lun = MPT_LAST_LUN + 1;
1788 sh->max_channel = 0;
1789 sh->this_id = ioc->pfacts[0].PortSCSIID;
1790
1791 /* Required entry.
1792 */
1793 sh->unique_id = ioc->id;
1794
1795 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001796 mutex_init(&ioc->sas_topology_mutex);
1797
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01001798 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001799 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001800
1801 /* Verify that we won't exceed the maximum
1802 * number of chain buffers
1803 * We can optimize: ZZ = req_sz/sizeof(SGE)
1804 * For 32bit SGE's:
1805 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1806 * + (req_sz - 64)/sizeof(SGE)
1807 * A slightly different algorithm is required for
1808 * 64bit SGEs.
1809 */
1810 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1811 if (sizeof(dma_addr_t) == sizeof(u64)) {
1812 numSGE = (scale - 1) *
1813 (ioc->facts.MaxChainDepth-1) + scale +
1814 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1815 sizeof(u32));
1816 } else {
1817 numSGE = 1 + (scale - 1) *
1818 (ioc->facts.MaxChainDepth-1) + scale +
1819 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1820 sizeof(u32));
1821 }
1822
1823 if (numSGE < sh->sg_tablesize) {
1824 /* Reset this value */
1825 dprintk((MYIOC_s_INFO_FMT
1826 "Resetting sg_tablesize to %d from %d\n",
1827 ioc->name, numSGE, sh->sg_tablesize));
1828 sh->sg_tablesize = numSGE;
1829 }
1830
1831 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1832
1833 hd = (MPT_SCSI_HOST *) sh->hostdata;
1834 hd->ioc = ioc;
1835
1836 /* SCSI needs scsi_cmnd lookup table!
1837 * (with size equal to req_depth*PtrSz!)
1838 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001839 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1840 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001841 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001842 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001843 }
1844
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001845 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1846 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001847
1848 /* Allocate memory for the device structures.
1849 * A non-Null pointer at an offset
1850 * indicates a device exists.
1851 * max_id = 1 + maximum id (hosts.h)
1852 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001853 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
1854 if (!hd->Targets) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001855 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001856 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001857 }
1858
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001859 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001860
1861 /* Clear the TM flags
1862 */
1863 hd->tmPending = 0;
1864 hd->tmState = TM_STATE_NONE;
1865 hd->resetPending = 0;
1866 hd->abortSCpnt = NULL;
1867
1868 /* Clear the pointer used to store
1869 * single-threaded commands, i.e., those
1870 * issued during a bus scan, dv and
1871 * configuration pages.
1872 */
1873 hd->cmdPtr = NULL;
1874
1875 /* Initialize this SCSI Hosts' timers
1876 * To use, set the timer expires field
1877 * and add_timer
1878 */
1879 init_timer(&hd->timer);
1880 hd->timer.data = (unsigned long) hd;
1881 hd->timer.function = mptscsih_timer_expired;
1882
1883 hd->mpt_pq_filter = mpt_pq_filter;
1884 ioc->sas_data.ptClear = mpt_pt_clear;
1885
1886 if (ioc->sas_data.ptClear==1) {
1887 mptbase_sas_persist_operation(
1888 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
1889 }
1890
1891 ddvprintk((MYIOC_s_INFO_FMT
1892 "mpt_pq_filter %x mpt_pq_filter %x\n",
1893 ioc->name,
1894 mpt_pq_filter,
1895 mpt_pq_filter));
1896
1897 init_waitqueue_head(&hd->scandv_waitq);
1898 hd->scandv_wait_done = 0;
1899 hd->last_queue_full = 0;
1900
1901 error = scsi_add_host(sh, &ioc->pcidev->dev);
1902 if (error) {
1903 dprintk((KERN_ERR MYNAM
1904 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001905 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001906 }
1907
1908 mptsas_scan_sas_topology(ioc);
1909
Moore, Eric816aa902006-01-13 16:25:20 -07001910 /*
1911 Reporting RAID volumes.
1912 */
1913 if (!ioc->raid_data.pIocPg2)
1914 return 0;
1915 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1916 return 0;
1917 for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
1918 scsi_add_device(sh,
1919 ioc->num_ports,
1920 ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
1921 0);
1922 }
1923
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001924 return 0;
1925
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001926out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001927
1928 mptscsih_remove(pdev);
1929 return error;
1930}
1931
1932static void __devexit mptsas_remove(struct pci_dev *pdev)
1933{
1934 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1935 struct mptsas_portinfo *p, *n;
1936
1937 sas_remove_host(ioc->sh);
1938
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001939 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001940 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
1941 list_del(&p->list);
1942 kfree(p);
1943 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001944 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001945
1946 mptscsih_remove(pdev);
1947}
1948
1949static struct pci_device_id mptsas_pci_table[] = {
1950 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
1951 PCI_ANY_ID, PCI_ANY_ID },
1952 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
1953 PCI_ANY_ID, PCI_ANY_ID },
1954 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
1955 PCI_ANY_ID, PCI_ANY_ID },
1956 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
1957 PCI_ANY_ID, PCI_ANY_ID },
1958 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
1959 PCI_ANY_ID, PCI_ANY_ID },
1960 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
1961 PCI_ANY_ID, PCI_ANY_ID },
1962 {0} /* Terminating entry */
1963};
1964MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
1965
1966
1967static struct pci_driver mptsas_driver = {
1968 .name = "mptsas",
1969 .id_table = mptsas_pci_table,
1970 .probe = mptsas_probe,
1971 .remove = __devexit_p(mptsas_remove),
1972 .shutdown = mptscsih_shutdown,
1973#ifdef CONFIG_PM
1974 .suspend = mptscsih_suspend,
1975 .resume = mptscsih_resume,
1976#endif
1977};
1978
1979static int __init
1980mptsas_init(void)
1981{
1982 show_mptmod_ver(my_NAME, my_VERSION);
1983
1984 mptsas_transport_template =
1985 sas_attach_transport(&mptsas_transport_functions);
1986 if (!mptsas_transport_template)
1987 return -ENODEV;
1988
1989 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
1990 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
1991 mptsasInternalCtx =
1992 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001993 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001994
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001995 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001996 devtprintk((KERN_INFO MYNAM
1997 ": Registered for IOC event notifications\n"));
1998 }
1999
2000 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
2001 dprintk((KERN_INFO MYNAM
2002 ": Registered for IOC reset notifications\n"));
2003 }
2004
2005 return pci_register_driver(&mptsas_driver);
2006}
2007
2008static void __exit
2009mptsas_exit(void)
2010{
2011 pci_unregister_driver(&mptsas_driver);
2012 sas_release_transport(mptsas_transport_template);
2013
2014 mpt_reset_deregister(mptsasDoneCtx);
2015 mpt_event_deregister(mptsasDoneCtx);
2016
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002017 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002018 mpt_deregister(mptsasInternalCtx);
2019 mpt_deregister(mptsasTaskCtx);
2020 mpt_deregister(mptsasDoneCtx);
2021}
2022
2023module_init(mptsas_init);
2024module_exit(mptsas_exit);