blob: 79f5433359f9b3fc1b346cb78b5d11dcd60d15de [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 Heo5f49f632009-05-19 18:33:05 +09001360 req->resid_len = 0;
1361 rsp->resid_len -= smprep->ResponseDataLength;
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001362 } else {
Eric Moore29dd3602007-09-14 18:46:51 -06001363 printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07001364 ioc->name, __func__);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001365 ret = -ENXIO;
1366 }
1367unmap:
1368 if (dma_addr_out)
Tejun Heob0790412009-05-07 22:24:42 +09001369 pci_unmap_single(ioc->pcidev, dma_addr_out, blk_rq_bytes(req),
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001370 PCI_DMA_BIDIRECTIONAL);
1371 if (dma_addr_in)
Tejun Heob0790412009-05-07 22:24:42 +09001372 pci_unmap_single(ioc->pcidev, dma_addr_in, blk_rq_bytes(rsp),
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001373 PCI_DMA_BIDIRECTIONAL);
1374put_mf:
1375 if (mf)
1376 mpt_free_msg_frame(ioc, mf);
1377out_unlock:
1378 mutex_unlock(&ioc->sas_mgmt.mutex);
1379out:
1380 return ret;
1381}
1382
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001383static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +02001384 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +01001385 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1386 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001387 .phy_reset = mptsas_phy_reset,
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001388 .smp_handler = mptsas_smp_handler,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001389};
1390
1391static struct scsi_transport_template *mptsas_transport_template;
1392
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001393static int
1394mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1395{
1396 ConfigExtendedPageHeader_t hdr;
1397 CONFIGPARMS cfg;
1398 SasIOUnitPage0_t *buffer;
1399 dma_addr_t dma_handle;
1400 int error, i;
1401
1402 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1403 hdr.ExtPageLength = 0;
1404 hdr.PageNumber = 0;
1405 hdr.Reserved1 = 0;
1406 hdr.Reserved2 = 0;
1407 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1408 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1409
1410 cfg.cfghdr.ehdr = &hdr;
1411 cfg.physAddr = -1;
1412 cfg.pageAddr = 0;
1413 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1414 cfg.dir = 0; /* read */
1415 cfg.timeout = 10;
1416
1417 error = mpt_config(ioc, &cfg);
1418 if (error)
1419 goto out;
1420 if (!hdr.ExtPageLength) {
1421 error = -ENXIO;
1422 goto out;
1423 }
1424
1425 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1426 &dma_handle);
1427 if (!buffer) {
1428 error = -ENOMEM;
1429 goto out;
1430 }
1431
1432 cfg.physAddr = dma_handle;
1433 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1434
1435 error = mpt_config(ioc, &cfg);
1436 if (error)
1437 goto out_free_consistent;
1438
1439 port_info->num_phys = buffer->NumPhys;
1440 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001441 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001442 if (!port_info->phy_info) {
1443 error = -ENOMEM;
1444 goto out_free_consistent;
1445 }
1446
Prakash, Sathyaedb90682007-07-17 14:39:14 +05301447 ioc->nvdata_version_persistent =
1448 le16_to_cpu(buffer->NvdataVersionPersistent);
1449 ioc->nvdata_version_default =
1450 le16_to_cpu(buffer->NvdataVersionDefault);
1451
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001452 for (i = 0; i < port_info->num_phys; i++) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301453 mptsas_print_phy_data(ioc, &buffer->PhyData[i]);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001454 port_info->phy_info[i].phy_id = i;
1455 port_info->phy_info[i].port_id =
1456 buffer->PhyData[i].Port;
1457 port_info->phy_info[i].negotiated_link_rate =
1458 buffer->PhyData[i].NegotiatedLinkRate;
Eric Moore547f9a22006-06-27 14:42:12 -06001459 port_info->phy_info[i].portinfo = port_info;
Eric Moore2ecce492007-01-29 09:47:08 -07001460 port_info->phy_info[i].handle =
1461 le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001462 }
1463
1464 out_free_consistent:
1465 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1466 buffer, dma_handle);
1467 out:
1468 return error;
1469}
1470
1471static int
Prakash, Sathyaedb90682007-07-17 14:39:14 +05301472mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
1473{
1474 ConfigExtendedPageHeader_t hdr;
1475 CONFIGPARMS cfg;
1476 SasIOUnitPage1_t *buffer;
1477 dma_addr_t dma_handle;
1478 int error;
1479 u16 device_missing_delay;
1480
1481 memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
1482 memset(&cfg, 0, sizeof(CONFIGPARMS));
1483
1484 cfg.cfghdr.ehdr = &hdr;
1485 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1486 cfg.timeout = 10;
1487 cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1488 cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1489 cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
1490 cfg.cfghdr.ehdr->PageNumber = 1;
1491
1492 error = mpt_config(ioc, &cfg);
1493 if (error)
1494 goto out;
1495 if (!hdr.ExtPageLength) {
1496 error = -ENXIO;
1497 goto out;
1498 }
1499
1500 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1501 &dma_handle);
1502 if (!buffer) {
1503 error = -ENOMEM;
1504 goto out;
1505 }
1506
1507 cfg.physAddr = dma_handle;
1508 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1509
1510 error = mpt_config(ioc, &cfg);
1511 if (error)
1512 goto out_free_consistent;
1513
1514 ioc->io_missing_delay =
1515 le16_to_cpu(buffer->IODeviceMissingDelay);
1516 device_missing_delay = le16_to_cpu(buffer->ReportDeviceMissingDelay);
1517 ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ?
1518 (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 :
1519 device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
1520
1521 out_free_consistent:
1522 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1523 buffer, dma_handle);
1524 out:
1525 return error;
1526}
1527
1528static int
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001529mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1530 u32 form, u32 form_specific)
1531{
1532 ConfigExtendedPageHeader_t hdr;
1533 CONFIGPARMS cfg;
1534 SasPhyPage0_t *buffer;
1535 dma_addr_t dma_handle;
1536 int error;
1537
1538 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1539 hdr.ExtPageLength = 0;
1540 hdr.PageNumber = 0;
1541 hdr.Reserved1 = 0;
1542 hdr.Reserved2 = 0;
1543 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1544 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1545
1546 cfg.cfghdr.ehdr = &hdr;
1547 cfg.dir = 0; /* read */
1548 cfg.timeout = 10;
1549
1550 /* Get Phy Pg 0 for each Phy. */
1551 cfg.physAddr = -1;
1552 cfg.pageAddr = form + form_specific;
1553 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1554
1555 error = mpt_config(ioc, &cfg);
1556 if (error)
1557 goto out;
1558
1559 if (!hdr.ExtPageLength) {
1560 error = -ENXIO;
1561 goto out;
1562 }
1563
1564 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1565 &dma_handle);
1566 if (!buffer) {
1567 error = -ENOMEM;
1568 goto out;
1569 }
1570
1571 cfg.physAddr = dma_handle;
1572 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1573
1574 error = mpt_config(ioc, &cfg);
1575 if (error)
1576 goto out_free_consistent;
1577
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301578 mptsas_print_phy_pg0(ioc, buffer);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001579
1580 phy_info->hw_link_rate = buffer->HwLinkRate;
1581 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1582 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1583 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1584
1585 out_free_consistent:
1586 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1587 buffer, dma_handle);
1588 out:
1589 return error;
1590}
1591
1592static int
1593mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1594 u32 form, u32 form_specific)
1595{
1596 ConfigExtendedPageHeader_t hdr;
1597 CONFIGPARMS cfg;
1598 SasDevicePage0_t *buffer;
1599 dma_addr_t dma_handle;
1600 __le64 sas_address;
Moore, Ericbd23e942006-04-17 12:43:04 -06001601 int error=0;
1602
1603 if (ioc->sas_discovery_runtime &&
1604 mptsas_is_end_device(device_info))
1605 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001606
1607 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1608 hdr.ExtPageLength = 0;
1609 hdr.PageNumber = 0;
1610 hdr.Reserved1 = 0;
1611 hdr.Reserved2 = 0;
1612 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1613 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1614
1615 cfg.cfghdr.ehdr = &hdr;
1616 cfg.pageAddr = form + form_specific;
1617 cfg.physAddr = -1;
1618 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1619 cfg.dir = 0; /* read */
1620 cfg.timeout = 10;
1621
Moore, Ericdb9c9172006-03-14 09:14:18 -07001622 memset(device_info, 0, sizeof(struct mptsas_devinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001623 error = mpt_config(ioc, &cfg);
1624 if (error)
1625 goto out;
1626 if (!hdr.ExtPageLength) {
1627 error = -ENXIO;
1628 goto out;
1629 }
1630
1631 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1632 &dma_handle);
1633 if (!buffer) {
1634 error = -ENOMEM;
1635 goto out;
1636 }
1637
1638 cfg.physAddr = dma_handle;
1639 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1640
1641 error = mpt_config(ioc, &cfg);
1642 if (error)
1643 goto out_free_consistent;
1644
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301645 mptsas_print_device_pg0(ioc, buffer);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001646
1647 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001648 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +01001649 device_info->handle_enclosure =
1650 le16_to_cpu(buffer->EnclosureHandle);
1651 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001652 device_info->phy_id = buffer->PhyNum;
1653 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001654 device_info->id = buffer->TargetID;
Eric Mooreb506ade2007-01-29 09:45:37 -07001655 device_info->phys_disk_num = ~0;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001656 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001657 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1658 device_info->sas_address = le64_to_cpu(sas_address);
1659 device_info->device_info =
1660 le32_to_cpu(buffer->DeviceInfo);
1661
1662 out_free_consistent:
1663 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1664 buffer, dma_handle);
1665 out:
1666 return error;
1667}
1668
1669static int
1670mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1671 u32 form, u32 form_specific)
1672{
1673 ConfigExtendedPageHeader_t hdr;
1674 CONFIGPARMS cfg;
1675 SasExpanderPage0_t *buffer;
1676 dma_addr_t dma_handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001677 int i, error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001678
1679 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1680 hdr.ExtPageLength = 0;
1681 hdr.PageNumber = 0;
1682 hdr.Reserved1 = 0;
1683 hdr.Reserved2 = 0;
1684 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1685 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1686
1687 cfg.cfghdr.ehdr = &hdr;
1688 cfg.physAddr = -1;
1689 cfg.pageAddr = form + form_specific;
1690 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1691 cfg.dir = 0; /* read */
1692 cfg.timeout = 10;
1693
Moore, Ericdb9c9172006-03-14 09:14:18 -07001694 memset(port_info, 0, sizeof(struct mptsas_portinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001695 error = mpt_config(ioc, &cfg);
1696 if (error)
1697 goto out;
1698
1699 if (!hdr.ExtPageLength) {
1700 error = -ENXIO;
1701 goto out;
1702 }
1703
1704 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1705 &dma_handle);
1706 if (!buffer) {
1707 error = -ENOMEM;
1708 goto out;
1709 }
1710
1711 cfg.physAddr = dma_handle;
1712 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1713
1714 error = mpt_config(ioc, &cfg);
1715 if (error)
1716 goto out_free_consistent;
1717
Krzysztof Oledzki51f39ea2008-03-04 14:56:23 -08001718 if (!buffer->NumPhys) {
1719 error = -ENODEV;
1720 goto out_free_consistent;
1721 }
1722
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001723 /* save config data */
1724 port_info->num_phys = buffer->NumPhys;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001725 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001726 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001727 if (!port_info->phy_info) {
1728 error = -ENOMEM;
1729 goto out_free_consistent;
1730 }
1731
Eric Moore2ecce492007-01-29 09:47:08 -07001732 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06001733 port_info->phy_info[i].portinfo = port_info;
Eric Moore2ecce492007-01-29 09:47:08 -07001734 port_info->phy_info[i].handle =
1735 le16_to_cpu(buffer->DevHandle);
1736 }
Eric Moore547f9a22006-06-27 14:42:12 -06001737
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001738 out_free_consistent:
1739 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1740 buffer, dma_handle);
1741 out:
1742 return error;
1743}
1744
1745static int
1746mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1747 u32 form, u32 form_specific)
1748{
1749 ConfigExtendedPageHeader_t hdr;
1750 CONFIGPARMS cfg;
1751 SasExpanderPage1_t *buffer;
1752 dma_addr_t dma_handle;
Moore, Ericbd23e942006-04-17 12:43:04 -06001753 int error=0;
1754
1755 if (ioc->sas_discovery_runtime &&
1756 mptsas_is_end_device(&phy_info->attached))
1757 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001758
1759 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1760 hdr.ExtPageLength = 0;
1761 hdr.PageNumber = 1;
1762 hdr.Reserved1 = 0;
1763 hdr.Reserved2 = 0;
1764 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1765 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1766
1767 cfg.cfghdr.ehdr = &hdr;
1768 cfg.physAddr = -1;
1769 cfg.pageAddr = form + form_specific;
1770 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1771 cfg.dir = 0; /* read */
1772 cfg.timeout = 10;
1773
1774 error = mpt_config(ioc, &cfg);
1775 if (error)
1776 goto out;
1777
1778 if (!hdr.ExtPageLength) {
1779 error = -ENXIO;
1780 goto out;
1781 }
1782
1783 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1784 &dma_handle);
1785 if (!buffer) {
1786 error = -ENOMEM;
1787 goto out;
1788 }
1789
1790 cfg.physAddr = dma_handle;
1791 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1792
1793 error = mpt_config(ioc, &cfg);
1794 if (error)
1795 goto out_free_consistent;
1796
1797
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301798 mptsas_print_expander_pg1(ioc, buffer);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001799
1800 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001801 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001802 phy_info->port_id = buffer->PhysicalPort;
1803 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1804 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1805 phy_info->hw_link_rate = buffer->HwLinkRate;
1806 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1807 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1808
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001809 out_free_consistent:
1810 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1811 buffer, dma_handle);
1812 out:
1813 return error;
1814}
1815
1816static void
1817mptsas_parse_device_info(struct sas_identify *identify,
1818 struct mptsas_devinfo *device_info)
1819{
1820 u16 protocols;
1821
1822 identify->sas_address = device_info->sas_address;
1823 identify->phy_identifier = device_info->phy_id;
1824
1825 /*
1826 * Fill in Phy Initiator Port Protocol.
1827 * Bits 6:3, more than one bit can be set, fall through cases.
1828 */
1829 protocols = device_info->device_info & 0x78;
1830 identify->initiator_port_protocols = 0;
1831 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1832 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1833 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1834 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1835 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1836 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1837 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1838 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1839
1840 /*
1841 * Fill in Phy Target Port Protocol.
1842 * Bits 10:7, more than one bit can be set, fall through cases.
1843 */
1844 protocols = device_info->device_info & 0x780;
1845 identify->target_port_protocols = 0;
1846 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1847 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1848 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1849 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1850 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1851 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1852 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1853 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1854
1855 /*
1856 * Fill in Attached device type.
1857 */
1858 switch (device_info->device_info &
1859 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1860 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1861 identify->device_type = SAS_PHY_UNUSED;
1862 break;
1863 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1864 identify->device_type = SAS_END_DEVICE;
1865 break;
1866 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1867 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1868 break;
1869 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1870 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1871 break;
1872 }
1873}
1874
1875static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001876 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001877{
Moore, Erice6b2d762006-03-14 09:14:24 -07001878 MPT_ADAPTER *ioc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001879 struct sas_phy *phy;
Eric Moore547f9a22006-06-27 14:42:12 -06001880 struct sas_port *port;
1881 int error = 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001882
Eric Moore547f9a22006-06-27 14:42:12 -06001883 if (!dev) {
1884 error = -ENODEV;
1885 goto out;
1886 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001887
1888 if (!phy_info->phy) {
1889 phy = sas_phy_alloc(dev, index);
Eric Moore547f9a22006-06-27 14:42:12 -06001890 if (!phy) {
1891 error = -ENOMEM;
1892 goto out;
1893 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001894 } else
1895 phy = phy_info->phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001896
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001897 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001898
1899 /*
1900 * Set Negotiated link rate.
1901 */
1902 switch (phy_info->negotiated_link_rate) {
1903 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001904 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001905 break;
1906 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001907 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001908 break;
1909 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001910 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001911 break;
1912 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001913 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001914 break;
1915 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1916 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1917 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001918 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001919 break;
1920 }
1921
1922 /*
1923 * Set Max hardware link rate.
1924 */
1925 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1926 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001927 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001928 break;
1929 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001930 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001931 break;
1932 default:
1933 break;
1934 }
1935
1936 /*
1937 * Set Max programmed link rate.
1938 */
1939 switch (phy_info->programmed_link_rate &
1940 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1941 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001942 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001943 break;
1944 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001945 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001946 break;
1947 default:
1948 break;
1949 }
1950
1951 /*
1952 * Set Min hardware link rate.
1953 */
1954 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1955 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001956 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001957 break;
1958 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001959 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001960 break;
1961 default:
1962 break;
1963 }
1964
1965 /*
1966 * Set Min programmed link rate.
1967 */
1968 switch (phy_info->programmed_link_rate &
1969 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1970 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001971 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001972 break;
1973 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001974 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001975 break;
1976 default:
1977 break;
1978 }
1979
Moore, Erice6b2d762006-03-14 09:14:24 -07001980 if (!phy_info->phy) {
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001981
Moore, Erice6b2d762006-03-14 09:14:24 -07001982 error = sas_phy_add(phy);
1983 if (error) {
1984 sas_phy_free(phy);
Eric Moore547f9a22006-06-27 14:42:12 -06001985 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001986 }
1987 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001988 }
1989
Eric Moore547f9a22006-06-27 14:42:12 -06001990 if (!phy_info->attached.handle ||
1991 !phy_info->port_details)
1992 goto out;
1993
1994 port = mptsas_get_port(phy_info);
1995 ioc = phy_to_ioc(phy_info->phy);
1996
1997 if (phy_info->sas_port_add_phy) {
1998
1999 if (!port) {
Eric Mooredc22f162006-07-06 11:23:14 -06002000 port = sas_port_alloc_num(dev);
Eric Moore547f9a22006-06-27 14:42:12 -06002001 if (!port) {
2002 error = -ENOMEM;
2003 goto out;
2004 }
2005 error = sas_port_add(port);
2006 if (error) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302007 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002008 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002009 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002010 goto out;
2011 }
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302012 mptsas_set_port(ioc, phy_info, port);
Eric Moore29dd3602007-09-14 18:46:51 -06002013 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
Eric Mooredc22f162006-07-06 11:23:14 -06002014 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
Eric Moore29dd3602007-09-14 18:46:51 -06002015 ioc->name, port, dev, port->port_identifier));
Eric Moore547f9a22006-06-27 14:42:12 -06002016 }
Eric Moore29dd3602007-09-14 18:46:51 -06002017 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_port_add_phy: phy_id=%d\n",
2018 ioc->name, phy_info->phy_id));
Eric Moore547f9a22006-06-27 14:42:12 -06002019 sas_port_add_phy(port, phy_info->phy);
2020 phy_info->sas_port_add_phy = 0;
2021 }
2022
2023 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
Moore, Erice6b2d762006-03-14 09:14:24 -07002024
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002025 struct sas_rphy *rphy;
James Bottomley2686de22006-06-30 12:54:02 -05002026 struct device *parent;
James Bottomleyf013db32006-03-18 14:54:36 -06002027 struct sas_identify identify;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002028
James Bottomley2686de22006-06-30 12:54:02 -05002029 parent = dev->parent->parent;
Moore, Erice6b2d762006-03-14 09:14:24 -07002030 /*
2031 * Let the hotplug_work thread handle processing
2032 * the adding/removing of devices that occur
2033 * after start of day.
2034 */
2035 if (ioc->sas_discovery_runtime &&
2036 mptsas_is_end_device(&phy_info->attached))
Eric Moore547f9a22006-06-27 14:42:12 -06002037 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07002038
James Bottomleyf013db32006-03-18 14:54:36 -06002039 mptsas_parse_device_info(&identify, &phy_info->attached);
James Bottomley2686de22006-06-30 12:54:02 -05002040 if (scsi_is_host_device(parent)) {
2041 struct mptsas_portinfo *port_info;
2042 int i;
2043
2044 mutex_lock(&ioc->sas_topology_mutex);
Michael Reed77483692008-03-20 17:32:05 -05002045 port_info = mptsas_get_hba_portinfo(ioc);
James Bottomley2686de22006-06-30 12:54:02 -05002046 mutex_unlock(&ioc->sas_topology_mutex);
2047
2048 for (i = 0; i < port_info->num_phys; i++)
2049 if (port_info->phy_info[i].identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04002050 identify.sas_address) {
2051 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05002052 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04002053 }
James Bottomley2686de22006-06-30 12:54:02 -05002054
2055 } else if (scsi_is_sas_rphy(parent)) {
2056 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
2057 if (identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04002058 parent_rphy->identify.sas_address) {
2059 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05002060 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04002061 }
James Bottomley2686de22006-06-30 12:54:02 -05002062 }
2063
James Bottomleyf013db32006-03-18 14:54:36 -06002064 switch (identify.device_type) {
2065 case SAS_END_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06002066 rphy = sas_end_device_alloc(port);
James Bottomleyf013db32006-03-18 14:54:36 -06002067 break;
2068 case SAS_EDGE_EXPANDER_DEVICE:
2069 case SAS_FANOUT_EXPANDER_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06002070 rphy = sas_expander_alloc(port, identify.device_type);
James Bottomleyf013db32006-03-18 14:54:36 -06002071 break;
2072 default:
2073 rphy = NULL;
2074 break;
2075 }
Eric Moore547f9a22006-06-27 14:42:12 -06002076 if (!rphy) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302077 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002078 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002079 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002080 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002081 }
2082
Eric Moore547f9a22006-06-27 14:42:12 -06002083 rphy->identify = identify;
2084 error = sas_rphy_add(rphy);
2085 if (error) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302086 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002087 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002088 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002089 sas_rphy_free(rphy);
2090 goto out;
2091 }
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302092 mptsas_set_rphy(ioc, phy_info, rphy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002093 }
2094
Eric Moore547f9a22006-06-27 14:42:12 -06002095 out:
2096 return error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002097}
2098
2099static int
Moore, Erice6b2d762006-03-14 09:14:24 -07002100mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002101{
Moore, Erice6b2d762006-03-14 09:14:24 -07002102 struct mptsas_portinfo *port_info, *hba;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002103 int error = -ENOMEM, i;
2104
Moore, Erice6b2d762006-03-14 09:14:24 -07002105 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
2106 if (! hba)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002107 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002108
Moore, Erice6b2d762006-03-14 09:14:24 -07002109 error = mptsas_sas_io_unit_pg0(ioc, hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002110 if (error)
2111 goto out_free_port_info;
2112
Prakash, Sathyaedb90682007-07-17 14:39:14 +05302113 mptsas_sas_io_unit_pg1(ioc);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002114 mutex_lock(&ioc->sas_topology_mutex);
Michael Reed77483692008-03-20 17:32:05 -05002115 port_info = mptsas_get_hba_portinfo(ioc);
Moore, Erice6b2d762006-03-14 09:14:24 -07002116 if (!port_info) {
2117 port_info = hba;
2118 list_add_tail(&port_info->list, &ioc->sas_topology);
2119 } else {
Eric Moore2ecce492007-01-29 09:47:08 -07002120 for (i = 0; i < hba->num_phys; i++) {
Moore, Erice6b2d762006-03-14 09:14:24 -07002121 port_info->phy_info[i].negotiated_link_rate =
2122 hba->phy_info[i].negotiated_link_rate;
Eric Moore2ecce492007-01-29 09:47:08 -07002123 port_info->phy_info[i].handle =
2124 hba->phy_info[i].handle;
2125 port_info->phy_info[i].port_id =
2126 hba->phy_info[i].port_id;
2127 }
Eric Moore547f9a22006-06-27 14:42:12 -06002128 kfree(hba->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002129 kfree(hba);
2130 hba = NULL;
2131 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002132 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002133 for (i = 0; i < port_info->num_phys; i++) {
2134 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
2135 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
2136 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
2137
2138 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
Eric Moore2ecce492007-01-29 09:47:08 -07002139 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2140 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2141 port_info->phy_info[i].handle);
Eric Moore024358e2005-10-21 20:56:36 +02002142 port_info->phy_info[i].identify.phy_id =
Eric Moore2ecce492007-01-29 09:47:08 -07002143 port_info->phy_info[i].phy_id = i;
Eric Moore547f9a22006-06-27 14:42:12 -06002144 if (port_info->phy_info[i].attached.handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002145 mptsas_sas_device_pg0(ioc,
2146 &port_info->phy_info[i].attached,
2147 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2148 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2149 port_info->phy_info[i].attached.handle);
Eric Moore547f9a22006-06-27 14:42:12 -06002150 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002151
Eric Moore547f9a22006-06-27 14:42:12 -06002152 mptsas_setup_wide_ports(ioc, port_info);
2153
2154 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002155 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Moore, Erice6b2d762006-03-14 09:14:24 -07002156 &port_info->phy_info[i], ioc->sas_index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002157
2158 return 0;
2159
2160 out_free_port_info:
Eric Moore547f9a22006-06-27 14:42:12 -06002161 kfree(hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002162 out:
2163 return error;
2164}
2165
2166static int
Moore, Erice6b2d762006-03-14 09:14:24 -07002167mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002168{
Moore, Erice6b2d762006-03-14 09:14:24 -07002169 struct mptsas_portinfo *port_info, *p, *ex;
Eric Moore547f9a22006-06-27 14:42:12 -06002170 struct device *parent;
2171 struct sas_rphy *rphy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002172 int error = -ENOMEM, i, j;
2173
Moore, Erice6b2d762006-03-14 09:14:24 -07002174 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
2175 if (!ex)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002176 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002177
Moore, Erice6b2d762006-03-14 09:14:24 -07002178 error = mptsas_sas_expander_pg0(ioc, ex,
Eric Moore2ecce492007-01-29 09:47:08 -07002179 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
2180 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002181 if (error)
2182 goto out_free_port_info;
2183
Eric Moore2ecce492007-01-29 09:47:08 -07002184 *handle = ex->phy_info[0].handle;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002185
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002186 mutex_lock(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07002187 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
2188 if (!port_info) {
2189 port_info = ex;
2190 list_add_tail(&port_info->list, &ioc->sas_topology);
2191 } else {
Eric Moore2ecce492007-01-29 09:47:08 -07002192 for (i = 0; i < ex->num_phys; i++) {
2193 port_info->phy_info[i].handle =
2194 ex->phy_info[i].handle;
2195 port_info->phy_info[i].port_id =
2196 ex->phy_info[i].port_id;
2197 }
Eric Moore547f9a22006-06-27 14:42:12 -06002198 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002199 kfree(ex);
2200 ex = NULL;
2201 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002202 mutex_unlock(&ioc->sas_topology_mutex);
2203
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002204 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002205 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
2206 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
2207 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
2208
2209 if (port_info->phy_info[i].identify.handle) {
2210 mptsas_sas_device_pg0(ioc,
2211 &port_info->phy_info[i].identify,
2212 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2213 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2214 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02002215 port_info->phy_info[i].identify.phy_id =
2216 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002217 }
2218
2219 if (port_info->phy_info[i].attached.handle) {
2220 mptsas_sas_device_pg0(ioc,
2221 &port_info->phy_info[i].attached,
2222 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2223 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2224 port_info->phy_info[i].attached.handle);
Moore, Ericdb9c9172006-03-14 09:14:18 -07002225 port_info->phy_info[i].attached.phy_id =
2226 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002227 }
Eric Moore547f9a22006-06-27 14:42:12 -06002228 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002229
Eric Moore547f9a22006-06-27 14:42:12 -06002230 parent = &ioc->sh->shost_gendev;
2231 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002232 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002233 list_for_each_entry(p, &ioc->sas_topology, list) {
2234 for (j = 0; j < p->num_phys; j++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002235 if (port_info->phy_info[i].identify.handle !=
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002236 p->phy_info[j].attached.handle)
Eric Moore547f9a22006-06-27 14:42:12 -06002237 continue;
2238 rphy = mptsas_get_rphy(&p->phy_info[j]);
2239 parent = &rphy->dev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002240 }
2241 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002242 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002243 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002244
Eric Moore547f9a22006-06-27 14:42:12 -06002245 mptsas_setup_wide_ports(ioc, port_info);
2246
2247 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02002248 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
Moore, Erice6b2d762006-03-14 09:14:24 -07002249 ioc->sas_index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002250
2251 return 0;
2252
2253 out_free_port_info:
Moore, Erice6b2d762006-03-14 09:14:24 -07002254 if (ex) {
Eric Moore547f9a22006-06-27 14:42:12 -06002255 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002256 kfree(ex);
2257 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002258 out:
2259 return error;
2260}
2261
Moore, Erice6b2d762006-03-14 09:14:24 -07002262/*
2263 * mptsas_delete_expander_phys
2264 *
2265 *
2266 * This will traverse topology, and remove expanders
2267 * that are no longer present
2268 */
2269static void
2270mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
2271{
2272 struct mptsas_portinfo buffer;
2273 struct mptsas_portinfo *port_info, *n, *parent;
Eric Moore547f9a22006-06-27 14:42:12 -06002274 struct mptsas_phyinfo *phy_info;
Eric Moore547f9a22006-06-27 14:42:12 -06002275 struct sas_port * port;
Moore, Erice6b2d762006-03-14 09:14:24 -07002276 int i;
Eric Moore547f9a22006-06-27 14:42:12 -06002277 u64 expander_sas_address;
Moore, Erice6b2d762006-03-14 09:14:24 -07002278
2279 mutex_lock(&ioc->sas_topology_mutex);
2280 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
2281
Alan Coxd58069a2009-04-01 15:00:29 +01002282 if (!(port_info->phy_info[0].identify.device_info &
2283 MPI_SAS_DEVICE_INFO_SMP_TARGET))
Moore, Erice6b2d762006-03-14 09:14:24 -07002284 continue;
2285
2286 if (mptsas_sas_expander_pg0(ioc, &buffer,
2287 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
Eric Moore2ecce492007-01-29 09:47:08 -07002288 MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
2289 port_info->phy_info[0].handle)) {
Moore, Erice6b2d762006-03-14 09:14:24 -07002290
2291 /*
2292 * Obtain the port_info instance to the parent port
2293 */
2294 parent = mptsas_find_portinfo_by_handle(ioc,
2295 port_info->phy_info[0].identify.handle_parent);
2296
2297 if (!parent)
2298 goto next_port;
2299
Eric Moore547f9a22006-06-27 14:42:12 -06002300 expander_sas_address =
2301 port_info->phy_info[0].identify.sas_address;
2302
Moore, Erice6b2d762006-03-14 09:14:24 -07002303 /*
2304 * Delete rphys in the parent that point
2305 * to this expander. The transport layer will
2306 * cleanup all the children.
2307 */
Eric Moore547f9a22006-06-27 14:42:12 -06002308 phy_info = parent->phy_info;
2309 for (i = 0; i < parent->num_phys; i++, phy_info++) {
2310 port = mptsas_get_port(phy_info);
2311 if (!port)
Moore, Erice6b2d762006-03-14 09:14:24 -07002312 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06002313 if (phy_info->attached.sas_address !=
2314 expander_sas_address)
2315 continue;
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302316 dsaswideprintk(ioc,
Eric Moorec51d0be2007-09-29 10:17:21 -06002317 dev_printk(KERN_DEBUG, &port->dev,
2318 MYIOC_s_FMT "delete port (%d)\n", ioc->name,
2319 port->port_identifier));
Eric Moore547f9a22006-06-27 14:42:12 -06002320 sas_port_delete(port);
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302321 mptsas_port_delete(ioc, phy_info->port_details);
Moore, Erice6b2d762006-03-14 09:14:24 -07002322 }
2323 next_port:
Eric Moore547f9a22006-06-27 14:42:12 -06002324
2325 phy_info = port_info->phy_info;
2326 for (i = 0; i < port_info->num_phys; i++, phy_info++)
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302327 mptsas_port_delete(ioc, phy_info->port_details);
Eric Moore547f9a22006-06-27 14:42:12 -06002328
Moore, Erice6b2d762006-03-14 09:14:24 -07002329 list_del(&port_info->list);
Eric Moore547f9a22006-06-27 14:42:12 -06002330 kfree(port_info->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002331 kfree(port_info);
2332 }
2333 /*
2334 * Free this memory allocated from inside
2335 * mptsas_sas_expander_pg0
2336 */
Eric Moore547f9a22006-06-27 14:42:12 -06002337 kfree(buffer.phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002338 }
2339 mutex_unlock(&ioc->sas_topology_mutex);
2340}
2341
2342/*
2343 * Start of day discovery
2344 */
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002345static void
2346mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
2347{
2348 u32 handle = 0xFFFF;
Moore, Ericf44e5462006-03-14 09:14:21 -07002349 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002350
Moore, Erice6b2d762006-03-14 09:14:24 -07002351 mutex_lock(&ioc->sas_discovery_mutex);
2352 mptsas_probe_hba_phys(ioc);
2353 while (!mptsas_probe_expander_phys(ioc, &handle))
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002354 ;
Moore, Ericf44e5462006-03-14 09:14:21 -07002355 /*
2356 Reporting RAID volumes.
2357 */
Eric Mooreb506ade2007-01-29 09:45:37 -07002358 if (!ioc->ir_firmware)
2359 goto out;
Moore, Ericf44e5462006-03-14 09:14:21 -07002360 if (!ioc->raid_data.pIocPg2)
2361 goto out;
2362 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
2363 goto out;
Eric Moore793955f2007-01-29 09:42:20 -07002364 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
James Bottomleye8bf3942006-07-11 17:49:34 -04002365 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
Moore, Ericf44e5462006-03-14 09:14:21 -07002366 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
2367 }
2368 out:
Moore, Erice6b2d762006-03-14 09:14:24 -07002369 mutex_unlock(&ioc->sas_discovery_mutex);
2370}
2371
2372/*
2373 * Work queue thread to handle Runtime discovery
2374 * Mere purpose is the hot add/delete of expanders
Eric Moore547f9a22006-06-27 14:42:12 -06002375 *(Mutex UNLOCKED)
Moore, Erice6b2d762006-03-14 09:14:24 -07002376 */
2377static void
Eric Moore547f9a22006-06-27 14:42:12 -06002378__mptsas_discovery_work(MPT_ADAPTER *ioc)
Moore, Erice6b2d762006-03-14 09:14:24 -07002379{
Moore, Erice6b2d762006-03-14 09:14:24 -07002380 u32 handle = 0xFFFF;
2381
Moore, Erice6b2d762006-03-14 09:14:24 -07002382 ioc->sas_discovery_runtime=1;
2383 mptsas_delete_expander_phys(ioc);
2384 mptsas_probe_hba_phys(ioc);
2385 while (!mptsas_probe_expander_phys(ioc, &handle))
2386 ;
Moore, Erice6b2d762006-03-14 09:14:24 -07002387 ioc->sas_discovery_runtime=0;
Eric Moore547f9a22006-06-27 14:42:12 -06002388}
2389
2390/*
2391 * Work queue thread to handle Runtime discovery
2392 * Mere purpose is the hot add/delete of expanders
2393 *(Mutex LOCKED)
2394 */
2395static void
David Howellsc4028952006-11-22 14:57:56 +00002396mptsas_discovery_work(struct work_struct *work)
Eric Moore547f9a22006-06-27 14:42:12 -06002397{
David Howellsc4028952006-11-22 14:57:56 +00002398 struct mptsas_discovery_event *ev =
2399 container_of(work, struct mptsas_discovery_event, work);
Eric Moore547f9a22006-06-27 14:42:12 -06002400 MPT_ADAPTER *ioc = ev->ioc;
2401
2402 mutex_lock(&ioc->sas_discovery_mutex);
2403 __mptsas_discovery_work(ioc);
Moore, Erice6b2d762006-03-14 09:14:24 -07002404 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002405 kfree(ev);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002406}
2407
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002408static struct mptsas_phyinfo *
Eric Moore547f9a22006-06-27 14:42:12 -06002409mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002410{
2411 struct mptsas_portinfo *port_info;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002412 struct mptsas_phyinfo *phy_info = NULL;
Eric Moore547f9a22006-06-27 14:42:12 -06002413 int i;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002414
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002415 mutex_lock(&ioc->sas_topology_mutex);
2416 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2417 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002418 if (!mptsas_is_end_device(
2419 &port_info->phy_info[i].attached))
2420 continue;
Eric Mooreb506ade2007-01-29 09:45:37 -07002421 if (port_info->phy_info[i].attached.sas_address
2422 != sas_address)
2423 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06002424 phy_info = &port_info->phy_info[i];
2425 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002426 }
2427 }
2428 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002429 return phy_info;
2430}
2431
2432static struct mptsas_phyinfo *
Eric Mooreb506ade2007-01-29 09:45:37 -07002433mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002434{
2435 struct mptsas_portinfo *port_info;
2436 struct mptsas_phyinfo *phy_info = NULL;
2437 int i;
2438
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002439 mutex_lock(&ioc->sas_topology_mutex);
2440 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -06002441 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002442 if (!mptsas_is_end_device(
2443 &port_info->phy_info[i].attached))
2444 continue;
Eric Mooreb506ade2007-01-29 09:45:37 -07002445 if (port_info->phy_info[i].attached.id != id)
2446 continue;
2447 if (port_info->phy_info[i].attached.channel != channel)
2448 continue;
2449 phy_info = &port_info->phy_info[i];
2450 break;
2451 }
2452 }
2453 mutex_unlock(&ioc->sas_topology_mutex);
2454 return phy_info;
2455}
2456
2457static struct mptsas_phyinfo *
2458mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2459{
2460 struct mptsas_portinfo *port_info;
2461 struct mptsas_phyinfo *phy_info = NULL;
2462 int i;
2463
2464 mutex_lock(&ioc->sas_topology_mutex);
2465 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2466 for (i = 0; i < port_info->num_phys; i++) {
2467 if (!mptsas_is_end_device(
2468 &port_info->phy_info[i].attached))
2469 continue;
2470 if (port_info->phy_info[i].attached.phys_disk_num == ~0)
2471 continue;
2472 if (port_info->phy_info[i].attached.phys_disk_num != id)
2473 continue;
2474 if (port_info->phy_info[i].attached.channel != channel)
2475 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06002476 phy_info = &port_info->phy_info[i];
2477 break;
2478 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002479 }
2480 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002481 return phy_info;
2482}
2483
Moore, Eric4b766472006-03-14 09:14:12 -07002484/*
2485 * Work queue thread to clear the persitency table
2486 */
2487static void
David Howellsc4028952006-11-22 14:57:56 +00002488mptsas_persist_clear_table(struct work_struct *work)
Moore, Eric4b766472006-03-14 09:14:12 -07002489{
David Howellsc4028952006-11-22 14:57:56 +00002490 MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002491
2492 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2493}
2494
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002495static void
Moore, Ericf44e5462006-03-14 09:14:21 -07002496mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2497{
Eric Mooref99be432007-01-04 20:46:54 -07002498 int rc;
2499
Moore, Ericf44e5462006-03-14 09:14:21 -07002500 sdev->no_uld_attach = data ? 1 : 0;
Eric Mooref99be432007-01-04 20:46:54 -07002501 rc = scsi_device_reprobe(sdev);
Moore, Ericf44e5462006-03-14 09:14:21 -07002502}
2503
2504static void
2505mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2506{
2507 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2508 mptsas_reprobe_lun);
2509}
2510
Eric Mooreb506ade2007-01-29 09:45:37 -07002511static void
2512mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
2513{
2514 CONFIGPARMS cfg;
2515 ConfigPageHeader_t hdr;
2516 dma_addr_t dma_handle;
2517 pRaidVolumePage0_t buffer = NULL;
2518 RaidPhysDiskPage0_t phys_disk;
2519 int i;
2520 struct mptsas_hotplug_event *ev;
2521
2522 memset(&cfg, 0 , sizeof(CONFIGPARMS));
2523 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
2524 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
2525 cfg.pageAddr = (channel << 8) + id;
2526 cfg.cfghdr.hdr = &hdr;
2527 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2528
2529 if (mpt_config(ioc, &cfg) != 0)
2530 goto out;
2531
2532 if (!hdr.PageLength)
2533 goto out;
2534
2535 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
2536 &dma_handle);
2537
2538 if (!buffer)
2539 goto out;
2540
2541 cfg.physAddr = dma_handle;
2542 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2543
2544 if (mpt_config(ioc, &cfg) != 0)
2545 goto out;
2546
2547 if (!(buffer->VolumeStatus.Flags &
2548 MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
2549 goto out;
2550
2551 if (!buffer->NumPhysDisks)
2552 goto out;
2553
2554 for (i = 0; i < buffer->NumPhysDisks; i++) {
2555
2556 if (mpt_raid_phys_disk_pg0(ioc,
2557 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
2558 continue;
2559
2560 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
2561 if (!ev) {
Eric Moore29dd3602007-09-14 18:46:51 -06002562 printk(MYIOC_s_WARN_FMT "mptsas: lost hotplug event\n", ioc->name);
Eric Mooreb506ade2007-01-29 09:45:37 -07002563 goto out;
2564 }
2565
2566 INIT_WORK(&ev->work, mptsas_hotplug_work);
2567 ev->ioc = ioc;
2568 ev->id = phys_disk.PhysDiskID;
2569 ev->channel = phys_disk.PhysDiskBus;
2570 ev->phys_disk_num_valid = 1;
2571 ev->phys_disk_num = phys_disk.PhysDiskNum;
2572 ev->event_type = MPTSAS_ADD_DEVICE;
2573 schedule_work(&ev->work);
2574 }
2575
2576 out:
2577 if (buffer)
2578 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
2579 dma_handle);
2580}
Moore, Erice6b2d762006-03-14 09:14:24 -07002581/*
2582 * Work queue thread to handle SAS hotplug events
2583 */
Moore, Ericf44e5462006-03-14 09:14:21 -07002584static void
David Howellsc4028952006-11-22 14:57:56 +00002585mptsas_hotplug_work(struct work_struct *work)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002586{
David Howellsc4028952006-11-22 14:57:56 +00002587 struct mptsas_hotplug_event *ev =
2588 container_of(work, struct mptsas_hotplug_event, work);
Eric Mooreb506ade2007-01-29 09:45:37 -07002589
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002590 MPT_ADAPTER *ioc = ev->ioc;
2591 struct mptsas_phyinfo *phy_info;
2592 struct sas_rphy *rphy;
Eric Moore547f9a22006-06-27 14:42:12 -06002593 struct sas_port *port;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002594 struct scsi_device *sdev;
Eric Moore547f9a22006-06-27 14:42:12 -06002595 struct scsi_target * starget;
James Bottomleyf013db32006-03-18 14:54:36 -06002596 struct sas_identify identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002597 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002598 struct mptsas_devinfo sas_device;
Moore, Ericf44e5462006-03-14 09:14:21 -07002599 VirtTarget *vtarget;
Eric Moore547f9a22006-06-27 14:42:12 -06002600 VirtDevice *vdevice;
2601
Moore, Erice6b2d762006-03-14 09:14:24 -07002602 mutex_lock(&ioc->sas_discovery_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002603 switch (ev->event_type) {
2604 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002605
Eric Mooreb506ade2007-01-29 09:45:37 -07002606 phy_info = NULL;
2607 if (ev->phys_disk_num_valid) {
2608 if (ev->hidden_raid_component){
2609 if (mptsas_sas_device_pg0(ioc, &sas_device,
2610 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
2611 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2612 (ev->channel << 8) + ev->id)) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302613 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Mooreb506ade2007-01-29 09:45:37 -07002614 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002615 __func__, __LINE__));
Eric Mooreb506ade2007-01-29 09:45:37 -07002616 break;
2617 }
2618 phy_info = mptsas_find_phyinfo_by_sas_address(
2619 ioc, sas_device.sas_address);
2620 }else
2621 phy_info = mptsas_find_phyinfo_by_phys_disk_num(
2622 ioc, ev->channel, ev->phys_disk_num);
2623 }
2624
2625 if (!phy_info)
2626 phy_info = mptsas_find_phyinfo_by_target(ioc,
2627 ev->channel, ev->id);
Moore, Erice6b2d762006-03-14 09:14:24 -07002628
Moore, Ericf44e5462006-03-14 09:14:21 -07002629 /*
2630 * Sanity checks, for non-existing phys and remote rphys.
2631 */
Eric Mooreb506ade2007-01-29 09:45:37 -07002632 if (!phy_info){
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302633 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Mooreb506ade2007-01-29 09:45:37 -07002634 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002635 __func__, __LINE__));
Eric Mooreb506ade2007-01-29 09:45:37 -07002636 break;
2637 }
2638 if (!phy_info->port_details) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302639 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002640 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002641 __func__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002642 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002643 }
2644 rphy = mptsas_get_rphy(phy_info);
2645 if (!rphy) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302646 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002647 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002648 __func__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002649 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002650 }
Eric Mooreb506ade2007-01-29 09:45:37 -07002651
Eric Moore547f9a22006-06-27 14:42:12 -06002652 port = mptsas_get_port(phy_info);
2653 if (!port) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302654 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002655 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002656 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002657 break;
2658 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002659
Eric Moore547f9a22006-06-27 14:42:12 -06002660 starget = mptsas_get_starget(phy_info);
2661 if (starget) {
2662 vtarget = starget->hostdata;
2663
2664 if (!vtarget) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302665 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002666 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002667 __func__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002668 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002669 }
2670
Moore, Ericf44e5462006-03-14 09:14:21 -07002671 /*
2672 * Handling RAID components
2673 */
Eric Mooreb506ade2007-01-29 09:45:37 -07002674 if (ev->phys_disk_num_valid &&
2675 ev->hidden_raid_component) {
2676 printk(MYIOC_s_INFO_FMT
2677 "RAID Hidding: channel=%d, id=%d, "
2678 "physdsk %d \n", ioc->name, ev->channel,
2679 ev->id, ev->phys_disk_num);
Eric Moore793955f2007-01-29 09:42:20 -07002680 vtarget->id = ev->phys_disk_num;
Eric Mooreb506ade2007-01-29 09:45:37 -07002681 vtarget->tflags |=
2682 MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore547f9a22006-06-27 14:42:12 -06002683 mptsas_reprobe_target(starget, 1);
Eric Mooreb506ade2007-01-29 09:45:37 -07002684 phy_info->attached.phys_disk_num =
2685 ev->phys_disk_num;
2686 break;
Moore, Ericf44e5462006-03-14 09:14:21 -07002687 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002688 }
2689
Eric Mooreb506ade2007-01-29 09:45:37 -07002690 if (phy_info->attached.device_info &
2691 MPI_SAS_DEVICE_INFO_SSP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002692 ds = "ssp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002693 if (phy_info->attached.device_info &
2694 MPI_SAS_DEVICE_INFO_STP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002695 ds = "stp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002696 if (phy_info->attached.device_info &
2697 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002698 ds = "sata";
2699
2700 printk(MYIOC_s_INFO_FMT
2701 "removing %s device, channel %d, id %d, phy %d\n",
2702 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
Eric Moorec51d0be2007-09-29 10:17:21 -06002703 dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
Eric Moore29dd3602007-09-14 18:46:51 -06002704 "delete port (%d)\n", ioc->name, port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06002705 sas_port_delete(port);
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302706 mptsas_port_delete(ioc, phy_info->port_details);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002707 break;
2708 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002709
Moore, Ericbd23e942006-04-17 12:43:04 -06002710 if (ev->phys_disk_num_valid)
2711 mpt_findImVolumes(ioc);
2712
Moore, Ericc73787ee2006-01-26 16:20:06 -07002713 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01002714 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07002715 */
Christoph Hellwige3094442006-02-16 13:25:36 +01002716 if (mptsas_sas_device_pg0(ioc, &sas_device,
2717 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
Eric Mooreb506ade2007-01-29 09:45:37 -07002718 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2719 (ev->channel << 8) + ev->id)) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302720 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002721 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002722 __func__, __LINE__));
Christoph Hellwige3094442006-02-16 13:25:36 +01002723 break;
Moore, Erice6b2d762006-03-14 09:14:24 -07002724 }
2725
Eric Moore547f9a22006-06-27 14:42:12 -06002726 __mptsas_discovery_work(ioc);
Moore, Ericf44e5462006-03-14 09:14:21 -07002727
Eric Moore547f9a22006-06-27 14:42:12 -06002728 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2729 sas_device.sas_address);
2730
2731 if (!phy_info || !phy_info->port_details) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302732 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002733 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002734 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002735 break;
2736 }
2737
2738 starget = mptsas_get_starget(phy_info);
Eric Mooreb506ade2007-01-29 09:45:37 -07002739 if (starget && (!ev->hidden_raid_component)){
2740
Eric Moore547f9a22006-06-27 14:42:12 -06002741 vtarget = starget->hostdata;
2742
2743 if (!vtarget) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302744 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore29dd3602007-09-14 18:46:51 -06002745 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002746 __func__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002747 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002748 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002749 /*
2750 * Handling RAID components
2751 */
2752 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
Eric Mooreb506ade2007-01-29 09:45:37 -07002753 printk(MYIOC_s_INFO_FMT
2754 "RAID Exposing: channel=%d, id=%d, "
2755 "physdsk %d \n", ioc->name, ev->channel,
2756 ev->id, ev->phys_disk_num);
2757 vtarget->tflags &=
2758 ~MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore793955f2007-01-29 09:42:20 -07002759 vtarget->id = ev->id;
Eric Moore547f9a22006-06-27 14:42:12 -06002760 mptsas_reprobe_target(starget, 0);
Eric Mooreb506ade2007-01-29 09:45:37 -07002761 phy_info->attached.phys_disk_num = ~0;
Moore, Ericf44e5462006-03-14 09:14:21 -07002762 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002763 break;
2764 }
2765
Eric Moore547f9a22006-06-27 14:42:12 -06002766 if (mptsas_get_rphy(phy_info)) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302767 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002768 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002769 __func__, __LINE__));
Eric Mooreb506ade2007-01-29 09:45:37 -07002770 if (ev->channel) printk("%d\n", __LINE__);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002771 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002772 }
Eric Mooreb506ade2007-01-29 09:45:37 -07002773
Eric Moore547f9a22006-06-27 14:42:12 -06002774 port = mptsas_get_port(phy_info);
2775 if (!port) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302776 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002777 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002778 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002779 break;
2780 }
Christoph Hellwige3094442006-02-16 13:25:36 +01002781 memcpy(&phy_info->attached, &sas_device,
2782 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002783
Eric Mooreb506ade2007-01-29 09:45:37 -07002784 if (phy_info->attached.device_info &
2785 MPI_SAS_DEVICE_INFO_SSP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002786 ds = "ssp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002787 if (phy_info->attached.device_info &
2788 MPI_SAS_DEVICE_INFO_STP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002789 ds = "stp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002790 if (phy_info->attached.device_info &
2791 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002792 ds = "sata";
2793
2794 printk(MYIOC_s_INFO_FMT
2795 "attaching %s device, channel %d, id %d, phy %d\n",
2796 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2797
James Bottomleyf013db32006-03-18 14:54:36 -06002798 mptsas_parse_device_info(&identify, &phy_info->attached);
Eric Moore547f9a22006-06-27 14:42:12 -06002799 rphy = sas_end_device_alloc(port);
2800 if (!rphy) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302801 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002802 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002803 __func__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002804 break; /* non-fatal: an rphy can be added later */
Eric Moore547f9a22006-06-27 14:42:12 -06002805 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002806
James Bottomleyf013db32006-03-18 14:54:36 -06002807 rphy->identify = identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002808 if (sas_rphy_add(rphy)) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302809 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002810 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002811 __func__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002812 sas_rphy_free(rphy);
2813 break;
2814 }
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302815 mptsas_set_rphy(ioc, phy_info, rphy);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002816 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002817 case MPTSAS_ADD_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002818 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2819 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002820 if (sdev) {
2821 scsi_device_put(sdev);
2822 break;
2823 }
2824 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002825 "attaching raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002826 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2827 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002828 mpt_findImVolumes(ioc);
2829 break;
2830 case MPTSAS_DEL_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002831 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
Eric Mooreb506ade2007-01-29 09:45:37 -07002832 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002833 if (!sdev)
2834 break;
2835 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002836 "removing raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002837 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
Eric Mooreb506ade2007-01-29 09:45:37 -07002838 vdevice = sdev->hostdata;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002839 scsi_remove_device(sdev);
2840 scsi_device_put(sdev);
2841 mpt_findImVolumes(ioc);
2842 break;
Eric Mooreb506ade2007-01-29 09:45:37 -07002843 case MPTSAS_ADD_INACTIVE_VOLUME:
2844 mptsas_adding_inactive_raid_components(ioc,
2845 ev->channel, ev->id);
2846 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002847 case MPTSAS_IGNORE_EVENT:
2848 default:
2849 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002850 }
2851
Moore, Erice6b2d762006-03-14 09:14:24 -07002852 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002853 kfree(ev);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002854}
2855
2856static void
Eric Moore547f9a22006-06-27 14:42:12 -06002857mptsas_send_sas_event(MPT_ADAPTER *ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002858 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2859{
2860 struct mptsas_hotplug_event *ev;
2861 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2862 __le64 sas_address;
2863
2864 if ((device_info &
2865 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2866 MPI_SAS_DEVICE_INFO_STP_TARGET |
2867 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2868 return;
2869
Moore, Eric4b766472006-03-14 09:14:12 -07002870 switch (sas_event_data->ReasonCode) {
Moore, Eric4b766472006-03-14 09:14:12 -07002871 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
Eric Mooredf9e0622007-01-29 09:46:21 -07002872
2873 mptsas_target_reset_queue(ioc, sas_event_data);
2874 break;
2875
2876 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
Eric Moore547f9a22006-06-27 14:42:12 -06002877 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Eric4b766472006-03-14 09:14:12 -07002878 if (!ev) {
Eric Moore29dd3602007-09-14 18:46:51 -06002879 printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
Moore, Eric4b766472006-03-14 09:14:12 -07002880 break;
2881 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002882
David Howellsc4028952006-11-22 14:57:56 +00002883 INIT_WORK(&ev->work, mptsas_hotplug_work);
Moore, Eric4b766472006-03-14 09:14:12 -07002884 ev->ioc = ioc;
2885 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2886 ev->parent_handle =
2887 le16_to_cpu(sas_event_data->ParentDevHandle);
2888 ev->channel = sas_event_data->Bus;
2889 ev->id = sas_event_data->TargetID;
2890 ev->phy_id = sas_event_data->PhyNum;
2891 memcpy(&sas_address, &sas_event_data->SASAddress,
2892 sizeof(__le64));
2893 ev->sas_address = le64_to_cpu(sas_address);
2894 ev->device_info = device_info;
2895
2896 if (sas_event_data->ReasonCode &
2897 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2898 ev->event_type = MPTSAS_ADD_DEVICE;
2899 else
2900 ev->event_type = MPTSAS_DEL_DEVICE;
2901 schedule_work(&ev->work);
2902 break;
2903 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2904 /*
2905 * Persistent table is full.
2906 */
Eric Moore547f9a22006-06-27 14:42:12 -06002907 INIT_WORK(&ioc->sas_persist_task,
David Howellsc4028952006-11-22 14:57:56 +00002908 mptsas_persist_clear_table);
Eric Moore547f9a22006-06-27 14:42:12 -06002909 schedule_work(&ioc->sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002910 break;
Eric Mooreb506ade2007-01-29 09:45:37 -07002911 /*
2912 * TODO, handle other events
2913 */
Moore, Eric4b766472006-03-14 09:14:12 -07002914 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
Eric Mooreb506ade2007-01-29 09:45:37 -07002915 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
Moore, Eric4b766472006-03-14 09:14:12 -07002916 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
Eric Mooreb506ade2007-01-29 09:45:37 -07002917 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
2918 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
2919 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
2920 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
Moore, Eric4b766472006-03-14 09:14:12 -07002921 default:
2922 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002923 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002924}
Moore, Ericc73787ee2006-01-26 16:20:06 -07002925static void
Eric Moore547f9a22006-06-27 14:42:12 -06002926mptsas_send_raid_event(MPT_ADAPTER *ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002927 EVENT_DATA_RAID *raid_event_data)
2928{
2929 struct mptsas_hotplug_event *ev;
Moore, Ericbd23e942006-04-17 12:43:04 -06002930 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2931 int state = (status >> 8) & 0xff;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002932
2933 if (ioc->bus_type != SAS)
2934 return;
2935
Eric Moore547f9a22006-06-27 14:42:12 -06002936 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002937 if (!ev) {
Eric Moore29dd3602007-09-14 18:46:51 -06002938 printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002939 return;
2940 }
2941
David Howellsc4028952006-11-22 14:57:56 +00002942 INIT_WORK(&ev->work, mptsas_hotplug_work);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002943 ev->ioc = ioc;
2944 ev->id = raid_event_data->VolumeID;
Eric Mooreb506ade2007-01-29 09:45:37 -07002945 ev->channel = raid_event_data->VolumeBus;
Moore, Ericbd23e942006-04-17 12:43:04 -06002946 ev->event_type = MPTSAS_IGNORE_EVENT;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002947
2948 switch (raid_event_data->ReasonCode) {
2949 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
Eric Mooreb506ade2007-01-29 09:45:37 -07002950 ev->phys_disk_num_valid = 1;
2951 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002952 ev->event_type = MPTSAS_ADD_DEVICE;
2953 break;
2954 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
Moore, Ericf44e5462006-03-14 09:14:21 -07002955 ev->phys_disk_num_valid = 1;
2956 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Eric Mooreb506ade2007-01-29 09:45:37 -07002957 ev->hidden_raid_component = 1;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002958 ev->event_type = MPTSAS_DEL_DEVICE;
2959 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002960 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2961 switch (state) {
2962 case MPI_PD_STATE_ONLINE:
Eric Mooreb506ade2007-01-29 09:45:37 -07002963 case MPI_PD_STATE_NOT_COMPATIBLE:
Moore, Ericbd23e942006-04-17 12:43:04 -06002964 ev->phys_disk_num_valid = 1;
2965 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Eric Mooreb506ade2007-01-29 09:45:37 -07002966 ev->hidden_raid_component = 1;
Moore, Ericbd23e942006-04-17 12:43:04 -06002967 ev->event_type = MPTSAS_ADD_DEVICE;
2968 break;
2969 case MPI_PD_STATE_MISSING:
Moore, Ericbd23e942006-04-17 12:43:04 -06002970 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2971 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2972 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
Eric Mooreb506ade2007-01-29 09:45:37 -07002973 ev->phys_disk_num_valid = 1;
2974 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericbd23e942006-04-17 12:43:04 -06002975 ev->event_type = MPTSAS_DEL_DEVICE;
2976 break;
2977 default:
2978 break;
2979 }
2980 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002981 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2982 ev->event_type = MPTSAS_DEL_RAID;
2983 break;
2984 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2985 ev->event_type = MPTSAS_ADD_RAID;
2986 break;
2987 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
Moore, Ericbd23e942006-04-17 12:43:04 -06002988 switch (state) {
2989 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2990 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2991 ev->event_type = MPTSAS_DEL_RAID;
2992 break;
2993 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
2994 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
2995 ev->event_type = MPTSAS_ADD_RAID;
2996 break;
2997 default:
2998 break;
2999 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07003000 break;
3001 default:
3002 break;
3003 }
3004 schedule_work(&ev->work);
3005}
3006
Moore, Erice6b2d762006-03-14 09:14:24 -07003007static void
Eric Moore547f9a22006-06-27 14:42:12 -06003008mptsas_send_discovery_event(MPT_ADAPTER *ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07003009 EVENT_DATA_SAS_DISCOVERY *discovery_data)
3010{
3011 struct mptsas_discovery_event *ev;
3012
3013 /*
3014 * DiscoveryStatus
3015 *
3016 * This flag will be non-zero when firmware
3017 * kicks off discovery, and return to zero
3018 * once its completed.
3019 */
3020 if (discovery_data->DiscoveryStatus)
3021 return;
3022
Eric Moore547f9a22006-06-27 14:42:12 -06003023 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Erice6b2d762006-03-14 09:14:24 -07003024 if (!ev)
3025 return;
David Howellsc4028952006-11-22 14:57:56 +00003026 INIT_WORK(&ev->work, mptsas_discovery_work);
Moore, Erice6b2d762006-03-14 09:14:24 -07003027 ev->ioc = ioc;
3028 schedule_work(&ev->work);
3029};
3030
Eric Mooreb506ade2007-01-29 09:45:37 -07003031/*
3032 * mptsas_send_ir2_event - handle exposing hidden disk when
3033 * an inactive raid volume is added
3034 *
3035 * @ioc: Pointer to MPT_ADAPTER structure
3036 * @ir2_data
3037 *
3038 */
3039static void
3040mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data)
3041{
3042 struct mptsas_hotplug_event *ev;
3043
3044 if (ir2_data->ReasonCode !=
3045 MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED)
3046 return;
3047
3048 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
3049 if (!ev)
3050 return;
3051
3052 INIT_WORK(&ev->work, mptsas_hotplug_work);
3053 ev->ioc = ioc;
3054 ev->id = ir2_data->TargetID;
3055 ev->channel = ir2_data->Bus;
3056 ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
3057
3058 schedule_work(&ev->work);
3059};
Moore, Erice6b2d762006-03-14 09:14:24 -07003060
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003061static int
3062mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
3063{
Moore, Ericc73787ee2006-01-26 16:20:06 -07003064 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003065 u8 event = le32_to_cpu(reply->Event) & 0xFF;
3066
3067 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07003068 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003069
Moore, Erice6b2d762006-03-14 09:14:24 -07003070 /*
3071 * sas_discovery_ignore_events
3072 *
3073 * This flag is to prevent anymore processing of
3074 * sas events once mptsas_remove function is called.
3075 */
3076 if (ioc->sas_discovery_ignore_events) {
3077 rc = mptscsih_event_process(ioc, reply);
3078 goto out;
3079 }
3080
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003081 switch (event) {
3082 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
Eric Moore547f9a22006-06-27 14:42:12 -06003083 mptsas_send_sas_event(ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003084 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07003085 break;
3086 case MPI_EVENT_INTEGRATED_RAID:
Eric Moore547f9a22006-06-27 14:42:12 -06003087 mptsas_send_raid_event(ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07003088 (EVENT_DATA_RAID *)reply->Data);
3089 break;
Moore, Eric79de2782006-01-25 18:05:15 -07003090 case MPI_EVENT_PERSISTENT_TABLE_FULL:
Eric Moore547f9a22006-06-27 14:42:12 -06003091 INIT_WORK(&ioc->sas_persist_task,
David Howellsc4028952006-11-22 14:57:56 +00003092 mptsas_persist_clear_table);
Eric Moore547f9a22006-06-27 14:42:12 -06003093 schedule_work(&ioc->sas_persist_task);
Moore, Eric79de2782006-01-25 18:05:15 -07003094 break;
Moore, Eric4b766472006-03-14 09:14:12 -07003095 case MPI_EVENT_SAS_DISCOVERY:
Eric Moore547f9a22006-06-27 14:42:12 -06003096 mptsas_send_discovery_event(ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07003097 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
3098 break;
Eric Mooreb506ade2007-01-29 09:45:37 -07003099 case MPI_EVENT_IR2:
3100 mptsas_send_ir2_event(ioc,
3101 (PTR_MPI_EVENT_DATA_IR2)reply->Data);
3102 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003103 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07003104 rc = mptscsih_event_process(ioc, reply);
3105 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003106 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07003107 out:
3108
3109 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003110}
3111
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003112static int
3113mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3114{
3115 struct Scsi_Host *sh;
3116 MPT_SCSI_HOST *hd;
3117 MPT_ADAPTER *ioc;
3118 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01003119 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003120 int numSGE = 0;
3121 int scale;
3122 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003123 int error=0;
3124 int r;
3125
3126 r = mpt_attach(pdev,id);
3127 if (r)
3128 return r;
3129
3130 ioc = pci_get_drvdata(pdev);
3131 ioc->DoneCtx = mptsasDoneCtx;
3132 ioc->TaskCtx = mptsasTaskCtx;
3133 ioc->InternalCtx = mptsasInternalCtx;
3134
3135 /* Added sanity check on readiness of the MPT adapter.
3136 */
3137 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
3138 printk(MYIOC_s_WARN_FMT
3139 "Skipping because it's not operational!\n",
3140 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003141 error = -ENODEV;
3142 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003143 }
3144
3145 if (!ioc->active) {
3146 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
3147 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003148 error = -ENODEV;
3149 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003150 }
3151
3152 /* Sanity check - ensure at least 1 port is INITIATOR capable
3153 */
3154 ioc_cap = 0;
3155 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
3156 if (ioc->pfacts[ii].ProtocolFlags &
3157 MPI_PORTFACTS_PROTOCOL_INITIATOR)
3158 ioc_cap++;
3159 }
3160
3161 if (!ioc_cap) {
3162 printk(MYIOC_s_WARN_FMT
3163 "Skipping ioc=%p because SCSI Initiator mode "
3164 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06003165 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003166 }
3167
3168 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
3169 if (!sh) {
3170 printk(MYIOC_s_WARN_FMT
3171 "Unable to register controller with SCSI subsystem\n",
3172 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003173 error = -1;
3174 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003175 }
3176
3177 spin_lock_irqsave(&ioc->FreeQlock, flags);
3178
3179 /* Attach the SCSI Host to the IOC structure
3180 */
3181 ioc->sh = sh;
3182
3183 sh->io_port = 0;
3184 sh->n_io_port = 0;
3185 sh->irq = 0;
3186
3187 /* set 16 byte cdb's */
3188 sh->max_cmd_len = 16;
3189
Eric Moore793955f2007-01-29 09:42:20 -07003190 sh->max_id = ioc->pfacts[0].PortSCSIID;
3191 sh->max_lun = max_lun;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003192
3193 sh->transportt = mptsas_transport_template;
3194
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003195 /* Required entry.
3196 */
3197 sh->unique_id = ioc->id;
3198
3199 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003200 mutex_init(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07003201 mutex_init(&ioc->sas_discovery_mutex);
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01003202 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02003203 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003204
3205 /* Verify that we won't exceed the maximum
3206 * number of chain buffers
3207 * We can optimize: ZZ = req_sz/sizeof(SGE)
3208 * For 32bit SGE's:
3209 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
3210 * + (req_sz - 64)/sizeof(SGE)
3211 * A slightly different algorithm is required for
3212 * 64bit SGEs.
3213 */
3214 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3215 if (sizeof(dma_addr_t) == sizeof(u64)) {
3216 numSGE = (scale - 1) *
3217 (ioc->facts.MaxChainDepth-1) + scale +
3218 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
3219 sizeof(u32));
3220 } else {
3221 numSGE = 1 + (scale - 1) *
3222 (ioc->facts.MaxChainDepth-1) + scale +
3223 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
3224 sizeof(u32));
3225 }
3226
3227 if (numSGE < sh->sg_tablesize) {
3228 /* Reset this value */
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05303229 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003230 "Resetting sg_tablesize to %d from %d\n",
3231 ioc->name, numSGE, sh->sg_tablesize));
3232 sh->sg_tablesize = numSGE;
3233 }
3234
Eric Mooree7eae9f2007-09-29 10:15:59 -06003235 hd = shost_priv(sh);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003236 hd->ioc = ioc;
3237
3238 /* SCSI needs scsi_cmnd lookup table!
3239 * (with size equal to req_depth*PtrSz!)
3240 */
Eric Mooree8206382007-09-29 10:16:53 -06003241 ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
3242 if (!ioc->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003243 error = -ENOMEM;
Eric Moorebc6e0892007-09-29 10:16:28 -06003244 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003245 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003246 }
Eric Mooree8206382007-09-29 10:16:53 -06003247 spin_lock_init(&ioc->scsi_lookup_lock);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003248
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05303249 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
Eric Mooree8206382007-09-29 10:16:53 -06003250 ioc->name, ioc->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003251
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003252 /* Clear the TM flags
3253 */
3254 hd->tmPending = 0;
3255 hd->tmState = TM_STATE_NONE;
3256 hd->resetPending = 0;
3257 hd->abortSCpnt = NULL;
3258
3259 /* Clear the pointer used to store
3260 * single-threaded commands, i.e., those
3261 * issued during a bus scan, dv and
3262 * configuration pages.
3263 */
3264 hd->cmdPtr = NULL;
3265
3266 /* Initialize this SCSI Hosts' timers
3267 * To use, set the timer expires field
3268 * and add_timer
3269 */
3270 init_timer(&hd->timer);
3271 hd->timer.data = (unsigned long) hd;
3272 hd->timer.function = mptscsih_timer_expired;
3273
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003274 ioc->sas_data.ptClear = mpt_pt_clear;
3275
Eric Mooredf9e0622007-01-29 09:46:21 -07003276 init_waitqueue_head(&hd->scandv_waitq);
3277 hd->scandv_wait_done = 0;
3278 hd->last_queue_full = 0;
3279 INIT_LIST_HEAD(&hd->target_reset_list);
3280 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3281
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003282 if (ioc->sas_data.ptClear==1) {
3283 mptbase_sas_persist_operation(
3284 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
3285 }
3286
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003287 error = scsi_add_host(sh, &ioc->pcidev->dev);
3288 if (error) {
Eric Moore29dd3602007-09-14 18:46:51 -06003289 dprintk(ioc, printk(MYIOC_s_ERR_FMT
3290 "scsi_add_host failed\n", ioc->name));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003291 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003292 }
3293
3294 mptsas_scan_sas_topology(ioc);
3295
3296 return 0;
3297
Eric Moore547f9a22006-06-27 14:42:12 -06003298 out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003299
3300 mptscsih_remove(pdev);
3301 return error;
3302}
3303
3304static void __devexit mptsas_remove(struct pci_dev *pdev)
3305{
3306 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
3307 struct mptsas_portinfo *p, *n;
Eric Moore547f9a22006-06-27 14:42:12 -06003308 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003309
Eric Mooreb506ade2007-01-29 09:45:37 -07003310 ioc->sas_discovery_ignore_events = 1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003311 sas_remove_host(ioc->sh);
3312
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003313 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003314 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
3315 list_del(&p->list);
Eric Moore547f9a22006-06-27 14:42:12 -06003316 for (i = 0 ; i < p->num_phys ; i++)
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05303317 mptsas_port_delete(ioc, p->phy_info[i].port_details);
Eric Moore547f9a22006-06-27 14:42:12 -06003318 kfree(p->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003319 kfree(p);
3320 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003321 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003322
3323 mptscsih_remove(pdev);
3324}
3325
3326static struct pci_device_id mptsas_pci_table[] = {
Eric Moore87cf8982006-06-27 16:09:26 -06003327 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003328 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003329 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003330 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003331 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003332 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003333 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003334 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003335 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003336 PCI_ANY_ID, PCI_ANY_ID },
3337 {0} /* Terminating entry */
3338};
3339MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
3340
3341
3342static struct pci_driver mptsas_driver = {
3343 .name = "mptsas",
3344 .id_table = mptsas_pci_table,
3345 .probe = mptsas_probe,
3346 .remove = __devexit_p(mptsas_remove),
3347 .shutdown = mptscsih_shutdown,
3348#ifdef CONFIG_PM
3349 .suspend = mptscsih_suspend,
3350 .resume = mptscsih_resume,
3351#endif
3352};
3353
3354static int __init
3355mptsas_init(void)
3356{
Prakash, Sathya57ce21b2007-07-02 17:04:10 +05303357 int error;
3358
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003359 show_mptmod_ver(my_NAME, my_VERSION);
3360
3361 mptsas_transport_template =
3362 sas_attach_transport(&mptsas_transport_functions);
3363 if (!mptsas_transport_template)
3364 return -ENODEV;
3365
3366 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
Eric Mooredf9e0622007-01-29 09:46:21 -07003367 mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003368 mptsasInternalCtx =
3369 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02003370 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003371
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05303372 mpt_event_register(mptsasDoneCtx, mptsas_event_process);
3373 mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003374
Prakash, Sathya57ce21b2007-07-02 17:04:10 +05303375 error = pci_register_driver(&mptsas_driver);
3376 if (error)
3377 sas_release_transport(mptsas_transport_template);
3378
3379 return error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003380}
3381
3382static void __exit
3383mptsas_exit(void)
3384{
3385 pci_unregister_driver(&mptsas_driver);
3386 sas_release_transport(mptsas_transport_template);
3387
3388 mpt_reset_deregister(mptsasDoneCtx);
3389 mpt_event_deregister(mptsasDoneCtx);
3390
Christoph Hellwigda4fa652005-10-19 20:01:42 +02003391 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003392 mpt_deregister(mptsasInternalCtx);
3393 mpt_deregister(mptsasTaskCtx);
3394 mpt_deregister(mptsasDoneCtx);
3395}
3396
3397module_init(mptsas_init);
3398module_exit(mptsas_exit);