blob: ba555a60bf7f3498afb337698f1b88304febc8ee [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 Hellwig9a28f49a2006-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 Hellwig9a28f49a2006-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 Hellwig9a28f49a2006-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 Hellwig9a28f49a2006-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 Hellwig9a28f49a2006-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;
Moore, Eric914c2d82006-03-14 09:19:36 -0700353 u32 target_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200354 int i;
355
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100356 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200357 if (!vdev) {
358 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
359 hd->ioc->name, sizeof(VirtDevice));
360 return -ENOMEM;
361 }
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700362 sdev->hostdata = vdev;
363 starget = scsi_target(sdev);
364 vtarget = starget->hostdata;
Moore, Eric914c2d82006-03-14 09:19:36 -0700365 vtarget->ioc_id = hd->ioc->id;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700366 vdev->vtarget = vtarget;
367 if (vtarget->num_luns == 0) {
368 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
369 hd->Targets[sdev->id] = vtarget;
370 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200371
Moore, Eric816aa902006-01-13 16:25:20 -0700372 /*
373 RAID volumes placed beyond the last expected port.
374 */
375 if (sdev->channel == hd->ioc->num_ports) {
Moore, Eric914c2d82006-03-14 09:19:36 -0700376 target_id = sdev->id;
377 vtarget->bus_id = 0;
Moore, Eric816aa902006-01-13 16:25:20 -0700378 vdev->lun = 0;
379 goto out;
380 }
381
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700382 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +0100383 mutex_lock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200384 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
385 for (i = 0; i < p->num_phys; i++) {
386 if (p->phy_info[i].attached.sas_address ==
387 rphy->identify.sas_address) {
Moore, Eric914c2d82006-03-14 09:19:36 -0700388 target_id = p->phy_info[i].attached.id;
389 vtarget->bus_id = p->phy_info[i].attached.channel;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700390 vdev->lun = sdev->lun;
Moore, Eric914c2d82006-03-14 09:19:36 -0700391 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200392 goto out;
393 }
394 }
395 }
Christoph Hellwig9a28f49a2006-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, Eric914c2d82006-03-14 09:19:36 -0700402 vtarget->target_id = target_id;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700403 vtarget->num_luns++;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200404 return 0;
405}
406
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +0100407static void
408mptsas_slave_destroy(struct scsi_device *sdev)
409{
410 struct Scsi_Host *host = sdev->host;
411 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
412 struct sas_rphy *rphy;
413 struct mptsas_portinfo *p;
414 int i;
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700415 VirtDevice *vdev;
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +0100416
417 /*
418 * Handle hotplug removal case.
419 * We need to clear out attached data structure.
420 */
421 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
422
423 mutex_lock(&hd->ioc->sas_topology_mutex);
424 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
425 for (i = 0; i < p->num_phys; i++) {
426 if (p->phy_info[i].attached.sas_address ==
427 rphy->identify.sas_address) {
428 memset(&p->phy_info[i].attached, 0,
429 sizeof(struct mptsas_devinfo));
430 p->phy_info[i].rphy = NULL;
431 goto out;
432 }
433 }
434 }
435
436 out:
437 mutex_unlock(&hd->ioc->sas_topology_mutex);
438 /*
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700439 * Issue target reset to flush firmware outstanding commands.
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +0100440 */
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700441 vdev = sdev->hostdata;
442 if (vdev->configured_lun){
443 if (mptscsih_TMHandler(hd,
444 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
Moore, Eric914c2d82006-03-14 09:19:36 -0700445 vdev->vtarget->bus_id,
446 vdev->vtarget->target_id,
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700447 0, 0, 5 /* 5 second timeout */)
448 < 0){
449
450 /* The TM request failed!
451 * Fatal error case.
452 */
453 printk(MYIOC_s_WARN_FMT
454 "Error processing TaskMgmt id=%d TARGET_RESET\n",
455 hd->ioc->name,
Moore, Eric914c2d82006-03-14 09:19:36 -0700456 vdev->vtarget->target_id);
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700457
458 hd->tmPending = 0;
459 hd->tmState = TM_STATE_NONE;
460 }
461 }
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +0100462 mptscsih_slave_destroy(sdev);
463}
464
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200465static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700466 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200467 .proc_name = "mptsas",
468 .proc_info = mptscsih_proc_info,
469 .name = "MPT SPI Host",
470 .info = mptscsih_info,
471 .queuecommand = mptscsih_qcmd,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700472 .target_alloc = mptscsih_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200473 .slave_alloc = mptsas_slave_alloc,
474 .slave_configure = mptscsih_slave_configure,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700475 .target_destroy = mptscsih_target_destroy,
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +0100476 .slave_destroy = mptsas_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200477 .change_queue_depth = mptscsih_change_queue_depth,
478 .eh_abort_handler = mptscsih_abort,
479 .eh_device_reset_handler = mptscsih_dev_reset,
480 .eh_bus_reset_handler = mptscsih_bus_reset,
481 .eh_host_reset_handler = mptscsih_host_reset,
482 .bios_param = mptscsih_bios_param,
483 .can_queue = MPT_FC_CAN_QUEUE,
484 .this_id = -1,
485 .sg_tablesize = MPT_SCSI_SG_DEPTH,
486 .max_sectors = 8192,
487 .cmd_per_lun = 7,
488 .use_clustering = ENABLE_CLUSTERING,
489};
490
Christoph Hellwigb5141122005-10-28 22:07:41 +0200491static int mptsas_get_linkerrors(struct sas_phy *phy)
492{
493 MPT_ADAPTER *ioc = phy_to_ioc(phy);
494 ConfigExtendedPageHeader_t hdr;
495 CONFIGPARMS cfg;
496 SasPhyPage1_t *buffer;
497 dma_addr_t dma_handle;
498 int error;
499
500 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
501 hdr.ExtPageLength = 0;
502 hdr.PageNumber = 1 /* page number 1*/;
503 hdr.Reserved1 = 0;
504 hdr.Reserved2 = 0;
505 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
506 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
507
508 cfg.cfghdr.ehdr = &hdr;
509 cfg.physAddr = -1;
510 cfg.pageAddr = phy->identify.phy_identifier;
511 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
512 cfg.dir = 0; /* read */
513 cfg.timeout = 10;
514
515 error = mpt_config(ioc, &cfg);
516 if (error)
517 return error;
518 if (!hdr.ExtPageLength)
519 return -ENXIO;
520
521 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
522 &dma_handle);
523 if (!buffer)
524 return -ENOMEM;
525
526 cfg.physAddr = dma_handle;
527 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
528
529 error = mpt_config(ioc, &cfg);
530 if (error)
531 goto out_free_consistent;
532
533 mptsas_print_phy_pg1(buffer);
534
535 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
536 phy->running_disparity_error_count =
537 le32_to_cpu(buffer->RunningDisparityErrorCount);
538 phy->loss_of_dword_sync_count =
539 le32_to_cpu(buffer->LossDwordSynchCount);
540 phy->phy_reset_problem_count =
541 le32_to_cpu(buffer->PhyResetProblemCount);
542
543 out_free_consistent:
544 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
545 buffer, dma_handle);
546 return error;
547}
548
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200549static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
550 MPT_FRAME_HDR *reply)
551{
552 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
553 if (reply != NULL) {
554 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
555 memcpy(ioc->sas_mgmt.reply, reply,
556 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
557 }
558 complete(&ioc->sas_mgmt.done);
559 return 1;
560}
561
562static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
563{
564 MPT_ADAPTER *ioc = phy_to_ioc(phy);
565 SasIoUnitControlRequest_t *req;
566 SasIoUnitControlReply_t *reply;
567 MPT_FRAME_HDR *mf;
568 MPIHeader_t *hdr;
569 unsigned long timeleft;
570 int error = -ERESTARTSYS;
571
572 /* not implemented for expanders */
573 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
574 return -ENXIO;
575
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100576 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200577 goto out;
578
579 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
580 if (!mf) {
581 error = -ENOMEM;
582 goto out_unlock;
583 }
584
585 hdr = (MPIHeader_t *) mf;
586 req = (SasIoUnitControlRequest_t *)mf;
587 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
588 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
589 req->MsgContext = hdr->MsgContext;
590 req->Operation = hard_reset ?
591 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
592 req->PhyNum = phy->identify.phy_identifier;
593
594 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
595
596 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
597 10 * HZ);
598 if (!timeleft) {
599 /* On timeout reset the board */
600 mpt_free_msg_frame(ioc, mf);
601 mpt_HardResetHandler(ioc, CAN_SLEEP);
602 error = -ETIMEDOUT;
603 goto out_unlock;
604 }
605
606 /* a reply frame is expected */
607 if ((ioc->sas_mgmt.status &
608 MPT_IOCTL_STATUS_RF_VALID) == 0) {
609 error = -ENXIO;
610 goto out_unlock;
611 }
612
613 /* process the completed Reply Message Frame */
614 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
615 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
616 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
617 __FUNCTION__,
618 reply->IOCStatus,
619 reply->IOCLogInfo);
620 error = -ENXIO;
621 goto out_unlock;
622 }
623
624 error = 0;
625
626 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100627 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200628 out:
629 return error;
630}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200631
Christoph Hellwige3094442006-02-16 13:25:36 +0100632static int
633mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
634{
635 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
636 int i, error;
637 struct mptsas_portinfo *p;
638 struct mptsas_enclosure enclosure_info;
639 u64 enclosure_handle;
640
641 mutex_lock(&ioc->sas_topology_mutex);
642 list_for_each_entry(p, &ioc->sas_topology, list) {
643 for (i = 0; i < p->num_phys; i++) {
644 if (p->phy_info[i].attached.sas_address ==
645 rphy->identify.sas_address) {
646 enclosure_handle = p->phy_info[i].
647 attached.handle_enclosure;
648 goto found_info;
649 }
650 }
651 }
652 mutex_unlock(&ioc->sas_topology_mutex);
653 return -ENXIO;
654
655 found_info:
656 mutex_unlock(&ioc->sas_topology_mutex);
657 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
658 error = mptsas_sas_exclosure_pg0(ioc, &enclosure_info,
659 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
660 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
661 if (!error)
662 *identifier = enclosure_info.enclosure_logical_id;
663 return error;
664}
665
666static int
667mptsas_get_bay_identifier(struct sas_rphy *rphy)
668{
669 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
670 struct mptsas_portinfo *p;
671 int i, rc;
672
673 mutex_lock(&ioc->sas_topology_mutex);
674 list_for_each_entry(p, &ioc->sas_topology, list) {
675 for (i = 0; i < p->num_phys; i++) {
676 if (p->phy_info[i].attached.sas_address ==
677 rphy->identify.sas_address) {
678 rc = p->phy_info[i].attached.slot;
679 goto out;
680 }
681 }
682 }
683 rc = -ENXIO;
684 out:
685 mutex_unlock(&ioc->sas_topology_mutex);
686 return rc;
687}
688
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200689static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +0200690 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +0100691 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
692 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200693 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200694};
695
696static struct scsi_transport_template *mptsas_transport_template;
697
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200698static int
699mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
700{
701 ConfigExtendedPageHeader_t hdr;
702 CONFIGPARMS cfg;
703 SasIOUnitPage0_t *buffer;
704 dma_addr_t dma_handle;
705 int error, i;
706
707 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
708 hdr.ExtPageLength = 0;
709 hdr.PageNumber = 0;
710 hdr.Reserved1 = 0;
711 hdr.Reserved2 = 0;
712 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
713 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
714
715 cfg.cfghdr.ehdr = &hdr;
716 cfg.physAddr = -1;
717 cfg.pageAddr = 0;
718 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
719 cfg.dir = 0; /* read */
720 cfg.timeout = 10;
721
722 error = mpt_config(ioc, &cfg);
723 if (error)
724 goto out;
725 if (!hdr.ExtPageLength) {
726 error = -ENXIO;
727 goto out;
728 }
729
730 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
731 &dma_handle);
732 if (!buffer) {
733 error = -ENOMEM;
734 goto out;
735 }
736
737 cfg.physAddr = dma_handle;
738 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
739
740 error = mpt_config(ioc, &cfg);
741 if (error)
742 goto out_free_consistent;
743
744 port_info->num_phys = buffer->NumPhys;
745 port_info->phy_info = kcalloc(port_info->num_phys,
746 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
747 if (!port_info->phy_info) {
748 error = -ENOMEM;
749 goto out_free_consistent;
750 }
751
752 for (i = 0; i < port_info->num_phys; i++) {
753 mptsas_print_phy_data(&buffer->PhyData[i]);
754 port_info->phy_info[i].phy_id = i;
755 port_info->phy_info[i].port_id =
756 buffer->PhyData[i].Port;
757 port_info->phy_info[i].negotiated_link_rate =
758 buffer->PhyData[i].NegotiatedLinkRate;
759 }
760
761 out_free_consistent:
762 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
763 buffer, dma_handle);
764 out:
765 return error;
766}
767
768static int
769mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
770 u32 form, u32 form_specific)
771{
772 ConfigExtendedPageHeader_t hdr;
773 CONFIGPARMS cfg;
774 SasPhyPage0_t *buffer;
775 dma_addr_t dma_handle;
776 int error;
777
778 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
779 hdr.ExtPageLength = 0;
780 hdr.PageNumber = 0;
781 hdr.Reserved1 = 0;
782 hdr.Reserved2 = 0;
783 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
784 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
785
786 cfg.cfghdr.ehdr = &hdr;
787 cfg.dir = 0; /* read */
788 cfg.timeout = 10;
789
790 /* Get Phy Pg 0 for each Phy. */
791 cfg.physAddr = -1;
792 cfg.pageAddr = form + form_specific;
793 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
794
795 error = mpt_config(ioc, &cfg);
796 if (error)
797 goto out;
798
799 if (!hdr.ExtPageLength) {
800 error = -ENXIO;
801 goto out;
802 }
803
804 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
805 &dma_handle);
806 if (!buffer) {
807 error = -ENOMEM;
808 goto out;
809 }
810
811 cfg.physAddr = dma_handle;
812 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
813
814 error = mpt_config(ioc, &cfg);
815 if (error)
816 goto out_free_consistent;
817
818 mptsas_print_phy_pg0(buffer);
819
820 phy_info->hw_link_rate = buffer->HwLinkRate;
821 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
822 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
823 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
824
825 out_free_consistent:
826 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
827 buffer, dma_handle);
828 out:
829 return error;
830}
831
832static int
833mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
834 u32 form, u32 form_specific)
835{
836 ConfigExtendedPageHeader_t hdr;
837 CONFIGPARMS cfg;
838 SasDevicePage0_t *buffer;
839 dma_addr_t dma_handle;
840 __le64 sas_address;
841 int error;
842
843 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
844 hdr.ExtPageLength = 0;
845 hdr.PageNumber = 0;
846 hdr.Reserved1 = 0;
847 hdr.Reserved2 = 0;
848 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
849 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
850
851 cfg.cfghdr.ehdr = &hdr;
852 cfg.pageAddr = form + form_specific;
853 cfg.physAddr = -1;
854 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
855 cfg.dir = 0; /* read */
856 cfg.timeout = 10;
857
858 error = mpt_config(ioc, &cfg);
859 if (error)
860 goto out;
861 if (!hdr.ExtPageLength) {
862 error = -ENXIO;
863 goto out;
864 }
865
866 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
867 &dma_handle);
868 if (!buffer) {
869 error = -ENOMEM;
870 goto out;
871 }
872
873 cfg.physAddr = dma_handle;
874 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
875
876 error = mpt_config(ioc, &cfg);
877 if (error)
878 goto out_free_consistent;
879
880 mptsas_print_device_pg0(buffer);
881
882 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -0700883 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +0100884 device_info->handle_enclosure =
885 le16_to_cpu(buffer->EnclosureHandle);
886 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200887 device_info->phy_id = buffer->PhyNum;
888 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +0100889 device_info->id = buffer->TargetID;
890 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200891 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
892 device_info->sas_address = le64_to_cpu(sas_address);
893 device_info->device_info =
894 le32_to_cpu(buffer->DeviceInfo);
895
896 out_free_consistent:
897 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
898 buffer, dma_handle);
899 out:
900 return error;
901}
902
903static int
904mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
905 u32 form, u32 form_specific)
906{
907 ConfigExtendedPageHeader_t hdr;
908 CONFIGPARMS cfg;
909 SasExpanderPage0_t *buffer;
910 dma_addr_t dma_handle;
911 int error;
912
913 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
914 hdr.ExtPageLength = 0;
915 hdr.PageNumber = 0;
916 hdr.Reserved1 = 0;
917 hdr.Reserved2 = 0;
918 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
919 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
920
921 cfg.cfghdr.ehdr = &hdr;
922 cfg.physAddr = -1;
923 cfg.pageAddr = form + form_specific;
924 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
925 cfg.dir = 0; /* read */
926 cfg.timeout = 10;
927
928 error = mpt_config(ioc, &cfg);
929 if (error)
930 goto out;
931
932 if (!hdr.ExtPageLength) {
933 error = -ENXIO;
934 goto out;
935 }
936
937 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
938 &dma_handle);
939 if (!buffer) {
940 error = -ENOMEM;
941 goto out;
942 }
943
944 cfg.physAddr = dma_handle;
945 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
946
947 error = mpt_config(ioc, &cfg);
948 if (error)
949 goto out_free_consistent;
950
951 /* save config data */
952 port_info->num_phys = buffer->NumPhys;
953 port_info->handle = le16_to_cpu(buffer->DevHandle);
954 port_info->phy_info = kcalloc(port_info->num_phys,
955 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
956 if (!port_info->phy_info) {
957 error = -ENOMEM;
958 goto out_free_consistent;
959 }
960
961 out_free_consistent:
962 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
963 buffer, dma_handle);
964 out:
965 return error;
966}
967
968static int
969mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
970 u32 form, u32 form_specific)
971{
972 ConfigExtendedPageHeader_t hdr;
973 CONFIGPARMS cfg;
974 SasExpanderPage1_t *buffer;
975 dma_addr_t dma_handle;
976 int error;
977
978 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
979 hdr.ExtPageLength = 0;
980 hdr.PageNumber = 1;
981 hdr.Reserved1 = 0;
982 hdr.Reserved2 = 0;
983 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
984 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
985
986 cfg.cfghdr.ehdr = &hdr;
987 cfg.physAddr = -1;
988 cfg.pageAddr = form + form_specific;
989 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
990 cfg.dir = 0; /* read */
991 cfg.timeout = 10;
992
993 error = mpt_config(ioc, &cfg);
994 if (error)
995 goto out;
996
997 if (!hdr.ExtPageLength) {
998 error = -ENXIO;
999 goto out;
1000 }
1001
1002 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1003 &dma_handle);
1004 if (!buffer) {
1005 error = -ENOMEM;
1006 goto out;
1007 }
1008
1009 cfg.physAddr = dma_handle;
1010 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1011
1012 error = mpt_config(ioc, &cfg);
1013 if (error)
1014 goto out_free_consistent;
1015
1016
1017 mptsas_print_expander_pg1(buffer);
1018
1019 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001020 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001021 phy_info->port_id = buffer->PhysicalPort;
1022 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1023 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1024 phy_info->hw_link_rate = buffer->HwLinkRate;
1025 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1026 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1027
1028
1029 out_free_consistent:
1030 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1031 buffer, dma_handle);
1032 out:
1033 return error;
1034}
1035
Moore, Ericc73787ee2006-01-26 16:20:06 -07001036/*
1037 * Returns true if there is a scsi end device
1038 */
1039static inline int
1040mptsas_is_end_device(struct mptsas_devinfo * attached)
1041{
1042 if ((attached->handle) &&
1043 (attached->device_info &
1044 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
1045 ((attached->device_info &
1046 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
1047 (attached->device_info &
1048 MPI_SAS_DEVICE_INFO_STP_TARGET) |
1049 (attached->device_info &
1050 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
1051 return 1;
1052 else
1053 return 0;
1054}
1055
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001056static void
1057mptsas_parse_device_info(struct sas_identify *identify,
1058 struct mptsas_devinfo *device_info)
1059{
1060 u16 protocols;
1061
1062 identify->sas_address = device_info->sas_address;
1063 identify->phy_identifier = device_info->phy_id;
1064
1065 /*
1066 * Fill in Phy Initiator Port Protocol.
1067 * Bits 6:3, more than one bit can be set, fall through cases.
1068 */
1069 protocols = device_info->device_info & 0x78;
1070 identify->initiator_port_protocols = 0;
1071 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1072 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1073 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1074 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1075 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1076 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1077 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1078 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1079
1080 /*
1081 * Fill in Phy Target Port Protocol.
1082 * Bits 10:7, more than one bit can be set, fall through cases.
1083 */
1084 protocols = device_info->device_info & 0x780;
1085 identify->target_port_protocols = 0;
1086 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1087 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1088 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1089 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1090 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1091 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1092 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1093 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1094
1095 /*
1096 * Fill in Attached device type.
1097 */
1098 switch (device_info->device_info &
1099 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1100 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1101 identify->device_type = SAS_PHY_UNUSED;
1102 break;
1103 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1104 identify->device_type = SAS_END_DEVICE;
1105 break;
1106 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1107 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1108 break;
1109 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1110 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1111 break;
1112 }
1113}
1114
1115static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001116 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001117{
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001118 struct sas_phy *phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001119 int error;
1120
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001121 phy = sas_phy_alloc(dev, index);
1122 if (!phy)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001123 return -ENOMEM;
1124
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001125 phy->port_identifier = phy_info->port_id;
1126 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001127
1128 /*
1129 * Set Negotiated link rate.
1130 */
1131 switch (phy_info->negotiated_link_rate) {
1132 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001133 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001134 break;
1135 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001136 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001137 break;
1138 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001139 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001140 break;
1141 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001142 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001143 break;
1144 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1145 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1146 default:
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001147 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001148 break;
1149 }
1150
1151 /*
1152 * Set Max hardware link rate.
1153 */
1154 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1155 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001156 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001157 break;
1158 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001159 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001160 break;
1161 default:
1162 break;
1163 }
1164
1165 /*
1166 * Set Max programmed link rate.
1167 */
1168 switch (phy_info->programmed_link_rate &
1169 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1170 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001171 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001172 break;
1173 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001174 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001175 break;
1176 default:
1177 break;
1178 }
1179
1180 /*
1181 * Set Min hardware link rate.
1182 */
1183 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1184 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001185 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001186 break;
1187 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001188 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001189 break;
1190 default:
1191 break;
1192 }
1193
1194 /*
1195 * Set Min programmed link rate.
1196 */
1197 switch (phy_info->programmed_link_rate &
1198 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1199 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001200 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001201 break;
1202 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001203 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001204 break;
1205 default:
1206 break;
1207 }
1208
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001209 if (local)
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001210 phy->local_attached = 1;
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001211
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001212 error = sas_phy_add(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001213 if (error) {
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001214 sas_phy_free(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001215 return error;
1216 }
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001217 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001218
1219 if (phy_info->attached.handle) {
1220 struct sas_rphy *rphy;
1221
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001222 rphy = sas_rphy_alloc(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001223 if (!rphy)
1224 return 0; /* non-fatal: an rphy can be added later */
1225
1226 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1227 error = sas_rphy_add(rphy);
1228 if (error) {
1229 sas_rphy_free(rphy);
1230 return error;
1231 }
1232
1233 phy_info->rphy = rphy;
1234 }
1235
1236 return 0;
1237}
1238
1239static int
1240mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
1241{
1242 struct mptsas_portinfo *port_info;
1243 u32 handle = 0xFFFF;
1244 int error = -ENOMEM, i;
1245
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001246 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001247 if (!port_info)
1248 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001249
1250 error = mptsas_sas_io_unit_pg0(ioc, port_info);
1251 if (error)
1252 goto out_free_port_info;
1253
Moore, Eric816aa902006-01-13 16:25:20 -07001254 ioc->num_ports = port_info->num_phys;
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001255 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001256 list_add_tail(&port_info->list, &ioc->sas_topology);
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001257 mutex_unlock(&ioc->sas_topology_mutex);
1258
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001259 for (i = 0; i < port_info->num_phys; i++) {
1260 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1261 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1262 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1263
1264 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1265 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1266 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02001267 port_info->phy_info[i].identify.phy_id =
1268 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001269 handle = port_info->phy_info[i].identify.handle;
1270
1271 if (port_info->phy_info[i].attached.handle) {
1272 mptsas_sas_device_pg0(ioc,
1273 &port_info->phy_info[i].attached,
1274 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1275 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1276 port_info->phy_info[i].attached.handle);
1277 }
1278
1279 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001280 &port_info->phy_info[i], *index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001281 (*index)++;
1282 }
1283
1284 return 0;
1285
1286 out_free_port_info:
1287 kfree(port_info);
1288 out:
1289 return error;
1290}
1291
1292static int
1293mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1294{
1295 struct mptsas_portinfo *port_info, *p;
1296 int error = -ENOMEM, i, j;
1297
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001298 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001299 if (!port_info)
1300 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001301
1302 error = mptsas_sas_expander_pg0(ioc, port_info,
1303 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1304 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1305 if (error)
1306 goto out_free_port_info;
1307
1308 *handle = port_info->handle;
1309
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001310 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001311 list_add_tail(&port_info->list, &ioc->sas_topology);
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001312 mutex_unlock(&ioc->sas_topology_mutex);
1313
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001314 for (i = 0; i < port_info->num_phys; i++) {
1315 struct device *parent;
1316
1317 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1318 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1319 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1320
1321 if (port_info->phy_info[i].identify.handle) {
1322 mptsas_sas_device_pg0(ioc,
1323 &port_info->phy_info[i].identify,
1324 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1325 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1326 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001327 port_info->phy_info[i].identify.phy_id =
1328 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001329 }
1330
1331 if (port_info->phy_info[i].attached.handle) {
1332 mptsas_sas_device_pg0(ioc,
1333 &port_info->phy_info[i].attached,
1334 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1335 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1336 port_info->phy_info[i].attached.handle);
1337 }
1338
1339 /*
1340 * If we find a parent port handle this expander is
1341 * attached to another expander, else it hangs of the
1342 * HBA phys.
1343 */
1344 parent = &ioc->sh->shost_gendev;
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001345 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001346 list_for_each_entry(p, &ioc->sas_topology, list) {
1347 for (j = 0; j < p->num_phys; j++) {
1348 if (port_info->phy_info[i].identify.handle ==
1349 p->phy_info[j].attached.handle)
1350 parent = &p->phy_info[j].rphy->dev;
1351 }
1352 }
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001353 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001354
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001355 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
1356 *index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001357 (*index)++;
1358 }
1359
1360 return 0;
1361
1362 out_free_port_info:
1363 kfree(port_info);
1364 out:
1365 return error;
1366}
1367
1368static void
1369mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1370{
1371 u32 handle = 0xFFFF;
1372 int index = 0;
1373
1374 mptsas_probe_hba_phys(ioc, &index);
1375 while (!mptsas_probe_expander_phys(ioc, &handle, &index))
1376 ;
1377}
1378
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001379static struct mptsas_phyinfo *
1380mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
1381{
1382 struct mptsas_portinfo *port_info;
1383 struct mptsas_devinfo device_info;
1384 struct mptsas_phyinfo *phy_info = NULL;
1385 int i, error;
1386
1387 /*
1388 * Retrieve the parent sas_address
1389 */
1390 error = mptsas_sas_device_pg0(ioc, &device_info,
1391 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1392 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1393 parent_handle);
1394 if (error) {
1395 printk("mptsas: failed to retrieve device page\n");
1396 return NULL;
1397 }
1398
1399 /*
1400 * The phy_info structures are never deallocated during lifetime of
1401 * a host, so the code below is safe without additional refcounting.
1402 */
1403 mutex_lock(&ioc->sas_topology_mutex);
1404 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1405 for (i = 0; i < port_info->num_phys; i++) {
1406 if (port_info->phy_info[i].identify.sas_address ==
1407 device_info.sas_address &&
1408 port_info->phy_info[i].phy_id == phy_id) {
1409 phy_info = &port_info->phy_info[i];
1410 break;
1411 }
1412 }
1413 }
1414 mutex_unlock(&ioc->sas_topology_mutex);
1415
1416 return phy_info;
1417}
1418
1419static struct mptsas_phyinfo *
Moore, Ericc73787ee2006-01-26 16:20:06 -07001420mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001421{
1422 struct mptsas_portinfo *port_info;
1423 struct mptsas_phyinfo *phy_info = NULL;
1424 int i;
1425
1426 /*
1427 * The phy_info structures are never deallocated during lifetime of
1428 * a host, so the code below is safe without additional refcounting.
1429 */
1430 mutex_lock(&ioc->sas_topology_mutex);
1431 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Moore, Ericc73787ee2006-01-26 16:20:06 -07001432 for (i = 0; i < port_info->num_phys; i++)
1433 if (mptsas_is_end_device(&port_info->phy_info[i].attached))
1434 if (port_info->phy_info[i].attached.id == id) {
1435 phy_info = &port_info->phy_info[i];
1436 break;
1437 }
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001438 }
1439 mutex_unlock(&ioc->sas_topology_mutex);
1440
1441 return phy_info;
1442}
1443
1444static void
1445mptsas_hotplug_work(void *arg)
1446{
1447 struct mptsas_hotplug_event *ev = arg;
1448 MPT_ADAPTER *ioc = ev->ioc;
1449 struct mptsas_phyinfo *phy_info;
1450 struct sas_rphy *rphy;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001451 struct scsi_device *sdev;
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001452 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001453 struct mptsas_devinfo sas_device;
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001454
1455 switch (ev->event_type) {
1456 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001457
Moore, Ericc73787ee2006-01-26 16:20:06 -07001458 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001459 if (!phy_info) {
1460 printk("mptsas: remove event for non-existant PHY.\n");
1461 break;
1462 }
1463
Moore, Ericc73787ee2006-01-26 16:20:06 -07001464 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1465 ds = "ssp";
1466 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1467 ds = "stp";
1468 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1469 ds = "sata";
1470
1471 printk(MYIOC_s_INFO_FMT
1472 "removing %s device, channel %d, id %d, phy %d\n",
1473 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
1474
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001475 if (phy_info->rphy) {
1476 sas_rphy_delete(phy_info->rphy);
1477 phy_info->rphy = NULL;
1478 }
1479 break;
1480 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07001481
1482 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01001483 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07001484 */
Christoph Hellwige3094442006-02-16 13:25:36 +01001485 if (mptsas_sas_device_pg0(ioc, &sas_device,
1486 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
1487 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id))
1488 break;
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001489
1490 phy_info = mptsas_find_phyinfo_by_parent(ioc,
Christoph Hellwige3094442006-02-16 13:25:36 +01001491 sas_device.handle_parent, sas_device.phy_id);
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001492 if (!phy_info) {
1493 printk("mptsas: add event for non-existant PHY.\n");
1494 break;
1495 }
1496
1497 if (phy_info->rphy) {
1498 printk("mptsas: trying to add existing device.\n");
1499 break;
1500 }
1501
Christoph Hellwige3094442006-02-16 13:25:36 +01001502 memcpy(&phy_info->attached, &sas_device,
1503 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001504
Moore, Ericc73787ee2006-01-26 16:20:06 -07001505 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1506 ds = "ssp";
1507 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1508 ds = "stp";
1509 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1510 ds = "sata";
1511
1512 printk(MYIOC_s_INFO_FMT
1513 "attaching %s device, channel %d, id %d, phy %d\n",
1514 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1515
1516
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001517 rphy = sas_rphy_alloc(phy_info->phy);
1518 if (!rphy)
1519 break; /* non-fatal: an rphy can be added later */
1520
1521 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1522 if (sas_rphy_add(rphy)) {
1523 sas_rphy_free(rphy);
1524 break;
1525 }
1526
1527 phy_info->rphy = rphy;
1528 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001529 case MPTSAS_ADD_RAID:
1530 sdev = scsi_device_lookup(
1531 ioc->sh,
1532 ioc->num_ports,
1533 ev->id,
1534 0);
1535 if (sdev) {
1536 scsi_device_put(sdev);
1537 break;
1538 }
1539 printk(MYIOC_s_INFO_FMT
1540 "attaching device, channel %d, id %d\n",
1541 ioc->name, ioc->num_ports, ev->id);
1542 scsi_add_device(ioc->sh,
1543 ioc->num_ports,
1544 ev->id,
1545 0);
1546 mpt_findImVolumes(ioc);
1547 break;
1548 case MPTSAS_DEL_RAID:
1549 sdev = scsi_device_lookup(
1550 ioc->sh,
1551 ioc->num_ports,
1552 ev->id,
1553 0);
1554 if (!sdev)
1555 break;
1556 printk(MYIOC_s_INFO_FMT
1557 "removing device, channel %d, id %d\n",
1558 ioc->name, ioc->num_ports, ev->id);
1559 scsi_remove_device(sdev);
1560 scsi_device_put(sdev);
1561 mpt_findImVolumes(ioc);
1562 break;
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001563 }
1564
1565 kfree(ev);
1566}
1567
1568static void
1569mptscsih_send_sas_event(MPT_ADAPTER *ioc,
1570 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
1571{
1572 struct mptsas_hotplug_event *ev;
1573 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
1574 __le64 sas_address;
1575
1576 if ((device_info &
1577 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
1578 MPI_SAS_DEVICE_INFO_STP_TARGET |
1579 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
1580 return;
1581
1582 if ((sas_event_data->ReasonCode &
1583 (MPI_EVENT_SAS_DEV_STAT_RC_ADDED |
1584 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0)
1585 return;
1586
1587 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1588 if (!ev) {
1589 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1590 return;
1591 }
1592
1593
1594 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1595 ev->ioc = ioc;
1596 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
1597 ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
1598 ev->channel = sas_event_data->Bus;
1599 ev->id = sas_event_data->TargetID;
1600 ev->phy_id = sas_event_data->PhyNum;
1601 memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64));
1602 ev->sas_address = le64_to_cpu(sas_address);
1603 ev->device_info = device_info;
1604
1605 if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
1606 ev->event_type = MPTSAS_ADD_DEVICE;
1607 else
1608 ev->event_type = MPTSAS_DEL_DEVICE;
1609
1610 schedule_work(&ev->work);
1611}
1612
Moore, Ericc73787ee2006-01-26 16:20:06 -07001613static void
1614mptscsih_send_raid_event(MPT_ADAPTER *ioc,
1615 EVENT_DATA_RAID *raid_event_data)
1616{
1617 struct mptsas_hotplug_event *ev;
1618 RAID_VOL0_STATUS * volumeStatus;
1619
1620 if (ioc->bus_type != SAS)
1621 return;
1622
1623 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1624 if (!ev) {
1625 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1626 return;
1627 }
1628
1629 memset(ev,0,sizeof(struct mptsas_hotplug_event));
1630 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1631 ev->ioc = ioc;
1632 ev->id = raid_event_data->VolumeID;
1633
1634 switch (raid_event_data->ReasonCode) {
1635 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
1636 ev->event_type = MPTSAS_ADD_DEVICE;
1637 break;
1638 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
1639 ev->event_type = MPTSAS_DEL_DEVICE;
1640 break;
1641 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
1642 ev->event_type = MPTSAS_DEL_RAID;
1643 break;
1644 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
1645 ev->event_type = MPTSAS_ADD_RAID;
1646 break;
1647 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
1648 volumeStatus = (RAID_VOL0_STATUS *) &
1649 raid_event_data->SettingsStatus;
1650 ev->event_type = (volumeStatus->State ==
1651 MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
1652 MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
1653 break;
1654 default:
1655 break;
1656 }
1657 schedule_work(&ev->work);
1658}
1659
Moore, Eric79de2782006-01-25 18:05:15 -07001660/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1661/* work queue thread to clear the persitency table */
1662static void
1663mptscsih_sas_persist_clear_table(void * arg)
1664{
1665 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
1666
1667 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
1668}
1669
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001670static int
1671mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
1672{
Moore, Ericc73787ee2006-01-26 16:20:06 -07001673 int rc=1;
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001674 u8 event = le32_to_cpu(reply->Event) & 0xFF;
1675
1676 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07001677 goto out;
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001678
1679 switch (event) {
1680 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1681 mptscsih_send_sas_event(ioc,
1682 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001683 break;
1684 case MPI_EVENT_INTEGRATED_RAID:
1685 mptscsih_send_raid_event(ioc,
1686 (EVENT_DATA_RAID *)reply->Data);
1687 break;
Moore, Eric79de2782006-01-25 18:05:15 -07001688 case MPI_EVENT_PERSISTENT_TABLE_FULL:
1689 INIT_WORK(&ioc->mptscsih_persistTask,
1690 mptscsih_sas_persist_clear_table,
1691 (void *)ioc);
1692 schedule_work(&ioc->mptscsih_persistTask);
1693 break;
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001694 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07001695 rc = mptscsih_event_process(ioc, reply);
1696 break;
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001697 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07001698 out:
1699
1700 return rc;
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001701}
1702
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001703static int
1704mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1705{
1706 struct Scsi_Host *sh;
1707 MPT_SCSI_HOST *hd;
1708 MPT_ADAPTER *ioc;
1709 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001710 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001711 int numSGE = 0;
1712 int scale;
1713 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001714 int error=0;
1715 int r;
1716
1717 r = mpt_attach(pdev,id);
1718 if (r)
1719 return r;
1720
1721 ioc = pci_get_drvdata(pdev);
1722 ioc->DoneCtx = mptsasDoneCtx;
1723 ioc->TaskCtx = mptsasTaskCtx;
1724 ioc->InternalCtx = mptsasInternalCtx;
1725
1726 /* Added sanity check on readiness of the MPT adapter.
1727 */
1728 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1729 printk(MYIOC_s_WARN_FMT
1730 "Skipping because it's not operational!\n",
1731 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001732 error = -ENODEV;
1733 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001734 }
1735
1736 if (!ioc->active) {
1737 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1738 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001739 error = -ENODEV;
1740 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001741 }
1742
1743 /* Sanity check - ensure at least 1 port is INITIATOR capable
1744 */
1745 ioc_cap = 0;
1746 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
1747 if (ioc->pfacts[ii].ProtocolFlags &
1748 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1749 ioc_cap++;
1750 }
1751
1752 if (!ioc_cap) {
1753 printk(MYIOC_s_WARN_FMT
1754 "Skipping ioc=%p because SCSI Initiator mode "
1755 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06001756 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001757 }
1758
1759 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
1760 if (!sh) {
1761 printk(MYIOC_s_WARN_FMT
1762 "Unable to register controller with SCSI subsystem\n",
1763 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001764 error = -1;
1765 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001766 }
1767
1768 spin_lock_irqsave(&ioc->FreeQlock, flags);
1769
1770 /* Attach the SCSI Host to the IOC structure
1771 */
1772 ioc->sh = sh;
1773
1774 sh->io_port = 0;
1775 sh->n_io_port = 0;
1776 sh->irq = 0;
1777
1778 /* set 16 byte cdb's */
1779 sh->max_cmd_len = 16;
1780
1781 sh->max_id = ioc->pfacts->MaxDevices + 1;
1782
1783 sh->transportt = mptsas_transport_template;
1784
1785 sh->max_lun = MPT_LAST_LUN + 1;
1786 sh->max_channel = 0;
1787 sh->this_id = ioc->pfacts[0].PortSCSIID;
1788
1789 /* Required entry.
1790 */
1791 sh->unique_id = ioc->id;
1792
1793 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001794 mutex_init(&ioc->sas_topology_mutex);
1795
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01001796 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001797 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001798
1799 /* Verify that we won't exceed the maximum
1800 * number of chain buffers
1801 * We can optimize: ZZ = req_sz/sizeof(SGE)
1802 * For 32bit SGE's:
1803 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1804 * + (req_sz - 64)/sizeof(SGE)
1805 * A slightly different algorithm is required for
1806 * 64bit SGEs.
1807 */
1808 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1809 if (sizeof(dma_addr_t) == sizeof(u64)) {
1810 numSGE = (scale - 1) *
1811 (ioc->facts.MaxChainDepth-1) + scale +
1812 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1813 sizeof(u32));
1814 } else {
1815 numSGE = 1 + (scale - 1) *
1816 (ioc->facts.MaxChainDepth-1) + scale +
1817 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1818 sizeof(u32));
1819 }
1820
1821 if (numSGE < sh->sg_tablesize) {
1822 /* Reset this value */
1823 dprintk((MYIOC_s_INFO_FMT
1824 "Resetting sg_tablesize to %d from %d\n",
1825 ioc->name, numSGE, sh->sg_tablesize));
1826 sh->sg_tablesize = numSGE;
1827 }
1828
1829 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1830
1831 hd = (MPT_SCSI_HOST *) sh->hostdata;
1832 hd->ioc = ioc;
1833
1834 /* SCSI needs scsi_cmnd lookup table!
1835 * (with size equal to req_depth*PtrSz!)
1836 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001837 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1838 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001839 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001840 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001841 }
1842
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001843 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1844 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001845
1846 /* Allocate memory for the device structures.
1847 * A non-Null pointer at an offset
1848 * indicates a device exists.
1849 * max_id = 1 + maximum id (hosts.h)
1850 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001851 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
1852 if (!hd->Targets) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001853 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001854 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001855 }
1856
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001857 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001858
1859 /* Clear the TM flags
1860 */
1861 hd->tmPending = 0;
1862 hd->tmState = TM_STATE_NONE;
1863 hd->resetPending = 0;
1864 hd->abortSCpnt = NULL;
1865
1866 /* Clear the pointer used to store
1867 * single-threaded commands, i.e., those
1868 * issued during a bus scan, dv and
1869 * configuration pages.
1870 */
1871 hd->cmdPtr = NULL;
1872
1873 /* Initialize this SCSI Hosts' timers
1874 * To use, set the timer expires field
1875 * and add_timer
1876 */
1877 init_timer(&hd->timer);
1878 hd->timer.data = (unsigned long) hd;
1879 hd->timer.function = mptscsih_timer_expired;
1880
1881 hd->mpt_pq_filter = mpt_pq_filter;
1882 ioc->sas_data.ptClear = mpt_pt_clear;
1883
1884 if (ioc->sas_data.ptClear==1) {
1885 mptbase_sas_persist_operation(
1886 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
1887 }
1888
1889 ddvprintk((MYIOC_s_INFO_FMT
1890 "mpt_pq_filter %x mpt_pq_filter %x\n",
1891 ioc->name,
1892 mpt_pq_filter,
1893 mpt_pq_filter));
1894
1895 init_waitqueue_head(&hd->scandv_waitq);
1896 hd->scandv_wait_done = 0;
1897 hd->last_queue_full = 0;
1898
1899 error = scsi_add_host(sh, &ioc->pcidev->dev);
1900 if (error) {
1901 dprintk((KERN_ERR MYNAM
1902 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001903 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001904 }
1905
1906 mptsas_scan_sas_topology(ioc);
1907
Moore, Eric816aa902006-01-13 16:25:20 -07001908 /*
1909 Reporting RAID volumes.
1910 */
1911 if (!ioc->raid_data.pIocPg2)
1912 return 0;
1913 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1914 return 0;
1915 for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
1916 scsi_add_device(sh,
1917 ioc->num_ports,
1918 ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
1919 0);
1920 }
1921
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001922 return 0;
1923
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001924out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001925
1926 mptscsih_remove(pdev);
1927 return error;
1928}
1929
1930static void __devexit mptsas_remove(struct pci_dev *pdev)
1931{
1932 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1933 struct mptsas_portinfo *p, *n;
1934
1935 sas_remove_host(ioc->sh);
1936
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001937 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001938 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
1939 list_del(&p->list);
1940 kfree(p);
1941 }
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001942 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001943
1944 mptscsih_remove(pdev);
1945}
1946
1947static struct pci_device_id mptsas_pci_table[] = {
1948 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
1949 PCI_ANY_ID, PCI_ANY_ID },
1950 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
1951 PCI_ANY_ID, PCI_ANY_ID },
1952 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
1953 PCI_ANY_ID, PCI_ANY_ID },
1954 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
1955 PCI_ANY_ID, PCI_ANY_ID },
1956 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
1957 PCI_ANY_ID, PCI_ANY_ID },
1958 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
1959 PCI_ANY_ID, PCI_ANY_ID },
1960 {0} /* Terminating entry */
1961};
1962MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
1963
1964
1965static struct pci_driver mptsas_driver = {
1966 .name = "mptsas",
1967 .id_table = mptsas_pci_table,
1968 .probe = mptsas_probe,
1969 .remove = __devexit_p(mptsas_remove),
1970 .shutdown = mptscsih_shutdown,
1971#ifdef CONFIG_PM
1972 .suspend = mptscsih_suspend,
1973 .resume = mptscsih_resume,
1974#endif
1975};
1976
1977static int __init
1978mptsas_init(void)
1979{
1980 show_mptmod_ver(my_NAME, my_VERSION);
1981
1982 mptsas_transport_template =
1983 sas_attach_transport(&mptsas_transport_functions);
1984 if (!mptsas_transport_template)
1985 return -ENODEV;
1986
1987 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
1988 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
1989 mptsasInternalCtx =
1990 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001991 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001992
Christoph Hellwig9a28f49a2006-01-13 18:04:41 +01001993 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07001994 devtverboseprintk((KERN_INFO MYNAM
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001995 ": Registered for IOC event notifications\n"));
1996 }
1997
1998 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
1999 dprintk((KERN_INFO MYNAM
2000 ": Registered for IOC reset notifications\n"));
2001 }
2002
2003 return pci_register_driver(&mptsas_driver);
2004}
2005
2006static void __exit
2007mptsas_exit(void)
2008{
2009 pci_unregister_driver(&mptsas_driver);
2010 sas_release_transport(mptsas_transport_template);
2011
2012 mpt_reset_deregister(mptsasDoneCtx);
2013 mpt_event_deregister(mptsasDoneCtx);
2014
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002015 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002016 mpt_deregister(mptsasInternalCtx);
2017 mpt_deregister(mptsasTaskCtx);
2018 mpt_deregister(mptsasDoneCtx);
2019}
2020
2021module_init(mptsas_init);
2022module_exit(mptsas_exit);