blob: 5a06d8d8694eb3cff0322e479a089ffb5d7021c1 [file] [log] [blame]
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001/*
2 * linux/drivers/message/fusion/mptsas.c
3 * For use with LSI Logic PCI chip/adapter(s)
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5 *
6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01008 * Copyright (c) 2005-2006 Dell
Christoph Hellwig0c33b272005-09-09 16:27:19 +02009 */
10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11/*
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 NO WARRANTY
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
31
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44*/
45/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46
47#include <linux/module.h>
48#include <linux/kernel.h>
49#include <linux/init.h>
50#include <linux/errno.h>
51#include <linux/sched.h>
52#include <linux/workqueue.h>
53
54#include <scsi/scsi_cmnd.h>
55#include <scsi/scsi_device.h>
56#include <scsi/scsi_host.h>
57#include <scsi/scsi_transport_sas.h>
58
59#include "mptbase.h"
60#include "mptscsih.h"
61
62
63#define my_NAME "Fusion MPT SAS Host driver"
64#define my_VERSION MPT_LINUX_VERSION_COMMON
65#define MYNAM "mptsas"
66
67MODULE_AUTHOR(MODULEAUTHOR);
68MODULE_DESCRIPTION(my_NAME);
69MODULE_LICENSE("GPL");
70
71static int mpt_pq_filter;
72module_param(mpt_pq_filter, int, 0);
73MODULE_PARM_DESC(mpt_pq_filter,
74 "Enable peripheral qualifier filter: enable=1 "
75 "(default=0)");
76
77static int mpt_pt_clear;
78module_param(mpt_pt_clear, int, 0);
79MODULE_PARM_DESC(mpt_pt_clear,
80 "Clear persistency table: enable=1 "
81 "(default=MPTSCSIH_PT_CLEAR=0)");
82
83static int mptsasDoneCtx = -1;
84static int mptsasTaskCtx = -1;
85static int mptsasInternalCtx = -1; /* Used only for internal commands */
Christoph Hellwigda4fa652005-10-19 20:01:42 +020086static int mptsasMgmtCtx = -1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +020087
88
Christoph Hellwig9a28f492006-01-13 18:04:41 +010089enum mptsas_hotplug_action {
90 MPTSAS_ADD_DEVICE,
91 MPTSAS_DEL_DEVICE,
92};
93
94struct mptsas_hotplug_event {
95 struct work_struct work;
96 MPT_ADAPTER *ioc;
97 enum mptsas_hotplug_action event_type;
98 u64 sas_address;
99 u32 channel;
100 u32 id;
101 u32 device_info;
102 u16 handle;
103 u16 parent_handle;
104 u8 phy_id;
105};
106
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200107/*
108 * SAS topology structures
109 *
110 * The MPT Fusion firmware interface spreads information about the
111 * SAS topology over many manufacture pages, thus we need some data
112 * structure to collect it and process it for the SAS transport class.
113 */
114
115struct mptsas_devinfo {
116 u16 handle; /* unique id to address this device */
117 u8 phy_id; /* phy number of parent device */
118 u8 port_id; /* sas physical port this device
119 is assoc'd with */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100120 u8 id; /* logical target id of this device */
121 u8 channel; /* logical bus number of this device */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200122 u64 sas_address; /* WWN of this device,
123 SATA is assigned by HBA,expander */
124 u32 device_info; /* bitfield detailed info about this device */
125};
126
127struct mptsas_phyinfo {
128 u8 phy_id; /* phy index */
129 u8 port_id; /* port number this phy is part of */
130 u8 negotiated_link_rate; /* nego'd link rate for this phy */
131 u8 hw_link_rate; /* hardware max/min phys link rate */
132 u8 programmed_link_rate; /* programmed max/min phy link rate */
133 struct mptsas_devinfo identify; /* point to phy device info */
134 struct mptsas_devinfo attached; /* point to attached device info */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100135 struct sas_phy *phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200136 struct sas_rphy *rphy;
137};
138
139struct mptsas_portinfo {
140 struct list_head list;
141 u16 handle; /* unique id to address this */
142 u8 num_phys; /* number of phys */
143 struct mptsas_phyinfo *phy_info;
144};
145
Christoph Hellwigb5141122005-10-28 22:07:41 +0200146
147#ifdef SASDEBUG
148static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
149{
150 printk("---- IO UNIT PAGE 0 ------------\n");
151 printk("Handle=0x%X\n",
152 le16_to_cpu(phy_data->AttachedDeviceHandle));
153 printk("Controller Handle=0x%X\n",
154 le16_to_cpu(phy_data->ControllerDevHandle));
155 printk("Port=0x%X\n", phy_data->Port);
156 printk("Port Flags=0x%X\n", phy_data->PortFlags);
157 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
158 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
159 printk("Controller PHY Device Info=0x%X\n",
160 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
161 printk("DiscoveryStatus=0x%X\n",
162 le32_to_cpu(phy_data->DiscoveryStatus));
163 printk("\n");
164}
165
166static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
167{
168 __le64 sas_address;
169
170 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
171
172 printk("---- SAS PHY PAGE 0 ------------\n");
173 printk("Attached Device Handle=0x%X\n",
174 le16_to_cpu(pg0->AttachedDevHandle));
175 printk("SAS Address=0x%llX\n",
176 (unsigned long long)le64_to_cpu(sas_address));
177 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
178 printk("Attached Device Info=0x%X\n",
179 le32_to_cpu(pg0->AttachedDeviceInfo));
180 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
181 printk("Change Count=0x%X\n", pg0->ChangeCount);
182 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
183 printk("\n");
184}
185
186static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
187{
188 printk("---- SAS PHY PAGE 1 ------------\n");
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200189 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
190 printk("Running Disparity Error Count=0x%x\n",
Christoph Hellwigb5141122005-10-28 22:07:41 +0200191 pg1->RunningDisparityErrorCount);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200192 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
193 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
194 printk("\n");
Christoph Hellwigb5141122005-10-28 22:07:41 +0200195}
196
197static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
198{
199 __le64 sas_address;
200
201 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
202
203 printk("---- SAS DEVICE PAGE 0 ---------\n");
204 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
205 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
206 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
207 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
208 printk("Target ID=0x%X\n", pg0->TargetID);
209 printk("Bus=0x%X\n", pg0->Bus);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200210 /* The PhyNum field specifies the PHY number of the parent
211 * device this device is linked to
212 */
213 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
214 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200215 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
216 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
217 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
218 printk("\n");
219}
220
221static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
222{
223 printk("---- SAS EXPANDER PAGE 1 ------------\n");
224
225 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200226 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwigb5141122005-10-28 22:07:41 +0200227 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
228 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
229 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
230 printk("Owner Device Handle=0x%X\n",
231 le16_to_cpu(pg1->OwnerDevHandle));
232 printk("Attached Device Handle=0x%X\n",
233 le16_to_cpu(pg1->AttachedDevHandle));
234}
235#else
236#define mptsas_print_phy_data(phy_data) do { } while (0)
237#define mptsas_print_phy_pg0(pg0) do { } while (0)
238#define mptsas_print_phy_pg1(pg1) do { } while (0)
239#define mptsas_print_device_pg0(pg0) do { } while (0)
240#define mptsas_print_expander_pg1(pg1) do { } while (0)
241#endif
242
243
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200244/*
245 * This is pretty ugly. We will be able to seriously clean it up
246 * once the DV code in mptscsih goes away and we can properly
247 * implement ->target_alloc.
248 */
249static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700250mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200251{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700252 struct Scsi_Host *host = sdev->host;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200253 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
254 struct sas_rphy *rphy;
255 struct mptsas_portinfo *p;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700256 VirtTarget *vtarget;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200257 VirtDevice *vdev;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700258 struct scsi_target *starget;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200259 int i;
260
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100261 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200262 if (!vdev) {
263 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
264 hd->ioc->name, sizeof(VirtDevice));
265 return -ENOMEM;
266 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200267 vdev->ioc_id = hd->ioc->id;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700268 sdev->hostdata = vdev;
269 starget = scsi_target(sdev);
270 vtarget = starget->hostdata;
271 vdev->vtarget = vtarget;
272 if (vtarget->num_luns == 0) {
273 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
274 hd->Targets[sdev->id] = vtarget;
275 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200276
Moore, Eric816aa902006-01-13 16:25:20 -0700277 /*
278 RAID volumes placed beyond the last expected port.
279 */
280 if (sdev->channel == hd->ioc->num_ports) {
281 vdev->target_id = sdev->id;
282 vdev->bus_id = 0;
283 vdev->lun = 0;
284 goto out;
285 }
286
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700287 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100288 mutex_lock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200289 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
290 for (i = 0; i < p->num_phys; i++) {
291 if (p->phy_info[i].attached.sas_address ==
292 rphy->identify.sas_address) {
293 vdev->target_id =
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100294 p->phy_info[i].attached.id;
295 vdev->bus_id = p->phy_info[i].attached.channel;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700296 vdev->lun = sdev->lun;
Moore, Eric816aa902006-01-13 16:25:20 -0700297 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200298 goto out;
299 }
300 }
301 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100302 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200303
304 printk("No matching SAS device found!!\n");
305 kfree(vdev);
306 return -ENODEV;
307
308 out:
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700309 vtarget->ioc_id = vdev->ioc_id;
310 vtarget->target_id = vdev->target_id;
311 vtarget->bus_id = vdev->bus_id;
312 vtarget->num_luns++;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200313 return 0;
314}
315
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100316static void
317mptsas_slave_destroy(struct scsi_device *sdev)
318{
319 struct Scsi_Host *host = sdev->host;
320 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
321 struct sas_rphy *rphy;
322 struct mptsas_portinfo *p;
323 int i;
324
325 /*
326 * Handle hotplug removal case.
327 * We need to clear out attached data structure.
328 */
329 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
330
331 mutex_lock(&hd->ioc->sas_topology_mutex);
332 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
333 for (i = 0; i < p->num_phys; i++) {
334 if (p->phy_info[i].attached.sas_address ==
335 rphy->identify.sas_address) {
336 memset(&p->phy_info[i].attached, 0,
337 sizeof(struct mptsas_devinfo));
338 p->phy_info[i].rphy = NULL;
339 goto out;
340 }
341 }
342 }
343
344 out:
345 mutex_unlock(&hd->ioc->sas_topology_mutex);
346 /*
347 * TODO: Issue target reset to flush firmware outstanding commands.
348 */
349 mptscsih_slave_destroy(sdev);
350}
351
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200352static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700353 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200354 .proc_name = "mptsas",
355 .proc_info = mptscsih_proc_info,
356 .name = "MPT SPI Host",
357 .info = mptscsih_info,
358 .queuecommand = mptscsih_qcmd,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700359 .target_alloc = mptscsih_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200360 .slave_alloc = mptsas_slave_alloc,
361 .slave_configure = mptscsih_slave_configure,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700362 .target_destroy = mptscsih_target_destroy,
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100363 .slave_destroy = mptsas_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200364 .change_queue_depth = mptscsih_change_queue_depth,
365 .eh_abort_handler = mptscsih_abort,
366 .eh_device_reset_handler = mptscsih_dev_reset,
367 .eh_bus_reset_handler = mptscsih_bus_reset,
368 .eh_host_reset_handler = mptscsih_host_reset,
369 .bios_param = mptscsih_bios_param,
370 .can_queue = MPT_FC_CAN_QUEUE,
371 .this_id = -1,
372 .sg_tablesize = MPT_SCSI_SG_DEPTH,
373 .max_sectors = 8192,
374 .cmd_per_lun = 7,
375 .use_clustering = ENABLE_CLUSTERING,
376};
377
Christoph Hellwigb5141122005-10-28 22:07:41 +0200378static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
379{
380 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
381 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
382}
383
384static int mptsas_get_linkerrors(struct sas_phy *phy)
385{
386 MPT_ADAPTER *ioc = phy_to_ioc(phy);
387 ConfigExtendedPageHeader_t hdr;
388 CONFIGPARMS cfg;
389 SasPhyPage1_t *buffer;
390 dma_addr_t dma_handle;
391 int error;
392
393 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
394 hdr.ExtPageLength = 0;
395 hdr.PageNumber = 1 /* page number 1*/;
396 hdr.Reserved1 = 0;
397 hdr.Reserved2 = 0;
398 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
399 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
400
401 cfg.cfghdr.ehdr = &hdr;
402 cfg.physAddr = -1;
403 cfg.pageAddr = phy->identify.phy_identifier;
404 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
405 cfg.dir = 0; /* read */
406 cfg.timeout = 10;
407
408 error = mpt_config(ioc, &cfg);
409 if (error)
410 return error;
411 if (!hdr.ExtPageLength)
412 return -ENXIO;
413
414 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
415 &dma_handle);
416 if (!buffer)
417 return -ENOMEM;
418
419 cfg.physAddr = dma_handle;
420 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
421
422 error = mpt_config(ioc, &cfg);
423 if (error)
424 goto out_free_consistent;
425
426 mptsas_print_phy_pg1(buffer);
427
428 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
429 phy->running_disparity_error_count =
430 le32_to_cpu(buffer->RunningDisparityErrorCount);
431 phy->loss_of_dword_sync_count =
432 le32_to_cpu(buffer->LossDwordSynchCount);
433 phy->phy_reset_problem_count =
434 le32_to_cpu(buffer->PhyResetProblemCount);
435
436 out_free_consistent:
437 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
438 buffer, dma_handle);
439 return error;
440}
441
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200442static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
443 MPT_FRAME_HDR *reply)
444{
445 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
446 if (reply != NULL) {
447 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
448 memcpy(ioc->sas_mgmt.reply, reply,
449 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
450 }
451 complete(&ioc->sas_mgmt.done);
452 return 1;
453}
454
455static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
456{
457 MPT_ADAPTER *ioc = phy_to_ioc(phy);
458 SasIoUnitControlRequest_t *req;
459 SasIoUnitControlReply_t *reply;
460 MPT_FRAME_HDR *mf;
461 MPIHeader_t *hdr;
462 unsigned long timeleft;
463 int error = -ERESTARTSYS;
464
465 /* not implemented for expanders */
466 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
467 return -ENXIO;
468
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100469 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200470 goto out;
471
472 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
473 if (!mf) {
474 error = -ENOMEM;
475 goto out_unlock;
476 }
477
478 hdr = (MPIHeader_t *) mf;
479 req = (SasIoUnitControlRequest_t *)mf;
480 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
481 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
482 req->MsgContext = hdr->MsgContext;
483 req->Operation = hard_reset ?
484 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
485 req->PhyNum = phy->identify.phy_identifier;
486
487 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
488
489 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
490 10 * HZ);
491 if (!timeleft) {
492 /* On timeout reset the board */
493 mpt_free_msg_frame(ioc, mf);
494 mpt_HardResetHandler(ioc, CAN_SLEEP);
495 error = -ETIMEDOUT;
496 goto out_unlock;
497 }
498
499 /* a reply frame is expected */
500 if ((ioc->sas_mgmt.status &
501 MPT_IOCTL_STATUS_RF_VALID) == 0) {
502 error = -ENXIO;
503 goto out_unlock;
504 }
505
506 /* process the completed Reply Message Frame */
507 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
508 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
509 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
510 __FUNCTION__,
511 reply->IOCStatus,
512 reply->IOCLogInfo);
513 error = -ENXIO;
514 goto out_unlock;
515 }
516
517 error = 0;
518
519 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100520 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200521 out:
522 return error;
523}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200524
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200525static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +0200526 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200527 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200528};
529
530static struct scsi_transport_template *mptsas_transport_template;
531
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200532static int
533mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
534{
535 ConfigExtendedPageHeader_t hdr;
536 CONFIGPARMS cfg;
537 SasIOUnitPage0_t *buffer;
538 dma_addr_t dma_handle;
539 int error, i;
540
541 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
542 hdr.ExtPageLength = 0;
543 hdr.PageNumber = 0;
544 hdr.Reserved1 = 0;
545 hdr.Reserved2 = 0;
546 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
547 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
548
549 cfg.cfghdr.ehdr = &hdr;
550 cfg.physAddr = -1;
551 cfg.pageAddr = 0;
552 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
553 cfg.dir = 0; /* read */
554 cfg.timeout = 10;
555
556 error = mpt_config(ioc, &cfg);
557 if (error)
558 goto out;
559 if (!hdr.ExtPageLength) {
560 error = -ENXIO;
561 goto out;
562 }
563
564 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
565 &dma_handle);
566 if (!buffer) {
567 error = -ENOMEM;
568 goto out;
569 }
570
571 cfg.physAddr = dma_handle;
572 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
573
574 error = mpt_config(ioc, &cfg);
575 if (error)
576 goto out_free_consistent;
577
578 port_info->num_phys = buffer->NumPhys;
579 port_info->phy_info = kcalloc(port_info->num_phys,
580 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
581 if (!port_info->phy_info) {
582 error = -ENOMEM;
583 goto out_free_consistent;
584 }
585
586 for (i = 0; i < port_info->num_phys; i++) {
587 mptsas_print_phy_data(&buffer->PhyData[i]);
588 port_info->phy_info[i].phy_id = i;
589 port_info->phy_info[i].port_id =
590 buffer->PhyData[i].Port;
591 port_info->phy_info[i].negotiated_link_rate =
592 buffer->PhyData[i].NegotiatedLinkRate;
593 }
594
595 out_free_consistent:
596 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
597 buffer, dma_handle);
598 out:
599 return error;
600}
601
602static int
603mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
604 u32 form, u32 form_specific)
605{
606 ConfigExtendedPageHeader_t hdr;
607 CONFIGPARMS cfg;
608 SasPhyPage0_t *buffer;
609 dma_addr_t dma_handle;
610 int error;
611
612 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
613 hdr.ExtPageLength = 0;
614 hdr.PageNumber = 0;
615 hdr.Reserved1 = 0;
616 hdr.Reserved2 = 0;
617 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
618 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
619
620 cfg.cfghdr.ehdr = &hdr;
621 cfg.dir = 0; /* read */
622 cfg.timeout = 10;
623
624 /* Get Phy Pg 0 for each Phy. */
625 cfg.physAddr = -1;
626 cfg.pageAddr = form + form_specific;
627 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
628
629 error = mpt_config(ioc, &cfg);
630 if (error)
631 goto out;
632
633 if (!hdr.ExtPageLength) {
634 error = -ENXIO;
635 goto out;
636 }
637
638 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
639 &dma_handle);
640 if (!buffer) {
641 error = -ENOMEM;
642 goto out;
643 }
644
645 cfg.physAddr = dma_handle;
646 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
647
648 error = mpt_config(ioc, &cfg);
649 if (error)
650 goto out_free_consistent;
651
652 mptsas_print_phy_pg0(buffer);
653
654 phy_info->hw_link_rate = buffer->HwLinkRate;
655 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
656 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
657 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
658
659 out_free_consistent:
660 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
661 buffer, dma_handle);
662 out:
663 return error;
664}
665
666static int
667mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
668 u32 form, u32 form_specific)
669{
670 ConfigExtendedPageHeader_t hdr;
671 CONFIGPARMS cfg;
672 SasDevicePage0_t *buffer;
673 dma_addr_t dma_handle;
674 __le64 sas_address;
675 int error;
676
677 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
678 hdr.ExtPageLength = 0;
679 hdr.PageNumber = 0;
680 hdr.Reserved1 = 0;
681 hdr.Reserved2 = 0;
682 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
683 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
684
685 cfg.cfghdr.ehdr = &hdr;
686 cfg.pageAddr = form + form_specific;
687 cfg.physAddr = -1;
688 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
689 cfg.dir = 0; /* read */
690 cfg.timeout = 10;
691
692 error = mpt_config(ioc, &cfg);
693 if (error)
694 goto out;
695 if (!hdr.ExtPageLength) {
696 error = -ENXIO;
697 goto out;
698 }
699
700 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
701 &dma_handle);
702 if (!buffer) {
703 error = -ENOMEM;
704 goto out;
705 }
706
707 cfg.physAddr = dma_handle;
708 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
709
710 error = mpt_config(ioc, &cfg);
711 if (error)
712 goto out_free_consistent;
713
714 mptsas_print_device_pg0(buffer);
715
716 device_info->handle = le16_to_cpu(buffer->DevHandle);
717 device_info->phy_id = buffer->PhyNum;
718 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100719 device_info->id = buffer->TargetID;
720 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200721 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
722 device_info->sas_address = le64_to_cpu(sas_address);
723 device_info->device_info =
724 le32_to_cpu(buffer->DeviceInfo);
725
726 out_free_consistent:
727 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
728 buffer, dma_handle);
729 out:
730 return error;
731}
732
733static int
734mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
735 u32 form, u32 form_specific)
736{
737 ConfigExtendedPageHeader_t hdr;
738 CONFIGPARMS cfg;
739 SasExpanderPage0_t *buffer;
740 dma_addr_t dma_handle;
741 int error;
742
743 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
744 hdr.ExtPageLength = 0;
745 hdr.PageNumber = 0;
746 hdr.Reserved1 = 0;
747 hdr.Reserved2 = 0;
748 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
749 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
750
751 cfg.cfghdr.ehdr = &hdr;
752 cfg.physAddr = -1;
753 cfg.pageAddr = form + form_specific;
754 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
755 cfg.dir = 0; /* read */
756 cfg.timeout = 10;
757
758 error = mpt_config(ioc, &cfg);
759 if (error)
760 goto out;
761
762 if (!hdr.ExtPageLength) {
763 error = -ENXIO;
764 goto out;
765 }
766
767 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
768 &dma_handle);
769 if (!buffer) {
770 error = -ENOMEM;
771 goto out;
772 }
773
774 cfg.physAddr = dma_handle;
775 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
776
777 error = mpt_config(ioc, &cfg);
778 if (error)
779 goto out_free_consistent;
780
781 /* save config data */
782 port_info->num_phys = buffer->NumPhys;
783 port_info->handle = le16_to_cpu(buffer->DevHandle);
784 port_info->phy_info = kcalloc(port_info->num_phys,
785 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
786 if (!port_info->phy_info) {
787 error = -ENOMEM;
788 goto out_free_consistent;
789 }
790
791 out_free_consistent:
792 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
793 buffer, dma_handle);
794 out:
795 return error;
796}
797
798static int
799mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
800 u32 form, u32 form_specific)
801{
802 ConfigExtendedPageHeader_t hdr;
803 CONFIGPARMS cfg;
804 SasExpanderPage1_t *buffer;
805 dma_addr_t dma_handle;
806 int error;
807
808 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
809 hdr.ExtPageLength = 0;
810 hdr.PageNumber = 1;
811 hdr.Reserved1 = 0;
812 hdr.Reserved2 = 0;
813 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
814 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
815
816 cfg.cfghdr.ehdr = &hdr;
817 cfg.physAddr = -1;
818 cfg.pageAddr = form + form_specific;
819 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
820 cfg.dir = 0; /* read */
821 cfg.timeout = 10;
822
823 error = mpt_config(ioc, &cfg);
824 if (error)
825 goto out;
826
827 if (!hdr.ExtPageLength) {
828 error = -ENXIO;
829 goto out;
830 }
831
832 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
833 &dma_handle);
834 if (!buffer) {
835 error = -ENOMEM;
836 goto out;
837 }
838
839 cfg.physAddr = dma_handle;
840 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
841
842 error = mpt_config(ioc, &cfg);
843 if (error)
844 goto out_free_consistent;
845
846
847 mptsas_print_expander_pg1(buffer);
848
849 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +0200850 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200851 phy_info->port_id = buffer->PhysicalPort;
852 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
853 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
854 phy_info->hw_link_rate = buffer->HwLinkRate;
855 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
856 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
857
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 void
867mptsas_parse_device_info(struct sas_identify *identify,
868 struct mptsas_devinfo *device_info)
869{
870 u16 protocols;
871
872 identify->sas_address = device_info->sas_address;
873 identify->phy_identifier = device_info->phy_id;
874
875 /*
876 * Fill in Phy Initiator Port Protocol.
877 * Bits 6:3, more than one bit can be set, fall through cases.
878 */
879 protocols = device_info->device_info & 0x78;
880 identify->initiator_port_protocols = 0;
881 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
882 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
883 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
884 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
885 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
886 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
887 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
888 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
889
890 /*
891 * Fill in Phy Target Port Protocol.
892 * Bits 10:7, more than one bit can be set, fall through cases.
893 */
894 protocols = device_info->device_info & 0x780;
895 identify->target_port_protocols = 0;
896 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
897 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
898 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
899 identify->target_port_protocols |= SAS_PROTOCOL_STP;
900 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
901 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
902 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
903 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
904
905 /*
906 * Fill in Attached device type.
907 */
908 switch (device_info->device_info &
909 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
910 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
911 identify->device_type = SAS_PHY_UNUSED;
912 break;
913 case MPI_SAS_DEVICE_INFO_END_DEVICE:
914 identify->device_type = SAS_END_DEVICE;
915 break;
916 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
917 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
918 break;
919 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
920 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
921 break;
922 }
923}
924
925static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +0200926 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200927{
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100928 struct sas_phy *phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200929 int error;
930
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100931 phy = sas_phy_alloc(dev, index);
932 if (!phy)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200933 return -ENOMEM;
934
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100935 phy->port_identifier = phy_info->port_id;
936 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200937
938 /*
939 * Set Negotiated link rate.
940 */
941 switch (phy_info->negotiated_link_rate) {
942 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100943 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200944 break;
945 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100946 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200947 break;
948 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100949 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200950 break;
951 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100952 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200953 break;
954 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
955 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
956 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100957 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200958 break;
959 }
960
961 /*
962 * Set Max hardware link rate.
963 */
964 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
965 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100966 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200967 break;
968 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100969 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200970 break;
971 default:
972 break;
973 }
974
975 /*
976 * Set Max programmed link rate.
977 */
978 switch (phy_info->programmed_link_rate &
979 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
980 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100981 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200982 break;
983 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100984 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200985 break;
986 default:
987 break;
988 }
989
990 /*
991 * Set Min hardware link rate.
992 */
993 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
994 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100995 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200996 break;
997 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100998 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200999 break;
1000 default:
1001 break;
1002 }
1003
1004 /*
1005 * Set Min programmed link rate.
1006 */
1007 switch (phy_info->programmed_link_rate &
1008 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1009 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001010 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001011 break;
1012 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001013 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001014 break;
1015 default:
1016 break;
1017 }
1018
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001019 if (local)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001020 phy->local_attached = 1;
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001021
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001022 error = sas_phy_add(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001023 if (error) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001024 sas_phy_free(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001025 return error;
1026 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001027 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001028
1029 if (phy_info->attached.handle) {
1030 struct sas_rphy *rphy;
1031
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001032 rphy = sas_rphy_alloc(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001033 if (!rphy)
1034 return 0; /* non-fatal: an rphy can be added later */
1035
1036 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1037 error = sas_rphy_add(rphy);
1038 if (error) {
1039 sas_rphy_free(rphy);
1040 return error;
1041 }
1042
1043 phy_info->rphy = rphy;
1044 }
1045
1046 return 0;
1047}
1048
1049static int
1050mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
1051{
1052 struct mptsas_portinfo *port_info;
1053 u32 handle = 0xFFFF;
1054 int error = -ENOMEM, i;
1055
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001056 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001057 if (!port_info)
1058 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001059
1060 error = mptsas_sas_io_unit_pg0(ioc, port_info);
1061 if (error)
1062 goto out_free_port_info;
1063
Moore, Eric816aa902006-01-13 16:25:20 -07001064 ioc->num_ports = port_info->num_phys;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001065 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001066 list_add_tail(&port_info->list, &ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001067 mutex_unlock(&ioc->sas_topology_mutex);
1068
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001069 for (i = 0; i < port_info->num_phys; i++) {
1070 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1071 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1072 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1073
1074 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1075 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1076 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02001077 port_info->phy_info[i].identify.phy_id =
1078 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001079 handle = port_info->phy_info[i].identify.handle;
1080
1081 if (port_info->phy_info[i].attached.handle) {
1082 mptsas_sas_device_pg0(ioc,
1083 &port_info->phy_info[i].attached,
1084 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1085 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1086 port_info->phy_info[i].attached.handle);
1087 }
1088
1089 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001090 &port_info->phy_info[i], *index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001091 (*index)++;
1092 }
1093
1094 return 0;
1095
1096 out_free_port_info:
1097 kfree(port_info);
1098 out:
1099 return error;
1100}
1101
1102static int
1103mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1104{
1105 struct mptsas_portinfo *port_info, *p;
1106 int error = -ENOMEM, i, j;
1107
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001108 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001109 if (!port_info)
1110 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001111
1112 error = mptsas_sas_expander_pg0(ioc, port_info,
1113 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1114 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1115 if (error)
1116 goto out_free_port_info;
1117
1118 *handle = port_info->handle;
1119
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001120 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001121 list_add_tail(&port_info->list, &ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001122 mutex_unlock(&ioc->sas_topology_mutex);
1123
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001124 for (i = 0; i < port_info->num_phys; i++) {
1125 struct device *parent;
1126
1127 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1128 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1129 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1130
1131 if (port_info->phy_info[i].identify.handle) {
1132 mptsas_sas_device_pg0(ioc,
1133 &port_info->phy_info[i].identify,
1134 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1135 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1136 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001137 port_info->phy_info[i].identify.phy_id =
1138 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001139 }
1140
1141 if (port_info->phy_info[i].attached.handle) {
1142 mptsas_sas_device_pg0(ioc,
1143 &port_info->phy_info[i].attached,
1144 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1145 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1146 port_info->phy_info[i].attached.handle);
1147 }
1148
1149 /*
1150 * If we find a parent port handle this expander is
1151 * attached to another expander, else it hangs of the
1152 * HBA phys.
1153 */
1154 parent = &ioc->sh->shost_gendev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001155 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001156 list_for_each_entry(p, &ioc->sas_topology, list) {
1157 for (j = 0; j < p->num_phys; j++) {
1158 if (port_info->phy_info[i].identify.handle ==
1159 p->phy_info[j].attached.handle)
1160 parent = &p->phy_info[j].rphy->dev;
1161 }
1162 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001163 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001164
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001165 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
1166 *index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001167 (*index)++;
1168 }
1169
1170 return 0;
1171
1172 out_free_port_info:
1173 kfree(port_info);
1174 out:
1175 return error;
1176}
1177
1178static void
1179mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1180{
1181 u32 handle = 0xFFFF;
1182 int index = 0;
1183
1184 mptsas_probe_hba_phys(ioc, &index);
1185 while (!mptsas_probe_expander_phys(ioc, &handle, &index))
1186 ;
1187}
1188
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001189static struct mptsas_phyinfo *
1190mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
1191{
1192 struct mptsas_portinfo *port_info;
1193 struct mptsas_devinfo device_info;
1194 struct mptsas_phyinfo *phy_info = NULL;
1195 int i, error;
1196
1197 /*
1198 * Retrieve the parent sas_address
1199 */
1200 error = mptsas_sas_device_pg0(ioc, &device_info,
1201 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1202 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1203 parent_handle);
1204 if (error) {
1205 printk("mptsas: failed to retrieve device page\n");
1206 return NULL;
1207 }
1208
1209 /*
1210 * The phy_info structures are never deallocated during lifetime of
1211 * a host, so the code below is safe without additional refcounting.
1212 */
1213 mutex_lock(&ioc->sas_topology_mutex);
1214 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1215 for (i = 0; i < port_info->num_phys; i++) {
1216 if (port_info->phy_info[i].identify.sas_address ==
1217 device_info.sas_address &&
1218 port_info->phy_info[i].phy_id == phy_id) {
1219 phy_info = &port_info->phy_info[i];
1220 break;
1221 }
1222 }
1223 }
1224 mutex_unlock(&ioc->sas_topology_mutex);
1225
1226 return phy_info;
1227}
1228
1229static struct mptsas_phyinfo *
1230mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
1231{
1232 struct mptsas_portinfo *port_info;
1233 struct mptsas_phyinfo *phy_info = NULL;
1234 int i;
1235
1236 /*
1237 * The phy_info structures are never deallocated during lifetime of
1238 * a host, so the code below is safe without additional refcounting.
1239 */
1240 mutex_lock(&ioc->sas_topology_mutex);
1241 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1242 for (i = 0; i < port_info->num_phys; i++) {
1243 if (port_info->phy_info[i].attached.handle == handle) {
1244 phy_info = &port_info->phy_info[i];
1245 break;
1246 }
1247 }
1248 }
1249 mutex_unlock(&ioc->sas_topology_mutex);
1250
1251 return phy_info;
1252}
1253
1254static void
1255mptsas_hotplug_work(void *arg)
1256{
1257 struct mptsas_hotplug_event *ev = arg;
1258 MPT_ADAPTER *ioc = ev->ioc;
1259 struct mptsas_phyinfo *phy_info;
1260 struct sas_rphy *rphy;
1261 char *ds = NULL;
1262
1263 if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1264 ds = "ssp";
1265 if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1266 ds = "stp";
1267 if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1268 ds = "sata";
1269
1270 switch (ev->event_type) {
1271 case MPTSAS_DEL_DEVICE:
1272 printk(MYIOC_s_INFO_FMT
1273 "removing %s device, channel %d, id %d, phy %d\n",
1274 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1275
1276 phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle);
1277 if (!phy_info) {
1278 printk("mptsas: remove event for non-existant PHY.\n");
1279 break;
1280 }
1281
1282 if (phy_info->rphy) {
1283 sas_rphy_delete(phy_info->rphy);
1284 phy_info->rphy = NULL;
1285 }
1286 break;
1287 case MPTSAS_ADD_DEVICE:
1288 printk(MYIOC_s_INFO_FMT
1289 "attaching %s device, channel %d, id %d, phy %d\n",
1290 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1291
1292 phy_info = mptsas_find_phyinfo_by_parent(ioc,
1293 ev->parent_handle, ev->phy_id);
1294 if (!phy_info) {
1295 printk("mptsas: add event for non-existant PHY.\n");
1296 break;
1297 }
1298
1299 if (phy_info->rphy) {
1300 printk("mptsas: trying to add existing device.\n");
1301 break;
1302 }
1303
1304 /* fill attached info */
1305 phy_info->attached.handle = ev->handle;
1306 phy_info->attached.phy_id = ev->phy_id;
1307 phy_info->attached.port_id = phy_info->identify.port_id;
1308 phy_info->attached.id = ev->id;
1309 phy_info->attached.channel = ev->channel;
1310 phy_info->attached.sas_address = ev->sas_address;
1311 phy_info->attached.device_info = ev->device_info;
1312
1313 rphy = sas_rphy_alloc(phy_info->phy);
1314 if (!rphy)
1315 break; /* non-fatal: an rphy can be added later */
1316
1317 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1318 if (sas_rphy_add(rphy)) {
1319 sas_rphy_free(rphy);
1320 break;
1321 }
1322
1323 phy_info->rphy = rphy;
1324 break;
1325 }
1326
1327 kfree(ev);
1328}
1329
1330static void
1331mptscsih_send_sas_event(MPT_ADAPTER *ioc,
1332 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
1333{
1334 struct mptsas_hotplug_event *ev;
1335 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
1336 __le64 sas_address;
1337
1338 if ((device_info &
1339 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
1340 MPI_SAS_DEVICE_INFO_STP_TARGET |
1341 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
1342 return;
1343
1344 if ((sas_event_data->ReasonCode &
1345 (MPI_EVENT_SAS_DEV_STAT_RC_ADDED |
1346 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0)
1347 return;
1348
1349 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1350 if (!ev) {
1351 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1352 return;
1353 }
1354
1355
1356 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1357 ev->ioc = ioc;
1358 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
1359 ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
1360 ev->channel = sas_event_data->Bus;
1361 ev->id = sas_event_data->TargetID;
1362 ev->phy_id = sas_event_data->PhyNum;
1363 memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64));
1364 ev->sas_address = le64_to_cpu(sas_address);
1365 ev->device_info = device_info;
1366
1367 if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
1368 ev->event_type = MPTSAS_ADD_DEVICE;
1369 else
1370 ev->event_type = MPTSAS_DEL_DEVICE;
1371
1372 schedule_work(&ev->work);
1373}
1374
1375static int
1376mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
1377{
1378 u8 event = le32_to_cpu(reply->Event) & 0xFF;
1379
1380 if (!ioc->sh)
1381 return 1;
1382
1383 switch (event) {
1384 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1385 mptscsih_send_sas_event(ioc,
1386 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
1387 return 1; /* currently means nothing really */
1388
1389 default:
1390 return mptscsih_event_process(ioc, reply);
1391 }
1392}
1393
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001394static int
1395mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1396{
1397 struct Scsi_Host *sh;
1398 MPT_SCSI_HOST *hd;
1399 MPT_ADAPTER *ioc;
1400 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001401 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001402 int numSGE = 0;
1403 int scale;
1404 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001405 int error=0;
1406 int r;
1407
1408 r = mpt_attach(pdev,id);
1409 if (r)
1410 return r;
1411
1412 ioc = pci_get_drvdata(pdev);
1413 ioc->DoneCtx = mptsasDoneCtx;
1414 ioc->TaskCtx = mptsasTaskCtx;
1415 ioc->InternalCtx = mptsasInternalCtx;
1416
1417 /* Added sanity check on readiness of the MPT adapter.
1418 */
1419 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1420 printk(MYIOC_s_WARN_FMT
1421 "Skipping because it's not operational!\n",
1422 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001423 error = -ENODEV;
1424 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001425 }
1426
1427 if (!ioc->active) {
1428 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1429 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001430 error = -ENODEV;
1431 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001432 }
1433
1434 /* Sanity check - ensure at least 1 port is INITIATOR capable
1435 */
1436 ioc_cap = 0;
1437 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
1438 if (ioc->pfacts[ii].ProtocolFlags &
1439 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1440 ioc_cap++;
1441 }
1442
1443 if (!ioc_cap) {
1444 printk(MYIOC_s_WARN_FMT
1445 "Skipping ioc=%p because SCSI Initiator mode "
1446 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06001447 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001448 }
1449
1450 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
1451 if (!sh) {
1452 printk(MYIOC_s_WARN_FMT
1453 "Unable to register controller with SCSI subsystem\n",
1454 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001455 error = -1;
1456 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001457 }
1458
1459 spin_lock_irqsave(&ioc->FreeQlock, flags);
1460
1461 /* Attach the SCSI Host to the IOC structure
1462 */
1463 ioc->sh = sh;
1464
1465 sh->io_port = 0;
1466 sh->n_io_port = 0;
1467 sh->irq = 0;
1468
1469 /* set 16 byte cdb's */
1470 sh->max_cmd_len = 16;
1471
1472 sh->max_id = ioc->pfacts->MaxDevices + 1;
1473
1474 sh->transportt = mptsas_transport_template;
1475
1476 sh->max_lun = MPT_LAST_LUN + 1;
1477 sh->max_channel = 0;
1478 sh->this_id = ioc->pfacts[0].PortSCSIID;
1479
1480 /* Required entry.
1481 */
1482 sh->unique_id = ioc->id;
1483
1484 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001485 mutex_init(&ioc->sas_topology_mutex);
1486
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01001487 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001488 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001489
1490 /* Verify that we won't exceed the maximum
1491 * number of chain buffers
1492 * We can optimize: ZZ = req_sz/sizeof(SGE)
1493 * For 32bit SGE's:
1494 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1495 * + (req_sz - 64)/sizeof(SGE)
1496 * A slightly different algorithm is required for
1497 * 64bit SGEs.
1498 */
1499 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1500 if (sizeof(dma_addr_t) == sizeof(u64)) {
1501 numSGE = (scale - 1) *
1502 (ioc->facts.MaxChainDepth-1) + scale +
1503 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1504 sizeof(u32));
1505 } else {
1506 numSGE = 1 + (scale - 1) *
1507 (ioc->facts.MaxChainDepth-1) + scale +
1508 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1509 sizeof(u32));
1510 }
1511
1512 if (numSGE < sh->sg_tablesize) {
1513 /* Reset this value */
1514 dprintk((MYIOC_s_INFO_FMT
1515 "Resetting sg_tablesize to %d from %d\n",
1516 ioc->name, numSGE, sh->sg_tablesize));
1517 sh->sg_tablesize = numSGE;
1518 }
1519
1520 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1521
1522 hd = (MPT_SCSI_HOST *) sh->hostdata;
1523 hd->ioc = ioc;
1524
1525 /* SCSI needs scsi_cmnd lookup table!
1526 * (with size equal to req_depth*PtrSz!)
1527 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001528 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1529 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001530 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001531 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001532 }
1533
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001534 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1535 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001536
1537 /* Allocate memory for the device structures.
1538 * A non-Null pointer at an offset
1539 * indicates a device exists.
1540 * max_id = 1 + maximum id (hosts.h)
1541 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001542 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
1543 if (!hd->Targets) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001544 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001545 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001546 }
1547
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001548 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001549
1550 /* Clear the TM flags
1551 */
1552 hd->tmPending = 0;
1553 hd->tmState = TM_STATE_NONE;
1554 hd->resetPending = 0;
1555 hd->abortSCpnt = NULL;
1556
1557 /* Clear the pointer used to store
1558 * single-threaded commands, i.e., those
1559 * issued during a bus scan, dv and
1560 * configuration pages.
1561 */
1562 hd->cmdPtr = NULL;
1563
1564 /* Initialize this SCSI Hosts' timers
1565 * To use, set the timer expires field
1566 * and add_timer
1567 */
1568 init_timer(&hd->timer);
1569 hd->timer.data = (unsigned long) hd;
1570 hd->timer.function = mptscsih_timer_expired;
1571
1572 hd->mpt_pq_filter = mpt_pq_filter;
1573 ioc->sas_data.ptClear = mpt_pt_clear;
1574
1575 if (ioc->sas_data.ptClear==1) {
1576 mptbase_sas_persist_operation(
1577 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
1578 }
1579
1580 ddvprintk((MYIOC_s_INFO_FMT
1581 "mpt_pq_filter %x mpt_pq_filter %x\n",
1582 ioc->name,
1583 mpt_pq_filter,
1584 mpt_pq_filter));
1585
1586 init_waitqueue_head(&hd->scandv_waitq);
1587 hd->scandv_wait_done = 0;
1588 hd->last_queue_full = 0;
1589
1590 error = scsi_add_host(sh, &ioc->pcidev->dev);
1591 if (error) {
1592 dprintk((KERN_ERR MYNAM
1593 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001594 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001595 }
1596
1597 mptsas_scan_sas_topology(ioc);
1598
Moore, Eric816aa902006-01-13 16:25:20 -07001599 /*
1600 Reporting RAID volumes.
1601 */
1602 if (!ioc->raid_data.pIocPg2)
1603 return 0;
1604 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1605 return 0;
1606 for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
1607 scsi_add_device(sh,
1608 ioc->num_ports,
1609 ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
1610 0);
1611 }
1612
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001613 return 0;
1614
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001615out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001616
1617 mptscsih_remove(pdev);
1618 return error;
1619}
1620
1621static void __devexit mptsas_remove(struct pci_dev *pdev)
1622{
1623 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1624 struct mptsas_portinfo *p, *n;
1625
1626 sas_remove_host(ioc->sh);
1627
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001628 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001629 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
1630 list_del(&p->list);
1631 kfree(p);
1632 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001633 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001634
1635 mptscsih_remove(pdev);
1636}
1637
1638static struct pci_device_id mptsas_pci_table[] = {
1639 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
1640 PCI_ANY_ID, PCI_ANY_ID },
1641 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
1642 PCI_ANY_ID, PCI_ANY_ID },
1643 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
1644 PCI_ANY_ID, PCI_ANY_ID },
1645 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
1646 PCI_ANY_ID, PCI_ANY_ID },
1647 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
1648 PCI_ANY_ID, PCI_ANY_ID },
1649 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
1650 PCI_ANY_ID, PCI_ANY_ID },
1651 {0} /* Terminating entry */
1652};
1653MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
1654
1655
1656static struct pci_driver mptsas_driver = {
1657 .name = "mptsas",
1658 .id_table = mptsas_pci_table,
1659 .probe = mptsas_probe,
1660 .remove = __devexit_p(mptsas_remove),
1661 .shutdown = mptscsih_shutdown,
1662#ifdef CONFIG_PM
1663 .suspend = mptscsih_suspend,
1664 .resume = mptscsih_resume,
1665#endif
1666};
1667
1668static int __init
1669mptsas_init(void)
1670{
1671 show_mptmod_ver(my_NAME, my_VERSION);
1672
1673 mptsas_transport_template =
1674 sas_attach_transport(&mptsas_transport_functions);
1675 if (!mptsas_transport_template)
1676 return -ENODEV;
1677
1678 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
1679 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
1680 mptsasInternalCtx =
1681 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001682 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001683
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001684 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001685 devtprintk((KERN_INFO MYNAM
1686 ": Registered for IOC event notifications\n"));
1687 }
1688
1689 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
1690 dprintk((KERN_INFO MYNAM
1691 ": Registered for IOC reset notifications\n"));
1692 }
1693
1694 return pci_register_driver(&mptsas_driver);
1695}
1696
1697static void __exit
1698mptsas_exit(void)
1699{
1700 pci_unregister_driver(&mptsas_driver);
1701 sas_release_transport(mptsas_transport_template);
1702
1703 mpt_reset_deregister(mptsasDoneCtx);
1704 mpt_event_deregister(mptsasDoneCtx);
1705
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001706 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001707 mpt_deregister(mptsasInternalCtx);
1708 mpt_deregister(mptsasTaskCtx);
1709 mpt_deregister(mptsasDoneCtx);
1710}
1711
1712module_init(mptsas_init);
1713module_exit(mptsas_exit);