blob: 4e6fcf06a6f2d541300e38bdeeea6b766424cdff [file] [log] [blame]
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001/*
2 * linux/drivers/message/fusion/mptsas.c
Prakash, Sathyaf36789e2007-08-14 16:22:54 +05303 * For use with LSI PCI chip/adapter(s)
4 * running LSI Fusion MPT (Message Passing Technology) firmware.
Christoph Hellwig0c33b272005-09-09 16:27:19 +02005 *
Prakash, Sathyacddc0ab2008-05-21 00:56:41 +05306 * Copyright (c) 1999-2008 LSI Corporation
Eric Moore16d20102007-06-13 16:31:07 -06007 * (mailto:DL-MPTFusionLinux@lsi.com)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02008 */
9/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10/*
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; version 2 of the License.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 NO WARRANTY
21 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
22 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
23 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
24 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
25 solely responsible for determining the appropriateness of using and
26 distributing the Program and assumes all risks associated with its
27 exercise of rights under this Agreement, including but not limited to
28 the risks and costs of program errors, damage to or loss of data,
29 programs or equipment, and unavailability or interruption of operations.
30
31 DISCLAIMER OF LIABILITY
32 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
33 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
35 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
38 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
39
40 You should have received a copy of the GNU General Public License
41 along with this program; if not, write to the Free Software
42 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43*/
44/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
45
46#include <linux/module.h>
47#include <linux/kernel.h>
48#include <linux/init.h>
49#include <linux/errno.h>
Tim Schmielaucd354f12007-02-14 00:33:14 -080050#include <linux/jiffies.h>
Christoph Hellwig0c33b272005-09-09 16:27:19 +020051#include <linux/workqueue.h>
Eric Moore547f9a22006-06-27 14:42:12 -060052#include <linux/delay.h> /* for mdelay */
Christoph Hellwig0c33b272005-09-09 16:27:19 +020053
Eric Moore547f9a22006-06-27 14:42:12 -060054#include <scsi/scsi.h>
Christoph Hellwig0c33b272005-09-09 16:27:19 +020055#include <scsi/scsi_cmnd.h>
56#include <scsi/scsi_device.h>
57#include <scsi/scsi_host.h>
58#include <scsi/scsi_transport_sas.h>
Eric Moore547f9a22006-06-27 14:42:12 -060059#include <scsi/scsi_dbg.h>
Christoph Hellwig0c33b272005-09-09 16:27:19 +020060
61#include "mptbase.h"
62#include "mptscsih.h"
Prakash, Sathya56af97a2007-08-14 16:15:38 +053063#include "mptsas.h"
Christoph Hellwig0c33b272005-09-09 16:27:19 +020064
65
66#define my_NAME "Fusion MPT SAS Host driver"
67#define my_VERSION MPT_LINUX_VERSION_COMMON
68#define MYNAM "mptsas"
69
James Bottomleye8bf3942006-07-11 17:49:34 -040070/*
71 * Reserved channel for integrated raid
72 */
73#define MPTSAS_RAID_CHANNEL 1
74
Christoph Hellwig0c33b272005-09-09 16:27:19 +020075MODULE_AUTHOR(MODULEAUTHOR);
76MODULE_DESCRIPTION(my_NAME);
77MODULE_LICENSE("GPL");
Eric Moore9f4203b2007-01-04 20:47:47 -070078MODULE_VERSION(my_VERSION);
Christoph Hellwig0c33b272005-09-09 16:27:19 +020079
Christoph Hellwig0c33b272005-09-09 16:27:19 +020080static int mpt_pt_clear;
81module_param(mpt_pt_clear, int, 0);
82MODULE_PARM_DESC(mpt_pt_clear,
Eric Mooreba856d32006-07-11 17:34:01 -060083 " Clear persistency table: enable=1 "
Christoph Hellwig0c33b272005-09-09 16:27:19 +020084 "(default=MPTSCSIH_PT_CLEAR=0)");
85
Eric Moore793955f2007-01-29 09:42:20 -070086/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
87#define MPTSAS_MAX_LUN (16895)
88static int max_lun = MPTSAS_MAX_LUN;
89module_param(max_lun, int, 0);
90MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
91
Prakash, Sathyaf606f572007-08-14 16:12:53 +053092static u8 mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
93static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
94static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
95static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +020096
Eric Mooreb506ade2007-01-29 09:45:37 -070097static void mptsas_hotplug_work(struct work_struct *work);
Christoph Hellwig0c33b272005-09-09 16:27:19 +020098
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +053099static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
100 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
Christoph Hellwigb5141122005-10-28 22:07:41 +0200101{
Eric Moore29dd3602007-09-14 18:46:51 -0600102 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
103 "---- IO UNIT PAGE 0 ------------\n", ioc->name));
104 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
105 ioc->name, le16_to_cpu(phy_data->AttachedDeviceHandle)));
106 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Controller Handle=0x%X\n",
107 ioc->name, le16_to_cpu(phy_data->ControllerDevHandle)));
108 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port=0x%X\n",
109 ioc->name, phy_data->Port));
110 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port Flags=0x%X\n",
111 ioc->name, phy_data->PortFlags));
112 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Flags=0x%X\n",
113 ioc->name, phy_data->PhyFlags));
114 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
115 ioc->name, phy_data->NegotiatedLinkRate));
116 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
117 "Controller PHY Device Info=0x%X\n", ioc->name,
118 le32_to_cpu(phy_data->ControllerPhyDeviceInfo)));
119 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DiscoveryStatus=0x%X\n\n",
120 ioc->name, le32_to_cpu(phy_data->DiscoveryStatus)));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200121}
122
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530123static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0)
Christoph Hellwigb5141122005-10-28 22:07:41 +0200124{
125 __le64 sas_address;
126
127 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
128
Eric Moore29dd3602007-09-14 18:46:51 -0600129 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
130 "---- SAS PHY PAGE 0 ------------\n", ioc->name));
131 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
132 "Attached Device Handle=0x%X\n", ioc->name,
133 le16_to_cpu(pg0->AttachedDevHandle)));
134 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
135 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
136 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
137 "Attached PHY Identifier=0x%X\n", ioc->name,
138 pg0->AttachedPhyIdentifier));
139 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Attached Device Info=0x%X\n",
140 ioc->name, le32_to_cpu(pg0->AttachedDeviceInfo)));
141 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
142 ioc->name, pg0->ProgrammedLinkRate));
143 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Change Count=0x%X\n",
144 ioc->name, pg0->ChangeCount));
145 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Info=0x%X\n\n",
146 ioc->name, le32_to_cpu(pg0->PhyInfo)));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200147}
148
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530149static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1)
Christoph Hellwigb5141122005-10-28 22:07:41 +0200150{
Eric Moore29dd3602007-09-14 18:46:51 -0600151 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
152 "---- SAS PHY PAGE 1 ------------\n", ioc->name));
153 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Invalid Dword Count=0x%x\n",
154 ioc->name, pg1->InvalidDwordCount));
155 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
156 "Running Disparity Error Count=0x%x\n", ioc->name,
157 pg1->RunningDisparityErrorCount));
158 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
159 "Loss Dword Synch Count=0x%x\n", ioc->name,
160 pg1->LossDwordSynchCount));
161 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
162 "PHY Reset Problem Count=0x%x\n\n", ioc->name,
163 pg1->PhyResetProblemCount));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200164}
165
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530166static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0)
Christoph Hellwigb5141122005-10-28 22:07:41 +0200167{
168 __le64 sas_address;
169
170 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
171
Eric Moore29dd3602007-09-14 18:46:51 -0600172 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
173 "---- SAS DEVICE PAGE 0 ---------\n", ioc->name));
174 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
175 ioc->name, le16_to_cpu(pg0->DevHandle)));
176 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Handle=0x%X\n",
177 ioc->name, le16_to_cpu(pg0->ParentDevHandle)));
178 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Enclosure Handle=0x%X\n",
179 ioc->name, le16_to_cpu(pg0->EnclosureHandle)));
180 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Slot=0x%X\n",
181 ioc->name, le16_to_cpu(pg0->Slot)));
182 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
183 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
184 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Target ID=0x%X\n",
185 ioc->name, pg0->TargetID));
186 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Bus=0x%X\n",
187 ioc->name, pg0->Bus));
188 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Phy Num=0x%X\n",
189 ioc->name, pg0->PhyNum));
190 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Access Status=0x%X\n",
191 ioc->name, le16_to_cpu(pg0->AccessStatus)));
192 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Device Info=0x%X\n",
193 ioc->name, le32_to_cpu(pg0->DeviceInfo)));
194 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Flags=0x%X\n",
195 ioc->name, le16_to_cpu(pg0->Flags)));
196 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n\n",
197 ioc->name, pg0->PhysicalPort));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200198}
199
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530200static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1)
Christoph Hellwigb5141122005-10-28 22:07:41 +0200201{
Eric Moore29dd3602007-09-14 18:46:51 -0600202 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
203 "---- SAS EXPANDER PAGE 1 ------------\n", ioc->name));
204 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n",
205 ioc->name, pg1->PhysicalPort));
206 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Identifier=0x%X\n",
207 ioc->name, pg1->PhyIdentifier));
208 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
209 ioc->name, pg1->NegotiatedLinkRate));
210 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
211 ioc->name, pg1->ProgrammedLinkRate));
212 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hardware Link Rate=0x%X\n",
213 ioc->name, pg1->HwLinkRate));
214 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Owner Device Handle=0x%X\n",
215 ioc->name, le16_to_cpu(pg1->OwnerDevHandle)));
216 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
217 "Attached Device Handle=0x%X\n\n", ioc->name,
218 le16_to_cpu(pg1->AttachedDevHandle)));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200219}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200220
Christoph Hellwige3094442006-02-16 13:25:36 +0100221static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
222{
223 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
224 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
225}
226
227static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
228{
229 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
230 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
231}
232
Michael Reed77483692008-03-20 17:32:05 -0500233static struct mptsas_portinfo *
234mptsas_get_hba_portinfo(MPT_ADAPTER *ioc)
235{
236 struct list_head *head = &ioc->sas_topology;
237 struct mptsas_portinfo *pi = NULL;
238
239 /* always the first entry on sas_topology list */
240
241 if (!list_empty(head))
242 pi = list_entry(head->next, struct mptsas_portinfo, list);
243
244 return pi;
245}
246
Moore, Erice6b2d762006-03-14 09:14:24 -0700247/*
248 * mptsas_find_portinfo_by_handle
249 *
250 * This function should be called with the sas_topology_mutex already held
251 */
252static struct mptsas_portinfo *
253mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
254{
255 struct mptsas_portinfo *port_info, *rc=NULL;
256 int i;
257
258 list_for_each_entry(port_info, &ioc->sas_topology, list)
259 for (i = 0; i < port_info->num_phys; i++)
260 if (port_info->phy_info[i].identify.handle == handle) {
261 rc = port_info;
262 goto out;
263 }
264 out:
265 return rc;
266}
267
Moore, Ericbd23e942006-04-17 12:43:04 -0600268/*
269 * Returns true if there is a scsi end device
270 */
271static inline int
272mptsas_is_end_device(struct mptsas_devinfo * attached)
273{
Eric Moore547f9a22006-06-27 14:42:12 -0600274 if ((attached->sas_address) &&
Moore, Ericbd23e942006-04-17 12:43:04 -0600275 (attached->device_info &
276 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
277 ((attached->device_info &
278 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
279 (attached->device_info &
280 MPI_SAS_DEVICE_INFO_STP_TARGET) |
281 (attached->device_info &
282 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
283 return 1;
284 else
285 return 0;
286}
287
Eric Moore547f9a22006-06-27 14:42:12 -0600288/* no mutex */
Eric Moore376ac832006-06-29 17:36:26 -0600289static void
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530290mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
Eric Moore547f9a22006-06-27 14:42:12 -0600291{
292 struct mptsas_portinfo *port_info;
293 struct mptsas_phyinfo *phy_info;
294 u8 i;
295
296 if (!port_details)
297 return;
298
299 port_info = port_details->port_info;
300 phy_info = port_info->phy_info;
301
Eric Moore29dd3602007-09-14 18:46:51 -0600302 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -0700303 "bitmask=0x%016llX\n", ioc->name, __func__, port_details,
Eric Mooref99be432007-01-04 20:46:54 -0700304 port_details->num_phys, (unsigned long long)
305 port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600306
307 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
308 if(phy_info->port_details != port_details)
309 continue;
310 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
311 phy_info->port_details = NULL;
312 }
313 kfree(port_details);
314}
315
316static inline struct sas_rphy *
317mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
318{
319 if (phy_info->port_details)
320 return phy_info->port_details->rphy;
321 else
322 return NULL;
323}
324
325static inline void
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530326mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
Eric Moore547f9a22006-06-27 14:42:12 -0600327{
328 if (phy_info->port_details) {
329 phy_info->port_details->rphy = rphy;
Eric Moore29dd3602007-09-14 18:46:51 -0600330 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
331 ioc->name, rphy));
Eric Moore547f9a22006-06-27 14:42:12 -0600332 }
333
Eric Moore547f9a22006-06-27 14:42:12 -0600334 if (rphy) {
Eric Moorec51d0be2007-09-29 10:17:21 -0600335 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
336 &rphy->dev, MYIOC_s_FMT "add:", ioc->name));
Eric Moore29dd3602007-09-14 18:46:51 -0600337 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n",
338 ioc->name, rphy, rphy->dev.release));
Eric Moore547f9a22006-06-27 14:42:12 -0600339 }
Eric Moore547f9a22006-06-27 14:42:12 -0600340}
341
342static inline struct sas_port *
343mptsas_get_port(struct mptsas_phyinfo *phy_info)
344{
345 if (phy_info->port_details)
346 return phy_info->port_details->port;
347 else
348 return NULL;
349}
350
351static inline void
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530352mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port)
Eric Moore547f9a22006-06-27 14:42:12 -0600353{
354 if (phy_info->port_details)
355 phy_info->port_details->port = port;
356
Eric Moore547f9a22006-06-27 14:42:12 -0600357 if (port) {
Eric Moorec51d0be2007-09-29 10:17:21 -0600358 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
359 &port->dev, MYIOC_s_FMT "add:", ioc->name));
Eric Moore29dd3602007-09-14 18:46:51 -0600360 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "port=%p release=%p\n",
361 ioc->name, port, port->dev.release));
Eric Moore547f9a22006-06-27 14:42:12 -0600362 }
Eric Moore547f9a22006-06-27 14:42:12 -0600363}
364
365static inline struct scsi_target *
366mptsas_get_starget(struct mptsas_phyinfo *phy_info)
367{
368 if (phy_info->port_details)
369 return phy_info->port_details->starget;
370 else
371 return NULL;
372}
373
374static inline void
375mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
376starget)
377{
378 if (phy_info->port_details)
379 phy_info->port_details->starget = starget;
380}
381
382
383/*
384 * mptsas_setup_wide_ports
385 *
386 * Updates for new and existing narrow/wide port configuration
387 * in the sas_topology
388 */
Eric Moore376ac832006-06-29 17:36:26 -0600389static void
Eric Moore547f9a22006-06-27 14:42:12 -0600390mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
391{
392 struct mptsas_portinfo_details * port_details;
393 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
394 u64 sas_address;
395 int i, j;
396
397 mutex_lock(&ioc->sas_topology_mutex);
398
399 phy_info = port_info->phy_info;
400 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
401 if (phy_info->attached.handle)
402 continue;
403 port_details = phy_info->port_details;
404 if (!port_details)
405 continue;
406 if (port_details->num_phys < 2)
407 continue;
408 /*
409 * Removing a phy from a port, letting the last
410 * phy be removed by firmware events.
411 */
Eric Moore29dd3602007-09-14 18:46:51 -0600412 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
413 "%s: [%p]: deleting phy = %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -0700414 ioc->name, __func__, port_details, i));
Eric Moore547f9a22006-06-27 14:42:12 -0600415 port_details->num_phys--;
416 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
417 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
418 sas_port_delete_phy(port_details->port, phy_info->phy);
419 phy_info->port_details = NULL;
420 }
421
422 /*
423 * Populate and refresh the tree
424 */
425 phy_info = port_info->phy_info;
426 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
427 sas_address = phy_info->attached.sas_address;
Eric Moore29dd3602007-09-14 18:46:51 -0600428 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n",
429 ioc->name, i, (unsigned long long)sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600430 if (!sas_address)
431 continue;
432 port_details = phy_info->port_details;
433 /*
434 * Forming a port
435 */
436 if (!port_details) {
437 port_details = kzalloc(sizeof(*port_details),
438 GFP_KERNEL);
439 if (!port_details)
440 goto out;
441 port_details->num_phys = 1;
442 port_details->port_info = port_info;
Eric Moore547f9a22006-06-27 14:42:12 -0600443 if (phy_info->phy_id < 64 )
444 port_details->phy_bitmask |=
445 (1 << phy_info->phy_id);
446 phy_info->sas_port_add_phy=1;
Eric Moore29dd3602007-09-14 18:46:51 -0600447 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t"
Eric Mooref99be432007-01-04 20:46:54 -0700448 "phy_id=%d sas_address=0x%018llX\n",
Eric Moore29dd3602007-09-14 18:46:51 -0600449 ioc->name, i, (unsigned long long)sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600450 phy_info->port_details = port_details;
451 }
452
453 if (i == port_info->num_phys - 1)
454 continue;
455 phy_info_cmp = &port_info->phy_info[i + 1];
456 for (j = i + 1 ; j < port_info->num_phys ; j++,
457 phy_info_cmp++) {
458 if (!phy_info_cmp->attached.sas_address)
459 continue;
460 if (sas_address != phy_info_cmp->attached.sas_address)
461 continue;
462 if (phy_info_cmp->port_details == port_details )
463 continue;
Eric Moore29dd3602007-09-14 18:46:51 -0600464 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
Eric Mooref99be432007-01-04 20:46:54 -0700465 "\t\tphy_id=%d sas_address=0x%018llX\n",
Eric Moore29dd3602007-09-14 18:46:51 -0600466 ioc->name, j, (unsigned long long)
Eric Mooref99be432007-01-04 20:46:54 -0700467 phy_info_cmp->attached.sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600468 if (phy_info_cmp->port_details) {
469 port_details->rphy =
470 mptsas_get_rphy(phy_info_cmp);
471 port_details->port =
472 mptsas_get_port(phy_info_cmp);
473 port_details->starget =
474 mptsas_get_starget(phy_info_cmp);
Eric Moore547f9a22006-06-27 14:42:12 -0600475 port_details->num_phys =
476 phy_info_cmp->port_details->num_phys;
Eric Moore547f9a22006-06-27 14:42:12 -0600477 if (!phy_info_cmp->port_details->num_phys)
478 kfree(phy_info_cmp->port_details);
479 } else
480 phy_info_cmp->sas_port_add_phy=1;
481 /*
482 * Adding a phy to a port
483 */
484 phy_info_cmp->port_details = port_details;
485 if (phy_info_cmp->phy_id < 64 )
486 port_details->phy_bitmask |=
487 (1 << phy_info_cmp->phy_id);
488 port_details->num_phys++;
489 }
490 }
491
492 out:
493
Eric Moore547f9a22006-06-27 14:42:12 -0600494 for (i = 0; i < port_info->num_phys; i++) {
495 port_details = port_info->phy_info[i].port_details;
496 if (!port_details)
497 continue;
Eric Moore29dd3602007-09-14 18:46:51 -0600498 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
Eric Mooref99be432007-01-04 20:46:54 -0700499 "%s: [%p]: phy_id=%02d num_phys=%02d "
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -0700500 "bitmask=0x%016llX\n", ioc->name, __func__,
Eric Mooref99be432007-01-04 20:46:54 -0700501 port_details, i, port_details->num_phys,
502 (unsigned long long)port_details->phy_bitmask));
Eric Moore29dd3602007-09-14 18:46:51 -0600503 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
504 ioc->name, port_details->port, port_details->rphy));
Eric Moore547f9a22006-06-27 14:42:12 -0600505 }
Eric Moore29dd3602007-09-14 18:46:51 -0600506 dsaswideprintk(ioc, printk("\n"));
Eric Moore547f9a22006-06-27 14:42:12 -0600507 mutex_unlock(&ioc->sas_topology_mutex);
508}
509
Eric Mooredf9e0622007-01-29 09:46:21 -0700510/**
511 * csmisas_find_vtarget
512 *
513 * @ioc
514 * @volume_id
515 * @volume_bus
516 *
517 **/
518static VirtTarget *
519mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
Eric Moore547f9a22006-06-27 14:42:12 -0600520{
Eric Mooredf9e0622007-01-29 09:46:21 -0700521 struct scsi_device *sdev;
Eric Moorea69de502007-09-14 18:48:19 -0600522 VirtDevice *vdevice;
Eric Mooredf9e0622007-01-29 09:46:21 -0700523 VirtTarget *vtarget = NULL;
Eric Moore547f9a22006-06-27 14:42:12 -0600524
Eric Mooredf9e0622007-01-29 09:46:21 -0700525 shost_for_each_device(sdev, ioc->sh) {
Eric Moorea69de502007-09-14 18:48:19 -0600526 if ((vdevice = sdev->hostdata) == NULL)
Eric Mooredf9e0622007-01-29 09:46:21 -0700527 continue;
Eric Moorea69de502007-09-14 18:48:19 -0600528 if (vdevice->vtarget->id == id &&
529 vdevice->vtarget->channel == channel)
530 vtarget = vdevice->vtarget;
Eric Moore547f9a22006-06-27 14:42:12 -0600531 }
Eric Mooredf9e0622007-01-29 09:46:21 -0700532 return vtarget;
533}
534
535/**
536 * mptsas_target_reset
537 *
538 * Issues TARGET_RESET to end device using handshaking method
539 *
540 * @ioc
541 * @channel
542 * @id
543 *
544 * Returns (1) success
545 * (0) failure
546 *
547 **/
548static int
549mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
550{
551 MPT_FRAME_HDR *mf;
552 SCSITaskMgmt_t *pScsiTm;
553
554 if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530555 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -0700556 ioc->name,__func__, __LINE__));
Eric Mooredf9e0622007-01-29 09:46:21 -0700557 return 0;
558 }
559
560 /* Format the Request
561 */
562 pScsiTm = (SCSITaskMgmt_t *) mf;
563 memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
564 pScsiTm->TargetID = id;
565 pScsiTm->Bus = channel;
566 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
567 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
568 pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
569
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530570 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
Eric Mooredf9e0622007-01-29 09:46:21 -0700571
Prakash, Sathya7a195f42007-08-14 16:08:40 +0530572 mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
Eric Mooredf9e0622007-01-29 09:46:21 -0700573
574 return 1;
575}
576
577/**
578 * mptsas_target_reset_queue
579 *
580 * Receive request for TARGET_RESET after recieving an firmware
581 * event NOT_RESPONDING_EVENT, then put command in link list
582 * and queue if task_queue already in use.
583 *
584 * @ioc
585 * @sas_event_data
586 *
587 **/
588static void
589mptsas_target_reset_queue(MPT_ADAPTER *ioc,
590 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
591{
Eric Mooree7eae9f2007-09-29 10:15:59 -0600592 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
Eric Mooredf9e0622007-01-29 09:46:21 -0700593 VirtTarget *vtarget = NULL;
594 struct mptsas_target_reset_event *target_reset_list;
595 u8 id, channel;
596
597 id = sas_event_data->TargetID;
598 channel = sas_event_data->Bus;
599
600 if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
601 return;
602
603 vtarget->deleted = 1; /* block IO */
604
605 target_reset_list = kzalloc(sizeof(*target_reset_list),
606 GFP_ATOMIC);
607 if (!target_reset_list) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530608 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -0700609 ioc->name,__func__, __LINE__));
Eric Mooredf9e0622007-01-29 09:46:21 -0700610 return;
611 }
612
613 memcpy(&target_reset_list->sas_event_data, sas_event_data,
614 sizeof(*sas_event_data));
615 list_add_tail(&target_reset_list->list, &hd->target_reset_list);
616
617 if (hd->resetPending)
618 return;
619
620 if (mptsas_target_reset(ioc, channel, id)) {
621 target_reset_list->target_reset_issued = 1;
622 hd->resetPending = 1;
623 }
624}
625
626/**
627 * mptsas_dev_reset_complete
628 *
629 * Completion for TARGET_RESET after NOT_RESPONDING_EVENT,
630 * enable work queue to finish off removing device from upper layers.
631 * then send next TARGET_RESET in the queue.
632 *
633 * @ioc
634 *
635 **/
636static void
637mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
638{
Eric Mooree7eae9f2007-09-29 10:15:59 -0600639 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
Eric Mooredf9e0622007-01-29 09:46:21 -0700640 struct list_head *head = &hd->target_reset_list;
641 struct mptsas_target_reset_event *target_reset_list;
642 struct mptsas_hotplug_event *ev;
643 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
644 u8 id, channel;
645 __le64 sas_address;
646
647 if (list_empty(head))
648 return;
649
650 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list);
651
652 sas_event_data = &target_reset_list->sas_event_data;
653 id = sas_event_data->TargetID;
654 channel = sas_event_data->Bus;
655 hd->resetPending = 0;
656
657 /*
658 * retry target reset
659 */
660 if (!target_reset_list->target_reset_issued) {
661 if (mptsas_target_reset(ioc, channel, id)) {
662 target_reset_list->target_reset_issued = 1;
663 hd->resetPending = 1;
664 }
665 return;
666 }
667
668 /*
669 * enable work queue to remove device from upper layers
670 */
671 list_del(&target_reset_list->list);
672
673 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
674 if (!ev) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530675 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -0700676 ioc->name,__func__, __LINE__));
Eric Mooredf9e0622007-01-29 09:46:21 -0700677 return;
678 }
679
680 INIT_WORK(&ev->work, mptsas_hotplug_work);
681 ev->ioc = ioc;
682 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
683 ev->parent_handle =
684 le16_to_cpu(sas_event_data->ParentDevHandle);
685 ev->channel = channel;
686 ev->id =id;
687 ev->phy_id = sas_event_data->PhyNum;
688 memcpy(&sas_address, &sas_event_data->SASAddress,
689 sizeof(__le64));
690 ev->sas_address = le64_to_cpu(sas_address);
691 ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
692 ev->event_type = MPTSAS_DEL_DEVICE;
693 schedule_work(&ev->work);
694 kfree(target_reset_list);
695
696 /*
697 * issue target reset to next device in the queue
698 */
699
700 head = &hd->target_reset_list;
701 if (list_empty(head))
702 return;
703
704 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
705 list);
706
707 sas_event_data = &target_reset_list->sas_event_data;
708 id = sas_event_data->TargetID;
709 channel = sas_event_data->Bus;
710
711 if (mptsas_target_reset(ioc, channel, id)) {
712 target_reset_list->target_reset_issued = 1;
713 hd->resetPending = 1;
714 }
715}
716
717/**
718 * mptsas_taskmgmt_complete
719 *
720 * @ioc
721 * @mf
722 * @mr
723 *
724 **/
725static int
726mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
727{
728 mptsas_dev_reset_complete(ioc);
729 return mptscsih_taskmgmt_complete(ioc, mf, mr);
730}
731
732/**
733 * mptscsih_ioc_reset
734 *
735 * @ioc
736 * @reset_phase
737 *
738 **/
739static int
740mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
741{
Judith Lebzelterba76ef22007-03-09 13:07:44 -0800742 MPT_SCSI_HOST *hd;
Eric Mooredf9e0622007-01-29 09:46:21 -0700743 struct mptsas_target_reset_event *target_reset_list, *n;
744 int rc;
745
746 rc = mptscsih_ioc_reset(ioc, reset_phase);
747
748 if (ioc->bus_type != SAS)
749 goto out;
750
751 if (reset_phase != MPT_IOC_POST_RESET)
752 goto out;
753
Judith Lebzelterba76ef22007-03-09 13:07:44 -0800754 if (!ioc->sh || !ioc->sh->hostdata)
755 goto out;
Eric Mooree7eae9f2007-09-29 10:15:59 -0600756 hd = shost_priv(ioc->sh);
Judith Lebzelterba76ef22007-03-09 13:07:44 -0800757 if (!hd->ioc)
Eric Mooredf9e0622007-01-29 09:46:21 -0700758 goto out;
759
760 if (list_empty(&hd->target_reset_list))
761 goto out;
762
763 /* flush the target_reset_list */
764 list_for_each_entry_safe(target_reset_list, n,
765 &hd->target_reset_list, list) {
766 list_del(&target_reset_list->list);
767 kfree(target_reset_list);
768 }
769
770 out:
771 return rc;
Eric Moore547f9a22006-06-27 14:42:12 -0600772}
773
Christoph Hellwige3094442006-02-16 13:25:36 +0100774static int
Moore, Eric52435432006-03-14 09:14:15 -0700775mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
Christoph Hellwige3094442006-02-16 13:25:36 +0100776 u32 form, u32 form_specific)
777{
778 ConfigExtendedPageHeader_t hdr;
779 CONFIGPARMS cfg;
780 SasEnclosurePage0_t *buffer;
781 dma_addr_t dma_handle;
782 int error;
783 __le64 le_identifier;
784
785 memset(&hdr, 0, sizeof(hdr));
786 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
787 hdr.PageNumber = 0;
788 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
789 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
790
791 cfg.cfghdr.ehdr = &hdr;
792 cfg.physAddr = -1;
793 cfg.pageAddr = form + form_specific;
794 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
795 cfg.dir = 0; /* read */
796 cfg.timeout = 10;
797
798 error = mpt_config(ioc, &cfg);
799 if (error)
800 goto out;
801 if (!hdr.ExtPageLength) {
802 error = -ENXIO;
803 goto out;
804 }
805
806 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
807 &dma_handle);
808 if (!buffer) {
809 error = -ENOMEM;
810 goto out;
811 }
812
813 cfg.physAddr = dma_handle;
814 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
815
816 error = mpt_config(ioc, &cfg);
817 if (error)
818 goto out_free_consistent;
819
820 /* save config data */
821 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
822 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
823 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
824 enclosure->flags = le16_to_cpu(buffer->Flags);
825 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
826 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
827 enclosure->start_id = buffer->StartTargetID;
828 enclosure->start_channel = buffer->StartBus;
829 enclosure->sep_id = buffer->SEPTargetID;
830 enclosure->sep_channel = buffer->SEPBus;
831
832 out_free_consistent:
833 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
834 buffer, dma_handle);
835 out:
836 return error;
837}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200838
James Bottomleyf013db32006-03-18 14:54:36 -0600839static int
840mptsas_slave_configure(struct scsi_device *sdev)
841{
Moore, Eric3c0c25b2006-04-13 16:08:17 -0600842
James Bottomleye8bf3942006-07-11 17:49:34 -0400843 if (sdev->channel == MPTSAS_RAID_CHANNEL)
844 goto out;
James Bottomleyf013db32006-03-18 14:54:36 -0600845
James Bottomleye8bf3942006-07-11 17:49:34 -0400846 sas_read_port_mode_page(sdev);
847
848 out:
James Bottomleyf013db32006-03-18 14:54:36 -0600849 return mptscsih_slave_configure(sdev);
850}
851
Eric Moore547f9a22006-06-27 14:42:12 -0600852static int
853mptsas_target_alloc(struct scsi_target *starget)
854{
855 struct Scsi_Host *host = dev_to_shost(&starget->dev);
Eric Mooree7eae9f2007-09-29 10:15:59 -0600856 MPT_SCSI_HOST *hd = shost_priv(host);
Eric Moore547f9a22006-06-27 14:42:12 -0600857 VirtTarget *vtarget;
Eric Moore793955f2007-01-29 09:42:20 -0700858 u8 id, channel;
Eric Moore547f9a22006-06-27 14:42:12 -0600859 struct sas_rphy *rphy;
860 struct mptsas_portinfo *p;
861 int i;
Eric Mooree80b0022007-09-14 18:49:03 -0600862 MPT_ADAPTER *ioc = hd->ioc;
Eric Moore547f9a22006-06-27 14:42:12 -0600863
864 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
865 if (!vtarget)
866 return -ENOMEM;
867
868 vtarget->starget = starget;
Eric Mooree80b0022007-09-14 18:49:03 -0600869 vtarget->ioc_id = ioc->id;
Eric Moore793955f2007-01-29 09:42:20 -0700870 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
871 id = starget->id;
Eric Moore547f9a22006-06-27 14:42:12 -0600872 channel = 0;
873
Eric Moore793955f2007-01-29 09:42:20 -0700874 /*
875 * RAID volumes placed beyond the last expected port.
876 */
877 if (starget->channel == MPTSAS_RAID_CHANNEL) {
Eric Mooree80b0022007-09-14 18:49:03 -0600878 for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
879 if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
880 channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
Eric Moore547f9a22006-06-27 14:42:12 -0600881 goto out;
Eric Moore793955f2007-01-29 09:42:20 -0700882 }
Eric Moore547f9a22006-06-27 14:42:12 -0600883
884 rphy = dev_to_rphy(starget->dev.parent);
Eric Mooree80b0022007-09-14 18:49:03 -0600885 mutex_lock(&ioc->sas_topology_mutex);
886 list_for_each_entry(p, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -0600887 for (i = 0; i < p->num_phys; i++) {
888 if (p->phy_info[i].attached.sas_address !=
889 rphy->identify.sas_address)
890 continue;
Eric Moore793955f2007-01-29 09:42:20 -0700891 id = p->phy_info[i].attached.id;
Eric Moore547f9a22006-06-27 14:42:12 -0600892 channel = p->phy_info[i].attached.channel;
893 mptsas_set_starget(&p->phy_info[i], starget);
894
895 /*
896 * Exposing hidden raid components
897 */
Eric Mooree80b0022007-09-14 18:49:03 -0600898 if (mptscsih_is_phys_disk(ioc, channel, id)) {
899 id = mptscsih_raid_id_to_num(ioc,
Eric Moore793955f2007-01-29 09:42:20 -0700900 channel, id);
Eric Moore547f9a22006-06-27 14:42:12 -0600901 vtarget->tflags |=
902 MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Mooreb506ade2007-01-29 09:45:37 -0700903 p->phy_info[i].attached.phys_disk_num = id;
Eric Moore547f9a22006-06-27 14:42:12 -0600904 }
Eric Mooree80b0022007-09-14 18:49:03 -0600905 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -0600906 goto out;
907 }
908 }
Eric Mooree80b0022007-09-14 18:49:03 -0600909 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -0600910
911 kfree(vtarget);
912 return -ENXIO;
913
914 out:
Eric Moore793955f2007-01-29 09:42:20 -0700915 vtarget->id = id;
916 vtarget->channel = channel;
Eric Moore547f9a22006-06-27 14:42:12 -0600917 starget->hostdata = vtarget;
918 return 0;
919}
920
921static void
922mptsas_target_destroy(struct scsi_target *starget)
923{
924 struct Scsi_Host *host = dev_to_shost(&starget->dev);
Eric Mooree7eae9f2007-09-29 10:15:59 -0600925 MPT_SCSI_HOST *hd = shost_priv(host);
Eric Moore547f9a22006-06-27 14:42:12 -0600926 struct sas_rphy *rphy;
927 struct mptsas_portinfo *p;
928 int i;
Eric Mooree80b0022007-09-14 18:49:03 -0600929 MPT_ADAPTER *ioc = hd->ioc;
Eric Moore547f9a22006-06-27 14:42:12 -0600930
931 if (!starget->hostdata)
932 return;
933
James Bottomleye8bf3942006-07-11 17:49:34 -0400934 if (starget->channel == MPTSAS_RAID_CHANNEL)
Eric Moore547f9a22006-06-27 14:42:12 -0600935 goto out;
936
937 rphy = dev_to_rphy(starget->dev.parent);
Eric Mooree80b0022007-09-14 18:49:03 -0600938 list_for_each_entry(p, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -0600939 for (i = 0; i < p->num_phys; i++) {
940 if (p->phy_info[i].attached.sas_address !=
941 rphy->identify.sas_address)
942 continue;
943 mptsas_set_starget(&p->phy_info[i], NULL);
944 goto out;
945 }
946 }
947
948 out:
949 kfree(starget->hostdata);
950 starget->hostdata = NULL;
951}
952
953
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200954static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700955mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200956{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700957 struct Scsi_Host *host = sdev->host;
Eric Mooree7eae9f2007-09-29 10:15:59 -0600958 MPT_SCSI_HOST *hd = shost_priv(host);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200959 struct sas_rphy *rphy;
960 struct mptsas_portinfo *p;
Eric Moorea69de502007-09-14 18:48:19 -0600961 VirtDevice *vdevice;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700962 struct scsi_target *starget;
Eric Moore547f9a22006-06-27 14:42:12 -0600963 int i;
Eric Mooree80b0022007-09-14 18:49:03 -0600964 MPT_ADAPTER *ioc = hd->ioc;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200965
Eric Moorea69de502007-09-14 18:48:19 -0600966 vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
967 if (!vdevice) {
Eric Moore547f9a22006-06-27 14:42:12 -0600968 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
Eric Mooree80b0022007-09-14 18:49:03 -0600969 ioc->name, sizeof(VirtDevice));
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200970 return -ENOMEM;
971 }
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700972 starget = scsi_target(sdev);
Eric Moorea69de502007-09-14 18:48:19 -0600973 vdevice->vtarget = starget->hostdata;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200974
James Bottomleye8bf3942006-07-11 17:49:34 -0400975 if (sdev->channel == MPTSAS_RAID_CHANNEL)
Moore, Eric816aa902006-01-13 16:25:20 -0700976 goto out;
Moore, Eric816aa902006-01-13 16:25:20 -0700977
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700978 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Eric Mooree80b0022007-09-14 18:49:03 -0600979 mutex_lock(&ioc->sas_topology_mutex);
980 list_for_each_entry(p, &ioc->sas_topology, list) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200981 for (i = 0; i < p->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -0600982 if (p->phy_info[i].attached.sas_address !=
983 rphy->identify.sas_address)
984 continue;
Eric Moorea69de502007-09-14 18:48:19 -0600985 vdevice->lun = sdev->lun;
Eric Moore547f9a22006-06-27 14:42:12 -0600986 /*
987 * Exposing hidden raid components
988 */
Eric Mooree80b0022007-09-14 18:49:03 -0600989 if (mptscsih_is_phys_disk(ioc,
Eric Moore793955f2007-01-29 09:42:20 -0700990 p->phy_info[i].attached.channel,
991 p->phy_info[i].attached.id))
Eric Moore547f9a22006-06-27 14:42:12 -0600992 sdev->no_uld_attach = 1;
Eric Mooree80b0022007-09-14 18:49:03 -0600993 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -0600994 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200995 }
996 }
Eric Mooree80b0022007-09-14 18:49:03 -0600997 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200998
Eric Moorea69de502007-09-14 18:48:19 -0600999 kfree(vdevice);
Christoph Hellwig23f236e2006-01-30 19:00:43 +01001000 return -ENXIO;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001001
1002 out:
Eric Moorea69de502007-09-14 18:48:19 -06001003 vdevice->vtarget->num_luns++;
1004 sdev->hostdata = vdevice;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001005 return 0;
1006}
1007
Eric Moore547f9a22006-06-27 14:42:12 -06001008static int
1009mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001010{
Eric Moorea69de502007-09-14 18:48:19 -06001011 VirtDevice *vdevice = SCpnt->device->hostdata;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001012
Eric Moorea69de502007-09-14 18:48:19 -06001013 if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
Eric Moore547f9a22006-06-27 14:42:12 -06001014 SCpnt->result = DID_NO_CONNECT << 16;
1015 done(SCpnt);
1016 return 0;
Moore, Eric7d3eecf2006-01-25 18:05:12 -07001017 }
Eric Moore547f9a22006-06-27 14:42:12 -06001018
Eric Moore793955f2007-01-29 09:42:20 -07001019// scsi_print_command(SCpnt);
1020
Eric Moore547f9a22006-06-27 14:42:12 -06001021 return mptscsih_qcmd(SCpnt,done);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001022}
1023
Eric Moore547f9a22006-06-27 14:42:12 -06001024
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001025static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -07001026 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001027 .proc_name = "mptsas",
1028 .proc_info = mptscsih_proc_info,
1029 .name = "MPT SPI Host",
1030 .info = mptscsih_info,
Eric Moore547f9a22006-06-27 14:42:12 -06001031 .queuecommand = mptsas_qcmd,
1032 .target_alloc = mptsas_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001033 .slave_alloc = mptsas_slave_alloc,
James Bottomleyf013db32006-03-18 14:54:36 -06001034 .slave_configure = mptsas_slave_configure,
Eric Moore547f9a22006-06-27 14:42:12 -06001035 .target_destroy = mptsas_target_destroy,
1036 .slave_destroy = mptscsih_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001037 .change_queue_depth = mptscsih_change_queue_depth,
1038 .eh_abort_handler = mptscsih_abort,
1039 .eh_device_reset_handler = mptscsih_dev_reset,
1040 .eh_bus_reset_handler = mptscsih_bus_reset,
1041 .eh_host_reset_handler = mptscsih_host_reset,
1042 .bios_param = mptscsih_bios_param,
1043 .can_queue = MPT_FC_CAN_QUEUE,
1044 .this_id = -1,
1045 .sg_tablesize = MPT_SCSI_SG_DEPTH,
1046 .max_sectors = 8192,
1047 .cmd_per_lun = 7,
1048 .use_clustering = ENABLE_CLUSTERING,
Prakash, Sathyaedb90682007-07-17 14:39:14 +05301049 .shost_attrs = mptscsih_host_attrs,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001050};
1051
Christoph Hellwigb5141122005-10-28 22:07:41 +02001052static int mptsas_get_linkerrors(struct sas_phy *phy)
1053{
1054 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1055 ConfigExtendedPageHeader_t hdr;
1056 CONFIGPARMS cfg;
1057 SasPhyPage1_t *buffer;
1058 dma_addr_t dma_handle;
1059 int error;
1060
James Bottomleyf4ad7b52006-08-25 13:48:18 -05001061 /* FIXME: only have link errors on local phys */
1062 if (!scsi_is_sas_phy_local(phy))
1063 return -EINVAL;
1064
Christoph Hellwigb5141122005-10-28 22:07:41 +02001065 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
1066 hdr.ExtPageLength = 0;
1067 hdr.PageNumber = 1 /* page number 1*/;
1068 hdr.Reserved1 = 0;
1069 hdr.Reserved2 = 0;
1070 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1071 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1072
1073 cfg.cfghdr.ehdr = &hdr;
1074 cfg.physAddr = -1;
1075 cfg.pageAddr = phy->identify.phy_identifier;
1076 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1077 cfg.dir = 0; /* read */
1078 cfg.timeout = 10;
1079
1080 error = mpt_config(ioc, &cfg);
1081 if (error)
1082 return error;
1083 if (!hdr.ExtPageLength)
1084 return -ENXIO;
1085
1086 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1087 &dma_handle);
1088 if (!buffer)
1089 return -ENOMEM;
1090
1091 cfg.physAddr = dma_handle;
1092 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1093
1094 error = mpt_config(ioc, &cfg);
1095 if (error)
1096 goto out_free_consistent;
1097
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301098 mptsas_print_phy_pg1(ioc, buffer);
Christoph Hellwigb5141122005-10-28 22:07:41 +02001099
1100 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
1101 phy->running_disparity_error_count =
1102 le32_to_cpu(buffer->RunningDisparityErrorCount);
1103 phy->loss_of_dword_sync_count =
1104 le32_to_cpu(buffer->LossDwordSynchCount);
1105 phy->phy_reset_problem_count =
1106 le32_to_cpu(buffer->PhyResetProblemCount);
1107
1108 out_free_consistent:
1109 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1110 buffer, dma_handle);
1111 return error;
1112}
1113
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001114static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
1115 MPT_FRAME_HDR *reply)
1116{
1117 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
1118 if (reply != NULL) {
1119 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
1120 memcpy(ioc->sas_mgmt.reply, reply,
1121 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
1122 }
1123 complete(&ioc->sas_mgmt.done);
1124 return 1;
1125}
1126
1127static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
1128{
1129 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1130 SasIoUnitControlRequest_t *req;
1131 SasIoUnitControlReply_t *reply;
1132 MPT_FRAME_HDR *mf;
1133 MPIHeader_t *hdr;
1134 unsigned long timeleft;
1135 int error = -ERESTARTSYS;
1136
James Bottomleyf4ad7b52006-08-25 13:48:18 -05001137 /* FIXME: fusion doesn't allow non-local phy reset */
1138 if (!scsi_is_sas_phy_local(phy))
1139 return -EINVAL;
1140
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001141 /* not implemented for expanders */
1142 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
1143 return -ENXIO;
1144
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01001145 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001146 goto out;
1147
1148 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
1149 if (!mf) {
1150 error = -ENOMEM;
1151 goto out_unlock;
1152 }
1153
1154 hdr = (MPIHeader_t *) mf;
1155 req = (SasIoUnitControlRequest_t *)mf;
1156 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
1157 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
1158 req->MsgContext = hdr->MsgContext;
1159 req->Operation = hard_reset ?
1160 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
1161 req->PhyNum = phy->identify.phy_identifier;
1162
1163 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
1164
1165 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
1166 10 * HZ);
1167 if (!timeleft) {
1168 /* On timeout reset the board */
1169 mpt_free_msg_frame(ioc, mf);
1170 mpt_HardResetHandler(ioc, CAN_SLEEP);
1171 error = -ETIMEDOUT;
1172 goto out_unlock;
1173 }
1174
1175 /* a reply frame is expected */
1176 if ((ioc->sas_mgmt.status &
1177 MPT_IOCTL_STATUS_RF_VALID) == 0) {
1178 error = -ENXIO;
1179 goto out_unlock;
1180 }
1181
1182 /* process the completed Reply Message Frame */
1183 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
1184 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
Eric Moore29dd3602007-09-14 18:46:51 -06001185 printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07001186 ioc->name, __func__, reply->IOCStatus, reply->IOCLogInfo);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001187 error = -ENXIO;
1188 goto out_unlock;
1189 }
1190
1191 error = 0;
1192
1193 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01001194 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001195 out:
1196 return error;
1197}
Christoph Hellwigb5141122005-10-28 22:07:41 +02001198
Christoph Hellwige3094442006-02-16 13:25:36 +01001199static int
1200mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1201{
1202 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1203 int i, error;
1204 struct mptsas_portinfo *p;
1205 struct mptsas_enclosure enclosure_info;
1206 u64 enclosure_handle;
1207
1208 mutex_lock(&ioc->sas_topology_mutex);
1209 list_for_each_entry(p, &ioc->sas_topology, list) {
1210 for (i = 0; i < p->num_phys; i++) {
1211 if (p->phy_info[i].attached.sas_address ==
1212 rphy->identify.sas_address) {
1213 enclosure_handle = p->phy_info[i].
1214 attached.handle_enclosure;
1215 goto found_info;
1216 }
1217 }
1218 }
1219 mutex_unlock(&ioc->sas_topology_mutex);
1220 return -ENXIO;
1221
1222 found_info:
1223 mutex_unlock(&ioc->sas_topology_mutex);
1224 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
Moore, Eric52435432006-03-14 09:14:15 -07001225 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
Christoph Hellwige3094442006-02-16 13:25:36 +01001226 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1227 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1228 if (!error)
1229 *identifier = enclosure_info.enclosure_logical_id;
1230 return error;
1231}
1232
1233static int
1234mptsas_get_bay_identifier(struct sas_rphy *rphy)
1235{
1236 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1237 struct mptsas_portinfo *p;
1238 int i, rc;
1239
1240 mutex_lock(&ioc->sas_topology_mutex);
1241 list_for_each_entry(p, &ioc->sas_topology, list) {
1242 for (i = 0; i < p->num_phys; i++) {
1243 if (p->phy_info[i].attached.sas_address ==
1244 rphy->identify.sas_address) {
1245 rc = p->phy_info[i].attached.slot;
1246 goto out;
1247 }
1248 }
1249 }
1250 rc = -ENXIO;
1251 out:
1252 mutex_unlock(&ioc->sas_topology_mutex);
1253 return rc;
1254}
1255
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001256static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1257 struct request *req)
1258{
1259 MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
1260 MPT_FRAME_HDR *mf;
1261 SmpPassthroughRequest_t *smpreq;
1262 struct request *rsp = req->next_rq;
1263 int ret;
1264 int flagsLength;
1265 unsigned long timeleft;
1266 char *psge;
1267 dma_addr_t dma_addr_in = 0;
1268 dma_addr_t dma_addr_out = 0;
1269 u64 sas_address = 0;
1270
1271 if (!rsp) {
Eric Moore29dd3602007-09-14 18:46:51 -06001272 printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07001273 ioc->name, __func__);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001274 return -EINVAL;
1275 }
1276
1277 /* do we need to support multiple segments? */
1278 if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
Eric Moore29dd3602007-09-14 18:46:51 -06001279 printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
Tejun Heob0790412009-05-07 22:24:42 +09001280 ioc->name, __func__, req->bio->bi_vcnt, blk_rq_bytes(req),
1281 rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001282 return -EINVAL;
1283 }
1284
1285 ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
1286 if (ret)
1287 goto out;
1288
1289 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
1290 if (!mf) {
1291 ret = -ENOMEM;
1292 goto out_unlock;
1293 }
1294
1295 smpreq = (SmpPassthroughRequest_t *)mf;
1296 memset(smpreq, 0, sizeof(*smpreq));
1297
Tejun Heob0790412009-05-07 22:24:42 +09001298 smpreq->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001299 smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
1300
1301 if (rphy)
1302 sas_address = rphy->identify.sas_address;
1303 else {
1304 struct mptsas_portinfo *port_info;
1305
1306 mutex_lock(&ioc->sas_topology_mutex);
Michael Reed77483692008-03-20 17:32:05 -05001307 port_info = mptsas_get_hba_portinfo(ioc);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001308 if (port_info && port_info->phy_info)
1309 sas_address =
1310 port_info->phy_info[0].phy->identify.sas_address;
1311 mutex_unlock(&ioc->sas_topology_mutex);
1312 }
1313
1314 *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
1315
1316 psge = (char *)
1317 (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
1318
1319 /* request */
1320 flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1321 MPI_SGE_FLAGS_END_OF_BUFFER |
1322 MPI_SGE_FLAGS_DIRECTION |
1323 mpt_addr_size()) << MPI_SGE_FLAGS_SHIFT;
Tejun Heob0790412009-05-07 22:24:42 +09001324 flagsLength |= (blk_rq_bytes(req) - 4);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001325
1326 dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
Tejun Heob0790412009-05-07 22:24:42 +09001327 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001328 if (!dma_addr_out)
1329 goto put_mf;
1330 mpt_add_sge(psge, flagsLength, dma_addr_out);
1331 psge += (sizeof(u32) + sizeof(dma_addr_t));
1332
1333 /* response */
1334 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
Tejun Heob0790412009-05-07 22:24:42 +09001335 flagsLength |= blk_rq_bytes(rsp) + 4;
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001336 dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio),
Tejun Heob0790412009-05-07 22:24:42 +09001337 blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001338 if (!dma_addr_in)
1339 goto unmap;
1340 mpt_add_sge(psge, flagsLength, dma_addr_in);
1341
1342 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
1343
1344 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
1345 if (!timeleft) {
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07001346 printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __func__);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001347 /* On timeout reset the board */
1348 mpt_HardResetHandler(ioc, CAN_SLEEP);
1349 ret = -ETIMEDOUT;
1350 goto unmap;
1351 }
1352 mf = NULL;
1353
1354 if (ioc->sas_mgmt.status & MPT_IOCTL_STATUS_RF_VALID) {
1355 SmpPassthroughReply_t *smprep;
1356
1357 smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
1358 memcpy(req->sense, smprep, sizeof(*smprep));
1359 req->sense_len = sizeof(*smprep);
Tejun Heob0790412009-05-07 22:24:42 +09001360 rsp->resid_len = blk_rq_bytes(rsp) - smprep->ResponseDataLength;
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001361 } else {
Eric Moore29dd3602007-09-14 18:46:51 -06001362 printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07001363 ioc->name, __func__);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001364 ret = -ENXIO;
1365 }
1366unmap:
1367 if (dma_addr_out)
Tejun Heob0790412009-05-07 22:24:42 +09001368 pci_unmap_single(ioc->pcidev, dma_addr_out, blk_rq_bytes(req),
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001369 PCI_DMA_BIDIRECTIONAL);
1370 if (dma_addr_in)
Tejun Heob0790412009-05-07 22:24:42 +09001371 pci_unmap_single(ioc->pcidev, dma_addr_in, blk_rq_bytes(rsp),
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001372 PCI_DMA_BIDIRECTIONAL);
1373put_mf:
1374 if (mf)
1375 mpt_free_msg_frame(ioc, mf);
1376out_unlock:
1377 mutex_unlock(&ioc->sas_mgmt.mutex);
1378out:
1379 return ret;
1380}
1381
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001382static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +02001383 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +01001384 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1385 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001386 .phy_reset = mptsas_phy_reset,
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001387 .smp_handler = mptsas_smp_handler,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001388};
1389
1390static struct scsi_transport_template *mptsas_transport_template;
1391
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001392static int
1393mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1394{
1395 ConfigExtendedPageHeader_t hdr;
1396 CONFIGPARMS cfg;
1397 SasIOUnitPage0_t *buffer;
1398 dma_addr_t dma_handle;
1399 int error, i;
1400
1401 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1402 hdr.ExtPageLength = 0;
1403 hdr.PageNumber = 0;
1404 hdr.Reserved1 = 0;
1405 hdr.Reserved2 = 0;
1406 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1407 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1408
1409 cfg.cfghdr.ehdr = &hdr;
1410 cfg.physAddr = -1;
1411 cfg.pageAddr = 0;
1412 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1413 cfg.dir = 0; /* read */
1414 cfg.timeout = 10;
1415
1416 error = mpt_config(ioc, &cfg);
1417 if (error)
1418 goto out;
1419 if (!hdr.ExtPageLength) {
1420 error = -ENXIO;
1421 goto out;
1422 }
1423
1424 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1425 &dma_handle);
1426 if (!buffer) {
1427 error = -ENOMEM;
1428 goto out;
1429 }
1430
1431 cfg.physAddr = dma_handle;
1432 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1433
1434 error = mpt_config(ioc, &cfg);
1435 if (error)
1436 goto out_free_consistent;
1437
1438 port_info->num_phys = buffer->NumPhys;
1439 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001440 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001441 if (!port_info->phy_info) {
1442 error = -ENOMEM;
1443 goto out_free_consistent;
1444 }
1445
Prakash, Sathyaedb90682007-07-17 14:39:14 +05301446 ioc->nvdata_version_persistent =
1447 le16_to_cpu(buffer->NvdataVersionPersistent);
1448 ioc->nvdata_version_default =
1449 le16_to_cpu(buffer->NvdataVersionDefault);
1450
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001451 for (i = 0; i < port_info->num_phys; i++) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301452 mptsas_print_phy_data(ioc, &buffer->PhyData[i]);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001453 port_info->phy_info[i].phy_id = i;
1454 port_info->phy_info[i].port_id =
1455 buffer->PhyData[i].Port;
1456 port_info->phy_info[i].negotiated_link_rate =
1457 buffer->PhyData[i].NegotiatedLinkRate;
Eric Moore547f9a22006-06-27 14:42:12 -06001458 port_info->phy_info[i].portinfo = port_info;
Eric Moore2ecce492007-01-29 09:47:08 -07001459 port_info->phy_info[i].handle =
1460 le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001461 }
1462
1463 out_free_consistent:
1464 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1465 buffer, dma_handle);
1466 out:
1467 return error;
1468}
1469
1470static int
Prakash, Sathyaedb90682007-07-17 14:39:14 +05301471mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
1472{
1473 ConfigExtendedPageHeader_t hdr;
1474 CONFIGPARMS cfg;
1475 SasIOUnitPage1_t *buffer;
1476 dma_addr_t dma_handle;
1477 int error;
1478 u16 device_missing_delay;
1479
1480 memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
1481 memset(&cfg, 0, sizeof(CONFIGPARMS));
1482
1483 cfg.cfghdr.ehdr = &hdr;
1484 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1485 cfg.timeout = 10;
1486 cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1487 cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1488 cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
1489 cfg.cfghdr.ehdr->PageNumber = 1;
1490
1491 error = mpt_config(ioc, &cfg);
1492 if (error)
1493 goto out;
1494 if (!hdr.ExtPageLength) {
1495 error = -ENXIO;
1496 goto out;
1497 }
1498
1499 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1500 &dma_handle);
1501 if (!buffer) {
1502 error = -ENOMEM;
1503 goto out;
1504 }
1505
1506 cfg.physAddr = dma_handle;
1507 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1508
1509 error = mpt_config(ioc, &cfg);
1510 if (error)
1511 goto out_free_consistent;
1512
1513 ioc->io_missing_delay =
1514 le16_to_cpu(buffer->IODeviceMissingDelay);
1515 device_missing_delay = le16_to_cpu(buffer->ReportDeviceMissingDelay);
1516 ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ?
1517 (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 :
1518 device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
1519
1520 out_free_consistent:
1521 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1522 buffer, dma_handle);
1523 out:
1524 return error;
1525}
1526
1527static int
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001528mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1529 u32 form, u32 form_specific)
1530{
1531 ConfigExtendedPageHeader_t hdr;
1532 CONFIGPARMS cfg;
1533 SasPhyPage0_t *buffer;
1534 dma_addr_t dma_handle;
1535 int error;
1536
1537 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1538 hdr.ExtPageLength = 0;
1539 hdr.PageNumber = 0;
1540 hdr.Reserved1 = 0;
1541 hdr.Reserved2 = 0;
1542 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1543 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1544
1545 cfg.cfghdr.ehdr = &hdr;
1546 cfg.dir = 0; /* read */
1547 cfg.timeout = 10;
1548
1549 /* Get Phy Pg 0 for each Phy. */
1550 cfg.physAddr = -1;
1551 cfg.pageAddr = form + form_specific;
1552 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1553
1554 error = mpt_config(ioc, &cfg);
1555 if (error)
1556 goto out;
1557
1558 if (!hdr.ExtPageLength) {
1559 error = -ENXIO;
1560 goto out;
1561 }
1562
1563 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1564 &dma_handle);
1565 if (!buffer) {
1566 error = -ENOMEM;
1567 goto out;
1568 }
1569
1570 cfg.physAddr = dma_handle;
1571 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1572
1573 error = mpt_config(ioc, &cfg);
1574 if (error)
1575 goto out_free_consistent;
1576
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301577 mptsas_print_phy_pg0(ioc, buffer);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001578
1579 phy_info->hw_link_rate = buffer->HwLinkRate;
1580 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1581 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1582 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1583
1584 out_free_consistent:
1585 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1586 buffer, dma_handle);
1587 out:
1588 return error;
1589}
1590
1591static int
1592mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1593 u32 form, u32 form_specific)
1594{
1595 ConfigExtendedPageHeader_t hdr;
1596 CONFIGPARMS cfg;
1597 SasDevicePage0_t *buffer;
1598 dma_addr_t dma_handle;
1599 __le64 sas_address;
Moore, Ericbd23e942006-04-17 12:43:04 -06001600 int error=0;
1601
1602 if (ioc->sas_discovery_runtime &&
1603 mptsas_is_end_device(device_info))
1604 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001605
1606 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1607 hdr.ExtPageLength = 0;
1608 hdr.PageNumber = 0;
1609 hdr.Reserved1 = 0;
1610 hdr.Reserved2 = 0;
1611 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1612 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1613
1614 cfg.cfghdr.ehdr = &hdr;
1615 cfg.pageAddr = form + form_specific;
1616 cfg.physAddr = -1;
1617 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1618 cfg.dir = 0; /* read */
1619 cfg.timeout = 10;
1620
Moore, Ericdb9c9172006-03-14 09:14:18 -07001621 memset(device_info, 0, sizeof(struct mptsas_devinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001622 error = mpt_config(ioc, &cfg);
1623 if (error)
1624 goto out;
1625 if (!hdr.ExtPageLength) {
1626 error = -ENXIO;
1627 goto out;
1628 }
1629
1630 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1631 &dma_handle);
1632 if (!buffer) {
1633 error = -ENOMEM;
1634 goto out;
1635 }
1636
1637 cfg.physAddr = dma_handle;
1638 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1639
1640 error = mpt_config(ioc, &cfg);
1641 if (error)
1642 goto out_free_consistent;
1643
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301644 mptsas_print_device_pg0(ioc, buffer);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001645
1646 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001647 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +01001648 device_info->handle_enclosure =
1649 le16_to_cpu(buffer->EnclosureHandle);
1650 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001651 device_info->phy_id = buffer->PhyNum;
1652 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001653 device_info->id = buffer->TargetID;
Eric Mooreb506ade2007-01-29 09:45:37 -07001654 device_info->phys_disk_num = ~0;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001655 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001656 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1657 device_info->sas_address = le64_to_cpu(sas_address);
1658 device_info->device_info =
1659 le32_to_cpu(buffer->DeviceInfo);
1660
1661 out_free_consistent:
1662 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1663 buffer, dma_handle);
1664 out:
1665 return error;
1666}
1667
1668static int
1669mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1670 u32 form, u32 form_specific)
1671{
1672 ConfigExtendedPageHeader_t hdr;
1673 CONFIGPARMS cfg;
1674 SasExpanderPage0_t *buffer;
1675 dma_addr_t dma_handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001676 int i, error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001677
1678 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1679 hdr.ExtPageLength = 0;
1680 hdr.PageNumber = 0;
1681 hdr.Reserved1 = 0;
1682 hdr.Reserved2 = 0;
1683 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1684 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1685
1686 cfg.cfghdr.ehdr = &hdr;
1687 cfg.physAddr = -1;
1688 cfg.pageAddr = form + form_specific;
1689 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1690 cfg.dir = 0; /* read */
1691 cfg.timeout = 10;
1692
Moore, Ericdb9c9172006-03-14 09:14:18 -07001693 memset(port_info, 0, sizeof(struct mptsas_portinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001694 error = mpt_config(ioc, &cfg);
1695 if (error)
1696 goto out;
1697
1698 if (!hdr.ExtPageLength) {
1699 error = -ENXIO;
1700 goto out;
1701 }
1702
1703 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1704 &dma_handle);
1705 if (!buffer) {
1706 error = -ENOMEM;
1707 goto out;
1708 }
1709
1710 cfg.physAddr = dma_handle;
1711 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1712
1713 error = mpt_config(ioc, &cfg);
1714 if (error)
1715 goto out_free_consistent;
1716
Krzysztof Oledzki51f39ea2008-03-04 14:56:23 -08001717 if (!buffer->NumPhys) {
1718 error = -ENODEV;
1719 goto out_free_consistent;
1720 }
1721
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001722 /* save config data */
1723 port_info->num_phys = buffer->NumPhys;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001724 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001725 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001726 if (!port_info->phy_info) {
1727 error = -ENOMEM;
1728 goto out_free_consistent;
1729 }
1730
Eric Moore2ecce492007-01-29 09:47:08 -07001731 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06001732 port_info->phy_info[i].portinfo = port_info;
Eric Moore2ecce492007-01-29 09:47:08 -07001733 port_info->phy_info[i].handle =
1734 le16_to_cpu(buffer->DevHandle);
1735 }
Eric Moore547f9a22006-06-27 14:42:12 -06001736
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001737 out_free_consistent:
1738 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1739 buffer, dma_handle);
1740 out:
1741 return error;
1742}
1743
1744static int
1745mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1746 u32 form, u32 form_specific)
1747{
1748 ConfigExtendedPageHeader_t hdr;
1749 CONFIGPARMS cfg;
1750 SasExpanderPage1_t *buffer;
1751 dma_addr_t dma_handle;
Moore, Ericbd23e942006-04-17 12:43:04 -06001752 int error=0;
1753
1754 if (ioc->sas_discovery_runtime &&
1755 mptsas_is_end_device(&phy_info->attached))
1756 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001757
1758 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1759 hdr.ExtPageLength = 0;
1760 hdr.PageNumber = 1;
1761 hdr.Reserved1 = 0;
1762 hdr.Reserved2 = 0;
1763 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1764 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1765
1766 cfg.cfghdr.ehdr = &hdr;
1767 cfg.physAddr = -1;
1768 cfg.pageAddr = form + form_specific;
1769 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1770 cfg.dir = 0; /* read */
1771 cfg.timeout = 10;
1772
1773 error = mpt_config(ioc, &cfg);
1774 if (error)
1775 goto out;
1776
1777 if (!hdr.ExtPageLength) {
1778 error = -ENXIO;
1779 goto out;
1780 }
1781
1782 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1783 &dma_handle);
1784 if (!buffer) {
1785 error = -ENOMEM;
1786 goto out;
1787 }
1788
1789 cfg.physAddr = dma_handle;
1790 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1791
1792 error = mpt_config(ioc, &cfg);
1793 if (error)
1794 goto out_free_consistent;
1795
1796
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301797 mptsas_print_expander_pg1(ioc, buffer);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001798
1799 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001800 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001801 phy_info->port_id = buffer->PhysicalPort;
1802 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1803 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1804 phy_info->hw_link_rate = buffer->HwLinkRate;
1805 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1806 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1807
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001808 out_free_consistent:
1809 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1810 buffer, dma_handle);
1811 out:
1812 return error;
1813}
1814
1815static void
1816mptsas_parse_device_info(struct sas_identify *identify,
1817 struct mptsas_devinfo *device_info)
1818{
1819 u16 protocols;
1820
1821 identify->sas_address = device_info->sas_address;
1822 identify->phy_identifier = device_info->phy_id;
1823
1824 /*
1825 * Fill in Phy Initiator Port Protocol.
1826 * Bits 6:3, more than one bit can be set, fall through cases.
1827 */
1828 protocols = device_info->device_info & 0x78;
1829 identify->initiator_port_protocols = 0;
1830 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1831 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1832 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1833 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1834 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1835 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1836 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1837 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1838
1839 /*
1840 * Fill in Phy Target Port Protocol.
1841 * Bits 10:7, more than one bit can be set, fall through cases.
1842 */
1843 protocols = device_info->device_info & 0x780;
1844 identify->target_port_protocols = 0;
1845 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1846 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1847 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1848 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1849 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1850 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1851 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1852 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1853
1854 /*
1855 * Fill in Attached device type.
1856 */
1857 switch (device_info->device_info &
1858 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1859 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1860 identify->device_type = SAS_PHY_UNUSED;
1861 break;
1862 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1863 identify->device_type = SAS_END_DEVICE;
1864 break;
1865 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1866 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1867 break;
1868 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1869 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1870 break;
1871 }
1872}
1873
1874static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001875 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001876{
Moore, Erice6b2d762006-03-14 09:14:24 -07001877 MPT_ADAPTER *ioc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001878 struct sas_phy *phy;
Eric Moore547f9a22006-06-27 14:42:12 -06001879 struct sas_port *port;
1880 int error = 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001881
Eric Moore547f9a22006-06-27 14:42:12 -06001882 if (!dev) {
1883 error = -ENODEV;
1884 goto out;
1885 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001886
1887 if (!phy_info->phy) {
1888 phy = sas_phy_alloc(dev, index);
Eric Moore547f9a22006-06-27 14:42:12 -06001889 if (!phy) {
1890 error = -ENOMEM;
1891 goto out;
1892 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001893 } else
1894 phy = phy_info->phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001895
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001896 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001897
1898 /*
1899 * Set Negotiated link rate.
1900 */
1901 switch (phy_info->negotiated_link_rate) {
1902 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001903 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001904 break;
1905 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001906 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001907 break;
1908 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001909 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001910 break;
1911 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001912 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001913 break;
1914 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1915 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1916 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001917 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001918 break;
1919 }
1920
1921 /*
1922 * Set Max hardware link rate.
1923 */
1924 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1925 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001926 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001927 break;
1928 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001929 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001930 break;
1931 default:
1932 break;
1933 }
1934
1935 /*
1936 * Set Max programmed link rate.
1937 */
1938 switch (phy_info->programmed_link_rate &
1939 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1940 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001941 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001942 break;
1943 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001944 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001945 break;
1946 default:
1947 break;
1948 }
1949
1950 /*
1951 * Set Min hardware link rate.
1952 */
1953 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1954 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001955 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001956 break;
1957 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001958 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001959 break;
1960 default:
1961 break;
1962 }
1963
1964 /*
1965 * Set Min programmed link rate.
1966 */
1967 switch (phy_info->programmed_link_rate &
1968 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1969 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001970 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001971 break;
1972 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001973 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001974 break;
1975 default:
1976 break;
1977 }
1978
Moore, Erice6b2d762006-03-14 09:14:24 -07001979 if (!phy_info->phy) {
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001980
Moore, Erice6b2d762006-03-14 09:14:24 -07001981 error = sas_phy_add(phy);
1982 if (error) {
1983 sas_phy_free(phy);
Eric Moore547f9a22006-06-27 14:42:12 -06001984 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001985 }
1986 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001987 }
1988
Eric Moore547f9a22006-06-27 14:42:12 -06001989 if (!phy_info->attached.handle ||
1990 !phy_info->port_details)
1991 goto out;
1992
1993 port = mptsas_get_port(phy_info);
1994 ioc = phy_to_ioc(phy_info->phy);
1995
1996 if (phy_info->sas_port_add_phy) {
1997
1998 if (!port) {
Eric Mooredc22f162006-07-06 11:23:14 -06001999 port = sas_port_alloc_num(dev);
Eric Moore547f9a22006-06-27 14:42:12 -06002000 if (!port) {
2001 error = -ENOMEM;
2002 goto out;
2003 }
2004 error = sas_port_add(port);
2005 if (error) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302006 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002007 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002008 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002009 goto out;
2010 }
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302011 mptsas_set_port(ioc, phy_info, port);
Eric Moore29dd3602007-09-14 18:46:51 -06002012 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
Eric Mooredc22f162006-07-06 11:23:14 -06002013 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
Eric Moore29dd3602007-09-14 18:46:51 -06002014 ioc->name, port, dev, port->port_identifier));
Eric Moore547f9a22006-06-27 14:42:12 -06002015 }
Eric Moore29dd3602007-09-14 18:46:51 -06002016 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_port_add_phy: phy_id=%d\n",
2017 ioc->name, phy_info->phy_id));
Eric Moore547f9a22006-06-27 14:42:12 -06002018 sas_port_add_phy(port, phy_info->phy);
2019 phy_info->sas_port_add_phy = 0;
2020 }
2021
2022 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
Moore, Erice6b2d762006-03-14 09:14:24 -07002023
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002024 struct sas_rphy *rphy;
James Bottomley2686de22006-06-30 12:54:02 -05002025 struct device *parent;
James Bottomleyf013db32006-03-18 14:54:36 -06002026 struct sas_identify identify;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002027
James Bottomley2686de22006-06-30 12:54:02 -05002028 parent = dev->parent->parent;
Moore, Erice6b2d762006-03-14 09:14:24 -07002029 /*
2030 * Let the hotplug_work thread handle processing
2031 * the adding/removing of devices that occur
2032 * after start of day.
2033 */
2034 if (ioc->sas_discovery_runtime &&
2035 mptsas_is_end_device(&phy_info->attached))
Eric Moore547f9a22006-06-27 14:42:12 -06002036 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07002037
James Bottomleyf013db32006-03-18 14:54:36 -06002038 mptsas_parse_device_info(&identify, &phy_info->attached);
James Bottomley2686de22006-06-30 12:54:02 -05002039 if (scsi_is_host_device(parent)) {
2040 struct mptsas_portinfo *port_info;
2041 int i;
2042
2043 mutex_lock(&ioc->sas_topology_mutex);
Michael Reed77483692008-03-20 17:32:05 -05002044 port_info = mptsas_get_hba_portinfo(ioc);
James Bottomley2686de22006-06-30 12:54:02 -05002045 mutex_unlock(&ioc->sas_topology_mutex);
2046
2047 for (i = 0; i < port_info->num_phys; i++)
2048 if (port_info->phy_info[i].identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04002049 identify.sas_address) {
2050 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05002051 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04002052 }
James Bottomley2686de22006-06-30 12:54:02 -05002053
2054 } else if (scsi_is_sas_rphy(parent)) {
2055 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
2056 if (identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04002057 parent_rphy->identify.sas_address) {
2058 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05002059 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04002060 }
James Bottomley2686de22006-06-30 12:54:02 -05002061 }
2062
James Bottomleyf013db32006-03-18 14:54:36 -06002063 switch (identify.device_type) {
2064 case SAS_END_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06002065 rphy = sas_end_device_alloc(port);
James Bottomleyf013db32006-03-18 14:54:36 -06002066 break;
2067 case SAS_EDGE_EXPANDER_DEVICE:
2068 case SAS_FANOUT_EXPANDER_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06002069 rphy = sas_expander_alloc(port, identify.device_type);
James Bottomleyf013db32006-03-18 14:54:36 -06002070 break;
2071 default:
2072 rphy = NULL;
2073 break;
2074 }
Eric Moore547f9a22006-06-27 14:42:12 -06002075 if (!rphy) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302076 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002077 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002078 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002079 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002080 }
2081
Eric Moore547f9a22006-06-27 14:42:12 -06002082 rphy->identify = identify;
2083 error = sas_rphy_add(rphy);
2084 if (error) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302085 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002086 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002087 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002088 sas_rphy_free(rphy);
2089 goto out;
2090 }
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302091 mptsas_set_rphy(ioc, phy_info, rphy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002092 }
2093
Eric Moore547f9a22006-06-27 14:42:12 -06002094 out:
2095 return error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002096}
2097
2098static int
Moore, Erice6b2d762006-03-14 09:14:24 -07002099mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002100{
Moore, Erice6b2d762006-03-14 09:14:24 -07002101 struct mptsas_portinfo *port_info, *hba;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002102 int error = -ENOMEM, i;
2103
Moore, Erice6b2d762006-03-14 09:14:24 -07002104 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
2105 if (! hba)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002106 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002107
Moore, Erice6b2d762006-03-14 09:14:24 -07002108 error = mptsas_sas_io_unit_pg0(ioc, hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002109 if (error)
2110 goto out_free_port_info;
2111
Prakash, Sathyaedb90682007-07-17 14:39:14 +05302112 mptsas_sas_io_unit_pg1(ioc);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002113 mutex_lock(&ioc->sas_topology_mutex);
Michael Reed77483692008-03-20 17:32:05 -05002114 port_info = mptsas_get_hba_portinfo(ioc);
Moore, Erice6b2d762006-03-14 09:14:24 -07002115 if (!port_info) {
2116 port_info = hba;
2117 list_add_tail(&port_info->list, &ioc->sas_topology);
2118 } else {
Eric Moore2ecce492007-01-29 09:47:08 -07002119 for (i = 0; i < hba->num_phys; i++) {
Moore, Erice6b2d762006-03-14 09:14:24 -07002120 port_info->phy_info[i].negotiated_link_rate =
2121 hba->phy_info[i].negotiated_link_rate;
Eric Moore2ecce492007-01-29 09:47:08 -07002122 port_info->phy_info[i].handle =
2123 hba->phy_info[i].handle;
2124 port_info->phy_info[i].port_id =
2125 hba->phy_info[i].port_id;
2126 }
Eric Moore547f9a22006-06-27 14:42:12 -06002127 kfree(hba->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002128 kfree(hba);
2129 hba = NULL;
2130 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002131 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002132 for (i = 0; i < port_info->num_phys; i++) {
2133 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
2134 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
2135 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
2136
2137 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
Eric Moore2ecce492007-01-29 09:47:08 -07002138 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2139 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2140 port_info->phy_info[i].handle);
Eric Moore024358e2005-10-21 20:56:36 +02002141 port_info->phy_info[i].identify.phy_id =
Eric Moore2ecce492007-01-29 09:47:08 -07002142 port_info->phy_info[i].phy_id = i;
Eric Moore547f9a22006-06-27 14:42:12 -06002143 if (port_info->phy_info[i].attached.handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002144 mptsas_sas_device_pg0(ioc,
2145 &port_info->phy_info[i].attached,
2146 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2147 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2148 port_info->phy_info[i].attached.handle);
Eric Moore547f9a22006-06-27 14:42:12 -06002149 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002150
Eric Moore547f9a22006-06-27 14:42:12 -06002151 mptsas_setup_wide_ports(ioc, port_info);
2152
2153 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002154 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Moore, Erice6b2d762006-03-14 09:14:24 -07002155 &port_info->phy_info[i], ioc->sas_index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002156
2157 return 0;
2158
2159 out_free_port_info:
Eric Moore547f9a22006-06-27 14:42:12 -06002160 kfree(hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002161 out:
2162 return error;
2163}
2164
2165static int
Moore, Erice6b2d762006-03-14 09:14:24 -07002166mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002167{
Moore, Erice6b2d762006-03-14 09:14:24 -07002168 struct mptsas_portinfo *port_info, *p, *ex;
Eric Moore547f9a22006-06-27 14:42:12 -06002169 struct device *parent;
2170 struct sas_rphy *rphy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002171 int error = -ENOMEM, i, j;
2172
Moore, Erice6b2d762006-03-14 09:14:24 -07002173 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
2174 if (!ex)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002175 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002176
Moore, Erice6b2d762006-03-14 09:14:24 -07002177 error = mptsas_sas_expander_pg0(ioc, ex,
Eric Moore2ecce492007-01-29 09:47:08 -07002178 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
2179 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002180 if (error)
2181 goto out_free_port_info;
2182
Eric Moore2ecce492007-01-29 09:47:08 -07002183 *handle = ex->phy_info[0].handle;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002184
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002185 mutex_lock(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07002186 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
2187 if (!port_info) {
2188 port_info = ex;
2189 list_add_tail(&port_info->list, &ioc->sas_topology);
2190 } else {
Eric Moore2ecce492007-01-29 09:47:08 -07002191 for (i = 0; i < ex->num_phys; i++) {
2192 port_info->phy_info[i].handle =
2193 ex->phy_info[i].handle;
2194 port_info->phy_info[i].port_id =
2195 ex->phy_info[i].port_id;
2196 }
Eric Moore547f9a22006-06-27 14:42:12 -06002197 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002198 kfree(ex);
2199 ex = NULL;
2200 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002201 mutex_unlock(&ioc->sas_topology_mutex);
2202
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002203 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002204 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
2205 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
2206 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
2207
2208 if (port_info->phy_info[i].identify.handle) {
2209 mptsas_sas_device_pg0(ioc,
2210 &port_info->phy_info[i].identify,
2211 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2212 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2213 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02002214 port_info->phy_info[i].identify.phy_id =
2215 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002216 }
2217
2218 if (port_info->phy_info[i].attached.handle) {
2219 mptsas_sas_device_pg0(ioc,
2220 &port_info->phy_info[i].attached,
2221 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2222 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2223 port_info->phy_info[i].attached.handle);
Moore, Ericdb9c9172006-03-14 09:14:18 -07002224 port_info->phy_info[i].attached.phy_id =
2225 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002226 }
Eric Moore547f9a22006-06-27 14:42:12 -06002227 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002228
Eric Moore547f9a22006-06-27 14:42:12 -06002229 parent = &ioc->sh->shost_gendev;
2230 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002231 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002232 list_for_each_entry(p, &ioc->sas_topology, list) {
2233 for (j = 0; j < p->num_phys; j++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002234 if (port_info->phy_info[i].identify.handle !=
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002235 p->phy_info[j].attached.handle)
Eric Moore547f9a22006-06-27 14:42:12 -06002236 continue;
2237 rphy = mptsas_get_rphy(&p->phy_info[j]);
2238 parent = &rphy->dev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002239 }
2240 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002241 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002242 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002243
Eric Moore547f9a22006-06-27 14:42:12 -06002244 mptsas_setup_wide_ports(ioc, port_info);
2245
2246 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02002247 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
Moore, Erice6b2d762006-03-14 09:14:24 -07002248 ioc->sas_index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002249
2250 return 0;
2251
2252 out_free_port_info:
Moore, Erice6b2d762006-03-14 09:14:24 -07002253 if (ex) {
Eric Moore547f9a22006-06-27 14:42:12 -06002254 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002255 kfree(ex);
2256 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002257 out:
2258 return error;
2259}
2260
Moore, Erice6b2d762006-03-14 09:14:24 -07002261/*
2262 * mptsas_delete_expander_phys
2263 *
2264 *
2265 * This will traverse topology, and remove expanders
2266 * that are no longer present
2267 */
2268static void
2269mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
2270{
2271 struct mptsas_portinfo buffer;
2272 struct mptsas_portinfo *port_info, *n, *parent;
Eric Moore547f9a22006-06-27 14:42:12 -06002273 struct mptsas_phyinfo *phy_info;
Eric Moore547f9a22006-06-27 14:42:12 -06002274 struct sas_port * port;
Moore, Erice6b2d762006-03-14 09:14:24 -07002275 int i;
Eric Moore547f9a22006-06-27 14:42:12 -06002276 u64 expander_sas_address;
Moore, Erice6b2d762006-03-14 09:14:24 -07002277
2278 mutex_lock(&ioc->sas_topology_mutex);
2279 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
2280
Alan Coxd58069a2009-04-01 15:00:29 +01002281 if (!(port_info->phy_info[0].identify.device_info &
2282 MPI_SAS_DEVICE_INFO_SMP_TARGET))
Moore, Erice6b2d762006-03-14 09:14:24 -07002283 continue;
2284
2285 if (mptsas_sas_expander_pg0(ioc, &buffer,
2286 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
Eric Moore2ecce492007-01-29 09:47:08 -07002287 MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
2288 port_info->phy_info[0].handle)) {
Moore, Erice6b2d762006-03-14 09:14:24 -07002289
2290 /*
2291 * Obtain the port_info instance to the parent port
2292 */
2293 parent = mptsas_find_portinfo_by_handle(ioc,
2294 port_info->phy_info[0].identify.handle_parent);
2295
2296 if (!parent)
2297 goto next_port;
2298
Eric Moore547f9a22006-06-27 14:42:12 -06002299 expander_sas_address =
2300 port_info->phy_info[0].identify.sas_address;
2301
Moore, Erice6b2d762006-03-14 09:14:24 -07002302 /*
2303 * Delete rphys in the parent that point
2304 * to this expander. The transport layer will
2305 * cleanup all the children.
2306 */
Eric Moore547f9a22006-06-27 14:42:12 -06002307 phy_info = parent->phy_info;
2308 for (i = 0; i < parent->num_phys; i++, phy_info++) {
2309 port = mptsas_get_port(phy_info);
2310 if (!port)
Moore, Erice6b2d762006-03-14 09:14:24 -07002311 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06002312 if (phy_info->attached.sas_address !=
2313 expander_sas_address)
2314 continue;
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302315 dsaswideprintk(ioc,
Eric Moorec51d0be2007-09-29 10:17:21 -06002316 dev_printk(KERN_DEBUG, &port->dev,
2317 MYIOC_s_FMT "delete port (%d)\n", ioc->name,
2318 port->port_identifier));
Eric Moore547f9a22006-06-27 14:42:12 -06002319 sas_port_delete(port);
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302320 mptsas_port_delete(ioc, phy_info->port_details);
Moore, Erice6b2d762006-03-14 09:14:24 -07002321 }
2322 next_port:
Eric Moore547f9a22006-06-27 14:42:12 -06002323
2324 phy_info = port_info->phy_info;
2325 for (i = 0; i < port_info->num_phys; i++, phy_info++)
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302326 mptsas_port_delete(ioc, phy_info->port_details);
Eric Moore547f9a22006-06-27 14:42:12 -06002327
Moore, Erice6b2d762006-03-14 09:14:24 -07002328 list_del(&port_info->list);
Eric Moore547f9a22006-06-27 14:42:12 -06002329 kfree(port_info->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002330 kfree(port_info);
2331 }
2332 /*
2333 * Free this memory allocated from inside
2334 * mptsas_sas_expander_pg0
2335 */
Eric Moore547f9a22006-06-27 14:42:12 -06002336 kfree(buffer.phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002337 }
2338 mutex_unlock(&ioc->sas_topology_mutex);
2339}
2340
2341/*
2342 * Start of day discovery
2343 */
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002344static void
2345mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
2346{
2347 u32 handle = 0xFFFF;
Moore, Ericf44e5462006-03-14 09:14:21 -07002348 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002349
Moore, Erice6b2d762006-03-14 09:14:24 -07002350 mutex_lock(&ioc->sas_discovery_mutex);
2351 mptsas_probe_hba_phys(ioc);
2352 while (!mptsas_probe_expander_phys(ioc, &handle))
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002353 ;
Moore, Ericf44e5462006-03-14 09:14:21 -07002354 /*
2355 Reporting RAID volumes.
2356 */
Eric Mooreb506ade2007-01-29 09:45:37 -07002357 if (!ioc->ir_firmware)
2358 goto out;
Moore, Ericf44e5462006-03-14 09:14:21 -07002359 if (!ioc->raid_data.pIocPg2)
2360 goto out;
2361 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
2362 goto out;
Eric Moore793955f2007-01-29 09:42:20 -07002363 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
James Bottomleye8bf3942006-07-11 17:49:34 -04002364 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
Moore, Ericf44e5462006-03-14 09:14:21 -07002365 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
2366 }
2367 out:
Moore, Erice6b2d762006-03-14 09:14:24 -07002368 mutex_unlock(&ioc->sas_discovery_mutex);
2369}
2370
2371/*
2372 * Work queue thread to handle Runtime discovery
2373 * Mere purpose is the hot add/delete of expanders
Eric Moore547f9a22006-06-27 14:42:12 -06002374 *(Mutex UNLOCKED)
Moore, Erice6b2d762006-03-14 09:14:24 -07002375 */
2376static void
Eric Moore547f9a22006-06-27 14:42:12 -06002377__mptsas_discovery_work(MPT_ADAPTER *ioc)
Moore, Erice6b2d762006-03-14 09:14:24 -07002378{
Moore, Erice6b2d762006-03-14 09:14:24 -07002379 u32 handle = 0xFFFF;
2380
Moore, Erice6b2d762006-03-14 09:14:24 -07002381 ioc->sas_discovery_runtime=1;
2382 mptsas_delete_expander_phys(ioc);
2383 mptsas_probe_hba_phys(ioc);
2384 while (!mptsas_probe_expander_phys(ioc, &handle))
2385 ;
Moore, Erice6b2d762006-03-14 09:14:24 -07002386 ioc->sas_discovery_runtime=0;
Eric Moore547f9a22006-06-27 14:42:12 -06002387}
2388
2389/*
2390 * Work queue thread to handle Runtime discovery
2391 * Mere purpose is the hot add/delete of expanders
2392 *(Mutex LOCKED)
2393 */
2394static void
David Howellsc4028952006-11-22 14:57:56 +00002395mptsas_discovery_work(struct work_struct *work)
Eric Moore547f9a22006-06-27 14:42:12 -06002396{
David Howellsc4028952006-11-22 14:57:56 +00002397 struct mptsas_discovery_event *ev =
2398 container_of(work, struct mptsas_discovery_event, work);
Eric Moore547f9a22006-06-27 14:42:12 -06002399 MPT_ADAPTER *ioc = ev->ioc;
2400
2401 mutex_lock(&ioc->sas_discovery_mutex);
2402 __mptsas_discovery_work(ioc);
Moore, Erice6b2d762006-03-14 09:14:24 -07002403 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002404 kfree(ev);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002405}
2406
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002407static struct mptsas_phyinfo *
Eric Moore547f9a22006-06-27 14:42:12 -06002408mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002409{
2410 struct mptsas_portinfo *port_info;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002411 struct mptsas_phyinfo *phy_info = NULL;
Eric Moore547f9a22006-06-27 14:42:12 -06002412 int i;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002413
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002414 mutex_lock(&ioc->sas_topology_mutex);
2415 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2416 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002417 if (!mptsas_is_end_device(
2418 &port_info->phy_info[i].attached))
2419 continue;
Eric Mooreb506ade2007-01-29 09:45:37 -07002420 if (port_info->phy_info[i].attached.sas_address
2421 != sas_address)
2422 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06002423 phy_info = &port_info->phy_info[i];
2424 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002425 }
2426 }
2427 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002428 return phy_info;
2429}
2430
2431static struct mptsas_phyinfo *
Eric Mooreb506ade2007-01-29 09:45:37 -07002432mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002433{
2434 struct mptsas_portinfo *port_info;
2435 struct mptsas_phyinfo *phy_info = NULL;
2436 int i;
2437
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002438 mutex_lock(&ioc->sas_topology_mutex);
2439 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -06002440 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002441 if (!mptsas_is_end_device(
2442 &port_info->phy_info[i].attached))
2443 continue;
Eric Mooreb506ade2007-01-29 09:45:37 -07002444 if (port_info->phy_info[i].attached.id != id)
2445 continue;
2446 if (port_info->phy_info[i].attached.channel != channel)
2447 continue;
2448 phy_info = &port_info->phy_info[i];
2449 break;
2450 }
2451 }
2452 mutex_unlock(&ioc->sas_topology_mutex);
2453 return phy_info;
2454}
2455
2456static struct mptsas_phyinfo *
2457mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2458{
2459 struct mptsas_portinfo *port_info;
2460 struct mptsas_phyinfo *phy_info = NULL;
2461 int i;
2462
2463 mutex_lock(&ioc->sas_topology_mutex);
2464 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2465 for (i = 0; i < port_info->num_phys; i++) {
2466 if (!mptsas_is_end_device(
2467 &port_info->phy_info[i].attached))
2468 continue;
2469 if (port_info->phy_info[i].attached.phys_disk_num == ~0)
2470 continue;
2471 if (port_info->phy_info[i].attached.phys_disk_num != id)
2472 continue;
2473 if (port_info->phy_info[i].attached.channel != channel)
2474 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06002475 phy_info = &port_info->phy_info[i];
2476 break;
2477 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002478 }
2479 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002480 return phy_info;
2481}
2482
Moore, Eric4b766472006-03-14 09:14:12 -07002483/*
2484 * Work queue thread to clear the persitency table
2485 */
2486static void
David Howellsc4028952006-11-22 14:57:56 +00002487mptsas_persist_clear_table(struct work_struct *work)
Moore, Eric4b766472006-03-14 09:14:12 -07002488{
David Howellsc4028952006-11-22 14:57:56 +00002489 MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002490
2491 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2492}
2493
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002494static void
Moore, Ericf44e5462006-03-14 09:14:21 -07002495mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2496{
Eric Mooref99be432007-01-04 20:46:54 -07002497 int rc;
2498
Moore, Ericf44e5462006-03-14 09:14:21 -07002499 sdev->no_uld_attach = data ? 1 : 0;
Eric Mooref99be432007-01-04 20:46:54 -07002500 rc = scsi_device_reprobe(sdev);
Moore, Ericf44e5462006-03-14 09:14:21 -07002501}
2502
2503static void
2504mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2505{
2506 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2507 mptsas_reprobe_lun);
2508}
2509
Eric Mooreb506ade2007-01-29 09:45:37 -07002510static void
2511mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
2512{
2513 CONFIGPARMS cfg;
2514 ConfigPageHeader_t hdr;
2515 dma_addr_t dma_handle;
2516 pRaidVolumePage0_t buffer = NULL;
2517 RaidPhysDiskPage0_t phys_disk;
2518 int i;
2519 struct mptsas_hotplug_event *ev;
2520
2521 memset(&cfg, 0 , sizeof(CONFIGPARMS));
2522 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
2523 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
2524 cfg.pageAddr = (channel << 8) + id;
2525 cfg.cfghdr.hdr = &hdr;
2526 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2527
2528 if (mpt_config(ioc, &cfg) != 0)
2529 goto out;
2530
2531 if (!hdr.PageLength)
2532 goto out;
2533
2534 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
2535 &dma_handle);
2536
2537 if (!buffer)
2538 goto out;
2539
2540 cfg.physAddr = dma_handle;
2541 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2542
2543 if (mpt_config(ioc, &cfg) != 0)
2544 goto out;
2545
2546 if (!(buffer->VolumeStatus.Flags &
2547 MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
2548 goto out;
2549
2550 if (!buffer->NumPhysDisks)
2551 goto out;
2552
2553 for (i = 0; i < buffer->NumPhysDisks; i++) {
2554
2555 if (mpt_raid_phys_disk_pg0(ioc,
2556 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
2557 continue;
2558
2559 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
2560 if (!ev) {
Eric Moore29dd3602007-09-14 18:46:51 -06002561 printk(MYIOC_s_WARN_FMT "mptsas: lost hotplug event\n", ioc->name);
Eric Mooreb506ade2007-01-29 09:45:37 -07002562 goto out;
2563 }
2564
2565 INIT_WORK(&ev->work, mptsas_hotplug_work);
2566 ev->ioc = ioc;
2567 ev->id = phys_disk.PhysDiskID;
2568 ev->channel = phys_disk.PhysDiskBus;
2569 ev->phys_disk_num_valid = 1;
2570 ev->phys_disk_num = phys_disk.PhysDiskNum;
2571 ev->event_type = MPTSAS_ADD_DEVICE;
2572 schedule_work(&ev->work);
2573 }
2574
2575 out:
2576 if (buffer)
2577 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
2578 dma_handle);
2579}
Moore, Erice6b2d762006-03-14 09:14:24 -07002580/*
2581 * Work queue thread to handle SAS hotplug events
2582 */
Moore, Ericf44e5462006-03-14 09:14:21 -07002583static void
David Howellsc4028952006-11-22 14:57:56 +00002584mptsas_hotplug_work(struct work_struct *work)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002585{
David Howellsc4028952006-11-22 14:57:56 +00002586 struct mptsas_hotplug_event *ev =
2587 container_of(work, struct mptsas_hotplug_event, work);
Eric Mooreb506ade2007-01-29 09:45:37 -07002588
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002589 MPT_ADAPTER *ioc = ev->ioc;
2590 struct mptsas_phyinfo *phy_info;
2591 struct sas_rphy *rphy;
Eric Moore547f9a22006-06-27 14:42:12 -06002592 struct sas_port *port;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002593 struct scsi_device *sdev;
Eric Moore547f9a22006-06-27 14:42:12 -06002594 struct scsi_target * starget;
James Bottomleyf013db32006-03-18 14:54:36 -06002595 struct sas_identify identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002596 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002597 struct mptsas_devinfo sas_device;
Moore, Ericf44e5462006-03-14 09:14:21 -07002598 VirtTarget *vtarget;
Eric Moore547f9a22006-06-27 14:42:12 -06002599 VirtDevice *vdevice;
2600
Moore, Erice6b2d762006-03-14 09:14:24 -07002601 mutex_lock(&ioc->sas_discovery_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002602 switch (ev->event_type) {
2603 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002604
Eric Mooreb506ade2007-01-29 09:45:37 -07002605 phy_info = NULL;
2606 if (ev->phys_disk_num_valid) {
2607 if (ev->hidden_raid_component){
2608 if (mptsas_sas_device_pg0(ioc, &sas_device,
2609 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
2610 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2611 (ev->channel << 8) + ev->id)) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302612 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Mooreb506ade2007-01-29 09:45:37 -07002613 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002614 __func__, __LINE__));
Eric Mooreb506ade2007-01-29 09:45:37 -07002615 break;
2616 }
2617 phy_info = mptsas_find_phyinfo_by_sas_address(
2618 ioc, sas_device.sas_address);
2619 }else
2620 phy_info = mptsas_find_phyinfo_by_phys_disk_num(
2621 ioc, ev->channel, ev->phys_disk_num);
2622 }
2623
2624 if (!phy_info)
2625 phy_info = mptsas_find_phyinfo_by_target(ioc,
2626 ev->channel, ev->id);
Moore, Erice6b2d762006-03-14 09:14:24 -07002627
Moore, Ericf44e5462006-03-14 09:14:21 -07002628 /*
2629 * Sanity checks, for non-existing phys and remote rphys.
2630 */
Eric Mooreb506ade2007-01-29 09:45:37 -07002631 if (!phy_info){
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302632 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Mooreb506ade2007-01-29 09:45:37 -07002633 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002634 __func__, __LINE__));
Eric Mooreb506ade2007-01-29 09:45:37 -07002635 break;
2636 }
2637 if (!phy_info->port_details) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302638 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002639 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002640 __func__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002641 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002642 }
2643 rphy = mptsas_get_rphy(phy_info);
2644 if (!rphy) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302645 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002646 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002647 __func__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002648 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002649 }
Eric Mooreb506ade2007-01-29 09:45:37 -07002650
Eric Moore547f9a22006-06-27 14:42:12 -06002651 port = mptsas_get_port(phy_info);
2652 if (!port) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302653 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002654 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002655 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002656 break;
2657 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002658
Eric Moore547f9a22006-06-27 14:42:12 -06002659 starget = mptsas_get_starget(phy_info);
2660 if (starget) {
2661 vtarget = starget->hostdata;
2662
2663 if (!vtarget) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302664 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002665 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002666 __func__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002667 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002668 }
2669
Moore, Ericf44e5462006-03-14 09:14:21 -07002670 /*
2671 * Handling RAID components
2672 */
Eric Mooreb506ade2007-01-29 09:45:37 -07002673 if (ev->phys_disk_num_valid &&
2674 ev->hidden_raid_component) {
2675 printk(MYIOC_s_INFO_FMT
2676 "RAID Hidding: channel=%d, id=%d, "
2677 "physdsk %d \n", ioc->name, ev->channel,
2678 ev->id, ev->phys_disk_num);
Eric Moore793955f2007-01-29 09:42:20 -07002679 vtarget->id = ev->phys_disk_num;
Eric Mooreb506ade2007-01-29 09:45:37 -07002680 vtarget->tflags |=
2681 MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore547f9a22006-06-27 14:42:12 -06002682 mptsas_reprobe_target(starget, 1);
Eric Mooreb506ade2007-01-29 09:45:37 -07002683 phy_info->attached.phys_disk_num =
2684 ev->phys_disk_num;
2685 break;
Moore, Ericf44e5462006-03-14 09:14:21 -07002686 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002687 }
2688
Eric Mooreb506ade2007-01-29 09:45:37 -07002689 if (phy_info->attached.device_info &
2690 MPI_SAS_DEVICE_INFO_SSP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002691 ds = "ssp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002692 if (phy_info->attached.device_info &
2693 MPI_SAS_DEVICE_INFO_STP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002694 ds = "stp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002695 if (phy_info->attached.device_info &
2696 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002697 ds = "sata";
2698
2699 printk(MYIOC_s_INFO_FMT
2700 "removing %s device, channel %d, id %d, phy %d\n",
2701 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
Eric Moorec51d0be2007-09-29 10:17:21 -06002702 dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
Eric Moore29dd3602007-09-14 18:46:51 -06002703 "delete port (%d)\n", ioc->name, port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06002704 sas_port_delete(port);
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302705 mptsas_port_delete(ioc, phy_info->port_details);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002706 break;
2707 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002708
Moore, Ericbd23e942006-04-17 12:43:04 -06002709 if (ev->phys_disk_num_valid)
2710 mpt_findImVolumes(ioc);
2711
Moore, Ericc73787ee2006-01-26 16:20:06 -07002712 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01002713 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07002714 */
Christoph Hellwige3094442006-02-16 13:25:36 +01002715 if (mptsas_sas_device_pg0(ioc, &sas_device,
2716 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
Eric Mooreb506ade2007-01-29 09:45:37 -07002717 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2718 (ev->channel << 8) + ev->id)) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302719 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002720 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002721 __func__, __LINE__));
Christoph Hellwige3094442006-02-16 13:25:36 +01002722 break;
Moore, Erice6b2d762006-03-14 09:14:24 -07002723 }
2724
Eric Moore547f9a22006-06-27 14:42:12 -06002725 __mptsas_discovery_work(ioc);
Moore, Ericf44e5462006-03-14 09:14:21 -07002726
Eric Moore547f9a22006-06-27 14:42:12 -06002727 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2728 sas_device.sas_address);
2729
2730 if (!phy_info || !phy_info->port_details) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302731 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002732 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002733 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002734 break;
2735 }
2736
2737 starget = mptsas_get_starget(phy_info);
Eric Mooreb506ade2007-01-29 09:45:37 -07002738 if (starget && (!ev->hidden_raid_component)){
2739
Eric Moore547f9a22006-06-27 14:42:12 -06002740 vtarget = starget->hostdata;
2741
2742 if (!vtarget) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302743 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore29dd3602007-09-14 18:46:51 -06002744 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002745 __func__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002746 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002747 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002748 /*
2749 * Handling RAID components
2750 */
2751 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
Eric Mooreb506ade2007-01-29 09:45:37 -07002752 printk(MYIOC_s_INFO_FMT
2753 "RAID Exposing: channel=%d, id=%d, "
2754 "physdsk %d \n", ioc->name, ev->channel,
2755 ev->id, ev->phys_disk_num);
2756 vtarget->tflags &=
2757 ~MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore793955f2007-01-29 09:42:20 -07002758 vtarget->id = ev->id;
Eric Moore547f9a22006-06-27 14:42:12 -06002759 mptsas_reprobe_target(starget, 0);
Eric Mooreb506ade2007-01-29 09:45:37 -07002760 phy_info->attached.phys_disk_num = ~0;
Moore, Ericf44e5462006-03-14 09:14:21 -07002761 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002762 break;
2763 }
2764
Eric Moore547f9a22006-06-27 14:42:12 -06002765 if (mptsas_get_rphy(phy_info)) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302766 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002767 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002768 __func__, __LINE__));
Eric Mooreb506ade2007-01-29 09:45:37 -07002769 if (ev->channel) printk("%d\n", __LINE__);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002770 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002771 }
Eric Mooreb506ade2007-01-29 09:45:37 -07002772
Eric Moore547f9a22006-06-27 14:42:12 -06002773 port = mptsas_get_port(phy_info);
2774 if (!port) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302775 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002776 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002777 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002778 break;
2779 }
Christoph Hellwige3094442006-02-16 13:25:36 +01002780 memcpy(&phy_info->attached, &sas_device,
2781 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002782
Eric Mooreb506ade2007-01-29 09:45:37 -07002783 if (phy_info->attached.device_info &
2784 MPI_SAS_DEVICE_INFO_SSP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002785 ds = "ssp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002786 if (phy_info->attached.device_info &
2787 MPI_SAS_DEVICE_INFO_STP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002788 ds = "stp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002789 if (phy_info->attached.device_info &
2790 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002791 ds = "sata";
2792
2793 printk(MYIOC_s_INFO_FMT
2794 "attaching %s device, channel %d, id %d, phy %d\n",
2795 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2796
James Bottomleyf013db32006-03-18 14:54:36 -06002797 mptsas_parse_device_info(&identify, &phy_info->attached);
Eric Moore547f9a22006-06-27 14:42:12 -06002798 rphy = sas_end_device_alloc(port);
2799 if (!rphy) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302800 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002801 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002802 __func__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002803 break; /* non-fatal: an rphy can be added later */
Eric Moore547f9a22006-06-27 14:42:12 -06002804 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002805
James Bottomleyf013db32006-03-18 14:54:36 -06002806 rphy->identify = identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002807 if (sas_rphy_add(rphy)) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302808 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002809 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002810 __func__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002811 sas_rphy_free(rphy);
2812 break;
2813 }
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302814 mptsas_set_rphy(ioc, phy_info, rphy);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002815 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002816 case MPTSAS_ADD_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002817 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2818 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002819 if (sdev) {
2820 scsi_device_put(sdev);
2821 break;
2822 }
2823 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002824 "attaching raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002825 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2826 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002827 mpt_findImVolumes(ioc);
2828 break;
2829 case MPTSAS_DEL_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002830 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
Eric Mooreb506ade2007-01-29 09:45:37 -07002831 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002832 if (!sdev)
2833 break;
2834 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002835 "removing raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002836 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
Eric Mooreb506ade2007-01-29 09:45:37 -07002837 vdevice = sdev->hostdata;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002838 scsi_remove_device(sdev);
2839 scsi_device_put(sdev);
2840 mpt_findImVolumes(ioc);
2841 break;
Eric Mooreb506ade2007-01-29 09:45:37 -07002842 case MPTSAS_ADD_INACTIVE_VOLUME:
2843 mptsas_adding_inactive_raid_components(ioc,
2844 ev->channel, ev->id);
2845 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002846 case MPTSAS_IGNORE_EVENT:
2847 default:
2848 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002849 }
2850
Moore, Erice6b2d762006-03-14 09:14:24 -07002851 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002852 kfree(ev);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002853}
2854
2855static void
Eric Moore547f9a22006-06-27 14:42:12 -06002856mptsas_send_sas_event(MPT_ADAPTER *ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002857 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2858{
2859 struct mptsas_hotplug_event *ev;
2860 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2861 __le64 sas_address;
2862
2863 if ((device_info &
2864 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2865 MPI_SAS_DEVICE_INFO_STP_TARGET |
2866 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2867 return;
2868
Moore, Eric4b766472006-03-14 09:14:12 -07002869 switch (sas_event_data->ReasonCode) {
Moore, Eric4b766472006-03-14 09:14:12 -07002870 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
Eric Mooredf9e0622007-01-29 09:46:21 -07002871
2872 mptsas_target_reset_queue(ioc, sas_event_data);
2873 break;
2874
2875 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
Eric Moore547f9a22006-06-27 14:42:12 -06002876 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Eric4b766472006-03-14 09:14:12 -07002877 if (!ev) {
Eric Moore29dd3602007-09-14 18:46:51 -06002878 printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
Moore, Eric4b766472006-03-14 09:14:12 -07002879 break;
2880 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002881
David Howellsc4028952006-11-22 14:57:56 +00002882 INIT_WORK(&ev->work, mptsas_hotplug_work);
Moore, Eric4b766472006-03-14 09:14:12 -07002883 ev->ioc = ioc;
2884 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2885 ev->parent_handle =
2886 le16_to_cpu(sas_event_data->ParentDevHandle);
2887 ev->channel = sas_event_data->Bus;
2888 ev->id = sas_event_data->TargetID;
2889 ev->phy_id = sas_event_data->PhyNum;
2890 memcpy(&sas_address, &sas_event_data->SASAddress,
2891 sizeof(__le64));
2892 ev->sas_address = le64_to_cpu(sas_address);
2893 ev->device_info = device_info;
2894
2895 if (sas_event_data->ReasonCode &
2896 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2897 ev->event_type = MPTSAS_ADD_DEVICE;
2898 else
2899 ev->event_type = MPTSAS_DEL_DEVICE;
2900 schedule_work(&ev->work);
2901 break;
2902 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2903 /*
2904 * Persistent table is full.
2905 */
Eric Moore547f9a22006-06-27 14:42:12 -06002906 INIT_WORK(&ioc->sas_persist_task,
David Howellsc4028952006-11-22 14:57:56 +00002907 mptsas_persist_clear_table);
Eric Moore547f9a22006-06-27 14:42:12 -06002908 schedule_work(&ioc->sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002909 break;
Eric Mooreb506ade2007-01-29 09:45:37 -07002910 /*
2911 * TODO, handle other events
2912 */
Moore, Eric4b766472006-03-14 09:14:12 -07002913 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
Eric Mooreb506ade2007-01-29 09:45:37 -07002914 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
Moore, Eric4b766472006-03-14 09:14:12 -07002915 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
Eric Mooreb506ade2007-01-29 09:45:37 -07002916 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
2917 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
2918 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
2919 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
Moore, Eric4b766472006-03-14 09:14:12 -07002920 default:
2921 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002922 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002923}
Moore, Ericc73787ee2006-01-26 16:20:06 -07002924static void
Eric Moore547f9a22006-06-27 14:42:12 -06002925mptsas_send_raid_event(MPT_ADAPTER *ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002926 EVENT_DATA_RAID *raid_event_data)
2927{
2928 struct mptsas_hotplug_event *ev;
Moore, Ericbd23e942006-04-17 12:43:04 -06002929 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2930 int state = (status >> 8) & 0xff;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002931
2932 if (ioc->bus_type != SAS)
2933 return;
2934
Eric Moore547f9a22006-06-27 14:42:12 -06002935 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002936 if (!ev) {
Eric Moore29dd3602007-09-14 18:46:51 -06002937 printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002938 return;
2939 }
2940
David Howellsc4028952006-11-22 14:57:56 +00002941 INIT_WORK(&ev->work, mptsas_hotplug_work);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002942 ev->ioc = ioc;
2943 ev->id = raid_event_data->VolumeID;
Eric Mooreb506ade2007-01-29 09:45:37 -07002944 ev->channel = raid_event_data->VolumeBus;
Moore, Ericbd23e942006-04-17 12:43:04 -06002945 ev->event_type = MPTSAS_IGNORE_EVENT;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002946
2947 switch (raid_event_data->ReasonCode) {
2948 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
Eric Mooreb506ade2007-01-29 09:45:37 -07002949 ev->phys_disk_num_valid = 1;
2950 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002951 ev->event_type = MPTSAS_ADD_DEVICE;
2952 break;
2953 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
Moore, Ericf44e5462006-03-14 09:14:21 -07002954 ev->phys_disk_num_valid = 1;
2955 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Eric Mooreb506ade2007-01-29 09:45:37 -07002956 ev->hidden_raid_component = 1;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002957 ev->event_type = MPTSAS_DEL_DEVICE;
2958 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002959 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2960 switch (state) {
2961 case MPI_PD_STATE_ONLINE:
Eric Mooreb506ade2007-01-29 09:45:37 -07002962 case MPI_PD_STATE_NOT_COMPATIBLE:
Moore, Ericbd23e942006-04-17 12:43:04 -06002963 ev->phys_disk_num_valid = 1;
2964 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Eric Mooreb506ade2007-01-29 09:45:37 -07002965 ev->hidden_raid_component = 1;
Moore, Ericbd23e942006-04-17 12:43:04 -06002966 ev->event_type = MPTSAS_ADD_DEVICE;
2967 break;
2968 case MPI_PD_STATE_MISSING:
Moore, Ericbd23e942006-04-17 12:43:04 -06002969 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2970 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2971 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
Eric Mooreb506ade2007-01-29 09:45:37 -07002972 ev->phys_disk_num_valid = 1;
2973 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericbd23e942006-04-17 12:43:04 -06002974 ev->event_type = MPTSAS_DEL_DEVICE;
2975 break;
2976 default:
2977 break;
2978 }
2979 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002980 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2981 ev->event_type = MPTSAS_DEL_RAID;
2982 break;
2983 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2984 ev->event_type = MPTSAS_ADD_RAID;
2985 break;
2986 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
Moore, Ericbd23e942006-04-17 12:43:04 -06002987 switch (state) {
2988 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2989 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2990 ev->event_type = MPTSAS_DEL_RAID;
2991 break;
2992 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
2993 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
2994 ev->event_type = MPTSAS_ADD_RAID;
2995 break;
2996 default:
2997 break;
2998 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002999 break;
3000 default:
3001 break;
3002 }
3003 schedule_work(&ev->work);
3004}
3005
Moore, Erice6b2d762006-03-14 09:14:24 -07003006static void
Eric Moore547f9a22006-06-27 14:42:12 -06003007mptsas_send_discovery_event(MPT_ADAPTER *ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07003008 EVENT_DATA_SAS_DISCOVERY *discovery_data)
3009{
3010 struct mptsas_discovery_event *ev;
3011
3012 /*
3013 * DiscoveryStatus
3014 *
3015 * This flag will be non-zero when firmware
3016 * kicks off discovery, and return to zero
3017 * once its completed.
3018 */
3019 if (discovery_data->DiscoveryStatus)
3020 return;
3021
Eric Moore547f9a22006-06-27 14:42:12 -06003022 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Erice6b2d762006-03-14 09:14:24 -07003023 if (!ev)
3024 return;
David Howellsc4028952006-11-22 14:57:56 +00003025 INIT_WORK(&ev->work, mptsas_discovery_work);
Moore, Erice6b2d762006-03-14 09:14:24 -07003026 ev->ioc = ioc;
3027 schedule_work(&ev->work);
3028};
3029
Eric Mooreb506ade2007-01-29 09:45:37 -07003030/*
3031 * mptsas_send_ir2_event - handle exposing hidden disk when
3032 * an inactive raid volume is added
3033 *
3034 * @ioc: Pointer to MPT_ADAPTER structure
3035 * @ir2_data
3036 *
3037 */
3038static void
3039mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data)
3040{
3041 struct mptsas_hotplug_event *ev;
3042
3043 if (ir2_data->ReasonCode !=
3044 MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED)
3045 return;
3046
3047 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
3048 if (!ev)
3049 return;
3050
3051 INIT_WORK(&ev->work, mptsas_hotplug_work);
3052 ev->ioc = ioc;
3053 ev->id = ir2_data->TargetID;
3054 ev->channel = ir2_data->Bus;
3055 ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
3056
3057 schedule_work(&ev->work);
3058};
Moore, Erice6b2d762006-03-14 09:14:24 -07003059
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003060static int
3061mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
3062{
Moore, Ericc73787ee2006-01-26 16:20:06 -07003063 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003064 u8 event = le32_to_cpu(reply->Event) & 0xFF;
3065
3066 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07003067 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003068
Moore, Erice6b2d762006-03-14 09:14:24 -07003069 /*
3070 * sas_discovery_ignore_events
3071 *
3072 * This flag is to prevent anymore processing of
3073 * sas events once mptsas_remove function is called.
3074 */
3075 if (ioc->sas_discovery_ignore_events) {
3076 rc = mptscsih_event_process(ioc, reply);
3077 goto out;
3078 }
3079
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003080 switch (event) {
3081 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
Eric Moore547f9a22006-06-27 14:42:12 -06003082 mptsas_send_sas_event(ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003083 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07003084 break;
3085 case MPI_EVENT_INTEGRATED_RAID:
Eric Moore547f9a22006-06-27 14:42:12 -06003086 mptsas_send_raid_event(ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07003087 (EVENT_DATA_RAID *)reply->Data);
3088 break;
Moore, Eric79de2782006-01-25 18:05:15 -07003089 case MPI_EVENT_PERSISTENT_TABLE_FULL:
Eric Moore547f9a22006-06-27 14:42:12 -06003090 INIT_WORK(&ioc->sas_persist_task,
David Howellsc4028952006-11-22 14:57:56 +00003091 mptsas_persist_clear_table);
Eric Moore547f9a22006-06-27 14:42:12 -06003092 schedule_work(&ioc->sas_persist_task);
Moore, Eric79de2782006-01-25 18:05:15 -07003093 break;
Moore, Eric4b766472006-03-14 09:14:12 -07003094 case MPI_EVENT_SAS_DISCOVERY:
Eric Moore547f9a22006-06-27 14:42:12 -06003095 mptsas_send_discovery_event(ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07003096 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
3097 break;
Eric Mooreb506ade2007-01-29 09:45:37 -07003098 case MPI_EVENT_IR2:
3099 mptsas_send_ir2_event(ioc,
3100 (PTR_MPI_EVENT_DATA_IR2)reply->Data);
3101 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003102 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07003103 rc = mptscsih_event_process(ioc, reply);
3104 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003105 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07003106 out:
3107
3108 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003109}
3110
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003111static int
3112mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3113{
3114 struct Scsi_Host *sh;
3115 MPT_SCSI_HOST *hd;
3116 MPT_ADAPTER *ioc;
3117 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01003118 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003119 int numSGE = 0;
3120 int scale;
3121 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003122 int error=0;
3123 int r;
3124
3125 r = mpt_attach(pdev,id);
3126 if (r)
3127 return r;
3128
3129 ioc = pci_get_drvdata(pdev);
3130 ioc->DoneCtx = mptsasDoneCtx;
3131 ioc->TaskCtx = mptsasTaskCtx;
3132 ioc->InternalCtx = mptsasInternalCtx;
3133
3134 /* Added sanity check on readiness of the MPT adapter.
3135 */
3136 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
3137 printk(MYIOC_s_WARN_FMT
3138 "Skipping because it's not operational!\n",
3139 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003140 error = -ENODEV;
3141 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003142 }
3143
3144 if (!ioc->active) {
3145 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
3146 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003147 error = -ENODEV;
3148 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003149 }
3150
3151 /* Sanity check - ensure at least 1 port is INITIATOR capable
3152 */
3153 ioc_cap = 0;
3154 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
3155 if (ioc->pfacts[ii].ProtocolFlags &
3156 MPI_PORTFACTS_PROTOCOL_INITIATOR)
3157 ioc_cap++;
3158 }
3159
3160 if (!ioc_cap) {
3161 printk(MYIOC_s_WARN_FMT
3162 "Skipping ioc=%p because SCSI Initiator mode "
3163 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06003164 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003165 }
3166
3167 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
3168 if (!sh) {
3169 printk(MYIOC_s_WARN_FMT
3170 "Unable to register controller with SCSI subsystem\n",
3171 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003172 error = -1;
3173 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003174 }
3175
3176 spin_lock_irqsave(&ioc->FreeQlock, flags);
3177
3178 /* Attach the SCSI Host to the IOC structure
3179 */
3180 ioc->sh = sh;
3181
3182 sh->io_port = 0;
3183 sh->n_io_port = 0;
3184 sh->irq = 0;
3185
3186 /* set 16 byte cdb's */
3187 sh->max_cmd_len = 16;
3188
Eric Moore793955f2007-01-29 09:42:20 -07003189 sh->max_id = ioc->pfacts[0].PortSCSIID;
3190 sh->max_lun = max_lun;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003191
3192 sh->transportt = mptsas_transport_template;
3193
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003194 /* Required entry.
3195 */
3196 sh->unique_id = ioc->id;
3197
3198 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003199 mutex_init(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07003200 mutex_init(&ioc->sas_discovery_mutex);
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01003201 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02003202 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003203
3204 /* Verify that we won't exceed the maximum
3205 * number of chain buffers
3206 * We can optimize: ZZ = req_sz/sizeof(SGE)
3207 * For 32bit SGE's:
3208 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
3209 * + (req_sz - 64)/sizeof(SGE)
3210 * A slightly different algorithm is required for
3211 * 64bit SGEs.
3212 */
3213 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3214 if (sizeof(dma_addr_t) == sizeof(u64)) {
3215 numSGE = (scale - 1) *
3216 (ioc->facts.MaxChainDepth-1) + scale +
3217 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
3218 sizeof(u32));
3219 } else {
3220 numSGE = 1 + (scale - 1) *
3221 (ioc->facts.MaxChainDepth-1) + scale +
3222 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
3223 sizeof(u32));
3224 }
3225
3226 if (numSGE < sh->sg_tablesize) {
3227 /* Reset this value */
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05303228 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003229 "Resetting sg_tablesize to %d from %d\n",
3230 ioc->name, numSGE, sh->sg_tablesize));
3231 sh->sg_tablesize = numSGE;
3232 }
3233
Eric Mooree7eae9f2007-09-29 10:15:59 -06003234 hd = shost_priv(sh);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003235 hd->ioc = ioc;
3236
3237 /* SCSI needs scsi_cmnd lookup table!
3238 * (with size equal to req_depth*PtrSz!)
3239 */
Eric Mooree8206382007-09-29 10:16:53 -06003240 ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
3241 if (!ioc->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003242 error = -ENOMEM;
Eric Moorebc6e0892007-09-29 10:16:28 -06003243 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003244 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003245 }
Eric Mooree8206382007-09-29 10:16:53 -06003246 spin_lock_init(&ioc->scsi_lookup_lock);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003247
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05303248 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
Eric Mooree8206382007-09-29 10:16:53 -06003249 ioc->name, ioc->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003250
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003251 /* Clear the TM flags
3252 */
3253 hd->tmPending = 0;
3254 hd->tmState = TM_STATE_NONE;
3255 hd->resetPending = 0;
3256 hd->abortSCpnt = NULL;
3257
3258 /* Clear the pointer used to store
3259 * single-threaded commands, i.e., those
3260 * issued during a bus scan, dv and
3261 * configuration pages.
3262 */
3263 hd->cmdPtr = NULL;
3264
3265 /* Initialize this SCSI Hosts' timers
3266 * To use, set the timer expires field
3267 * and add_timer
3268 */
3269 init_timer(&hd->timer);
3270 hd->timer.data = (unsigned long) hd;
3271 hd->timer.function = mptscsih_timer_expired;
3272
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003273 ioc->sas_data.ptClear = mpt_pt_clear;
3274
Eric Mooredf9e0622007-01-29 09:46:21 -07003275 init_waitqueue_head(&hd->scandv_waitq);
3276 hd->scandv_wait_done = 0;
3277 hd->last_queue_full = 0;
3278 INIT_LIST_HEAD(&hd->target_reset_list);
3279 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3280
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003281 if (ioc->sas_data.ptClear==1) {
3282 mptbase_sas_persist_operation(
3283 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
3284 }
3285
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003286 error = scsi_add_host(sh, &ioc->pcidev->dev);
3287 if (error) {
Eric Moore29dd3602007-09-14 18:46:51 -06003288 dprintk(ioc, printk(MYIOC_s_ERR_FMT
3289 "scsi_add_host failed\n", ioc->name));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003290 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003291 }
3292
3293 mptsas_scan_sas_topology(ioc);
3294
3295 return 0;
3296
Eric Moore547f9a22006-06-27 14:42:12 -06003297 out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003298
3299 mptscsih_remove(pdev);
3300 return error;
3301}
3302
3303static void __devexit mptsas_remove(struct pci_dev *pdev)
3304{
3305 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
3306 struct mptsas_portinfo *p, *n;
Eric Moore547f9a22006-06-27 14:42:12 -06003307 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003308
Eric Mooreb506ade2007-01-29 09:45:37 -07003309 ioc->sas_discovery_ignore_events = 1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003310 sas_remove_host(ioc->sh);
3311
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003312 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003313 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
3314 list_del(&p->list);
Eric Moore547f9a22006-06-27 14:42:12 -06003315 for (i = 0 ; i < p->num_phys ; i++)
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05303316 mptsas_port_delete(ioc, p->phy_info[i].port_details);
Eric Moore547f9a22006-06-27 14:42:12 -06003317 kfree(p->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003318 kfree(p);
3319 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003320 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003321
3322 mptscsih_remove(pdev);
3323}
3324
3325static struct pci_device_id mptsas_pci_table[] = {
Eric Moore87cf8982006-06-27 16:09:26 -06003326 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003327 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003328 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003329 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003330 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003331 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003332 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003333 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003334 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003335 PCI_ANY_ID, PCI_ANY_ID },
3336 {0} /* Terminating entry */
3337};
3338MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
3339
3340
3341static struct pci_driver mptsas_driver = {
3342 .name = "mptsas",
3343 .id_table = mptsas_pci_table,
3344 .probe = mptsas_probe,
3345 .remove = __devexit_p(mptsas_remove),
3346 .shutdown = mptscsih_shutdown,
3347#ifdef CONFIG_PM
3348 .suspend = mptscsih_suspend,
3349 .resume = mptscsih_resume,
3350#endif
3351};
3352
3353static int __init
3354mptsas_init(void)
3355{
Prakash, Sathya57ce21b2007-07-02 17:04:10 +05303356 int error;
3357
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003358 show_mptmod_ver(my_NAME, my_VERSION);
3359
3360 mptsas_transport_template =
3361 sas_attach_transport(&mptsas_transport_functions);
3362 if (!mptsas_transport_template)
3363 return -ENODEV;
3364
3365 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
Eric Mooredf9e0622007-01-29 09:46:21 -07003366 mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003367 mptsasInternalCtx =
3368 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02003369 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003370
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05303371 mpt_event_register(mptsasDoneCtx, mptsas_event_process);
3372 mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003373
Prakash, Sathya57ce21b2007-07-02 17:04:10 +05303374 error = pci_register_driver(&mptsas_driver);
3375 if (error)
3376 sas_release_transport(mptsas_transport_template);
3377
3378 return error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003379}
3380
3381static void __exit
3382mptsas_exit(void)
3383{
3384 pci_unregister_driver(&mptsas_driver);
3385 sas_release_transport(mptsas_transport_template);
3386
3387 mpt_reset_deregister(mptsasDoneCtx);
3388 mpt_event_deregister(mptsasDoneCtx);
3389
Christoph Hellwigda4fa652005-10-19 20:01:42 +02003390 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003391 mpt_deregister(mptsasInternalCtx);
3392 mpt_deregister(mptsasTaskCtx);
3393 mpt_deregister(mptsasDoneCtx);
3394}
3395
3396module_init(mptsas_init);
3397module_exit(mptsas_exit);