diff options
Diffstat (limited to 'drivers/scsi/aic94xx')
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_hwi.c | 18 | ||||
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_hwi.h | 13 | ||||
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_init.c | 4 | ||||
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_sas.h | 1 | ||||
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_scb.c | 72 | ||||
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_sds.c | 4 | ||||
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_seq.c | 5 | ||||
-rw-r--r-- | drivers/scsi/aic94xx/aic94xx_seq.h | 2 |
8 files changed, 109 insertions, 10 deletions
diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c index 3c2d7a379931..af7e01134364 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.c +++ b/drivers/scsi/aic94xx/aic94xx_hwi.c | |||
@@ -112,6 +112,21 @@ static int asd_init_phy(struct asd_phy *phy) | |||
112 | return 0; | 112 | return 0; |
113 | } | 113 | } |
114 | 114 | ||
115 | static void asd_init_ports(struct asd_ha_struct *asd_ha) | ||
116 | { | ||
117 | int i; | ||
118 | |||
119 | spin_lock_init(&asd_ha->asd_ports_lock); | ||
120 | for (i = 0; i < ASD_MAX_PHYS; i++) { | ||
121 | struct asd_port *asd_port = &asd_ha->asd_ports[i]; | ||
122 | |||
123 | memset(asd_port->sas_addr, 0, SAS_ADDR_SIZE); | ||
124 | memset(asd_port->attached_sas_addr, 0, SAS_ADDR_SIZE); | ||
125 | asd_port->phy_mask = 0; | ||
126 | asd_port->num_phys = 0; | ||
127 | } | ||
128 | } | ||
129 | |||
115 | static int asd_init_phys(struct asd_ha_struct *asd_ha) | 130 | static int asd_init_phys(struct asd_ha_struct *asd_ha) |
116 | { | 131 | { |
117 | u8 i; | 132 | u8 i; |
@@ -121,6 +136,7 @@ static int asd_init_phys(struct asd_ha_struct *asd_ha) | |||
121 | struct asd_phy *phy = &asd_ha->phys[i]; | 136 | struct asd_phy *phy = &asd_ha->phys[i]; |
122 | 137 | ||
123 | phy->phy_desc = &asd_ha->hw_prof.phy_desc[i]; | 138 | phy->phy_desc = &asd_ha->hw_prof.phy_desc[i]; |
139 | phy->asd_port = NULL; | ||
124 | 140 | ||
125 | phy->sas_phy.enabled = 0; | 141 | phy->sas_phy.enabled = 0; |
126 | phy->sas_phy.id = i; | 142 | phy->sas_phy.id = i; |
@@ -658,6 +674,8 @@ int asd_init_hw(struct asd_ha_struct *asd_ha) | |||
658 | goto Out; | 674 | goto Out; |
659 | } | 675 | } |
660 | 676 | ||
677 | asd_init_ports(asd_ha); | ||
678 | |||
661 | err = asd_init_scbs(asd_ha); | 679 | err = asd_init_scbs(asd_ha); |
662 | if (err) { | 680 | if (err) { |
663 | asd_printk("couldn't initialize scbs for %s\n", | 681 | asd_printk("couldn't initialize scbs for %s\n", |
diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.h b/drivers/scsi/aic94xx/aic94xx_hwi.h index 14319d1d6804..c6c3d18222fa 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.h +++ b/drivers/scsi/aic94xx/aic94xx_hwi.h | |||
@@ -46,6 +46,7 @@ | |||
46 | #define PCI_DEVICE_ID_ADAPTEC2_RAZOR10 0x410 | 46 | #define PCI_DEVICE_ID_ADAPTEC2_RAZOR10 0x410 |
47 | #define PCI_DEVICE_ID_ADAPTEC2_RAZOR12 0x412 | 47 | #define PCI_DEVICE_ID_ADAPTEC2_RAZOR12 0x412 |
48 | #define PCI_DEVICE_ID_ADAPTEC2_RAZOR1E 0x41E | 48 | #define PCI_DEVICE_ID_ADAPTEC2_RAZOR1E 0x41E |
49 | #define PCI_DEVICE_ID_ADAPTEC2_RAZOR1F 0x41F | ||
49 | #define PCI_DEVICE_ID_ADAPTEC2_RAZOR30 0x430 | 50 | #define PCI_DEVICE_ID_ADAPTEC2_RAZOR30 0x430 |
50 | #define PCI_DEVICE_ID_ADAPTEC2_RAZOR32 0x432 | 51 | #define PCI_DEVICE_ID_ADAPTEC2_RAZOR32 0x432 |
51 | #define PCI_DEVICE_ID_ADAPTEC2_RAZOR3E 0x43E | 52 | #define PCI_DEVICE_ID_ADAPTEC2_RAZOR3E 0x43E |
@@ -192,6 +193,16 @@ struct asd_seq_data { | |||
192 | struct asd_ascb **escb_arr; /* array of pointers to escbs */ | 193 | struct asd_ascb **escb_arr; /* array of pointers to escbs */ |
193 | }; | 194 | }; |
194 | 195 | ||
196 | /* This is an internal port structure. These are used to get accurate | ||
197 | * phy_mask for updating DDB 0. | ||
198 | */ | ||
199 | struct asd_port { | ||
200 | u8 sas_addr[SAS_ADDR_SIZE]; | ||
201 | u8 attached_sas_addr[SAS_ADDR_SIZE]; | ||
202 | u32 phy_mask; | ||
203 | int num_phys; | ||
204 | }; | ||
205 | |||
195 | /* This is the Host Adapter structure. It describes the hardware | 206 | /* This is the Host Adapter structure. It describes the hardware |
196 | * SAS adapter. | 207 | * SAS adapter. |
197 | */ | 208 | */ |
@@ -210,6 +221,8 @@ struct asd_ha_struct { | |||
210 | struct hw_profile hw_prof; | 221 | struct hw_profile hw_prof; |
211 | 222 | ||
212 | struct asd_phy phys[ASD_MAX_PHYS]; | 223 | struct asd_phy phys[ASD_MAX_PHYS]; |
224 | spinlock_t asd_ports_lock; | ||
225 | struct asd_port asd_ports[ASD_MAX_PHYS]; | ||
213 | struct asd_sas_port ports[ASD_MAX_PHYS]; | 226 | struct asd_sas_port ports[ASD_MAX_PHYS]; |
214 | 227 | ||
215 | struct dma_pool *scb_pool; | 228 | struct dma_pool *scb_pool; |
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 3a5bbba3976e..42302ef05ee5 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c | |||
@@ -795,8 +795,6 @@ static void asd_remove_driver_attrs(struct device_driver *driver) | |||
795 | } | 795 | } |
796 | 796 | ||
797 | static struct sas_domain_function_template aic94xx_transport_functions = { | 797 | static struct sas_domain_function_template aic94xx_transport_functions = { |
798 | .lldd_port_formed = asd_update_port_links, | ||
799 | |||
800 | .lldd_dev_found = asd_dev_found, | 798 | .lldd_dev_found = asd_dev_found, |
801 | .lldd_dev_gone = asd_dev_gone, | 799 | .lldd_dev_gone = asd_dev_gone, |
802 | 800 | ||
@@ -823,6 +821,8 @@ static const struct pci_device_id aic94xx_pci_table[] __devinitdata = { | |||
823 | 0, 0, 1}, | 821 | 0, 0, 1}, |
824 | {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR1E), | 822 | {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR1E), |
825 | 0, 0, 1}, | 823 | 0, 0, 1}, |
824 | {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR1F), | ||
825 | 0, 0, 1}, | ||
826 | {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR30), | 826 | {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR30), |
827 | 0, 0, 2}, | 827 | 0, 0, 2}, |
828 | {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR32), | 828 | {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR32), |
diff --git a/drivers/scsi/aic94xx/aic94xx_sas.h b/drivers/scsi/aic94xx/aic94xx_sas.h index 64d231712345..9050e93bfd5e 100644 --- a/drivers/scsi/aic94xx/aic94xx_sas.h +++ b/drivers/scsi/aic94xx/aic94xx_sas.h | |||
@@ -733,6 +733,7 @@ struct asd_phy { | |||
733 | 733 | ||
734 | struct sas_identify_frame *identify_frame; | 734 | struct sas_identify_frame *identify_frame; |
735 | struct asd_dma_tok *id_frm_tok; | 735 | struct asd_dma_tok *id_frm_tok; |
736 | struct asd_port *asd_port; | ||
736 | 737 | ||
737 | u8 frame_rcvd[ASD_EDB_SIZE]; | 738 | u8 frame_rcvd[ASD_EDB_SIZE]; |
738 | }; | 739 | }; |
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index 52c6ea4fbf71..14d5d8c2ee13 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c | |||
@@ -169,6 +169,70 @@ static inline void asd_get_attached_sas_addr(struct asd_phy *phy, u8 *sas_addr) | |||
169 | } | 169 | } |
170 | } | 170 | } |
171 | 171 | ||
172 | static void asd_form_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy) | ||
173 | { | ||
174 | int i; | ||
175 | struct asd_port *free_port = NULL; | ||
176 | struct asd_port *port; | ||
177 | struct asd_sas_phy *sas_phy = &phy->sas_phy; | ||
178 | unsigned long flags; | ||
179 | |||
180 | spin_lock_irqsave(&asd_ha->asd_ports_lock, flags); | ||
181 | if (!phy->asd_port) { | ||
182 | for (i = 0; i < ASD_MAX_PHYS; i++) { | ||
183 | port = &asd_ha->asd_ports[i]; | ||
184 | |||
185 | /* Check for wide port */ | ||
186 | if (port->num_phys > 0 && | ||
187 | memcmp(port->sas_addr, sas_phy->sas_addr, | ||
188 | SAS_ADDR_SIZE) == 0 && | ||
189 | memcmp(port->attached_sas_addr, | ||
190 | sas_phy->attached_sas_addr, | ||
191 | SAS_ADDR_SIZE) == 0) { | ||
192 | break; | ||
193 | } | ||
194 | |||
195 | /* Find a free port */ | ||
196 | if (port->num_phys == 0 && free_port == NULL) { | ||
197 | free_port = port; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | /* Use a free port if this doesn't form a wide port */ | ||
202 | if (i >= ASD_MAX_PHYS) { | ||
203 | port = free_port; | ||
204 | BUG_ON(!port); | ||
205 | memcpy(port->sas_addr, sas_phy->sas_addr, | ||
206 | SAS_ADDR_SIZE); | ||
207 | memcpy(port->attached_sas_addr, | ||
208 | sas_phy->attached_sas_addr, | ||
209 | SAS_ADDR_SIZE); | ||
210 | } | ||
211 | port->num_phys++; | ||
212 | port->phy_mask |= (1U << sas_phy->id); | ||
213 | phy->asd_port = port; | ||
214 | } | ||
215 | ASD_DPRINTK("%s: updating phy_mask 0x%x for phy%d\n", | ||
216 | __FUNCTION__, phy->asd_port->phy_mask, sas_phy->id); | ||
217 | asd_update_port_links(asd_ha, phy); | ||
218 | spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags); | ||
219 | } | ||
220 | |||
221 | static void asd_deform_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy) | ||
222 | { | ||
223 | struct asd_port *port = phy->asd_port; | ||
224 | struct asd_sas_phy *sas_phy = &phy->sas_phy; | ||
225 | unsigned long flags; | ||
226 | |||
227 | spin_lock_irqsave(&asd_ha->asd_ports_lock, flags); | ||
228 | if (port) { | ||
229 | port->num_phys--; | ||
230 | port->phy_mask &= ~(1U << sas_phy->id); | ||
231 | phy->asd_port = NULL; | ||
232 | } | ||
233 | spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags); | ||
234 | } | ||
235 | |||
172 | static inline void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb, | 236 | static inline void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb, |
173 | struct done_list_struct *dl, | 237 | struct done_list_struct *dl, |
174 | int edb_id, int phy_id) | 238 | int edb_id, int phy_id) |
@@ -188,6 +252,7 @@ static inline void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb, | |||
188 | asd_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr); | 252 | asd_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr); |
189 | spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags); | 253 | spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags); |
190 | asd_dump_frame_rcvd(phy, dl); | 254 | asd_dump_frame_rcvd(phy, dl); |
255 | asd_form_port(ascb->ha, phy); | ||
191 | sas_ha->notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED); | 256 | sas_ha->notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED); |
192 | } | 257 | } |
193 | 258 | ||
@@ -198,6 +263,7 @@ static inline void asd_link_reset_err_tasklet(struct asd_ascb *ascb, | |||
198 | struct asd_ha_struct *asd_ha = ascb->ha; | 263 | struct asd_ha_struct *asd_ha = ascb->ha; |
199 | struct sas_ha_struct *sas_ha = &asd_ha->sas_ha; | 264 | struct sas_ha_struct *sas_ha = &asd_ha->sas_ha; |
200 | struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; | 265 | struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; |
266 | struct asd_phy *phy = &asd_ha->phys[phy_id]; | ||
201 | u8 lr_error = dl->status_block[1]; | 267 | u8 lr_error = dl->status_block[1]; |
202 | u8 retries_left = dl->status_block[2]; | 268 | u8 retries_left = dl->status_block[2]; |
203 | 269 | ||
@@ -222,6 +288,7 @@ static inline void asd_link_reset_err_tasklet(struct asd_ascb *ascb, | |||
222 | 288 | ||
223 | asd_turn_led(asd_ha, phy_id, 0); | 289 | asd_turn_led(asd_ha, phy_id, 0); |
224 | sas_phy_disconnected(sas_phy); | 290 | sas_phy_disconnected(sas_phy); |
291 | asd_deform_port(asd_ha, phy); | ||
225 | sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); | 292 | sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); |
226 | 293 | ||
227 | if (retries_left == 0) { | 294 | if (retries_left == 0) { |
@@ -249,6 +316,8 @@ static inline void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb, | |||
249 | unsigned long flags; | 316 | unsigned long flags; |
250 | struct sas_ha_struct *sas_ha = &ascb->ha->sas_ha; | 317 | struct sas_ha_struct *sas_ha = &ascb->ha->sas_ha; |
251 | struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; | 318 | struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; |
319 | struct asd_ha_struct *asd_ha = ascb->ha; | ||
320 | struct asd_phy *phy = &asd_ha->phys[phy_id]; | ||
252 | u8 reg = dl->status_block[1]; | 321 | u8 reg = dl->status_block[1]; |
253 | u32 cont = dl->status_block[2] << ((reg & 3)*8); | 322 | u32 cont = dl->status_block[2] << ((reg & 3)*8); |
254 | 323 | ||
@@ -285,6 +354,7 @@ static inline void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb, | |||
285 | phy_id); | 354 | phy_id); |
286 | /* The sequencer disables all phys on that port. | 355 | /* The sequencer disables all phys on that port. |
287 | * We have to re-enable the phys ourselves. */ | 356 | * We have to re-enable the phys ourselves. */ |
357 | asd_deform_port(asd_ha, phy); | ||
288 | sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET); | 358 | sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET); |
289 | break; | 359 | break; |
290 | 360 | ||
@@ -385,6 +455,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, | |||
385 | u8 sb_opcode = dl->status_block[0]; | 455 | u8 sb_opcode = dl->status_block[0]; |
386 | int phy_id = sb_opcode & DL_PHY_MASK; | 456 | int phy_id = sb_opcode & DL_PHY_MASK; |
387 | struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; | 457 | struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; |
458 | struct asd_phy *phy = &asd_ha->phys[phy_id]; | ||
388 | 459 | ||
389 | if (edb > 6 || edb < 0) { | 460 | if (edb > 6 || edb < 0) { |
390 | ASD_DPRINTK("edb is 0x%x! dl->opcode is 0x%x\n", | 461 | ASD_DPRINTK("edb is 0x%x! dl->opcode is 0x%x\n", |
@@ -497,6 +568,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, | |||
497 | asd_turn_led(asd_ha, phy_id, 0); | 568 | asd_turn_led(asd_ha, phy_id, 0); |
498 | /* the device is gone */ | 569 | /* the device is gone */ |
499 | sas_phy_disconnected(sas_phy); | 570 | sas_phy_disconnected(sas_phy); |
571 | asd_deform_port(asd_ha, phy); | ||
500 | sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT); | 572 | sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT); |
501 | break; | 573 | break; |
502 | default: | 574 | default: |
diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c index 83574b5b4e69..de7c04d4254d 100644 --- a/drivers/scsi/aic94xx/aic94xx_sds.c +++ b/drivers/scsi/aic94xx/aic94xx_sds.c | |||
@@ -630,10 +630,6 @@ static int asd_flash_getid(struct asd_ha_struct *asd_ha) | |||
630 | 630 | ||
631 | reg = asd_read_reg_dword(asd_ha, EXSICNFGR); | 631 | reg = asd_read_reg_dword(asd_ha, EXSICNFGR); |
632 | 632 | ||
633 | if (!(reg & FLASHEX)) { | ||
634 | ASD_DPRINTK("flash doesn't exist\n"); | ||
635 | return -ENOENT; | ||
636 | } | ||
637 | if (pci_read_config_dword(asd_ha->pcidev, PCI_CONF_FLSH_BAR, | 633 | if (pci_read_config_dword(asd_ha->pcidev, PCI_CONF_FLSH_BAR, |
638 | &asd_ha->hw_prof.flash.bar)) { | 634 | &asd_ha->hw_prof.flash.bar)) { |
639 | asd_printk("couldn't read PCI_CONF_FLSH_BAR of %s\n", | 635 | asd_printk("couldn't read PCI_CONF_FLSH_BAR of %s\n", |
diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c index 56e4b3ba6a08..845112539d05 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.c +++ b/drivers/scsi/aic94xx/aic94xx_seq.c | |||
@@ -1369,10 +1369,9 @@ int asd_start_seqs(struct asd_ha_struct *asd_ha) | |||
1369 | * port_map_by_links is also used as the conn_mask byte in the | 1369 | * port_map_by_links is also used as the conn_mask byte in the |
1370 | * initiator/target port DDB. | 1370 | * initiator/target port DDB. |
1371 | */ | 1371 | */ |
1372 | void asd_update_port_links(struct asd_sas_phy *sas_phy) | 1372 | void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy) |
1373 | { | 1373 | { |
1374 | struct asd_ha_struct *asd_ha = sas_phy->ha->lldd_ha; | 1374 | const u8 phy_mask = (u8) phy->asd_port->phy_mask; |
1375 | const u8 phy_mask = (u8) sas_phy->port->phy_mask; | ||
1376 | u8 phy_is_up; | 1375 | u8 phy_is_up; |
1377 | u8 mask; | 1376 | u8 mask; |
1378 | int i, err; | 1377 | int i, err; |
diff --git a/drivers/scsi/aic94xx/aic94xx_seq.h b/drivers/scsi/aic94xx/aic94xx_seq.h index 42281c36153b..9e715e5496af 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.h +++ b/drivers/scsi/aic94xx/aic94xx_seq.h | |||
@@ -64,7 +64,7 @@ int asd_unpause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask); | |||
64 | int asd_init_seqs(struct asd_ha_struct *asd_ha); | 64 | int asd_init_seqs(struct asd_ha_struct *asd_ha); |
65 | int asd_start_seqs(struct asd_ha_struct *asd_ha); | 65 | int asd_start_seqs(struct asd_ha_struct *asd_ha); |
66 | 66 | ||
67 | void asd_update_port_links(struct asd_sas_phy *phy); | 67 | void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy); |
68 | #endif | 68 | #endif |
69 | 69 | ||
70 | #endif | 70 | #endif |