blob: 2512d0e6155ede3b55f1996b13fe69b6b78eda0a [file] [log] [blame]
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001/*
2 * linux/drivers/message/fusion/mptsas.c
3 * For use with LSI Logic PCI chip/adapter(s)
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5 *
6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01008 * Copyright (c) 2005-2006 Dell
Christoph Hellwig0c33b272005-09-09 16:27:19 +02009 */
10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11/*
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 NO WARRANTY
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
31
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44*/
45/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46
47#include <linux/module.h>
48#include <linux/kernel.h>
49#include <linux/init.h>
50#include <linux/errno.h>
51#include <linux/sched.h>
52#include <linux/workqueue.h>
53
54#include <scsi/scsi_cmnd.h>
55#include <scsi/scsi_device.h>
56#include <scsi/scsi_host.h>
57#include <scsi/scsi_transport_sas.h>
58
59#include "mptbase.h"
60#include "mptscsih.h"
61
62
63#define my_NAME "Fusion MPT SAS Host driver"
64#define my_VERSION MPT_LINUX_VERSION_COMMON
65#define MYNAM "mptsas"
66
67MODULE_AUTHOR(MODULEAUTHOR);
68MODULE_DESCRIPTION(my_NAME);
69MODULE_LICENSE("GPL");
70
71static int mpt_pq_filter;
72module_param(mpt_pq_filter, int, 0);
73MODULE_PARM_DESC(mpt_pq_filter,
74 "Enable peripheral qualifier filter: enable=1 "
75 "(default=0)");
76
77static int mpt_pt_clear;
78module_param(mpt_pt_clear, int, 0);
79MODULE_PARM_DESC(mpt_pt_clear,
80 "Clear persistency table: enable=1 "
81 "(default=MPTSCSIH_PT_CLEAR=0)");
82
83static int mptsasDoneCtx = -1;
84static int mptsasTaskCtx = -1;
85static int mptsasInternalCtx = -1; /* Used only for internal commands */
Christoph Hellwigda4fa652005-10-19 20:01:42 +020086static int mptsasMgmtCtx = -1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +020087
88
Christoph Hellwig9a28f492006-01-13 18:04:41 +010089enum mptsas_hotplug_action {
90 MPTSAS_ADD_DEVICE,
91 MPTSAS_DEL_DEVICE,
Moore, Ericc73787ee2006-01-26 16:20:06 -070092 MPTSAS_ADD_RAID,
93 MPTSAS_DEL_RAID,
Christoph Hellwig9a28f492006-01-13 18:04:41 +010094};
95
96struct mptsas_hotplug_event {
97 struct work_struct work;
98 MPT_ADAPTER *ioc;
99 enum mptsas_hotplug_action event_type;
100 u64 sas_address;
101 u32 channel;
102 u32 id;
103 u32 device_info;
104 u16 handle;
105 u16 parent_handle;
106 u8 phy_id;
107};
108
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200109/*
110 * SAS topology structures
111 *
112 * The MPT Fusion firmware interface spreads information about the
113 * SAS topology over many manufacture pages, thus we need some data
114 * structure to collect it and process it for the SAS transport class.
115 */
116
117struct mptsas_devinfo {
118 u16 handle; /* unique id to address this device */
Moore, Ericc73787ee2006-01-26 16:20:06 -0700119 u16 handle_parent; /* unique id to address parent device */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200120 u8 phy_id; /* phy number of parent device */
121 u8 port_id; /* sas physical port this device
122 is assoc'd with */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100123 u8 id; /* logical target id of this device */
124 u8 channel; /* logical bus number of this device */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200125 u64 sas_address; /* WWN of this device,
126 SATA is assigned by HBA,expander */
127 u32 device_info; /* bitfield detailed info about this device */
128};
129
130struct mptsas_phyinfo {
131 u8 phy_id; /* phy index */
132 u8 port_id; /* port number this phy is part of */
133 u8 negotiated_link_rate; /* nego'd link rate for this phy */
134 u8 hw_link_rate; /* hardware max/min phys link rate */
135 u8 programmed_link_rate; /* programmed max/min phy link rate */
136 struct mptsas_devinfo identify; /* point to phy device info */
137 struct mptsas_devinfo attached; /* point to attached device info */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100138 struct sas_phy *phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200139 struct sas_rphy *rphy;
140};
141
142struct mptsas_portinfo {
143 struct list_head list;
144 u16 handle; /* unique id to address this */
145 u8 num_phys; /* number of phys */
146 struct mptsas_phyinfo *phy_info;
147};
148
Christoph Hellwigb5141122005-10-28 22:07:41 +0200149
150#ifdef SASDEBUG
151static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
152{
153 printk("---- IO UNIT PAGE 0 ------------\n");
154 printk("Handle=0x%X\n",
155 le16_to_cpu(phy_data->AttachedDeviceHandle));
156 printk("Controller Handle=0x%X\n",
157 le16_to_cpu(phy_data->ControllerDevHandle));
158 printk("Port=0x%X\n", phy_data->Port);
159 printk("Port Flags=0x%X\n", phy_data->PortFlags);
160 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
161 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
162 printk("Controller PHY Device Info=0x%X\n",
163 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
164 printk("DiscoveryStatus=0x%X\n",
165 le32_to_cpu(phy_data->DiscoveryStatus));
166 printk("\n");
167}
168
169static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
170{
171 __le64 sas_address;
172
173 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
174
175 printk("---- SAS PHY PAGE 0 ------------\n");
176 printk("Attached Device Handle=0x%X\n",
177 le16_to_cpu(pg0->AttachedDevHandle));
178 printk("SAS Address=0x%llX\n",
179 (unsigned long long)le64_to_cpu(sas_address));
180 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
181 printk("Attached Device Info=0x%X\n",
182 le32_to_cpu(pg0->AttachedDeviceInfo));
183 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
184 printk("Change Count=0x%X\n", pg0->ChangeCount);
185 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
186 printk("\n");
187}
188
189static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
190{
191 printk("---- SAS PHY PAGE 1 ------------\n");
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200192 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
193 printk("Running Disparity Error Count=0x%x\n",
Christoph Hellwigb5141122005-10-28 22:07:41 +0200194 pg1->RunningDisparityErrorCount);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200195 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
196 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
197 printk("\n");
Christoph Hellwigb5141122005-10-28 22:07:41 +0200198}
199
200static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
201{
202 __le64 sas_address;
203
204 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
205
206 printk("---- SAS DEVICE PAGE 0 ---------\n");
207 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
208 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
209 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
210 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
211 printk("Target ID=0x%X\n", pg0->TargetID);
212 printk("Bus=0x%X\n", pg0->Bus);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200213 /* The PhyNum field specifies the PHY number of the parent
214 * device this device is linked to
215 */
216 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
217 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200218 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
219 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
220 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
221 printk("\n");
222}
223
224static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
225{
226 printk("---- SAS EXPANDER PAGE 1 ------------\n");
227
228 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200229 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwigb5141122005-10-28 22:07:41 +0200230 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
231 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
232 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
233 printk("Owner Device Handle=0x%X\n",
234 le16_to_cpu(pg1->OwnerDevHandle));
235 printk("Attached Device Handle=0x%X\n",
236 le16_to_cpu(pg1->AttachedDevHandle));
237}
238#else
239#define mptsas_print_phy_data(phy_data) do { } while (0)
240#define mptsas_print_phy_pg0(pg0) do { } while (0)
241#define mptsas_print_phy_pg1(pg1) do { } while (0)
242#define mptsas_print_device_pg0(pg0) do { } while (0)
243#define mptsas_print_expander_pg1(pg1) do { } while (0)
244#endif
245
246
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200247/*
248 * This is pretty ugly. We will be able to seriously clean it up
249 * once the DV code in mptscsih goes away and we can properly
250 * implement ->target_alloc.
251 */
252static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700253mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200254{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700255 struct Scsi_Host *host = sdev->host;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200256 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
257 struct sas_rphy *rphy;
258 struct mptsas_portinfo *p;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700259 VirtTarget *vtarget;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200260 VirtDevice *vdev;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700261 struct scsi_target *starget;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200262 int i;
263
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100264 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200265 if (!vdev) {
266 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
267 hd->ioc->name, sizeof(VirtDevice));
268 return -ENOMEM;
269 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200270 vdev->ioc_id = hd->ioc->id;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700271 sdev->hostdata = vdev;
272 starget = scsi_target(sdev);
273 vtarget = starget->hostdata;
274 vdev->vtarget = vtarget;
275 if (vtarget->num_luns == 0) {
276 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
277 hd->Targets[sdev->id] = vtarget;
278 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200279
Moore, Eric816aa902006-01-13 16:25:20 -0700280 /*
281 RAID volumes placed beyond the last expected port.
282 */
283 if (sdev->channel == hd->ioc->num_ports) {
284 vdev->target_id = sdev->id;
285 vdev->bus_id = 0;
286 vdev->lun = 0;
287 goto out;
288 }
289
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700290 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100291 mutex_lock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200292 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
293 for (i = 0; i < p->num_phys; i++) {
294 if (p->phy_info[i].attached.sas_address ==
295 rphy->identify.sas_address) {
296 vdev->target_id =
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100297 p->phy_info[i].attached.id;
298 vdev->bus_id = p->phy_info[i].attached.channel;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700299 vdev->lun = sdev->lun;
Moore, Eric816aa902006-01-13 16:25:20 -0700300 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200301 goto out;
302 }
303 }
304 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100305 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200306
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200307 kfree(vdev);
Christoph Hellwig23f236e2006-01-30 19:00:43 +0100308 return -ENXIO;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200309
310 out:
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700311 vtarget->ioc_id = vdev->ioc_id;
312 vtarget->target_id = vdev->target_id;
313 vtarget->bus_id = vdev->bus_id;
314 vtarget->num_luns++;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200315 return 0;
316}
317
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100318static void
319mptsas_slave_destroy(struct scsi_device *sdev)
320{
321 struct Scsi_Host *host = sdev->host;
322 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
323 struct sas_rphy *rphy;
324 struct mptsas_portinfo *p;
325 int i;
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700326 VirtDevice *vdev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100327
328 /*
329 * Handle hotplug removal case.
330 * We need to clear out attached data structure.
331 */
332 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
333
334 mutex_lock(&hd->ioc->sas_topology_mutex);
335 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
336 for (i = 0; i < p->num_phys; i++) {
337 if (p->phy_info[i].attached.sas_address ==
338 rphy->identify.sas_address) {
339 memset(&p->phy_info[i].attached, 0,
340 sizeof(struct mptsas_devinfo));
341 p->phy_info[i].rphy = NULL;
342 goto out;
343 }
344 }
345 }
346
347 out:
348 mutex_unlock(&hd->ioc->sas_topology_mutex);
349 /*
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700350 * Issue target reset to flush firmware outstanding commands.
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100351 */
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700352 vdev = sdev->hostdata;
353 if (vdev->configured_lun){
354 if (mptscsih_TMHandler(hd,
355 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
356 vdev->bus_id,
357 vdev->target_id,
358 0, 0, 5 /* 5 second timeout */)
359 < 0){
360
361 /* The TM request failed!
362 * Fatal error case.
363 */
364 printk(MYIOC_s_WARN_FMT
365 "Error processing TaskMgmt id=%d TARGET_RESET\n",
366 hd->ioc->name,
367 vdev->target_id);
368
369 hd->tmPending = 0;
370 hd->tmState = TM_STATE_NONE;
371 }
372 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100373 mptscsih_slave_destroy(sdev);
374}
375
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200376static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700377 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200378 .proc_name = "mptsas",
379 .proc_info = mptscsih_proc_info,
380 .name = "MPT SPI Host",
381 .info = mptscsih_info,
382 .queuecommand = mptscsih_qcmd,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700383 .target_alloc = mptscsih_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200384 .slave_alloc = mptsas_slave_alloc,
385 .slave_configure = mptscsih_slave_configure,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700386 .target_destroy = mptscsih_target_destroy,
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100387 .slave_destroy = mptsas_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200388 .change_queue_depth = mptscsih_change_queue_depth,
389 .eh_abort_handler = mptscsih_abort,
390 .eh_device_reset_handler = mptscsih_dev_reset,
391 .eh_bus_reset_handler = mptscsih_bus_reset,
392 .eh_host_reset_handler = mptscsih_host_reset,
393 .bios_param = mptscsih_bios_param,
394 .can_queue = MPT_FC_CAN_QUEUE,
395 .this_id = -1,
396 .sg_tablesize = MPT_SCSI_SG_DEPTH,
397 .max_sectors = 8192,
398 .cmd_per_lun = 7,
399 .use_clustering = ENABLE_CLUSTERING,
400};
401
Christoph Hellwigb5141122005-10-28 22:07:41 +0200402static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
403{
404 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
405 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
406}
407
408static int mptsas_get_linkerrors(struct sas_phy *phy)
409{
410 MPT_ADAPTER *ioc = phy_to_ioc(phy);
411 ConfigExtendedPageHeader_t hdr;
412 CONFIGPARMS cfg;
413 SasPhyPage1_t *buffer;
414 dma_addr_t dma_handle;
415 int error;
416
417 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
418 hdr.ExtPageLength = 0;
419 hdr.PageNumber = 1 /* page number 1*/;
420 hdr.Reserved1 = 0;
421 hdr.Reserved2 = 0;
422 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
423 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
424
425 cfg.cfghdr.ehdr = &hdr;
426 cfg.physAddr = -1;
427 cfg.pageAddr = phy->identify.phy_identifier;
428 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
429 cfg.dir = 0; /* read */
430 cfg.timeout = 10;
431
432 error = mpt_config(ioc, &cfg);
433 if (error)
434 return error;
435 if (!hdr.ExtPageLength)
436 return -ENXIO;
437
438 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
439 &dma_handle);
440 if (!buffer)
441 return -ENOMEM;
442
443 cfg.physAddr = dma_handle;
444 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
445
446 error = mpt_config(ioc, &cfg);
447 if (error)
448 goto out_free_consistent;
449
450 mptsas_print_phy_pg1(buffer);
451
452 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
453 phy->running_disparity_error_count =
454 le32_to_cpu(buffer->RunningDisparityErrorCount);
455 phy->loss_of_dword_sync_count =
456 le32_to_cpu(buffer->LossDwordSynchCount);
457 phy->phy_reset_problem_count =
458 le32_to_cpu(buffer->PhyResetProblemCount);
459
460 out_free_consistent:
461 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
462 buffer, dma_handle);
463 return error;
464}
465
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200466static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
467 MPT_FRAME_HDR *reply)
468{
469 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
470 if (reply != NULL) {
471 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
472 memcpy(ioc->sas_mgmt.reply, reply,
473 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
474 }
475 complete(&ioc->sas_mgmt.done);
476 return 1;
477}
478
479static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
480{
481 MPT_ADAPTER *ioc = phy_to_ioc(phy);
482 SasIoUnitControlRequest_t *req;
483 SasIoUnitControlReply_t *reply;
484 MPT_FRAME_HDR *mf;
485 MPIHeader_t *hdr;
486 unsigned long timeleft;
487 int error = -ERESTARTSYS;
488
489 /* not implemented for expanders */
490 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
491 return -ENXIO;
492
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100493 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200494 goto out;
495
496 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
497 if (!mf) {
498 error = -ENOMEM;
499 goto out_unlock;
500 }
501
502 hdr = (MPIHeader_t *) mf;
503 req = (SasIoUnitControlRequest_t *)mf;
504 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
505 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
506 req->MsgContext = hdr->MsgContext;
507 req->Operation = hard_reset ?
508 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
509 req->PhyNum = phy->identify.phy_identifier;
510
511 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
512
513 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
514 10 * HZ);
515 if (!timeleft) {
516 /* On timeout reset the board */
517 mpt_free_msg_frame(ioc, mf);
518 mpt_HardResetHandler(ioc, CAN_SLEEP);
519 error = -ETIMEDOUT;
520 goto out_unlock;
521 }
522
523 /* a reply frame is expected */
524 if ((ioc->sas_mgmt.status &
525 MPT_IOCTL_STATUS_RF_VALID) == 0) {
526 error = -ENXIO;
527 goto out_unlock;
528 }
529
530 /* process the completed Reply Message Frame */
531 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
532 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
533 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
534 __FUNCTION__,
535 reply->IOCStatus,
536 reply->IOCLogInfo);
537 error = -ENXIO;
538 goto out_unlock;
539 }
540
541 error = 0;
542
543 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100544 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200545 out:
546 return error;
547}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200548
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200549static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +0200550 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200551 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200552};
553
554static struct scsi_transport_template *mptsas_transport_template;
555
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200556static int
557mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
558{
559 ConfigExtendedPageHeader_t hdr;
560 CONFIGPARMS cfg;
561 SasIOUnitPage0_t *buffer;
562 dma_addr_t dma_handle;
563 int error, i;
564
565 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
566 hdr.ExtPageLength = 0;
567 hdr.PageNumber = 0;
568 hdr.Reserved1 = 0;
569 hdr.Reserved2 = 0;
570 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
571 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
572
573 cfg.cfghdr.ehdr = &hdr;
574 cfg.physAddr = -1;
575 cfg.pageAddr = 0;
576 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
577 cfg.dir = 0; /* read */
578 cfg.timeout = 10;
579
580 error = mpt_config(ioc, &cfg);
581 if (error)
582 goto out;
583 if (!hdr.ExtPageLength) {
584 error = -ENXIO;
585 goto out;
586 }
587
588 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
589 &dma_handle);
590 if (!buffer) {
591 error = -ENOMEM;
592 goto out;
593 }
594
595 cfg.physAddr = dma_handle;
596 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
597
598 error = mpt_config(ioc, &cfg);
599 if (error)
600 goto out_free_consistent;
601
602 port_info->num_phys = buffer->NumPhys;
603 port_info->phy_info = kcalloc(port_info->num_phys,
604 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
605 if (!port_info->phy_info) {
606 error = -ENOMEM;
607 goto out_free_consistent;
608 }
609
610 for (i = 0; i < port_info->num_phys; i++) {
611 mptsas_print_phy_data(&buffer->PhyData[i]);
612 port_info->phy_info[i].phy_id = i;
613 port_info->phy_info[i].port_id =
614 buffer->PhyData[i].Port;
615 port_info->phy_info[i].negotiated_link_rate =
616 buffer->PhyData[i].NegotiatedLinkRate;
617 }
618
619 out_free_consistent:
620 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
621 buffer, dma_handle);
622 out:
623 return error;
624}
625
626static int
627mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
628 u32 form, u32 form_specific)
629{
630 ConfigExtendedPageHeader_t hdr;
631 CONFIGPARMS cfg;
632 SasPhyPage0_t *buffer;
633 dma_addr_t dma_handle;
634 int error;
635
636 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
637 hdr.ExtPageLength = 0;
638 hdr.PageNumber = 0;
639 hdr.Reserved1 = 0;
640 hdr.Reserved2 = 0;
641 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
642 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
643
644 cfg.cfghdr.ehdr = &hdr;
645 cfg.dir = 0; /* read */
646 cfg.timeout = 10;
647
648 /* Get Phy Pg 0 for each Phy. */
649 cfg.physAddr = -1;
650 cfg.pageAddr = form + form_specific;
651 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
652
653 error = mpt_config(ioc, &cfg);
654 if (error)
655 goto out;
656
657 if (!hdr.ExtPageLength) {
658 error = -ENXIO;
659 goto out;
660 }
661
662 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
663 &dma_handle);
664 if (!buffer) {
665 error = -ENOMEM;
666 goto out;
667 }
668
669 cfg.physAddr = dma_handle;
670 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
671
672 error = mpt_config(ioc, &cfg);
673 if (error)
674 goto out_free_consistent;
675
676 mptsas_print_phy_pg0(buffer);
677
678 phy_info->hw_link_rate = buffer->HwLinkRate;
679 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
680 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
681 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
682
683 out_free_consistent:
684 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
685 buffer, dma_handle);
686 out:
687 return error;
688}
689
690static int
691mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
692 u32 form, u32 form_specific)
693{
694 ConfigExtendedPageHeader_t hdr;
695 CONFIGPARMS cfg;
696 SasDevicePage0_t *buffer;
697 dma_addr_t dma_handle;
698 __le64 sas_address;
699 int error;
700
701 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
702 hdr.ExtPageLength = 0;
703 hdr.PageNumber = 0;
704 hdr.Reserved1 = 0;
705 hdr.Reserved2 = 0;
706 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
707 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
708
709 cfg.cfghdr.ehdr = &hdr;
710 cfg.pageAddr = form + form_specific;
711 cfg.physAddr = -1;
712 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
713 cfg.dir = 0; /* read */
714 cfg.timeout = 10;
715
716 error = mpt_config(ioc, &cfg);
717 if (error)
718 goto out;
719 if (!hdr.ExtPageLength) {
720 error = -ENXIO;
721 goto out;
722 }
723
724 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
725 &dma_handle);
726 if (!buffer) {
727 error = -ENOMEM;
728 goto out;
729 }
730
731 cfg.physAddr = dma_handle;
732 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
733
734 error = mpt_config(ioc, &cfg);
735 if (error)
736 goto out_free_consistent;
737
738 mptsas_print_device_pg0(buffer);
739
740 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -0700741 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200742 device_info->phy_id = buffer->PhyNum;
743 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100744 device_info->id = buffer->TargetID;
745 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200746 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
747 device_info->sas_address = le64_to_cpu(sas_address);
748 device_info->device_info =
749 le32_to_cpu(buffer->DeviceInfo);
750
751 out_free_consistent:
752 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
753 buffer, dma_handle);
754 out:
755 return error;
756}
757
758static int
759mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
760 u32 form, u32 form_specific)
761{
762 ConfigExtendedPageHeader_t hdr;
763 CONFIGPARMS cfg;
764 SasExpanderPage0_t *buffer;
765 dma_addr_t dma_handle;
766 int error;
767
768 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
769 hdr.ExtPageLength = 0;
770 hdr.PageNumber = 0;
771 hdr.Reserved1 = 0;
772 hdr.Reserved2 = 0;
773 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
774 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
775
776 cfg.cfghdr.ehdr = &hdr;
777 cfg.physAddr = -1;
778 cfg.pageAddr = form + form_specific;
779 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
780 cfg.dir = 0; /* read */
781 cfg.timeout = 10;
782
783 error = mpt_config(ioc, &cfg);
784 if (error)
785 goto out;
786
787 if (!hdr.ExtPageLength) {
788 error = -ENXIO;
789 goto out;
790 }
791
792 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
793 &dma_handle);
794 if (!buffer) {
795 error = -ENOMEM;
796 goto out;
797 }
798
799 cfg.physAddr = dma_handle;
800 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
801
802 error = mpt_config(ioc, &cfg);
803 if (error)
804 goto out_free_consistent;
805
806 /* save config data */
807 port_info->num_phys = buffer->NumPhys;
808 port_info->handle = le16_to_cpu(buffer->DevHandle);
809 port_info->phy_info = kcalloc(port_info->num_phys,
810 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
811 if (!port_info->phy_info) {
812 error = -ENOMEM;
813 goto out_free_consistent;
814 }
815
816 out_free_consistent:
817 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
818 buffer, dma_handle);
819 out:
820 return error;
821}
822
823static int
824mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
825 u32 form, u32 form_specific)
826{
827 ConfigExtendedPageHeader_t hdr;
828 CONFIGPARMS cfg;
829 SasExpanderPage1_t *buffer;
830 dma_addr_t dma_handle;
831 int error;
832
833 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
834 hdr.ExtPageLength = 0;
835 hdr.PageNumber = 1;
836 hdr.Reserved1 = 0;
837 hdr.Reserved2 = 0;
838 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
839 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
840
841 cfg.cfghdr.ehdr = &hdr;
842 cfg.physAddr = -1;
843 cfg.pageAddr = form + form_specific;
844 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
845 cfg.dir = 0; /* read */
846 cfg.timeout = 10;
847
848 error = mpt_config(ioc, &cfg);
849 if (error)
850 goto out;
851
852 if (!hdr.ExtPageLength) {
853 error = -ENXIO;
854 goto out;
855 }
856
857 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
858 &dma_handle);
859 if (!buffer) {
860 error = -ENOMEM;
861 goto out;
862 }
863
864 cfg.physAddr = dma_handle;
865 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
866
867 error = mpt_config(ioc, &cfg);
868 if (error)
869 goto out_free_consistent;
870
871
872 mptsas_print_expander_pg1(buffer);
873
874 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +0200875 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200876 phy_info->port_id = buffer->PhysicalPort;
877 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
878 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
879 phy_info->hw_link_rate = buffer->HwLinkRate;
880 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
881 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
882
883
884 out_free_consistent:
885 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
886 buffer, dma_handle);
887 out:
888 return error;
889}
890
Moore, Ericc73787ee2006-01-26 16:20:06 -0700891/*
892 * Returns true if there is a scsi end device
893 */
894static inline int
895mptsas_is_end_device(struct mptsas_devinfo * attached)
896{
897 if ((attached->handle) &&
898 (attached->device_info &
899 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
900 ((attached->device_info &
901 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
902 (attached->device_info &
903 MPI_SAS_DEVICE_INFO_STP_TARGET) |
904 (attached->device_info &
905 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
906 return 1;
907 else
908 return 0;
909}
910
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200911static void
912mptsas_parse_device_info(struct sas_identify *identify,
913 struct mptsas_devinfo *device_info)
914{
915 u16 protocols;
916
917 identify->sas_address = device_info->sas_address;
918 identify->phy_identifier = device_info->phy_id;
919
920 /*
921 * Fill in Phy Initiator Port Protocol.
922 * Bits 6:3, more than one bit can be set, fall through cases.
923 */
924 protocols = device_info->device_info & 0x78;
925 identify->initiator_port_protocols = 0;
926 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
927 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
928 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
929 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
930 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
931 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
932 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
933 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
934
935 /*
936 * Fill in Phy Target Port Protocol.
937 * Bits 10:7, more than one bit can be set, fall through cases.
938 */
939 protocols = device_info->device_info & 0x780;
940 identify->target_port_protocols = 0;
941 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
942 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
943 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
944 identify->target_port_protocols |= SAS_PROTOCOL_STP;
945 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
946 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
947 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
948 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
949
950 /*
951 * Fill in Attached device type.
952 */
953 switch (device_info->device_info &
954 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
955 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
956 identify->device_type = SAS_PHY_UNUSED;
957 break;
958 case MPI_SAS_DEVICE_INFO_END_DEVICE:
959 identify->device_type = SAS_END_DEVICE;
960 break;
961 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
962 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
963 break;
964 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
965 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
966 break;
967 }
968}
969
970static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +0200971 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200972{
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100973 struct sas_phy *phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200974 int error;
975
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100976 phy = sas_phy_alloc(dev, index);
977 if (!phy)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200978 return -ENOMEM;
979
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100980 phy->port_identifier = phy_info->port_id;
981 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200982
983 /*
984 * Set Negotiated link rate.
985 */
986 switch (phy_info->negotiated_link_rate) {
987 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100988 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200989 break;
990 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100991 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200992 break;
993 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100994 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200995 break;
996 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100997 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200998 break;
999 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1000 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1001 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001002 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001003 break;
1004 }
1005
1006 /*
1007 * Set Max hardware link rate.
1008 */
1009 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1010 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001011 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001012 break;
1013 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001014 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001015 break;
1016 default:
1017 break;
1018 }
1019
1020 /*
1021 * Set Max programmed link rate.
1022 */
1023 switch (phy_info->programmed_link_rate &
1024 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1025 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001026 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001027 break;
1028 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001029 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001030 break;
1031 default:
1032 break;
1033 }
1034
1035 /*
1036 * Set Min hardware link rate.
1037 */
1038 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1039 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001040 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001041 break;
1042 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001043 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001044 break;
1045 default:
1046 break;
1047 }
1048
1049 /*
1050 * Set Min programmed link rate.
1051 */
1052 switch (phy_info->programmed_link_rate &
1053 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1054 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001055 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001056 break;
1057 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001058 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001059 break;
1060 default:
1061 break;
1062 }
1063
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001064 if (local)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001065 phy->local_attached = 1;
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001066
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001067 error = sas_phy_add(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001068 if (error) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001069 sas_phy_free(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001070 return error;
1071 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001072 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001073
1074 if (phy_info->attached.handle) {
1075 struct sas_rphy *rphy;
1076
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001077 rphy = sas_rphy_alloc(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001078 if (!rphy)
1079 return 0; /* non-fatal: an rphy can be added later */
1080
1081 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1082 error = sas_rphy_add(rphy);
1083 if (error) {
1084 sas_rphy_free(rphy);
1085 return error;
1086 }
1087
1088 phy_info->rphy = rphy;
1089 }
1090
1091 return 0;
1092}
1093
1094static int
1095mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
1096{
1097 struct mptsas_portinfo *port_info;
1098 u32 handle = 0xFFFF;
1099 int error = -ENOMEM, i;
1100
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001101 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001102 if (!port_info)
1103 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001104
1105 error = mptsas_sas_io_unit_pg0(ioc, port_info);
1106 if (error)
1107 goto out_free_port_info;
1108
Moore, Eric816aa902006-01-13 16:25:20 -07001109 ioc->num_ports = port_info->num_phys;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001110 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001111 list_add_tail(&port_info->list, &ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001112 mutex_unlock(&ioc->sas_topology_mutex);
1113
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001114 for (i = 0; i < port_info->num_phys; i++) {
1115 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1116 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1117 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1118
1119 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1120 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1121 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02001122 port_info->phy_info[i].identify.phy_id =
1123 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001124 handle = port_info->phy_info[i].identify.handle;
1125
1126 if (port_info->phy_info[i].attached.handle) {
1127 mptsas_sas_device_pg0(ioc,
1128 &port_info->phy_info[i].attached,
1129 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1130 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1131 port_info->phy_info[i].attached.handle);
1132 }
1133
1134 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001135 &port_info->phy_info[i], *index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001136 (*index)++;
1137 }
1138
1139 return 0;
1140
1141 out_free_port_info:
1142 kfree(port_info);
1143 out:
1144 return error;
1145}
1146
1147static int
1148mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1149{
1150 struct mptsas_portinfo *port_info, *p;
1151 int error = -ENOMEM, i, j;
1152
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001153 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001154 if (!port_info)
1155 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001156
1157 error = mptsas_sas_expander_pg0(ioc, port_info,
1158 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1159 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1160 if (error)
1161 goto out_free_port_info;
1162
1163 *handle = port_info->handle;
1164
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001165 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001166 list_add_tail(&port_info->list, &ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001167 mutex_unlock(&ioc->sas_topology_mutex);
1168
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001169 for (i = 0; i < port_info->num_phys; i++) {
1170 struct device *parent;
1171
1172 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1173 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1174 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1175
1176 if (port_info->phy_info[i].identify.handle) {
1177 mptsas_sas_device_pg0(ioc,
1178 &port_info->phy_info[i].identify,
1179 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1180 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1181 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001182 port_info->phy_info[i].identify.phy_id =
1183 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001184 }
1185
1186 if (port_info->phy_info[i].attached.handle) {
1187 mptsas_sas_device_pg0(ioc,
1188 &port_info->phy_info[i].attached,
1189 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1190 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1191 port_info->phy_info[i].attached.handle);
1192 }
1193
1194 /*
1195 * If we find a parent port handle this expander is
1196 * attached to another expander, else it hangs of the
1197 * HBA phys.
1198 */
1199 parent = &ioc->sh->shost_gendev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001200 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001201 list_for_each_entry(p, &ioc->sas_topology, list) {
1202 for (j = 0; j < p->num_phys; j++) {
1203 if (port_info->phy_info[i].identify.handle ==
1204 p->phy_info[j].attached.handle)
1205 parent = &p->phy_info[j].rphy->dev;
1206 }
1207 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001208 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001209
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001210 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
1211 *index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001212 (*index)++;
1213 }
1214
1215 return 0;
1216
1217 out_free_port_info:
1218 kfree(port_info);
1219 out:
1220 return error;
1221}
1222
1223static void
1224mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1225{
1226 u32 handle = 0xFFFF;
1227 int index = 0;
1228
1229 mptsas_probe_hba_phys(ioc, &index);
1230 while (!mptsas_probe_expander_phys(ioc, &handle, &index))
1231 ;
1232}
1233
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001234static struct mptsas_phyinfo *
1235mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
1236{
1237 struct mptsas_portinfo *port_info;
1238 struct mptsas_devinfo device_info;
1239 struct mptsas_phyinfo *phy_info = NULL;
1240 int i, error;
1241
1242 /*
1243 * Retrieve the parent sas_address
1244 */
1245 error = mptsas_sas_device_pg0(ioc, &device_info,
1246 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1247 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1248 parent_handle);
1249 if (error) {
1250 printk("mptsas: failed to retrieve device page\n");
1251 return NULL;
1252 }
1253
1254 /*
1255 * The phy_info structures are never deallocated during lifetime of
1256 * a host, so the code below is safe without additional refcounting.
1257 */
1258 mutex_lock(&ioc->sas_topology_mutex);
1259 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1260 for (i = 0; i < port_info->num_phys; i++) {
1261 if (port_info->phy_info[i].identify.sas_address ==
1262 device_info.sas_address &&
1263 port_info->phy_info[i].phy_id == phy_id) {
1264 phy_info = &port_info->phy_info[i];
1265 break;
1266 }
1267 }
1268 }
1269 mutex_unlock(&ioc->sas_topology_mutex);
1270
1271 return phy_info;
1272}
1273
1274static struct mptsas_phyinfo *
Moore, Ericc73787ee2006-01-26 16:20:06 -07001275mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001276{
1277 struct mptsas_portinfo *port_info;
1278 struct mptsas_phyinfo *phy_info = NULL;
1279 int i;
1280
1281 /*
1282 * The phy_info structures are never deallocated during lifetime of
1283 * a host, so the code below is safe without additional refcounting.
1284 */
1285 mutex_lock(&ioc->sas_topology_mutex);
1286 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Moore, Ericc73787ee2006-01-26 16:20:06 -07001287 for (i = 0; i < port_info->num_phys; i++)
1288 if (mptsas_is_end_device(&port_info->phy_info[i].attached))
1289 if (port_info->phy_info[i].attached.id == id) {
1290 phy_info = &port_info->phy_info[i];
1291 break;
1292 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001293 }
1294 mutex_unlock(&ioc->sas_topology_mutex);
1295
1296 return phy_info;
1297}
1298
1299static void
1300mptsas_hotplug_work(void *arg)
1301{
1302 struct mptsas_hotplug_event *ev = arg;
1303 MPT_ADAPTER *ioc = ev->ioc;
1304 struct mptsas_phyinfo *phy_info;
1305 struct sas_rphy *rphy;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001306 struct scsi_device *sdev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001307 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001308 struct mptsas_devinfo sas_device;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001309
1310 switch (ev->event_type) {
1311 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001312
Moore, Ericc73787ee2006-01-26 16:20:06 -07001313 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001314 if (!phy_info) {
1315 printk("mptsas: remove event for non-existant PHY.\n");
1316 break;
1317 }
1318
Moore, Ericc73787ee2006-01-26 16:20:06 -07001319 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1320 ds = "ssp";
1321 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1322 ds = "stp";
1323 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1324 ds = "sata";
1325
1326 printk(MYIOC_s_INFO_FMT
1327 "removing %s device, channel %d, id %d, phy %d\n",
1328 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
1329
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001330 if (phy_info->rphy) {
1331 sas_rphy_delete(phy_info->rphy);
1332 phy_info->rphy = NULL;
1333 }
1334 break;
1335 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07001336
1337 /*
1338 * When there is no sas address,
1339 * RAID volumes are being deleted,
1340 * and hidden phy disk are being added.
1341 * We don't know the SAS data yet,
1342 * so lookup sas device page to get
1343 * pertaining info
1344 */
1345 if (!ev->sas_address) {
1346 if (mptsas_sas_device_pg0(ioc,
1347 &sas_device, ev->id,
1348 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
1349 MPI_SAS_DEVICE_PGAD_FORM_SHIFT)))
1350 break;
1351 ev->handle = sas_device.handle;
1352 ev->parent_handle = sas_device.handle_parent;
1353 ev->channel = sas_device.channel;
1354 ev->phy_id = sas_device.phy_id;
1355 ev->sas_address = sas_device.sas_address;
1356 ev->device_info = sas_device.device_info;
1357 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001358
1359 phy_info = mptsas_find_phyinfo_by_parent(ioc,
1360 ev->parent_handle, ev->phy_id);
1361 if (!phy_info) {
1362 printk("mptsas: add event for non-existant PHY.\n");
1363 break;
1364 }
1365
1366 if (phy_info->rphy) {
1367 printk("mptsas: trying to add existing device.\n");
1368 break;
1369 }
1370
1371 /* fill attached info */
1372 phy_info->attached.handle = ev->handle;
1373 phy_info->attached.phy_id = ev->phy_id;
1374 phy_info->attached.port_id = phy_info->identify.port_id;
1375 phy_info->attached.id = ev->id;
1376 phy_info->attached.channel = ev->channel;
1377 phy_info->attached.sas_address = ev->sas_address;
1378 phy_info->attached.device_info = ev->device_info;
1379
Moore, Ericc73787ee2006-01-26 16:20:06 -07001380 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1381 ds = "ssp";
1382 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1383 ds = "stp";
1384 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1385 ds = "sata";
1386
1387 printk(MYIOC_s_INFO_FMT
1388 "attaching %s device, channel %d, id %d, phy %d\n",
1389 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1390
1391
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001392 rphy = sas_rphy_alloc(phy_info->phy);
1393 if (!rphy)
1394 break; /* non-fatal: an rphy can be added later */
1395
Moore, Ericc73787ee2006-01-26 16:20:06 -07001396 rphy->scsi_target_id = phy_info->attached.id;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001397 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1398 if (sas_rphy_add(rphy)) {
1399 sas_rphy_free(rphy);
1400 break;
1401 }
1402
1403 phy_info->rphy = rphy;
1404 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001405 case MPTSAS_ADD_RAID:
1406 sdev = scsi_device_lookup(
1407 ioc->sh,
1408 ioc->num_ports,
1409 ev->id,
1410 0);
1411 if (sdev) {
1412 scsi_device_put(sdev);
1413 break;
1414 }
1415 printk(MYIOC_s_INFO_FMT
1416 "attaching device, channel %d, id %d\n",
1417 ioc->name, ioc->num_ports, ev->id);
1418 scsi_add_device(ioc->sh,
1419 ioc->num_ports,
1420 ev->id,
1421 0);
1422 mpt_findImVolumes(ioc);
1423 break;
1424 case MPTSAS_DEL_RAID:
1425 sdev = scsi_device_lookup(
1426 ioc->sh,
1427 ioc->num_ports,
1428 ev->id,
1429 0);
1430 if (!sdev)
1431 break;
1432 printk(MYIOC_s_INFO_FMT
1433 "removing device, channel %d, id %d\n",
1434 ioc->name, ioc->num_ports, ev->id);
1435 scsi_remove_device(sdev);
1436 scsi_device_put(sdev);
1437 mpt_findImVolumes(ioc);
1438 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001439 }
1440
1441 kfree(ev);
1442}
1443
1444static void
1445mptscsih_send_sas_event(MPT_ADAPTER *ioc,
1446 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
1447{
1448 struct mptsas_hotplug_event *ev;
1449 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
1450 __le64 sas_address;
1451
1452 if ((device_info &
1453 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
1454 MPI_SAS_DEVICE_INFO_STP_TARGET |
1455 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
1456 return;
1457
1458 if ((sas_event_data->ReasonCode &
1459 (MPI_EVENT_SAS_DEV_STAT_RC_ADDED |
1460 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0)
1461 return;
1462
1463 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1464 if (!ev) {
1465 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1466 return;
1467 }
1468
1469
1470 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1471 ev->ioc = ioc;
1472 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
1473 ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
1474 ev->channel = sas_event_data->Bus;
1475 ev->id = sas_event_data->TargetID;
1476 ev->phy_id = sas_event_data->PhyNum;
1477 memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64));
1478 ev->sas_address = le64_to_cpu(sas_address);
1479 ev->device_info = device_info;
1480
1481 if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
1482 ev->event_type = MPTSAS_ADD_DEVICE;
1483 else
1484 ev->event_type = MPTSAS_DEL_DEVICE;
1485
1486 schedule_work(&ev->work);
1487}
1488
Moore, Ericc73787ee2006-01-26 16:20:06 -07001489static void
1490mptscsih_send_raid_event(MPT_ADAPTER *ioc,
1491 EVENT_DATA_RAID *raid_event_data)
1492{
1493 struct mptsas_hotplug_event *ev;
1494 RAID_VOL0_STATUS * volumeStatus;
1495
1496 if (ioc->bus_type != SAS)
1497 return;
1498
1499 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1500 if (!ev) {
1501 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1502 return;
1503 }
1504
1505 memset(ev,0,sizeof(struct mptsas_hotplug_event));
1506 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1507 ev->ioc = ioc;
1508 ev->id = raid_event_data->VolumeID;
1509
1510 switch (raid_event_data->ReasonCode) {
1511 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
1512 ev->event_type = MPTSAS_ADD_DEVICE;
1513 break;
1514 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
1515 ev->event_type = MPTSAS_DEL_DEVICE;
1516 break;
1517 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
1518 ev->event_type = MPTSAS_DEL_RAID;
1519 break;
1520 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
1521 ev->event_type = MPTSAS_ADD_RAID;
1522 break;
1523 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
1524 volumeStatus = (RAID_VOL0_STATUS *) &
1525 raid_event_data->SettingsStatus;
1526 ev->event_type = (volumeStatus->State ==
1527 MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
1528 MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
1529 break;
1530 default:
1531 break;
1532 }
1533 schedule_work(&ev->work);
1534}
1535
Moore, Eric79de2782006-01-25 18:05:15 -07001536/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
1537/* work queue thread to clear the persitency table */
1538static void
1539mptscsih_sas_persist_clear_table(void * arg)
1540{
1541 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
1542
1543 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
1544}
1545
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001546static int
1547mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
1548{
Moore, Ericc73787ee2006-01-26 16:20:06 -07001549 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001550 u8 event = le32_to_cpu(reply->Event) & 0xFF;
1551
1552 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07001553 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001554
1555 switch (event) {
1556 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1557 mptscsih_send_sas_event(ioc,
1558 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001559 break;
1560 case MPI_EVENT_INTEGRATED_RAID:
1561 mptscsih_send_raid_event(ioc,
1562 (EVENT_DATA_RAID *)reply->Data);
1563 break;
Moore, Eric79de2782006-01-25 18:05:15 -07001564 case MPI_EVENT_PERSISTENT_TABLE_FULL:
1565 INIT_WORK(&ioc->mptscsih_persistTask,
1566 mptscsih_sas_persist_clear_table,
1567 (void *)ioc);
1568 schedule_work(&ioc->mptscsih_persistTask);
1569 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001570 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07001571 rc = mptscsih_event_process(ioc, reply);
1572 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001573 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07001574 out:
1575
1576 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001577}
1578
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001579static int
1580mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1581{
1582 struct Scsi_Host *sh;
1583 MPT_SCSI_HOST *hd;
1584 MPT_ADAPTER *ioc;
1585 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001586 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001587 int numSGE = 0;
1588 int scale;
1589 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001590 int error=0;
1591 int r;
1592
1593 r = mpt_attach(pdev,id);
1594 if (r)
1595 return r;
1596
1597 ioc = pci_get_drvdata(pdev);
1598 ioc->DoneCtx = mptsasDoneCtx;
1599 ioc->TaskCtx = mptsasTaskCtx;
1600 ioc->InternalCtx = mptsasInternalCtx;
1601
1602 /* Added sanity check on readiness of the MPT adapter.
1603 */
1604 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1605 printk(MYIOC_s_WARN_FMT
1606 "Skipping because it's not operational!\n",
1607 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001608 error = -ENODEV;
1609 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001610 }
1611
1612 if (!ioc->active) {
1613 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1614 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001615 error = -ENODEV;
1616 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001617 }
1618
1619 /* Sanity check - ensure at least 1 port is INITIATOR capable
1620 */
1621 ioc_cap = 0;
1622 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
1623 if (ioc->pfacts[ii].ProtocolFlags &
1624 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1625 ioc_cap++;
1626 }
1627
1628 if (!ioc_cap) {
1629 printk(MYIOC_s_WARN_FMT
1630 "Skipping ioc=%p because SCSI Initiator mode "
1631 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06001632 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001633 }
1634
1635 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
1636 if (!sh) {
1637 printk(MYIOC_s_WARN_FMT
1638 "Unable to register controller with SCSI subsystem\n",
1639 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001640 error = -1;
1641 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001642 }
1643
1644 spin_lock_irqsave(&ioc->FreeQlock, flags);
1645
1646 /* Attach the SCSI Host to the IOC structure
1647 */
1648 ioc->sh = sh;
1649
1650 sh->io_port = 0;
1651 sh->n_io_port = 0;
1652 sh->irq = 0;
1653
1654 /* set 16 byte cdb's */
1655 sh->max_cmd_len = 16;
1656
1657 sh->max_id = ioc->pfacts->MaxDevices + 1;
1658
1659 sh->transportt = mptsas_transport_template;
1660
1661 sh->max_lun = MPT_LAST_LUN + 1;
1662 sh->max_channel = 0;
1663 sh->this_id = ioc->pfacts[0].PortSCSIID;
1664
1665 /* Required entry.
1666 */
1667 sh->unique_id = ioc->id;
1668
1669 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001670 mutex_init(&ioc->sas_topology_mutex);
1671
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01001672 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001673 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001674
1675 /* Verify that we won't exceed the maximum
1676 * number of chain buffers
1677 * We can optimize: ZZ = req_sz/sizeof(SGE)
1678 * For 32bit SGE's:
1679 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1680 * + (req_sz - 64)/sizeof(SGE)
1681 * A slightly different algorithm is required for
1682 * 64bit SGEs.
1683 */
1684 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1685 if (sizeof(dma_addr_t) == sizeof(u64)) {
1686 numSGE = (scale - 1) *
1687 (ioc->facts.MaxChainDepth-1) + scale +
1688 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1689 sizeof(u32));
1690 } else {
1691 numSGE = 1 + (scale - 1) *
1692 (ioc->facts.MaxChainDepth-1) + scale +
1693 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1694 sizeof(u32));
1695 }
1696
1697 if (numSGE < sh->sg_tablesize) {
1698 /* Reset this value */
1699 dprintk((MYIOC_s_INFO_FMT
1700 "Resetting sg_tablesize to %d from %d\n",
1701 ioc->name, numSGE, sh->sg_tablesize));
1702 sh->sg_tablesize = numSGE;
1703 }
1704
1705 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1706
1707 hd = (MPT_SCSI_HOST *) sh->hostdata;
1708 hd->ioc = ioc;
1709
1710 /* SCSI needs scsi_cmnd lookup table!
1711 * (with size equal to req_depth*PtrSz!)
1712 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001713 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1714 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001715 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001716 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001717 }
1718
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001719 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1720 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001721
1722 /* Allocate memory for the device structures.
1723 * A non-Null pointer at an offset
1724 * indicates a device exists.
1725 * max_id = 1 + maximum id (hosts.h)
1726 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001727 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
1728 if (!hd->Targets) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001729 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001730 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001731 }
1732
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001733 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001734
1735 /* Clear the TM flags
1736 */
1737 hd->tmPending = 0;
1738 hd->tmState = TM_STATE_NONE;
1739 hd->resetPending = 0;
1740 hd->abortSCpnt = NULL;
1741
1742 /* Clear the pointer used to store
1743 * single-threaded commands, i.e., those
1744 * issued during a bus scan, dv and
1745 * configuration pages.
1746 */
1747 hd->cmdPtr = NULL;
1748
1749 /* Initialize this SCSI Hosts' timers
1750 * To use, set the timer expires field
1751 * and add_timer
1752 */
1753 init_timer(&hd->timer);
1754 hd->timer.data = (unsigned long) hd;
1755 hd->timer.function = mptscsih_timer_expired;
1756
1757 hd->mpt_pq_filter = mpt_pq_filter;
1758 ioc->sas_data.ptClear = mpt_pt_clear;
1759
1760 if (ioc->sas_data.ptClear==1) {
1761 mptbase_sas_persist_operation(
1762 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
1763 }
1764
1765 ddvprintk((MYIOC_s_INFO_FMT
1766 "mpt_pq_filter %x mpt_pq_filter %x\n",
1767 ioc->name,
1768 mpt_pq_filter,
1769 mpt_pq_filter));
1770
1771 init_waitqueue_head(&hd->scandv_waitq);
1772 hd->scandv_wait_done = 0;
1773 hd->last_queue_full = 0;
1774
1775 error = scsi_add_host(sh, &ioc->pcidev->dev);
1776 if (error) {
1777 dprintk((KERN_ERR MYNAM
1778 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001779 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001780 }
1781
1782 mptsas_scan_sas_topology(ioc);
1783
Moore, Eric816aa902006-01-13 16:25:20 -07001784 /*
1785 Reporting RAID volumes.
1786 */
1787 if (!ioc->raid_data.pIocPg2)
1788 return 0;
1789 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1790 return 0;
1791 for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
1792 scsi_add_device(sh,
1793 ioc->num_ports,
1794 ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
1795 0);
1796 }
1797
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001798 return 0;
1799
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001800out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001801
1802 mptscsih_remove(pdev);
1803 return error;
1804}
1805
1806static void __devexit mptsas_remove(struct pci_dev *pdev)
1807{
1808 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1809 struct mptsas_portinfo *p, *n;
1810
1811 sas_remove_host(ioc->sh);
1812
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001813 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001814 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
1815 list_del(&p->list);
1816 kfree(p);
1817 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001818 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001819
1820 mptscsih_remove(pdev);
1821}
1822
1823static struct pci_device_id mptsas_pci_table[] = {
1824 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
1825 PCI_ANY_ID, PCI_ANY_ID },
1826 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
1827 PCI_ANY_ID, PCI_ANY_ID },
1828 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
1829 PCI_ANY_ID, PCI_ANY_ID },
1830 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
1831 PCI_ANY_ID, PCI_ANY_ID },
1832 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
1833 PCI_ANY_ID, PCI_ANY_ID },
1834 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
1835 PCI_ANY_ID, PCI_ANY_ID },
1836 {0} /* Terminating entry */
1837};
1838MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
1839
1840
1841static struct pci_driver mptsas_driver = {
1842 .name = "mptsas",
1843 .id_table = mptsas_pci_table,
1844 .probe = mptsas_probe,
1845 .remove = __devexit_p(mptsas_remove),
1846 .shutdown = mptscsih_shutdown,
1847#ifdef CONFIG_PM
1848 .suspend = mptscsih_suspend,
1849 .resume = mptscsih_resume,
1850#endif
1851};
1852
1853static int __init
1854mptsas_init(void)
1855{
1856 show_mptmod_ver(my_NAME, my_VERSION);
1857
1858 mptsas_transport_template =
1859 sas_attach_transport(&mptsas_transport_functions);
1860 if (!mptsas_transport_template)
1861 return -ENODEV;
1862
1863 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
1864 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
1865 mptsasInternalCtx =
1866 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001867 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001868
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001869 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001870 devtprintk((KERN_INFO MYNAM
1871 ": Registered for IOC event notifications\n"));
1872 }
1873
1874 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
1875 dprintk((KERN_INFO MYNAM
1876 ": Registered for IOC reset notifications\n"));
1877 }
1878
1879 return pci_register_driver(&mptsas_driver);
1880}
1881
1882static void __exit
1883mptsas_exit(void)
1884{
1885 pci_unregister_driver(&mptsas_driver);
1886 sas_release_transport(mptsas_transport_template);
1887
1888 mpt_reset_deregister(mptsasDoneCtx);
1889 mpt_event_deregister(mptsasDoneCtx);
1890
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001891 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001892 mpt_deregister(mptsasInternalCtx);
1893 mpt_deregister(mptsasTaskCtx);
1894 mpt_deregister(mptsasDoneCtx);
1895}
1896
1897module_init(mptsas_init);
1898module_exit(mptsas_exit);