[SCSI] aic7xxx: ahc_pci_write_config() fix
[deliverable/linux.git] / drivers / message / fusion / mptsas.c
CommitLineData
0c33b27d
CH
1/*
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)
9a28f49a 8 * Copyright (c) 2005-2006 Dell
0c33b27d
CH
9 */
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 */
da4fa655 86static int mptsasMgmtCtx = -1;
0c33b27d
CH
87
88
9a28f49a
CH
89enum mptsas_hotplug_action {
90 MPTSAS_ADD_DEVICE,
91 MPTSAS_DEL_DEVICE,
c73787ee
ME
92 MPTSAS_ADD_RAID,
93 MPTSAS_DEL_RAID,
9a28f49a
CH
94};
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;
f44e5461
ME
107 u8 phys_disk_num;
108 u8 phys_disk_num_valid;
9a28f49a
CH
109};
110
e6b2d76a
ME
111struct mptsas_discovery_event {
112 struct work_struct work;
113 MPT_ADAPTER *ioc;
114};
115
0c33b27d
CH
116/*
117 * SAS topology structures
118 *
119 * The MPT Fusion firmware interface spreads information about the
120 * SAS topology over many manufacture pages, thus we need some data
121 * structure to collect it and process it for the SAS transport class.
122 */
123
124struct mptsas_devinfo {
125 u16 handle; /* unique id to address this device */
c73787ee 126 u16 handle_parent; /* unique id to address parent device */
e3094447
CH
127 u16 handle_enclosure; /* enclosure identifier of the enclosure */
128 u16 slot; /* physical slot in enclosure */
0c33b27d
CH
129 u8 phy_id; /* phy number of parent device */
130 u8 port_id; /* sas physical port this device
131 is assoc'd with */
9a28f49a
CH
132 u8 id; /* logical target id of this device */
133 u8 channel; /* logical bus number of this device */
0c33b27d
CH
134 u64 sas_address; /* WWN of this device,
135 SATA is assigned by HBA,expander */
136 u32 device_info; /* bitfield detailed info about this device */
137};
138
139struct mptsas_phyinfo {
140 u8 phy_id; /* phy index */
141 u8 port_id; /* port number this phy is part of */
142 u8 negotiated_link_rate; /* nego'd link rate for this phy */
143 u8 hw_link_rate; /* hardware max/min phys link rate */
144 u8 programmed_link_rate; /* programmed max/min phy link rate */
145 struct mptsas_devinfo identify; /* point to phy device info */
146 struct mptsas_devinfo attached; /* point to attached device info */
9a28f49a 147 struct sas_phy *phy;
0c33b27d 148 struct sas_rphy *rphy;
f44e5461 149 struct scsi_target *starget;
0c33b27d
CH
150};
151
152struct mptsas_portinfo {
153 struct list_head list;
154 u16 handle; /* unique id to address this */
155 u8 num_phys; /* number of phys */
156 struct mptsas_phyinfo *phy_info;
157};
158
e3094447
CH
159struct mptsas_enclosure {
160 u64 enclosure_logical_id; /* The WWN for the enclosure */
161 u16 enclosure_handle; /* unique id to address this */
162 u16 flags; /* details enclosure management */
163 u16 num_slot; /* num slots */
164 u16 start_slot; /* first slot */
165 u8 start_id; /* starting logical target id */
166 u8 start_channel; /* starting logical channel id */
167 u8 sep_id; /* SEP device logical target id */
168 u8 sep_channel; /* SEP channel logical channel id */
169};
170
b5141128
CH
171#ifdef SASDEBUG
172static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
173{
174 printk("---- IO UNIT PAGE 0 ------------\n");
175 printk("Handle=0x%X\n",
176 le16_to_cpu(phy_data->AttachedDeviceHandle));
177 printk("Controller Handle=0x%X\n",
178 le16_to_cpu(phy_data->ControllerDevHandle));
179 printk("Port=0x%X\n", phy_data->Port);
180 printk("Port Flags=0x%X\n", phy_data->PortFlags);
181 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
182 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
183 printk("Controller PHY Device Info=0x%X\n",
184 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
185 printk("DiscoveryStatus=0x%X\n",
186 le32_to_cpu(phy_data->DiscoveryStatus));
187 printk("\n");
188}
189
190static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
191{
192 __le64 sas_address;
193
194 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
195
196 printk("---- SAS PHY PAGE 0 ------------\n");
197 printk("Attached Device Handle=0x%X\n",
198 le16_to_cpu(pg0->AttachedDevHandle));
199 printk("SAS Address=0x%llX\n",
200 (unsigned long long)le64_to_cpu(sas_address));
201 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
202 printk("Attached Device Info=0x%X\n",
203 le32_to_cpu(pg0->AttachedDeviceInfo));
204 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
205 printk("Change Count=0x%X\n", pg0->ChangeCount);
206 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
207 printk("\n");
208}
209
210static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
211{
212 printk("---- SAS PHY PAGE 1 ------------\n");
f9a2d2e0
CH
213 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
214 printk("Running Disparity Error Count=0x%x\n",
b5141128 215 pg1->RunningDisparityErrorCount);
f9a2d2e0
CH
216 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
217 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
218 printk("\n");
b5141128
CH
219}
220
221static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
222{
223 __le64 sas_address;
224
225 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
226
227 printk("---- SAS DEVICE PAGE 0 ---------\n");
228 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
e3094447 229 printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
b5141128
CH
230 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
231 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
232 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
233 printk("Target ID=0x%X\n", pg0->TargetID);
234 printk("Bus=0x%X\n", pg0->Bus);
f9a2d2e0
CH
235 /* The PhyNum field specifies the PHY number of the parent
236 * device this device is linked to
237 */
238 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
239 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
b5141128
CH
240 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
241 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
242 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
243 printk("\n");
244}
245
246static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
247{
248 printk("---- SAS EXPANDER PAGE 1 ------------\n");
249
250 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
f9a2d2e0 251 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
b5141128
CH
252 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
253 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
254 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
255 printk("Owner Device Handle=0x%X\n",
256 le16_to_cpu(pg1->OwnerDevHandle));
257 printk("Attached Device Handle=0x%X\n",
258 le16_to_cpu(pg1->AttachedDevHandle));
259}
260#else
261#define mptsas_print_phy_data(phy_data) do { } while (0)
262#define mptsas_print_phy_pg0(pg0) do { } while (0)
263#define mptsas_print_phy_pg1(pg1) do { } while (0)
264#define mptsas_print_device_pg0(pg0) do { } while (0)
265#define mptsas_print_expander_pg1(pg1) do { } while (0)
266#endif
267
e3094447
CH
268static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
269{
270 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
271 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
272}
273
274static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
275{
276 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
277 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
278}
279
e6b2d76a
ME
280/*
281 * mptsas_find_portinfo_by_handle
282 *
283 * This function should be called with the sas_topology_mutex already held
284 */
285static struct mptsas_portinfo *
286mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
287{
288 struct mptsas_portinfo *port_info, *rc=NULL;
289 int i;
290
291 list_for_each_entry(port_info, &ioc->sas_topology, list)
292 for (i = 0; i < port_info->num_phys; i++)
293 if (port_info->phy_info[i].identify.handle == handle) {
294 rc = port_info;
295 goto out;
296 }
297 out:
298 return rc;
299}
300
e3094447 301static int
52435430 302mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
e3094447
CH
303 u32 form, u32 form_specific)
304{
305 ConfigExtendedPageHeader_t hdr;
306 CONFIGPARMS cfg;
307 SasEnclosurePage0_t *buffer;
308 dma_addr_t dma_handle;
309 int error;
310 __le64 le_identifier;
311
312 memset(&hdr, 0, sizeof(hdr));
313 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
314 hdr.PageNumber = 0;
315 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
316 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
317
318 cfg.cfghdr.ehdr = &hdr;
319 cfg.physAddr = -1;
320 cfg.pageAddr = form + form_specific;
321 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
322 cfg.dir = 0; /* read */
323 cfg.timeout = 10;
324
325 error = mpt_config(ioc, &cfg);
326 if (error)
327 goto out;
328 if (!hdr.ExtPageLength) {
329 error = -ENXIO;
330 goto out;
331 }
332
333 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
334 &dma_handle);
335 if (!buffer) {
336 error = -ENOMEM;
337 goto out;
338 }
339
340 cfg.physAddr = dma_handle;
341 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
342
343 error = mpt_config(ioc, &cfg);
344 if (error)
345 goto out_free_consistent;
346
347 /* save config data */
348 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
349 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
350 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
351 enclosure->flags = le16_to_cpu(buffer->Flags);
352 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
353 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
354 enclosure->start_id = buffer->StartTargetID;
355 enclosure->start_channel = buffer->StartBus;
356 enclosure->sep_id = buffer->SEPTargetID;
357 enclosure->sep_channel = buffer->SEPBus;
358
359 out_free_consistent:
360 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
361 buffer, dma_handle);
362 out:
363 return error;
364}
b5141128 365
f013db32
JB
366static int
367mptsas_slave_configure(struct scsi_device *sdev)
368{
3c0c25b9
ME
369 struct Scsi_Host *host = sdev->host;
370 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
371
372 /*
373 * RAID volumes placed beyond the last expected port.
374 * Ignore sending sas mode pages in that case..
375 */
376 if (sdev->channel < hd->ioc->num_ports)
377 sas_read_port_mode_page(sdev);
f013db32
JB
378
379 return mptscsih_slave_configure(sdev);
380}
381
0c33b27d
CH
382/*
383 * This is pretty ugly. We will be able to seriously clean it up
384 * once the DV code in mptscsih goes away and we can properly
385 * implement ->target_alloc.
386 */
387static int
c7c82987 388mptsas_slave_alloc(struct scsi_device *sdev)
0c33b27d 389{
c7c82987 390 struct Scsi_Host *host = sdev->host;
0c33b27d
CH
391 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
392 struct sas_rphy *rphy;
393 struct mptsas_portinfo *p;
c7c82987 394 VirtTarget *vtarget;
0c33b27d 395 VirtDevice *vdev;
c7c82987 396 struct scsi_target *starget;
914c2d8e 397 u32 target_id;
0c33b27d
CH
398 int i;
399
1ca00bb7 400 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
0c33b27d
CH
401 if (!vdev) {
402 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
403 hd->ioc->name, sizeof(VirtDevice));
404 return -ENOMEM;
405 }
c7c82987
MED
406 sdev->hostdata = vdev;
407 starget = scsi_target(sdev);
408 vtarget = starget->hostdata;
914c2d8e 409 vtarget->ioc_id = hd->ioc->id;
c7c82987
MED
410 vdev->vtarget = vtarget;
411 if (vtarget->num_luns == 0) {
412 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
413 hd->Targets[sdev->id] = vtarget;
414 }
0c33b27d 415
816aa907
ME
416 /*
417 RAID volumes placed beyond the last expected port.
418 */
419 if (sdev->channel == hd->ioc->num_ports) {
914c2d8e
ME
420 target_id = sdev->id;
421 vtarget->bus_id = 0;
816aa907
ME
422 vdev->lun = 0;
423 goto out;
424 }
425
c7c82987 426 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
9a28f49a 427 mutex_lock(&hd->ioc->sas_topology_mutex);
0c33b27d
CH
428 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
429 for (i = 0; i < p->num_phys; i++) {
430 if (p->phy_info[i].attached.sas_address ==
431 rphy->identify.sas_address) {
914c2d8e
ME
432 target_id = p->phy_info[i].attached.id;
433 vtarget->bus_id = p->phy_info[i].attached.channel;
c7c82987 434 vdev->lun = sdev->lun;
f44e5461
ME
435 p->phy_info[i].starget = sdev->sdev_target;
436 /*
437 * Exposing hidden disk (RAID)
438 */
439 if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
440 target_id = mptscsih_raid_id_to_num(hd,
441 target_id);
442 vdev->vtarget->tflags |=
443 MPT_TARGET_FLAGS_RAID_COMPONENT;
444 sdev->no_uld_attach = 1;
445 }
914c2d8e 446 mutex_unlock(&hd->ioc->sas_topology_mutex);
0c33b27d
CH
447 goto out;
448 }
449 }
450 }
9a28f49a 451 mutex_unlock(&hd->ioc->sas_topology_mutex);
0c33b27d 452
0c33b27d 453 kfree(vdev);
23f236ed 454 return -ENXIO;
0c33b27d
CH
455
456 out:
914c2d8e 457 vtarget->target_id = target_id;
c7c82987 458 vtarget->num_luns++;
0c33b27d
CH
459 return 0;
460}
461
9a28f49a
CH
462static void
463mptsas_slave_destroy(struct scsi_device *sdev)
464{
465 struct Scsi_Host *host = sdev->host;
466 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
7d3eecf7 467 VirtDevice *vdev;
9a28f49a 468
9a28f49a 469 /*
7d3eecf7 470 * Issue target reset to flush firmware outstanding commands.
9a28f49a 471 */
7d3eecf7
ME
472 vdev = sdev->hostdata;
473 if (vdev->configured_lun){
474 if (mptscsih_TMHandler(hd,
475 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
914c2d8e
ME
476 vdev->vtarget->bus_id,
477 vdev->vtarget->target_id,
7d3eecf7
ME
478 0, 0, 5 /* 5 second timeout */)
479 < 0){
480
481 /* The TM request failed!
482 * Fatal error case.
483 */
484 printk(MYIOC_s_WARN_FMT
485 "Error processing TaskMgmt id=%d TARGET_RESET\n",
486 hd->ioc->name,
914c2d8e 487 vdev->vtarget->target_id);
7d3eecf7
ME
488
489 hd->tmPending = 0;
490 hd->tmState = TM_STATE_NONE;
491 }
492 }
9a28f49a
CH
493 mptscsih_slave_destroy(sdev);
494}
495
0c33b27d 496static struct scsi_host_template mptsas_driver_template = {
f78496da 497 .module = THIS_MODULE,
0c33b27d
CH
498 .proc_name = "mptsas",
499 .proc_info = mptscsih_proc_info,
500 .name = "MPT SPI Host",
501 .info = mptscsih_info,
502 .queuecommand = mptscsih_qcmd,
c7c82987 503 .target_alloc = mptscsih_target_alloc,
0c33b27d 504 .slave_alloc = mptsas_slave_alloc,
f013db32 505 .slave_configure = mptsas_slave_configure,
c7c82987 506 .target_destroy = mptscsih_target_destroy,
9a28f49a 507 .slave_destroy = mptsas_slave_destroy,
0c33b27d
CH
508 .change_queue_depth = mptscsih_change_queue_depth,
509 .eh_abort_handler = mptscsih_abort,
510 .eh_device_reset_handler = mptscsih_dev_reset,
511 .eh_bus_reset_handler = mptscsih_bus_reset,
512 .eh_host_reset_handler = mptscsih_host_reset,
513 .bios_param = mptscsih_bios_param,
514 .can_queue = MPT_FC_CAN_QUEUE,
515 .this_id = -1,
516 .sg_tablesize = MPT_SCSI_SG_DEPTH,
517 .max_sectors = 8192,
518 .cmd_per_lun = 7,
519 .use_clustering = ENABLE_CLUSTERING,
520};
521
b5141128 522static int mptsas_get_linkerrors(struct sas_phy *phy)
0c33b27d 523{
b5141128
CH
524 MPT_ADAPTER *ioc = phy_to_ioc(phy);
525 ConfigExtendedPageHeader_t hdr;
526 CONFIGPARMS cfg;
527 SasPhyPage1_t *buffer;
528 dma_addr_t dma_handle;
529 int error;
0c33b27d 530
b5141128
CH
531 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
532 hdr.ExtPageLength = 0;
533 hdr.PageNumber = 1 /* page number 1*/;
534 hdr.Reserved1 = 0;
535 hdr.Reserved2 = 0;
536 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
537 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
0c33b27d 538
b5141128
CH
539 cfg.cfghdr.ehdr = &hdr;
540 cfg.physAddr = -1;
541 cfg.pageAddr = phy->identify.phy_identifier;
542 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
543 cfg.dir = 0; /* read */
544 cfg.timeout = 10;
0c33b27d 545
b5141128
CH
546 error = mpt_config(ioc, &cfg);
547 if (error)
548 return error;
549 if (!hdr.ExtPageLength)
550 return -ENXIO;
0c33b27d 551
b5141128
CH
552 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
553 &dma_handle);
554 if (!buffer)
555 return -ENOMEM;
0c33b27d 556
b5141128
CH
557 cfg.physAddr = dma_handle;
558 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
559
560 error = mpt_config(ioc, &cfg);
561 if (error)
562 goto out_free_consistent;
563
564 mptsas_print_phy_pg1(buffer);
565
566 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
567 phy->running_disparity_error_count =
568 le32_to_cpu(buffer->RunningDisparityErrorCount);
569 phy->loss_of_dword_sync_count =
570 le32_to_cpu(buffer->LossDwordSynchCount);
571 phy->phy_reset_problem_count =
572 le32_to_cpu(buffer->PhyResetProblemCount);
573
574 out_free_consistent:
575 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
576 buffer, dma_handle);
577 return error;
0c33b27d
CH
578}
579
da4fa655
CH
580static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
581 MPT_FRAME_HDR *reply)
582{
583 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
584 if (reply != NULL) {
585 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
586 memcpy(ioc->sas_mgmt.reply, reply,
587 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
588 }
589 complete(&ioc->sas_mgmt.done);
590 return 1;
591}
592
593static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
594{
595 MPT_ADAPTER *ioc = phy_to_ioc(phy);
596 SasIoUnitControlRequest_t *req;
597 SasIoUnitControlReply_t *reply;
598 MPT_FRAME_HDR *mf;
599 MPIHeader_t *hdr;
600 unsigned long timeleft;
601 int error = -ERESTARTSYS;
602
603 /* not implemented for expanders */
604 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
605 return -ENXIO;
606
eeb846ce 607 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
da4fa655
CH
608 goto out;
609
610 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
611 if (!mf) {
612 error = -ENOMEM;
613 goto out_unlock;
614 }
615
616 hdr = (MPIHeader_t *) mf;
617 req = (SasIoUnitControlRequest_t *)mf;
618 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
619 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
620 req->MsgContext = hdr->MsgContext;
621 req->Operation = hard_reset ?
622 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
623 req->PhyNum = phy->identify.phy_identifier;
624
625 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
626
627 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
628 10 * HZ);
629 if (!timeleft) {
630 /* On timeout reset the board */
631 mpt_free_msg_frame(ioc, mf);
632 mpt_HardResetHandler(ioc, CAN_SLEEP);
633 error = -ETIMEDOUT;
634 goto out_unlock;
635 }
636
637 /* a reply frame is expected */
638 if ((ioc->sas_mgmt.status &
639 MPT_IOCTL_STATUS_RF_VALID) == 0) {
640 error = -ENXIO;
641 goto out_unlock;
642 }
643
644 /* process the completed Reply Message Frame */
645 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
646 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
647 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
648 __FUNCTION__,
649 reply->IOCStatus,
650 reply->IOCLogInfo);
651 error = -ENXIO;
652 goto out_unlock;
653 }
654
655 error = 0;
656
657 out_unlock:
eeb846ce 658 mutex_unlock(&ioc->sas_mgmt.mutex);
da4fa655
CH
659 out:
660 return error;
661}
0c33b27d 662
e3094447
CH
663static int
664mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
665{
666 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
667 int i, error;
668 struct mptsas_portinfo *p;
669 struct mptsas_enclosure enclosure_info;
670 u64 enclosure_handle;
671
672 mutex_lock(&ioc->sas_topology_mutex);
673 list_for_each_entry(p, &ioc->sas_topology, list) {
674 for (i = 0; i < p->num_phys; i++) {
675 if (p->phy_info[i].attached.sas_address ==
676 rphy->identify.sas_address) {
677 enclosure_handle = p->phy_info[i].
678 attached.handle_enclosure;
679 goto found_info;
680 }
681 }
682 }
683 mutex_unlock(&ioc->sas_topology_mutex);
684 return -ENXIO;
685
686 found_info:
687 mutex_unlock(&ioc->sas_topology_mutex);
688 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
52435430 689 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
e3094447
CH
690 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
691 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
692 if (!error)
693 *identifier = enclosure_info.enclosure_logical_id;
694 return error;
695}
696
697static int
698mptsas_get_bay_identifier(struct sas_rphy *rphy)
699{
700 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
701 struct mptsas_portinfo *p;
702 int i, rc;
703
704 mutex_lock(&ioc->sas_topology_mutex);
705 list_for_each_entry(p, &ioc->sas_topology, list) {
706 for (i = 0; i < p->num_phys; i++) {
707 if (p->phy_info[i].attached.sas_address ==
708 rphy->identify.sas_address) {
709 rc = p->phy_info[i].attached.slot;
710 goto out;
711 }
712 }
713 }
714 rc = -ENXIO;
715 out:
716 mutex_unlock(&ioc->sas_topology_mutex);
717 return rc;
718}
719
b5141128
CH
720static struct sas_function_template mptsas_transport_functions = {
721 .get_linkerrors = mptsas_get_linkerrors,
e3094447
CH
722 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
723 .get_bay_identifier = mptsas_get_bay_identifier,
da4fa655 724 .phy_reset = mptsas_phy_reset,
b5141128
CH
725};
726
727static struct scsi_transport_template *mptsas_transport_template;
0c33b27d
CH
728
729static int
730mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
731{
732 ConfigExtendedPageHeader_t hdr;
733 CONFIGPARMS cfg;
734 SasIOUnitPage0_t *buffer;
735 dma_addr_t dma_handle;
736 int error, i;
737
738 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
739 hdr.ExtPageLength = 0;
740 hdr.PageNumber = 0;
741 hdr.Reserved1 = 0;
742 hdr.Reserved2 = 0;
743 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
744 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
745
746 cfg.cfghdr.ehdr = &hdr;
747 cfg.physAddr = -1;
748 cfg.pageAddr = 0;
749 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
750 cfg.dir = 0; /* read */
751 cfg.timeout = 10;
752
753 error = mpt_config(ioc, &cfg);
754 if (error)
755 goto out;
756 if (!hdr.ExtPageLength) {
757 error = -ENXIO;
758 goto out;
759 }
760
761 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
762 &dma_handle);
763 if (!buffer) {
764 error = -ENOMEM;
765 goto out;
766 }
767
768 cfg.physAddr = dma_handle;
769 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
770
771 error = mpt_config(ioc, &cfg);
772 if (error)
773 goto out_free_consistent;
774
775 port_info->num_phys = buffer->NumPhys;
776 port_info->phy_info = kcalloc(port_info->num_phys,
777 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
778 if (!port_info->phy_info) {
779 error = -ENOMEM;
780 goto out_free_consistent;
781 }
782
db9c9174
ME
783 if (port_info->num_phys)
784 port_info->handle =
785 le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
0c33b27d
CH
786 for (i = 0; i < port_info->num_phys; i++) {
787 mptsas_print_phy_data(&buffer->PhyData[i]);
788 port_info->phy_info[i].phy_id = i;
789 port_info->phy_info[i].port_id =
790 buffer->PhyData[i].Port;
791 port_info->phy_info[i].negotiated_link_rate =
792 buffer->PhyData[i].NegotiatedLinkRate;
793 }
794
795 out_free_consistent:
796 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
797 buffer, dma_handle);
798 out:
799 return error;
800}
801
802static int
803mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
804 u32 form, u32 form_specific)
805{
806 ConfigExtendedPageHeader_t hdr;
807 CONFIGPARMS cfg;
808 SasPhyPage0_t *buffer;
809 dma_addr_t dma_handle;
810 int error;
811
812 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
813 hdr.ExtPageLength = 0;
814 hdr.PageNumber = 0;
815 hdr.Reserved1 = 0;
816 hdr.Reserved2 = 0;
817 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
818 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
819
820 cfg.cfghdr.ehdr = &hdr;
821 cfg.dir = 0; /* read */
822 cfg.timeout = 10;
823
824 /* Get Phy Pg 0 for each Phy. */
825 cfg.physAddr = -1;
826 cfg.pageAddr = form + form_specific;
827 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
828
829 error = mpt_config(ioc, &cfg);
830 if (error)
831 goto out;
832
833 if (!hdr.ExtPageLength) {
834 error = -ENXIO;
835 goto out;
836 }
837
838 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
839 &dma_handle);
840 if (!buffer) {
841 error = -ENOMEM;
842 goto out;
843 }
844
845 cfg.physAddr = dma_handle;
846 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
847
848 error = mpt_config(ioc, &cfg);
849 if (error)
850 goto out_free_consistent;
851
852 mptsas_print_phy_pg0(buffer);
853
854 phy_info->hw_link_rate = buffer->HwLinkRate;
855 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
856 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
857 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
858
859 out_free_consistent:
860 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
861 buffer, dma_handle);
862 out:
863 return error;
864}
865
866static int
867mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
868 u32 form, u32 form_specific)
869{
870 ConfigExtendedPageHeader_t hdr;
871 CONFIGPARMS cfg;
872 SasDevicePage0_t *buffer;
873 dma_addr_t dma_handle;
874 __le64 sas_address;
875 int error;
876
877 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
878 hdr.ExtPageLength = 0;
879 hdr.PageNumber = 0;
880 hdr.Reserved1 = 0;
881 hdr.Reserved2 = 0;
882 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
883 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
884
885 cfg.cfghdr.ehdr = &hdr;
886 cfg.pageAddr = form + form_specific;
887 cfg.physAddr = -1;
888 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
889 cfg.dir = 0; /* read */
890 cfg.timeout = 10;
891
db9c9174 892 memset(device_info, 0, sizeof(struct mptsas_devinfo));
0c33b27d
CH
893 error = mpt_config(ioc, &cfg);
894 if (error)
895 goto out;
896 if (!hdr.ExtPageLength) {
897 error = -ENXIO;
898 goto out;
899 }
900
901 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
902 &dma_handle);
903 if (!buffer) {
904 error = -ENOMEM;
905 goto out;
906 }
907
908 cfg.physAddr = dma_handle;
909 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
910
911 error = mpt_config(ioc, &cfg);
912 if (error)
913 goto out_free_consistent;
914
915 mptsas_print_device_pg0(buffer);
916
917 device_info->handle = le16_to_cpu(buffer->DevHandle);
c73787ee 918 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
e3094447
CH
919 device_info->handle_enclosure =
920 le16_to_cpu(buffer->EnclosureHandle);
921 device_info->slot = le16_to_cpu(buffer->Slot);
0c33b27d
CH
922 device_info->phy_id = buffer->PhyNum;
923 device_info->port_id = buffer->PhysicalPort;
9a28f49a
CH
924 device_info->id = buffer->TargetID;
925 device_info->channel = buffer->Bus;
0c33b27d
CH
926 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
927 device_info->sas_address = le64_to_cpu(sas_address);
928 device_info->device_info =
929 le32_to_cpu(buffer->DeviceInfo);
930
931 out_free_consistent:
932 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
933 buffer, dma_handle);
934 out:
935 return error;
936}
937
938static int
939mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
940 u32 form, u32 form_specific)
941{
942 ConfigExtendedPageHeader_t hdr;
943 CONFIGPARMS cfg;
944 SasExpanderPage0_t *buffer;
945 dma_addr_t dma_handle;
946 int error;
947
948 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
949 hdr.ExtPageLength = 0;
950 hdr.PageNumber = 0;
951 hdr.Reserved1 = 0;
952 hdr.Reserved2 = 0;
953 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
954 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
955
956 cfg.cfghdr.ehdr = &hdr;
957 cfg.physAddr = -1;
958 cfg.pageAddr = form + form_specific;
959 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
960 cfg.dir = 0; /* read */
961 cfg.timeout = 10;
962
db9c9174 963 memset(port_info, 0, sizeof(struct mptsas_portinfo));
0c33b27d
CH
964 error = mpt_config(ioc, &cfg);
965 if (error)
966 goto out;
967
968 if (!hdr.ExtPageLength) {
969 error = -ENXIO;
970 goto out;
971 }
972
973 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
974 &dma_handle);
975 if (!buffer) {
976 error = -ENOMEM;
977 goto out;
978 }
979
980 cfg.physAddr = dma_handle;
981 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
982
983 error = mpt_config(ioc, &cfg);
984 if (error)
985 goto out_free_consistent;
986
987 /* save config data */
988 port_info->num_phys = buffer->NumPhys;
989 port_info->handle = le16_to_cpu(buffer->DevHandle);
990 port_info->phy_info = kcalloc(port_info->num_phys,
991 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
992 if (!port_info->phy_info) {
993 error = -ENOMEM;
994 goto out_free_consistent;
995 }
996
997 out_free_consistent:
998 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
999 buffer, dma_handle);
1000 out:
1001 return error;
1002}
1003
1004static int
1005mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1006 u32 form, u32 form_specific)
1007{
1008 ConfigExtendedPageHeader_t hdr;
1009 CONFIGPARMS cfg;
1010 SasExpanderPage1_t *buffer;
1011 dma_addr_t dma_handle;
1012 int error;
1013
1014 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1015 hdr.ExtPageLength = 0;
1016 hdr.PageNumber = 1;
1017 hdr.Reserved1 = 0;
1018 hdr.Reserved2 = 0;
1019 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1020 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1021
1022 cfg.cfghdr.ehdr = &hdr;
1023 cfg.physAddr = -1;
1024 cfg.pageAddr = form + form_specific;
1025 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1026 cfg.dir = 0; /* read */
1027 cfg.timeout = 10;
1028
1029 error = mpt_config(ioc, &cfg);
1030 if (error)
1031 goto out;
1032
1033 if (!hdr.ExtPageLength) {
1034 error = -ENXIO;
1035 goto out;
1036 }
1037
1038 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1039 &dma_handle);
1040 if (!buffer) {
1041 error = -ENOMEM;
1042 goto out;
1043 }
1044
1045 cfg.physAddr = dma_handle;
1046 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1047
1048 error = mpt_config(ioc, &cfg);
1049 if (error)
1050 goto out_free_consistent;
1051
1052
1053 mptsas_print_expander_pg1(buffer);
1054
1055 /* save config data */
024358ee 1056 phy_info->phy_id = buffer->PhyIdentifier;
0c33b27d
CH
1057 phy_info->port_id = buffer->PhysicalPort;
1058 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1059 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1060 phy_info->hw_link_rate = buffer->HwLinkRate;
1061 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1062 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1063
0c33b27d
CH
1064 out_free_consistent:
1065 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1066 buffer, dma_handle);
1067 out:
1068 return error;
1069}
1070
c73787ee
ME
1071/*
1072 * Returns true if there is a scsi end device
1073 */
1074static inline int
1075mptsas_is_end_device(struct mptsas_devinfo * attached)
1076{
1077 if ((attached->handle) &&
1078 (attached->device_info &
1079 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
1080 ((attached->device_info &
1081 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
1082 (attached->device_info &
1083 MPI_SAS_DEVICE_INFO_STP_TARGET) |
1084 (attached->device_info &
1085 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
1086 return 1;
1087 else
1088 return 0;
1089}
1090
0c33b27d
CH
1091static void
1092mptsas_parse_device_info(struct sas_identify *identify,
1093 struct mptsas_devinfo *device_info)
1094{
1095 u16 protocols;
1096
1097 identify->sas_address = device_info->sas_address;
1098 identify->phy_identifier = device_info->phy_id;
1099
1100 /*
1101 * Fill in Phy Initiator Port Protocol.
1102 * Bits 6:3, more than one bit can be set, fall through cases.
1103 */
1104 protocols = device_info->device_info & 0x78;
1105 identify->initiator_port_protocols = 0;
1106 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1107 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1108 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1109 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1110 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1111 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1112 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1113 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1114
1115 /*
1116 * Fill in Phy Target Port Protocol.
1117 * Bits 10:7, more than one bit can be set, fall through cases.
1118 */
1119 protocols = device_info->device_info & 0x780;
1120 identify->target_port_protocols = 0;
1121 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1122 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1123 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1124 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1125 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1126 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1127 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1128 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1129
1130 /*
1131 * Fill in Attached device type.
1132 */
1133 switch (device_info->device_info &
1134 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1135 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1136 identify->device_type = SAS_PHY_UNUSED;
1137 break;
1138 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1139 identify->device_type = SAS_END_DEVICE;
1140 break;
1141 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1142 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1143 break;
1144 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1145 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1146 break;
1147 }
1148}
1149
1150static int mptsas_probe_one_phy(struct device *dev,
ac01bbbd 1151 struct mptsas_phyinfo *phy_info, int index, int local)
0c33b27d 1152{
e6b2d76a 1153 MPT_ADAPTER *ioc;
9a28f49a 1154 struct sas_phy *phy;
0c33b27d
CH
1155 int error;
1156
e6b2d76a
ME
1157 if (!dev)
1158 return -ENODEV;
1159
1160 if (!phy_info->phy) {
1161 phy = sas_phy_alloc(dev, index);
1162 if (!phy)
1163 return -ENOMEM;
1164 } else
1165 phy = phy_info->phy;
0c33b27d 1166
9a28f49a
CH
1167 phy->port_identifier = phy_info->port_id;
1168 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
0c33b27d
CH
1169
1170 /*
1171 * Set Negotiated link rate.
1172 */
1173 switch (phy_info->negotiated_link_rate) {
1174 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
9a28f49a 1175 phy->negotiated_linkrate = SAS_PHY_DISABLED;
0c33b27d
CH
1176 break;
1177 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
9a28f49a 1178 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
0c33b27d
CH
1179 break;
1180 case MPI_SAS_IOUNIT0_RATE_1_5:
9a28f49a 1181 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1182 break;
1183 case MPI_SAS_IOUNIT0_RATE_3_0:
9a28f49a 1184 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1185 break;
1186 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1187 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1188 default:
9a28f49a 1189 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
0c33b27d
CH
1190 break;
1191 }
1192
1193 /*
1194 * Set Max hardware link rate.
1195 */
1196 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1197 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
9a28f49a 1198 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1199 break;
1200 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 1201 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1202 break;
1203 default:
1204 break;
1205 }
1206
1207 /*
1208 * Set Max programmed link rate.
1209 */
1210 switch (phy_info->programmed_link_rate &
1211 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1212 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
9a28f49a 1213 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1214 break;
1215 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 1216 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1217 break;
1218 default:
1219 break;
1220 }
1221
1222 /*
1223 * Set Min hardware link rate.
1224 */
1225 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1226 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
9a28f49a 1227 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1228 break;
1229 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 1230 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1231 break;
1232 default:
1233 break;
1234 }
1235
1236 /*
1237 * Set Min programmed link rate.
1238 */
1239 switch (phy_info->programmed_link_rate &
1240 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1241 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
9a28f49a 1242 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1243 break;
1244 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 1245 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1246 break;
1247 default:
1248 break;
1249 }
1250
e6b2d76a 1251 if (!phy_info->phy) {
ac01bbbd 1252
e6b2d76a
ME
1253 if (local)
1254 phy->local_attached = 1;
1255
1256 error = sas_phy_add(phy);
1257 if (error) {
1258 sas_phy_free(phy);
1259 return error;
1260 }
1261 phy_info->phy = phy;
0c33b27d
CH
1262 }
1263
e6b2d76a
ME
1264 if ((phy_info->attached.handle) &&
1265 (!phy_info->rphy)) {
1266
0c33b27d 1267 struct sas_rphy *rphy;
f013db32 1268 struct sas_identify identify;
0c33b27d 1269
e6b2d76a
ME
1270 ioc = phy_to_ioc(phy_info->phy);
1271
1272 /*
1273 * Let the hotplug_work thread handle processing
1274 * the adding/removing of devices that occur
1275 * after start of day.
1276 */
1277 if (ioc->sas_discovery_runtime &&
1278 mptsas_is_end_device(&phy_info->attached))
1279 return 0;
1280
f013db32
JB
1281 mptsas_parse_device_info(&identify, &phy_info->attached);
1282 switch (identify.device_type) {
1283 case SAS_END_DEVICE:
1284 rphy = sas_end_device_alloc(phy);
1285 break;
1286 case SAS_EDGE_EXPANDER_DEVICE:
1287 case SAS_FANOUT_EXPANDER_DEVICE:
1288 rphy = sas_expander_alloc(phy, identify.device_type);
1289 break;
1290 default:
1291 rphy = NULL;
1292 break;
1293 }
0c33b27d
CH
1294 if (!rphy)
1295 return 0; /* non-fatal: an rphy can be added later */
1296
f013db32
JB
1297 rphy->identify = identify;
1298
0c33b27d
CH
1299 error = sas_rphy_add(rphy);
1300 if (error) {
1301 sas_rphy_free(rphy);
1302 return error;
1303 }
1304
1305 phy_info->rphy = rphy;
1306 }
1307
1308 return 0;
1309}
1310
1311static int
e6b2d76a 1312mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
0c33b27d 1313{
e6b2d76a 1314 struct mptsas_portinfo *port_info, *hba;
0c33b27d
CH
1315 u32 handle = 0xFFFF;
1316 int error = -ENOMEM, i;
1317
e6b2d76a
ME
1318 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
1319 if (! hba)
0c33b27d 1320 goto out;
0c33b27d 1321
e6b2d76a 1322 error = mptsas_sas_io_unit_pg0(ioc, hba);
0c33b27d
CH
1323 if (error)
1324 goto out_free_port_info;
1325
9a28f49a 1326 mutex_lock(&ioc->sas_topology_mutex);
e6b2d76a
ME
1327 port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
1328 if (!port_info) {
1329 port_info = hba;
1330 list_add_tail(&port_info->list, &ioc->sas_topology);
1331 } else {
1332 port_info->handle = hba->handle;
1333 for (i = 0; i < hba->num_phys; i++)
1334 port_info->phy_info[i].negotiated_link_rate =
1335 hba->phy_info[i].negotiated_link_rate;
1336 if (hba->phy_info)
1337 kfree(hba->phy_info);
1338 kfree(hba);
1339 hba = NULL;
1340 }
9a28f49a 1341 mutex_unlock(&ioc->sas_topology_mutex);
e6b2d76a 1342 ioc->num_ports = port_info->num_phys;
9a28f49a 1343
0c33b27d
CH
1344 for (i = 0; i < port_info->num_phys; i++) {
1345 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1346 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1347 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1348
1349 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1350 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1351 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
024358ee
EM
1352 port_info->phy_info[i].identify.phy_id =
1353 port_info->phy_info[i].phy_id;
0c33b27d
CH
1354 handle = port_info->phy_info[i].identify.handle;
1355
1356 if (port_info->phy_info[i].attached.handle) {
1357 mptsas_sas_device_pg0(ioc,
1358 &port_info->phy_info[i].attached,
1359 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1360 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1361 port_info->phy_info[i].attached.handle);
1362 }
1363
1364 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
e6b2d76a
ME
1365 &port_info->phy_info[i], ioc->sas_index, 1);
1366 ioc->sas_index++;
0c33b27d
CH
1367 }
1368
1369 return 0;
1370
1371 out_free_port_info:
e6b2d76a
ME
1372 if (hba)
1373 kfree(hba);
0c33b27d
CH
1374 out:
1375 return error;
1376}
1377
1378static int
e6b2d76a 1379mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
0c33b27d 1380{
e6b2d76a 1381 struct mptsas_portinfo *port_info, *p, *ex;
0c33b27d
CH
1382 int error = -ENOMEM, i, j;
1383
e6b2d76a
ME
1384 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
1385 if (!ex)
0c33b27d 1386 goto out;
0c33b27d 1387
e6b2d76a 1388 error = mptsas_sas_expander_pg0(ioc, ex,
0c33b27d
CH
1389 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1390 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1391 if (error)
1392 goto out_free_port_info;
1393
e6b2d76a 1394 *handle = ex->handle;
0c33b27d 1395
9a28f49a 1396 mutex_lock(&ioc->sas_topology_mutex);
e6b2d76a
ME
1397 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
1398 if (!port_info) {
1399 port_info = ex;
1400 list_add_tail(&port_info->list, &ioc->sas_topology);
1401 } else {
1402 port_info->handle = ex->handle;
1403 if (ex->phy_info)
1404 kfree(ex->phy_info);
1405 kfree(ex);
1406 ex = NULL;
1407 }
9a28f49a
CH
1408 mutex_unlock(&ioc->sas_topology_mutex);
1409
0c33b27d
CH
1410 for (i = 0; i < port_info->num_phys; i++) {
1411 struct device *parent;
1412
1413 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1414 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1415 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1416
1417 if (port_info->phy_info[i].identify.handle) {
1418 mptsas_sas_device_pg0(ioc,
1419 &port_info->phy_info[i].identify,
1420 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1421 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1422 port_info->phy_info[i].identify.handle);
024358ee
EM
1423 port_info->phy_info[i].identify.phy_id =
1424 port_info->phy_info[i].phy_id;
0c33b27d
CH
1425 }
1426
1427 if (port_info->phy_info[i].attached.handle) {
1428 mptsas_sas_device_pg0(ioc,
1429 &port_info->phy_info[i].attached,
1430 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1431 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1432 port_info->phy_info[i].attached.handle);
db9c9174
ME
1433 port_info->phy_info[i].attached.phy_id =
1434 port_info->phy_info[i].phy_id;
0c33b27d
CH
1435 }
1436
1437 /*
1438 * If we find a parent port handle this expander is
1439 * attached to another expander, else it hangs of the
1440 * HBA phys.
1441 */
1442 parent = &ioc->sh->shost_gendev;
9a28f49a 1443 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
1444 list_for_each_entry(p, &ioc->sas_topology, list) {
1445 for (j = 0; j < p->num_phys; j++) {
1446 if (port_info->phy_info[i].identify.handle ==
1447 p->phy_info[j].attached.handle)
1448 parent = &p->phy_info[j].rphy->dev;
1449 }
1450 }
9a28f49a 1451 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d 1452
ac01bbbd 1453 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
e6b2d76a
ME
1454 ioc->sas_index, 0);
1455 ioc->sas_index++;
0c33b27d
CH
1456 }
1457
1458 return 0;
1459
1460 out_free_port_info:
e6b2d76a
ME
1461 if (ex) {
1462 if (ex->phy_info)
1463 kfree(ex->phy_info);
1464 kfree(ex);
1465 }
0c33b27d
CH
1466 out:
1467 return error;
1468}
1469
e6b2d76a
ME
1470/*
1471 * mptsas_delete_expander_phys
1472 *
1473 *
1474 * This will traverse topology, and remove expanders
1475 * that are no longer present
1476 */
1477static void
1478mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
1479{
1480 struct mptsas_portinfo buffer;
1481 struct mptsas_portinfo *port_info, *n, *parent;
1482 int i;
1483
1484 mutex_lock(&ioc->sas_topology_mutex);
1485 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
1486
1487 if (port_info->phy_info &&
1488 (!(port_info->phy_info[0].identify.device_info &
1489 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
1490 continue;
1491
1492 if (mptsas_sas_expander_pg0(ioc, &buffer,
1493 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
1494 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
1495
1496 /*
1497 * Obtain the port_info instance to the parent port
1498 */
1499 parent = mptsas_find_portinfo_by_handle(ioc,
1500 port_info->phy_info[0].identify.handle_parent);
1501
1502 if (!parent)
1503 goto next_port;
1504
1505 /*
1506 * Delete rphys in the parent that point
1507 * to this expander. The transport layer will
1508 * cleanup all the children.
1509 */
1510 for (i = 0; i < parent->num_phys; i++) {
1511 if ((!parent->phy_info[i].rphy) ||
1512 (parent->phy_info[i].attached.sas_address !=
1513 port_info->phy_info[i].identify.sas_address))
1514 continue;
1515 sas_rphy_delete(parent->phy_info[i].rphy);
1516 memset(&parent->phy_info[i].attached, 0,
1517 sizeof(struct mptsas_devinfo));
1518 parent->phy_info[i].rphy = NULL;
1519 parent->phy_info[i].starget = NULL;
1520 }
1521 next_port:
1522 list_del(&port_info->list);
1523 if (port_info->phy_info)
1524 kfree(port_info->phy_info);
1525 kfree(port_info);
1526 }
1527 /*
1528 * Free this memory allocated from inside
1529 * mptsas_sas_expander_pg0
1530 */
1531 if (buffer.phy_info)
1532 kfree(buffer.phy_info);
1533 }
1534 mutex_unlock(&ioc->sas_topology_mutex);
1535}
1536
1537/*
1538 * Start of day discovery
1539 */
0c33b27d
CH
1540static void
1541mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1542{
1543 u32 handle = 0xFFFF;
f44e5461 1544 int i;
0c33b27d 1545
e6b2d76a
ME
1546 mutex_lock(&ioc->sas_discovery_mutex);
1547 mptsas_probe_hba_phys(ioc);
1548 while (!mptsas_probe_expander_phys(ioc, &handle))
0c33b27d 1549 ;
f44e5461
ME
1550 /*
1551 Reporting RAID volumes.
1552 */
1553 if (!ioc->raid_data.pIocPg2)
1554 goto out;
1555 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1556 goto out;
1557 for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
1558 scsi_add_device(ioc->sh, ioc->num_ports,
1559 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
1560 }
1561 out:
e6b2d76a
ME
1562 mutex_unlock(&ioc->sas_discovery_mutex);
1563}
1564
1565/*
1566 * Work queue thread to handle Runtime discovery
1567 * Mere purpose is the hot add/delete of expanders
1568 */
1569static void
1570mptscsih_discovery_work(void * arg)
1571{
1572 struct mptsas_discovery_event *ev = arg;
1573 MPT_ADAPTER *ioc = ev->ioc;
1574 u32 handle = 0xFFFF;
1575
1576 mutex_lock(&ioc->sas_discovery_mutex);
1577 ioc->sas_discovery_runtime=1;
1578 mptsas_delete_expander_phys(ioc);
1579 mptsas_probe_hba_phys(ioc);
1580 while (!mptsas_probe_expander_phys(ioc, &handle))
1581 ;
1582 kfree(ev);
1583 ioc->sas_discovery_runtime=0;
1584 mutex_unlock(&ioc->sas_discovery_mutex);
0c33b27d
CH
1585}
1586
9a28f49a
CH
1587static struct mptsas_phyinfo *
1588mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
1589{
1590 struct mptsas_portinfo *port_info;
1591 struct mptsas_devinfo device_info;
1592 struct mptsas_phyinfo *phy_info = NULL;
1593 int i, error;
1594
1595 /*
1596 * Retrieve the parent sas_address
1597 */
1598 error = mptsas_sas_device_pg0(ioc, &device_info,
1599 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1600 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1601 parent_handle);
e6b2d76a 1602 if (error)
9a28f49a 1603 return NULL;
9a28f49a
CH
1604
1605 /*
1606 * The phy_info structures are never deallocated during lifetime of
1607 * a host, so the code below is safe without additional refcounting.
1608 */
1609 mutex_lock(&ioc->sas_topology_mutex);
1610 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1611 for (i = 0; i < port_info->num_phys; i++) {
1612 if (port_info->phy_info[i].identify.sas_address ==
1613 device_info.sas_address &&
1614 port_info->phy_info[i].phy_id == phy_id) {
1615 phy_info = &port_info->phy_info[i];
1616 break;
1617 }
1618 }
1619 }
1620 mutex_unlock(&ioc->sas_topology_mutex);
1621
1622 return phy_info;
1623}
1624
1625static struct mptsas_phyinfo *
c73787ee 1626mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
9a28f49a
CH
1627{
1628 struct mptsas_portinfo *port_info;
1629 struct mptsas_phyinfo *phy_info = NULL;
1630 int i;
1631
1632 /*
1633 * The phy_info structures are never deallocated during lifetime of
1634 * a host, so the code below is safe without additional refcounting.
1635 */
1636 mutex_lock(&ioc->sas_topology_mutex);
1637 list_for_each_entry(port_info, &ioc->sas_topology, list) {
c73787ee
ME
1638 for (i = 0; i < port_info->num_phys; i++)
1639 if (mptsas_is_end_device(&port_info->phy_info[i].attached))
1640 if (port_info->phy_info[i].attached.id == id) {
1641 phy_info = &port_info->phy_info[i];
1642 break;
1643 }
9a28f49a
CH
1644 }
1645 mutex_unlock(&ioc->sas_topology_mutex);
1646
1647 return phy_info;
1648}
1649
4b766471
ME
1650/*
1651 * Work queue thread to clear the persitency table
1652 */
1653static void
1654mptscsih_sas_persist_clear_table(void * arg)
1655{
1656 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
1657
1658 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
1659}
1660
f44e5461
ME
1661static void
1662mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
1663{
1664 sdev->no_uld_attach = data ? 1 : 0;
1665 scsi_device_reprobe(sdev);
1666}
1667
1668static void
1669mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
1670{
1671 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
1672 mptsas_reprobe_lun);
1673}
1674
e6b2d76a
ME
1675
1676/*
1677 * Work queue thread to handle SAS hotplug events
1678 */
9a28f49a
CH
1679static void
1680mptsas_hotplug_work(void *arg)
1681{
1682 struct mptsas_hotplug_event *ev = arg;
1683 MPT_ADAPTER *ioc = ev->ioc;
1684 struct mptsas_phyinfo *phy_info;
1685 struct sas_rphy *rphy;
c73787ee 1686 struct scsi_device *sdev;
f013db32 1687 struct sas_identify identify;
9a28f49a 1688 char *ds = NULL;
c73787ee 1689 struct mptsas_devinfo sas_device;
f44e5461 1690 VirtTarget *vtarget;
9a28f49a 1691
e6b2d76a
ME
1692 mutex_lock(&ioc->sas_discovery_mutex);
1693
9a28f49a
CH
1694 switch (ev->event_type) {
1695 case MPTSAS_DEL_DEVICE:
9a28f49a 1696
c73787ee 1697 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
e6b2d76a 1698
f44e5461
ME
1699 /*
1700 * Sanity checks, for non-existing phys and remote rphys.
1701 */
1702 if (!phy_info)
9a28f49a 1703 break;
f44e5461
ME
1704 if (!phy_info->rphy)
1705 break;
1706 if (phy_info->starget) {
1707 vtarget = phy_info->starget->hostdata;
1708
1709 if (!vtarget)
1710 break;
1711 /*
1712 * Handling RAID components
1713 */
1714 if (ev->phys_disk_num_valid) {
1715 vtarget->target_id = ev->phys_disk_num;
1716 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
1717 mptsas_reprobe_target(vtarget->starget, 1);
1718 break;
1719 }
9a28f49a
CH
1720 }
1721
c73787ee
ME
1722 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1723 ds = "ssp";
1724 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1725 ds = "stp";
1726 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1727 ds = "sata";
1728
1729 printk(MYIOC_s_INFO_FMT
1730 "removing %s device, channel %d, id %d, phy %d\n",
1731 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
1732
f44e5461
ME
1733 sas_rphy_delete(phy_info->rphy);
1734 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
1735 phy_info->rphy = NULL;
1736 phy_info->starget = NULL;
9a28f49a
CH
1737 break;
1738 case MPTSAS_ADD_DEVICE:
c73787ee
ME
1739
1740 /*
e3094447 1741 * Refresh sas device pg0 data
c73787ee 1742 */
e3094447
CH
1743 if (mptsas_sas_device_pg0(ioc, &sas_device,
1744 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
1745 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id))
1746 break;
9a28f49a
CH
1747
1748 phy_info = mptsas_find_phyinfo_by_parent(ioc,
e3094447 1749 sas_device.handle_parent, sas_device.phy_id);
e6b2d76a
ME
1750
1751 if (!phy_info) {
1752 u32 handle = 0xFFFF;
1753
1754 /*
1755 * Its possible when an expander has been hot added
1756 * containing attached devices, the sas firmware
1757 * may send a RC_ADDED event prior to the
1758 * DISCOVERY STOP event. If that occurs, our
1759 * view of the topology in the driver in respect to this
1760 * expander might of not been setup, and we hit this
1761 * condition.
1762 * Therefore, this code kicks off discovery to
1763 * refresh the data.
1764 * Then again, we check whether the parent phy has
1765 * been created.
1766 */
1767 ioc->sas_discovery_runtime=1;
1768 mptsas_delete_expander_phys(ioc);
1769 mptsas_probe_hba_phys(ioc);
1770 while (!mptsas_probe_expander_phys(ioc, &handle))
1771 ;
1772 ioc->sas_discovery_runtime=0;
1773
1774 phy_info = mptsas_find_phyinfo_by_parent(ioc,
1775 sas_device.handle_parent, sas_device.phy_id);
1776 if (!phy_info)
1777 break;
1778 }
1779
f44e5461
ME
1780 if (phy_info->starget) {
1781 vtarget = phy_info->starget->hostdata;
9a28f49a 1782
f44e5461
ME
1783 if (!vtarget)
1784 break;
1785 /*
1786 * Handling RAID components
1787 */
1788 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1789 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
1790 vtarget->target_id = ev->id;
1791 mptsas_reprobe_target(phy_info->starget, 0);
1792 }
9a28f49a
CH
1793 break;
1794 }
1795
f44e5461
ME
1796 if (phy_info->rphy)
1797 break;
1798
e3094447
CH
1799 memcpy(&phy_info->attached, &sas_device,
1800 sizeof(struct mptsas_devinfo));
9a28f49a 1801
c73787ee
ME
1802 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1803 ds = "ssp";
1804 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1805 ds = "stp";
1806 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1807 ds = "sata";
1808
1809 printk(MYIOC_s_INFO_FMT
1810 "attaching %s device, channel %d, id %d, phy %d\n",
1811 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1812
f013db32
JB
1813 mptsas_parse_device_info(&identify, &phy_info->attached);
1814 switch (identify.device_type) {
1815 case SAS_END_DEVICE:
1816 rphy = sas_end_device_alloc(phy_info->phy);
1817 break;
1818 case SAS_EDGE_EXPANDER_DEVICE:
1819 case SAS_FANOUT_EXPANDER_DEVICE:
1820 rphy = sas_expander_alloc(phy_info->phy, identify.device_type);
1821 break;
1822 default:
1823 rphy = NULL;
1824 break;
1825 }
9a28f49a
CH
1826 if (!rphy)
1827 break; /* non-fatal: an rphy can be added later */
1828
f013db32 1829 rphy->identify = identify;
9a28f49a
CH
1830 if (sas_rphy_add(rphy)) {
1831 sas_rphy_free(rphy);
1832 break;
1833 }
1834
1835 phy_info->rphy = rphy;
1836 break;
c73787ee
ME
1837 case MPTSAS_ADD_RAID:
1838 sdev = scsi_device_lookup(
1839 ioc->sh,
1840 ioc->num_ports,
1841 ev->id,
1842 0);
1843 if (sdev) {
1844 scsi_device_put(sdev);
1845 break;
1846 }
1847 printk(MYIOC_s_INFO_FMT
4b766471 1848 "attaching raid volume, channel %d, id %d\n",
c73787ee
ME
1849 ioc->name, ioc->num_ports, ev->id);
1850 scsi_add_device(ioc->sh,
1851 ioc->num_ports,
1852 ev->id,
1853 0);
1854 mpt_findImVolumes(ioc);
1855 break;
1856 case MPTSAS_DEL_RAID:
1857 sdev = scsi_device_lookup(
1858 ioc->sh,
1859 ioc->num_ports,
1860 ev->id,
1861 0);
1862 if (!sdev)
1863 break;
1864 printk(MYIOC_s_INFO_FMT
4b766471 1865 "removing raid volume, channel %d, id %d\n",
c73787ee
ME
1866 ioc->name, ioc->num_ports, ev->id);
1867 scsi_remove_device(sdev);
1868 scsi_device_put(sdev);
1869 mpt_findImVolumes(ioc);
1870 break;
9a28f49a
CH
1871 }
1872
1873 kfree(ev);
e6b2d76a 1874 mutex_unlock(&ioc->sas_discovery_mutex);
9a28f49a
CH
1875}
1876
1877static void
1878mptscsih_send_sas_event(MPT_ADAPTER *ioc,
1879 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
1880{
1881 struct mptsas_hotplug_event *ev;
1882 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
1883 __le64 sas_address;
1884
1885 if ((device_info &
1886 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
1887 MPI_SAS_DEVICE_INFO_STP_TARGET |
1888 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
1889 return;
1890
4b766471
ME
1891 switch (sas_event_data->ReasonCode) {
1892 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
1893 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
1894 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1895 if (!ev) {
1896 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1897 break;
1898 }
9a28f49a 1899
4b766471
ME
1900 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1901 ev->ioc = ioc;
1902 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
1903 ev->parent_handle =
1904 le16_to_cpu(sas_event_data->ParentDevHandle);
1905 ev->channel = sas_event_data->Bus;
1906 ev->id = sas_event_data->TargetID;
1907 ev->phy_id = sas_event_data->PhyNum;
1908 memcpy(&sas_address, &sas_event_data->SASAddress,
1909 sizeof(__le64));
1910 ev->sas_address = le64_to_cpu(sas_address);
1911 ev->device_info = device_info;
1912
1913 if (sas_event_data->ReasonCode &
1914 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
1915 ev->event_type = MPTSAS_ADD_DEVICE;
1916 else
1917 ev->event_type = MPTSAS_DEL_DEVICE;
1918 schedule_work(&ev->work);
1919 break;
1920 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
1921 /*
1922 * Persistent table is full.
1923 */
1924 INIT_WORK(&ioc->mptscsih_persistTask,
1925 mptscsih_sas_persist_clear_table,
1926 (void *)ioc);
1927 schedule_work(&ioc->mptscsih_persistTask);
1928 break;
1929 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
1930 /* TODO */
1931 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
1932 /* TODO */
1933 default:
1934 break;
9a28f49a 1935 }
9a28f49a
CH
1936}
1937
c73787ee
ME
1938static void
1939mptscsih_send_raid_event(MPT_ADAPTER *ioc,
1940 EVENT_DATA_RAID *raid_event_data)
1941{
1942 struct mptsas_hotplug_event *ev;
1943 RAID_VOL0_STATUS * volumeStatus;
1944
1945 if (ioc->bus_type != SAS)
1946 return;
1947
1948 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1949 if (!ev) {
1950 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1951 return;
1952 }
1953
1954 memset(ev,0,sizeof(struct mptsas_hotplug_event));
1955 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1956 ev->ioc = ioc;
1957 ev->id = raid_event_data->VolumeID;
1958
1959 switch (raid_event_data->ReasonCode) {
1960 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
1961 ev->event_type = MPTSAS_ADD_DEVICE;
1962 break;
1963 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
f44e5461
ME
1964 ioc->raid_data.isRaid = 1;
1965 ev->phys_disk_num_valid = 1;
1966 ev->phys_disk_num = raid_event_data->PhysDiskNum;
c73787ee
ME
1967 ev->event_type = MPTSAS_DEL_DEVICE;
1968 break;
1969 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
1970 ev->event_type = MPTSAS_DEL_RAID;
1971 break;
1972 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
1973 ev->event_type = MPTSAS_ADD_RAID;
1974 break;
1975 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
1976 volumeStatus = (RAID_VOL0_STATUS *) &
1977 raid_event_data->SettingsStatus;
1978 ev->event_type = (volumeStatus->State ==
1979 MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
1980 MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
1981 break;
1982 default:
1983 break;
1984 }
1985 schedule_work(&ev->work);
1986}
1987
e6b2d76a
ME
1988static void
1989mptscsih_send_discovery(MPT_ADAPTER *ioc,
1990 EVENT_DATA_SAS_DISCOVERY *discovery_data)
1991{
1992 struct mptsas_discovery_event *ev;
1993
1994 /*
1995 * DiscoveryStatus
1996 *
1997 * This flag will be non-zero when firmware
1998 * kicks off discovery, and return to zero
1999 * once its completed.
2000 */
2001 if (discovery_data->DiscoveryStatus)
2002 return;
2003
2004 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
2005 if (!ev)
2006 return;
2007 memset(ev,0,sizeof(struct mptsas_discovery_event));
2008 INIT_WORK(&ev->work, mptscsih_discovery_work, ev);
2009 ev->ioc = ioc;
2010 schedule_work(&ev->work);
2011};
2012
2013
9a28f49a
CH
2014static int
2015mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
2016{
c73787ee 2017 int rc=1;
9a28f49a
CH
2018 u8 event = le32_to_cpu(reply->Event) & 0xFF;
2019
2020 if (!ioc->sh)
c73787ee 2021 goto out;
9a28f49a 2022
e6b2d76a
ME
2023 /*
2024 * sas_discovery_ignore_events
2025 *
2026 * This flag is to prevent anymore processing of
2027 * sas events once mptsas_remove function is called.
2028 */
2029 if (ioc->sas_discovery_ignore_events) {
2030 rc = mptscsih_event_process(ioc, reply);
2031 goto out;
2032 }
2033
9a28f49a
CH
2034 switch (event) {
2035 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
2036 mptscsih_send_sas_event(ioc,
2037 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
c73787ee
ME
2038 break;
2039 case MPI_EVENT_INTEGRATED_RAID:
2040 mptscsih_send_raid_event(ioc,
2041 (EVENT_DATA_RAID *)reply->Data);
2042 break;
79de278e
ME
2043 case MPI_EVENT_PERSISTENT_TABLE_FULL:
2044 INIT_WORK(&ioc->mptscsih_persistTask,
2045 mptscsih_sas_persist_clear_table,
2046 (void *)ioc);
2047 schedule_work(&ioc->mptscsih_persistTask);
2048 break;
4b766471 2049 case MPI_EVENT_SAS_DISCOVERY:
e6b2d76a
ME
2050 mptscsih_send_discovery(ioc,
2051 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
2052 break;
9a28f49a 2053 default:
c73787ee
ME
2054 rc = mptscsih_event_process(ioc, reply);
2055 break;
9a28f49a 2056 }
c73787ee
ME
2057 out:
2058
2059 return rc;
9a28f49a
CH
2060}
2061
0c33b27d
CH
2062static int
2063mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2064{
2065 struct Scsi_Host *sh;
2066 MPT_SCSI_HOST *hd;
2067 MPT_ADAPTER *ioc;
2068 unsigned long flags;
1ca00bb7 2069 int ii;
0c33b27d
CH
2070 int numSGE = 0;
2071 int scale;
2072 int ioc_cap;
0c33b27d
CH
2073 int error=0;
2074 int r;
2075
2076 r = mpt_attach(pdev,id);
2077 if (r)
2078 return r;
2079
2080 ioc = pci_get_drvdata(pdev);
2081 ioc->DoneCtx = mptsasDoneCtx;
2082 ioc->TaskCtx = mptsasTaskCtx;
2083 ioc->InternalCtx = mptsasInternalCtx;
2084
2085 /* Added sanity check on readiness of the MPT adapter.
2086 */
2087 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
2088 printk(MYIOC_s_WARN_FMT
2089 "Skipping because it's not operational!\n",
2090 ioc->name);
7acec1e7
MED
2091 error = -ENODEV;
2092 goto out_mptsas_probe;
0c33b27d
CH
2093 }
2094
2095 if (!ioc->active) {
2096 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
2097 ioc->name);
7acec1e7
MED
2098 error = -ENODEV;
2099 goto out_mptsas_probe;
0c33b27d
CH
2100 }
2101
2102 /* Sanity check - ensure at least 1 port is INITIATOR capable
2103 */
2104 ioc_cap = 0;
2105 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
2106 if (ioc->pfacts[ii].ProtocolFlags &
2107 MPI_PORTFACTS_PROTOCOL_INITIATOR)
2108 ioc_cap++;
2109 }
2110
2111 if (!ioc_cap) {
2112 printk(MYIOC_s_WARN_FMT
2113 "Skipping ioc=%p because SCSI Initiator mode "
2114 "is NOT enabled!\n", ioc->name, ioc);
466544d8 2115 return 0;
0c33b27d
CH
2116 }
2117
2118 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
2119 if (!sh) {
2120 printk(MYIOC_s_WARN_FMT
2121 "Unable to register controller with SCSI subsystem\n",
2122 ioc->name);
7acec1e7
MED
2123 error = -1;
2124 goto out_mptsas_probe;
0c33b27d
CH
2125 }
2126
2127 spin_lock_irqsave(&ioc->FreeQlock, flags);
2128
2129 /* Attach the SCSI Host to the IOC structure
2130 */
2131 ioc->sh = sh;
2132
2133 sh->io_port = 0;
2134 sh->n_io_port = 0;
2135 sh->irq = 0;
2136
2137 /* set 16 byte cdb's */
2138 sh->max_cmd_len = 16;
2139
2140 sh->max_id = ioc->pfacts->MaxDevices + 1;
2141
2142 sh->transportt = mptsas_transport_template;
2143
2144 sh->max_lun = MPT_LAST_LUN + 1;
2145 sh->max_channel = 0;
2146 sh->this_id = ioc->pfacts[0].PortSCSIID;
2147
2148 /* Required entry.
2149 */
2150 sh->unique_id = ioc->id;
2151
2152 INIT_LIST_HEAD(&ioc->sas_topology);
9a28f49a 2153 mutex_init(&ioc->sas_topology_mutex);
e6b2d76a 2154 mutex_init(&ioc->sas_discovery_mutex);
eeb846ce 2155 mutex_init(&ioc->sas_mgmt.mutex);
da4fa655 2156 init_completion(&ioc->sas_mgmt.done);
0c33b27d
CH
2157
2158 /* Verify that we won't exceed the maximum
2159 * number of chain buffers
2160 * We can optimize: ZZ = req_sz/sizeof(SGE)
2161 * For 32bit SGE's:
2162 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
2163 * + (req_sz - 64)/sizeof(SGE)
2164 * A slightly different algorithm is required for
2165 * 64bit SGEs.
2166 */
2167 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
2168 if (sizeof(dma_addr_t) == sizeof(u64)) {
2169 numSGE = (scale - 1) *
2170 (ioc->facts.MaxChainDepth-1) + scale +
2171 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
2172 sizeof(u32));
2173 } else {
2174 numSGE = 1 + (scale - 1) *
2175 (ioc->facts.MaxChainDepth-1) + scale +
2176 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
2177 sizeof(u32));
2178 }
2179
2180 if (numSGE < sh->sg_tablesize) {
2181 /* Reset this value */
2182 dprintk((MYIOC_s_INFO_FMT
2183 "Resetting sg_tablesize to %d from %d\n",
2184 ioc->name, numSGE, sh->sg_tablesize));
2185 sh->sg_tablesize = numSGE;
2186 }
2187
2188 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2189
2190 hd = (MPT_SCSI_HOST *) sh->hostdata;
2191 hd->ioc = ioc;
2192
2193 /* SCSI needs scsi_cmnd lookup table!
2194 * (with size equal to req_depth*PtrSz!)
2195 */
1ca00bb7
CH
2196 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
2197 if (!hd->ScsiLookup) {
0c33b27d 2198 error = -ENOMEM;
7acec1e7 2199 goto out_mptsas_probe;
0c33b27d
CH
2200 }
2201
1ca00bb7
CH
2202 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
2203 ioc->name, hd->ScsiLookup));
0c33b27d
CH
2204
2205 /* Allocate memory for the device structures.
2206 * A non-Null pointer at an offset
2207 * indicates a device exists.
2208 * max_id = 1 + maximum id (hosts.h)
2209 */
1ca00bb7
CH
2210 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
2211 if (!hd->Targets) {
0c33b27d 2212 error = -ENOMEM;
7acec1e7 2213 goto out_mptsas_probe;
0c33b27d
CH
2214 }
2215
1ca00bb7 2216 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
0c33b27d
CH
2217
2218 /* Clear the TM flags
2219 */
2220 hd->tmPending = 0;
2221 hd->tmState = TM_STATE_NONE;
2222 hd->resetPending = 0;
2223 hd->abortSCpnt = NULL;
2224
2225 /* Clear the pointer used to store
2226 * single-threaded commands, i.e., those
2227 * issued during a bus scan, dv and
2228 * configuration pages.
2229 */
2230 hd->cmdPtr = NULL;
2231
2232 /* Initialize this SCSI Hosts' timers
2233 * To use, set the timer expires field
2234 * and add_timer
2235 */
2236 init_timer(&hd->timer);
2237 hd->timer.data = (unsigned long) hd;
2238 hd->timer.function = mptscsih_timer_expired;
2239
2240 hd->mpt_pq_filter = mpt_pq_filter;
2241 ioc->sas_data.ptClear = mpt_pt_clear;
2242
2243 if (ioc->sas_data.ptClear==1) {
2244 mptbase_sas_persist_operation(
2245 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
2246 }
2247
2248 ddvprintk((MYIOC_s_INFO_FMT
2249 "mpt_pq_filter %x mpt_pq_filter %x\n",
2250 ioc->name,
2251 mpt_pq_filter,
2252 mpt_pq_filter));
2253
2254 init_waitqueue_head(&hd->scandv_waitq);
2255 hd->scandv_wait_done = 0;
2256 hd->last_queue_full = 0;
2257
2258 error = scsi_add_host(sh, &ioc->pcidev->dev);
2259 if (error) {
2260 dprintk((KERN_ERR MYNAM
2261 "scsi_add_host failed\n"));
7acec1e7 2262 goto out_mptsas_probe;
0c33b27d
CH
2263 }
2264
2265 mptsas_scan_sas_topology(ioc);
2266
2267 return 0;
2268
7acec1e7 2269out_mptsas_probe:
0c33b27d
CH
2270
2271 mptscsih_remove(pdev);
2272 return error;
2273}
2274
2275static void __devexit mptsas_remove(struct pci_dev *pdev)
2276{
2277 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2278 struct mptsas_portinfo *p, *n;
2279
e6b2d76a 2280 ioc->sas_discovery_ignore_events=1;
0c33b27d
CH
2281 sas_remove_host(ioc->sh);
2282
9a28f49a 2283 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
2284 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
2285 list_del(&p->list);
db9c9174
ME
2286 if (p->phy_info)
2287 kfree(p->phy_info);
0c33b27d
CH
2288 kfree(p);
2289 }
9a28f49a 2290 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d
CH
2291
2292 mptscsih_remove(pdev);
2293}
2294
2295static struct pci_device_id mptsas_pci_table[] = {
2296 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
2297 PCI_ANY_ID, PCI_ANY_ID },
2298 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
2299 PCI_ANY_ID, PCI_ANY_ID },
2300 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
2301 PCI_ANY_ID, PCI_ANY_ID },
2302 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
2303 PCI_ANY_ID, PCI_ANY_ID },
2304 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
2305 PCI_ANY_ID, PCI_ANY_ID },
2306 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
2307 PCI_ANY_ID, PCI_ANY_ID },
2308 {0} /* Terminating entry */
2309};
2310MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
2311
2312
2313static struct pci_driver mptsas_driver = {
2314 .name = "mptsas",
2315 .id_table = mptsas_pci_table,
2316 .probe = mptsas_probe,
2317 .remove = __devexit_p(mptsas_remove),
2318 .shutdown = mptscsih_shutdown,
2319#ifdef CONFIG_PM
2320 .suspend = mptscsih_suspend,
2321 .resume = mptscsih_resume,
2322#endif
2323};
2324
2325static int __init
2326mptsas_init(void)
2327{
2328 show_mptmod_ver(my_NAME, my_VERSION);
2329
2330 mptsas_transport_template =
2331 sas_attach_transport(&mptsas_transport_functions);
2332 if (!mptsas_transport_template)
2333 return -ENODEV;
2334
2335 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
2336 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
2337 mptsasInternalCtx =
2338 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
da4fa655 2339 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
0c33b27d 2340
9a28f49a 2341 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
3a892bef 2342 devtverboseprintk((KERN_INFO MYNAM
0c33b27d
CH
2343 ": Registered for IOC event notifications\n"));
2344 }
2345
2346 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
2347 dprintk((KERN_INFO MYNAM
2348 ": Registered for IOC reset notifications\n"));
2349 }
2350
2351 return pci_register_driver(&mptsas_driver);
2352}
2353
2354static void __exit
2355mptsas_exit(void)
2356{
2357 pci_unregister_driver(&mptsas_driver);
2358 sas_release_transport(mptsas_transport_template);
2359
2360 mpt_reset_deregister(mptsasDoneCtx);
2361 mpt_event_deregister(mptsasDoneCtx);
2362
da4fa655 2363 mpt_deregister(mptsasMgmtCtx);
0c33b27d
CH
2364 mpt_deregister(mptsasInternalCtx);
2365 mpt_deregister(mptsasTaskCtx);
2366 mpt_deregister(mptsasDoneCtx);
2367}
2368
2369module_init(mptsas_init);
2370module_exit(mptsas_exit);
This page took 0.22734 seconds and 5 git commands to generate.